From 28aa4bff8d6be031c6089fe5c7ab010f1cc48340 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Sep 2007 12:03:58 +0000 Subject: r25154: move winbindd code into winbindd/ metze (This used to be commit 3ac7566ae14c48ff9b0f6b232e0ec4b2f73df558) --- source3/winbindd/idmap.c | 1562 ++++++++++++ source3/winbindd/idmap_ad.c | 870 +++++++ source3/winbindd/idmap_cache.c | 531 ++++ source3/winbindd/idmap_ldap.c | 1505 +++++++++++ source3/winbindd/idmap_nss.c | 223 ++ source3/winbindd/idmap_passdb.c | 139 ++ source3/winbindd/idmap_rid.c | 267 ++ source3/winbindd/idmap_tdb.c | 1232 +++++++++ source3/winbindd/idmap_util.c | 171 ++ source3/winbindd/nss_info.c | 301 +++ source3/winbindd/nss_info_template.c | 83 + source3/winbindd/winbindd.c | 1254 ++++++++++ source3/winbindd/winbindd.h | 365 +++ source3/winbindd/winbindd_ads.c | 1312 ++++++++++ source3/winbindd/winbindd_async.c | 1695 +++++++++++++ source3/winbindd/winbindd_cache.c | 3892 +++++++++++++++++++++++++++++ source3/winbindd/winbindd_ccache_access.c | 283 +++ source3/winbindd/winbindd_cm.c | 2271 +++++++++++++++++ source3/winbindd/winbindd_cred_cache.c | 802 ++++++ source3/winbindd/winbindd_creds.c | 162 ++ source3/winbindd/winbindd_dual.c | 1130 +++++++++ source3/winbindd/winbindd_group.c | 1746 +++++++++++++ source3/winbindd/winbindd_misc.c | 634 +++++ source3/winbindd/winbindd_pam.c | 2382 ++++++++++++++++++ source3/winbindd/winbindd_passdb.c | 467 ++++ source3/winbindd/winbindd_reconnect.c | 316 +++ source3/winbindd/winbindd_rpc.c | 1111 ++++++++ source3/winbindd/winbindd_sid.c | 560 +++++ source3/winbindd/winbindd_sockinit.c | 126 + source3/winbindd/winbindd_user.c | 875 +++++++ source3/winbindd/winbindd_util.c | 1460 +++++++++++ source3/winbindd/winbindd_wins.c | 234 ++ 32 files changed, 29961 insertions(+) create mode 100644 source3/winbindd/idmap.c create mode 100644 source3/winbindd/idmap_ad.c create mode 100644 source3/winbindd/idmap_cache.c create mode 100644 source3/winbindd/idmap_ldap.c create mode 100644 source3/winbindd/idmap_nss.c create mode 100644 source3/winbindd/idmap_passdb.c create mode 100644 source3/winbindd/idmap_rid.c create mode 100644 source3/winbindd/idmap_tdb.c create mode 100644 source3/winbindd/idmap_util.c create mode 100644 source3/winbindd/nss_info.c create mode 100644 source3/winbindd/nss_info_template.c create mode 100644 source3/winbindd/winbindd.c create mode 100644 source3/winbindd/winbindd.h create mode 100644 source3/winbindd/winbindd_ads.c create mode 100644 source3/winbindd/winbindd_async.c create mode 100644 source3/winbindd/winbindd_cache.c create mode 100644 source3/winbindd/winbindd_ccache_access.c create mode 100644 source3/winbindd/winbindd_cm.c create mode 100644 source3/winbindd/winbindd_cred_cache.c create mode 100644 source3/winbindd/winbindd_creds.c create mode 100644 source3/winbindd/winbindd_dual.c create mode 100644 source3/winbindd/winbindd_group.c create mode 100644 source3/winbindd/winbindd_misc.c create mode 100644 source3/winbindd/winbindd_pam.c create mode 100644 source3/winbindd/winbindd_passdb.c create mode 100644 source3/winbindd/winbindd_reconnect.c create mode 100644 source3/winbindd/winbindd_rpc.c create mode 100644 source3/winbindd/winbindd_sid.c create mode 100644 source3/winbindd/winbindd_sockinit.c create mode 100644 source3/winbindd/winbindd_user.c create mode 100644 source3/winbindd/winbindd_util.c create mode 100644 source3/winbindd/winbindd_wins.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c new file mode 100644 index 0000000000..2c7acc185c --- /dev/null +++ b/source3/winbindd/idmap.c @@ -0,0 +1,1562 @@ +/* + Unix SMB/CIFS implementation. + ID Mapping + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Simo Sorce 2003-2007 + Copyright (C) Jeremy Allison 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +static_decl_idmap; + +struct idmap_backend { + const char *name; + struct idmap_methods *methods; + struct idmap_backend *prev, *next; +}; + +struct idmap_alloc_backend { + const char *name; + struct idmap_alloc_methods *methods; + struct idmap_alloc_backend *prev, *next; +}; + +struct idmap_cache_ctx; + +struct idmap_alloc_context { + const char *params; + struct idmap_alloc_methods *methods; + BOOL initialized; +}; + +static TALLOC_CTX *idmap_ctx = NULL; +static struct idmap_cache_ctx *idmap_cache; + +static struct idmap_backend *backends = NULL; +static struct idmap_domain **idmap_domains = NULL; +static int num_domains = 0; +static int pdb_dom_num = -1; +static int def_dom_num = -1; + +static struct idmap_alloc_backend *alloc_backends = NULL; +static struct idmap_alloc_context *idmap_alloc_ctx = NULL; + +#define IDMAP_CHECK_RET(ret) do { \ + if ( ! NT_STATUS_IS_OK(ret)) { \ + DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \ + goto done; \ + } } while(0) +#define IDMAP_REPORT_RET(ret) do { \ + if ( ! NT_STATUS_IS_OK(ret)) { \ + DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \ + } } while(0) +#define IDMAP_CHECK_ALLOC(mem) do { \ + if (!mem) { \ + DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; \ + goto done; \ + } } while(0) + +static struct idmap_methods *get_methods(struct idmap_backend *be, + const char *name) +{ + struct idmap_backend *b; + + for (b = be; b; b = b->next) { + if (strequal(b->name, name)) { + return b->methods; + } + } + + return NULL; +} + +static struct idmap_alloc_methods *get_alloc_methods( + struct idmap_alloc_backend *be, + const char *name) +{ + struct idmap_alloc_backend *b; + + for (b = be; b; b = b->next) { + if (strequal(b->name, name)) { + return b->methods; + } + } + + return NULL; +} + +BOOL idmap_is_offline(void) +{ + return ( lp_winbind_offline_logon() && + get_global_winbindd_state_offline() ); +} + +/********************************************************************** + Allow a module to register itself as a method. +**********************************************************************/ + +NTSTATUS smb_register_idmap(int version, const char *name, + struct idmap_methods *methods) +{ + struct idmap_methods *test; + struct idmap_backend *entry; + + if (!idmap_ctx) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + if ((version != SMB_IDMAP_INTERFACE_VERSION)) { + DEBUG(0, ("Failed to register idmap module.\n" + "The module was compiled against " + "SMB_IDMAP_INTERFACE_VERSION %d,\n" + "current SMB_IDMAP_INTERFACE_VERSION is %d.\n" + "Please recompile against the current version " + "of samba!\n", + version, SMB_IDMAP_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !methods) { + DEBUG(0,("Called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + test = get_methods(backends, name); + if (test) { + DEBUG(0,("Idmap module %s already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = talloc(idmap_ctx, struct idmap_backend); + if ( ! entry) { + DEBUG(0,("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + entry->name = talloc_strdup(idmap_ctx, name); + if ( ! entry->name) { + DEBUG(0,("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + entry->methods = methods; + + DLIST_ADD(backends, entry); + DEBUG(5, ("Successfully added idmap backend '%s'\n", name)); + return NT_STATUS_OK; +} + +/********************************************************************** + Allow a module to register itself as a method. +**********************************************************************/ + +NTSTATUS smb_register_idmap_alloc(int version, const char *name, + struct idmap_alloc_methods *methods) +{ + struct idmap_alloc_methods *test; + struct idmap_alloc_backend *entry; + + if (!idmap_ctx) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + if ((version != SMB_IDMAP_INTERFACE_VERSION)) { + DEBUG(0, ("Failed to register idmap alloc module.\n" + "The module was compiled against " + "SMB_IDMAP_INTERFACE_VERSION %d,\n" + "current SMB_IDMAP_INTERFACE_VERSION is %d.\n" + "Please recompile against the current version " + "of samba!\n", + version, SMB_IDMAP_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !methods) { + DEBUG(0,("Called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + test = get_alloc_methods(alloc_backends, name); + if (test) { + DEBUG(0,("idmap_alloc module %s already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = talloc(idmap_ctx, struct idmap_alloc_backend); + if ( ! entry) { + DEBUG(0,("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + entry->name = talloc_strdup(idmap_ctx, name); + if ( ! entry->name) { + DEBUG(0,("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + entry->methods = methods; + + DLIST_ADD(alloc_backends, entry); + DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name)); + return NT_STATUS_OK; +} + +static int close_domain_destructor(struct idmap_domain *dom) +{ + NTSTATUS ret; + + ret = dom->methods->close_fn(dom); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(3, ("Failed to close idmap domain [%s]!\n", dom->name)); + } + + return 0; +} + +/************************************************************************** + Shutdown. +**************************************************************************/ + +NTSTATUS idmap_close(void) +{ + /* close the alloc backend first before freeing idmap_ctx */ + if (idmap_alloc_ctx) { + idmap_alloc_ctx->methods->close_fn(); + idmap_alloc_ctx->methods = NULL; + } + alloc_backends = NULL; + + /* this talloc_free call will fire the talloc destructors + * that will free all active backends resources */ + TALLOC_FREE(idmap_ctx); + idmap_cache = NULL; + idmap_domains = NULL; + backends = NULL; + + return NT_STATUS_OK; +} + +/********************************************************************** + Initialise idmap cache and a remote backend (if configured). +**********************************************************************/ + +static const char *idmap_default_domain[] = { "default domain", NULL }; + +/**************************************************************************** + ****************************************************************************/ + +NTSTATUS idmap_init_cache(void) +{ + /* Always initialize the cache. We'll have to delay initialization + of backends if we are offline */ + + if ( idmap_ctx ) { + return NT_STATUS_OK; + } + + if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) { + return NT_STATUS_NO_MEMORY; + } + + if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + +/**************************************************************************** + ****************************************************************************/ + +NTSTATUS idmap_init(void) +{ + NTSTATUS ret; + static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; + struct idmap_domain *dom; + char *compat_backend = NULL; + char *compat_params = NULL; + const char **dom_list = NULL; + char *alloc_backend = NULL; + BOOL default_already_defined = False; + BOOL pri_dom_is_in_list = False; + int compat = 0; + int i; + + ret = idmap_init_cache(); + if (!NT_STATUS_IS_OK(ret)) + return ret; + + if (NT_STATUS_IS_OK(idmap_init_status)) { + return NT_STATUS_OK; + } + + /* We can't reliably call intialization code here unless + we are online. But return NT_STATUS_OK so the upper + level code doesn't abort idmap lookups. */ + + if ( get_global_winbindd_state_offline() ) { + idmap_init_status = NT_STATUS_FILE_IS_OFFLINE; + return NT_STATUS_OK; + } + + static_init_idmap; + + dom_list = lp_idmap_domains(); + + if ( lp_idmap_backend() ) { + const char **compat_list = lp_idmap_backend(); + char *p = NULL; + const char *q = NULL; + + if ( dom_list ) { + DEBUG(0, ("WARNING: idmap backend and idmap domains are" + " mutually exclusive!\n")); + DEBUGADD(0,("idmap backend option will be IGNORED!\n")); + } else { + compat = 1; + + compat_backend = talloc_strdup(idmap_ctx, *compat_list); + if (compat_backend == NULL ) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + /* strip any leading idmap_ prefix of */ + if (strncmp(*compat_list, "idmap_", 6) == 0 ) { + q = *compat_list += 6; + DEBUG(0, ("WARNING: idmap backend uses obsolete" + " and deprecated 'idmap_' prefix.\n" + "Please replace 'idmap_%s' by '%s' in" + " %s\n", q, q, dyn_CONFIGFILE)); + compat_backend = talloc_strdup(idmap_ctx, q); + } else { + compat_backend = talloc_strdup(idmap_ctx, + *compat_list); + } + + /* separate the backend and module arguements */ + if ((p = strchr(compat_backend, ':')) != NULL) { + *p = '\0'; + compat_params = p + 1; + } + } + } else if ( !dom_list ) { + /* Back compatible: without idmap domains and explicit + idmap backend. Taking default idmap backend: tdb */ + + compat = 1; + compat_backend = talloc_strdup( idmap_ctx, "tdb"); + compat_params = compat_backend; + } + + if ( ! dom_list) { + dom_list = idmap_default_domain; + } + + /*************************** + * initialize idmap domains + */ + DEBUG(1, ("Initializing idmap domains\n")); + + for (i = 0; dom_list[i]; i++) { + const char *parm_backend; + char *config_option; + + /* ignore BUILTIN and local MACHINE domains */ + if (strequal(dom_list[i], "BUILTIN") + || strequal(dom_list[i], get_global_sam_name())) + { + DEBUG(0,("idmap_init: Ignoring invalid domain %s\n", + dom_list[i])); + continue; + } + + if (strequal(dom_list[i], lp_workgroup())) { + pri_dom_is_in_list = True; + } + /* init domain */ + + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); + + dom->name = talloc_strdup(dom, dom_list[i]); + IDMAP_CHECK_ALLOC(dom->name); + + config_option = talloc_asprintf(dom, "idmap config %s", + dom->name); + IDMAP_CHECK_ALLOC(config_option); + + /* default or specific ? */ + + dom->default_domain = lp_parm_bool(-1, config_option, + "default", False); + + if (dom->default_domain || + strequal(dom_list[i], idmap_default_domain[0])) { + + /* make sure this is set even when we match + * idmap_default_domain[0] */ + dom->default_domain = True; + + if (default_already_defined) { + DEBUG(1, ("ERROR: Multiple domains defined as" + " default!\n")); + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + default_already_defined = True; + + } + + dom->readonly = lp_parm_bool(-1, config_option, + "readonly", False); + + /* find associated backend (default: tdb) */ + if (compat) { + parm_backend = talloc_strdup(idmap_ctx, compat_backend); + } else { + parm_backend = talloc_strdup(idmap_ctx, + lp_parm_const_string( + -1, config_option, + "backend", "tdb")); + } + IDMAP_CHECK_ALLOC(parm_backend); + + /* get the backend methods for this domain */ + dom->methods = get_methods(backends, parm_backend); + + if ( ! dom->methods) { + ret = smb_probe_module("idmap", parm_backend); + if (NT_STATUS_IS_OK(ret)) { + dom->methods = get_methods(backends, + parm_backend); + } + } + if ( ! dom->methods) { + DEBUG(0, ("ERROR: Could not get methods for " + "backend %s\n", parm_backend)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* check the set_mapping function exists otherwise mark the + * module as readonly */ + if ( ! dom->methods->set_mapping) { + DEBUG(5, ("Forcing to readonly, as this module can't" + " store arbitrary mappings.\n")); + dom->readonly = True; + } + + /* now that we have methods, + * set the destructor for this domain */ + talloc_set_destructor(dom, close_domain_destructor); + + if (compat_params) { + dom->params = talloc_strdup(dom, compat_params); + IDMAP_CHECK_ALLOC(dom->params); + } else { + dom->params = NULL; + } + + /* Finally instance a backend copy for this domain */ + ret = dom->methods->init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Initialization failed for backend " + "%s (domain %s), deferred!\n", + parm_backend, dom->name)); + } + idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, + struct idmap_domain *, i+1); + if ( ! idmap_domains) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + idmap_domains[i] = dom; + + /* save default domain position for future uses */ + if (dom->default_domain) { + def_dom_num = i; + } + + DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", + dom->name, parm_backend, + dom->default_domain?"":"not ", + dom->readonly?"":"not ")); + + talloc_free(config_option); + } + + /* save the number of domains we have */ + num_domains = i; + + /* automatically add idmap_nss backend if needed */ + if ((lp_server_role() == ROLE_DOMAIN_MEMBER) && + ( ! pri_dom_is_in_list) && + lp_winbind_trusted_domains_only()) { + + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); + + dom->name = talloc_strdup(dom, lp_workgroup()); + IDMAP_CHECK_ALLOC(dom->name); + + dom->default_domain = False; + dom->readonly = True; + + /* get the backend methods for passdb */ + dom->methods = get_methods(backends, "nss"); + + /* (the nss module is always statically linked) */ + if ( ! dom->methods) { + DEBUG(0, ("ERROR: No methods for idmap_nss ?!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* now that we have methods, + * set the destructor for this domain */ + talloc_set_destructor(dom, close_domain_destructor); + + if (compat_params) { + dom->params = talloc_strdup(dom, compat_params); + IDMAP_CHECK_ALLOC(dom->params); + } else { + dom->params = NULL; + } + + /* Finally instance a backend copy for this domain */ + ret = dom->methods->init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Init. failed for idmap_nss ?!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + idmap_domains = talloc_realloc(idmap_ctx, + idmap_domains, + struct idmap_domain *, + num_domains+1); + if ( ! idmap_domains) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + idmap_domains[num_domains] = dom; + + DEBUG(10, ("Domain %s - Backend nss - not default - readonly\n", + dom->name )); + + num_domains++; + } + + /**** automatically add idmap_passdb backend ****/ + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); + + dom->name = talloc_strdup(dom, get_global_sam_name()); + IDMAP_CHECK_ALLOC(dom->name); + + dom->default_domain = False; + dom->readonly = True; + + /* get the backend methods for passdb */ + dom->methods = get_methods(backends, "passdb"); + + /* (the passdb module is always statically linked) */ + if ( ! dom->methods) { + DEBUG(0, ("ERROR: No methods for idmap_passdb ?!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* now that we have methods, set the destructor for this domain */ + talloc_set_destructor(dom, close_domain_destructor); + + if (compat_params) { + dom->params = talloc_strdup(dom, compat_params); + IDMAP_CHECK_ALLOC(dom->params); + } else { + dom->params = NULL; + } + + /* Finally instance a backend copy for this domain */ + ret = dom->methods->init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Init. failed for idmap_passdb ?!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + idmap_domains = talloc_realloc(idmap_ctx, + idmap_domains, + struct idmap_domain *, + num_domains+1); + if ( ! idmap_domains) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + idmap_domains[num_domains] = dom; + + /* needed to handle special BUILTIN and wellknown SIDs cases */ + pdb_dom_num = num_domains; + + DEBUG(10, ("Domain %s - Backend passdb - not default - readonly\n", + dom->name)); + + num_domains++; + /**** finished adding idmap_passdb backend ****/ + + /* sort domains so that the default is the last one */ + /* don't sort if no default domain defined */ + if (def_dom_num != -1 && def_dom_num != num_domains-1) { + /* default is not last, move it */ + struct idmap_domain *tmp; + + if (pdb_dom_num > def_dom_num) { + pdb_dom_num --; + + } else if (pdb_dom_num == def_dom_num) { /* ?? */ + pdb_dom_num = num_domains - 1; + } + + tmp = idmap_domains[def_dom_num]; + + for (i = def_dom_num; i < num_domains-1; i++) { + idmap_domains[i] = idmap_domains[i+1]; + } + idmap_domains[i] = tmp; + def_dom_num = i; + } + + + /* Initialize alloc module */ + + DEBUG(3, ("Initializing idmap alloc module\n")); + + alloc_backend = NULL; + if (compat) { + alloc_backend = talloc_strdup(idmap_ctx, compat_backend); + } else { + char *ab = lp_idmap_alloc_backend(); + + if (ab && (ab[0] != '\0')) { + alloc_backend = talloc_strdup(idmap_ctx, + lp_idmap_alloc_backend()); + } + } + + if ( alloc_backend ) { + + idmap_alloc_ctx = TALLOC_ZERO_P(idmap_ctx, + struct idmap_alloc_context); + IDMAP_CHECK_ALLOC(idmap_alloc_ctx); + + idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, + alloc_backend); + if ( ! idmap_alloc_ctx->methods) { + ret = smb_probe_module("idmap", alloc_backend); + if (NT_STATUS_IS_OK(ret)) { + idmap_alloc_ctx->methods = + get_alloc_methods(alloc_backends, + alloc_backend); + } + } + if (idmap_alloc_ctx->methods) { + + if (compat_params) { + idmap_alloc_ctx->params = + talloc_strdup(idmap_alloc_ctx, + compat_params); + IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params); + } else { + idmap_alloc_ctx->params = NULL; + } + + ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Initialization failed for " + "alloc backend %s, deferred!\n", + alloc_backend)); + } else { + idmap_alloc_ctx->initialized = True; + } + } else { + DEBUG(2, ("idmap_init: Unable to get methods for " + "alloc backend %s\n", + alloc_backend)); + /* certain compat backends are just readonly */ + if ( compat ) { + TALLOC_FREE(idmap_alloc_ctx); + ret = NT_STATUS_OK; + } else { + ret = NT_STATUS_UNSUCCESSFUL; + } + } + } + + /* cleanpu temporary strings */ + TALLOC_FREE( compat_backend ); + + idmap_init_status = NT_STATUS_OK; + + return ret; + +done: + DEBUG(0, ("Aborting IDMAP Initialization ...\n")); + idmap_close(); + + return ret; +} + +static NTSTATUS idmap_alloc_init(void) +{ + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_init())) { + return ret; + } + + if ( ! idmap_alloc_ctx) { + return NT_STATUS_NOT_SUPPORTED; + } + + if ( ! idmap_alloc_ctx->initialized) { + ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Initialization failed for alloc " + "backend, deferred!\n")); + return ret; + } else { + idmap_alloc_ctx->initialized = True; + } + } + + return NT_STATUS_OK; +} + +/************************************************************************** + idmap allocator interface functions +**************************************************************************/ + +NTSTATUS idmap_allocate_uid(struct unixid *id) +{ + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + return ret; + } + + id->type = ID_TYPE_UID; + return idmap_alloc_ctx->methods->allocate_id(id); +} + +NTSTATUS idmap_allocate_gid(struct unixid *id) +{ + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + return ret; + } + + id->type = ID_TYPE_GID; + return idmap_alloc_ctx->methods->allocate_id(id); +} + +NTSTATUS idmap_set_uid_hwm(struct unixid *id) +{ + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + return ret; + } + + id->type = ID_TYPE_UID; + return idmap_alloc_ctx->methods->set_id_hwm(id); +} + +NTSTATUS idmap_set_gid_hwm(struct unixid *id) +{ + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + return ret; + } + + id->type = ID_TYPE_GID; + return idmap_alloc_ctx->methods->set_id_hwm(id); +} + +/****************************************************************************** + Lookup an idmap_domain give a full user or group SID + ******************************************************************************/ + +static struct idmap_domain* find_idmap_domain_from_sid( DOM_SID *account_sid ) +{ + DOM_SID domain_sid; + uint32 rid; + struct winbindd_domain *domain = NULL; + int i; + + /* 1. Handle BUILTIN or Special SIDs and prevent them from + falling into the default domain space (if we have a + configured passdb backend. */ + + if ( (pdb_dom_num != -1) && + (sid_check_is_in_builtin(account_sid) || + sid_check_is_in_wellknown_domain(account_sid) || + sid_check_is_in_unix_groups(account_sid) || + sid_check_is_in_unix_users(account_sid)) ) + { + return idmap_domains[pdb_dom_num]; + } + + /* 2. Lookup the winbindd_domain from the account_sid */ + + sid_copy( &domain_sid, account_sid ); + sid_split_rid( &domain_sid, &rid ); + domain = find_domain_from_sid_noinit( &domain_sid ); + + for (i = 0; domain && i < num_domains; i++) { + if ( strequal( idmap_domains[i]->name, domain->name ) ) { + return idmap_domains[i]; + } + } + + /* 3. Fall back to the default domain */ + + if ( def_dom_num != -1 ) { + return idmap_domains[def_dom_num]; + } + + return NULL; +} + +/****************************************************************************** + Lookup an index given an idmap_domain pointer + ******************************************************************************/ + +static uint32 find_idmap_domain_index( struct idmap_domain *id_domain) +{ + int i; + + for (i = 0; i < num_domains; i++) { + if ( idmap_domains[i] == id_domain ) + return i; + } + + return -1; +} + + +/********************************************************* + Check if creating a mapping is permitted for the domain +*********************************************************/ + +static NTSTATUS idmap_can_map(const struct id_map *map, + struct idmap_domain **ret_dom) +{ + struct idmap_domain *dom; + + /* Check we do not create mappings for our own local domain, + * or BUILTIN or special SIDs */ + if ((sid_compare_domain(map->sid, get_global_sam_sid()) == 0) || + sid_check_is_in_builtin(map->sid) || + sid_check_is_in_wellknown_domain(map->sid) || + sid_check_is_in_unix_users(map->sid) || + sid_check_is_in_unix_groups(map->sid) ) + { + DEBUG(10, ("We are not supposed to create mappings for our own " + "domains (local, builtin, specials)\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Special check for trusted domain only = Yes */ + if (lp_winbind_trusted_domains_only()) { + struct winbindd_domain *wdom = find_our_domain(); + if (wdom && (sid_compare_domain(map->sid, &wdom->sid) == 0)) { + DEBUG(10, ("We are not supposed to create mappings for " + "our primary domain when is True\n")); + DEBUGADD(10, ("Leave [%s] unmapped\n", + sid_string_static(map->sid))); + return NT_STATUS_UNSUCCESSFUL; + } + } + + if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) { + /* huh, couldn't find a suitable domain, + * let's just leave it unmapped */ + DEBUG(10, ("Could not find idmap backend for SID %s", + sid_string_static(map->sid))); + return NT_STATUS_NO_SUCH_DOMAIN; + } + + if (dom->readonly) { + /* ouch the domain is read only, + * let's just leave it unmapped */ + DEBUG(10, ("idmap backend for SID %s is READONLY!\n", + sid_string_static(map->sid))); + return NT_STATUS_UNSUCCESSFUL; + } + + *ret_dom = dom; + return NT_STATUS_OK; +} + +static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map) +{ + NTSTATUS ret; + struct idmap_domain *dom; + + /* If we are offline we cannot lookup SIDs, deny mapping */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + ret = idmap_can_map(map, &dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return NT_STATUS_NONE_MAPPED; + } + + /* check if this is a valid SID and then map it */ + switch (map->xid.type) { + case ID_TYPE_UID: + ret = idmap_allocate_uid(&map->xid); + if ( ! NT_STATUS_IS_OK(ret)) { + /* can't allocate id, let's just leave it unmapped */ + DEBUG(2, ("uid allocation failed! " + "Can't create mapping\n")); + return NT_STATUS_NONE_MAPPED; + } + break; + case ID_TYPE_GID: + ret = idmap_allocate_gid(&map->xid); + if ( ! NT_STATUS_IS_OK(ret)) { + /* can't allocate id, let's just leave it unmapped */ + DEBUG(2, ("gid allocation failed! " + "Can't create mapping\n")); + return NT_STATUS_NONE_MAPPED; + } + break; + default: + /* invalid sid, let's just leave it unmapped */ + DEBUG(3,("idmap_new_mapping: Refusing to create a " + "mapping for an unspecified ID type.\n")); + return NT_STATUS_NONE_MAPPED; + } + + /* ok, got a new id, let's set a mapping */ + map->status = ID_MAPPED; + + DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", + sid_string_static(map->sid), + (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", + (unsigned long)map->xid.id)); + ret = dom->methods->set_mapping(dom, map); + + if ( ! NT_STATUS_IS_OK(ret)) { + /* something wrong here :-( */ + DEBUG(2, ("Failed to commit mapping\n!")); + + /* TODO: would it make sense to have an "unalloc_id function?" */ + + return NT_STATUS_NONE_MAPPED; + } + + return NT_STATUS_OK; +} + +static NTSTATUS idmap_backends_set_mapping(const struct id_map *map) +{ + struct idmap_domain *dom; + NTSTATUS ret; + + DEBUG(10, ("Setting mapping %s <-> %s %lu\n", + sid_string_static(map->sid), + (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", + (unsigned long)map->xid.id)); + + ret = idmap_can_map(map, &dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + + DEBUG(10,("set_mapping for domain %s\n", dom->name )); + + return dom->methods->set_mapping(dom, map); +} + +static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids) +{ + struct idmap_domain *dom; + struct id_map **unmapped; + struct id_map **_ids; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i, u, n; + + if (!ids || !*ids) { + DEBUG(1, ("Invalid list of maps\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + ctx = talloc_named_const(NULL, 0, "idmap_backends_unixids_to_sids ctx"); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(10, ("Query backends to map ids->sids\n")); + + /* start from the default (the last one) and then if there are still + * unmapped entries cycle through the others */ + + _ids = ids; + + unmapped = NULL; + for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */ + + dom = idmap_domains[n]; + + DEBUG(10, ("Query sids from domain %s\n", dom->name)); + + ret = dom->methods->unixids_to_sids(dom, _ids); + IDMAP_REPORT_RET(ret); + + unmapped = NULL; + + for (i = 0, u = 0; _ids[i]; i++) { + if (_ids[i]->status != ID_MAPPED) { + unmapped = talloc_realloc(ctx, unmapped, + struct id_map *, u + 2); + IDMAP_CHECK_ALLOC(unmapped); + unmapped[u] = _ids[i]; + u++; + } + } + if (unmapped) { + /* terminate the unmapped list */ + unmapped[u] = NULL; + } else { /* no more entries, get out */ + break; + } + + _ids = unmapped; + + } + + if (unmapped) { + /* there are still unmapped ids, + * map them to the unix users/groups domains */ + /* except for expired entries, + * these will be returned as valid (offline mode) */ + for (i = 0; unmapped[i]; i++) { + if (unmapped[i]->status == ID_EXPIRED) continue; + switch (unmapped[i]->xid.type) { + case ID_TYPE_UID: + uid_to_unix_users_sid( + (uid_t)unmapped[i]->xid.id, + unmapped[i]->sid); + unmapped[i]->status = ID_MAPPED; + break; + case ID_TYPE_GID: + gid_to_unix_groups_sid( + (gid_t)unmapped[i]->xid.id, + unmapped[i]->sid); + unmapped[i]->status = ID_MAPPED; + break; + default: /* what?! */ + unmapped[i]->status = ID_UNKNOWN; + break; + } + } + } + + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; +} + +static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) +{ + struct id_map ***dom_ids; + struct idmap_domain *dom; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i, *counters; + + if ( (ctx = talloc_named_const(NULL, 0, "be_sids_to_ids")) == NULL ) { + DEBUG(1, ("failed to allocate talloc context, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(10, ("Query backends to map sids->ids\n")); + + /* split list per domain */ + if (num_domains == 0) { + DEBUG(1, ("No domains available?\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + dom_ids = TALLOC_ZERO_ARRAY(ctx, struct id_map **, num_domains); + IDMAP_CHECK_ALLOC(dom_ids); + counters = TALLOC_ZERO_ARRAY(ctx, int, num_domains); + IDMAP_CHECK_ALLOC(counters); + + /* partition the requests by domain */ + + for (i = 0; ids[i]; i++) { + uint32 idx; + + if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) { + /* no available idmap_domain. Move on */ + continue; + } + + DEBUG(10,("SID %s is being handled by %s\n", + sid_string_static(ids[i]->sid), + dom ? dom->name : "none" )); + + idx = find_idmap_domain_index( dom ); + SMB_ASSERT( idx != -1 ); + + dom_ids[idx] = talloc_realloc(ctx, dom_ids[idx], + struct id_map *, + counters[idx] + 2); + IDMAP_CHECK_ALLOC(dom_ids[idx]); + + dom_ids[idx][counters[idx]] = ids[i]; + counters[idx]++; + dom_ids[idx][counters[idx]] = NULL; + } + + /* All the ids have been dispatched in the right queues. + Let's cycle through the filled ones */ + + for (i = 0; i < num_domains; i++) { + if (dom_ids[i]) { + dom = idmap_domains[i]; + DEBUG(10, ("Query ids from domain %s\n", dom->name)); + ret = dom->methods->sids_to_unixids(dom, dom_ids[i]); + IDMAP_REPORT_RET(ret); + } + } + + /* ok all the backends have been contacted at this point */ + /* let's see if we have any unmapped SID left and act accordingly */ + + for (i = 0; ids[i]; i++) { + /* NOTE: this will NOT touch ID_EXPIRED entries that the backend + * was not able to confirm/deny (offline mode) */ + if (ids[i]->status == ID_UNKNOWN || + ids[i]->status == ID_UNMAPPED) { + /* ok this is an unmapped one, see if we can map it */ + ret = idmap_new_mapping(ctx, ids[i]); + if (NT_STATUS_IS_OK(ret)) { + /* successfully mapped */ + ids[i]->status = ID_MAPPED; + } else + if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { + /* could not map it */ + ids[i]->status = ID_UNMAPPED; + } else { + /* Something very bad happened down there + * OR we are offline */ + ids[i]->status = ID_UNKNOWN; + } + } + } + + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; +} + +/************************************************************************** + idmap interface functions +**************************************************************************/ + +NTSTATUS idmap_unixids_to_sids(struct id_map **ids) +{ + TALLOC_CTX *ctx; + NTSTATUS ret; + struct id_map **bids; + int i, bi; + int bn = 0; + struct winbindd_domain *our_domain = find_our_domain(); + + if (! NT_STATUS_IS_OK(ret = idmap_init())) { + return ret; + } + + if (!ids || !*ids) { + DEBUG(1, ("Invalid list of maps\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + ctx = talloc_named_const(NULL, 0, "idmap_unixids_to_sids ctx"); + if ( ! ctx) { + DEBUG(1, ("failed to allocate talloc context, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + /* no ids to be asked to the backends by default */ + bids = NULL; + bi = 0; + + for (i = 0; ids[i]; i++) { + + if ( ! ids[i]->sid) { + DEBUG(1, ("invalid null SID in id_map array")); + talloc_free(ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + ret = idmap_cache_map_id(idmap_cache, ids[i]); + + if ( ! NT_STATUS_IS_OK(ret)) { + + if ( ! bids) { + /* alloc space for ids to be resolved by + * backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + bn = 10; + } + + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; + + /* check if we need to allocate new space + * on the rids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, + struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + } + + /* make sure the last element is NULL */ + bids[bi] = NULL; + } + } + + /* let's see if there is any id mapping to be retieved + * from the backends */ + if (bi) { + /* Only do query if we are online */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + ret = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + + ret = idmap_backends_unixids_to_sids(bids); + IDMAP_CHECK_RET(ret); + + /* update the cache */ + for (i = 0; i < bi; i++) { + if (bids[i]->status == ID_MAPPED) { + ret = idmap_cache_set(idmap_cache, bids[i]); + } else if (bids[i]->status == ID_EXPIRED) { + /* the cache returned an expired entry and the + * backend was not able to clear the situation + * (offline). This handles a previous + * NT_STATUS_SYNCHRONIZATION_REQUIRED + * for disconnected mode, */ + bids[i]->status = ID_MAPPED; + } else if (bids[i]->status == ID_UNKNOWN) { + /* something bad here. We were not able to + * handle this for some reason, mark it as + * unmapped and hope next time things will + * settle down. */ + bids[i]->status = ID_UNMAPPED; + } else { /* unmapped */ + ret = idmap_cache_set_negative_id(idmap_cache, + bids[i]); + } + IDMAP_CHECK_RET(ret); + } + } + + ret = NT_STATUS_OK; +done: + talloc_free(ctx); + return ret; +} + +NTSTATUS idmap_sids_to_unixids(struct id_map **ids) +{ + TALLOC_CTX *ctx; + NTSTATUS ret; + struct id_map **bids; + int i, bi; + int bn = 0; + struct winbindd_domain *our_domain = find_our_domain(); + + if (! NT_STATUS_IS_OK(ret = idmap_init())) { + return ret; + } + + if (!ids || !*ids) { + DEBUG(1, ("Invalid list of maps\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + ctx = talloc_named_const(NULL, 0, "idmap_sids_to_unixids ctx"); + if ( ! ctx) { + DEBUG(1, ("failed to allocate talloc context, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + /* no ids to be asked to the backends by default */ + bids = NULL; + bi = 0; + + for (i = 0; ids[i]; i++) { + + if ( ! ids[i]->sid) { + DEBUG(1, ("invalid null SID in id_map array\n")); + talloc_free(ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + ret = idmap_cache_map_sid(idmap_cache, ids[i]); + + if ( ! NT_STATUS_IS_OK(ret)) { + + if ( ! bids) { + /* alloc space for ids to be resolved + by backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + bn = 10; + } + + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; + + /* check if we need to allocate new space + * on the ids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, + struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + } + + /* make sure the last element is NULL */ + bids[bi] = NULL; + } + } + + /* let's see if there is any id mapping to be retieved + * from the backends */ + if (bids) { + /* Only do query if we are online */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + ret = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + + ret = idmap_backends_sids_to_unixids(bids); + IDMAP_CHECK_RET(ret); + + /* update the cache */ + for (i = 0; bids[i]; i++) { + if (bids[i]->status == ID_MAPPED) { + ret = idmap_cache_set(idmap_cache, bids[i]); + } else if (bids[i]->status == ID_EXPIRED) { + /* the cache returned an expired entry and the + * backend was not able to clear the situation + * (offline). This handles a previous + * NT_STATUS_SYNCHRONIZATION_REQUIRED + * for disconnected mode, */ + bids[i]->status = ID_MAPPED; + } else if (bids[i]->status == ID_UNKNOWN) { + /* something bad here. We were not able to + * handle this for some reason, mark it as + * unmapped and hope next time things will + * settle down. */ + bids[i]->status = ID_UNMAPPED; + } else { /* unmapped */ + ret = idmap_cache_set_negative_sid(idmap_cache, + bids[i]); + } + IDMAP_CHECK_RET(ret); + } + } + + ret = NT_STATUS_OK; +done: + talloc_free(ctx); + return ret; +} + +NTSTATUS idmap_set_mapping(const struct id_map *id) +{ + TALLOC_CTX *ctx; + NTSTATUS ret; + + if (! NT_STATUS_IS_OK(ret = idmap_init())) { + return ret; + } + + /* sanity checks */ + if ((id->sid == NULL) || (id->status != ID_MAPPED)) { + DEBUG(1, ("NULL SID or unmapped entry\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + /* TODO: check uid/gid range ? */ + + ctx = talloc_named_const(NULL, 0, "idmap_set_mapping ctx"); + if ( ! ctx) { + DEBUG(1, ("failed to allocate talloc context, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + /* set the new mapping */ + ret = idmap_backends_set_mapping(id); + IDMAP_CHECK_RET(ret); + + /* set the mapping in the cache */ + ret = idmap_cache_set(idmap_cache, id); + IDMAP_CHECK_RET(ret); + +done: + talloc_free(ctx); + return ret; +} + +/************************************************************************** + Dump backend status. +**************************************************************************/ + +void idmap_dump_maps(char *logfile) +{ + NTSTATUS ret; + struct unixid allid; + struct id_map *maps; + int num_maps; + FILE *dump; + int i; + + if (! NT_STATUS_IS_OK(ret = idmap_init())) { + return; + } + + dump = fopen(logfile, "w"); + if ( ! dump) { + DEBUG(0, ("Unable to open open stream for file [%s], " + "errno: %d\n", logfile, errno)); + return; + } + + if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + allid.type = ID_TYPE_UID; + allid.id = 0; + idmap_alloc_ctx->methods->get_id_hwm(&allid); + fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id); + + allid.type = ID_TYPE_GID; + allid.id = 0; + idmap_alloc_ctx->methods->get_id_hwm(&allid); + fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id); + } + + maps = talloc(idmap_ctx, struct id_map); + num_maps = 0; + + for (i = 0; i < num_domains; i++) { + if (idmap_domains[i]->methods->dump_data) { + idmap_domains[i]->methods->dump_data(idmap_domains[i], + &maps, &num_maps); + } + } + + for (i = 0; i < num_maps; i++) { + switch (maps[i].xid.type) { + case ID_TYPE_UID: + fprintf(dump, "UID %lu %s\n", + (unsigned long)maps[i].xid.id, + sid_string_static(maps[i].sid)); + break; + case ID_TYPE_GID: + fprintf(dump, "GID %lu %s\n", + (unsigned long)maps[i].xid.id, + sid_string_static(maps[i].sid)); + break; + case ID_TYPE_NOT_SPECIFIED: + break; + } + } + + fflush(dump); + fclose(dump); +} + +char *idmap_fetch_secret(const char *backend, bool alloc, + const char *domain, const char *identity) +{ + char *tmp, *ret; + int r; + + if (alloc) { + r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend); + } else { + r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain); + } + + if (r < 0) + return NULL; + + strupper_m(tmp); /* make sure the key is case insensitive */ + ret = secrets_fetch_generic(tmp, identity); + + SAFE_FREE(tmp); + + return ret; +} + diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c new file mode 100644 index 0000000000..41dbb471f9 --- /dev/null +++ b/source3/winbindd/idmap_ad.c @@ -0,0 +1,870 @@ +/* + * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts + * + * Unix SMB/CIFS implementation. + * + * Winbind ADS backend functions + * + * Copyright (C) Andrew Tridgell 2001 + * Copyright (C) Andrew Bartlett 2003 + * Copyright (C) Gerald (Jerry) Carter 2004-2007 + * Copyright (C) Luke Howard 2001-2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache" + +#define IDMAP_AD_MAX_IDS 30 +#define CHECK_ALLOC_DONE(mem) do { \ + if (!mem) { \ + DEBUG(0, ("Out of memory!\n")); \ + ret = NT_STATUS_NO_MEMORY; \ + goto done; \ + } \ +} while (0) + +struct idmap_ad_context { + uint32_t filter_low_id; + uint32_t filter_high_id; +}; + +NTSTATUS init_module(void); + +static ADS_STRUCT *ad_idmap_ads = NULL; +static struct posix_schema *ad_schema = NULL; +static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN; + +/************************************************************************ + ***********************************************************************/ + +static ADS_STRUCT *ad_idmap_cached_connection_internal(void) +{ + ADS_STRUCT *ads; + ADS_STATUS status; + BOOL local = False; + fstring dc_name; + struct in_addr dc_ip; + + if (ad_idmap_ads != NULL) { + + time_t expire; + time_t now = time(NULL); + + ads = ad_idmap_ads; + + expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire); + + /* check for a valid structure */ + DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n", + (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); + + if ( ads->config.realm && (expire > time(NULL))) { + return ads; + } else { + /* we own this ADS_STRUCT so make sure it goes away */ + DEBUG(7,("Deleting expired krb5 credential cache\n")); + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy(WINBIND_CCACHE_NAME); + ad_idmap_ads = NULL; + TALLOC_FREE( ad_schema ); + } + } + + if (!local) { + /* we don't want this to affect the users ccache */ + setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); + } + + if ( (ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL ) { + DEBUG(1,("ads_init failed\n")); + return NULL; + } + + /* the machine acct password might have change - fetch it every time */ + SAFE_FREE(ads->auth.password); + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + SAFE_FREE(ads->auth.realm); + ads->auth.realm = SMB_STRDUP(lp_realm()); + + /* setup server affinity */ + + get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip ); + + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(1, ("ad_idmap_init: failed to connect to AD\n")); + ads_destroy(&ads); + return NULL; + } + + ads->is_mine = False; + + ad_idmap_ads = ads; + + return ads; +} + +/************************************************************************ + ***********************************************************************/ + +static ADS_STRUCT *ad_idmap_cached_connection(void) +{ + ADS_STRUCT *ads = ad_idmap_cached_connection_internal(); + + if ( !ads ) + return NULL; + + /* if we have a valid ADS_STRUCT and the schema model is + defined, then we can return here. */ + + if ( ad_schema ) + return ads; + + /* Otherwise, set the schema model */ + + if ( (ad_map_type == WB_POSIX_MAP_SFU) || + (ad_map_type == WB_POSIX_MAP_SFU20) || + (ad_map_type == WB_POSIX_MAP_RFC2307) ) + { + ADS_STATUS schema_status; + + schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema); + if ( !ADS_ERR_OK(schema_status) ) { + DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n")); + return NULL; + } + } + + return ads; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom) +{ + struct idmap_ad_context *ctx; + char *config_option; + const char *range = NULL; + const char *schema_mode = NULL; + + if ( (ctx = TALLOC_ZERO_P(dom, struct idmap_ad_context)) == NULL ) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + + /* load ranges */ + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (range && range[0]) { + if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) || + (ctx->filter_low_id > ctx->filter_high_id)) { + DEBUG(1, ("ERROR: invalid filter range [%s]", range)); + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + } + + /* schema mode */ + if ( ad_map_type == WB_POSIX_MAP_UNKNOWN ) + ad_map_type = WB_POSIX_MAP_RFC2307; + schema_mode = lp_parm_const_string(-1, config_option, "schema_mode", NULL); + if ( schema_mode && schema_mode[0] ) { + if ( strequal(schema_mode, "sfu") ) + ad_map_type = WB_POSIX_MAP_SFU; + else if ( strequal(schema_mode, "sfu20" ) ) + ad_map_type = WB_POSIX_MAP_SFU20; + else if ( strequal(schema_mode, "rfc2307" ) ) + ad_map_type = WB_POSIX_MAP_RFC2307; + else + DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n", + schema_mode)); + } + + dom->private_data = ctx; + dom->initialized = True; + + talloc_free(config_option); + + return NT_STATUS_OK; +} + +/************************************************************************ + Search up to IDMAP_AD_MAX_IDS entries in maps for a match. + ***********************************************************************/ + +static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id) +{ + int i; + + for (i = 0; maps[i] && ixid.type == type) && (maps[i]->xid.id == id)) { + return maps[i]; + } + } + + return NULL; +} + +/************************************************************************ + Search up to IDMAP_AD_MAX_IDS entries in maps for a match + ***********************************************************************/ + +static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid) +{ + int i; + + for (i = 0; maps[i] && isid, sid)) { + return maps[i]; + } + } + + return NULL; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + NTSTATUS ret; + TALLOC_CTX *memctx; + struct idmap_ad_context *ctx; + ADS_STATUS rc; + ADS_STRUCT *ads; + const char *attrs[] = { "sAMAccountType", + "objectSid", + NULL, /* uidnumber */ + NULL, /* gidnumber */ + NULL }; + LDAPMessage *res = NULL; + LDAPMessage *entry = NULL; + char *filter = NULL; + int idx = 0; + int bidx = 0; + int count; + int i; + char *u_filter = NULL; + char *g_filter = NULL; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* Initilization my have been deferred because we were offline */ + if ( ! dom->initialized) { + ret = idmap_ad_initialize(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + if ( (memctx = talloc_new(ctx)) == NULL ) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + if ( (ads = ad_idmap_cached_connection()) == NULL ) { + DEBUG(1, ("ADS uninitialized\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + attrs[2] = ad_schema->posix_uidnumber_attr; + attrs[3] = ad_schema->posix_gidnumber_attr; + +again: + bidx = idx; + for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) { + switch (ids[idx]->xid.type) { + case ID_TYPE_UID: + if ( ! u_filter) { + u_filter = talloc_asprintf(memctx, "(&(|" + "(sAMAccountType=%d)" + "(sAMAccountType=%d)" + "(sAMAccountType=%d))(|", + ATYPE_NORMAL_ACCOUNT, + ATYPE_WORKSTATION_TRUST, + ATYPE_INTERDOMAIN_TRUST); + } + u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)", + ad_schema->posix_uidnumber_attr, + (unsigned long)ids[idx]->xid.id); + CHECK_ALLOC_DONE(u_filter); + break; + + case ID_TYPE_GID: + if ( ! g_filter) { + g_filter = talloc_asprintf(memctx, "(&(|" + "(sAMAccountType=%d)" + "(sAMAccountType=%d))(|", + ATYPE_SECURITY_GLOBAL_GROUP, + ATYPE_SECURITY_LOCAL_GROUP); + } + g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)", + ad_schema->posix_gidnumber_attr, + (unsigned long)ids[idx]->xid.id); + CHECK_ALLOC_DONE(g_filter); + break; + + default: + DEBUG(3, ("Error: mapping requested but Unknown ID type\n")); + ids[idx]->status = ID_UNKNOWN; + continue; + } + } + filter = talloc_asprintf(memctx, "(|"); + CHECK_ALLOC_DONE(filter); + if ( u_filter) { + filter = talloc_asprintf_append(filter, "%s))", u_filter); + CHECK_ALLOC_DONE(filter); + TALLOC_FREE(u_filter); + } + if ( g_filter) { + filter = talloc_asprintf_append(filter, "%s))", g_filter); + CHECK_ALLOC_DONE(filter); + TALLOC_FREE(g_filter); + } + filter = talloc_asprintf_append(filter, ")"); + CHECK_ALLOC_DONE(filter); + + rc = ads_search_retry(ads, &res, filter, attrs); + if (!ADS_ERR_OK(rc)) { + DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc))); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if ( (count = ads_count_replies(ads, res)) == 0 ) { + DEBUG(10, ("No IDs found\n")); + } + + entry = res; + for (i = 0; (i < count) && entry; i++) { + DOM_SID sid; + enum id_type type; + struct id_map *map; + uint32_t id; + uint32_t atype; + + if (i == 0) { /* first entry */ + entry = ads_first_entry(ads, entry); + } else { /* following ones */ + entry = ads_next_entry(ads, entry); + } + + if ( !entry ) { + DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n")); + break; + } + + /* first check if the SID is present */ + if (!ads_pull_sid(ads, entry, "objectSid", &sid)) { + DEBUG(2, ("Could not retrieve SID from entry\n")); + continue; + } + + /* get type */ + if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) { + DEBUG(1, ("could not get SAM account type\n")); + continue; + } + + switch (atype & 0xF0000000) { + case ATYPE_SECURITY_GLOBAL_GROUP: + case ATYPE_SECURITY_LOCAL_GROUP: + type = ID_TYPE_GID; + break; + case ATYPE_NORMAL_ACCOUNT: + case ATYPE_WORKSTATION_TRUST: + case ATYPE_INTERDOMAIN_TRUST: + type = ID_TYPE_UID; + break; + default: + DEBUG(1, ("unrecognized SAM account type %08x\n", atype)); + continue; + } + + if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ? + ad_schema->posix_uidnumber_attr : + ad_schema->posix_gidnumber_attr, + &id)) + { + DEBUG(1, ("Could not get unix ID\n")); + continue; + } + + if ((id == 0) || + (ctx->filter_low_id && (id < ctx->filter_low_id)) || + (ctx->filter_high_id && (id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + id, ctx->filter_low_id, ctx->filter_high_id)); + continue; + } + + map = find_map_by_id(&ids[bidx], type, id); + if (!map) { + DEBUG(2, ("WARNING: couldn't match result with requested ID\n")); + continue; + } + + sid_copy(map->sid, &sid); + + /* mapped */ + map->status = ID_MAPPED; + + DEBUG(10, ("Mapped %s -> %lu (%d)\n", + sid_string_static(map->sid), + (unsigned long)map->xid.id, + map->xid.type)); + } + + if (res) { + ads_msgfree(ads, res); + } + + if (ids[idx]) { /* still some values to map */ + goto again; + } + + ret = NT_STATUS_OK; + + /* mark all unknown/expired ones as unmapped */ + for (i = 0; ids[i]; i++) { + if (ids[i]->status != ID_MAPPED) + ids[i]->status = ID_UNMAPPED; + } + +done: + talloc_free(memctx); + return ret; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + NTSTATUS ret; + TALLOC_CTX *memctx; + struct idmap_ad_context *ctx; + ADS_STATUS rc; + ADS_STRUCT *ads; + const char *attrs[] = { "sAMAccountType", + "objectSid", + NULL, /* attr_uidnumber */ + NULL, /* attr_gidnumber */ + NULL }; + LDAPMessage *res = NULL; + LDAPMessage *entry = NULL; + char *filter = NULL; + int idx = 0; + int bidx = 0; + int count; + int i; + char *sidstr; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* Initilization my have been deferred because we were offline */ + if ( ! dom->initialized) { + ret = idmap_ad_initialize(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + if ( (memctx = talloc_new(ctx)) == NULL ) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + if ( (ads = ad_idmap_cached_connection()) == NULL ) { + DEBUG(1, ("ADS uninitialized\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + attrs[2] = ad_schema->posix_uidnumber_attr; + attrs[3] = ad_schema->posix_gidnumber_attr; + +again: + filter = talloc_asprintf(memctx, "(&(|" + "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */ + "(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */ + ")(|", + ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, + ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP); + + CHECK_ALLOC_DONE(filter); + + bidx = idx; + for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) { + + sidstr = sid_binstring(ids[idx]->sid); + filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr); + + free(sidstr); + CHECK_ALLOC_DONE(filter); + } + filter = talloc_asprintf_append(filter, "))"); + CHECK_ALLOC_DONE(filter); + DEBUG(10, ("Filter: [%s]\n", filter)); + + rc = ads_search_retry(ads, &res, filter, attrs); + if (!ADS_ERR_OK(rc)) { + DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc))); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if ( (count = ads_count_replies(ads, res)) == 0 ) { + DEBUG(10, ("No IDs found\n")); + } + + entry = res; + for (i = 0; (i < count) && entry; i++) { + DOM_SID sid; + enum id_type type; + struct id_map *map; + uint32_t id; + uint32_t atype; + + if (i == 0) { /* first entry */ + entry = ads_first_entry(ads, entry); + } else { /* following ones */ + entry = ads_next_entry(ads, entry); + } + + if ( !entry ) { + DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n")); + break; + } + + /* first check if the SID is present */ + if (!ads_pull_sid(ads, entry, "objectSid", &sid)) { + DEBUG(2, ("Could not retrieve SID from entry\n")); + continue; + } + + map = find_map_by_sid(&ids[bidx], &sid); + if (!map) { + DEBUG(2, ("WARNING: couldn't match result with requested SID\n")); + continue; + } + + /* get type */ + if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) { + DEBUG(1, ("could not get SAM account type\n")); + continue; + } + + switch (atype & 0xF0000000) { + case ATYPE_SECURITY_GLOBAL_GROUP: + case ATYPE_SECURITY_LOCAL_GROUP: + type = ID_TYPE_GID; + break; + case ATYPE_NORMAL_ACCOUNT: + case ATYPE_WORKSTATION_TRUST: + case ATYPE_INTERDOMAIN_TRUST: + type = ID_TYPE_UID; + break; + default: + DEBUG(1, ("unrecognized SAM account type %08x\n", atype)); + continue; + } + + if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ? + ad_schema->posix_uidnumber_attr : + ad_schema->posix_gidnumber_attr, + &id)) + { + DEBUG(1, ("Could not get unix ID\n")); + continue; + } + if ((id == 0) || + (ctx->filter_low_id && (id < ctx->filter_low_id)) || + (ctx->filter_high_id && (id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + id, ctx->filter_low_id, ctx->filter_high_id)); + continue; + } + + /* mapped */ + map->xid.type = type; + map->xid.id = id; + map->status = ID_MAPPED; + + DEBUG(10, ("Mapped %s -> %lu (%d)\n", + sid_string_static(map->sid), + (unsigned long)map->xid.id, + map->xid.type)); + } + + if (res) { + ads_msgfree(ads, res); + } + + if (ids[idx]) { /* still some values to map */ + goto again; + } + + ret = NT_STATUS_OK; + + /* mark all unknwoni/expired ones as unmapped */ + for (i = 0; ids[i]; i++) { + if (ids[i]->status != ID_MAPPED) + ids[i]->status = ID_UNMAPPED; + } + +done: + talloc_free(memctx); + return ret; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS idmap_ad_close(struct idmap_domain *dom) +{ + ADS_STRUCT *ads = ad_idmap_ads; + + if (ads != NULL) { + /* we own this ADS_STRUCT so make sure it goes away */ + ads->is_mine = True; + ads_destroy( &ads ); + ad_idmap_ads = NULL; + } + + TALLOC_FREE( ad_schema ); + + return NT_STATUS_OK; +} + +/* + * nss_info_{sfu,sfu20,rfc2307} + */ + +/************************************************************************ + Initialize the {sfu,sfu20,rfc2307} state + ***********************************************************************/ + +static NTSTATUS nss_sfu_init( struct nss_domain_entry *e ) +{ + /* Sanity check if we have previously been called with a + different schema model */ + + if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) && + (ad_map_type != WB_POSIX_MAP_SFU) ) + { + DEBUG(0,("nss_sfu_init: Posix Map type has already been set. " + "Mixed schema models not supported!\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + ad_map_type = WB_POSIX_MAP_SFU; + + return NT_STATUS_OK; +} + +static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e ) +{ + /* Sanity check if we have previously been called with a + different schema model */ + + if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) && + (ad_map_type != WB_POSIX_MAP_SFU20) ) + { + DEBUG(0,("nss_sfu20_init: Posix Map type has already been set. " + "Mixed schema models not supported!\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + ad_map_type = WB_POSIX_MAP_SFU20; + + return NT_STATUS_OK; +} + +static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) +{ + /* Sanity check if we have previously been called with a + different schema model */ + + if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) && + (ad_map_type != WB_POSIX_MAP_RFC2307) ) + { + DEBUG(0,("nss_rfc2307_init: Posix Map type has already been set. " + "Mixed schema models not supported!\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + ad_map_type = WB_POSIX_MAP_RFC2307; + + return NT_STATUS_OK; +} + + +/************************************************************************ + ***********************************************************************/ +static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, + const DOM_SID *sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, + LDAPMessage *msg, + char **homedir, + char **shell, + char **gecos, + uint32 *gid ) +{ + ADS_STRUCT *ads_internal = NULL; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* We are assuming that the internal ADS_STRUCT is for the + same forest as the incoming *ads pointer */ + + ads_internal = ad_idmap_cached_connection(); + + if ( !ads_internal || !ad_schema ) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + if ( !homedir || !shell || !gecos ) + return NT_STATUS_INVALID_PARAMETER; + + *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr ); + *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr ); + *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr ); + + if ( gid ) { + if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) ) + *gid = (uint32)-1; + } + + return NT_STATUS_OK; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS nss_ad_close( void ) +{ + /* nothing to do. All memory is free()'d by the idmap close_fn() */ + + return NT_STATUS_OK; +} + +/************************************************************************ + Function dispatch tables for the idmap and nss plugins + ***********************************************************************/ + +static struct idmap_methods ad_methods = { + .init = idmap_ad_initialize, + .unixids_to_sids = idmap_ad_unixids_to_sids, + .sids_to_unixids = idmap_ad_sids_to_unixids, + .close_fn = idmap_ad_close +}; + +/* The SFU and RFC2307 NSS plugins share everything but the init + function which sets the intended schema model to use */ + +static struct nss_info_methods nss_rfc2307_methods = { + .init = nss_rfc2307_init, + .get_nss_info = nss_ad_get_info, + .close_fn = nss_ad_close +}; + +static struct nss_info_methods nss_sfu_methods = { + .init = nss_sfu_init, + .get_nss_info = nss_ad_get_info, + .close_fn = nss_ad_close +}; + +static struct nss_info_methods nss_sfu20_methods = { + .init = nss_sfu20_init, + .get_nss_info = nss_ad_get_info, + .close_fn = nss_ad_close +}; + + + +/************************************************************************ + Initialize the plugins + ***********************************************************************/ + +NTSTATUS idmap_ad_init(void) +{ + static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_nss_sfu20 = NT_STATUS_UNSUCCESSFUL; + + /* Always register the AD method first in order to get the + idmap_domain interface called */ + + if ( !NT_STATUS_IS_OK(status_idmap_ad) ) { + status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, + "ad", &ad_methods); + if ( !NT_STATUS_IS_OK(status_idmap_ad) ) + return status_idmap_ad; + } + + if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) { + status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "rfc2307", &nss_rfc2307_methods ); + if ( !NT_STATUS_IS_OK(status_nss_rfc2307) ) + return status_nss_rfc2307; + } + + if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) { + status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "sfu", &nss_sfu_methods ); + if ( !NT_STATUS_IS_OK(status_nss_sfu) ) + return status_nss_sfu; + } + + if ( !NT_STATUS_IS_OK( status_nss_sfu20 ) ) { + status_nss_sfu20 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "sfu20", &nss_sfu20_methods ); + if ( !NT_STATUS_IS_OK(status_nss_sfu20) ) + return status_nss_sfu20; + } + + return NT_STATUS_OK; +} + diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c new file mode 100644 index 0000000000..4f01cb1392 --- /dev/null +++ b/source3/winbindd/idmap_cache.c @@ -0,0 +1,531 @@ +/* + Unix SMB/CIFS implementation. + ID Mapping Cache + + based on gencache + + Copyright (C) Simo Sorce 2006 + Copyright (C) Rafal Szczesniak 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .*/ + +#include "includes.h" +#include "winbindd.h" + +#define TIMEOUT_LEN 12 +#define IDMAP_CACHE_DATA_FMT "%12u/%s" +#define IDMAP_READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" + +struct idmap_cache_ctx { + TDB_CONTEXT *tdb; +}; + +static int idmap_cache_destructor(struct idmap_cache_ctx *cache) +{ + int ret = 0; + + if (cache && cache->tdb) { + ret = tdb_close(cache->tdb); + cache->tdb = NULL; + } + + return ret; +} + +struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) +{ + struct idmap_cache_ctx *cache; + char* cache_fname = NULL; + + cache = talloc(memctx, struct idmap_cache_ctx); + if ( ! cache) { + DEBUG(0, ("Out of memory!\n")); + return NULL; + } + + cache_fname = lock_path("idmap_cache.tdb"); + + DEBUG(10, ("Opening cache file at %s\n", cache_fname)); + + cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + + if (!cache->tdb) { + DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname)); + return NULL; + } + + talloc_set_destructor(cache, idmap_cache_destructor); + + return cache; +} + +void idmap_cache_shutdown(struct idmap_cache_ctx *cache) +{ + talloc_free(cache); +} + +NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct id_map *id) +{ + *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", sid_string_static(id->sid)); + if ( ! *sidkey) { + DEBUG(1, ("failed to build sidkey, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, const struct id_map *id) +{ + *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu", + (id->xid.type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)id->xid.id); + if ( ! *idkey) { + DEBUG(1, ("failed to build idkey, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) +{ + NTSTATUS ret; + time_t timeout = time(NULL) + lp_idmap_cache_time(); + TDB_DATA databuf; + char *sidkey; + char *idkey; + char *valstr; + + /* Don't cache lookups in the S-1-22-{1,2} domain */ + if ( (id->xid.type == ID_TYPE_UID) && + sid_check_is_in_unix_users(id->sid) ) + { + return NT_STATUS_OK; + } + if ( (id->xid.type == ID_TYPE_GID) && + sid_check_is_in_unix_groups(id->sid) ) + { + return NT_STATUS_OK; + } + + + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; + + /* use sidkey as the local memory ctx */ + ret = idmap_cache_build_idkey(sidkey, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) { + goto done; + } + + /* save SID -> ID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr , ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* save ID -> SID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ret = NT_STATUS_OK; + +done: + talloc_free(sidkey); + return ret; +} + +NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) +{ + NTSTATUS ret; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; + char *sidkey; + char *valstr; + + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + +done: + talloc_free(sidkey); + return ret; +} + +NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) +{ + NTSTATUS ret; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; + char *idkey; + char *valstr; + + ret = idmap_cache_build_idkey(cache, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; + + /* use idkey as the local memory ctx */ + valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + +done: + talloc_free(idkey); + return ret; +} + +NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) +{ + char *rem; + + /* see if it is a sid */ + if ( ! strncmp("IDMAP/SID/", value, 10)) { + + if ( ! string_to_sid(id->sid, &value[10])) { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + } + + /* not a SID see if it is an UID or a GID */ + if ( ! strncmp("IDMAP/UID/", value, 10)) { + + /* a uid */ + id->xid.type = ID_TYPE_UID; + + } else if ( ! strncmp("IDMAP/GID/", value, 10)) { + + /* a gid */ + id->xid.type = ID_TYPE_GID; + + } else { + + /* a completely bogus value bail out */ + goto failed; + } + + id->xid.id = strtol(&value[10], &rem, 0); + if (*rem != '\0') { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + +failed: + DEBUG(1, ("invalid value: %s\n", value)); + id->status = ID_UNKNOWN; + return NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +BOOL idmap_cache_is_negative(const char *val) +{ + if ( ! strcmp("IDMAP/NEGATIVE", val)) { + return True; + } + return False; +} + +/* search the cahce for the SID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. + */ + +NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) +{ + NTSTATUS ret; + TDB_DATA databuf; + time_t t; + char *sidkey; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); + + /* make sure it is marked as not mapped by default */ + id->status = ID_UNKNOWN; + + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; + + databuf = tdb_fetch_bystring(cache->tdb, sidkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", sidkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + goto done; + } + + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + + /* Check for valid or expired cache hits */ + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped as it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } + +done: + SAFE_FREE(databuf.dptr); + talloc_free(sidkey); + return ret; +} + +/* search the cahce for the ID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. + */ + +NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) +{ + NTSTATUS ret; + TDB_DATA databuf; + time_t t; + char *idkey; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); + + /* make sure it is marked as unknown by default */ + id->status = ID_UNKNOWN; + + ret = idmap_cache_build_idkey(cache, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; + + databuf = tdb_fetch_bystring(cache->tdb, idkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", idkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + goto done; + } + + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + ret = NT_STATUS_NONE_MAPPED; + + goto done; + } + + /* Process the negative cache hit */ + + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped is it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } + +done: + SAFE_FREE(databuf.dptr); + talloc_free(idkey); + return ret; +} + diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c new file mode 100644 index 0000000000..3b63915b05 --- /dev/null +++ b/source3/winbindd/idmap_ldap.c @@ -0,0 +1,1505 @@ +/* + Unix SMB/CIFS implementation. + + idmap LDAP backend + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Gerald Carter 2003 + Copyright (C) Simo Sorce 2003-2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +#include +#include + +#include "smbldap.h" + +struct idmap_ldap_context { + struct smbldap_state *smbldap_state; + char *url; + char *suffix; + char *user_dn; + uint32_t filter_low_id, filter_high_id; /* Filter range */ + BOOL anon; +}; + +struct idmap_ldap_alloc_context { + struct smbldap_state *smbldap_state; + char *url; + char *suffix; + char *user_dn; + uid_t low_uid, high_uid; /* Range of uids */ + gid_t low_gid, high_gid; /* Range of gids */ + +}; + +#define CHECK_ALLOC_DONE(mem) do { \ + if (!mem) { \ + DEBUG(0, ("Out of memory!\n")); \ + ret = NT_STATUS_NO_MEMORY; \ + goto done; \ + } } while (0) + +/********************************************************************** + IDMAP ALLOC TDB BACKEND +**********************************************************************/ + +static struct idmap_ldap_alloc_context *idmap_alloc_ldap; + +/********************************************************************* + ********************************************************************/ + +static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx, + struct smbldap_state *ldap_state, + const char *config_option, + struct idmap_domain *dom, + char **dn ) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + char *secret = NULL; + const char *tmp = NULL; + char *user_dn = NULL; + BOOL anon = False; + + /* assume anonymous if we don't have a specified user */ + + tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL); + + if ( tmp ) { + if (!dom) { + /* only the alloc backend can pass in a NULL dom */ + secret = idmap_fetch_secret("ldap", True, + NULL, tmp); + } else { + secret = idmap_fetch_secret("ldap", False, + dom->name, tmp); + } + + if (!secret) { + DEBUG(0, ("get_credentials: Unable to fetch " + "auth credentials for %s in %s\n", + tmp, (dom==NULL)?"ALLOC":dom->name)); + ret = NT_STATUS_ACCESS_DENIED; + goto done; + } + *dn = talloc_strdup(mem_ctx, tmp); + CHECK_ALLOC_DONE(*dn); + } else { + if (!fetch_ldap_pw(&user_dn, &secret)) { + DEBUG(2, ("get_credentials: Failed to lookup ldap " + "bind creds. Using anonymous connection.\n")); + anon = True; + } else { + *dn = talloc_strdup(mem_ctx, user_dn); + SAFE_FREE( user_dn ); + CHECK_ALLOC_DONE(*dn); + } + } + + smbldap_set_creds(ldap_state, anon, *dn, secret); + ret = NT_STATUS_OK; + +done: + SAFE_FREE(secret); + + return ret; +} + + +/********************************************************************** + Verify the sambaUnixIdPool entry in the directory. +**********************************************************************/ + +static NTSTATUS verify_idpool(void) +{ + NTSTATUS ret; + TALLOC_CTX *ctx; + LDAPMessage *result = NULL; + LDAPMod **mods = NULL; + const char **attr_list; + char *filter; + int count; + int rc; + + if ( ! idmap_alloc_ldap) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx = talloc_new(idmap_alloc_ldap); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL); + CHECK_ALLOC_DONE(filter); + + attr_list = get_attr_list(ctx, idpool_attr_list); + CHECK_ALLOC_DONE(attr_list); + + rc = smbldap_search(idmap_alloc_ldap->smbldap_state, + idmap_alloc_ldap->suffix, + LDAP_SCOPE_SUBTREE, + filter, + attr_list, + 0, + &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(1, ("Unable to verify the idpool, " + "cannot continue initialization!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + + ldap_msgfree(result); + + if ( count > 1 ) { + DEBUG(0,("Multiple entries returned from %s (base == %s)\n", + filter, idmap_alloc_ldap->suffix)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + else if (count == 0) { + char *uid_str, *gid_str; + + uid_str = talloc_asprintf(ctx, "%lu", + (unsigned long)idmap_alloc_ldap->low_uid); + gid_str = talloc_asprintf(ctx, "%lu", + (unsigned long)idmap_alloc_ldap->low_gid); + + smbldap_set_mod(&mods, LDAP_MOD_ADD, + "objectClass", LDAP_OBJ_IDPOOL); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(idpool_attr_list, + LDAP_ATTR_UIDNUMBER), + uid_str); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(idpool_attr_list, + LDAP_ATTR_GIDNUMBER), + gid_str); + if (mods) { + rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, + idmap_alloc_ldap->suffix, + mods); + ldap_mods_free(mods, True); + } else { + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } + + ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL; +done: + talloc_free(ctx); + return ret; +} + +/***************************************************************************** + Initialise idmap database. +*****************************************************************************/ + +static NTSTATUS idmap_ldap_alloc_init(const char *params) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + const char *range; + const char *tmp; + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + + /* Only do init if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context); + CHECK_ALLOC_DONE( idmap_alloc_ldap ); + + /* load ranges */ + + idmap_alloc_ldap->low_uid = 0; + idmap_alloc_ldap->high_uid = 0; + idmap_alloc_ldap->low_gid = 0; + idmap_alloc_ldap->high_gid = 0; + + range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); + if (range && range[0]) { + unsigned low_id, high_id; + + if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { + if (low_id < high_id) { + idmap_alloc_ldap->low_gid = low_id; + idmap_alloc_ldap->low_uid = low_id; + idmap_alloc_ldap->high_gid = high_id; + idmap_alloc_ldap->high_uid = high_id; + } else { + DEBUG(1, ("ERROR: invalid idmap alloc range " + "[%s]", range)); + } + } else { + DEBUG(1, ("ERROR: invalid syntax for idmap alloc " + "config:range [%s]", range)); + } + } + + if (lp_idmap_uid(&low_uid, &high_uid)) { + idmap_alloc_ldap->low_uid = low_uid; + idmap_alloc_ldap->high_uid = high_uid; + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + idmap_alloc_ldap->low_gid = low_gid; + idmap_alloc_ldap->high_gid= high_gid; + } + + if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) { + DEBUG(1, ("idmap uid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) { + DEBUG(1, ("idmap gid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (params && *params) { + /* assume location is the only parameter */ + idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params); + } else { + tmp = lp_parm_const_string(-1, "idmap alloc config", + "ldap_url", NULL); + + if ( ! tmp) { + DEBUG(1, ("ERROR: missing idmap ldap url\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp); + } + CHECK_ALLOC_DONE( idmap_alloc_ldap->url ); + + tmp = lp_parm_const_string(-1, "idmap alloc config", + "ldap_base_dn", NULL); + if ( ! tmp || ! *tmp) { + tmp = lp_ldap_idmap_suffix(); + if ( ! tmp) { + DEBUG(1, ("ERROR: missing idmap ldap suffix\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } + + idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp); + CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix ); + + ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(), + idmap_alloc_ldap->url, + &idmap_alloc_ldap->smbldap_state); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", + idmap_alloc_ldap->url)); + goto done; + } + + ret = get_credentials( idmap_alloc_ldap, + idmap_alloc_ldap->smbldap_state, + "idmap alloc config", NULL, + &idmap_alloc_ldap->user_dn ); + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection " + "credentials (%s)\n", nt_errstr(ret))); + goto done; + } + + /* see if the idmap suffix and sub entries exists */ + + ret = verify_idpool(); + + done: + if ( !NT_STATUS_IS_OK( ret ) ) + TALLOC_FREE( idmap_alloc_ldap ); + + return ret; +} + +/******************************** + Allocate a new uid or gid +********************************/ + +static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid) +{ + TALLOC_CTX *ctx; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + int rc = LDAP_SERVER_DOWN; + int count = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + LDAPMod **mods = NULL; + char *id_str; + char *new_id_str; + char *filter = NULL; + const char *dn = NULL; + const char **attr_list; + const char *type; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + if ( ! idmap_alloc_ldap) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx = talloc_new(idmap_alloc_ldap); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* get type */ + switch (xid->type) { + + case ID_TYPE_UID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_UIDNUMBER); + break; + + case ID_TYPE_GID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_GIDNUMBER); + break; + + default: + DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); + return NT_STATUS_INVALID_PARAMETER; + } + + filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + CHECK_ALLOC_DONE(filter); + + attr_list = get_attr_list(ctx, idpool_attr_list); + CHECK_ALLOC_DONE(attr_list); + + DEBUG(10, ("Search of the id pool (filter: %s)\n", filter)); + + rc = smbldap_search(idmap_alloc_ldap->smbldap_state, + idmap_alloc_ldap->suffix, + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + talloc_autofree_ldapmsg(ctx, result); + + count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + if (count != 1) { + DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + + dn = smbldap_talloc_dn(ctx, + idmap_alloc_ldap->smbldap_state->ldap_struct, + entry); + if ( ! dn) { + goto done; + } + + if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct, + entry, type, ctx))) { + DEBUG(0,("%s attribute not found\n", type)); + goto done; + } + if ( ! id_str) { + DEBUG(0,("Out of memory\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + xid->id = strtoul(id_str, NULL, 10); + + /* make sure we still have room to grow */ + + switch (xid->type) { + case ID_TYPE_UID: + if (xid->id > idmap_alloc_ldap->high_uid) { + DEBUG(0,("Cannot allocate uid above %lu!\n", + (unsigned long)idmap_alloc_ldap->high_uid)); + goto done; + } + break; + + case ID_TYPE_GID: + if (xid->id > idmap_alloc_ldap->high_gid) { + DEBUG(0,("Cannot allocate gid above %lu!\n", + (unsigned long)idmap_alloc_ldap->high_uid)); + goto done; + } + break; + + default: + /* impossible */ + goto done; + } + + new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1); + if ( ! new_id_str) { + DEBUG(0,("Out of memory\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str); + smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str); + + if (mods == NULL) { + DEBUG(0,("smbldap_set_mod() failed.\n")); + goto done; + } + + DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", + id_str, new_id_str)); + + rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods); + + ldap_mods_free(mods, True); + + if (rc != LDAP_SUCCESS) { + DEBUG(1,("Failed to allocate new %s. " + "smbldap_modify() failed.\n", type)); + goto done; + } + + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; +} + +/********************************** + Get current highest id. +**********************************/ + +static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid) +{ + TALLOC_CTX *memctx; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + int rc = LDAP_SERVER_DOWN; + int count = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + char *id_str; + char *filter = NULL; + const char **attr_list; + const char *type; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + if ( ! idmap_alloc_ldap) { + return NT_STATUS_UNSUCCESSFUL; + } + + memctx = talloc_new(idmap_alloc_ldap); + if ( ! memctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* get type */ + switch (xid->type) { + + case ID_TYPE_UID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_UIDNUMBER); + break; + + case ID_TYPE_GID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_GIDNUMBER); + break; + + default: + DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); + return NT_STATUS_INVALID_PARAMETER; + } + + filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + CHECK_ALLOC_DONE(filter); + + attr_list = get_attr_list(memctx, idpool_attr_list); + CHECK_ALLOC_DONE(attr_list); + + rc = smbldap_search(idmap_alloc_ldap->smbldap_state, + idmap_alloc_ldap->suffix, + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + talloc_autofree_ldapmsg(memctx, result); + + count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + if (count != 1) { + DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + + id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct, + entry, type, memctx); + if ( ! id_str) { + DEBUG(0,("%s attribute not found\n", type)); + goto done; + } + if ( ! id_str) { + DEBUG(0,("Out of memory\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + xid->id = strtoul(id_str, NULL, 10); + + ret = NT_STATUS_OK; +done: + talloc_free(memctx); + return ret; +} +/********************************** + Set highest id. +**********************************/ + +static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid) +{ + TALLOC_CTX *ctx; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + int rc = LDAP_SERVER_DOWN; + int count = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + LDAPMod **mods = NULL; + char *new_id_str; + char *filter = NULL; + const char *dn = NULL; + const char **attr_list; + const char *type; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + if ( ! idmap_alloc_ldap) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx = talloc_new(idmap_alloc_ldap); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* get type */ + switch (xid->type) { + + case ID_TYPE_UID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_UIDNUMBER); + break; + + case ID_TYPE_GID: + type = get_attr_key2string(idpool_attr_list, + LDAP_ATTR_GIDNUMBER); + break; + + default: + DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); + return NT_STATUS_INVALID_PARAMETER; + } + + filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + CHECK_ALLOC_DONE(filter); + + attr_list = get_attr_list(ctx, idpool_attr_list); + CHECK_ALLOC_DONE(attr_list); + + rc = smbldap_search(idmap_alloc_ldap->smbldap_state, + idmap_alloc_ldap->suffix, + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + talloc_autofree_ldapmsg(ctx, result); + + count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + if (count != 1) { + DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL)); + goto done; + } + + entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, + result); + + dn = smbldap_talloc_dn(ctx, + idmap_alloc_ldap->smbldap_state->ldap_struct, + entry); + if ( ! dn) { + goto done; + } + + new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id); + if ( ! new_id_str) { + DEBUG(0,("Out of memory\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str); + + if (mods == NULL) { + DEBUG(0,("smbldap_set_mod() failed.\n")); + goto done; + } + + rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods); + + ldap_mods_free(mods, True); + + if (rc != LDAP_SUCCESS) { + DEBUG(1,("Failed to allocate new %s. " + "smbldap_modify() failed.\n", type)); + goto done; + } + + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; +} + +/********************************** + Close idmap ldap alloc +**********************************/ + +static NTSTATUS idmap_ldap_alloc_close(void) +{ + if (idmap_alloc_ldap) { + smbldap_free_struct(&idmap_alloc_ldap->smbldap_state); + DEBUG(5,("The connection to the LDAP server was closed\n")); + /* maybe free the results here --metze */ + TALLOC_FREE(idmap_alloc_ldap); + } + return NT_STATUS_OK; +} + + +/********************************************************************** + IDMAP MAPPING LDAP BACKEND +**********************************************************************/ + +static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx) +{ + smbldap_free_struct(&ctx->smbldap_state); + DEBUG(5,("The connection to the LDAP server was closed\n")); + /* maybe free the results here --metze */ + + return 0; +} + +/******************************** + Initialise idmap database. +********************************/ + +static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) +{ + NTSTATUS ret; + struct idmap_ldap_context *ctx = NULL; + char *config_option = NULL; + const char *range = NULL; + const char *tmp = NULL; + + /* Only do init if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + /* load ranges */ + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (range && range[0]) { + if ((sscanf(range, "%u - %u", &ctx->filter_low_id, + &ctx->filter_high_id) != 2) || + (ctx->filter_low_id > ctx->filter_high_id)) { + DEBUG(1, ("ERROR: invalid filter range [%s]", range)); + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + } + + if (dom->params && *(dom->params)) { + /* assume location is the only parameter */ + ctx->url = talloc_strdup(ctx, dom->params); + } else { + tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL); + + if ( ! tmp) { + DEBUG(1, ("ERROR: missing idmap ldap url\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ctx->url = talloc_strdup(ctx, tmp); + } + CHECK_ALLOC_DONE(ctx->url); + + tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL); + if ( ! tmp || ! *tmp) { + tmp = lp_ldap_idmap_suffix(); + if ( ! tmp) { + DEBUG(1, ("ERROR: missing idmap ldap suffix\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } + + ctx->suffix = talloc_strdup(ctx, tmp); + CHECK_ALLOC_DONE(ctx->suffix); + + ret = smbldap_init(ctx, winbind_event_context(), ctx->url, + &ctx->smbldap_state); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url)); + goto done; + } + + ret = get_credentials( ctx, ctx->smbldap_state, config_option, + dom, &ctx->user_dn ); + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(1,("idmap_ldap_db_init: Failed to get connection " + "credentials (%s)\n", nt_errstr(ret))); + goto done; + } + + /* set the destructor on the context, so that resource are properly + freed if the contexts is released */ + + talloc_set_destructor(ctx, idmap_ldap_close_destructor); + + dom->private_data = ctx; + dom->initialized = True; + + talloc_free(config_option); + return NT_STATUS_OK; + +/*failed */ +done: + talloc_free(ctx); + return ret; +} + +/* max number of ids requested per batch query */ +#define IDMAP_LDAP_MAX_IDS 30 + +/********************************** + lookup a set of unix ids. +**********************************/ + +/* this function searches up to IDMAP_LDAP_MAX_IDS entries + * in maps for a match */ +static struct id_map *find_map_by_id(struct id_map **maps, + enum id_type type, + uint32_t id) +{ + int i; + + for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) { + if (maps[i] == NULL) { /* end of the run */ + return NULL; + } + if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) { + return maps[i]; + } + } + + return NULL; +} + +static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, + struct id_map **ids) +{ + NTSTATUS ret; + TALLOC_CTX *memctx; + struct idmap_ldap_context *ctx; + LDAPMessage *result = NULL; + const char *uidNumber; + const char *gidNumber; + const char **attr_list; + char *filter = NULL; + BOOL multi = False; + int idx = 0; + int bidx = 0; + int count; + int rc; + int i; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* Initilization my have been deferred because we were offline */ + if ( ! dom->initialized) { + ret = idmap_ldap_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); + + memctx = talloc_new(ctx); + if ( ! memctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER); + gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER); + + attr_list = get_attr_list(memctx, sidmap_attr_list); + + if ( ! ids[1]) { + /* if we are requested just one mapping use the simple filter */ + + filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))", + LDAP_OBJ_IDMAP_ENTRY, + (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber, + (unsigned long)ids[0]->xid.id); + CHECK_ALLOC_DONE(filter); + DEBUG(10, ("Filter: [%s]\n", filter)); + } else { + /* multiple mappings */ + multi = True; + } + +again: + if (multi) { + + talloc_free(filter); + filter = talloc_asprintf(memctx, + "(&(objectClass=%s)(|", + LDAP_OBJ_IDMAP_ENTRY); + CHECK_ALLOC_DONE(filter); + + bidx = idx; + for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { + filter = talloc_asprintf_append(filter, "(%s=%lu)", + (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber, + (unsigned long)ids[idx]->xid.id); + CHECK_ALLOC_DONE(filter); + } + filter = talloc_asprintf_append(filter, "))"); + CHECK_ALLOC_DONE(filter); + DEBUG(10, ("Filter: [%s]\n", filter)); + } else { + bidx = 0; + idx = 1; + } + + rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc))); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result); + + if (count == 0) { + DEBUG(10, ("NO SIDs found\n")); + } + + for (i = 0; i < count; i++) { + LDAPMessage *entry = NULL; + char *sidstr = NULL; + char *tmp = NULL; + enum id_type type; + struct id_map *map; + uint32_t id; + + if (i == 0) { /* first entry */ + entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, + result); + } else { /* following ones */ + entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, + entry); + } + if ( ! entry) { + DEBUG(2, ("ERROR: Unable to fetch ldap entries " + "from results\n")); + break; + } + + /* first check if the SID is present */ + sidstr = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, LDAP_ATTRIBUTE_SID, memctx); + if ( ! sidstr) { /* no sid, skip entry */ + DEBUG(2, ("WARNING SID not found on entry\n")); + continue; + } + + /* now try to see if it is a uid, if not try with a gid + * (gid is more common, but in case both uidNumber and + * gidNumber are returned the SID is mapped to the uid + *not the gid) */ + type = ID_TYPE_UID; + tmp = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, uidNumber, memctx); + if ( ! tmp) { + type = ID_TYPE_GID; + tmp = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, gidNumber, memctx); + } + if ( ! tmp) { /* wow very strange entry, how did it match ? */ + DEBUG(5, ("Unprobable match on (%s), no uidNumber, " + "nor gidNumber returned\n", sidstr)); + TALLOC_FREE(sidstr); + continue; + } + + id = strtoul(tmp, NULL, 10); + if ((id == 0) || + (ctx->filter_low_id && (id < ctx->filter_low_id)) || + (ctx->filter_high_id && (id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). " + "Filtered!\n", id, + ctx->filter_low_id, ctx->filter_high_id)); + TALLOC_FREE(sidstr); + TALLOC_FREE(tmp); + continue; + } + TALLOC_FREE(tmp); + + map = find_map_by_id(&ids[bidx], type, id); + if (!map) { + DEBUG(2, ("WARNING: couldn't match sid (%s) " + "with requested ids\n", sidstr)); + TALLOC_FREE(sidstr); + continue; + } + + if ( ! string_to_sid(map->sid, sidstr)) { + DEBUG(2, ("ERROR: Invalid SID on entry\n")); + TALLOC_FREE(sidstr); + continue; + } + TALLOC_FREE(sidstr); + + /* mapped */ + map->status = ID_MAPPED; + + DEBUG(10, ("Mapped %s -> %lu (%d)\n", + sid_string_static(map->sid), + (unsigned long)map->xid.id, map->xid.type)); + } + + /* free the ldap results */ + if (result) { + ldap_msgfree(result); + result = NULL; + } + + if (multi && ids[idx]) { /* still some values to map */ + goto again; + } + + ret = NT_STATUS_OK; + + /* mark all unknwon/expired ones as unmapped */ + for (i = 0; ids[i]; i++) { + if (ids[i]->status != ID_MAPPED) + ids[i]->status = ID_UNMAPPED; + } + +done: + talloc_free(memctx); + return ret; +} + +/********************************** + lookup a set of sids. +**********************************/ + +/* this function searches up to IDMAP_LDAP_MAX_IDS entries + * in maps for a match */ +static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid) +{ + int i; + + for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) { + if (maps[i] == NULL) { /* end of the run */ + return NULL; + } + if (sid_equal(maps[i]->sid, sid)) { + return maps[i]; + } + } + + return NULL; +} + +static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, + struct id_map **ids) +{ + LDAPMessage *entry = NULL; + NTSTATUS ret; + TALLOC_CTX *memctx; + struct idmap_ldap_context *ctx; + LDAPMessage *result = NULL; + const char *uidNumber; + const char *gidNumber; + const char **attr_list; + char *filter = NULL; + BOOL multi = False; + int idx = 0; + int bidx = 0; + int count; + int rc; + int i; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* Initilization my have been deferred because we were offline */ + if ( ! dom->initialized) { + ret = idmap_ldap_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); + + memctx = talloc_new(ctx); + if ( ! memctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER); + gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER); + + attr_list = get_attr_list(memctx, sidmap_attr_list); + + if ( ! ids[1]) { + /* if we are requested just one mapping use the simple filter */ + + filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, + LDAP_ATTRIBUTE_SID, + sid_string_static(ids[0]->sid)); + CHECK_ALLOC_DONE(filter); + DEBUG(10, ("Filter: [%s]\n", filter)); + } else { + /* multiple mappings */ + multi = True; + } + +again: + if (multi) { + + TALLOC_FREE(filter); + filter = talloc_asprintf(memctx, + "(&(objectClass=%s)(|", + LDAP_OBJ_IDMAP_ENTRY); + CHECK_ALLOC_DONE(filter); + + bidx = idx; + for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { + filter = talloc_asprintf_append(filter, "(%s=%s)", + LDAP_ATTRIBUTE_SID, + sid_string_static(ids[idx]->sid)); + CHECK_ALLOC_DONE(filter); + } + filter = talloc_asprintf_append(filter, "))"); + CHECK_ALLOC_DONE(filter); + DEBUG(10, ("Filter: [%s]", filter)); + } else { + bidx = 0; + idx = 1; + } + + rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) { + DEBUG(3,("Failure looking up sids (%s)\n", + ldap_err2string(rc))); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result); + + if (count == 0) { + DEBUG(10, ("NO SIDs found\n")); + } + + for (i = 0; i < count; i++) { + char *sidstr = NULL; + char *tmp = NULL; + enum id_type type; + struct id_map *map; + DOM_SID sid; + uint32_t id; + + if (i == 0) { /* first entry */ + entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, + result); + } else { /* following ones */ + entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, + entry); + } + if ( ! entry) { + DEBUG(2, ("ERROR: Unable to fetch ldap entries " + "from results\n")); + break; + } + + /* first check if the SID is present */ + sidstr = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, LDAP_ATTRIBUTE_SID, memctx); + if ( ! sidstr) { /* no sid ??, skip entry */ + DEBUG(2, ("WARNING SID not found on entry\n")); + continue; + } + + if ( ! string_to_sid(&sid, sidstr)) { + DEBUG(2, ("ERROR: Invalid SID on entry\n")); + TALLOC_FREE(sidstr); + continue; + } + + map = find_map_by_sid(&ids[bidx], &sid); + if (!map) { + DEBUG(2, ("WARNING: couldn't find entry sid (%s) " + "in ids", sidstr)); + TALLOC_FREE(sidstr); + continue; + } + + TALLOC_FREE(sidstr); + + /* now try to see if it is a uid, if not try with a gid + * (gid is more common, but in case both uidNumber and + * gidNumber are returned the SID is mapped to the uid + * not the gid) */ + type = ID_TYPE_UID; + tmp = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, uidNumber, memctx); + if ( ! tmp) { + type = ID_TYPE_GID; + tmp = smbldap_talloc_single_attribute( + ctx->smbldap_state->ldap_struct, + entry, gidNumber, memctx); + } + if ( ! tmp) { /* no ids ?? */ + DEBUG(5, ("no uidNumber, " + "nor gidNumber attributes found\n")); + continue; + } + + id = strtoul(tmp, NULL, 10); + if ((id == 0) || + (ctx->filter_low_id && (id < ctx->filter_low_id)) || + (ctx->filter_high_id && (id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). " + "Filtered!\n", id, + ctx->filter_low_id, ctx->filter_high_id)); + TALLOC_FREE(tmp); + continue; + } + TALLOC_FREE(tmp); + + /* mapped */ + map->xid.type = type; + map->xid.id = id; + map->status = ID_MAPPED; + + DEBUG(10, ("Mapped %s -> %lu (%d)\n", + sid_string_static(map->sid), + (unsigned long)map->xid.id, map->xid.type)); + } + + /* free the ldap results */ + if (result) { + ldap_msgfree(result); + result = NULL; + } + + if (multi && ids[idx]) { /* still some values to map */ + goto again; + } + + ret = NT_STATUS_OK; + + /* mark all unknwon/expired ones as unmapped */ + for (i = 0; ids[i]; i++) { + if (ids[i]->status != ID_MAPPED) + ids[i]->status = ID_UNMAPPED; + } + +done: + talloc_free(memctx); + return ret; +} + +/********************************** + set a mapping. +**********************************/ + +/* TODO: change this: This function cannot be called to modify a mapping, + * only set a new one */ + +static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, + const struct id_map *map) +{ + NTSTATUS ret; + TALLOC_CTX *memctx; + struct idmap_ldap_context *ctx; + LDAPMessage *entry = NULL; + LDAPMod **mods = NULL; + const char *type; + char *id_str; + char *sid; + char *dn; + int rc = -1; + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + /* Initilization my have been deferred because we were offline */ + if ( ! dom->initialized) { + ret = idmap_ldap_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); + + switch(map->xid.type) { + case ID_TYPE_UID: + type = get_attr_key2string(sidmap_attr_list, + LDAP_ATTR_UIDNUMBER); + break; + + case ID_TYPE_GID: + type = get_attr_key2string(sidmap_attr_list, + LDAP_ATTR_GIDNUMBER); + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + memctx = talloc_new(ctx); + if ( ! memctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id); + CHECK_ALLOC_DONE(id_str); + + sid = talloc_strdup(memctx, sid_string_static(map->sid)); + CHECK_ALLOC_DONE(sid); + + dn = talloc_asprintf(memctx, "%s=%s,%s", + get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), + sid, + ctx->suffix); + CHECK_ALLOC_DONE(dn); + + smbldap_set_mod(&mods, LDAP_MOD_ADD, + "objectClass", LDAP_OBJ_IDMAP_ENTRY); + + smbldap_make_mod(ctx->smbldap_state->ldap_struct, + entry, &mods, type, id_str); + + smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), + sid); + + if ( ! mods) { + DEBUG(2, ("ERROR: No mods?\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* TODO: remove conflicting mappings! */ + + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY); + + DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str)); + + rc = smbldap_add(ctx->smbldap_state, dn, mods); + ldap_mods_free(mods, True); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ctx->smbldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu " + "mapping [%s]\n", sid, + (unsigned long)map->xid.id, type)); + DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", + ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); + if (ld_error) { + ldap_memfree(ld_error); + } + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to " + "%lu [%s]\n", sid, (unsigned long)map->xid.id, type)); + + ret = NT_STATUS_OK; + +done: + talloc_free(memctx); + return ret; +} + +/********************************** + Close the idmap ldap instance +**********************************/ + +static NTSTATUS idmap_ldap_close(struct idmap_domain *dom) +{ + struct idmap_ldap_context *ctx; + + if (dom->private_data) { + ctx = talloc_get_type(dom->private_data, + struct idmap_ldap_context); + + talloc_free(ctx); + dom->private_data = NULL; + } + + return NT_STATUS_OK; +} + +static struct idmap_methods idmap_ldap_methods = { + + .init = idmap_ldap_db_init, + .unixids_to_sids = idmap_ldap_unixids_to_sids, + .sids_to_unixids = idmap_ldap_sids_to_unixids, + .set_mapping = idmap_ldap_set_mapping, + .close_fn = idmap_ldap_close +}; + +static struct idmap_alloc_methods idmap_ldap_alloc_methods = { + + .init = idmap_ldap_alloc_init, + .allocate_id = idmap_ldap_allocate_id, + .get_id_hwm = idmap_ldap_get_hwm, + .set_id_hwm = idmap_ldap_set_hwm, + .close_fn = idmap_ldap_alloc_close, + /* .dump_data = TODO */ +}; + +NTSTATUS idmap_alloc_ldap_init(void) +{ + return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap", + &idmap_ldap_alloc_methods); +} + +NTSTATUS idmap_ldap_init(void) +{ + NTSTATUS ret; + + /* FIXME: bad hack to actually register also the alloc_ldap module + * without changining configure.in */ + ret = idmap_alloc_ldap_init(); + if (! NT_STATUS_IS_OK(ret)) { + return ret; + } + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", + &idmap_ldap_methods); +} + diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c new file mode 100644 index 0000000000..5bb2389c93 --- /dev/null +++ b/source3/winbindd/idmap_nss.c @@ -0,0 +1,223 @@ +/* + Unix SMB/CIFS implementation. + + idmap PASSDB backend + + Copyright (C) Simo Sorce 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/***************************** + Initialise idmap database. +*****************************/ + +static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom) +{ + dom->initialized = True; + return NT_STATUS_OK; +} + +/********************************** + lookup a set of unix ids. +**********************************/ + +static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + TALLOC_CTX *ctx; + int i; + + if (! dom->initialized) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx = talloc_new(dom); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; ids[i]; i++) { + struct passwd *pw; + struct group *gr; + const char *name; + enum lsa_SidType type; + BOOL ret; + + switch (ids[i]->xid.type) { + case ID_TYPE_UID: + pw = getpwuid((uid_t)ids[i]->xid.id); + + if (!pw) { + ids[i]->status = ID_UNMAPPED; + continue; + } + name = pw->pw_name; + break; + case ID_TYPE_GID: + gr = getgrgid((gid_t)ids[i]->xid.id); + + if (!gr) { + ids[i]->status = ID_UNMAPPED; + continue; + } + name = gr->gr_name; + break; + default: /* ?? */ + ids[i]->status = ID_UNKNOWN; + continue; + } + + /* by default calls to winbindd are disabled + the following call will not recurse so this is safe */ + winbind_on(); + /* Lookup name from PDC using lsa_lookup_names() */ + ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type); + winbind_off(); + + if (!ret) { + /* TODO: how do we know if the name is really not mapped, + * or something just failed ? */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + switch (type) { + case SID_NAME_USER: + if (ids[i]->xid.type == ID_TYPE_UID) { + ids[i]->status = ID_MAPPED; + } + break; + + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + if (ids[i]->xid.type == ID_TYPE_GID) { + ids[i]->status = ID_MAPPED; + } + break; + + default: + ids[i]->status = ID_UNKNOWN; + break; + } + } + + + talloc_free(ctx); + return NT_STATUS_OK; +} + +/********************************** + lookup a set of sids. +**********************************/ + +static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + TALLOC_CTX *ctx; + int i; + + if (! dom->initialized) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx = talloc_new(dom); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; ids[i]; i++) { + struct passwd *pw; + struct group *gr; + enum lsa_SidType type; + const char *dom_name = NULL; + const char *name = NULL; + BOOL ret; + + /* by default calls to winbindd are disabled + the following call will not recurse so this is safe */ + winbind_on(); + ret = winbind_lookup_sid(ctx, ids[i]->sid, &dom_name, &name, &type); + winbind_off(); + + if (!ret) { + /* TODO: how do we know if the name is really not mapped, + * or something just failed ? */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + switch (type) { + case SID_NAME_USER: + + /* this will find also all lower case name and use username level */ + + pw = Get_Pwnam(name); + if (pw) { + ids[i]->xid.id = pw->pw_uid; + ids[i]->xid.type = ID_TYPE_UID; + ids[i]->status = ID_MAPPED; + } + break; + + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + + gr = getgrnam(name); + if (gr) { + ids[i]->xid.id = gr->gr_gid; + ids[i]->xid.type = ID_TYPE_GID; + ids[i]->status = ID_MAPPED; + } + break; + + default: + ids[i]->status = ID_UNKNOWN; + break; + } + } + + talloc_free(ctx); + return NT_STATUS_OK; +} + +/********************************** + Close the idmap tdb instance +**********************************/ + +static NTSTATUS idmap_nss_close(struct idmap_domain *dom) +{ + return NT_STATUS_OK; +} + +static struct idmap_methods nss_methods = { + + .init = idmap_nss_int_init, + .unixids_to_sids = idmap_nss_unixids_to_sids, + .sids_to_unixids = idmap_nss_sids_to_unixids, + .close_fn = idmap_nss_close +}; + +NTSTATUS idmap_nss_init(void) +{ + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "nss", &nss_methods); +} diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c new file mode 100644 index 0000000000..17afd71ab8 --- /dev/null +++ b/source3/winbindd/idmap_passdb.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + + idmap PASSDB backend + + Copyright (C) Simo Sorce 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/***************************** + Initialise idmap database. +*****************************/ + +static NTSTATUS idmap_pdb_init(struct idmap_domain *dom) +{ + dom->initialized = True; + return NT_STATUS_OK; +} + +/********************************** + lookup a set of unix ids. +**********************************/ + +static NTSTATUS idmap_pdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + int i; + + if (! dom->initialized) { + return NT_STATUS_UNSUCCESSFUL; + } + + for (i = 0; ids[i]; i++) { + + /* unmapped by default */ + ids[i]->status = ID_UNMAPPED; + + switch (ids[i]->xid.type) { + case ID_TYPE_UID: + if (pdb_uid_to_sid((uid_t)ids[i]->xid.id, ids[i]->sid)) { + ids[i]->status = ID_MAPPED; + } + break; + case ID_TYPE_GID: + if (pdb_gid_to_sid((gid_t)ids[i]->xid.id, ids[i]->sid)) { + ids[i]->status = ID_MAPPED; + } + break; + default: /* ?? */ + ids[i]->status = ID_UNKNOWN; + } + } + + return NT_STATUS_OK; +} + +/********************************** + lookup a set of sids. +**********************************/ + +static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + int i; + + if (! dom->initialized) { + return NT_STATUS_UNSUCCESSFUL; + } + + for (i = 0; ids[i]; i++) { + enum lsa_SidType type; + union unid_t id; + + if (pdb_sid_to_id(ids[i]->sid, &id, &type)) { + switch (type) { + case SID_NAME_USER: + ids[i]->xid.id = id.uid; + ids[i]->xid.type = ID_TYPE_UID; + ids[i]->status = ID_MAPPED; + break; + + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + ids[i]->xid.id = id.gid; + ids[i]->xid.type = ID_TYPE_GID; + ids[i]->status = ID_MAPPED; + break; + + default: /* ?? */ + /* make sure it is marked as unmapped */ + ids[i]->status = ID_UNKNOWN; + break; + } + } else { + /* Query Failed */ + ids[i]->status = ID_UNMAPPED; + } + } + + return NT_STATUS_OK; +} + +/********************************** + Close the idmap tdb instance +**********************************/ + +static NTSTATUS idmap_pdb_close(struct idmap_domain *dom) +{ + return NT_STATUS_OK; +} + +static struct idmap_methods passdb_methods = { + + .init = idmap_pdb_init, + .unixids_to_sids = idmap_pdb_unixids_to_sids, + .sids_to_unixids = idmap_pdb_sids_to_unixids, + .close_fn =idmap_pdb_close +}; + +NTSTATUS idmap_passdb_init(void) +{ + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "passdb", &passdb_methods); +} diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c new file mode 100644 index 0000000000..8e5f1302f7 --- /dev/null +++ b/source3/winbindd/idmap_rid.c @@ -0,0 +1,267 @@ +/* + * idmap_rid: static map between Active Directory/NT RIDs and RFC 2307 accounts + * Copyright (C) Guenther Deschner, 2004 + * Copyright (C) Sumit Bose, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +struct idmap_rid_context { + const char *domain_name; + uint32_t low_id; + uint32_t high_id; + uint32_t base_rid; +}; + +/****************************************************************************** + compat params can't be used because of the completely different way + we support multiple domains in the new idmap + *****************************************************************************/ + +static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom) +{ + NTSTATUS ret; + struct idmap_rid_context *ctx; + char *config_option = NULL; + const char *range; + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + + if ( (ctx = TALLOC_ZERO_P(dom, struct idmap_rid_context)) == NULL ) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto failed; + } + + range = lp_parm_const_string(-1, config_option, "range", NULL); + if ( !range || + (sscanf(range, "%u - %u", &ctx->low_id, &ctx->high_id) != 2) || + (ctx->low_id > ctx->high_id)) + { + ctx->low_id = 0; + ctx->high_id = 0; + } + + /* lets see if the range is defined by the old idmap uid/idmap gid */ + if (!ctx->low_id && !ctx->high_id) { + if (lp_idmap_uid(&low_uid, &high_uid)) { + ctx->low_id = low_uid; + ctx->high_id = high_uid; + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + if ((ctx->low_id != low_gid) || + (ctx->high_id != high_uid)) { + DEBUG(1, ("ERROR: idmap uid range must match idmap gid range\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto failed; + } + } + } + + if (!ctx->low_id || !ctx->high_id) { + DEBUG(1, ("ERROR: Invalid configuration, ID range missing or invalid\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto failed; + } + + ctx->base_rid = lp_parm_int(-1, config_option, "base_rid", 0); + ctx->domain_name = talloc_strdup( ctx, dom->name ); + + dom->private_data = ctx; + dom->initialized = True; + + talloc_free(config_option); + return NT_STATUS_OK; + +failed: + talloc_free(ctx); + return ret; +} + +static NTSTATUS idmap_rid_id_to_sid(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map) +{ + struct winbindd_domain *domain; + + /* apply filters before checking */ + if ((map->xid.id < ctx->low_id) || (map->xid.id > ctx->high_id)) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->low_id, ctx->high_id)); + return NT_STATUS_NONE_MAPPED; + } + + if ( (domain = find_domain_from_name_noinit(ctx->domain_name)) == NULL ) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + + sid_compose(map->sid, &domain->sid, map->xid.id - ctx->low_id + ctx->base_rid); + + /* We **really** should have some way of validating + the SID exists and is the correct type here. But + that is a deficiency in the idmap_rid design. */ + + map->status = ID_MAPPED; + + return NT_STATUS_OK; +} + +/********************************** + Single sid to id lookup function. +**********************************/ + +static NTSTATUS idmap_rid_sid_to_id(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map) +{ + uint32_t rid; + + sid_peek_rid(map->sid, &rid); + map->xid.id = rid - ctx->base_rid + ctx->low_id; + + /* apply filters before returning result */ + + if ((map->xid.id < ctx->low_id) || (map->xid.id > ctx->high_id)) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->low_id, ctx->high_id)); + map->status = ID_UNMAPPED; + return NT_STATUS_NONE_MAPPED; + } + + /* We **really** should have some way of validating + the SID exists and is the correct type here. But + that is a deficiency in the idmap_rid design. */ + + map->status = ID_MAPPED; + + return NT_STATUS_OK; +} + +/********************************** + lookup a set of unix ids. +**********************************/ + +static NTSTATUS idmap_rid_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_rid_context *ridctx; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i; + + /* Initilization my have been deferred because of an error, retry or fail */ + if ( ! dom->initialized) { + ret = idmap_rid_initialize(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context); + + ctx = talloc_new(dom); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; ids[i]; i++) { + + ret = idmap_rid_id_to_sid(ctx, ridctx, ids[i]); + + if (( ! NT_STATUS_IS_OK(ret)) && + ( ! NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) { + /* some fatal error occurred, log it */ + DEBUG(3, ("Unexpected error resolving an ID (%d)\n", ids[i]->xid.id)); + } + } + + talloc_free(ctx); + return NT_STATUS_OK; +} + +/********************************** + lookup a set of sids. +**********************************/ + +static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_rid_context *ridctx; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i; + + /* Initilization my have been deferred because of an error, retry or fail */ + if ( ! dom->initialized) { + ret = idmap_rid_initialize(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context); + + ctx = talloc_new(dom); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; ids[i]; i++) { + + ret = idmap_rid_sid_to_id(ctx, ridctx, ids[i]); + + if (( ! NT_STATUS_IS_OK(ret)) && + ( ! NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) { + /* some fatal error occurred, log it */ + DEBUG(3, ("Unexpected error resolving a SID (%s)\n", + sid_string_static(ids[i]->sid))); + } + } + + talloc_free(ctx); + return NT_STATUS_OK; +} + +static NTSTATUS idmap_rid_close(struct idmap_domain *dom) +{ + if (dom->private_data) { + TALLOC_FREE(dom->private_data); + } + return NT_STATUS_OK; +} + +static struct idmap_methods rid_methods = { + .init = idmap_rid_initialize, + .unixids_to_sids = idmap_rid_unixids_to_sids, + .sids_to_unixids = idmap_rid_sids_to_unixids, + .close_fn = idmap_rid_close +}; + +NTSTATUS idmap_rid_init(void) +{ + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rid", &rid_methods); +} + diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c new file mode 100644 index 0000000000..97000689fa --- /dev/null +++ b/source3/winbindd/idmap_tdb.c @@ -0,0 +1,1232 @@ +/* + Unix SMB/CIFS implementation. + + idmap TDB backend + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Jeremy Allison 2006 + Copyright (C) Simo Sorce 2003-2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/* High water mark keys */ +#define HWM_GROUP "GROUP HWM" +#define HWM_USER "USER HWM" + +static struct idmap_tdb_state { + + /* User and group id pool */ + uid_t low_uid, high_uid; /* Range of uids to allocate */ + gid_t low_gid, high_gid; /* Range of gids to allocate */ + +} idmap_tdb_state; + +/***************************************************************************** + For idmap conversion: convert one record to new format + Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid + instead of the SID. +*****************************************************************************/ +static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state) +{ + struct winbindd_domain *domain; + char *p; + DOM_SID sid; + uint32 rid; + fstring keystr; + fstring dom_name; + TDB_DATA key2; + BOOL *failed = (BOOL *)state; + + DEBUG(10,("Converting %s\n", (const char *)key.dptr)); + + p = strchr((const char *)key.dptr, '/'); + if (!p) + return 0; + + *p = 0; + fstrcpy(dom_name, (const char *)key.dptr); + *p++ = '/'; + + domain = find_domain_from_name(dom_name); + if (domain == NULL) { + /* We must delete the old record. */ + DEBUG(0,("Unable to find domain %s\n", dom_name )); + DEBUG(0,("deleting record %s\n", (const char *)key.dptr )); + + if (tdb_delete(tdb, key) != 0) { + DEBUG(0, ("Unable to delete record %s\n", (const char *)key.dptr)); + *failed = True; + return -1; + } + + return 0; + } + + rid = atoi(p); + + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, rid); + + sid_to_string(keystr, &sid); + key2 = string_term_tdb_data(keystr); + + if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) { + DEBUG(0,("Unable to add record %s\n", (const char *)key2.dptr )); + *failed = True; + return -1; + } + + if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) { + DEBUG(0,("Unable to update record %s\n", (const char *)data.dptr )); + *failed = True; + return -1; + } + + if (tdb_delete(tdb, key) != 0) { + DEBUG(0,("Unable to delete record %s\n", (const char *)key.dptr )); + *failed = True; + return -1; + } + + return 0; +} + +/***************************************************************************** + Convert the idmap database from an older version. +*****************************************************************************/ + +static BOOL idmap_tdb_upgrade(const char *idmap_name) +{ + int32 vers; + BOOL bigendianheader; + BOOL failed = False; + TDB_CONTEXT *idmap_tdb; + + DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); + + if (!(idmap_tdb = tdb_open_log(idmap_name, 0, + TDB_DEFAULT, O_RDWR, + 0600))) { + DEBUG(0, ("Unable to open idmap database\n")); + return False; + } + + bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False; + + vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); + + if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) { + /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ + /* + * high and low records were created on a + * big endian machine and will need byte-reversing. + */ + + int32 wm; + + wm = tdb_fetch_int32(idmap_tdb, HWM_USER); + + if (wm != -1) { + wm = IREV(wm); + } else { + wm = idmap_tdb_state.low_uid; + } + + if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { + DEBUG(0, ("Unable to byteswap user hwm in idmap database\n")); + tdb_close(idmap_tdb); + return False; + } + + wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); + if (wm != -1) { + wm = IREV(wm); + } else { + wm = idmap_tdb_state.low_gid; + } + + if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { + DEBUG(0, ("Unable to byteswap group hwm in idmap database\n")); + tdb_close(idmap_tdb); + return False; + } + } + + /* the old format stored as DOMAIN/rid - now we store the SID direct */ + tdb_traverse(idmap_tdb, convert_fn, &failed); + + if (failed) { + DEBUG(0, ("Problem during conversion\n")); + tdb_close(idmap_tdb); + return False; + } + + if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) { + DEBUG(0, ("Unable to dtore idmap version in databse\n")); + tdb_close(idmap_tdb); + return False; + } + + tdb_close(idmap_tdb); + return True; +} + +/* WARNING: We can't open a tdb twice inthe same process, for that reason + * I'm going to use a hack with open ref counts to open the winbindd_idmap.tdb + * only once. We will later decide whether to split the db in multiple files + * or come up with a better solution to share them. */ + +static TDB_CONTEXT *idmap_tdb_common_ctx; +static int idmap_tdb_open_ref_count = 0; + +static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx) +{ + NTSTATUS ret; + TALLOC_CTX *ctx; + SMB_STRUCT_STAT stbuf; + char *tdbfile = NULL; + int32 version; + BOOL tdb_is_new = False; + + if (idmap_tdb_open_ref_count) { /* the tdb has already been opened */ + idmap_tdb_open_ref_count++; + *tdbctx = idmap_tdb_common_ctx; + return NT_STATUS_OK; + } + + /* use our own context here */ + ctx = talloc_new(memctx); + if (!ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* use the old database if present */ + tdbfile = talloc_strdup(ctx, lock_path("winbindd_idmap.tdb")); + if (!tdbfile) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + if (!file_exist(tdbfile, &stbuf)) { + tdb_is_new = True; + } + + DEBUG(10,("Opening tdbfile %s\n", tdbfile )); + + /* Open idmap repository */ + if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) { + DEBUG(0, ("Unable to open idmap database\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (tdb_is_new) { + /* the file didn't existed before opening it, let's + * store idmap version as nobody else yet opened and + * stored it. I do not like this method but didn't + * found a way to understand if an opened tdb have + * been just created or not --- SSS */ + tdb_store_int32(idmap_tdb_common_ctx, "IDMAP_VERSION", IDMAP_VERSION); + } + + /* check against earlier versions */ + version = tdb_fetch_int32(idmap_tdb_common_ctx, "IDMAP_VERSION"); + if (version != IDMAP_VERSION) { + + /* backup_tdb expects the tdb not to be open */ + tdb_close(idmap_tdb_common_ctx); + + if ( ! idmap_tdb_upgrade(tdbfile)) { + + DEBUG(0, ("Unable to open idmap database, it's in an old formati, and upgrade failed!\n")); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + /* Re-Open idmap repository */ + if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) { + DEBUG(0, ("Unable to open idmap database\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } + + *tdbctx = idmap_tdb_common_ctx; + idmap_tdb_open_ref_count++; + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; +} + + /* NEVER use tdb_close() except for the conversion routines that are guaranteed + * to run only when the database is opened the first time, always use this function. */ + +BOOL idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx) +{ + if (tdbctx != idmap_tdb_common_ctx) { + DEBUG(0, ("ERROR: Invalid tdb context!")); + return False; + } + + idmap_tdb_open_ref_count--; + if (idmap_tdb_open_ref_count) { + return True; + } + + return tdb_close(idmap_tdb_common_ctx); +} + +/********************************************************************** + IDMAP ALLOC TDB BACKEND +**********************************************************************/ + +static TDB_CONTEXT *idmap_alloc_tdb; + +/********************************** + Initialise idmap alloc database. +**********************************/ + +static NTSTATUS idmap_tdb_alloc_init( const char *params ) +{ + NTSTATUS ret; + TALLOC_CTX *ctx; + const char *range; + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + + /* use our own context here */ + ctx = talloc_new(NULL); + if (!ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + ret = idmap_tdb_open_db(ctx, &idmap_alloc_tdb); + if ( ! NT_STATUS_IS_OK(ret)) { + talloc_free(ctx); + return ret; + } + + talloc_free(ctx); + + /* load ranges */ + idmap_tdb_state.low_uid = 0; + idmap_tdb_state.high_uid = 0; + idmap_tdb_state.low_gid = 0; + idmap_tdb_state.high_gid = 0; + + range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); + if (range && range[0]) { + unsigned low_id, high_id; + + if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { + if (low_id < high_id) { + idmap_tdb_state.low_gid = idmap_tdb_state.low_uid = low_id; + idmap_tdb_state.high_gid = idmap_tdb_state.high_uid = high_id; + } else { + DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range)); + } + } else { + DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range)); + } + } + + /* Create high water marks for group and user id */ + if (lp_idmap_uid(&low_uid, &high_uid)) { + idmap_tdb_state.low_uid = low_uid; + idmap_tdb_state.high_uid = high_uid; + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + idmap_tdb_state.low_gid = low_gid; + idmap_tdb_state.high_gid = high_gid; + } + + if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) { + DEBUG(1, ("idmap uid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + return NT_STATUS_UNSUCCESSFUL; + } else { + uint32 low_id; + + if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) || + (low_id < idmap_tdb_state.low_uid)) { + if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, idmap_tdb_state.low_uid) == -1) { + DEBUG(0, ("Unable to initialise user hwm in idmap database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + } + } + + if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) { + DEBUG(1, ("idmap gid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + return NT_STATUS_UNSUCCESSFUL; + } else { + uint32 low_id; + + if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) || + (low_id < idmap_tdb_state.low_gid)) { + if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, idmap_tdb_state.low_gid) == -1) { + DEBUG(0, ("Unable to initialise group hwm in idmap database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + } + } + + return NT_STATUS_OK; +} + +/********************************** + Allocate a new id. +**********************************/ + +static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid) +{ + BOOL ret; + const char *hwmkey; + const char *hwmtype; + uint32_t high_hwm; + uint32_t hwm; + + /* Get current high water mark */ + switch (xid->type) { + + case ID_TYPE_UID: + hwmkey = HWM_USER; + hwmtype = "UID"; + high_hwm = idmap_tdb_state.high_uid; + break; + + case ID_TYPE_GID: + hwmkey = HWM_GROUP; + hwmtype = "GID"; + high_hwm = idmap_tdb_state.high_gid; + break; + + default: + DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); + return NT_STATUS_INVALID_PARAMETER; + } + + if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* check it is in the range */ + if (hwm > high_hwm) { + DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* fetch a new id and increment it */ + ret = tdb_change_uint32_atomic(idmap_alloc_tdb, hwmkey, &hwm, 1); + if (!ret) { + DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > high_hwm) { + DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + return NT_STATUS_UNSUCCESSFUL; + } + + xid->id = hwm; + DEBUG(10,("New %s = %d\n", hwmtype, hwm)); + + return NT_STATUS_OK; +} + +/********************************** + Get current highest id. +**********************************/ + +static NTSTATUS idmap_tdb_get_hwm(struct unixid *xid) +{ + const char *hwmkey; + const char *hwmtype; + uint32_t hwm; + uint32_t high_hwm; + + /* Get current high water mark */ + switch (xid->type) { + + case ID_TYPE_UID: + hwmkey = HWM_USER; + hwmtype = "UID"; + high_hwm = idmap_tdb_state.high_uid; + break; + + case ID_TYPE_GID: + hwmkey = HWM_GROUP; + hwmtype = "GID"; + high_hwm = idmap_tdb_state.high_gid; + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + xid->id = hwm; + + /* Warn if it is out of range */ + if (hwm >= high_hwm) { + DEBUG(0, ("Warning: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + } + + return NT_STATUS_OK; +} + +/********************************** + Set high id. +**********************************/ + +static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid) +{ + const char *hwmkey; + const char *hwmtype; + uint32_t hwm; + uint32_t high_hwm; + + /* Get current high water mark */ + switch (xid->type) { + + case ID_TYPE_UID: + hwmkey = HWM_USER; + hwmtype = "UID"; + high_hwm = idmap_tdb_state.high_uid; + break; + + case ID_TYPE_GID: + hwmkey = HWM_GROUP; + hwmtype = "GID"; + high_hwm = idmap_tdb_state.high_gid; + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + hwm = xid->id; + + if ((hwm = tdb_store_int32(idmap_alloc_tdb, hwmkey, hwm)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* Warn if it is out of range */ + if (hwm >= high_hwm) { + DEBUG(0, ("Warning: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + } + + return NT_STATUS_OK; +} + +/********************************** + Close the alloc tdb +**********************************/ + +static NTSTATUS idmap_tdb_alloc_close(void) +{ + if (idmap_alloc_tdb) { + if (idmap_tdb_tdb_close(idmap_alloc_tdb) == 0) { + return NT_STATUS_OK; + } else { + return NT_STATUS_UNSUCCESSFUL; + } + } + return NT_STATUS_OK; +} + +/********************************************************************** + IDMAP MAPPING TDB BACKEND +**********************************************************************/ + +struct idmap_tdb_context { + TDB_CONTEXT *tdb; + uint32_t filter_low_id; + uint32_t filter_high_id; +}; + +/***************************** + Initialise idmap database. +*****************************/ + +static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom) +{ + NTSTATUS ret; + struct idmap_tdb_context *ctx; + char *config_option = NULL; + const char *range; + + ctx = talloc(dom, struct idmap_tdb_context); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto failed; + } + + ret = idmap_tdb_open_db(ctx, &ctx->tdb); + if ( ! NT_STATUS_IS_OK(ret)) { + goto failed; + } + + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (( ! range) || + (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) || + (ctx->filter_low_id > ctx->filter_high_id)) { + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + + dom->private_data = ctx; + dom->initialized = True; + + talloc_free(config_option); + return NT_STATUS_OK; + +failed: + talloc_free(ctx); + return ret; +} + +/********************************** + Single id to sid lookup function. +**********************************/ + +static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map *map) +{ + NTSTATUS ret; + TDB_DATA data; + char *keystr; + + if (!ctx || !map) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* apply filters before checking */ + if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || + (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->filter_low_id, ctx->filter_high_id)); + return NT_STATUS_NONE_MAPPED; + } + + switch (map->xid.type) { + + case ID_TYPE_UID: + keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); + break; + + case ID_TYPE_GID: + keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); + break; + + default: + DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); + return NT_STATUS_INVALID_PARAMETER; + } + + /* final SAFE_FREE safe */ + data.dptr = NULL; + + if (keystr == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10,("Fetching record %s\n", keystr)); + + /* Check if the mapping exists */ + data = tdb_fetch_bystring(ctx->tdb, keystr); + + if (!data.dptr) { + DEBUG(10,("Record %s not found\n", keystr)); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + if (!string_to_sid(map->sid, (const char *)data.dptr)) { + DEBUG(10,("INVALID SID (%s) in record %s\n", + (const char *)data.dptr, keystr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + DEBUG(10,("Found record %s -> %s\n", keystr, (const char *)data.dptr)); + ret = NT_STATUS_OK; + +done: + SAFE_FREE(data.dptr); + talloc_free(keystr); + return ret; +} + +/********************************** + Single sid to id lookup function. +**********************************/ + +static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map *map) +{ + NTSTATUS ret; + TDB_DATA data; + char *keystr; + unsigned long rec_id = 0; + + if ((keystr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10,("Fetching record %s\n", keystr)); + + /* Check if sid is present in database */ + data = tdb_fetch_bystring(ctx->tdb, keystr); + if (!data.dptr) { + DEBUG(10,("Record %s not found\n", keystr)); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* What type of record is this ? */ + if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */ + map->xid.id = rec_id; + map->xid.type = ID_TYPE_UID; + DEBUG(10,("Found uid record %s -> %s \n", keystr, (const char *)data.dptr )); + ret = NT_STATUS_OK; + + } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */ + map->xid.id = rec_id; + map->xid.type = ID_TYPE_GID; + DEBUG(10,("Found gid record %s -> %s \n", keystr, (const char *)data.dptr )); + ret = NT_STATUS_OK; + + } else { /* Unknown record type ! */ + DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + } + + SAFE_FREE(data.dptr); + + /* apply filters before returning result */ + if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || + (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->filter_low_id, ctx->filter_high_id)); + ret = NT_STATUS_NONE_MAPPED; + } + +done: + talloc_free(keystr); + return ret; +} + +/********************************** + lookup a set of unix ids. +**********************************/ + +static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_tdb_context *ctx; + NTSTATUS ret; + int i; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + for (i = 0; ids[i]; i++) { + ret = idmap_tdb_id_to_sid(ctx, ids[i]); + if ( ! NT_STATUS_IS_OK(ret)) { + + /* if it is just a failed mapping continue */ + if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { + + /* make sure it is marked as unmapped */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + /* some fatal error occurred, return immediately */ + goto done; + } + + /* all ok, id is mapped */ + ids[i]->status = ID_MAPPED; + } + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/********************************** + lookup a set of sids. +**********************************/ + +static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_tdb_context *ctx; + NTSTATUS ret; + int i; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + for (i = 0; ids[i]; i++) { + ret = idmap_tdb_sid_to_id(ctx, ids[i]); + if ( ! NT_STATUS_IS_OK(ret)) { + + /* if it is just a failed mapping continue */ + if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { + + /* make sure it is marked as unmapped */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + /* some fatal error occurred, return immediately */ + goto done; + } + + /* all ok, id is mapped */ + ids[i]->status = ID_MAPPED; + } + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/********************************** + set a mapping. +**********************************/ + +static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_map *map) +{ + struct idmap_tdb_context *ctx; + NTSTATUS ret; + TDB_DATA ksid, kid, data; + char *ksidstr, *kidstr; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + if (!map || !map->sid) { + return NT_STATUS_INVALID_PARAMETER; + } + + ksidstr = kidstr = NULL; + data.dptr = NULL; + + /* TODO: should we filter a set_mapping using low/high filters ? */ + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + switch (map->xid.type) { + + case ID_TYPE_UID: + kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); + break; + + case ID_TYPE_GID: + kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); + break; + + default: + DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (kidstr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + if ((ksidstr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr)); + kid = string_term_tdb_data(kidstr); + ksid = string_term_tdb_data(ksidstr); + + /* *DELETE* previous mappings if any. + * This is done both SID and [U|G]ID passed in */ + + /* Lock the record for this SID. */ + if (tdb_chainlock(ctx->tdb, ksid) != 0) { + DEBUG(10,("Failed to lock record %s. Error %s\n", + ksidstr, tdb_errorstr(ctx->tdb) )); + return NT_STATUS_UNSUCCESSFUL; + } + + data = tdb_fetch(ctx->tdb, ksid); + if (data.dptr) { + DEBUG(10, ("Deleting existing mapping %s <-> %s\n", (const char *)data.dptr, ksidstr )); + tdb_delete(ctx->tdb, data); + tdb_delete(ctx->tdb, ksid); + SAFE_FREE(data.dptr); + } + + data = tdb_fetch(ctx->tdb, kid); + if (data.dptr) { + DEBUG(10,("Deleting existing mapping %s <-> %s\n", (const char *)data.dptr, kidstr )); + tdb_delete(ctx->tdb, data); + tdb_delete(ctx->tdb, kid); + SAFE_FREE(data.dptr); + } + + if (tdb_store(ctx->tdb, ksid, kid, TDB_INSERT) == -1) { + DEBUG(0, ("Error storing SID -> ID: %s\n", tdb_errorstr(ctx->tdb))); + tdb_chainunlock(ctx->tdb, ksid); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + if (tdb_store(ctx->tdb, kid, ksid, TDB_INSERT) == -1) { + DEBUG(0, ("Error stroing ID -> SID: %s\n", tdb_errorstr(ctx->tdb))); + /* try to remove the previous stored SID -> ID map */ + tdb_delete(ctx->tdb, ksid); + tdb_chainunlock(ctx->tdb, ksid); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + tdb_chainunlock(ctx->tdb, ksid); + DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr)); + ret = NT_STATUS_OK; + +done: + talloc_free(ksidstr); + talloc_free(kidstr); + SAFE_FREE(data.dptr); + return ret; +} + +/********************************** + remove a mapping. +**********************************/ + +static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct id_map *map) +{ + struct idmap_tdb_context *ctx; + NTSTATUS ret; + TDB_DATA ksid, kid, data; + char *ksidstr, *kidstr; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + if (!map || !map->sid) { + return NT_STATUS_INVALID_PARAMETER; + } + + ksidstr = kidstr = NULL; + data.dptr = NULL; + + /* TODO: should we filter a remove_mapping using low/high filters ? */ + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + switch (map->xid.type) { + + case ID_TYPE_UID: + kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); + break; + + case ID_TYPE_GID: + kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); + break; + + default: + DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (kidstr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + if ((ksidstr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10, ("Checking %s <-> %s map\n", ksidstr, kidstr)); + ksid = string_term_tdb_data(ksidstr); + kid = string_term_tdb_data(kidstr); + + /* Lock the record for this SID. */ + if (tdb_chainlock(ctx->tdb, ksid) != 0) { + DEBUG(10,("Failed to lock record %s. Error %s\n", + ksidstr, tdb_errorstr(ctx->tdb) )); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if sid is present in database */ + data = tdb_fetch(ctx->tdb, ksid); + if (!data.dptr) { + DEBUG(10,("Record %s not found\n", ksidstr)); + tdb_chainunlock(ctx->tdb, ksid); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + /* Check if sid is mapped to the specified ID */ + if ((data.dsize != kid.dsize) || + (memcmp(data.dptr, kid.dptr, data.dsize) != 0)) { + DEBUG(10,("Specified SID does not map to specified ID\n")); + DEBUGADD(10,("Actual mapping is %s -> %s\n", ksidstr, (const char *)data.dptr)); + tdb_chainunlock(ctx->tdb, ksid); + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + DEBUG(10, ("Removing %s <-> %s map\n", ksidstr, kidstr)); + + /* Delete previous mappings. */ + + DEBUG(10, ("Deleting existing mapping %s -> %s\n", ksidstr, kidstr )); + tdb_delete(ctx->tdb, ksid); + + DEBUG(10,("Deleting existing mapping %s -> %s\n", kidstr, ksidstr )); + tdb_delete(ctx->tdb, kid); + + tdb_chainunlock(ctx->tdb, ksid); + ret = NT_STATUS_OK; + +done: + talloc_free(ksidstr); + talloc_free(kidstr); + SAFE_FREE(data.dptr); + return ret; +} + +/********************************** + Close the idmap tdb instance +**********************************/ + +static NTSTATUS idmap_tdb_close(struct idmap_domain *dom) +{ + struct idmap_tdb_context *ctx; + + if (dom->private_data) { + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + if (idmap_tdb_tdb_close(ctx->tdb) == 0) { + return NT_STATUS_OK; + } else { + return NT_STATUS_UNSUCCESSFUL; + } + } + return NT_STATUS_OK; +} + +struct dump_data { + TALLOC_CTX *memctx; + struct id_map **maps; + int *num_maps; + NTSTATUS ret; +}; + +static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, void *pdata) +{ + struct dump_data *data = talloc_get_type(pdata, struct dump_data); + struct id_map *maps; + int num_maps = *data->num_maps; + + /* ignore any record but the ones with a SID as key */ + if (strncmp((const char *)key.dptr, "S-", 2) == 0) { + + maps = talloc_realloc(NULL, *data->maps, struct id_map, num_maps+1); + if ( ! maps) { + DEBUG(0, ("Out of memory!\n")); + data->ret = NT_STATUS_NO_MEMORY; + return -1; + } + *data->maps = maps; + maps[num_maps].sid = talloc(maps, DOM_SID); + if ( ! maps[num_maps].sid) { + DEBUG(0, ("Out of memory!\n")); + data->ret = NT_STATUS_NO_MEMORY; + return -1; + } + + if (!string_to_sid(maps[num_maps].sid, (const char *)key.dptr)) { + DEBUG(10,("INVALID record %s\n", (const char *)key.dptr)); + /* continue even with errors */ + return 0; + } + + /* Try a UID record. */ + if (sscanf((const char *)value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) { + maps[num_maps].xid.type = ID_TYPE_UID; + maps[num_maps].status = ID_MAPPED; + *data->num_maps = num_maps + 1; + + /* Try a GID record. */ + } else + if (sscanf((const char *)value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) { + maps[num_maps].xid.type = ID_TYPE_GID; + maps[num_maps].status = ID_MAPPED; + *data->num_maps = num_maps + 1; + + /* Unknown record type ! */ + } else { + maps[num_maps].status = ID_UNKNOWN; + DEBUG(2, ("Found INVALID record %s -> %s\n", + (const char *)key.dptr, (const char *)value.dptr)); + /* do not increment num_maps */ + } + } + + return 0; +} + +/********************************** + Dump all mappings out +**********************************/ + +static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps) +{ + struct idmap_tdb_context *ctx; + struct dump_data *data; + NTSTATUS ret = NT_STATUS_OK; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); + + data = TALLOC_ZERO_P(ctx, struct dump_data); + if ( ! data) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + data->maps = maps; + data->num_maps = num_maps; + data->ret = NT_STATUS_OK; + + tdb_traverse(ctx->tdb, idmap_tdb_dump_one_entry, data); + + if ( ! NT_STATUS_IS_OK(data->ret)) { + ret = data->ret; + } + + talloc_free(data); + return ret; +} + +static struct idmap_methods db_methods = { + + .init = idmap_tdb_db_init, + .unixids_to_sids = idmap_tdb_unixids_to_sids, + .sids_to_unixids = idmap_tdb_sids_to_unixids, + .set_mapping = idmap_tdb_set_mapping, + .remove_mapping = idmap_tdb_remove_mapping, + .dump_data = idmap_tdb_dump_data, + .close_fn = idmap_tdb_close +}; + +static struct idmap_alloc_methods db_alloc_methods = { + + .init = idmap_tdb_alloc_init, + .allocate_id = idmap_tdb_allocate_id, + .get_id_hwm = idmap_tdb_get_hwm, + .set_id_hwm = idmap_tdb_set_hwm, + .close_fn = idmap_tdb_alloc_close +}; + +NTSTATUS idmap_alloc_tdb_init(void) +{ + return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_alloc_methods); +} + +NTSTATUS idmap_tdb_init(void) +{ + NTSTATUS ret; + + /* FIXME: bad hack to actually register also the alloc_tdb module without changining configure.in */ + ret = idmap_alloc_tdb_init(); + if (! NT_STATUS_IS_OK(ret)) { + return ret; + } + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods); +} diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c new file mode 100644 index 0000000000..077c599739 --- /dev/null +++ b/source3/winbindd/idmap_util.c @@ -0,0 +1,171 @@ +/* + Unix SMB/CIFS implementation. + ID Mapping + Copyright (C) Simo Sorce 2003 + Copyright (C) Jeremy Allison 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/***************************************************************** + Returns the SID mapped to the given UID. + If mapping is not possible returns an error. +*****************************************************************/ + +NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) +{ + NTSTATUS ret; + struct id_map map; + struct id_map *maps[2]; + + DEBUG(10,("uid = [%lu]\n", (unsigned long)uid)); + + map.sid = sid; + map.xid.type = ID_TYPE_UID; + map.xid.id = uid; + + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_unixids_to_sids(maps); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); + return ret; + } + + if (map.status != ID_MAPPED) { + DEBUG(10, ("uid [%lu] not mapped\n", (unsigned long)uid)); + return NT_STATUS_NONE_MAPPED; + } + + return NT_STATUS_OK; +} + +/***************************************************************** + Returns SID mapped to the given GID. + If mapping is not possible returns an error. +*****************************************************************/ + +NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) +{ + NTSTATUS ret; + struct id_map map; + struct id_map *maps[2]; + + DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); + + map.sid = sid; + map.xid.type = ID_TYPE_GID; + map.xid.id = gid; + + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_unixids_to_sids(maps); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); + return ret; + } + + if (map.status != ID_MAPPED) { + DEBUG(10, ("gid [%lu] not mapped\n", (unsigned long)gid)); + return NT_STATUS_NONE_MAPPED; + } + + return NT_STATUS_OK; +} + +/***************************************************************** + Returns the UID mapped to the given SID. + If mapping is not possible or SID maps to a GID returns an error. +*****************************************************************/ + +NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) +{ + NTSTATUS ret; + struct id_map map; + struct id_map *maps[2]; + + DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid))); + + map.sid = sid; + map.xid.type = ID_TYPE_UID; + + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_sids_to_unixids(maps); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("error mapping sid [%s] to uid\n", + sid_string_static(sid))); + return ret; + } + + if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_UID)) { + DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n", + sid_string_static(sid), + map.status, + map.xid.type, + map.xid.id)); + return NT_STATUS_NONE_MAPPED; + } + + *uid = map.xid.id; + + return NT_STATUS_OK; +} + +/***************************************************************** + Returns the GID mapped to the given SID. + If mapping is not possible or SID maps to a UID returns an error. +*****************************************************************/ + +NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) +{ + NTSTATUS ret; + struct id_map map; + struct id_map *maps[2]; + + DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_static(sid))); + + map.sid = sid; + map.xid.type = ID_TYPE_GID; + + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_sids_to_unixids(maps); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("error mapping sid [%s] to gid\n", + sid_string_static(sid))); + return ret; + } + + if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) { + DEBUG(10, ("sid [%s] not mapped to a gid [%u,%u,%u]\n", + sid_string_static(sid), + map.status, + map.xid.type, + map.xid.id)); + return NT_STATUS_NONE_MAPPED; + } + + *gid = map.xid.id; + + return NT_STATUS_OK; +} diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c new file mode 100644 index 0000000000..ea51e9dde8 --- /dev/null +++ b/source3/winbindd/nss_info.c @@ -0,0 +1,301 @@ +/* + Unix SMB/CIFS implementation. + Idmap NSS headers + + Copyright (C) Gerald Carter 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "nss_info.h" + +static struct nss_function_entry *backends = NULL; +static struct nss_domain_entry *nss_domain_list = NULL; + +/********************************************************************** + Get idmap nss methods. +**********************************************************************/ + +static struct nss_function_entry *nss_get_backend(const char *name ) +{ + struct nss_function_entry *entry = backends; + + for(entry = backends; entry; entry = entry->next) { + if ( strequal(entry->name, name) ) + return entry; + } + + return NULL; +} + +/********************************************************************* + Allow a module to register itself as a backend. +**********************************************************************/ + + NTSTATUS smb_register_idmap_nss(int version, const char *name, struct nss_info_methods *methods) +{ + struct nss_function_entry *entry; + + if ((version != SMB_NSS_INFO_INTERFACE_VERSION)) { + DEBUG(0, ("smb_register_idmap_nss: Failed to register idmap_nss module.\n" + "The module was compiled against SMB_NSS_INFO_INTERFACE_VERSION %d,\n" + "current SMB_NSS_INFO_INTERFACE_VERSION is %d.\n" + "Please recompile against the current version of samba!\n", + version, SMB_NSS_INFO_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !methods) { + DEBUG(0,("smb_register_idmap_nss: called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if ( nss_get_backend(name) ) { + DEBUG(0,("smb_register_idmap_nss: idmap module %s " + "already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = SMB_XMALLOC_P(struct nss_function_entry); + entry->name = smb_xstrdup(name); + entry->methods = methods; + + DLIST_ADD(backends, entry); + DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap " + "nss backend '%s'\n", name)); + + return NT_STATUS_OK; +} + +/******************************************************************** + *******************************************************************/ + +static BOOL parse_nss_parm( const char *config, char **backend, char **domain ) +{ + char *p; + char *q; + int len; + + *backend = *domain = NULL; + + if ( !config ) + return False; + + p = strchr( config, ':' ); + + /* if no : then the string must be the backend name only */ + + if ( !p ) { + *backend = SMB_STRDUP( config ); + return (*backend != NULL); + } + + /* split the string and return the two parts */ + + if ( strlen(p+1) > 0 ) { + *domain = SMB_STRDUP( p+1 ); + } + + len = PTR_DIFF(p,config)+1; + if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) { + SAFE_FREE( *backend ); + return False; + } + + StrnCpy( q, config, len-1); + q[len-1] = '\0'; + *backend = q; + + return True; +} + +/******************************************************************** + Each nss backend must not store global state, but rather be able + to initialize the state on a per domain basis. + *******************************************************************/ + + NTSTATUS nss_init( const char **nss_list ) +{ + NTSTATUS status; + static NTSTATUS nss_initialized = NT_STATUS_UNSUCCESSFUL; + int i; + char *backend, *domain; + struct nss_function_entry *nss_backend; + struct nss_domain_entry *nss_domain; + + /* check for previous successful initializations */ + + if ( NT_STATUS_IS_OK(nss_initialized) ) + return NT_STATUS_OK; + + /* The "template" backend should alqays be registered as it + is a static module */ + + if ( (nss_backend = nss_get_backend( "template" )) == NULL ) { + static_init_nss_info; + } + + /* Create the list of nss_domains (loading any shared plugins + as necessary) */ + + for ( i=0; nss_list && nss_list[i]; i++ ) { + + if ( !parse_nss_parm(nss_list[i], &backend, &domain) ) { + DEBUG(0,("nss_init: failed to parse \"%s\"!\n", + nss_list[i])); + continue; + } + + /* validate the backend */ + + if ( (nss_backend = nss_get_backend( backend )) == NULL ) { + /* attempt to register the backend */ + status = smb_probe_module( "nss_info", backend ); + if ( !NT_STATUS_IS_OK(status) ) { + continue; + } + + /* try again */ + if ( (nss_backend = nss_get_backend( backend )) == NULL ) { + DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n", + backend)); + continue; + } + + } + + /* fill in the nss_domain_entry and add it to the + list of domains */ + + nss_domain = TALLOC_ZERO_P( nss_domain_list, struct nss_domain_entry ); + if ( !nss_domain ) { + DEBUG(0,("nss_init: talloc() failure!\n")); + return NT_STATUS_NO_MEMORY; + } + + nss_domain->backend = nss_backend; + nss_domain->domain = talloc_strdup( nss_domain, domain ); + + /* Try to init and ave the result */ + + nss_domain->init_status = nss_domain->backend->methods->init( nss_domain ); + DLIST_ADD( nss_domain_list, nss_domain ); + if ( !NT_STATUS_IS_OK(nss_domain->init_status) ) { + DEBUG(0,("nss_init: Failed to init backend for %s domain!\n", + nss_domain->domain)); + } + + /* cleanup */ + + SAFE_FREE( backend ); + SAFE_FREE( domain ); + } + + if ( !nss_domain_list ) { + DEBUG(3,("nss_init: no nss backends configured. " + "Defaulting to \"template\".\n")); + + + /* we shouild default to use template here */ + } + + + nss_initialized = NT_STATUS_OK; + + return NT_STATUS_OK; +} + +/******************************************************************** + *******************************************************************/ + +static struct nss_domain_entry *find_nss_domain( const char *domain ) +{ + NTSTATUS status; + struct nss_domain_entry *p; + + status = nss_init( lp_winbind_nss_info() ); + if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(4,("nss_get_info: Failed to init nss_info API (%s)!\n", + nt_errstr(status))); + return NULL; + } + + for ( p=nss_domain_list; p; p=p->next ) { + if ( strequal( p->domain, domain ) ) + break; + } + + /* If we didn't find a match, then use the default nss info */ + + if ( !p ) { + if ( !nss_domain_list ) { + return NULL; + } + + p = nss_domain_list; + } + + if ( !NT_STATUS_IS_OK( p->init_status ) ) { + p->init_status = p->backend->methods->init( p ); + } + + return p; +} + +/******************************************************************** + *******************************************************************/ + + NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, LDAPMessage *msg, + char **homedir, char **shell, char **gecos, + gid_t *p_gid) +{ + struct nss_domain_entry *p; + struct nss_info_methods *m; + + if ( (p = find_nss_domain( domain )) == NULL ) { + DEBUG(4,("nss_get_info: Failed to find nss domain pointer for %s\n", + domain )); + return NT_STATUS_NOT_FOUND; + } + + m = p->backend->methods; + + return m->get_nss_info( p, user_sid, ctx, ads, msg, + homedir, shell, gecos, p_gid ); +} + +/******************************************************************** + *******************************************************************/ + + NTSTATUS nss_close( const char *parameters ) +{ + struct nss_domain_entry *p = nss_domain_list; + struct nss_domain_entry *q; + + while ( p && p->backend && p->backend->methods ) { + /* close the backend */ + p->backend->methods->close_fn(); + + /* free the memory */ + q = p; + p = p->next; + TALLOC_FREE( q ); + } + + return NT_STATUS_OK; +} + diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c new file mode 100644 index 0000000000..aaf02e4abe --- /dev/null +++ b/source3/winbindd/nss_info_template.c @@ -0,0 +1,83 @@ +/* + Unix SMB/CIFS implementation. + idMap nss template plugin + + Copyright (C) Gerald Carter 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "nss_info.h" + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS nss_template_init( struct nss_domain_entry *e ) +{ + return NT_STATUS_OK; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, + const DOM_SID *sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, + LDAPMessage *msg, + char **homedir, + char **shell, + char **gecos, + gid_t *gid ) +{ + if ( !homedir || !shell || !gecos ) + return NT_STATUS_INVALID_PARAMETER; + + *homedir = talloc_strdup( ctx, lp_template_homedir() ); + *shell = talloc_strdup( ctx, lp_template_shell() ); + *gecos = NULL; + + if ( !*homedir || !*shell ) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS nss_template_close( void ) +{ + return NT_STATUS_OK; +} + + +/************************************************************************ + ***********************************************************************/ + +static struct nss_info_methods nss_template_methods = { + .init = nss_template_init, + .get_nss_info = nss_template_get_info, + .close_fn = nss_template_close +}; + +NTSTATUS nss_info_template_init( void ) +{ + return smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "template", + &nss_template_methods); +} + diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c new file mode 100644 index 0000000000..17915fb01b --- /dev/null +++ b/source3/winbindd/winbindd.c @@ -0,0 +1,1254 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) by Tim Potter 2000-2002 + Copyright (C) Andrew Tridgell 2002 + Copyright (C) Jelmer Vernooij 2003 + Copyright (C) Volker Lendecke 2004 + Copyright (C) James Peach 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +BOOL opt_nocache = False; + +extern BOOL override_logfile; + +struct event_context *winbind_event_context(void) +{ + static struct event_context *ctx; + + if (!ctx && !(ctx = event_context_init(NULL))) { + smb_panic("Could not init winbind event context"); + } + return ctx; +} + +struct messaging_context *winbind_messaging_context(void) +{ + static struct messaging_context *ctx; + + if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), + winbind_event_context()))) { + smb_panic("Could not init winbind messaging context"); + } + return ctx; +} + +/* Reload configuration */ + +static BOOL reload_services_file(void) +{ + BOOL ret; + + if (lp_loaded()) { + pstring fname; + + pstrcpy(fname,lp_configfile()); + if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { + pstrcpy(dyn_CONFIGFILE,fname); + } + } + + reopen_logs(); + ret = lp_load(dyn_CONFIGFILE,False,False,True,True); + + reopen_logs(); + load_interfaces(); + + return(ret); +} + + +/**************************************************************************** ** + Handle a fault.. + **************************************************************************** */ + +static void fault_quit(void) +{ + dump_core(); +} + +static void winbindd_status(void) +{ + struct winbindd_cli_state *tmp; + + DEBUG(0, ("winbindd status:\n")); + + /* Print client state information */ + + DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients())); + + if (DEBUGLEVEL >= 2 && winbindd_num_clients()) { + DEBUG(2, ("\tclient list:\n")); + for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) { + DEBUGADD(2, ("\t\tpid %lu, sock %d\n", + (unsigned long)tmp->pid, tmp->sock)); + } + } +} + +/* Print winbindd status to log file */ + +static void print_winbindd_status(void) +{ + winbindd_status(); +} + +/* Flush client cache */ + +static void flush_caches(void) +{ + /* We need to invalidate cached user list entries on a SIGHUP + otherwise cached access denied errors due to restrict anonymous + hang around until the sequence number changes. */ + + wcache_invalidate_cache(); +} + +/* Handle the signal by unlinking socket and exiting */ + +static void terminate(void) +{ + + winbindd_release_sockets(); + idmap_close(); + + trustdom_cache_shutdown(); + +#if 0 + if (interactive) { + TALLOC_CTX *mem_ctx = talloc_init("end_description"); + char *description = talloc_describe_all(mem_ctx); + + DEBUG(3, ("tallocs left:\n%s\n", description)); + talloc_destroy(mem_ctx); + } +#endif + + exit(0); +} + +static BOOL do_sigterm; + +static void termination_handler(int signum) +{ + do_sigterm = True; + sys_select_signal(signum); +} + +static BOOL do_sigusr2; + +static void sigusr2_handler(int signum) +{ + do_sigusr2 = True; + sys_select_signal(SIGUSR2); +} + +static BOOL do_sighup; + +static void sighup_handler(int signum) +{ + do_sighup = True; + sys_select_signal(SIGHUP); +} + +static BOOL do_sigchld; + +static void sigchld_handler(int signum) +{ + do_sigchld = True; + sys_select_signal(SIGCHLD); +} + +/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ +static void msg_reload_services(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + /* Flush various caches */ + flush_caches(); + reload_services_file(); +} + +/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ +static void msg_shutdown(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + do_sigterm = True; +} + + +static void winbind_msg_validate_cache(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + uint8 ret; + pid_t child_pid; + struct sigaction act; + struct sigaction oldact; + + DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache " + "message.\n")); + + /* + * call the validation code from a child: + * so we don't block the main winbindd and the validation + * code can safely use fork/waitpid... + */ + CatchChild(); + child_pid = sys_fork(); + + if (child_pid == -1) { + DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n", + strerror(errno))); + return; + } + + if (child_pid != 0) { + /* parent */ + DEBUG(5, ("winbind_msg_validate_cache: child created with " + "pid %d.\n", child_pid)); + return; + } + + /* child */ + + /* install default SIGCHLD handler: validation code uses fork/waitpid */ + ZERO_STRUCT(act); + act.sa_handler = SIG_DFL; +#ifdef SA_RESTART + /* We *want* SIGALRM to interrupt a system call. */ + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,SIGCHLD); + sigaction(SIGCHLD,&act,&oldact); + + ret = (uint8)winbindd_validate_cache_nobackup(); + DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret)); + messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret, + (size_t)1); + _exit(0); +} + +static struct winbindd_dispatch_table { + enum winbindd_cmd cmd; + void (*fn)(struct winbindd_cli_state *state); + const char *winbindd_cmd_name; +} dispatch_table[] = { + + /* User functions */ + + { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" }, + { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" }, + + { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" }, + { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" }, + { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, + + { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, + { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" }, + { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups, + "GETUSERDOMGROUPS" }, + + /* Group functions */ + + { WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" }, + { WINBINDD_GETGRGID, winbindd_getgrgid, "GETGRGID" }, + { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" }, + { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" }, + { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" }, + { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" }, + + /* PAM auth functions */ + + { WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" }, + { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" }, + { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" }, + { WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" }, + { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, winbindd_pam_chng_pswd_auth_crap, "CHNG_PSWD_AUTH_CRAP" }, + + /* Enumeration functions */ + + { WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" }, + { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" }, + { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains, + "LIST_TRUSTDOM" }, + { WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" }, + + /* SID related functions */ + + { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" }, + { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, + { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" }, + + /* Lookup related functions */ + + { WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" }, + { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" }, + { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" }, + { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" }, +#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ + { WINBINDD_SIDS_TO_XIDS, winbindd_sids_to_unixids, "SIDS_TO_XIDS" }, +#endif /* end DISABLED */ + { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" }, + { WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" }, + { WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" }, + { WINBINDD_SET_HWM, winbindd_set_hwm, "SET_HWMS" }, + + /* Miscellaneous */ + + { WINBINDD_DUMP_MAPS, winbindd_dump_maps, "DUMP_MAPS" }, + + { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" }, + { WINBINDD_PING, winbindd_ping, "PING" }, + { WINBINDD_INFO, winbindd_info, "INFO" }, + { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, + "INTERFACE_VERSION" }, + { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" }, + { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" }, + { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" }, + { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir, + "WINBINDD_PRIV_PIPE_DIR" }, + { WINBINDD_GETDCNAME, winbindd_getdcname, "GETDCNAME" }, + { WINBINDD_DSGETDCNAME, winbindd_dsgetdcname, "DSGETDCNAME" }, + + /* Credential cache access */ + { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" }, + + /* WINS functions */ + + { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" }, + { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" }, + + /* End of list */ + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; + +static void process_request(struct winbindd_cli_state *state) +{ + struct winbindd_dispatch_table *table = dispatch_table; + + /* Free response data - we may be interrupted and receive another + command before being able to send this data off. */ + + SAFE_FREE(state->response.extra_data.data); + + ZERO_STRUCT(state->response); + + state->response.result = WINBINDD_PENDING; + state->response.length = sizeof(struct winbindd_response); + + state->mem_ctx = talloc_init("winbind request"); + if (state->mem_ctx == NULL) + return; + + /* Remember who asked us. */ + state->pid = state->request.pid; + + /* Process command */ + + for (table = dispatch_table; table->fn; table++) { + if (state->request.cmd == table->cmd) { + DEBUG(10,("process_request: request fn %s\n", + table->winbindd_cmd_name )); + table->fn(state); + break; + } + } + + if (!table->fn) { + DEBUG(10,("process_request: unknown request fn number %d\n", + (int)state->request.cmd )); + request_error(state); + } +} + +/* + * A list of file descriptors being monitored by select in the main processing + * loop. fd_event->handler is called whenever the socket is readable/writable. + */ + +static struct fd_event *fd_events = NULL; + +void add_fd_event(struct fd_event *ev) +{ + struct fd_event *match; + + /* only add unique fd_event structs */ + + for (match=fd_events; match; match=match->next ) { +#ifdef DEVELOPER + SMB_ASSERT( match != ev ); +#else + if ( match == ev ) + return; +#endif + } + + DLIST_ADD(fd_events, ev); +} + +void remove_fd_event(struct fd_event *ev) +{ + DLIST_REMOVE(fd_events, ev); +} + +/* + * Handler for fd_events to complete a read/write request, set up by + * setup_async_read/setup_async_write. + */ + +static void rw_callback(struct fd_event *event, int flags) +{ + size_t todo; + ssize_t done = 0; + + todo = event->length - event->done; + + if (event->flags & EVENT_FD_WRITE) { + SMB_ASSERT(flags == EVENT_FD_WRITE); + done = sys_write(event->fd, + &((char *)event->data)[event->done], + todo); + + if (done <= 0) { + event->flags = 0; + event->finished(event->private_data, False); + return; + } + } + + if (event->flags & EVENT_FD_READ) { + SMB_ASSERT(flags == EVENT_FD_READ); + done = sys_read(event->fd, &((char *)event->data)[event->done], + todo); + + if (done <= 0) { + event->flags = 0; + event->finished(event->private_data, False); + return; + } + } + + event->done += done; + + if (event->done == event->length) { + event->flags = 0; + event->finished(event->private_data, True); + } +} + +/* + * Request an async read/write on a fd_event structure. (*finished) is called + * when the request is completed or an error had occurred. + */ + +void setup_async_read(struct fd_event *event, void *data, size_t length, + void (*finished)(void *private_data, BOOL success), + void *private_data) +{ + SMB_ASSERT(event->flags == 0); + event->data = data; + event->length = length; + event->done = 0; + event->handler = rw_callback; + event->finished = finished; + event->private_data = private_data; + event->flags = EVENT_FD_READ; +} + +void setup_async_write(struct fd_event *event, void *data, size_t length, + void (*finished)(void *private_data, BOOL success), + void *private_data) +{ + SMB_ASSERT(event->flags == 0); + event->data = data; + event->length = length; + event->done = 0; + event->handler = rw_callback; + event->finished = finished; + event->private_data = private_data; + event->flags = EVENT_FD_WRITE; +} + +/* + * This is the main event loop of winbind requests. It goes through a + * state-machine of 3 read/write requests, 4 if you have extra data to send. + * + * An idle winbind client has a read request of 4 bytes outstanding, + * finalizing function is request_len_recv, checking the length. request_recv + * then processes the packet. The processing function then at some point has + * to call request_finished which schedules sending the response. + */ + +static void request_len_recv(void *private_data, BOOL success); +static void request_recv(void *private_data, BOOL success); +static void request_main_recv(void *private_data, BOOL success); +static void request_finished(struct winbindd_cli_state *state); +void request_finished_cont(void *private_data, BOOL success); +static void response_main_sent(void *private_data, BOOL success); +static void response_extra_sent(void *private_data, BOOL success); + +static void response_extra_sent(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (state->mem_ctx != NULL) { + talloc_destroy(state->mem_ctx); + state->mem_ctx = NULL; + } + + if (!success) { + state->finished = True; + return; + } + + SAFE_FREE(state->request.extra_data.data); + SAFE_FREE(state->response.extra_data.data); + + setup_async_read(&state->fd_event, &state->request, sizeof(uint32), + request_len_recv, state); +} + +static void response_main_sent(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + if (state->response.length == sizeof(state->response)) { + if (state->mem_ctx != NULL) { + talloc_destroy(state->mem_ctx); + state->mem_ctx = NULL; + } + + setup_async_read(&state->fd_event, &state->request, + sizeof(uint32), request_len_recv, state); + return; + } + + setup_async_write(&state->fd_event, state->response.extra_data.data, + state->response.length - sizeof(state->response), + response_extra_sent, state); +} + +static void request_finished(struct winbindd_cli_state *state) +{ + setup_async_write(&state->fd_event, &state->response, + sizeof(state->response), response_main_sent, state); +} + +void request_error(struct winbindd_cli_state *state) +{ + SMB_ASSERT(state->response.result == WINBINDD_PENDING); + state->response.result = WINBINDD_ERROR; + request_finished(state); +} + +void request_ok(struct winbindd_cli_state *state) +{ + SMB_ASSERT(state->response.result == WINBINDD_PENDING); + state->response.result = WINBINDD_OK; + request_finished(state); +} + +void request_finished_cont(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (success) + request_ok(state); + else + request_error(state); +} + +static void request_len_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + if (*(uint32 *)(&state->request) != sizeof(state->request)) { + DEBUG(0,("request_len_recv: Invalid request size received: %d\n", + *(uint32 *)(&state->request))); + state->finished = True; + return; + } + + setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, + sizeof(state->request) - sizeof(uint32), + request_main_recv, state); +} + +static void request_main_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + if (state->request.extra_len == 0) { + state->request.extra_data.data = NULL; + request_recv(state, True); + return; + } + + if ((!state->privileged) && + (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", (int)state->request.extra_len)); + state->request.extra_data.data = NULL; + state->finished = True; + return; + } + + state->request.extra_data.data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data.data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data.data[state->request.extra_len] = '\0'; + + setup_async_read(&state->fd_event, state->request.extra_data.data, + state->request.extra_len, request_recv, state); +} + +static void request_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + process_request(state); +} + +/* Process a new connection by adding it to the client connection list */ + +static void new_connection(int listen_sock, BOOL privileged) +{ + struct sockaddr_un sunaddr; + struct winbindd_cli_state *state; + socklen_t len; + int sock; + + /* Accept connection */ + + len = sizeof(sunaddr); + + do { + sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len); + } while (sock == -1 && errno == EINTR); + + if (sock == -1) + return; + + DEBUG(6,("accepted socket %d\n", sock)); + + /* Create new connection structure */ + + if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL) { + close(sock); + return; + } + + state->sock = sock; + + state->last_access = time(NULL); + + state->privileged = privileged; + + state->fd_event.fd = state->sock; + state->fd_event.flags = 0; + add_fd_event(&state->fd_event); + + setup_async_read(&state->fd_event, &state->request, sizeof(uint32), + request_len_recv, state); + + /* Add to connection list */ + + winbindd_add_client(state); +} + +/* Remove a client connection from client connection list */ + +static void remove_client(struct winbindd_cli_state *state) +{ + /* It's a dead client - hold a funeral */ + + if (state == NULL) { + return; + } + + /* Close socket */ + + close(state->sock); + + /* Free any getent state */ + + free_getent_state(state->getpwent_state); + free_getent_state(state->getgrent_state); + + /* We may have some extra data that was not freed if the client was + killed unexpectedly */ + + SAFE_FREE(state->response.extra_data.data); + + if (state->mem_ctx != NULL) { + talloc_destroy(state->mem_ctx); + state->mem_ctx = NULL; + } + + remove_fd_event(&state->fd_event); + + /* Remove from list and free */ + + winbindd_remove_client(state); + TALLOC_FREE(state); +} + +/* Shutdown client connection which has been idle for the longest time */ + +static BOOL remove_idle_client(void) +{ + struct winbindd_cli_state *state, *remove_state = NULL; + time_t last_access = 0; + int nidle = 0; + + for (state = winbindd_client_list(); state; state = state->next) { + if (state->response.result != WINBINDD_PENDING && + !state->getpwent_state && !state->getgrent_state) { + nidle++; + if (!last_access || state->last_access < last_access) { + last_access = state->last_access; + remove_state = state; + } + } + } + + if (remove_state) { + DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n", + nidle, remove_state->sock, (unsigned int)remove_state->pid)); + remove_client(remove_state); + return True; + } + + return False; +} + +/* Process incoming clients on listen_sock. We use a tricky non-blocking, + non-forking, non-threaded model which allows us to handle many + simultaneous connections while remaining impervious to many denial of + service attacks. */ + +static int process_loop(int listen_sock, int listen_priv_sock) +{ + struct winbindd_cli_state *state; + struct fd_event *ev; + fd_set r_fds, w_fds; + int maxfd, selret; + struct timeval timeout, ev_timeout; + + /* We'll be doing this a lot */ + + /* Handle messages */ + + message_dispatch(winbind_messaging_context()); + + run_events(winbind_event_context(), 0, NULL, NULL); + + /* refresh the trusted domain cache */ + + rescan_trusted_domains(); + + /* Initialise fd lists for select() */ + + maxfd = MAX(listen_sock, listen_priv_sock); + + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); + FD_SET(listen_sock, &r_fds); + FD_SET(listen_priv_sock, &r_fds); + + timeout.tv_sec = WINBINDD_ESTABLISH_LOOP; + timeout.tv_usec = 0; + + /* Check for any event timeouts. */ + if (get_timed_events_timeout(winbind_event_context(), &ev_timeout)) { + timeout = timeval_min(&timeout, &ev_timeout); + } + + /* Set up client readers and writers */ + + state = winbindd_client_list(); + + while (state) { + + struct winbindd_cli_state *next = state->next; + + /* Dispose of client connection if it is marked as + finished */ + + if (state->finished) + remove_client(state); + + state = next; + } + + for (ev = fd_events; ev; ev = ev->next) { + if (ev->flags & EVENT_FD_READ) { + FD_SET(ev->fd, &r_fds); + maxfd = MAX(ev->fd, maxfd); + } + if (ev->flags & EVENT_FD_WRITE) { + FD_SET(ev->fd, &w_fds); + maxfd = MAX(ev->fd, maxfd); + } + } + + /* Call select */ + + selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); + + if (selret == 0) { + goto no_fds_ready; + } + + if (selret == -1) { + if (errno == EINTR) { + goto no_fds_ready; + } + + /* Select error, something is badly wrong */ + + perror("select"); + exit(1); + } + + /* selret > 0 */ + + ev = fd_events; + while (ev != NULL) { + struct fd_event *next = ev->next; + int flags = 0; + if (FD_ISSET(ev->fd, &r_fds)) + flags |= EVENT_FD_READ; + if (FD_ISSET(ev->fd, &w_fds)) + flags |= EVENT_FD_WRITE; + if (flags) + ev->handler(ev, flags); + ev = next; + } + + if (FD_ISSET(listen_sock, &r_fds)) { + while (winbindd_num_clients() > + WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { + DEBUG(5,("winbindd: Exceeding %d client " + "connections, removing idle " + "connection.\n", + WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); + if (!remove_idle_client()) { + DEBUG(0,("winbindd: Exceeding %d " + "client connections, no idle " + "connection found\n", + WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); + break; + } + } + /* new, non-privileged connection */ + new_connection(listen_sock, False); + } + + if (FD_ISSET(listen_priv_sock, &r_fds)) { + while (winbindd_num_clients() > + WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { + DEBUG(5,("winbindd: Exceeding %d client " + "connections, removing idle " + "connection.\n", + WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); + if (!remove_idle_client()) { + DEBUG(0,("winbindd: Exceeding %d " + "client connections, no idle " + "connection found\n", + WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); + break; + } + } + /* new, privileged connection */ + new_connection(listen_priv_sock, True); + } + + no_fds_ready: + +#if 0 + winbindd_check_cache_size(time(NULL)); +#endif + + /* Check signal handling things */ + + if (do_sigterm) + terminate(); + + if (do_sighup) { + + DEBUG(3, ("got SIGHUP\n")); + + flush_caches(); + reload_services_file(); + + do_sighup = False; + } + + if (do_sigusr2) { + print_winbindd_status(); + do_sigusr2 = False; + } + + if (do_sigchld) { + pid_t pid; + + do_sigchld = False; + + while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { + winbind_child_died(pid); + } + } + + + return winbindd_num_clients(); +} + +static void winbindd_process_loop(enum smb_server_mode server_mode) +{ + int idle_timeout_sec; + struct timeval starttime; + int listen_public, listen_priv; + + errno = 0; + if (!winbindd_init_sockets(&listen_public, &listen_priv, + &idle_timeout_sec)) { + terminate(); + } + + starttime = timeval_current(); + + if (listen_public == -1 || listen_priv == -1) { + DEBUG(0, ("failed to open winbindd pipes: %s\n", + errno ? strerror(errno) : "unknown error")); + terminate(); + } + + for (;;) { + TALLOC_CTX *frame = talloc_stackframe(); + int clients = process_loop(listen_public, listen_priv); + + /* Don't bother figuring out the idle time if we won't be + * timing out anyway. + */ + if (idle_timeout_sec < 0) { + TALLOC_FREE(frame); + continue; + } + + if (clients == 0 && server_mode == SERVER_MODE_FOREGROUND) { + struct timeval now; + + now = timeval_current(); + if (timeval_elapsed2(&starttime, &now) > + (double)idle_timeout_sec) { + DEBUG(0, ("idle for %d secs, exitting\n", + idle_timeout_sec)); + terminate(); + } + } else { + starttime = timeval_current(); + } + TALLOC_FREE(frame); + } +} + +/* Main function */ + +int main(int argc, char **argv, char **envp) +{ + pstring logfile; + BOOL log_stdout = False; + BOOL no_process_group = False; + + enum smb_server_mode server_mode = SERVER_MODE_DAEMON; + + struct poptOption long_options[] = { + POPT_AUTOHELP + { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, + { "foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, "Daemon in foreground mode" }, + { "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, + { "daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, "Become a daemon (default)" }, + { "interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, "Interactive mode" }, + { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, + POPT_COMMON_SAMBA + POPT_TABLEEND + }; + poptContext pc; + int opt; + + /* glibc (?) likes to print "User defined signal 1" and exit if a + SIGUSR[12] is received before a handler is installed */ + + CatchSignal(SIGUSR1, SIG_IGN); + CatchSignal(SIGUSR2, SIG_IGN); + + fault_setup((void (*)(void *))fault_quit ); + dump_core_setup("winbindd"); + + load_case_tables(); + + /* Initialise for running in non-root mode */ + + sec_init(); + + set_remote_machine_name("winbindd", False); + + /* Set environment variable so we don't recursively call ourselves. + This may also be useful interactively. */ + + if ( !winbind_off() ) { + DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n")); + exit(1); + } + + /* Initialise samba/rpc client stuff */ + + pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + default: + d_fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + exit(1); + } + } + + if (server_mode == SERVER_MODE_INTERACTIVE) { + log_stdout = True; + if (DEBUGLEVEL >= 9) { + talloc_enable_leak_report(); + } + } + + if (log_stdout && server_mode == SERVER_MODE_DAEMON) { + printf("Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"); + poptPrintUsage(pc, stderr, 0); + exit(1); + } + + poptFreeContext(pc); + + if (!override_logfile) { + pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); + lp_set_logfile(logfile); + } + setup_logging("winbindd", log_stdout); + reopen_logs(); + + DEBUG(1, ("winbindd version %s started.\n%s\n", + SAMBA_VERSION_STRING, + COPYRIGHT_STARTUP_MESSAGE) ); + + if (!reload_services_file()) { + DEBUG(0, ("error opening config file\n")); + exit(1); + } + + if (!directory_exist(lp_lockdir(), NULL)) { + mkdir(lp_lockdir(), 0755); + } + + /* Setup names. */ + + if (!init_names()) + exit(1); + + load_interfaces(); + + if (!secrets_init()) { + + DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); + return False; + } + + /* Enable netbios namecache */ + + namecache_enable(); + + /* Winbind daemon initialisation */ + + if ( ! NT_STATUS_IS_OK(idmap_init_cache()) ) { + DEBUG(1, ("Could not init idmap cache!\n")); + } + + /* Unblock all signals we are interested in as they may have been + blocked by the parent process. */ + + BlockSignals(False, SIGINT); + BlockSignals(False, SIGQUIT); + BlockSignals(False, SIGTERM); + BlockSignals(False, SIGUSR1); + BlockSignals(False, SIGUSR2); + BlockSignals(False, SIGHUP); + BlockSignals(False, SIGCHLD); + + /* Setup signal handlers */ + + CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ + CatchSignal(SIGQUIT, termination_handler); + CatchSignal(SIGTERM, termination_handler); + CatchSignal(SIGCHLD, sigchld_handler); + + CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ + + CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ + CatchSignal(SIGHUP, sighup_handler); + + if (server_mode == SERVER_MODE_DAEMON) { + DEBUG( 3, ( "Becoming a daemon.\n" ) ); + become_daemon(True, no_process_group); + } else if (server_mode == SERVER_MODE_FOREGROUND) { + become_daemon(False, no_process_group); + } + + pidfile_create("winbindd"); + + /* Ensure all cache and idmap caches are consistent + before we startup. */ + + if (winbindd_validate_cache()) { + /* We have a bad cache, but luckily we + just deleted it. Restart ourselves */ + int i; + /* Ensure we have no open low fd's. */ + for (i = 3; i < 100; i++) { + close(i); + } + return execve(argv[0], argv, envp); + } + +#if HAVE_SETPGID + /* + * If we're interactive we want to set our own process group for + * signal management. + */ + if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { + setpgid( (pid_t)0, (pid_t)0); + } +#endif + + TimeInit(); + + /* Initialise messaging system */ + + if (winbind_messaging_context() == NULL) { + DEBUG(0, ("unable to initialize messaging system\n")); + exit(1); + } + + /* Initialize cache (ensure version is correct). */ + if (!initialize_winbindd_cache()) { + exit(1); + } + + /* React on 'smbcontrol winbindd reload-config' in the same way + as to SIGHUP signal */ + messaging_register(winbind_messaging_context(), NULL, + MSG_SMB_CONF_UPDATED, msg_reload_services); + messaging_register(winbind_messaging_context(), NULL, + MSG_SHUTDOWN, msg_shutdown); + + /* Handle online/offline messages. */ + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_OFFLINE, winbind_msg_offline); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_ONLINE, winbind_msg_online); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus); + + messaging_register(winbind_messaging_context(), NULL, + MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list); + + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_VALIDATE_CACHE, + winbind_msg_validate_cache); + + netsamlogon_cache_init(); /* Non-critical */ + + /* clear the cached list of trusted domains */ + + wcache_tdc_clear(); + + if (!init_domain_list()) { + DEBUG(0,("unable to initalize domain list\n")); + exit(1); + } + + init_idmap_child(); + init_locator_child(); + + smb_nscd_flush_user_cache(); + smb_nscd_flush_group_cache(); + + /* Loop waiting for requests */ + winbindd_process_loop(server_mode); + + return 0; +} diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h new file mode 100644 index 0000000000..e7119c332f --- /dev/null +++ b/source3/winbindd/winbindd.h @@ -0,0 +1,365 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBINDD_H +#define _WINBINDD_H + +#include "nsswitch/winbind_struct_protocol.h" + +#ifdef HAVE_LIBNSCD +#include +#endif + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +#define WB_REPLACE_CHAR '_' + +/* bits for fd_event.flags */ +#define EVENT_FD_READ 1 +#define EVENT_FD_WRITE 2 + +struct fd_event { + struct fd_event *next, *prev; + int fd; + int flags; /* see EVENT_FD_* flags */ + void (*handler)(struct fd_event *fde, int flags); + void *data; + size_t length, done; + void (*finished)(void *private_data, BOOL success); + void *private_data; +}; + +struct sid_ctr { + DOM_SID *sid; + BOOL finished; + const char *domain; + const char *name; + enum lsa_SidType type; +}; + +struct winbindd_cli_state { + struct winbindd_cli_state *prev, *next; /* Linked list pointers */ + int sock; /* Open socket from client */ + struct fd_event fd_event; + pid_t pid; /* pid of client */ + BOOL finished; /* Can delete from list */ + BOOL write_extra_data; /* Write extra_data field */ + time_t last_access; /* Time of last access (read or write) */ + BOOL privileged; /* Is the client 'privileged' */ + + TALLOC_CTX *mem_ctx; /* memory per request */ + struct winbindd_request request; /* Request from client */ + struct winbindd_response response; /* Respose to client */ + BOOL getpwent_initialized; /* Has getpwent_state been + * initialized? */ + BOOL getgrent_initialized; /* Has getgrent_state been + * initialized? */ + struct getent_state *getpwent_state; /* State for getpwent() */ + struct getent_state *getgrent_state; /* State for getgrent() */ +}; + +/* State between get{pw,gr}ent() calls */ + +struct getent_state { + struct getent_state *prev, *next; + void *sam_entries; + uint32 sam_entry_index, num_sam_entries; + BOOL got_sam_entries; + fstring domain_name; +}; + +/* Storage for cached getpwent() user entries */ + +struct getpwent_user { + fstring name; /* Account name */ + fstring gecos; /* User information */ + fstring homedir; /* User Home Directory */ + fstring shell; /* User Login Shell */ + DOM_SID user_sid; /* NT user and primary group SIDs */ + DOM_SID group_sid; +}; + +/* Server state structure */ + +typedef struct { + char *acct_name; + char *full_name; + char *homedir; + char *shell; + gid_t primary_gid; /* allow the nss_info + backend to set the primary group */ + DOM_SID user_sid; /* NT user and primary group SIDs */ + DOM_SID group_sid; +} WINBIND_USERINFO; + +/* Our connection to the DC */ + +struct winbindd_cm_conn { + struct cli_state *cli; + + struct rpc_pipe_client *samr_pipe; + POLICY_HND sam_connect_handle, sam_domain_handle; + + struct rpc_pipe_client *lsa_pipe; + POLICY_HND lsa_policy; + + struct rpc_pipe_client *netlogon_pipe; +}; + +struct winbindd_async_request; + +/* Async child */ + +struct winbindd_child { + struct winbindd_child *next, *prev; + + pid_t pid; + struct winbindd_domain *domain; + pstring logfilename; + + struct fd_event event; + struct timed_event *lockout_policy_event; + struct winbindd_async_request *requests; +}; + +/* Structures to hold per domain information */ + +struct winbindd_domain { + fstring name; /* Domain name (NetBIOS) */ + fstring alt_name; /* alt Domain name, if any (FQDN for ADS) */ + fstring forest_name; /* Name of the AD forest we're in */ + DOM_SID sid; /* SID for this domain */ + uint32 domain_flags; /* Domain flags from rpc_ds.h */ + uint32 domain_type; /* Domain type from rpc_ds.h */ + uint32 domain_trust_attribs; /* Trust attribs from rpc_ds.h */ + BOOL initialized; /* Did we already ask for the domain mode? */ + BOOL native_mode; /* is this a win2k domain in native mode ? */ + BOOL active_directory; /* is this a win2k active directory ? */ + BOOL primary; /* is this our primary domain ? */ + BOOL internal; /* BUILTIN and member SAM */ + BOOL online; /* is this domain available ? */ + time_t startup_time; /* When we set "startup" true. */ + BOOL startup; /* are we in the first 30 seconds after startup_time ? */ + + BOOL can_do_samlogon_ex; /* Due to the lack of finer control what type + * of DC we have, let us try to do a + * credential-chain less samlogon_ex call + * with AD and schannel. If this fails with + * DCERPC_FAULT_OP_RNG_ERROR, then set this + * to False. This variable is around so that + * we don't have to try _ex every time. */ + + /* Lookup methods for this domain (LDAP or RPC) */ + struct winbindd_methods *methods; + + /* the backend methods are used by the cache layer to find the right + backend */ + struct winbindd_methods *backend; + + /* Private data for the backends (used for connection cache) */ + + void *private_data; + + /* A working DC */ + fstring dcname; + struct sockaddr_in dcaddr; + + /* Sequence number stuff */ + + time_t last_seq_check; + uint32 sequence_number; + NTSTATUS last_status; + + /* The smb connection */ + + struct winbindd_cm_conn conn; + + /* The child pid we're talking to */ + + struct winbindd_child child; + + /* Callback we use to try put us back online. */ + + uint32 check_online_timeout; + struct timed_event *check_online_event; + + /* Linked list info */ + + struct winbindd_domain *prev, *next; +}; + +/* per-domain methods. This is how LDAP vs RPC is selected + */ +struct winbindd_methods { + /* does this backend provide a consistent view of the data? (ie. is the primary group + always correct) */ + BOOL consistent; + + /* get a list of users, returning a WINBIND_USERINFO for each one */ + NTSTATUS (*query_user_list)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info); + + /* get a list of domain groups */ + NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info); + + /* get a list of domain local groups */ + NTSTATUS (*enum_local_groups)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info); + + /* convert one user or group name to a sid */ + NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd orig_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type); + + /* convert a sid to a user or group name */ + NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type); + + NTSTATUS (*rids_to_names)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types); + + /* lookup user info for a given SID */ + NTSTATUS (*query_user)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + WINBIND_USERINFO *user_info); + + /* lookup all groups that a user is a member of. The backend + can also choose to lookup by username or rid for this + function */ + NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *num_groups, DOM_SID **user_gids); + + /* Lookup all aliases that the sids delivered are member of. This is + * to implement 'domain local groups' correctly */ + NTSTATUS (*lookup_useraliases)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, + const DOM_SID *sids, + uint32 *num_aliases, + uint32 **alias_rids); + + /* find all members of the group with the specified group_rid */ + NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, + uint32 *num_names, + DOM_SID **sid_mem, char ***names, + uint32 **name_types); + + /* return the current global sequence number */ + NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq); + + /* return the lockout policy */ + NTSTATUS (*lockout_policy)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_12 *lockout_policy); + + /* return the lockout policy */ + NTSTATUS (*password_policy)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_1 *password_policy); + + /* enumerate trusted domains */ + NTSTATUS (*trusted_domains)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + char ***names, + char ***alt_names, + DOM_SID **dom_sids); +}; + +/* Used to glue a policy handle and cli_state together */ + +typedef struct { + struct cli_state *cli; + POLICY_HND pol; +} CLI_POLICY_HND; + +/* Filled out by IDMAP backends */ +struct winbindd_idmap_methods { + /* Called when backend is first loaded */ + BOOL (*init)(void); + + BOOL (*get_sid_from_uid)(uid_t uid, DOM_SID *sid); + BOOL (*get_sid_from_gid)(gid_t gid, DOM_SID *sid); + + BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); + BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); + + /* Called when backend is unloaded */ + BOOL (*close)(void); + /* Called to dump backend status */ + void (*status)(void); +}; + +/* Data structures for dealing with the trusted domain cache */ + +struct winbindd_tdc_domain { + const char *domain_name; + const char *dns_name; + DOM_SID sid; + uint32 trust_flags; + uint32 trust_attribs; + uint32 trust_type; +}; + + +#include "winbindd/winbindd_proto.h" + +#define WINBINDD_ESTABLISH_LOOP 30 +#define WINBINDD_RESCAN_FREQ lp_winbind_cache_time() +#define WINBINDD_PAM_AUTH_KRB5_RENEW_TIME 2592000 /* one month */ +#define DOM_SEQUENCE_NONE ((uint32)-1) + +#define IS_DOMAIN_OFFLINE(x) ( lp_winbind_offline_logon() && \ + ( get_global_winbindd_state_offline() \ + || !(x)->online ) ) +#endif /* _WINBINDD_H */ diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c new file mode 100644 index 0000000000..65cc00bb97 --- /dev/null +++ b/source3/winbindd/winbindd_ads.c @@ -0,0 +1,1312 @@ +/* + Unix SMB/CIFS implementation. + + Winbind ADS backend functions + + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2003 + Copyright (C) Gerald (Jerry) Carter 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#ifdef HAVE_ADS + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +extern struct winbindd_methods reconnect_methods; + +/* + return our ads connections structure for a domain. We keep the connection + open to make things faster +*/ +static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) +{ + ADS_STRUCT *ads; + ADS_STATUS status; + fstring dc_name; + struct in_addr dc_ip; + + DEBUG(10,("ads_cached_connection\n")); + + if (domain->private_data) { + + time_t expire; + time_t now = time(NULL); + + /* check for a valid structure */ + ads = (ADS_STRUCT *)domain->private_data; + + expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire); + + DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n", + (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); + + if ( ads->config.realm && (expire > now)) { + return ads; + } else { + /* we own this ADS_STRUCT so make sure it goes away */ + DEBUG(7,("Deleting expired krb5 credential cache\n")); + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy("MEMORY:winbind_ccache"); + domain->private_data = NULL; + } + } + + /* we don't want this to affect the users ccache */ + setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1); + + ads = ads_init(domain->alt_name, domain->name, NULL); + if (!ads) { + DEBUG(1,("ads_init for domain %s failed\n", domain->name)); + return NULL; + } + + /* the machine acct password might have change - fetch it every time */ + + SAFE_FREE(ads->auth.password); + SAFE_FREE(ads->auth.realm); + + if ( IS_DC ) { + DOM_SID sid; + time_t last_set_time; + + if ( !pdb_get_trusteddom_pw( domain->name, &ads->auth.password, &sid, &last_set_time ) ) { + ads_destroy( &ads ); + return NULL; + } + ads->auth.realm = SMB_STRDUP( ads->server.realm ); + strupper_m( ads->auth.realm ); + } + else { + struct winbindd_domain *our_domain = domain; + + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + /* always give preference to the alt_name in our + primary domain if possible */ + + if ( !domain->primary ) + our_domain = find_our_domain(); + + if ( our_domain->alt_name[0] != '\0' ) { + ads->auth.realm = SMB_STRDUP( our_domain->alt_name ); + strupper_m( ads->auth.realm ); + } + else + ads->auth.realm = SMB_STRDUP( lp_realm() ); + } + + ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME; + + /* Setup the server affinity cache. We don't reaally care + about the name. Just setup affinity and the KRB5_CONFIG + file. */ + + get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip ); + + status = ads_connect(ads); + if (!ADS_ERR_OK(status) || !ads->config.realm) { + DEBUG(1,("ads_connect for domain %s failed: %s\n", + domain->name, ads_errstr(status))); + ads_destroy(&ads); + + /* if we get ECONNREFUSED then it might be a NT4 + server, fall back to MSRPC */ + if (status.error_type == ENUM_ADS_ERROR_SYSTEM && + status.err.rc == ECONNREFUSED) { + /* 'reconnect_methods' is the MS-RPC backend. */ + DEBUG(1,("Trying MSRPC methods\n")); + domain->backend = &reconnect_methods; + } + return NULL; + } + + /* set the flag that says we don't own the memory even + though we do so that ads_destroy() won't destroy the + structure we pass back by reference */ + + ads->is_mine = False; + + domain->private_data = (void *)ads; + return ads; +} + + +/* Query display info for a realm. This is the basic user list fn */ +static NTSTATUS query_user_list(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info) +{ + ADS_STRUCT *ads = NULL; + const char *attrs[] = { "*", NULL }; + int i, count; + ADS_STATUS rc; + LDAPMessage *res = NULL; + LDAPMessage *msg = NULL; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + + *num_entries = 0; + + DEBUG(3,("ads: query_user_list\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("query_user_list: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); + if (!ADS_ERR_OK(rc) || !res) { + DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); + goto done; + } + + count = ads_count_replies(ads, res); + if (count == 0) { + DEBUG(1,("query_user_list: No users found\n")); + goto done; + } + + (*info) = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, count); + if (!*info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + i = 0; + + for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { + char *name, *gecos = NULL; + char *homedir = NULL; + char *shell = NULL; + uint32 group; + uint32 atype; + DOM_SID user_sid; + gid_t primary_gid = (gid_t)-1; + + if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || + ads_atype_map(atype) != SID_NAME_USER) { + DEBUG(1,("Not a user account? atype=0x%x\n", atype)); + continue; + } + + name = ads_pull_username(ads, mem_ctx, msg); + + if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) { + status = nss_get_info_cached( domain, &user_sid, mem_ctx, + ads, msg, &homedir, &shell, &gecos, + &primary_gid ); + } + + if (gecos == NULL) { + gecos = ads_pull_string(ads, mem_ctx, msg, "name"); + } + + if (!ads_pull_sid(ads, msg, "objectSid", + &(*info)[i].user_sid)) { + DEBUG(1,("No sid for %s !?\n", name)); + continue; + } + if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) { + DEBUG(1,("No primary group for %s !?\n", name)); + continue; + } + + (*info)[i].acct_name = name; + (*info)[i].full_name = gecos; + (*info)[i].homedir = homedir; + (*info)[i].shell = shell; + (*info)[i].primary_gid = primary_gid; + sid_compose(&(*info)[i].group_sid, &domain->sid, group); + i++; + } + + (*num_entries) = i; + status = NT_STATUS_OK; + + DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries))); + +done: + if (res) + ads_msgfree(ads, res); + + return status; +} + +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + ADS_STRUCT *ads = NULL; + const char *attrs[] = {"userPrincipalName", "sAMAccountName", + "name", "objectSid", NULL}; + int i, count; + ADS_STATUS rc; + LDAPMessage *res = NULL; + LDAPMessage *msg = NULL; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + const char *filter; + BOOL enum_dom_local_groups = False; + + *num_entries = 0; + + DEBUG(3,("ads: enum_dom_groups\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + /* only grab domain local groups for our domain */ + if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) { + enum_dom_local_groups = True; + } + + /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o + * rollup-fixes: + * + * According to Section 5.1(4) of RFC 2251 if a value of a type is it's + * default value, it MUST be absent. In case of extensible matching the + * "dnattr" boolean defaults to FALSE and so it must be only be present + * when set to TRUE. + * + * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a + * filter using bitwise matching rule then the buggy AD fails to decode + * the extensible match. As a workaround set it to TRUE and thereby add + * the dnAttributes "dn" field to cope with those older AD versions. + * It should not harm and won't put any additional load on the AD since + * none of the dn components have a bitmask-attribute. + * + * Thanks to Ralf Haferkamp for input and testing - Guenther */ + + filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))", + ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED, + ADS_LDAP_MATCHING_RULE_BIT_AND, + enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP); + + if (filter == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + rc = ads_search_retry(ads, &res, filter, attrs); + if (!ADS_ERR_OK(rc) || !res) { + DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); + goto done; + } + + count = ads_count_replies(ads, res); + if (count == 0) { + DEBUG(1,("enum_dom_groups: No groups found\n")); + goto done; + } + + (*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct acct_info, count); + if (!*info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + i = 0; + + for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { + char *name, *gecos; + DOM_SID sid; + uint32 rid; + + name = ads_pull_username(ads, mem_ctx, msg); + gecos = ads_pull_string(ads, mem_ctx, msg, "name"); + if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { + DEBUG(1,("No sid for %s !?\n", name)); + continue; + } + + if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { + DEBUG(1,("No rid for %s !?\n", name)); + continue; + } + + fstrcpy((*info)[i].acct_name, name); + fstrcpy((*info)[i].acct_desc, gecos); + (*info)[i].rid = rid; + i++; + } + + (*num_entries) = i; + + status = NT_STATUS_OK; + + DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries))); + +done: + if (res) + ads_msgfree(ads, res); + + return status; +} + +/* list all domain local groups */ +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + /* + * This is a stub function only as we returned the domain + * local groups in enum_dom_groups() if the domain->native field + * was true. This is a simple performance optimization when + * using LDAP. + * + * if we ever need to enumerate domain local groups separately, + * then this the optimization in enum_dom_groups() will need + * to be split out + */ + *num_entries = 0; + + return NT_STATUS_OK; +} + +/* If you are looking for "dn_lookup": Yes, it used to be here! + * It has gone now since it was a major speed bottleneck in + * lookup_groupmem (its only use). It has been replaced by + * an rpc lookup sids call... R.I.P. */ + +/* Lookup user information from a rid */ +static NTSTATUS query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + WINBIND_USERINFO *info) +{ + ADS_STRUCT *ads = NULL; + const char *attrs[] = { "*", NULL }; + ADS_STATUS rc; + int count; + LDAPMessage *msg = NULL; + char *ldap_exp; + char *sidstr; + uint32 group_rid; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + NET_USER_INFO_3 *user; + + DEBUG(3,("ads: query_user\n")); + + info->homedir = NULL; + info->shell = NULL; + info->primary_gid = (gid_t)-1; + + /* try netsamlogon cache first */ + + if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL ) + { + + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(sid))); + + sid_compose(&info->user_sid, &domain->sid, user->user_rid); + sid_compose(&info->group_sid, &domain->sid, user->group_rid); + + info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name); + info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name); + + nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, + &info->homedir, &info->shell, &info->full_name, + &info->primary_gid ); + + TALLOC_FREE(user); + + return NT_STATUS_OK; + } + + if ( !winbindd_can_contact_domain(domain)) { + DEBUG(8,("query_user: No incoming trust from domain %s\n", + domain->name)); + + /* We still need to generate some basic information + about the user even if we cannot contact the + domain. Most of this stuff we can deduce. */ + + sid_copy( &info->user_sid, sid ); + + /* Assume "Domain Users" for the primary group */ + + sid_compose(&info->group_sid, &domain->sid, DOMAIN_GROUP_RID_USERS ); + + /* Try to fill in what the nss_info backend can do */ + + nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, + &info->homedir, &info->shell, &info->full_name, + &info->primary_gid ); + + status = NT_STATUS_OK; + goto done; + } + + /* no cache...do the query */ + + if ( (ads = ads_cached_connection(domain)) == NULL ) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + sidstr = sid_binstring(sid); + asprintf(&ldap_exp, "(objectSid=%s)", sidstr); + rc = ads_search_retry(ads, &msg, ldap_exp, attrs); + free(ldap_exp); + free(sidstr); + if (!ADS_ERR_OK(rc) || !msg) { + DEBUG(1,("query_user(sid=%s) ads_search: %s\n", + sid_string_static(sid), ads_errstr(rc))); + goto done; + } + + count = ads_count_replies(ads, msg); + if (count != 1) { + DEBUG(1,("query_user(sid=%s): Not found\n", + sid_string_static(sid))); + goto done; + } + + info->acct_name = ads_pull_username(ads, mem_ctx, msg); + + nss_get_info_cached( domain, sid, mem_ctx, ads, msg, + &info->homedir, &info->shell, &info->full_name, + &info->primary_gid ); + + if (info->full_name == NULL) { + info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); + } + + if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { + DEBUG(1,("No primary group for %s !?\n", + sid_string_static(sid))); + goto done; + } + + sid_copy(&info->user_sid, sid); + sid_compose(&info->group_sid, &domain->sid, group_rid); + + status = NT_STATUS_OK; + + DEBUG(3,("ads query_user gave %s\n", info->acct_name)); +done: + if (msg) + ads_msgfree(ads, msg); + + return status; +} + +/* Lookup groups a user is a member of - alternate method, for when + tokenGroups are not available. */ +static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user_dn, + DOM_SID *primary_group, + size_t *p_num_groups, DOM_SID **user_sids) +{ + ADS_STATUS rc; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + int count; + LDAPMessage *res = NULL; + LDAPMessage *msg = NULL; + char *ldap_exp; + ADS_STRUCT *ads; + const char *group_attrs[] = {"objectSid", NULL}; + char *escaped_dn; + size_t num_groups = 0; + + DEBUG(3,("ads: lookup_usergroups_member\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + ldap_exp = talloc_asprintf(mem_ctx, + "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))", + escaped_dn, + ADS_LDAP_MATCHING_RULE_BIT_AND, + GROUP_TYPE_SECURITY_ENABLED); + if (!ldap_exp) { + DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); + SAFE_FREE(escaped_dn); + status = NT_STATUS_NO_MEMORY; + goto done; + } + + SAFE_FREE(escaped_dn); + + rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); + + if (!ADS_ERR_OK(rc) || !res) { + DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); + return ads_ntstatus(rc); + } + + count = ads_count_replies(ads, res); + + *user_sids = NULL; + num_groups = 0; + + /* always add the primary group to the sid array */ + if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + if (count > 0) { + for (msg = ads_first_entry(ads, res); msg; + msg = ads_next_entry(ads, msg)) { + DOM_SID group_sid; + + if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) { + DEBUG(1,("No sid for this group ?!?\n")); + continue; + } + + /* ignore Builtin groups from ADS - Guenther */ + if (sid_check_is_in_builtin(&group_sid)) { + continue; + } + + if (!add_sid_to_array(mem_ctx, &group_sid, user_sids, + &num_groups)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + } + + } + + *p_num_groups = num_groups; + status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; + + DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn)); +done: + if (res) + ads_msgfree(ads, res); + + return status; +} + +/* Lookup groups a user is a member of - alternate method, for when + tokenGroups are not available. */ +static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user_dn, + DOM_SID *primary_group, + size_t *p_num_groups, DOM_SID **user_sids) +{ + ADS_STATUS rc; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + ADS_STRUCT *ads; + const char *attrs[] = {"memberOf", NULL}; + size_t num_groups = 0; + DOM_SID *group_sids = NULL; + int i; + char **strings; + size_t num_strings = 0; + + + DEBUG(3,("ads: lookup_usergroups_memberof\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("lookup_usergroups_memberof: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs, + ADS_EXTENDED_DN_HEX_STRING, + &strings, &num_strings); + + if (!ADS_ERR_OK(rc)) { + DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n", + user_dn, ads_errstr(rc))); + return ads_ntstatus(rc); + } + + *user_sids = NULL; + num_groups = 0; + + /* always add the primary group to the sid array */ + if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + group_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_strings + 1); + if (!group_sids) { + TALLOC_FREE(strings); + status = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0; iname)); + + /* Tell the cache manager not to remember this one */ + + return NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + rc = ads_search_retry_sid(ads, &msg, sid, attrs); + + if (!ADS_ERR_OK(rc)) { + status = ads_ntstatus(rc); + DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", + sid_to_string(sid_string, sid), ads_errstr(rc))); + goto done; + } + + count = ads_count_replies(ads, msg); + if (count != 1) { + status = NT_STATUS_UNSUCCESSFUL; + DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: " + "invalid number of results (count=%d)\n", + sid_to_string(sid_string, sid), count)); + goto done; + } + + if (!msg) { + DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n", + sid_to_string(sid_string, sid))); + status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + user_dn = ads_get_dn(ads, msg); + if (user_dn == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) { + DEBUG(1,("%s: No primary group for sid=%s !?\n", + domain->name, sid_to_string(sid_string, sid))); + goto done; + } + + sid_copy(&primary_group, &domain->sid); + sid_append_rid(&primary_group, primary_group_rid); + + count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); + + /* there must always be at least one group in the token, + unless we are talking to a buggy Win2k server */ + + /* actually this only happens when the machine account has no read + * permissions on the tokenGroup attribute - gd */ + + if (count == 0) { + + /* no tokenGroups */ + + /* lookup what groups this user is a member of by DN search on + * "memberOf" */ + + status = lookup_usergroups_memberof(domain, mem_ctx, user_dn, + &primary_group, + &num_groups, user_sids); + *p_num_groups = (uint32)num_groups; + if (NT_STATUS_IS_OK(status)) { + goto done; + } + + /* lookup what groups this user is a member of by DN search on + * "member" */ + + status = lookup_usergroups_member(domain, mem_ctx, user_dn, + &primary_group, + &num_groups, user_sids); + *p_num_groups = (uint32)num_groups; + goto done; + } + + *user_sids = NULL; + num_groups = 0; + + if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0;iname, + sid_string_static(group_sid))); + + *num_names = 0; + + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto done; + } + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } + + if ((sidbinstr = sid_binstring(group_sid)) == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + /* search for all members of the group */ + if (!(ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", + sidbinstr))) + { + SAFE_FREE(sidbinstr); + DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n")); + status = NT_STATUS_NO_MEMORY; + goto done; + } + SAFE_FREE(sidbinstr); + + args.control = ADS_EXTENDED_DN_OID; + args.val = ADS_EXTENDED_DN_HEX_STRING; + args.critical = True; + + rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path, + ldap_exp, &args, "member", &members, &num_members); + + if (!ADS_ERR_OK(rc)) { + DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc))); + status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members)); + + /* Now that we have a list of sids, we need to get the + * lists of names and name_types belonging to these sids. + * even though conceptually not quite clean, we use the + * RPC call lsa_lookup_sids for this since it can handle a + * list of sids. ldap calls can just resolve one sid at a time. + * + * At this stage, the sids are still hidden in the exetended dn + * member output format. We actually do a little better than + * stated above: In extracting the sids from the member strings, + * we try to resolve as many sids as possible from the + * cache. Only the rest is passed to the lsa_lookup_sids call. */ + + if (num_members) { + (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members); + (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members); + (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members); + (sid_mem_nocache) = TALLOC_ZERO_ARRAY(tmp_ctx, DOM_SID, num_members); + + if ((members == NULL) || (*sid_mem == NULL) || + (*names == NULL) || (*name_types == NULL) || + (sid_mem_nocache == NULL)) + { + DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto done; + } + } + else { + (*sid_mem) = NULL; + (*names) = NULL; + (*name_types) = NULL; + } + + for (i=0; i 0) { + + status = cm_connect_lsa(domain, tmp_ctx, &cli, &lsa_policy); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_lsa_lookup_sids_all(cli, tmp_ctx, + &lsa_policy, + num_nocache, + sid_mem_nocache, + &domains_nocache, + &names_nocache, + &name_types_nocache); + + if (NT_STATUS_IS_OK(status) || + NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) + { + /* Copy the entries over from the "_nocache" arrays + * to the result arrays, skipping the gaps the + * lookup_sids call left. */ + for (i=0; i < num_nocache; i++) { + if (((names_nocache)[i] != NULL) && + ((name_types_nocache)[i] != SID_NAME_UNKNOWN)) + { + sid_copy(&(*sid_mem)[*num_names], + &sid_mem_nocache[i]); + (*names)[*num_names] = talloc_asprintf( *names, + "%s%c%s", + domains_nocache[i], + *lp_winbind_separator(), + names_nocache[i] ); + (*name_types)[*num_names] = name_types_nocache[i]; + (*num_names)++; + } + } + } + else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { + DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could " + "not map any SIDs at all.\n")); + /* Don't handle this as an error here. + * There is nothing left to do with respect to the + * overall result... */ + } + else if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("lookup_groupmem: Error looking up %d " + "sids via rpc_lsa_lookup_sids: %s\n", + (int)num_members, nt_errstr(status))); + goto done; + } + } + + status = NT_STATUS_OK; + DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n", + sid_string_static(group_sid))); + +done: + + TALLOC_FREE(tmp_ctx); + + return status; +} + +/* find the sequence number for a domain */ +static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) +{ + ADS_STRUCT *ads = NULL; + ADS_STATUS rc; + + DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name)); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("sequence: No incoming trust for domain %s\n", + domain->name)); + *seq = time(NULL); + return NT_STATUS_OK; + } + + *seq = DOM_SEQUENCE_NONE; + + ads = ads_cached_connection(domain); + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + return NT_STATUS_UNSUCCESSFUL; + } + + rc = ads_USN(ads, seq); + + if (!ADS_ERR_OK(rc)) { + + /* its a dead connection, destroy it */ + + if (domain->private_data) { + ads = (ADS_STRUCT *)domain->private_data; + ads->is_mine = True; + ads_destroy(&ads); + ads_kdestroy("MEMORY:winbind_ccache"); + domain->private_data = NULL; + } + } + return ads_ntstatus(rc); +} + +/* get a list of trusted domains */ +static NTSTATUS trusted_domains(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + char ***names, + char ***alt_names, + DOM_SID **dom_sids) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + struct ds_domain_trust *domains = NULL; + int count = 0; + int i; + uint32 flags; + struct rpc_pipe_client *cli; + uint32 fr_flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_TREE_ROOT); + int ret_count; + + DEBUG(3,("ads: trusted_domains\n")); + + *num_domains = 0; + *alt_names = NULL; + *names = NULL; + *dom_sids = NULL; + + /* If this is our primary domain or a root in our forest, + query for all trusts. If not, then just look for domain + trusts in the target forest */ + + if ( domain->primary || + ((domain->domain_flags&fr_flags) == fr_flags) ) + { + flags = DS_DOMAIN_DIRECT_OUTBOUND | + DS_DOMAIN_DIRECT_INBOUND | + DS_DOMAIN_IN_FOREST; + } else { + flags = DS_DOMAIN_IN_FOREST; + } + + result = cm_connect_netlogon(domain, &cli); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(5, ("trusted_domains: Could not open a connection to %s " + "for PIPE_NETLOGON (%s)\n", + domain->name, nt_errstr(result))); + return NT_STATUS_UNSUCCESSFUL; + } + + if ( NT_STATUS_IS_OK(result) ) { + result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, + cli->cli->desthost, + flags, &domains, + (unsigned int *)&count); + } + + if ( NT_STATUS_IS_OK(result) && count) { + + /* Allocate memory for trusted domain names and sids */ + + if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + return NT_STATUS_NO_MEMORY; + } + + if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + return NT_STATUS_NO_MEMORY; + } + + if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + return NT_STATUS_NO_MEMORY; + } + + /* Copy across names and sids */ + + + ret_count = 0; + for (i = 0; i < count; i++) { + struct winbindd_domain d; + + /* drop external trusts if this is not our primary + domain. This means that the returned number of + domains may be less that the ones actually trusted + by the DC. */ + + if ( (domains[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) && + !domain->primary ) + { + DEBUG(10,("trusted_domains: Skipping external trusted domain " + "%s because it is outside of our primary domain\n", + domains[i].netbios_domain)); + continue; + } + + (*names)[ret_count] = domains[i].netbios_domain; + (*alt_names)[ret_count] = domains[i].dns_domain; + sid_copy(&(*dom_sids)[ret_count], &domains[i].sid); + + /* add to the trusted domain cache */ + + fstrcpy( d.name, domains[i].netbios_domain ); + fstrcpy( d.alt_name, domains[i].dns_domain ); + sid_copy( &d.sid, &domains[i].sid ); + + /* This gets a little tricky. If we are + following a transitive forest trust, then + innerit the flags, type, and attrins from + the domain we queried to make sure we don't + record the view of the trust from the wrong + side. Always view it from the side of our + primary domain. --jerry */ + if ( domain->primary || + ((domain->domain_flags&fr_flags) == fr_flags) ) + { + DEBUG(10,("trusted_domains(ads): Storing trust " + "flags for domain %s\n", d.alt_name)); + + /* Look this up in cache to make sure + we have the current trust flags and + attributes */ + + d.domain_flags = domains[i].flags; + d.domain_type = domains[i].trust_type; + d.domain_trust_attribs = domains[i].trust_attributes; + } else { + DEBUG(10,("trusted_domains(ads): Inheriting trust " + "flags for domain %s\n", d.alt_name)); + d.domain_flags = domain->domain_flags; + d.domain_type = domain->domain_type; + d.domain_trust_attribs = domain->domain_trust_attribs; + } + + wcache_tdc_add_domain( &d ); + + ret_count++; + + } + + *num_domains = ret_count; + } + + return result; +} + +/* the ADS backend methods are exposed via this structure */ +struct winbindd_methods ads_methods = { + True, + query_user_list, + enum_dom_groups, + enum_local_groups, + msrpc_name_to_sid, + msrpc_sid_to_name, + msrpc_rids_to_names, + query_user, + lookup_usergroups, + msrpc_lookup_useraliases, + lookup_groupmem, + sequence_number, + msrpc_lockout_policy, + msrpc_password_policy, + trusted_domains, +}; + +#endif diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c new file mode 100644 index 0000000000..5d31ff0a41 --- /dev/null +++ b/source3/winbindd/winbindd_async.c @@ -0,0 +1,1695 @@ +/* + Unix SMB/CIFS implementation. + + Async helpers for blocking functions + + Copyright (C) Volker Lendecke 2005 + Copyright (C) Gerald Carter 2006 + + The helpers always consist of three functions: + + * A request setup function that takes the necessary parameters together + with a continuation function that is to be called upon completion + + * A private continuation function that is internal only. This is to be + called by the lower-level functions in do_async(). Its only task is to + properly call the continuation function named above. + + * A worker function that is called inside the appropriate child process. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +struct do_async_state { + TALLOC_CTX *mem_ctx; + struct winbindd_request request; + struct winbindd_response response; + void (*cont)(TALLOC_CTX *mem_ctx, + BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + void *c, *private_data; +}; + +static void do_async_recv(void *private_data, BOOL success) +{ + struct do_async_state *state = + talloc_get_type_abort(private_data, struct do_async_state); + + state->cont(state->mem_ctx, success, &state->response, + state->c, state->private_data); +} + +static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) +{ + struct do_async_state *state; + + state = TALLOC_ZERO_P(mem_ctx, struct do_async_state); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + cont(mem_ctx, False, NULL, c, private_data); + return; + } + + state->mem_ctx = mem_ctx; + state->request = *request; + state->request.length = sizeof(state->request); + state->cont = cont; + state->c = c; + state->private_data = private_data; + + async_request(mem_ctx, child, &state->request, + &state->response, do_async_recv, state); +} + +void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) +{ + struct do_async_state *state; + + state = TALLOC_ZERO_P(mem_ctx, struct do_async_state); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + cont(mem_ctx, False, NULL, c, private_data); + return; + } + + state->mem_ctx = mem_ctx; + state->request = *request; + state->request.length = sizeof(state->request); + state->cont = cont; + state->c = c; + state->private_data = private_data; + + async_domain_request(mem_ctx, domain, &state->request, + &state->response, do_async_recv, state); +} + +static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_mapping\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_mapping returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_MAPPING; + request.data.dual_idmapset.id = map->xid.id; + request.data.dual_idmapset.type = map->xid.type; + sid_to_string(request.data.dual_idmapset.sid, map->sid); + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct id_map map; + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); + + if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) + return WINBINDD_ERROR; + + map.sid = &sid; + map.xid.id = state->request.data.dual_idmapset.id; + map.xid.type = state->request.data.dual_idmapset.type; + map.status = ID_MAPPED; + + result = idmap_set_mapping(&map); + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_hwm\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_hwm returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_HWM; + request.data.dual_idmapset.id = xid->id; + request.data.dual_idmapset.type = xid->type; + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); + + xid.id = state->request.data.dual_idmapset.id; + xid.type = state->request.data.dual_idmapset.type; + + switch (xid.type) { + case ID_TYPE_UID: + result = idmap_set_uid_hwm(&xid); + break; + case ID_TYPE_GID: + result = idmap_set_gid_hwm(&xid); + break; + default: + return WINBINDD_ERROR; + } + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, void *, int) = + (void (*)(void *, BOOL, void *, int))c; + + if (!success) { + DEBUG(5, ("Could not trigger sids2xids\n")); + cont(private_data, False, NULL, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sids2xids returned an error\n")); + cont(private_data, False, NULL, 0); + return; + } + + cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); +} + +void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, + void (*cont)(void *private_data, BOOL success, void *data, int len), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SIDS2XIDS; + request.extra_data.data = (char *)sids; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID *sids; + struct unixid *xids; + struct id_map **ids; + NTSTATUS result; + int num, i; + + DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); + + if (state->request.extra_len == 0) { + DEBUG(0, ("Invalid buffer size!\n")); + return WINBINDD_ERROR; + } + + sids = (DOM_SID *)state->request.extra_data.data; + num = state->request.extra_len / sizeof(DOM_SID); + + ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); + if ( ! ids) { + DEBUG(0, ("Out of memory!\n")); + return WINBINDD_ERROR; + } + for (i = 0; i < num; i++) { + ids[i] = TALLOC_P(ids, struct id_map); + if ( ! ids[i]) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + ids[i]->sid = &sids[i]; + } + + result = idmap_sids_to_unixids(ids); + + if (NT_STATUS_IS_OK(result)) { + + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } + } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; + + } else { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; + } + + talloc_free(ids); + return WINBINDD_OK; +} + +static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} + +void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2UID; + sid_to_string(request.data.dual_sid2id.sid, sid); + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2NAME; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, uid2name_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + pw = getpwuid(state->request.data.uid); + if (pw == NULL) { + DEBUG(5, ("User %lu not found\n", + (unsigned long)state->request.data.uid)); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.name.name, pw->pw_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2UID; + fstrcpy(request.data.username, name); + do_async(mem_ctx, idmap_child(), &request, name2uid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + /* Ensure null termination */ + state->request.data.username + [sizeof(state->request.data.username)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, + state->request.data.username)); + + pw = getpwnam(state->request.data.username); + if (pw == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.uid = pw->pw_uid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} +#endif /* not used */ + +static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} + +void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2GID; + sid_to_string(request.data.dual_sid2id.sid, sid); + + DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", + request.data.dual_sid2id.sid)); + + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find gid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_gid(&sid, &state->response.data.gid); + + DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2NAME; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, gid2name_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + gr = getgrgid(state->request.data.gid); + if (gr == NULL) + return WINBINDD_ERROR; + + fstrcpy(state->response.data.name.name, gr->gr_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2GID; + fstrcpy(request.data.groupname, name); + do_async(mem_ctx, idmap_child(), &request, name2gid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + /* Ensure null termination */ + state->request.data.groupname + [sizeof(state->request.data.groupname)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, + state->request.data.groupname)); + + gr = getgrnam(state->request.data.groupname); + if (gr == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.gid = gr->gr_gid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} +#endif /* not used */ + +struct lookupsid_state { + DOM_SID sid; + void *caller_private_data; +}; + + +static void lookupsid_recv2(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *dom_name, + const char *name, enum lsa_SidType type) = + (void (*)(void *, BOOL, const char *, const char *, + enum lsa_SidType))c; + struct lookupsid_state *s = talloc_get_type_abort(private_data, + struct lookupsid_state); + + if (!success) { + DEBUG(5, ("Could not trigger lookupsid\n")); + cont(s->caller_private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("lookupsid (forest root) returned an error\n")); + cont(s->caller_private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + cont(s->caller_private_data, True, response->data.name.dom_name, + response->data.name.name, + (enum lsa_SidType)response->data.name.type); +} + +static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *dom_name, + const char *name, enum lsa_SidType type) = + (void (*)(void *, BOOL, const char *, const char *, + enum lsa_SidType))c; + struct lookupsid_state *s = talloc_get_type_abort(private_data, + struct lookupsid_state); + + if (!success) { + DEBUG(5, ("Could not trigger lookupsid\n")); + cont(s->caller_private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + if (response->result != WINBINDD_OK) { + /* Try again using the forest root */ + struct winbindd_domain *root_domain = find_root_domain(); + struct winbindd_request request; + + if ( !root_domain ) { + DEBUG(5,("lookupsid_recv: unable to determine forest root\n")); + cont(s->caller_private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LOOKUPSID; + fstrcpy(request.data.sid, sid_string_static(&s->sid)); + + do_async_domain(mem_ctx, root_domain, &request, lookupsid_recv2, + (void *)cont, s); + + return; + } + + cont(s->caller_private_data, True, response->data.name.dom_name, + response->data.name.name, + (enum lsa_SidType)response->data.name.type); +} + +void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, + const char *dom_name, + const char *name, + enum lsa_SidType type), + void *private_data) +{ + struct winbindd_domain *domain; + struct winbindd_request request; + struct lookupsid_state *s; + + domain = find_lookup_domain_from_sid(sid); + if (domain == NULL) { + DEBUG(5, ("Could not find domain for sid %s\n", + sid_string_static(sid))); + cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LOOKUPSID; + fstrcpy(request.data.sid, sid_string_static(sid)); + + if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupsid_state)) == NULL ) { + DEBUG(0, ("winbindd_lookupsid_async: talloc failed\n")); + cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN); + return; + } + + sid_copy( &s->sid, sid ); + s->caller_private_data = private_data; + + do_async_domain(mem_ctx, domain, &request, lookupsid_recv, + (void *)cont, s); +} + +enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + enum lsa_SidType type; + DOM_SID sid; + char *name; + char *dom_name; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, + state->request.data.sid)); + + /* Lookup sid from PDC using lsa_lookup_sids() */ + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(5, ("%s not a SID\n", state->request.data.sid)); + return WINBINDD_ERROR; + } + + /* Lookup the sid */ + + if (!winbindd_lookup_name_by_sid(state->mem_ctx, domain, &sid, + &dom_name, &name, &type)) + { + TALLOC_FREE(dom_name); + TALLOC_FREE(name); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.name.dom_name, dom_name); + fstrcpy(state->response.data.name.name, name); + state->response.data.name.type = type; + + TALLOC_FREE(dom_name); + TALLOC_FREE(name); + return WINBINDD_OK; +} + +/******************************************************************** + This is the second callback after contacting the forest root +********************************************************************/ + +struct lookupname_state { + char *dom_name; + char *name; + void *caller_private_data; +}; + + +static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, + enum lsa_SidType type) = + (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; + DOM_SID sid; + struct lookupname_state *s = talloc_get_type_abort( private_data, + struct lookupname_state ); + + + if (!success) { + DEBUG(5, ("Could not trigger lookup_name\n")); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("lookup_name returned an error\n")); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + if (!string_to_sid(&sid, response->data.sid.sid)) { + DEBUG(0, ("Could not convert string %s to sid\n", + response->data.sid.sid)); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + cont(s->caller_private_data, True, &sid, + (enum lsa_SidType)response->data.sid.type); +} + +/******************************************************************** + This is the first callback after contacting our own domain +********************************************************************/ + +static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, + enum lsa_SidType type) = + (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; + DOM_SID sid; + struct lookupname_state *s = talloc_get_type_abort( private_data, + struct lookupname_state ); + + if (!success) { + DEBUG(5, ("lookupname_recv: lookup_name() failed!\n")); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + if (response->result != WINBINDD_OK) { + /* Try again using the forest root */ + struct winbindd_domain *root_domain = find_root_domain(); + struct winbindd_request request; + + if ( !root_domain ) { + DEBUG(5,("lookupname_recv: unable to determine forest root\n")); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LOOKUPNAME; + + fstrcpy( request.data.name.dom_name, s->dom_name ); + fstrcpy( request.data.name.name, s->name ); + + do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2, + (void *)cont, s); + + return; + } + + if (!string_to_sid(&sid, response->data.sid.sid)) { + DEBUG(0, ("Could not convert string %s to sid\n", + response->data.sid.sid)); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + cont(s->caller_private_data, True, &sid, + (enum lsa_SidType)response->data.sid.type); +} + +/******************************************************************** + The lookup name call first contacts a DC in its own domain + and fallbacks to contact a DC in the forest in our domain doesn't + know the name. +********************************************************************/ + +void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, + const char *dom_name, const char *name, + void (*cont)(void *private_data, BOOL success, + const DOM_SID *sid, + enum lsa_SidType type), + enum winbindd_cmd orig_cmd, + void *private_data) +{ + struct winbindd_request request; + struct winbindd_domain *domain; + struct lookupname_state *s; + + if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) { + DEBUG(5, ("Could not find domain for name %s\n", dom_name)); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LOOKUPNAME; + request.original_cmd = orig_cmd; + fstrcpy(request.data.name.dom_name, dom_name); + fstrcpy(request.data.name.name, name); + + if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupname_state)) == NULL ) { + DEBUG(0, ("winbindd_lookupname_async: talloc failed\n")); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + s->dom_name = talloc_strdup( s, dom_name ); + s->name = talloc_strdup( s, name ); + s->caller_private_data = private_data; + + do_async_domain(mem_ctx, domain, &request, lookupname_recv, + (void *)cont, s); +} + +enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + enum lsa_SidType type; + char *name_domain, *name_user; + DOM_SID sid; + char *p; + + /* Ensure null termination */ + state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0'; + + /* Ensure null termination */ + state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0'; + + /* cope with the name being a fully qualified name */ + p = strstr(state->request.data.name.name, lp_winbind_separator()); + if (p) { + *p = 0; + name_domain = state->request.data.name.name; + name_user = p+1; + } else { + name_domain = state->request.data.name.dom_name; + name_user = state->request.data.name.name; + } + + DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, + name_domain, lp_winbind_separator(), name_user)); + + /* Lookup name from DC using lsa_lookup_names() */ + if (!winbindd_lookup_sid_by_name(state->mem_ctx, state->request.original_cmd, domain, name_domain, + name_user, &sid, &type)) { + return WINBINDD_ERROR; + } + + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = type; + + return WINBINDD_OK; +} + +BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, + size_t num_sids, char **result, ssize_t *len) +{ + size_t i; + size_t buflen = 0; + + *len = 0; + *result = NULL; + for (i=0; irequest.domain_name, + state->request.data.sid)); + + if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data, + &rids, &num_rids)) { + DEBUG(5, ("Could not parse ridlist\n")); + return WINBINDD_ERROR; + } + + if (!string_to_sid(&domain_sid, state->request.data.sid)) { + DEBUG(5, ("Could not parse domain sid %s\n", + state->request.data.sid)); + return WINBINDD_ERROR; + } + + status = domain->methods->rids_to_names(domain, state->mem_ctx, + &domain_sid, rids, num_rids, + &domain_name, + &names, &types); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) { + return WINBINDD_ERROR; + } + + len = 0; + buflen = 0; + result = NULL; + + for (i=0; imem_ctx, &result, &len, &buflen, + "%d %s\n", types[i], names[i]); + } + + fstrcpy(state->response.data.domain_name, domain_name); + + if (result != NULL) { + state->response.extra_data.data = SMB_STRDUP(result); + if (!state->response.extra_data.data) { + return WINBINDD_ERROR; + } + state->response.length += len+1; + } + + return WINBINDD_OK; +} + +static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, + DOM_SID *aliases, size_t num_aliases) = + (void (*)(void *, BOOL, DOM_SID *, size_t))c; + char *aliases_str; + DOM_SID *sids = NULL; + size_t num_sids = 0; + + if (!success) { + DEBUG(5, ("Could not trigger getsidaliases\n")); + cont(private_data, success, NULL, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("getsidaliases returned an error\n")); + cont(private_data, False, NULL, 0); + return; + } + + aliases_str = (char *)response->extra_data.data; + + if (aliases_str == NULL) { + DEBUG(10, ("getsidaliases return 0 SIDs\n")); + cont(private_data, True, NULL, 0); + return; + } + + if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) { + DEBUG(0, ("Could not parse sids\n")); + cont(private_data, False, NULL, 0); + return; + } + + SAFE_FREE(response->extra_data.data); + + cont(private_data, True, sids, num_sids); +} + +void winbindd_getsidaliases_async(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sids, size_t num_sids, + void (*cont)(void *private_data, + BOOL success, + const DOM_SID *aliases, + size_t num_aliases), + void *private_data) +{ + struct winbindd_request request; + char *sidstr = NULL; + ssize_t len; + + if (num_sids == 0) { + cont(private_data, True, NULL, 0); + return; + } + + if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) { + cont(private_data, False, NULL, 0); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GETSIDALIASES; + request.extra_len = len; + request.extra_data.data = sidstr; + + do_async_domain(mem_ctx, domain, &request, getsidaliases_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID *sids = NULL; + size_t num_sids = 0; + char *sidstr = NULL; + ssize_t len; + size_t i; + uint32 num_aliases; + uint32 *alias_rids; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid)); + + sidstr = state->request.extra_data.data; + if (sidstr == NULL) { + sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */ + if (!sidstr) { + DEBUG(0, ("Out of memory\n")); + return WINBINDD_ERROR; + } + } + + DEBUG(10, ("Sidlist: %s\n", sidstr)); + + if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) { + DEBUG(0, ("Could not parse SID list: %s\n", sidstr)); + return WINBINDD_ERROR; + } + + num_aliases = 0; + alias_rids = NULL; + + result = domain->methods->lookup_useraliases(domain, + state->mem_ctx, + num_sids, sids, + &num_aliases, + &alias_rids); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("Could not lookup_useraliases: %s\n", + nt_errstr(result))); + return WINBINDD_ERROR; + } + + num_sids = 0; + sids = NULL; + sidstr = NULL; + + DEBUG(10, ("Got %d aliases\n", num_aliases)); + + for (i=0; isid); + sid_append_rid(&sid, alias_rids[i]); + if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) { + return WINBINDD_ERROR; + } + } + + + if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) { + DEBUG(0, ("Could not print_sidlist\n")); + state->response.extra_data.data = NULL; + return WINBINDD_ERROR; + } + + state->response.extra_data.data = NULL; + + if (sidstr) { + state->response.extra_data.data = SMB_STRDUP(sidstr); + if (!state->response.extra_data.data) { + DEBUG(0, ("Out of memory\n")); + return WINBINDD_ERROR; + } + DEBUG(10, ("aliases_list: %s\n", + (char *)state->response.extra_data.data)); + state->response.length += len+1; + } + + return WINBINDD_OK; +} + +struct gettoken_state { + TALLOC_CTX *mem_ctx; + DOM_SID user_sid; + struct winbindd_domain *alias_domain; + struct winbindd_domain *local_alias_domain; + struct winbindd_domain *builtin_domain; + DOM_SID *sids; + size_t num_sids; + void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids); + void *private_data; +}; + +static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); +static void gettoken_recvaliases(void *private_data, BOOL success, + const DOM_SID *aliases, + size_t num_aliases); + + +void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, + void (*cont)(void *private_data, BOOL success, + DOM_SID *sids, size_t num_sids), + void *private_data) +{ + struct winbindd_domain *domain; + struct winbindd_request request; + struct gettoken_state *state; + + state = TALLOC_ZERO_P(mem_ctx, struct gettoken_state); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + cont(private_data, False, NULL, 0); + return; + } + + state->mem_ctx = mem_ctx; + sid_copy(&state->user_sid, user_sid); + state->alias_domain = find_our_domain(); + state->local_alias_domain = find_domain_from_name( get_global_sam_name() ); + state->builtin_domain = find_builtin_domain(); + state->cont = cont; + state->private_data = private_data; + + domain = find_domain_from_sid_noinit(user_sid); + if (domain == NULL) { + DEBUG(5, ("Could not find domain from SID %s\n", + sid_string_static(user_sid))); + cont(private_data, False, NULL, 0); + return; + } + + ZERO_STRUCT(request); + request.cmd = WINBINDD_GETUSERDOMGROUPS; + fstrcpy(request.data.sid, sid_string_static(user_sid)); + + do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups, + NULL, state); +} + +static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + struct gettoken_state *state = + talloc_get_type_abort(private_data, struct gettoken_state); + char *sids_str; + + if (!success) { + DEBUG(10, ("Could not get domain groups\n")); + state->cont(state->private_data, False, NULL, 0); + return; + } + + sids_str = (char *)response->extra_data.data; + + if (sids_str == NULL) { + /* This could be normal if we are dealing with a + local user and local groups */ + + if ( !sid_check_is_in_our_domain( &state->user_sid ) ) { + DEBUG(10, ("Received no domain groups\n")); + state->cont(state->private_data, True, NULL, 0); + return; + } + } + + state->sids = NULL; + state->num_sids = 0; + + if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids, + &state->num_sids)) { + DEBUG(0, ("Out of memory\n")); + state->cont(state->private_data, False, NULL, 0); + return; + } + + if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids, + &state->num_sids)) { + DEBUG(0, ("Could not parse sids\n")); + state->cont(state->private_data, False, NULL, 0); + return; + } + + SAFE_FREE(response->extra_data.data); + + if (state->alias_domain == NULL) { + DEBUG(10, ("Don't expand domain local groups\n")); + state->cont(state->private_data, True, state->sids, + state->num_sids); + return; + } + + winbindd_getsidaliases_async(state->alias_domain, mem_ctx, + state->sids, state->num_sids, + gettoken_recvaliases, state); +} + +static void gettoken_recvaliases(void *private_data, BOOL success, + const DOM_SID *aliases, + size_t num_aliases) +{ + struct gettoken_state *state = (struct gettoken_state *)private_data; + size_t i; + + if (!success) { + DEBUG(10, ("Could not receive domain local groups\n")); + state->cont(state->private_data, False, NULL, 0); + return; + } + + for (i=0; imem_ctx, &aliases[i], + &state->sids, &state->num_sids)) { + DEBUG(0, ("Out of memory\n")); + state->cont(state->private_data, False, NULL, 0); + return; + } + } + + if (state->local_alias_domain != NULL) { + struct winbindd_domain *local_domain = state->local_alias_domain; + DEBUG(10, ("Expanding our own local groups\n")); + state->local_alias_domain = NULL; + winbindd_getsidaliases_async(local_domain, state->mem_ctx, + state->sids, state->num_sids, + gettoken_recvaliases, state); + return; + } + + if (state->builtin_domain != NULL) { + struct winbindd_domain *builtin_domain = state->builtin_domain; + DEBUG(10, ("Expanding our own BUILTIN groups\n")); + state->builtin_domain = NULL; + winbindd_getsidaliases_async(builtin_domain, state->mem_ctx, + state->sids, state->num_sids, + gettoken_recvaliases, state); + return; + } + + state->cont(state->private_data, True, state->sids, state->num_sids); +} + +static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *acct_name, + const char *full_name, const char *homedir, + const char *shell, uint32 gid, uint32 group_rid) = + (void (*)(void *, BOOL, const char *, const char *, + const char *, const char *, uint32, uint32))c; + + if (!success) { + DEBUG(5, ("Could not trigger query_user\n")); + cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("query_user returned an error\n")); + cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1); + return; + } + + cont(private_data, True, response->data.user_info.acct_name, + response->data.user_info.full_name, + response->data.user_info.homedir, + response->data.user_info.shell, + response->data.user_info.primary_gid, + response->data.user_info.group_rid); +} + +void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, + const char *acct_name, + const char *full_name, + const char *homedir, + const char *shell, + gid_t gid, + uint32 group_rid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_USERINFO; + sid_to_string(request.data.sid, sid); + do_async_domain(mem_ctx, domain, &request, query_user_recv, + (void *)cont, private_data); +} + +/* The following uid2sid/gid2sid functions has been contributed by + * Keith Reynolds */ + +static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2SID; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: uid to sid %lu\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.uid)); + + /* Find sid for this uid and return it, possibly ask the slow remote idmap */ + result = idmap_uid_to_sid(&sid, state->request.data.uid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_USER; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2SID; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: gid %lu to sid\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.gid)); + + /* Find sid for this gid and return it, possibly ask the slow remote idmap */ + result = idmap_gid_to_sid(&sid, state->request.data.gid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + DEBUG(10, ("[%5lu]: retrieved sid: %s\n", + (unsigned long)state->pid, + state->response.data.sid.sid)); + state->response.data.sid.type = SID_NAME_DOM_GRP; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = + (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger a map dump\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap dump maps returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_DUMP_MAPS; + request.extra_data.data = (char *)data; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); + + idmap_dump_maps((char *)state->request.extra_data.data); + + return WINBINDD_OK; +} + diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c new file mode 100644 index 0000000000..e5090dfacf --- /dev/null +++ b/source3/winbindd/winbindd_cache.c @@ -0,0 +1,3892 @@ +/* + Unix SMB/CIFS implementation. + + Winbind cache backend functions + + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Gerald Carter 2003-2007 + Copyright (C) Volker Lendecke 2005 + Copyright (C) Guenther Deschner 2005 + Copyright (C) Michael Adam 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +#define WINBINDD_CACHE_VERSION 1 +#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION" + +extern struct winbindd_methods reconnect_methods; +extern BOOL opt_nocache; +#ifdef HAVE_ADS +extern struct winbindd_methods ads_methods; +#endif + +/* + * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES. + * Here are the list of entry types that are *not* stored + * as form struct cache_entry in the cache. + */ + +static const char *non_centry_keys[] = { + "SEQNUM/", + "DR/", + "DE/", + "WINBINDD_OFFLINE", + WINBINDD_CACHE_VERSION_KEYSTR, + NULL +}; + +/************************************************************************ + Is this key a non-centry type ? +************************************************************************/ + +static BOOL is_non_centry_key(TDB_DATA kbuf) +{ + int i; + + if (kbuf.dptr == NULL || kbuf.dsize == 0) { + return False; + } + for (i = 0; non_centry_keys[i] != NULL; i++) { + size_t namelen = strlen(non_centry_keys[i]); + if (kbuf.dsize < namelen) { + continue; + } + if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) { + return True; + } + } + return False; +} + +/* Global online/offline state - False when online. winbindd starts up online + and sets this to true if the first query fails and there's an entry in + the cache tdb telling us to stay offline. */ + +static BOOL global_winbindd_offline_state; + +struct winbind_cache { + TDB_CONTEXT *tdb; +}; + +struct cache_entry { + NTSTATUS status; + uint32 sequence_number; + uint8 *data; + uint32 len, ofs; +}; + +void (*smb_panic_fn)(const char *const why) = smb_panic; + +#define WINBINDD_MAX_CACHE_SIZE (50*1024*1024) + +static struct winbind_cache *wcache; + +void winbindd_check_cache_size(time_t t) +{ + static time_t last_check_time; + struct stat st; + + if (last_check_time == (time_t)0) + last_check_time = t; + + if (t - last_check_time < 60 && t - last_check_time > 0) + return; + + if (wcache == NULL || wcache->tdb == NULL) { + DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n")); + return; + } + + if (fstat(tdb_fd(wcache->tdb), &st) == -1) { + DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) )); + return; + } + + if (st.st_size > WINBINDD_MAX_CACHE_SIZE) { + DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n", + (unsigned long)st.st_size, + (unsigned long)WINBINDD_MAX_CACHE_SIZE)); + wcache_flush_cache(); + } +} + +/* get the winbind_cache structure */ +static struct winbind_cache *get_cache(struct winbindd_domain *domain) +{ + struct winbind_cache *ret = wcache; + + /* We have to know what type of domain we are dealing with first. */ + + if ( !domain->initialized ) { + init_dc_connection( domain ); + } + + /* + OK. listen up becasue I'm only going to say this once. + We have the following scenarios to consider + (a) trusted AD domains on a Samba DC, + (b) trusted AD domains and we are joined to a non-kerberos domain + (c) trusted AD domains and we are joined to a kerberos (AD) domain + + For (a) we can always contact the trusted domain using krb5 + since we have the domain trust account password + + For (b) we can only use RPC since we have no way of + getting a krb5 ticket in our own domain + + For (c) we can always use krb5 since we have a kerberos trust + + --jerry + */ + + if (!domain->backend) { +#ifdef HAVE_ADS + struct winbindd_domain *our_domain = domain; + + /* find our domain first so we can figure out if we + are joined to a kerberized domain */ + + if ( !domain->primary ) + our_domain = find_our_domain(); + + if ((our_domain->active_directory || IS_DC) + && domain->active_directory + && !lp_winbind_rpc_only()) { + DEBUG(5,("get_cache: Setting ADS methods for domain %s\n", domain->name)); + domain->backend = &ads_methods; + } else { +#endif /* HAVE_ADS */ + DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n", domain->name)); + domain->backend = &reconnect_methods; +#ifdef HAVE_ADS + } +#endif /* HAVE_ADS */ + } + + if (ret) + return ret; + + ret = SMB_XMALLOC_P(struct winbind_cache); + ZERO_STRUCTP(ret); + + wcache = ret; + wcache_flush_cache(); + + return ret; +} + +/* + free a centry structure +*/ +static void centry_free(struct cache_entry *centry) +{ + if (!centry) + return; + SAFE_FREE(centry->data); + free(centry); +} + +static BOOL centry_check_bytes(struct cache_entry *centry, size_t nbytes) +{ + if (centry->len - centry->ofs < nbytes) { + DEBUG(0,("centry corruption? needed %u bytes, have %d\n", + (unsigned int)nbytes, + centry->len - centry->ofs)); + return False; + } + return True; +} + +/* + pull a uint32 from a cache entry +*/ +static uint32 centry_uint32(struct cache_entry *centry) +{ + uint32 ret; + + if (!centry_check_bytes(centry, 4)) { + smb_panic_fn("centry_uint32"); + } + ret = IVAL(centry->data, centry->ofs); + centry->ofs += 4; + return ret; +} + +/* + pull a uint16 from a cache entry +*/ +static uint16 centry_uint16(struct cache_entry *centry) +{ + uint16 ret; + if (!centry_check_bytes(centry, 2)) { + smb_panic_fn("centry_uint16"); + } + ret = CVAL(centry->data, centry->ofs); + centry->ofs += 2; + return ret; +} + +/* + pull a uint8 from a cache entry +*/ +static uint8 centry_uint8(struct cache_entry *centry) +{ + uint8 ret; + if (!centry_check_bytes(centry, 1)) { + smb_panic_fn("centry_uint8"); + } + ret = CVAL(centry->data, centry->ofs); + centry->ofs += 1; + return ret; +} + +/* + pull a NTTIME from a cache entry +*/ +static NTTIME centry_nttime(struct cache_entry *centry) +{ + NTTIME ret; + if (!centry_check_bytes(centry, 8)) { + smb_panic_fn("centry_nttime"); + } + ret = IVAL(centry->data, centry->ofs); + centry->ofs += 4; + ret += (uint64_t)IVAL(centry->data, centry->ofs) << 32; + centry->ofs += 4; + return ret; +} + +/* + pull a time_t from a cache entry. time_t stored portably as a 64-bit time. +*/ +static time_t centry_time(struct cache_entry *centry) +{ + return (time_t)centry_nttime(centry); +} + +/* pull a string from a cache entry, using the supplied + talloc context +*/ +static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx) +{ + uint32 len; + char *ret; + + len = centry_uint8(centry); + + if (len == 0xFF) { + /* a deliberate NULL string */ + return NULL; + } + + if (!centry_check_bytes(centry, (size_t)len)) { + smb_panic_fn("centry_string"); + } + + ret = TALLOC_ARRAY(mem_ctx, char, len+1); + if (!ret) { + smb_panic_fn("centry_string out of memory\n"); + } + memcpy(ret,centry->data + centry->ofs, len); + ret[len] = 0; + centry->ofs += len; + return ret; +} + +/* pull a hash16 from a cache entry, using the supplied + talloc context +*/ +static char *centry_hash16(struct cache_entry *centry, TALLOC_CTX *mem_ctx) +{ + uint32 len; + char *ret; + + len = centry_uint8(centry); + + if (len != 16) { + DEBUG(0,("centry corruption? hash len (%u) != 16\n", + len )); + return NULL; + } + + if (!centry_check_bytes(centry, 16)) { + return NULL; + } + + ret = TALLOC_ARRAY(mem_ctx, char, 16); + if (!ret) { + smb_panic_fn("centry_hash out of memory\n"); + } + memcpy(ret,centry->data + centry->ofs, 16); + centry->ofs += 16; + return ret; +} + +/* pull a sid from a cache entry, using the supplied + talloc context +*/ +static BOOL centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID *sid) +{ + char *sid_string; + sid_string = centry_string(centry, mem_ctx); + if ((sid_string == NULL) || (!string_to_sid(sid, sid_string))) { + return False; + } + return True; +} + + +/* + pull a NTSTATUS from a cache entry +*/ +static NTSTATUS centry_ntstatus(struct cache_entry *centry) +{ + NTSTATUS status; + + status = NT_STATUS(centry_uint32(centry)); + return status; +} + + +/* the server is considered down if it can't give us a sequence number */ +static BOOL wcache_server_down(struct winbindd_domain *domain) +{ + BOOL ret; + + if (!wcache->tdb) + return False; + + ret = (domain->sequence_number == DOM_SEQUENCE_NONE); + + if (ret) + DEBUG(10,("wcache_server_down: server for Domain %s down\n", + domain->name )); + return ret; +} + +static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) +{ + TDB_DATA data; + fstring key; + uint32 time_diff; + + if (!wcache->tdb) { + DEBUG(10,("fetch_cache_seqnum: tdb == NULL\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + fstr_sprintf( key, "SEQNUM/%s", domain->name ); + + data = tdb_fetch_bystring( wcache->tdb, key ); + if ( !data.dptr || data.dsize!=8 ) { + DEBUG(10,("fetch_cache_seqnum: invalid data size key [%s]\n", key )); + return NT_STATUS_UNSUCCESSFUL; + } + + domain->sequence_number = IVAL(data.dptr, 0); + domain->last_seq_check = IVAL(data.dptr, 4); + + SAFE_FREE(data.dptr); + + /* have we expired? */ + + time_diff = now - domain->last_seq_check; + if ( time_diff > lp_winbind_cache_time() ) { + DEBUG(10,("fetch_cache_seqnum: timeout [%s][%u @ %u]\n", + domain->name, domain->sequence_number, + (uint32)domain->last_seq_check)); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("fetch_cache_seqnum: success [%s][%u @ %u]\n", + domain->name, domain->sequence_number, + (uint32)domain->last_seq_check)); + + return NT_STATUS_OK; +} + +static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) +{ + TDB_DATA data; + fstring key_str; + uint8 buf[8]; + + if (!wcache->tdb) { + DEBUG(10,("store_cache_seqnum: tdb == NULL\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + fstr_sprintf( key_str, "SEQNUM/%s", domain->name ); + + SIVAL(buf, 0, domain->sequence_number); + SIVAL(buf, 4, domain->last_seq_check); + data.dptr = buf; + data.dsize = 8; + + if ( tdb_store_bystring( wcache->tdb, key_str, data, TDB_REPLACE) == -1 ) { + DEBUG(10,("store_cache_seqnum: tdb_store fail key [%s]\n", key_str )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("store_cache_seqnum: success [%s][%u @ %u]\n", + domain->name, domain->sequence_number, + (uint32)domain->last_seq_check)); + + return NT_STATUS_OK; +} + +/* + refresh the domain sequence number. If force is True + then always refresh it, no matter how recently we fetched it +*/ + +static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) +{ + NTSTATUS status; + unsigned time_diff; + time_t t = time(NULL); + unsigned cache_time = lp_winbind_cache_time(); + + if ( IS_DOMAIN_OFFLINE(domain) ) { + return; + } + + get_cache( domain ); + +#if 0 /* JERRY -- disable as the default cache time is now 5 minutes */ + /* trying to reconnect is expensive, don't do it too often */ + if (domain->sequence_number == DOM_SEQUENCE_NONE) { + cache_time *= 8; + } +#endif + + time_diff = t - domain->last_seq_check; + + /* see if we have to refetch the domain sequence number */ + if (!force && (time_diff < cache_time)) { + DEBUG(10, ("refresh_sequence_number: %s time ok\n", domain->name)); + goto done; + } + + /* try to get the sequence number from the tdb cache first */ + /* this will update the timestamp as well */ + + status = fetch_cache_seqnum( domain, t ); + if ( NT_STATUS_IS_OK(status) ) + goto done; + + /* important! make sure that we know if this is a native + mode domain or not. And that we can contact it. */ + + if ( winbindd_can_contact_domain( domain ) ) { + status = domain->backend->sequence_number(domain, + &domain->sequence_number); + } else { + /* just use the current time */ + status = NT_STATUS_OK; + domain->sequence_number = time(NULL); + } + + + /* the above call could have set our domain->backend to NULL when + * coming from offline to online mode, make sure to reinitialize the + * backend - Guenther */ + get_cache( domain ); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("refresh_sequence_number: failed with %s\n", nt_errstr(status))); + domain->sequence_number = DOM_SEQUENCE_NONE; + } + + domain->last_status = status; + domain->last_seq_check = time(NULL); + + /* save the new sequence number ni the cache */ + store_cache_seqnum( domain ); + +done: + DEBUG(10, ("refresh_sequence_number: %s seq number is now %d\n", + domain->name, domain->sequence_number)); + + return; +} + +/* + decide if a cache entry has expired +*/ +static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry) +{ + /* If we've been told to be offline - stay in that state... */ + if (lp_winbind_offline_logon() && global_winbindd_offline_state) { + DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n", + keystr, domain->name )); + return False; + } + + /* when the domain is offline return the cached entry. + * This deals with transient offline states... */ + + if (!domain->online) { + DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n", + keystr, domain->name )); + return False; + } + + /* if the server is OK and our cache entry came from when it was down then + the entry is invalid */ + if ((domain->sequence_number != DOM_SEQUENCE_NONE) && + (centry->sequence_number == DOM_SEQUENCE_NONE)) { + DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n", + keystr, domain->name )); + return True; + } + + /* if the server is down or the cache entry is not older than the + current sequence number then it is OK */ + if (wcache_server_down(domain) || + centry->sequence_number == domain->sequence_number) { + DEBUG(10,("centry_expired: Key %s for domain %s is good.\n", + keystr, domain->name )); + return False; + } + + DEBUG(10,("centry_expired: Key %s for domain %s expired\n", + keystr, domain->name )); + + /* it's expired */ + return True; +} + +static struct cache_entry *wcache_fetch_raw(char *kstr) +{ + TDB_DATA data; + struct cache_entry *centry; + TDB_DATA key; + + key = string_tdb_data(kstr); + data = tdb_fetch(wcache->tdb, key); + if (!data.dptr) { + /* a cache miss */ + return NULL; + } + + centry = SMB_XMALLOC_P(struct cache_entry); + centry->data = (unsigned char *)data.dptr; + centry->len = data.dsize; + centry->ofs = 0; + + if (centry->len < 8) { + /* huh? corrupt cache? */ + DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr)); + centry_free(centry); + return NULL; + } + + centry->status = centry_ntstatus(centry); + centry->sequence_number = centry_uint32(centry); + + return centry; +} + +/* + fetch an entry from the cache, with a varargs key. auto-fetch the sequence + number and return status +*/ +static struct cache_entry *wcache_fetch(struct winbind_cache *cache, + struct winbindd_domain *domain, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static struct cache_entry *wcache_fetch(struct winbind_cache *cache, + struct winbindd_domain *domain, + const char *format, ...) +{ + va_list ap; + char *kstr; + struct cache_entry *centry; + + if (opt_nocache) { + return NULL; + } + + refresh_sequence_number(domain, False); + + va_start(ap, format); + smb_xvasprintf(&kstr, format, ap); + va_end(ap); + + centry = wcache_fetch_raw(kstr); + if (centry == NULL) { + free(kstr); + return NULL; + } + + if (centry_expired(domain, kstr, centry)) { + + DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n", + kstr, domain->name )); + + centry_free(centry); + free(kstr); + return NULL; + } + + DEBUG(10,("wcache_fetch: returning entry %s for domain %s\n", + kstr, domain->name )); + + free(kstr); + return centry; +} + +static void wcache_delete(const char *format, ...) PRINTF_ATTRIBUTE(1,2); +static void wcache_delete(const char *format, ...) +{ + va_list ap; + char *kstr; + TDB_DATA key; + + va_start(ap, format); + smb_xvasprintf(&kstr, format, ap); + va_end(ap); + + key = string_tdb_data(kstr); + + tdb_delete(wcache->tdb, key); + free(kstr); +} + +/* + make sure we have at least len bytes available in a centry +*/ +static void centry_expand(struct cache_entry *centry, uint32 len) +{ + if (centry->len - centry->ofs >= len) + return; + centry->len *= 2; + centry->data = SMB_REALLOC_ARRAY(centry->data, unsigned char, + centry->len); + if (!centry->data) { + DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len)); + smb_panic_fn("out of memory in centry_expand"); + } +} + +/* + push a uint32 into a centry +*/ +static void centry_put_uint32(struct cache_entry *centry, uint32 v) +{ + centry_expand(centry, 4); + SIVAL(centry->data, centry->ofs, v); + centry->ofs += 4; +} + +/* + push a uint16 into a centry +*/ +static void centry_put_uint16(struct cache_entry *centry, uint16 v) +{ + centry_expand(centry, 2); + SIVAL(centry->data, centry->ofs, v); + centry->ofs += 2; +} + +/* + push a uint8 into a centry +*/ +static void centry_put_uint8(struct cache_entry *centry, uint8 v) +{ + centry_expand(centry, 1); + SCVAL(centry->data, centry->ofs, v); + centry->ofs += 1; +} + +/* + push a string into a centry + */ +static void centry_put_string(struct cache_entry *centry, const char *s) +{ + int len; + + if (!s) { + /* null strings are marked as len 0xFFFF */ + centry_put_uint8(centry, 0xFF); + return; + } + + len = strlen(s); + /* can't handle more than 254 char strings. Truncating is probably best */ + if (len > 254) { + DEBUG(10,("centry_put_string: truncating len (%d) to: 254\n", len)); + len = 254; + } + centry_put_uint8(centry, len); + centry_expand(centry, len); + memcpy(centry->data + centry->ofs, s, len); + centry->ofs += len; +} + +/* + push a 16 byte hash into a centry - treat as 16 byte string. + */ +static void centry_put_hash16(struct cache_entry *centry, const uint8 val[16]) +{ + centry_put_uint8(centry, 16); + centry_expand(centry, 16); + memcpy(centry->data + centry->ofs, val, 16); + centry->ofs += 16; +} + +static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) +{ + fstring sid_string; + centry_put_string(centry, sid_to_string(sid_string, sid)); +} + + +/* + put NTSTATUS into a centry +*/ +static void centry_put_ntstatus(struct cache_entry *centry, NTSTATUS status) +{ + uint32 status_value = NT_STATUS_V(status); + centry_put_uint32(centry, status_value); +} + + +/* + push a NTTIME into a centry +*/ +static void centry_put_nttime(struct cache_entry *centry, NTTIME nt) +{ + centry_expand(centry, 8); + SIVAL(centry->data, centry->ofs, nt & 0xFFFFFFFF); + centry->ofs += 4; + SIVAL(centry->data, centry->ofs, nt >> 32); + centry->ofs += 4; +} + +/* + push a time_t into a centry - use a 64 bit size. + NTTIME here is being used as a convenient 64-bit size. +*/ +static void centry_put_time(struct cache_entry *centry, time_t t) +{ + NTTIME nt = (NTTIME)t; + centry_put_nttime(centry, nt); +} + +/* + start a centry for output. When finished, call centry_end() +*/ +struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status) +{ + struct cache_entry *centry; + + if (!wcache->tdb) + return NULL; + + centry = SMB_XMALLOC_P(struct cache_entry); + + centry->len = 8192; /* reasonable default */ + centry->data = SMB_XMALLOC_ARRAY(uint8, centry->len); + centry->ofs = 0; + centry->sequence_number = domain->sequence_number; + centry_put_ntstatus(centry, status); + centry_put_uint32(centry, centry->sequence_number); + return centry; +} + +/* + finish a centry and write it to the tdb +*/ +static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +static void centry_end(struct cache_entry *centry, const char *format, ...) +{ + va_list ap; + char *kstr; + TDB_DATA key, data; + + if (opt_nocache) { + return; + } + + va_start(ap, format); + smb_xvasprintf(&kstr, format, ap); + va_end(ap); + + key = string_tdb_data(kstr); + data.dptr = centry->data; + data.dsize = centry->ofs; + + tdb_store(wcache->tdb, key, data, TDB_REPLACE); + free(kstr); +} + +static void wcache_save_name_to_sid(struct winbindd_domain *domain, + NTSTATUS status, const char *domain_name, + const char *name, const DOM_SID *sid, + enum lsa_SidType type) +{ + struct cache_entry *centry; + fstring uname; + + centry = centry_start(domain, status); + if (!centry) + return; + centry_put_uint32(centry, type); + centry_put_sid(centry, sid); + fstrcpy(uname, name); + strupper_m(uname); + centry_end(centry, "NS/%s/%s", domain_name, uname); + DEBUG(10,("wcache_save_name_to_sid: %s\\%s -> %s (%s)\n", domain_name, uname, + sid_string_static(sid), nt_errstr(status))); + centry_free(centry); +} + +static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, + const DOM_SID *sid, const char *domain_name, const char *name, enum lsa_SidType type) +{ + struct cache_entry *centry; + fstring sid_string; + + centry = centry_start(domain, status); + if (!centry) + return; + + if (NT_STATUS_IS_OK(status)) { + centry_put_uint32(centry, type); + centry_put_string(centry, domain_name); + centry_put_string(centry, name); + } + + centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); + DEBUG(10,("wcache_save_sid_to_name: %s -> %s (%s)\n", sid_string, + name, nt_errstr(status))); + centry_free(centry); +} + + +static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info) +{ + struct cache_entry *centry; + fstring sid_string; + + if (is_null_sid(&info->user_sid)) { + return; + } + + centry = centry_start(domain, status); + if (!centry) + return; + centry_put_string(centry, info->acct_name); + centry_put_string(centry, info->full_name); + centry_put_string(centry, info->homedir); + centry_put_string(centry, info->shell); + centry_put_uint32(centry, info->primary_gid); + centry_put_sid(centry, &info->user_sid); + centry_put_sid(centry, &info->group_sid); + centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid)); + DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name)); + centry_free(centry); +} + +static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy) +{ + struct cache_entry *centry; + + centry = centry_start(domain, status); + if (!centry) + return; + + centry_put_nttime(centry, lockout_policy->duration); + centry_put_nttime(centry, lockout_policy->reset_count); + centry_put_uint16(centry, lockout_policy->bad_attempt_lockout); + + centry_end(centry, "LOC_POL/%s", domain->name); + + DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name)); + + centry_free(centry); +} + +static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *policy) +{ + struct cache_entry *centry; + + centry = centry_start(domain, status); + if (!centry) + return; + + centry_put_uint16(centry, policy->min_length_password); + centry_put_uint16(centry, policy->password_history); + centry_put_uint32(centry, policy->password_properties); + centry_put_nttime(centry, policy->expire); + centry_put_nttime(centry, policy->min_passwordage); + + centry_end(centry, "PWD_POL/%s", domain->name); + + DEBUG(10,("wcache_save_password_policy: %s\n", domain->name)); + + centry_free(centry); +} + +NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid) +{ + struct winbind_cache *cache = get_cache(domain); + TDB_DATA data; + fstring key_str; + uint32 rid; + + if (!cache->tdb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + if (is_null_sid(sid)) { + return NT_STATUS_INVALID_SID; + } + + if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) { + return NT_STATUS_INVALID_SID; + } + + fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid)); + + data = tdb_fetch(cache->tdb, string_tdb_data(key_str)); + if (!data.dptr) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + SAFE_FREE(data.dptr); + return NT_STATUS_OK; +} + +/* Lookup creds for a SID - copes with old (unsalted) creds as well + as new salted ones. */ + +NTSTATUS wcache_get_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const uint8 **cached_nt_pass, + const uint8 **cached_salt) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + time_t t; + uint32 rid; + + if (!cache->tdb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + if (is_null_sid(sid)) { + return NT_STATUS_INVALID_SID; + } + + if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) { + return NT_STATUS_INVALID_SID; + } + + /* Try and get a salted cred first. If we can't + fall back to an unsalted cred. */ + + centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid)); + if (!centry) { + DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n", + sid_string_static(sid))); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + t = centry_time(centry); + + /* In the salted case this isn't actually the nt_hash itself, + but the MD5 of the salt + nt_hash. Let the caller + sort this out. It can tell as we only return the cached_salt + if we are returning a salted cred. */ + + *cached_nt_pass = (const uint8 *)centry_hash16(centry, mem_ctx); + if (*cached_nt_pass == NULL) { + const char *sidstr = sid_string_static(sid); + + /* Bad (old) cred cache. Delete and pretend we + don't have it. */ + DEBUG(0,("wcache_get_creds: bad entry for [CRED/%s] - deleting\n", + sidstr)); + wcache_delete("CRED/%s", sidstr); + centry_free(centry); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* We only have 17 bytes more data in the salted cred case. */ + if (centry->len - centry->ofs == 17) { + *cached_salt = (const uint8 *)centry_hash16(centry, mem_ctx); + } else { + *cached_salt = NULL; + } + + dump_data_pw("cached_nt_pass", *cached_nt_pass, NT_HASH_LEN); + if (*cached_salt) { + dump_data_pw("cached_salt", *cached_salt, NT_HASH_LEN); + } + + status = centry->status; + + DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status: %s\n", + sid_string_static(sid), nt_errstr(status) )); + + centry_free(centry); + return status; +} + +/* Store creds for a SID - only writes out new salted ones. */ + +NTSTATUS wcache_save_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const uint8 nt_pass[NT_HASH_LEN]) +{ + struct cache_entry *centry; + fstring sid_string; + uint32 rid; + uint8 cred_salt[NT_HASH_LEN]; + uint8 salted_hash[NT_HASH_LEN]; + + if (is_null_sid(sid)) { + return NT_STATUS_INVALID_SID; + } + + if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) { + return NT_STATUS_INVALID_SID; + } + + centry = centry_start(domain, NT_STATUS_OK); + if (!centry) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + dump_data_pw("nt_pass", nt_pass, NT_HASH_LEN); + + centry_put_time(centry, time(NULL)); + + /* Create a salt and then salt the hash. */ + generate_random_buffer(cred_salt, NT_HASH_LEN); + E_md5hash(cred_salt, nt_pass, salted_hash); + + centry_put_hash16(centry, salted_hash); + centry_put_hash16(centry, cred_salt); + centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid)); + + DEBUG(10,("wcache_save_creds: %s\n", sid_string)); + + centry_free(centry); + + return NT_STATUS_OK; +} + + +/* Query display info. This is the basic user list fn */ +static NTSTATUS query_user_list(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + unsigned int i, retry; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "UL/%s", domain->name); + if (!centry) + goto do_query; + + *num_entries = centry_uint32(centry); + + if (*num_entries == 0) + goto do_cached; + + (*info) = TALLOC_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries); + if (! (*info)) { + smb_panic_fn("query_user_list out of memory"); + } + for (i=0; i<(*num_entries); i++) { + (*info)[i].acct_name = centry_string(centry, mem_ctx); + (*info)[i].full_name = centry_string(centry, mem_ctx); + (*info)[i].homedir = centry_string(centry, mem_ctx); + (*info)[i].shell = centry_string(centry, mem_ctx); + centry_sid(centry, mem_ctx, &(*info)[i].user_sid); + centry_sid(centry, mem_ctx, &(*info)[i].group_sid); + } + +do_cached: + status = centry->status; + + DEBUG(10,("query_user_list: [Cached] - cached list for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + *num_entries = 0; + *info = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + /* Put the query_user_list() in a retry loop. There appears to be + * some bug either with Windows 2000 or Samba's handling of large + * rpc replies. This manifests itself as sudden disconnection + * at a random point in the enumeration of a large (60k) user list. + * The retry loop simply tries the operation again. )-: It's not + * pretty but an acceptable workaround until we work out what the + * real problem is. */ + + retry = 0; + do { + + DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("query_user_list: returned 0x%08x, " + "retrying\n", NT_STATUS_V(status))); + } + if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) { + DEBUG(3, ("query_user_list: flushing " + "connection cache\n")); + invalidate_cm_connection(&domain->conn); + } + + } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && + (retry++ < 5)); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_entries); + for (i=0; i<(*num_entries); i++) { + centry_put_string(centry, (*info)[i].acct_name); + centry_put_string(centry, (*info)[i].full_name); + centry_put_string(centry, (*info)[i].homedir); + centry_put_string(centry, (*info)[i].shell); + centry_put_sid(centry, &(*info)[i].user_sid); + centry_put_sid(centry, &(*info)[i].group_sid); + if (domain->backend && domain->backend->consistent) { + /* when the backend is consistent we can pre-prime some mappings */ + wcache_save_name_to_sid(domain, NT_STATUS_OK, + domain->name, + (*info)[i].acct_name, + &(*info)[i].user_sid, + SID_NAME_USER); + wcache_save_sid_to_name(domain, NT_STATUS_OK, + &(*info)[i].user_sid, + domain->name, + (*info)[i].acct_name, + SID_NAME_USER); + wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); + } + } + centry_end(centry, "UL/%s", domain->name); + centry_free(centry); + +skip_save: + return status; +} + +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + unsigned int i; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name); + if (!centry) + goto do_query; + + *num_entries = centry_uint32(centry); + + if (*num_entries == 0) + goto do_cached; + + (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); + if (! (*info)) { + smb_panic_fn("enum_dom_groups out of memory"); + } + for (i=0; i<(*num_entries); i++) { + fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); + fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); + (*info)[i].rid = centry_uint32(centry); + } + +do_cached: + status = centry->status; + + DEBUG(10,("enum_dom_groups: [Cached] - cached list for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + *num_entries = 0; + *info = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("enum_dom_groups: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_entries); + for (i=0; i<(*num_entries); i++) { + centry_put_string(centry, (*info)[i].acct_name); + centry_put_string(centry, (*info)[i].acct_desc); + centry_put_uint32(centry, (*info)[i].rid); + } + centry_end(centry, "GL/%s/domain", domain->name); + centry_free(centry); + +skip_save: + return status; +} + +/* list all domain groups */ +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + unsigned int i; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name); + if (!centry) + goto do_query; + + *num_entries = centry_uint32(centry); + + if (*num_entries == 0) + goto do_cached; + + (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); + if (! (*info)) { + smb_panic_fn("enum_dom_groups out of memory"); + } + for (i=0; i<(*num_entries); i++) { + fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); + fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); + (*info)[i].rid = centry_uint32(centry); + } + +do_cached: + + /* If we are returning cached data and the domain controller + is down then we don't know whether the data is up to date + or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to + indicate this. */ + + if (wcache_server_down(domain)) { + DEBUG(10, ("enum_local_groups: returning cached user list and server was down\n")); + status = NT_STATUS_MORE_PROCESSING_REQUIRED; + } else + status = centry->status; + + DEBUG(10,("enum_local_groups: [Cached] - cached list for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + *num_entries = 0; + *info = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("enum_local_groups: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_entries); + for (i=0; i<(*num_entries); i++) { + centry_put_string(centry, (*info)[i].acct_name); + centry_put_string(centry, (*info)[i].acct_desc); + centry_put_uint32(centry, (*info)[i].rid); + } + centry_end(centry, "GL/%s/local", domain->name); + centry_free(centry); + +skip_save: + return status; +} + +/* convert a single name to a sid in a domain */ +static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd orig_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + fstring uname; + + if (!cache->tdb) + goto do_query; + + fstrcpy(uname, name); + strupper_m(uname); + centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname); + if (!centry) + goto do_query; + + status = centry->status; + if (NT_STATUS_IS_OK(status)) { + *type = (enum lsa_SidType)centry_uint32(centry); + centry_sid(centry, mem_ctx, sid); + } + + DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + ZERO_STRUCTP(sid); + + /* If the seq number check indicated that there is a problem + * with this DC, then return that status... except for + * access_denied. This is special because the dc may be in + * "restrict anonymous = 1" mode, in which case it will deny + * most unauthenticated operations, but *will* allow the LSA + * name-to-sid that we try as a fallback. */ + + if (!(NT_STATUS_IS_OK(domain->last_status) + || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) + return domain->last_status; + + DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n", + domain->name )); + + status = domain->backend->name_to_sid(domain, mem_ctx, orig_cmd, + domain_name, name, sid, type); + + /* and save it */ + refresh_sequence_number(domain, False); + + if (domain->online && + (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) { + wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); + + /* Only save the reverse mapping if this was not a UPN */ + if (!strchr(name, '@')) { + strupper_m(CONST_DISCARD(char *,domain_name)); + strlower_m(CONST_DISCARD(char *,name)); + wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type); + } + } + + return status; +} + +/* convert a sid to a user or group name. The sid is guaranteed to be in the domain + given */ +static NTSTATUS sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + fstring sid_string; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); + if (!centry) + goto do_query; + + status = centry->status; + if (NT_STATUS_IS_OK(status)) { + *type = (enum lsa_SidType)centry_uint32(centry); + *domain_name = centry_string(centry, mem_ctx); + *name = centry_string(centry, mem_ctx); + } + + DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + *name = NULL; + *domain_name = NULL; + + /* If the seq number check indicated that there is a problem + * with this DC, then return that status... except for + * access_denied. This is special because the dc may be in + * "restrict anonymous = 1" mode, in which case it will deny + * most unauthenticated operations, but *will* allow the LSA + * sid-to-name that we try as a fallback. */ + + if (!(NT_STATUS_IS_OK(domain->last_status) + || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) + return domain->last_status; + + DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n", + domain->name )); + + status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type); + + /* and save it */ + refresh_sequence_number(domain, False); + wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type); + + /* We can't save the name to sid mapping here, as with sid history a + * later name2sid would give the wrong sid. */ + + return status; +} + +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types) +{ + struct winbind_cache *cache = get_cache(domain); + size_t i; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + BOOL have_mapped; + BOOL have_unmapped; + + *domain_name = NULL; + *names = NULL; + *types = NULL; + + if (!cache->tdb) { + goto do_query; + } + + if (num_rids == 0) { + return NT_STATUS_OK; + } + + *names = TALLOC_ARRAY(mem_ctx, char *, num_rids); + *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); + + if ((*names == NULL) || (*types == NULL)) { + result = NT_STATUS_NO_MEMORY; + goto error; + } + + have_mapped = have_unmapped = False; + + for (i=0; istatus)) { + char *dom; + have_mapped = True; + (*types)[i] = (enum lsa_SidType)centry_uint32(centry); + + dom = centry_string(centry, mem_ctx); + if (*domain_name == NULL) { + *domain_name = dom; + } else { + talloc_free(dom); + } + + (*names)[i] = centry_string(centry, *names); + + } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) { + have_unmapped = True; + + } else { + /* something's definitely wrong */ + result = centry->status; + goto error; + } + + centry_free(centry); + } + + if (!have_mapped) { + return NT_STATUS_NONE_MAPPED; + } + if (!have_unmapped) { + return NT_STATUS_OK; + } + return STATUS_SOME_UNMAPPED; + + do_query: + + TALLOC_FREE(*names); + TALLOC_FREE(*types); + + result = domain->backend->rids_to_names(domain, mem_ctx, domain_sid, + rids, num_rids, domain_name, + names, types); + + /* + None of the queried rids has been found so save all negative entries + */ + if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED)) { + for (i = 0; i < num_rids; i++) { + DOM_SID sid; + const char *name = ""; + const enum lsa_SidType type = SID_NAME_UNKNOWN; + NTSTATUS status = NT_STATUS_NONE_MAPPED; + + if (!sid_compose(&sid, domain_sid, rids[i])) { + return NT_STATUS_INTERNAL_ERROR; + } + + wcache_save_sid_to_name(domain, status, &sid, *domain_name, + name, type); + } + + return result; + } + + /* + Some or all of the queried rids have been found. + */ + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) { + return result; + } + + refresh_sequence_number(domain, False); + + for (i=0; itdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid)); + + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("query_user: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + + if (!centry) + goto do_query; + + /* if status is not ok then this is a negative hit + and the rest of the data doesn't matter */ + status = centry->status; + if (NT_STATUS_IS_OK(status)) { + info->acct_name = centry_string(centry, mem_ctx); + info->full_name = centry_string(centry, mem_ctx); + info->homedir = centry_string(centry, mem_ctx); + info->shell = centry_string(centry, mem_ctx); + info->primary_gid = centry_uint32(centry); + centry_sid(centry, mem_ctx, &info->user_sid); + centry_sid(centry, mem_ctx, &info->group_sid); + } + + DEBUG(10,("query_user: [Cached] - cached info for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + ZERO_STRUCTP(info); + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("query_user: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->query_user(domain, mem_ctx, user_sid, info); + + /* and save it */ + refresh_sequence_number(domain, False); + wcache_save_user(domain, status, info); + + return status; +} + + +/* Lookup groups a user is a member of. */ +static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *num_groups, DOM_SID **user_gids) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + unsigned int i; + fstring sid_string; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); + + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("lookup_usergroups: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + + if (!centry) + goto do_query; + + *num_groups = centry_uint32(centry); + + if (*num_groups == 0) + goto do_cached; + + (*user_gids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups); + if (! (*user_gids)) { + smb_panic_fn("lookup_usergroups out of memory"); + } + for (i=0; i<(*num_groups); i++) { + centry_sid(centry, mem_ctx, &(*user_gids)[i]); + } + +do_cached: + status = centry->status; + + DEBUG(10,("lookup_usergroups: [Cached] - cached info for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + (*num_groups) = 0; + (*user_gids) = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); + + if ( NT_STATUS_EQUAL(status, NT_STATUS_SYNCHRONIZATION_REQUIRED) ) + goto skip_save; + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + + centry_put_uint32(centry, *num_groups); + for (i=0; i<(*num_groups); i++) { + centry_put_sid(centry, &(*user_gids)[i]); + } + + centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid)); + centry_free(centry); + +skip_save: + return status; +} + +static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID *sids, + uint32 *num_aliases, uint32 **alias_rids) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + char *sidlist = talloc_strdup(mem_ctx, ""); + int i; + + if (!cache->tdb) + goto do_query; + + if (num_sids == 0) { + *num_aliases = 0; + *alias_rids = NULL; + return NT_STATUS_OK; + } + + /* We need to cache indexed by the whole list of SIDs, the aliases + * resulting might come from any of the SIDs. */ + + for (i=0; istatus; + + DEBUG(10,("lookup_useraliases: [Cached] - cached info for domain: %s " + "status %s\n", domain->name, nt_errstr(status))); + + centry_free(centry); + return status; + + do_query: + (*num_aliases) = 0; + (*alias_rids) = NULL; + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info " + "for domain %s\n", domain->name )); + + status = domain->backend->lookup_useraliases(domain, mem_ctx, + num_sids, sids, + num_aliases, alias_rids); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_aliases); + for (i=0; i<(*num_aliases); i++) + centry_put_uint32(centry, (*alias_rids)[i]); + centry_end(centry, "UA%s", sidlist); + centry_free(centry); + + skip_save: + return status; +} + + +static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, uint32 *num_names, + DOM_SID **sid_mem, char ***names, + uint32 **name_types) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + unsigned int i; + fstring sid_string; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); + if (!centry) + goto do_query; + + *num_names = centry_uint32(centry); + + if (*num_names == 0) + goto do_cached; + + (*sid_mem) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_names); + (*names) = TALLOC_ARRAY(mem_ctx, char *, *num_names); + (*name_types) = TALLOC_ARRAY(mem_ctx, uint32, *num_names); + + if (! (*sid_mem) || ! (*names) || ! (*name_types)) { + smb_panic_fn("lookup_groupmem out of memory"); + } + + for (i=0; i<(*num_names); i++) { + centry_sid(centry, mem_ctx, &(*sid_mem)[i]); + (*names)[i] = centry_string(centry, mem_ctx); + (*name_types)[i] = centry_uint32(centry); + } + +do_cached: + status = centry->status; + + DEBUG(10,("lookup_groupmem: [Cached] - cached info for domain %s status: %s\n", + domain->name, nt_errstr(status))); + + centry_free(centry); + return status; + +do_query: + (*num_names) = 0; + (*sid_mem) = NULL; + (*names) = NULL; + (*name_types) = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_groupmem: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, + sid_mem, names, name_types); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_names); + for (i=0; i<(*num_names); i++) { + centry_put_sid(centry, &(*sid_mem)[i]); + centry_put_string(centry, (*names)[i]); + centry_put_uint32(centry, (*name_types)[i]); + } + centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid)); + centry_free(centry); + +skip_save: + return status; +} + +/* find the sequence number for a domain */ +static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) +{ + refresh_sequence_number(domain, False); + + *seq = domain->sequence_number; + + return NT_STATUS_OK; +} + +/* enumerate trusted domains + * (we need to have the list of trustdoms in the cache when we go offline) - + * Guenther */ +static NTSTATUS trusted_domains(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + char ***names, + char ***alt_names, + DOM_SID **dom_sids) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + int i; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "TRUSTDOMS/%s", domain->name); + + if (!centry) { + goto do_query; + } + + *num_domains = centry_uint32(centry); + + if (*num_domains) { + (*names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains); + (*alt_names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains); + (*dom_sids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains); + + if (! (*dom_sids) || ! (*names) || ! (*alt_names)) { + smb_panic_fn("trusted_domains out of memory"); + } + } else { + (*names) = NULL; + (*alt_names) = NULL; + (*dom_sids) = NULL; + } + + for (i=0; i<(*num_domains); i++) { + (*names)[i] = centry_string(centry, mem_ctx); + (*alt_names)[i] = centry_string(centry, mem_ctx); + centry_sid(centry, mem_ctx, &(*dom_sids)[i]); + } + + status = centry->status; + + DEBUG(10,("trusted_domains: [Cached] - cached info for domain %s (%d trusts) status: %s\n", + domain->name, *num_domains, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + (*num_domains) = 0; + (*dom_sids) = NULL; + (*names) = NULL; + (*alt_names) = NULL; + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("trusted_domains: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->trusted_domains(domain, mem_ctx, num_domains, + names, alt_names, dom_sids); + + /* no trusts gives NT_STATUS_NO_MORE_ENTRIES resetting to NT_STATUS_OK + * so that the generic centry handling still applies correctly - + * Guenther*/ + + if (!NT_STATUS_IS_ERR(status)) { + status = NT_STATUS_OK; + } + + +#if 0 /* Disabled as we want the trust dom list to be managed by + the main parent and always to make the query. --jerry */ + + /* and save it */ + refresh_sequence_number(domain, False); + + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + + centry_put_uint32(centry, *num_domains); + + for (i=0; i<(*num_domains); i++) { + centry_put_string(centry, (*names)[i]); + centry_put_string(centry, (*alt_names)[i]); + centry_put_sid(centry, &(*dom_sids)[i]); + } + + centry_end(centry, "TRUSTDOMS/%s", domain->name); + + centry_free(centry); + +skip_save: +#endif + + return status; +} + +/* get lockout policy */ +static NTSTATUS lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_12 *policy){ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name); + + if (!centry) + goto do_query; + + policy->duration = centry_nttime(centry); + policy->reset_count = centry_nttime(centry); + policy->bad_attempt_lockout = centry_uint16(centry); + + status = centry->status; + + DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + ZERO_STRUCTP(policy); + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->lockout_policy(domain, mem_ctx, policy); + + /* and save it */ + refresh_sequence_number(domain, False); + wcache_save_lockout_policy(domain, status, policy); + + return status; +} + +/* get password policy */ +static NTSTATUS password_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_1 *policy) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name); + + if (!centry) + goto do_query; + + policy->min_length_password = centry_uint16(centry); + policy->password_history = centry_uint16(centry); + policy->password_properties = centry_uint32(centry); + policy->expire = centry_nttime(centry); + policy->min_passwordage = centry_nttime(centry); + + status = centry->status; + + DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status: %s\n", + domain->name, nt_errstr(status) )); + + centry_free(centry); + return status; + +do_query: + ZERO_STRUCTP(policy); + + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->password_policy(domain, mem_ctx, policy); + + /* and save it */ + refresh_sequence_number(domain, False); + wcache_save_password_policy(domain, status, policy); + + return status; +} + + +/* Invalidate cached user and group lists coherently */ + +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + if (strncmp((const char *)kbuf.dptr, "UL/", 3) == 0 || + strncmp((const char *)kbuf.dptr, "GL/", 3) == 0) + tdb_delete(the_tdb, kbuf); + + return 0; +} + +/* Invalidate the getpwnam and getgroups entries for a winbindd domain */ + +void wcache_invalidate_samlogon(struct winbindd_domain *domain, + NET_USER_INFO_3 *info3) +{ + struct winbind_cache *cache; + + /* dont clear cached U/SID and UG/SID entries when we want to logon + * offline - gd */ + + if (lp_winbind_offline_logon()) { + return; + } + + if (!domain) + return; + + cache = get_cache(domain); + netsamlogon_clear_cached_user(cache->tdb, info3); +} + +void wcache_invalidate_cache(void) +{ + struct winbindd_domain *domain; + + for (domain = domain_list(); domain; domain = domain->next) { + struct winbind_cache *cache = get_cache(domain); + + DEBUG(10, ("wcache_invalidate_cache: invalidating cache " + "entries for %s\n", domain->name)); + if (cache) + tdb_traverse(cache->tdb, traverse_fn, NULL); + } +} + +BOOL init_wcache(void) +{ + if (wcache == NULL) { + wcache = SMB_XMALLOC_P(struct winbind_cache); + ZERO_STRUCTP(wcache); + } + + if (wcache->tdb != NULL) + return True; + + /* when working offline we must not clear the cache on restart */ + wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), + WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, + lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), + O_RDWR|O_CREAT, 0600); + + if (wcache->tdb == NULL) { + DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); + return False; + } + + return True; +} + +/************************************************************************ + This is called by the parent to initialize the cache file. + We don't need sophisticated locking here as we know we're the + only opener. +************************************************************************/ + +BOOL initialize_winbindd_cache(void) +{ + BOOL cache_bad = True; + uint32 vers; + + if (!init_wcache()) { + DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n")); + return False; + } + + /* Check version number. */ + if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) && + vers == WINBINDD_CACHE_VERSION) { + cache_bad = False; + } + + if (cache_bad) { + DEBUG(0,("initialize_winbindd_cache: clearing cache " + "and re-creating with version number %d\n", + WINBINDD_CACHE_VERSION )); + + tdb_close(wcache->tdb); + wcache->tdb = NULL; + + if (unlink(lock_path("winbindd_cache.tdb")) == -1) { + DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ", + lock_path("winbindd_cache.tdb"), + strerror(errno) )); + return False; + } + if (!init_wcache()) { + DEBUG(0,("initialize_winbindd_cache: re-initialization " + "init_wcache failed.\n")); + return False; + } + + /* Write the version. */ + if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) { + DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n", + tdb_errorstr(wcache->tdb) )); + return False; + } + } + + tdb_close(wcache->tdb); + wcache->tdb = NULL; + return True; +} + +void cache_store_response(pid_t pid, struct winbindd_response *response) +{ + fstring key_str; + + if (!init_wcache()) + return; + + DEBUG(10, ("Storing response for pid %d, len %d\n", + pid, response->length)); + + fstr_sprintf(key_str, "DR/%d", pid); + if (tdb_store(wcache->tdb, string_tdb_data(key_str), + make_tdb_data((uint8 *)response, sizeof(*response)), + TDB_REPLACE) == -1) + return; + + if (response->length == sizeof(*response)) + return; + + /* There's extra data */ + + DEBUG(10, ("Storing extra data: len=%d\n", + (int)(response->length - sizeof(*response)))); + + fstr_sprintf(key_str, "DE/%d", pid); + if (tdb_store(wcache->tdb, string_tdb_data(key_str), + make_tdb_data((uint8 *)response->extra_data.data, + response->length - sizeof(*response)), + TDB_REPLACE) == 0) + return; + + /* We could not store the extra data, make sure the tdb does not + * contain a main record with wrong dangling extra data */ + + fstr_sprintf(key_str, "DR/%d", pid); + tdb_delete(wcache->tdb, string_tdb_data(key_str)); + + return; +} + +BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) +{ + TDB_DATA data; + fstring key_str; + + if (!init_wcache()) + return False; + + DEBUG(10, ("Retrieving response for pid %d\n", pid)); + + fstr_sprintf(key_str, "DR/%d", pid); + data = tdb_fetch(wcache->tdb, string_tdb_data(key_str)); + + if (data.dptr == NULL) + return False; + + if (data.dsize != sizeof(*response)) + return False; + + memcpy(response, data.dptr, data.dsize); + SAFE_FREE(data.dptr); + + if (response->length == sizeof(*response)) { + response->extra_data.data = NULL; + return True; + } + + /* There's extra data */ + + DEBUG(10, ("Retrieving extra data length=%d\n", + (int)(response->length - sizeof(*response)))); + + fstr_sprintf(key_str, "DE/%d", pid); + data = tdb_fetch(wcache->tdb, string_tdb_data(key_str)); + + if (data.dptr == NULL) { + DEBUG(0, ("Did not find extra data\n")); + return False; + } + + if (data.dsize != (response->length - sizeof(*response))) { + DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize)); + SAFE_FREE(data.dptr); + return False; + } + + dump_data(11, (uint8 *)data.dptr, data.dsize); + + response->extra_data.data = data.dptr; + return True; +} + +void cache_cleanup_response(pid_t pid) +{ + fstring key_str; + + if (!init_wcache()) + return; + + fstr_sprintf(key_str, "DR/%d", pid); + tdb_delete(wcache->tdb, string_tdb_data(key_str)); + + fstr_sprintf(key_str, "DE/%d", pid); + tdb_delete(wcache->tdb, string_tdb_data(key_str)); + + return; +} + + +BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, + enum lsa_SidType *type) +{ + struct winbindd_domain *domain; + struct winbind_cache *cache; + struct cache_entry *centry = NULL; + NTSTATUS status; + + domain = find_lookup_domain_from_sid(sid); + if (domain == NULL) { + return False; + } + + cache = get_cache(domain); + + if (cache->tdb == NULL) { + return False; + } + + centry = wcache_fetch(cache, domain, "SN/%s", sid_string_static(sid)); + if (centry == NULL) { + return False; + } + + if (NT_STATUS_IS_OK(centry->status)) { + *type = (enum lsa_SidType)centry_uint32(centry); + *domain_name = centry_string(centry, mem_ctx); + *name = centry_string(centry, mem_ctx); + } + + status = centry->status; + centry_free(centry); + return NT_STATUS_IS_OK(status); +} + +BOOL lookup_cached_name(TALLOC_CTX *mem_ctx, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type) +{ + struct winbindd_domain *domain; + struct winbind_cache *cache; + struct cache_entry *centry = NULL; + NTSTATUS status; + fstring uname; + BOOL original_online_state; + + domain = find_lookup_domain_from_name(domain_name); + if (domain == NULL) { + return False; + } + + cache = get_cache(domain); + + if (cache->tdb == NULL) { + return False; + } + + fstrcpy(uname, name); + strupper_m(uname); + + /* If we are doing a cached logon, temporarily set the domain + offline so the cache won't expire the entry */ + + original_online_state = domain->online; + domain->online = False; + centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname); + domain->online = original_online_state; + + if (centry == NULL) { + return False; + } + + if (NT_STATUS_IS_OK(centry->status)) { + *type = (enum lsa_SidType)centry_uint32(centry); + centry_sid(centry, mem_ctx, sid); + } + + status = centry->status; + centry_free(centry); + + return NT_STATUS_IS_OK(status); +} + +void cache_name2sid(struct winbindd_domain *domain, + const char *domain_name, const char *name, + enum lsa_SidType type, const DOM_SID *sid) +{ + refresh_sequence_number(domain, False); + wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name, + sid, type); +} + +/* + * The original idea that this cache only contains centries has + * been blurred - now other stuff gets put in here. Ensure we + * ignore these things on cleanup. + */ + +static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, + TDB_DATA dbuf, void *state) +{ + struct cache_entry *centry; + + if (is_non_centry_key(kbuf)) { + return 0; + } + + centry = wcache_fetch_raw((char *)kbuf.dptr); + if (!centry) { + return 0; + } + + if (!NT_STATUS_IS_OK(centry->status)) { + DEBUG(10,("deleting centry %s\n", (const char *)kbuf.dptr)); + tdb_delete(the_tdb, kbuf); + } + + centry_free(centry); + return 0; +} + +/* flush the cache */ +void wcache_flush_cache(void) +{ + if (!wcache) + return; + if (wcache->tdb) { + tdb_close(wcache->tdb); + wcache->tdb = NULL; + } + if (opt_nocache) + return; + + /* when working offline we must not clear the cache on restart */ + wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), + WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, + lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), + O_RDWR|O_CREAT, 0600); + + if (!wcache->tdb) { + DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); + return; + } + + tdb_traverse(wcache->tdb, traverse_fn_cleanup, NULL); + + DEBUG(10,("wcache_flush_cache success\n")); +} + +/* Count cached creds */ + +static int traverse_fn_cached_creds(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + int *cred_count = (int*)state; + + if (strncmp((const char *)kbuf.dptr, "CRED/", 5) == 0) { + (*cred_count)++; + } + return 0; +} + +NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count) +{ + struct winbind_cache *cache = get_cache(domain); + + *count = 0; + + if (!cache->tdb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + tdb_traverse(cache->tdb, traverse_fn_cached_creds, (void *)count); + + return NT_STATUS_OK; +} + +struct cred_list { + struct cred_list *prev, *next; + TDB_DATA key; + fstring name; + time_t created; +}; +static struct cred_list *wcache_cred_list; + +static int traverse_fn_get_credlist(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + struct cred_list *cred; + + if (strncmp((const char *)kbuf.dptr, "CRED/", 5) == 0) { + + cred = SMB_MALLOC_P(struct cred_list); + if (cred == NULL) { + DEBUG(0,("traverse_fn_remove_first_creds: failed to malloc new entry for list\n")); + return -1; + } + + ZERO_STRUCTP(cred); + + /* save a copy of the key */ + + fstrcpy(cred->name, (const char *)kbuf.dptr); + DLIST_ADD(wcache_cred_list, cred); + } + + return 0; +} + +NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) +{ + struct winbind_cache *cache = get_cache(domain); + NTSTATUS status; + int ret; + struct cred_list *cred, *oldest = NULL; + + if (!cache->tdb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* we possibly already have an entry */ + if (sid && NT_STATUS_IS_OK(wcache_cached_creds_exist(domain, sid))) { + + fstring key_str; + + DEBUG(11,("we already have an entry, deleting that\n")); + + fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid)); + + tdb_delete(cache->tdb, string_tdb_data(key_str)); + + return NT_STATUS_OK; + } + + ret = tdb_traverse(cache->tdb, traverse_fn_get_credlist, NULL); + if (ret == 0) { + return NT_STATUS_OK; + } else if ((ret == -1) || (wcache_cred_list == NULL)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + ZERO_STRUCTP(oldest); + + for (cred = wcache_cred_list; cred; cred = cred->next) { + + TDB_DATA data; + time_t t; + + data = tdb_fetch(cache->tdb, string_tdb_data(cred->name)); + if (!data.dptr) { + DEBUG(10,("wcache_remove_oldest_cached_creds: entry for [%s] not found\n", + cred->name)); + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto done; + } + + t = IVAL(data.dptr, 0); + SAFE_FREE(data.dptr); + + if (!oldest) { + oldest = SMB_MALLOC_P(struct cred_list); + if (oldest == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + fstrcpy(oldest->name, cred->name); + oldest->created = t; + continue; + } + + if (t < oldest->created) { + fstrcpy(oldest->name, cred->name); + oldest->created = t; + } + } + + if (tdb_delete(cache->tdb, string_tdb_data(oldest->name)) == 0) { + status = NT_STATUS_OK; + } else { + status = NT_STATUS_UNSUCCESSFUL; + } +done: + SAFE_FREE(wcache_cred_list); + SAFE_FREE(oldest); + + return status; +} + +/* Change the global online/offline state. */ +BOOL set_global_winbindd_state_offline(void) +{ + TDB_DATA data; + + DEBUG(10,("set_global_winbindd_state_offline: offline requested.\n")); + + /* Only go offline if someone has created + the key "WINBINDD_OFFLINE" in the cache tdb. */ + + if (wcache == NULL || wcache->tdb == NULL) { + DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n")); + return False; + } + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n")); + return False; + } + + if (global_winbindd_offline_state) { + /* Already offline. */ + return True; + } + + data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" ); + + if (!data.dptr || data.dsize != 4) { + DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n")); + SAFE_FREE(data.dptr); + return False; + } else { + DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n")); + global_winbindd_offline_state = True; + SAFE_FREE(data.dptr); + return True; + } +} + +void set_global_winbindd_state_online(void) +{ + DEBUG(10,("set_global_winbindd_state_online: online requested.\n")); + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("set_global_winbindd_state_online: rejecting.\n")); + return; + } + + if (!global_winbindd_offline_state) { + /* Already online. */ + return; + } + global_winbindd_offline_state = False; + + if (!wcache->tdb) { + return; + } + + /* Ensure there is no key "WINBINDD_OFFLINE" in the cache tdb. */ + tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE"); +} + +BOOL get_global_winbindd_state_offline(void) +{ + return global_winbindd_offline_state; +} + +/*********************************************************************** + Validate functions for all possible cache tdb keys. +***********************************************************************/ + +static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA data, + struct tdb_validation_status *state) +{ + struct cache_entry *centry; + + centry = SMB_XMALLOC_P(struct cache_entry); + centry->data = (unsigned char *)memdup(data.dptr, data.dsize); + if (!centry->data) { + SAFE_FREE(centry); + return NULL; + } + centry->len = data.dsize; + centry->ofs = 0; + + if (centry->len < 8) { + /* huh? corrupt cache? */ + DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr)); + centry_free(centry); + state->bad_entry = True; + state->success = False; + return NULL; + } + + centry->status = NT_STATUS(centry_uint32(centry)); + centry->sequence_number = centry_uint32(centry); + return centry; +} + +static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + if (dbuf.dsize != 8) { + DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n", + keystr, (unsigned int)dbuf.dsize )); + state->bad_entry = True; + return 1; + } + return 0; +} + +static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + if (!centry) { + return 1; + } + + (void)centry_uint32(centry); + if (NT_STATUS_IS_OK(centry->status)) { + DOM_SID sid; + (void)centry_sid(centry, mem_ctx, &sid); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_ns: %s ok\n", keystr)); + return 0; +} + +static int validate_sn(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + if (!centry) { + return 1; + } + + if (NT_STATUS_IS_OK(centry->status)) { + (void)centry_uint32(centry); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_sn: %s ok\n", keystr)); + return 0; +} + +static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + DOM_SID sid; + + if (!centry) { + return 1; + } + + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_uint32(centry); + (void)centry_sid(centry, mem_ctx, &sid); + (void)centry_sid(centry, mem_ctx, &sid); + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_u: %s ok\n", keystr)); + return 0; +} + +static int validate_loc_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + + if (!centry) { + return 1; + } + + (void)centry_nttime(centry); + (void)centry_nttime(centry); + (void)centry_uint16(centry); + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_loc_pol: %s ok\n", keystr)); + return 0; +} + +static int validate_pwd_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + + if (!centry) { + return 1; + } + + (void)centry_uint16(centry); + (void)centry_uint16(centry); + (void)centry_uint32(centry); + (void)centry_nttime(centry); + (void)centry_nttime(centry); + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_pwd_pol: %s ok\n", keystr)); + return 0; +} + +static int validate_cred(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + + if (!centry) { + return 1; + } + + (void)centry_time(centry); + (void)centry_hash16(centry, mem_ctx); + + /* We only have 17 bytes more data in the salted cred case. */ + if (centry->len - centry->ofs == 17) { + (void)centry_hash16(centry, mem_ctx); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_cred: %s ok\n", keystr)); + return 0; +} + +static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_entries, i; + + if (!centry) { + return 1; + } + + num_entries = (int32)centry_uint32(centry); + + for (i=0; i< num_entries; i++) { + DOM_SID sid; + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_sid(centry, mem_ctx, &sid); + (void)centry_sid(centry, mem_ctx, &sid); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_ul: %s ok\n", keystr)); + return 0; +} + +static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_entries, i; + + if (!centry) { + return 1; + } + + num_entries = centry_uint32(centry); + + for (i=0; i< num_entries; i++) { + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_uint32(centry); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_gl: %s ok\n", keystr)); + return 0; +} + +static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_groups, i; + + if (!centry) { + return 1; + } + + num_groups = centry_uint32(centry); + + for (i=0; i< num_groups; i++) { + DOM_SID sid; + centry_sid(centry, mem_ctx, &sid); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_ug: %s ok\n", keystr)); + return 0; +} + +static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_aliases, i; + + if (!centry) { + return 1; + } + + num_aliases = centry_uint32(centry); + + for (i=0; i < num_aliases; i++) { + (void)centry_uint32(centry); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_ua: %s ok\n", keystr)); + return 0; +} + +static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_names, i; + + if (!centry) { + return 1; + } + + num_names = centry_uint32(centry); + + for (i=0; i< num_names; i++) { + DOM_SID sid; + centry_sid(centry, mem_ctx, &sid); + (void)centry_string(centry, mem_ctx); + (void)centry_uint32(centry); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_gm: %s ok\n", keystr)); + return 0; +} + +static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + /* Can't say anything about this other than must be nonzero. */ + if (dbuf.dsize == 0) { + DEBUG(0,("validate_dr: Corrupt cache for key %s (len == 0) ?\n", + keystr)); + state->bad_entry = True; + state->success = False; + return 1; + } + + DEBUG(10,("validate_dr: %s ok\n", keystr)); + return 0; +} + +static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + /* Can't say anything about this other than must be nonzero. */ + if (dbuf.dsize == 0) { + DEBUG(0,("validate_de: Corrupt cache for key %s (len == 0) ?\n", + keystr)); + state->bad_entry = True; + state->success = False; + return 1; + } + + DEBUG(10,("validate_de: %s ok\n", keystr)); + return 0; +} + +static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + int32 num_domains, i; + + if (!centry) { + return 1; + } + + num_domains = centry_uint32(centry); + + for (i=0; i< num_domains; i++) { + DOM_SID sid; + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_sid(centry, mem_ctx, &sid); + } + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_trustdoms: %s ok\n", keystr)); + return 0; +} + +static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr, + TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + if (dbuf.dsize == 0) { + DEBUG(0, ("validate_trustdomcache: Corrupt cache for " + "key %s (len ==0) ?\n", keystr)); + state->bad_entry = True; + state->success = False; + return 1; + } + + DEBUG(10, ("validate_trustdomcache: %s ok\n", keystr)); + DEBUGADD(10, (" Don't trust me, I am a DUMMY!\n")); + return 0; +} + +static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + if (dbuf.dsize != 4) { + DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n", + keystr, (unsigned int)dbuf.dsize )); + state->bad_entry = True; + state->success = False; + return 1; + } + DEBUG(10,("validate_offline: %s ok\n", keystr)); + return 0; +} + +static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, + struct tdb_validation_status *state) +{ + if (dbuf.dsize != 4) { + DEBUG(0, ("validate_cache_version: Corrupt cache for " + "key %s (len %u != 4) ?\n", + keystr, (unsigned int)dbuf.dsize)); + state->bad_entry = True; + state->success = False; + return 1; + } + + DEBUG(10, ("validate_cache_version: %s ok\n", keystr)); + return 0; +} + +/*********************************************************************** + A list of all possible cache tdb keys with associated validation + functions. +***********************************************************************/ + +struct key_val_struct { + const char *keyname; + int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct tdb_validation_status* state); +} key_val[] = { + {"SEQNUM/", validate_seqnum}, + {"NS/", validate_ns}, + {"SN/", validate_sn}, + {"U/", validate_u}, + {"LOC_POL/", validate_loc_pol}, + {"PWD_POL/", validate_pwd_pol}, + {"CRED/", validate_cred}, + {"UL/", validate_ul}, + {"GL/", validate_gl}, + {"UG/", validate_ug}, + {"UA", validate_ua}, + {"GM/", validate_gm}, + {"DR/", validate_dr}, + {"DE/", validate_de}, + {"TRUSTDOMS/", validate_trustdoms}, + {"TRUSTDOMCACHE/", validate_trustdomcache}, + {"WINBINDD_OFFLINE", validate_offline}, + {WINBINDD_CACHE_VERSION_KEYSTR, validate_cache_version}, + {NULL, NULL} +}; + +/*********************************************************************** + Function to look at every entry in the tdb and validate it as far as + possible. +***********************************************************************/ + +static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + int i; + struct tdb_validation_status *v_state = (struct tdb_validation_status *)state; + + /* Paranoia check. */ + if (kbuf.dsize > 1024) { + DEBUG(0,("cache_traverse_validate_fn: key length too large (%u) > 1024\n\n", + (unsigned int)kbuf.dsize )); + return 1; + } + + for (i = 0; key_val[i].keyname; i++) { + size_t namelen = strlen(key_val[i].keyname); + if (kbuf.dsize >= namelen && ( + strncmp(key_val[i].keyname, (const char *)kbuf.dptr, namelen)) == 0) { + TALLOC_CTX *mem_ctx; + char *keystr; + int ret; + + keystr = SMB_MALLOC_ARRAY(char, kbuf.dsize+1); + if (!keystr) { + return 1; + } + memcpy(keystr, kbuf.dptr, kbuf.dsize); + keystr[kbuf.dsize] = '\0'; + + mem_ctx = talloc_init("validate_ctx"); + if (!mem_ctx) { + SAFE_FREE(keystr); + return 1; + } + + ret = key_val[i].validate_data_fn(mem_ctx, keystr, dbuf, + v_state); + + SAFE_FREE(keystr); + talloc_destroy(mem_ctx); + return ret; + } + } + + DEBUG(0,("cache_traverse_validate_fn: unknown cache entry\nkey :\n")); + dump_data(0, (uint8 *)kbuf.dptr, kbuf.dsize); + DEBUG(0,("data :\n")); + dump_data(0, (uint8 *)dbuf.dptr, dbuf.dsize); + v_state->unknown_key = True; + v_state->success = False; + return 1; /* terminate. */ +} + +static void validate_panic(const char *const why) +{ + DEBUG(0,("validating cache: would panic %s\n", why )); + DEBUGADD(0, ("exiting instead (cache validation mode)\n")); + exit(47); +} + +/*********************************************************************** + Try and validate every entry in the winbindd cache. If we fail here, + delete the cache tdb and return non-zero - the caller (main winbindd + function) will restart us as we don't know if we crashed or not. +***********************************************************************/ + +int winbindd_validate_cache(void) +{ + int ret = -1; + const char *tdb_path = lock_path("winbindd_cache.tdb"); + TDB_CONTEXT *tdb = NULL; + + DEBUG(10, ("winbindd_validate_cache: replacing panic function\n")); + smb_panic_fn = validate_panic; + + + tdb = tdb_open_log(tdb_path, + WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, + ( lp_winbind_offline_logon() + ? TDB_DEFAULT + : TDB_DEFAULT | TDB_CLEAR_IF_FIRST ), + O_RDWR|O_CREAT, + 0600); + if (!tdb) { + DEBUG(0, ("winbindd_validate_cache: " + "error opening/initializing tdb\n")); + goto done; + } + tdb_close(tdb); + + ret = tdb_validate_and_backup(tdb_path, cache_traverse_validate_fn); + + if (ret != 0) { + DEBUG(10, ("winbindd_validate_cache: validation not successful.\n")); + DEBUGADD(10, ("removing tdb %s.\n", tdb_path)); + unlink(tdb_path); + } + +done: + DEBUG(10, ("winbindd_validate_cache: restoring panic function\n")); + smb_panic_fn = smb_panic; + return ret; +} + +/*********************************************************************** + Try and validate every entry in the winbindd cache. +***********************************************************************/ + +int winbindd_validate_cache_nobackup(void) +{ + int ret = -1; + const char *tdb_path = lock_path("winbindd_cache.tdb"); + + DEBUG(10, ("winbindd_validate_cache: replacing panic function\n")); + smb_panic_fn = validate_panic; + + + if (wcache == NULL || wcache->tdb == NULL) { + ret = tdb_validate_open(tdb_path, cache_traverse_validate_fn); + } else { + ret = tdb_validate(wcache->tdb, cache_traverse_validate_fn); + } + + if (ret != 0) { + DEBUG(10, ("winbindd_validate_cache_nobackup: validation not " + "successful.\n")); + } + + DEBUG(10, ("winbindd_validate_cache_nobackup: restoring panic " + "function\n")); + smb_panic_fn = smb_panic; + return ret; +} + +/********************************************************************* + ********************************************************************/ + +static BOOL add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, + struct winbindd_tdc_domain **domains, + size_t *num_domains ) +{ + struct winbindd_tdc_domain *list = NULL; + size_t idx; + int i; + BOOL set_only = False; + + /* don't allow duplicates */ + + idx = *num_domains; + list = *domains; + + for ( i=0; i< (*num_domains); i++ ) { + if ( strequal( new_dom->name, list[i].domain_name ) ) { + DEBUG(10,("add_wbdomain_to_tdc_array: Found existing record for %s\n", + new_dom->name)); + idx = i; + set_only = True; + + break; + } + } + + if ( !set_only ) { + if ( !*domains ) { + list = TALLOC_ARRAY( NULL, struct winbindd_tdc_domain, 1 ); + idx = 0; + } else { + list = TALLOC_REALLOC_ARRAY( *domains, *domains, + struct winbindd_tdc_domain, + (*num_domains)+1); + idx = *num_domains; + } + + ZERO_STRUCT( list[idx] ); + } + + if ( !list ) + return False; + + list[idx].domain_name = talloc_strdup( list, new_dom->name ); + list[idx].dns_name = talloc_strdup( list, new_dom->alt_name ); + + if ( !is_null_sid( &new_dom->sid ) ) + sid_copy( &list[idx].sid, &new_dom->sid ); + + if ( new_dom->domain_flags != 0x0 ) + list[idx].trust_flags = new_dom->domain_flags; + + if ( new_dom->domain_type != 0x0 ) + list[idx].trust_type = new_dom->domain_type; + + if ( new_dom->domain_trust_attribs != 0x0 ) + list[idx].trust_attribs = new_dom->domain_trust_attribs; + + if ( !set_only ) { + *domains = list; + *num_domains = idx + 1; + } + + return True; +} + +/********************************************************************* + ********************************************************************/ + +static TDB_DATA make_tdc_key( const char *domain_name ) +{ + char *keystr = NULL; + TDB_DATA key = { NULL, 0 }; + + if ( !domain_name ) { + DEBUG(5,("make_tdc_key: Keyname workgroup is NULL!\n")); + return key; + } + + + asprintf( &keystr, "TRUSTDOMCACHE/%s", domain_name ); + key = string_term_tdb_data(keystr); + + return key; +} + +/********************************************************************* + ********************************************************************/ + +static int pack_tdc_domains( struct winbindd_tdc_domain *domains, + size_t num_domains, + unsigned char **buf ) +{ + unsigned char *buffer = NULL; + int len = 0; + int buflen = 0; + int i = 0; + + DEBUG(10,("pack_tdc_domains: Packing %d trusted domains\n", + (int)num_domains)); + + buflen = 0; + + again: + len = 0; + + /* Store the number of array items first */ + len += tdb_pack( buffer+len, buflen-len, "d", + num_domains ); + + /* now pack each domain trust record */ + for ( i=0; i 0 ) { + DEBUG(10,("pack_tdc_domains: Packing domain %s (%s)\n", + domains[i].domain_name, + domains[i].dns_name ? domains[i].dns_name : "UNKNOWN" )); + } + + len += tdb_pack( buffer+len, buflen-len, "fffddd", + domains[i].domain_name, + domains[i].dns_name, + sid_string_static(&domains[i].sid), + domains[i].trust_flags, + domains[i].trust_attribs, + domains[i].trust_type ); + } + + if ( buflen < len ) { + SAFE_FREE(buffer); + if ( (buffer = SMB_MALLOC_ARRAY(unsigned char, len)) == NULL ) { + DEBUG(0,("pack_tdc_domains: failed to alloc buffer!\n")); + buflen = -1; + goto done; + } + buflen = len; + goto again; + } + + *buf = buffer; + + done: + return buflen; +} + +/********************************************************************* + ********************************************************************/ + +static size_t unpack_tdc_domains( unsigned char *buf, int buflen, + struct winbindd_tdc_domain **domains ) +{ + fstring domain_name, dns_name, sid_string; + uint32 type, attribs, flags; + int num_domains; + int len = 0; + int i; + struct winbindd_tdc_domain *list = NULL; + + /* get the number of domains */ + len += tdb_unpack( buf+len, buflen-len, "d", &num_domains); + if ( len == -1 ) { + DEBUG(5,("unpack_tdc_domains: Failed to unpack domain array\n")); + return 0; + } + + list = TALLOC_ARRAY( NULL, struct winbindd_tdc_domain, num_domains ); + if ( !list ) { + DEBUG(0,("unpack_tdc_domains: Failed to talloc() domain list!\n")); + return 0; + } + + for ( i=0; itdb, key ); + goto done; + } + + data.dsize = pack_tdc_domains( domains, num_domains, &data.dptr ); + + if ( !data.dptr ) { + ret = -1; + goto done; + } + + ret = tdb_store( wcache->tdb, key, data, 0 ); + + done: + SAFE_FREE( data.dptr ); + SAFE_FREE( key.dptr ); + + return ( ret != -1 ); +} + +/********************************************************************* + ********************************************************************/ + +BOOL wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_domains ) +{ + TDB_DATA key = make_tdc_key( lp_workgroup() ); + TDB_DATA data = { NULL, 0 }; + + *domains = NULL; + *num_domains = 0; + + if ( !key.dptr ) + return False; + + data = tdb_fetch( wcache->tdb, key ); + + SAFE_FREE( key.dptr ); + + if ( !data.dptr ) + return False; + + *num_domains = unpack_tdc_domains( data.dptr, data.dsize, domains ); + + SAFE_FREE( data.dptr ); + + if ( !*domains ) + return False; + + return True; +} + +/********************************************************************* + ********************************************************************/ + +BOOL wcache_tdc_add_domain( struct winbindd_domain *domain ) +{ + struct winbindd_tdc_domain *dom_list = NULL; + size_t num_domains = 0; + BOOL ret = False; + + DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, " + "flags = 0x%x, attributes = 0x%x, type = 0x%x\n", + domain->name, domain->alt_name, + sid_string_static(&domain->sid), + domain->domain_flags, + domain->domain_trust_attribs, + domain->domain_type)); + + if ( !init_wcache() ) { + return False; + } + + /* fetch the list */ + + wcache_tdc_fetch_list( &dom_list, &num_domains ); + + /* add the new domain */ + + if ( !add_wbdomain_to_tdc_array( domain, &dom_list, &num_domains ) ) { + goto done; + } + + /* pack the domain */ + + if ( !wcache_tdc_store_list( dom_list, num_domains ) ) { + goto done; + } + + /* Success */ + + ret = True; + done: + TALLOC_FREE( dom_list ); + + return ret; +} + +/********************************************************************* + ********************************************************************/ + +struct winbindd_tdc_domain * wcache_tdc_fetch_domain( TALLOC_CTX *ctx, const char *name ) +{ + struct winbindd_tdc_domain *dom_list = NULL; + size_t num_domains = 0; + int i; + struct winbindd_tdc_domain *d = NULL; + + DEBUG(10,("wcache_tdc_fetch_domain: Searching for domain %s\n", name)); + + if ( !init_wcache() ) { + return False; + } + + /* fetch the list */ + + wcache_tdc_fetch_list( &dom_list, &num_domains ); + + for ( i=0; idomain_name = talloc_strdup( d, dom_list[i].domain_name ); + d->dns_name = talloc_strdup( d, dom_list[i].dns_name ); + sid_copy( &d->sid, &dom_list[i].sid ); + d->trust_flags = dom_list[i].trust_flags; + d->trust_type = dom_list[i].trust_type; + d->trust_attribs = dom_list[i].trust_attribs; + + break; + } + } + + TALLOC_FREE( dom_list ); + + return d; +} + + +/********************************************************************* + ********************************************************************/ + +void wcache_tdc_clear( void ) +{ + if ( !init_wcache() ) + return; + + wcache_tdc_store_list( NULL, 0 ); + + return; +} + + +/********************************************************************* + ********************************************************************/ + +static void wcache_save_user_pwinfo(struct winbindd_domain *domain, + NTSTATUS status, + const DOM_SID *user_sid, + const char *homedir, + const char *shell, + const char *gecos, + uint32 gid) +{ + struct cache_entry *centry; + + if ( (centry = centry_start(domain, status)) == NULL ) + return; + + centry_put_string( centry, homedir ); + centry_put_string( centry, shell ); + centry_put_string( centry, gecos ); + centry_put_uint32( centry, gid ); + + centry_end(centry, "NSS/PWINFO/%s", sid_string_static(user_sid) ); + + DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_static(user_sid) )); + + centry_free(centry); +} + +NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, + const DOM_SID *user_sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, LDAPMessage *msg, + char **homedir, char **shell, char **gecos, + gid_t *p_gid) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS nt_status; + + if (!cache->tdb) + goto do_query; + + centry = wcache_fetch(cache, domain, "NSS/PWINFO/%s", sid_string_static(user_sid)); + + if (!centry) + goto do_query; + + *homedir = centry_string( centry, ctx ); + *shell = centry_string( centry, ctx ); + *gecos = centry_string( centry, ctx ); + *p_gid = centry_uint32( centry ); + + centry_free(centry); + + DEBUG(10,("nss_get_info_cached: [Cached] - user_sid %s\n", + sid_string_static(user_sid))); + + return NT_STATUS_OK; + +do_query: + + nt_status = nss_get_info( domain->name, user_sid, ctx, ads, msg, + homedir, shell, gecos, p_gid ); + + if ( NT_STATUS_IS_OK(nt_status) ) { + wcache_save_user_pwinfo( domain, nt_status, user_sid, + *homedir, *shell, *gecos, *p_gid ); + } + + if ( NT_STATUS_EQUAL( nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ) ) { + DEBUG(5,("nss_get_info_cached: Setting domain %s offline\n", + domain->name )); + set_domain_offline( domain ); + } + + return nt_status; +} + + +/* the cache backend methods are exposed via this structure */ +struct winbindd_methods cache_methods = { + True, + query_user_list, + enum_dom_groups, + enum_local_groups, + name_to_sid, + sid_to_name, + rids_to_names, + query_user, + lookup_usergroups, + lookup_useraliases, + lookup_groupmem, + sequence_number, + lockout_policy, + password_policy, + trusted_domains +}; diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c new file mode 100644 index 0000000000..99c5c0c4d1 --- /dev/null +++ b/source3/winbindd/winbindd_ccache_access.c @@ -0,0 +1,283 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - cached credentials funcions + + Copyright (C) Robert O'Callahan 2006 + Copyright (C) Jeremy Allison 2006 (minor fixes to fit into Samba and + protect against integer wrap). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static BOOL client_can_access_ccache_entry(uid_t client_uid, + struct WINBINDD_MEMORY_CREDS *entry) +{ + if (client_uid == entry->uid || client_uid == 0) { + DEBUG(10, ("Access granted to uid %d\n", client_uid)); + return True; + } + + DEBUG(1, ("Access denied to uid %d (expected %d)\n", client_uid, entry->uid)); + return False; +} + +static NTSTATUS do_ntlm_auth_with_hashes(const char *username, + const char *domain, + const unsigned char lm_hash[LM_HASH_LEN], + const unsigned char nt_hash[NT_HASH_LEN], + const DATA_BLOB initial_msg, + const DATA_BLOB challenge_msg, + DATA_BLOB *auth_msg) +{ + NTSTATUS status; + NTLMSSP_STATE *ntlmssp_state = NULL; + DATA_BLOB dummy_msg, reply; + + status = ntlmssp_client_start(&ntlmssp_state); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not start NTLMSSP client: %s\n", + nt_errstr(status))); + goto done; + } + + status = ntlmssp_set_username(ntlmssp_state, username); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set username: %s\n", + nt_errstr(status))); + goto done; + } + + status = ntlmssp_set_domain(ntlmssp_state, domain); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set domain: %s\n", + nt_errstr(status))); + goto done; + } + + status = ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set hashes: %s\n", + nt_errstr(status))); + goto done; + } + + /* We need to get our protocol handler into the right state. So first + we ask it to generate the initial message. Actually the client has already + sent its own initial message, so we're going to drop this one on the floor. + The client might have sent a different message, for example with different + negotiation options, but as far as I can tell this won't hurt us. (Unless + the client sent a different username or domain, in which case that's their + problem for telling us the wrong username or domain.) + Since we have a copy of the initial message that the client sent, we could + resolve any discrepancies if we had to. + */ + dummy_msg = data_blob_null; + reply = data_blob_null; + status = ntlmssp_update(ntlmssp_state, dummy_msg, &reply); + data_blob_free(&dummy_msg); + data_blob_free(&reply); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(1, ("Failed to create initial message! [%s]\n", + nt_errstr(status))); + goto done; + } + + /* Now we are ready to handle the server's actual response. */ + status = ntlmssp_update(ntlmssp_state, challenge_msg, &reply); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) { + DEBUG(1, ("We didn't get a response to the challenge! [%s]\n", + nt_errstr(status))); + data_blob_free(&reply); + goto done; + } + *auth_msg = reply; + status = NT_STATUS_OK; + +done: + ntlmssp_end(&ntlmssp_state); + return status; +} + +static BOOL check_client_uid(struct winbindd_cli_state *state, uid_t uid) +{ + int ret; + uid_t ret_uid; + + ret_uid = (uid_t)-1; + + ret = sys_getpeereid(state->sock, &ret_uid); + if (ret != 0) { + DEBUG(1, ("check_client_uid: Could not get socket peer uid: %s; " + "denying access\n", strerror(errno))); + return False; + } + + if (uid != ret_uid) { + DEBUG(1, ("check_client_uid: Client lied about its uid: said %d, " + "actually was %d; denying access\n", + uid, ret_uid)); + return False; + } + + return True; +} + +void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, name_user; + + /* Ensure null termination */ + state->request.data.ccache_ntlm_auth.user[ + sizeof(state->request.data.ccache_ntlm_auth.user)-1]='\0'; + + DEBUG(3, ("[%5lu]: perform NTLM auth on behalf of user %s\n", (unsigned long)state->pid, + state->request.data.ccache_ntlm_auth.user)); + + /* Parse domain and username */ + + if (!canonicalize_username(state->request.data.ccache_ntlm_auth.user, + name_domain, name_user)) { + DEBUG(5,("winbindd_ccache_ntlm_auth: cannot parse domain and user from name [%s]\n", + state->request.data.ccache_ntlm_auth.user)); + request_error(state); + return; + } + + domain = find_auth_domain(state, name_domain); + + if (domain == NULL) { + DEBUG(5,("winbindd_ccache_ntlm_auth: can't get domain [%s]\n", + name_domain)); + request_error(state); + return; + } + + if (!check_client_uid(state, state->request.data.ccache_ntlm_auth.uid)) { + request_error(state); + return; + } + + sendto_domain(state, domain); +} + +enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_NOT_SUPPORTED; + struct WINBINDD_MEMORY_CREDS *entry; + DATA_BLOB initial, challenge, auth; + fstring name_domain, name_user; + uint32 initial_blob_len, challenge_blob_len, extra_len; + + /* Ensure null termination */ + state->request.data.ccache_ntlm_auth.user[ + sizeof(state->request.data.ccache_ntlm_auth.user)-1]='\0'; + + DEBUG(3, ("winbindd_dual_ccache_ntlm_auth: [%5lu]: perform NTLM auth on " + "behalf of user %s (dual)\n", (unsigned long)state->pid, + state->request.data.ccache_ntlm_auth.user)); + + /* validate blob lengths */ + initial_blob_len = state->request.data.ccache_ntlm_auth.initial_blob_len; + challenge_blob_len = state->request.data.ccache_ntlm_auth.challenge_blob_len; + extra_len = state->request.extra_len; + + if (initial_blob_len > extra_len || challenge_blob_len > extra_len || + initial_blob_len + challenge_blob_len > extra_len || + initial_blob_len + challenge_blob_len < initial_blob_len || + initial_blob_len + challenge_blob_len < challenge_blob_len) { + + DEBUG(10,("winbindd_dual_ccache_ntlm_auth: blob lengths overrun " + "or wrap. Buffer [%d+%d > %d]\n", + initial_blob_len, + challenge_blob_len, + extra_len)); + goto process_result; + } + + /* Parse domain and username */ + if (!parse_domain_user(state->request.data.ccache_ntlm_auth.user, name_domain, name_user)) { + DEBUG(10,("winbindd_dual_ccache_ntlm_auth: cannot parse " + "domain and user from name [%s]\n", + state->request.data.ccache_ntlm_auth.user)); + goto process_result; + } + + entry = find_memory_creds_by_name(state->request.data.ccache_ntlm_auth.user); + if (entry == NULL || entry->nt_hash == NULL || entry->lm_hash == NULL) { + DEBUG(10,("winbindd_dual_ccache_ntlm_auth: could not find " + "credentials for user %s\n", + state->request.data.ccache_ntlm_auth.user)); + goto process_result; + } + + DEBUG(10,("winbindd_dual_ccache_ntlm_auth: found ccache [%s]\n", entry->username)); + + if (!client_can_access_ccache_entry(state->request.data.ccache_ntlm_auth.uid, entry)) { + goto process_result; + } + + if (initial_blob_len == 0 && challenge_blob_len == 0) { + /* this is just a probe to see if credentials are available. */ + result = NT_STATUS_OK; + state->response.data.ccache_ntlm_auth.auth_blob_len = 0; + goto process_result; + } + + initial = data_blob(state->request.extra_data.data, initial_blob_len); + challenge = data_blob(state->request.extra_data.data + initial_blob_len, + state->request.data.ccache_ntlm_auth.challenge_blob_len); + + if (!initial.data || !challenge.data) { + result = NT_STATUS_NO_MEMORY; + } else { + result = do_ntlm_auth_with_hashes(name_user, name_domain, + entry->lm_hash, entry->nt_hash, + initial, challenge, &auth); + } + + data_blob_free(&initial); + data_blob_free(&challenge); + + if (!NT_STATUS_IS_OK(result)) { + goto process_result; + } + + state->response.extra_data.data = smb_xmemdup(auth.data, auth.length); + if (!state->response.extra_data.data) { + result = NT_STATUS_NO_MEMORY; + goto process_result; + } + state->response.length += auth.length; + state->response.data.ccache_ntlm_auth.auth_blob_len = auth.length; + + data_blob_free(&auth); + + process_result: + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c new file mode 100644 index 0000000000..9ffb3dfb23 --- /dev/null +++ b/source3/winbindd/winbindd_cm.c @@ -0,0 +1,2271 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon connection manager + + Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Gerald (Jerry) Carter 2003-2005. + Copyright (C) Volker Lendecke 2004-2005 + Copyright (C) Jeremy Allison 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + We need to manage connections to domain controllers without having to + mess up the main winbindd code with other issues. The aim of the + connection manager is to: + + - make connections to domain controllers and cache them + - re-establish connections when networks or servers go down + - centralise the policy on connection timeouts, domain controller + selection etc + - manage re-entrancy for when winbindd becomes able to handle + multiple outstanding rpc requests + + Why not have connection management as part of the rpc layer like tng? + Good question. This code may morph into libsmb/rpc_cache.c or something + like that but at the moment it's simply staying as part of winbind. I + think the TNG architecture of forcing every user of the rpc layer to use + the connection caching system is a bad idea. It should be an optional + method of using the routines. + + The TNG design is quite good but I disagree with some aspects of the + implementation. -tpot + + */ + +/* + TODO: + + - I'm pretty annoyed by all the make_nmb_name() stuff. It should be + moved down into another function. + + - Take care when destroying cli_structs as they can be shared between + various sam handles. + + */ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +struct dc_name_ip { + fstring name; + struct in_addr ip; +}; + +extern struct winbindd_methods reconnect_methods; +extern BOOL override_logfile; + +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain); +static void set_dc_type_and_flags( struct winbindd_domain *domain ); +static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, + struct dc_name_ip **dcs, int *num_dcs); + +/**************************************************************** + Child failed to find DC's. Reschedule check. +****************************************************************/ + +static void msg_failed_to_go_online(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_domain *domain; + const char *domainname = (const char *)data->data; + + if (data->data == NULL || data->length == 0) { + return; + } + + DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname)); + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + + if (strequal(domain->name, domainname)) { + if (domain->online) { + /* We're already online, ignore. */ + DEBUG(5,("msg_fail_to_go_online: domain %s " + "already online.\n", domainname)); + continue; + } + + /* Reschedule the online check. */ + set_domain_offline(domain); + break; + } + } +} + +/**************************************************************** + Actually cause a reconnect from a message. +****************************************************************/ + +static void msg_try_to_go_online(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_domain *domain; + const char *domainname = (const char *)data->data; + + if (data->data == NULL || data->length == 0) { + return; + } + + DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname)); + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + + if (strequal(domain->name, domainname)) { + + if (domain->online) { + /* We're already online, ignore. */ + DEBUG(5,("msg_try_to_go_online: domain %s " + "already online.\n", domainname)); + continue; + } + + /* This call takes care of setting the online + flag to true if we connected, or re-adding + the offline handler if false. Bypasses online + check so always does network calls. */ + + init_dc_connection_network(domain); + break; + } + } +} + +/**************************************************************** + Fork a child to try and contact a DC. Do this as contacting a + DC requires blocking lookups and we don't want to block our + parent. +****************************************************************/ + +static BOOL fork_child_dc_connect(struct winbindd_domain *domain) +{ + struct dc_name_ip *dcs = NULL; + int num_dcs = 0; + TALLOC_CTX *mem_ctx = NULL; + pid_t child_pid; + pid_t parent_pid = sys_getpid(); + + /* Stop zombies */ + CatchChild(); + + child_pid = sys_fork(); + + if (child_pid == -1) { + DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno))); + return False; + } + + if (child_pid != 0) { + /* Parent */ + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_TRY_TO_GO_ONLINE, + msg_try_to_go_online); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_FAILED_TO_GO_ONLINE, + msg_failed_to_go_online); + return True; + } + + /* Child. */ + + /* Leave messages blocked - we will never process one. */ + + /* tdb needs special fork handling */ + if (tdb_reopen_all(1) == -1) { + DEBUG(0,("tdb_reopen_all failed.\n")); + _exit(0); + } + + close_conns_after_fork(); + + if (!override_logfile) { + pstring logfile; + pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE); + lp_set_logfile(logfile); + reopen_logs(); + } + + mem_ctx = talloc_init("fork_child_dc_connect"); + if (!mem_ctx) { + DEBUG(0,("talloc_init failed.\n")); + _exit(0); + } + + if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) { + /* Still offline ? Can't find DC's. */ + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_FAILED_TO_GO_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); + _exit(0); + } + + /* We got a DC. Send a message to our parent to get it to + try and do the same. */ + + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_TRY_TO_GO_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); + _exit(0); +} + +/**************************************************************** + Handler triggered if we're offline to try and detect a DC. +****************************************************************/ + +static void check_domain_online_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct winbindd_domain *domain = + (struct winbindd_domain *)private_data; + + DEBUG(10,("check_domain_online_handler: called for domain " + "%s (online = %s)\n", domain->name, + domain->online ? "True" : "False" )); + + TALLOC_FREE(domain->check_online_event); + + /* Are we still in "startup" mode ? */ + + if (domain->startup && (now->tv_sec > domain->startup_time + 30)) { + /* No longer in "startup" mode. */ + DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n", + domain->name )); + domain->startup = False; + } + + /* We've been told to stay offline, so stay + that way. */ + + if (get_global_winbindd_state_offline()) { + DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n", + domain->name )); + return; + } + + /* Fork a child to test if it can contact a DC. + If it can then send ourselves a message to + cause a reconnect. */ + + fork_child_dc_connect(domain); +} + +/**************************************************************** + If we're still offline setup the timeout check. +****************************************************************/ + +static void calc_new_online_timeout_check(struct winbindd_domain *domain) +{ + int wbc = lp_winbind_cache_time(); + + if (domain->startup) { + domain->check_online_timeout = 10; + } else if (domain->check_online_timeout < wbc) { + domain->check_online_timeout = wbc; + } +} + +/**************************************************************** + Set domain offline and also add handler to put us back online + if we detect a DC. +****************************************************************/ + +void set_domain_offline(struct winbindd_domain *domain) +{ + DEBUG(10,("set_domain_offline: called for domain %s\n", + domain->name )); + + TALLOC_FREE(domain->check_online_event); + + if (domain->internal) { + DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n", + domain->name )); + return; + } + + domain->online = False; + + /* Offline domains are always initialized. They're + re-initialized when they go back online. */ + + domain->initialized = True; + + /* We only add the timeout handler that checks and + allows us to go back online when we've not + been told to remain offline. */ + + if (get_global_winbindd_state_offline()) { + DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n", + domain->name )); + return; + } + + /* If we're in statup mode, check again in 10 seconds, not in + lp_winbind_cache_time() seconds (which is 5 mins by default). */ + + calc_new_online_timeout_check(domain); + + domain->check_online_event = event_add_timed(winbind_event_context(), + NULL, + timeval_current_ofs(domain->check_online_timeout,0), + "check_domain_online_handler", + check_domain_online_handler, + domain); + + /* The above *has* to succeed for winbindd to work. */ + if (!domain->check_online_event) { + smb_panic("set_domain_offline: failed to add online handler"); + } + + DEBUG(10,("set_domain_offline: added event handler for domain %s\n", + domain->name )); + + /* Send an offline message to the idmap child when our + primary domain goes offline */ + + if ( domain->primary ) { + struct winbindd_child *idmap = idmap_child(); + + if ( idmap->pid != 0 ) { + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(idmap->pid), + MSG_WINBIND_OFFLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); + } + } + + return; +} + +/**************************************************************** + Set domain online - if allowed. +****************************************************************/ + +static void set_domain_online(struct winbindd_domain *domain) +{ + struct timeval now; + + DEBUG(10,("set_domain_online: called for domain %s\n", + domain->name )); + + if (domain->internal) { + DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n", + domain->name )); + return; + } + + if (get_global_winbindd_state_offline()) { + DEBUG(10,("set_domain_online: domain %s remaining globally offline\n", + domain->name )); + return; + } + + winbindd_set_locator_kdc_envs(domain); + + /* If we are waiting to get a krb5 ticket, trigger immediately. */ + GetTimeOfDay(&now); + set_event_dispatch_time(winbind_event_context(), + "krb5_ticket_gain_handler", now); + + /* Ok, we're out of any startup mode now... */ + domain->startup = False; + + if (domain->online == False) { + /* We were offline - now we're online. We default to + using the MS-RPC backend if we started offline, + and if we're going online for the first time we + should really re-initialize the backends and the + checks to see if we're talking to an AD or NT domain. + */ + + domain->initialized = False; + + /* 'reconnect_methods' is the MS-RPC backend. */ + if (domain->backend == &reconnect_methods) { + domain->backend = NULL; + } + } + + /* Ensure we have no online timeout checks. */ + domain->check_online_timeout = 0; + TALLOC_FREE(domain->check_online_event); + + /* Ensure we ignore any pending child messages. */ + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_TRY_TO_GO_ONLINE, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL); + + domain->online = True; + + /* Send an online message to the idmap child when our + primary domain comes online */ + + if ( domain->primary ) { + struct winbindd_child *idmap = idmap_child(); + + if ( idmap->pid != 0 ) { + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(idmap->pid), + MSG_WINBIND_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); + } + } + + return; +} + +/**************************************************************** + Requested to set a domain online. +****************************************************************/ + +void set_domain_online_request(struct winbindd_domain *domain) +{ + struct timeval tev; + + DEBUG(10,("set_domain_online_request: called for domain %s\n", + domain->name )); + + if (get_global_winbindd_state_offline()) { + DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n", + domain->name )); + return; + } + + /* We've been told it's safe to go online and + try and connect to a DC. But I don't believe it + because network manager seems to lie. + Wait at least 5 seconds. Heuristics suck... */ + + if (!domain->check_online_event) { + /* If we've come from being globally offline we + don't have a check online event handler set. + We need to add one now we're trying to go + back online. */ + + DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n", + domain->name )); + + domain->check_online_event = event_add_timed(winbind_event_context(), + NULL, + timeval_current_ofs(5, 0), + "check_domain_online_handler", + check_domain_online_handler, + domain); + + /* The above *has* to succeed for winbindd to work. */ + if (!domain->check_online_event) { + smb_panic("set_domain_online_request: failed to add online handler"); + } + } + + GetTimeOfDay(&tev); + + /* Go into "startup" mode again. */ + domain->startup_time = tev.tv_sec; + domain->startup = True; + + tev.tv_sec += 5; + + set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev); +} + +/**************************************************************** + Add -ve connection cache entries for domain and realm. +****************************************************************/ + +void winbind_add_failed_connection_entry(const struct winbindd_domain *domain, + const char *server, + NTSTATUS result) +{ + add_failed_connection_entry(domain->name, server, result); + /* If this was the saf name for the last thing we talked to, + remove it. */ + saf_delete(domain->name); + if (*domain->alt_name) { + add_failed_connection_entry(domain->alt_name, server, result); + saf_delete(domain->alt_name); + } + winbindd_unset_locator_kdc_env(domain); +} + +/* Choose between anonymous or authenticated connections. We need to use + an authenticated connection if DCs have the RestrictAnonymous registry + entry set > 0, or the "Additional restrictions for anonymous + connections" set in the win2k Local Security Policy. + + Caller to free() result in domain, username, password +*/ + +static void cm_get_ipc_userpass(char **username, char **domain, char **password) +{ + *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL); + *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); + *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); + + if (*username && **username) { + + if (!*domain || !**domain) + *domain = smb_xstrdup(lp_workgroup()); + + if (!*password || !**password) + *password = smb_xstrdup(""); + + DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", + *domain, *username)); + + } else { + DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n")); + *username = smb_xstrdup(""); + *domain = smb_xstrdup(""); + *password = smb_xstrdup(""); + } +} + +static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, + fstring dcname, struct in_addr *dc_ip) +{ + struct winbindd_domain *our_domain = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; + NTSTATUS result; + WERROR werr; + TALLOC_CTX *mem_ctx; + unsigned int orig_timeout; + fstring tmp; + char *p; + + /* Hmmmm. We can only open one connection to the NETLOGON pipe at the + * moment.... */ + + if (IS_DC) { + return False; + } + + if (domain->primary) { + return False; + } + + our_domain = find_our_domain(); + + if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) { + return False; + } + + result = cm_connect_netlogon(our_domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + talloc_destroy(mem_ctx); + return False; + } + + /* This call can take a long time - allow the server to time out. + 35 seconds should do it. */ + + orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); + + werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname, + domain->name, tmp); + + /* And restore our original timeout. */ + cli_set_timeout(netlogon_pipe->cli, orig_timeout); + + talloc_destroy(mem_ctx); + + if (!W_ERROR_IS_OK(werr)) { + DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n", + dos_errstr(werr))); + return False; + } + + /* cli_netlogon_getanydcname gives us a name with \\ */ + p = tmp; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } + + fstrcpy(dcname, p); + + DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname)); + + if (!resolve_name(dcname, dc_ip, 0x20)) { + return False; + } + + return True; +} + +/************************************************************************ + Given a fd with a just-connected TCP connection to a DC, open a connection + to the pipe. +************************************************************************/ + +static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, + const int sockfd, + const char *controller, + struct cli_state **cli, + BOOL *retry) +{ + char *machine_password, *machine_krb5_principal, *machine_account; + char *ipc_username, *ipc_domain, *ipc_password; + + BOOL got_mutex; + + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + struct sockaddr peeraddr; + socklen_t peeraddr_len; + + struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr; + + DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n", + controller, domain->name )); + + machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, + NULL); + + if (asprintf(&machine_account, "%s$", global_myname()) == -1) { + SAFE_FREE(machine_password); + return NT_STATUS_NO_MEMORY; + } + + if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), + lp_realm()) == -1) { + SAFE_FREE(machine_account); + SAFE_FREE(machine_password); + return NT_STATUS_NO_MEMORY; + } + + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + + *retry = True; + + got_mutex = secrets_named_mutex(controller, + WINBIND_SERVER_MUTEX_WAIT_TIME); + + if (!got_mutex) { + DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n", + controller)); + result = NT_STATUS_POSSIBLE_DEADLOCK; + goto done; + } + + if ((*cli = cli_initialise()) == NULL) { + DEBUG(1, ("Could not cli_initialize\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + (*cli)->timeout = 10000; /* 10 seconds */ + (*cli)->fd = sockfd; + fstrcpy((*cli)->desthost, controller); + (*cli)->use_kerberos = True; + + peeraddr_len = sizeof(peeraddr); + + if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) || + (peeraddr_len != sizeof(struct sockaddr_in)) || + (peeraddr_in->sin_family != PF_INET)) + { + DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno))); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (ntohs(peeraddr_in->sin_port) == 139) { + struct nmb_name calling; + struct nmb_name called; + + make_nmb_name(&calling, global_myname(), 0x0); + make_nmb_name(&called, "*SMBSERVER", 0x20); + + if (!cli_session_request(*cli, &calling, &called)) { + DEBUG(8, ("cli_session_request failed for %s\n", + controller)); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } + + cli_setup_signing_state(*cli, Undefined); + + if (!cli_negprot(*cli)) { + DEBUG(1, ("cli_negprot failed\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { + ADS_STATUS ads_status; + + if (lp_security() == SEC_ADS) { + + /* Try a krb5 session */ + + (*cli)->use_kerberos = True; + DEBUG(5, ("connecting to %s from %s with kerberos principal " + "[%s]\n", controller, global_myname(), + machine_krb5_principal)); + + winbindd_set_locator_kdc_envs(domain); + + ads_status = cli_session_setup_spnego(*cli, + machine_krb5_principal, + machine_password, + lp_workgroup()); + + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4,("failed kerberos session setup with %s\n", + ads_errstr(ads_status))); + } + + result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } + } + + /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */ + (*cli)->use_kerberos = False; + + DEBUG(5, ("connecting to %s from %s with username " + "[%s]\\[%s]\n", controller, global_myname(), + lp_workgroup(), machine_account)); + + ads_status = cli_session_setup_spnego(*cli, + machine_account, + machine_password, + lp_workgroup()); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4, ("authenticated session setup failed with %s\n", + ads_errstr(ads_status))); + } + + result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } + } + + /* Fall back to non-kerberos session setup */ + + (*cli)->use_kerberos = False; + + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && + (strlen(ipc_username) > 0)) { + + /* Only try authenticated if we have a username */ + + DEBUG(5, ("connecting to %s from %s with username " + "[%s]\\[%s]\n", controller, global_myname(), + ipc_domain, ipc_username)); + + if (NT_STATUS_IS_OK(cli_session_setup( + *cli, ipc_username, + ipc_password, strlen(ipc_password)+1, + ipc_password, strlen(ipc_password)+1, + ipc_domain))) { + /* Successful logon with given username. */ + cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password); + goto session_setup_done; + } else { + DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n", + ipc_domain, ipc_username )); + } + } + + /* Fall back to anonymous connection, this might fail later */ + + if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0, + NULL, 0, ""))) { + DEBUG(5, ("Connected anonymously\n")); + cli_init_creds(*cli, "", "", ""); + goto session_setup_done; + } + + result = cli_nt_error(*cli); + + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + + /* We can't session setup */ + + goto done; + + session_setup_done: + + /* cache the server name for later connections */ + + saf_store( domain->name, (*cli)->desthost ); + if (domain->alt_name && (*cli)->use_kerberos) { + saf_store( domain->alt_name, (*cli)->desthost ); + } + + winbindd_set_locator_kdc_envs(domain); + + if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) { + + result = cli_nt_error(*cli); + + DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); + + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + + goto done; + } + + secrets_named_mutex_release(controller); + got_mutex = False; + *retry = False; + + /* set the domain if empty; needed for schannel connections */ + if ( !*(*cli)->domain ) { + fstrcpy( (*cli)->domain, domain->name ); + } + + result = NT_STATUS_OK; + + done: + if (got_mutex) { + secrets_named_mutex_release(controller); + } + + SAFE_FREE(machine_account); + SAFE_FREE(machine_password); + SAFE_FREE(machine_krb5_principal); + SAFE_FREE(ipc_username); + SAFE_FREE(ipc_domain); + SAFE_FREE(ipc_password); + + if (!NT_STATUS_IS_OK(result)) { + winbind_add_failed_connection_entry(domain, controller, result); + if ((*cli) != NULL) { + cli_shutdown(*cli); + *cli = NULL; + } + } + + return result; +} + +static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, + const char *dcname, struct in_addr ip, + struct dc_name_ip **dcs, int *num) +{ + if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) { + DEBUG(10, ("DC %s was in the negative conn cache\n", dcname)); + return False; + } + + *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1); + + if (*dcs == NULL) + return False; + + fstrcpy((*dcs)[*num].name, dcname); + (*dcs)[*num].ip = ip; + *num += 1; + return True; +} + +static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx, + struct in_addr ip, uint16 port, + struct sockaddr_in **addrs, int *num) +{ + *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1); + + if (*addrs == NULL) { + *num = 0; + return False; + } + + (*addrs)[*num].sin_family = PF_INET; + putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip); + (*addrs)[*num].sin_port = htons(port); + + *num += 1; + return True; +} + +static void mailslot_name(struct in_addr dc_ip, fstring name) +{ + fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr); +} + +static BOOL send_getdc_request(struct in_addr dc_ip, + const char *domain_name, + const DOM_SID *sid) +{ + pstring outbuf; + char *p; + fstring my_acct_name; + fstring my_mailslot; + + mailslot_name(dc_ip, my_mailslot); + + memset(outbuf, '\0', sizeof(outbuf)); + + p = outbuf; + + SCVAL(p, 0, SAMLOGON); + p++; + + SCVAL(p, 0, 0); /* Count pointer ... */ + p++; + + SIVAL(p, 0, 0); /* The sender's token ... */ + p += 2; + + p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True); + fstr_sprintf(my_acct_name, "%s$", global_myname()); + p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True); + + memcpy(p, my_mailslot, strlen(my_mailslot)+1); + p += strlen(my_mailslot)+1; + + SIVAL(p, 0, 0x80); + p+=4; + + SIVAL(p, 0, sid_size(sid)); + p+=4; + + p = ALIGN4(p, outbuf); + + sid_linearize(p, sid_size(sid), sid); + p += sid_size(sid); + + SIVAL(p, 0, 1); + SSVAL(p, 4, 0xffff); + SSVAL(p, 6, 0xffff); + p+=8; + + return cli_send_mailslot(winbind_messaging_context(), + False, "\\MAILSLOT\\NET\\NTLOGON", 0, + outbuf, PTR_DIFF(p, outbuf), + global_myname(), 0, domain_name, 0x1c, + dc_ip); +} + +static BOOL receive_getdc_response(struct in_addr dc_ip, + const char *domain_name, + fstring dc_name) +{ + struct packet_struct *packet; + fstring my_mailslot; + char *buf, *p; + fstring dcname, user, domain; + int len; + + mailslot_name(dc_ip, my_mailslot); + + packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot); + + if (packet == NULL) { + DEBUG(5, ("Did not receive packet for %s\n", my_mailslot)); + return False; + } + + DEBUG(5, ("Received packet for %s\n", my_mailslot)); + + buf = packet->packet.dgram.data; + len = packet->packet.dgram.datasize; + + if (len < 70) { + /* 70 is a completely arbitrary value to make sure + the SVAL below does not read uninitialized memory */ + DEBUG(3, ("GetDC got short response\n")); + return False; + } + + /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */ + p = buf+SVAL(buf, smb_vwv10); + + if (CVAL(p,0) != SAMLOGON_R) { + DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0))); + return False; + } + + p+=2; + pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + + if (!strequal(domain, domain_name)) { + DEBUG(3, ("GetDC: Expected domain %s, got %s\n", + domain_name, domain)); + return False; + } + + p = dcname; + if (*p == '\\') p += 1; + if (*p == '\\') p += 1; + + fstrcpy(dc_name, p); + + DEBUG(10, ("GetDC gave name %s for domain %s\n", + dc_name, domain)); + + return True; +} + +/******************************************************************* + convert an ip to a name +*******************************************************************/ + +static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name ) +{ + struct ip_service ip_list; + + ip_list.ip = ip; + ip_list.port = 0; + +#ifdef WITH_ADS + /* For active directory servers, try to get the ldap server name. + None of these failures should be considered critical for now */ + + if (lp_security() == SEC_ADS) { + ADS_STRUCT *ads; + + ads = ads_init(domain->alt_name, domain->name, NULL); + ads->auth.flags |= ADS_AUTH_NO_BIND; + + if (ads_try_connect( ads, inet_ntoa(ip) ) ) { + /* We got a cldap packet. */ + fstrcpy(name, ads->config.ldap_server_name); + namecache_store(name, 0x20, 1, &ip_list); + + DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags)); + + if (domain->primary && (ads->config.flags & ADS_KDC)) { + if (ads_closest_dc(ads)) { + char *sitename = sitename_fetch(ads->config.realm); + + /* We're going to use this KDC for this realm/domain. + If we are using sites, then force the krb5 libs + to use this KDC. */ + + create_local_private_krb5_conf_for_domain(domain->alt_name, + domain->name, + sitename, + ip); + + SAFE_FREE(sitename); + } else { + /* use an off site KDC */ + create_local_private_krb5_conf_for_domain(domain->alt_name, + domain->name, + NULL, + ip); + } + winbindd_set_locator_kdc_envs(domain); + + /* Ensure we contact this DC also. */ + saf_store( domain->name, name); + saf_store( domain->alt_name, name); + } + + ads_destroy( &ads ); + return True; + } + + ads_destroy( &ads ); + } +#endif + + /* try GETDC requests next */ + + if (send_getdc_request(ip, domain->name, &domain->sid)) { + int i; + smb_msleep(100); + for (i=0; i<5; i++) { + if (receive_getdc_response(ip, domain->name, name)) { + namecache_store(name, 0x20, 1, &ip_list); + return True; + } + smb_msleep(500); + } + } + + /* try node status request */ + + if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) { + namecache_store(name, 0x20, 1, &ip_list); + return True; + } + return False; +} + +/******************************************************************* + Retreive a list of IP address for domain controllers. Fill in + the dcs[] with results. +*******************************************************************/ + +static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, + struct dc_name_ip **dcs, int *num_dcs) +{ + fstring dcname; + struct in_addr ip; + struct ip_service *ip_list = NULL; + int iplist_size = 0; + int i; + BOOL is_our_domain; + enum security_types sec = (enum security_types)lp_security(); + + is_our_domain = strequal(domain->name, lp_workgroup()); + + if ( !is_our_domain + && get_dc_name_via_netlogon(domain, dcname, &ip) + && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) ) + { + DEBUG(10, ("Retrieved DC %s at %s via netlogon\n", + dcname, inet_ntoa(ip))); + return True; + } + + if (sec == SEC_ADS) { + char *sitename = NULL; + + /* We need to make sure we know the local site before + doing any DNS queries, as this will restrict the + get_sorted_dc_list() call below to only fetching + DNS records for the correct site. */ + + /* Find any DC to get the site record. + We deliberately don't care about the + return here. */ + + get_dc_name(domain->name, domain->alt_name, dcname, &ip); + + sitename = sitename_fetch(domain->alt_name); + if (sitename) { + + /* Do the site-specific AD dns lookup first. */ + get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True); + + for ( i=0; iname, inet_ntoa(ip_list[i].ip), + ip_list[i].ip, dcs, num_dcs); + } + + SAFE_FREE(ip_list); + SAFE_FREE(sitename); + iplist_size = 0; + } + + /* Now we add DCs from the main AD dns lookup. */ + get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True); + + for ( i=0; iname, inet_ntoa(ip_list[i].ip), + ip_list[i].ip, dcs, num_dcs); + } + } + + /* try standard netbios queries if no ADS */ + + if (iplist_size==0) { + get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False); + } + + /* FIXME!! this is where we should re-insert the GETDC requests --jerry */ + + /* now add to the dc array. We'll wait until the last minute + to look up the name of the DC. But we fill in the char* for + the ip now in to make the failed connection cache work */ + + for ( i=0; iname, inet_ntoa(ip_list[i].ip), + ip_list[i].ip, dcs, num_dcs); + } + + SAFE_FREE( ip_list ); + + return True; +} + +static BOOL find_new_dc(TALLOC_CTX *mem_ctx, + const struct winbindd_domain *domain, + fstring dcname, struct sockaddr_in *addr, int *fd) +{ + struct dc_name_ip *dcs = NULL; + int num_dcs = 0; + + const char **dcnames = NULL; + int num_dcnames = 0; + + struct sockaddr_in *addrs = NULL; + int num_addrs = 0; + + int i, fd_index; + + again: + if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0)) + return False; + + for (i=0; iname, inet_ntoa(dcs[i].ip), strerror(errno) )); + winbind_add_failed_connection_entry(domain, + dcs[i].name, NT_STATUS_UNSUCCESSFUL); + } + return False; + } + + *addr = addrs[fd_index]; + + if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) { + /* Ok, we've got a name for the DC */ + fstrcpy(dcname, dcnames[fd_index]); + return True; + } + + /* Try to figure out the name */ + if (dcip_to_name( domain, addr->sin_addr, dcname )) { + return True; + } + + /* We can not continue without the DC's name */ + winbind_add_failed_connection_entry(domain, dcs[fd_index].name, + NT_STATUS_UNSUCCESSFUL); + goto again; +} + +static NTSTATUS cm_open_connection(struct winbindd_domain *domain, + struct winbindd_cm_conn *new_conn) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS result; + char *saf_servername = saf_fetch( domain->name ); + int retries; + + if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) { + SAFE_FREE(saf_servername); + set_domain_offline(domain); + return NT_STATUS_NO_MEMORY; + } + + /* we have to check the server affinity cache here since + later we selecte a DC based on response time and not preference */ + + /* Check the negative connection cache + before talking to it. It going down may have + triggered the reconnection. */ + + if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) { + + DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n", + saf_servername, domain->name )); + + /* convert an ip address to a name */ + if ( is_ipaddress( saf_servername ) ) { + fstring saf_name; + struct in_addr ip; + + ip = *interpret_addr2( saf_servername ); + if (dcip_to_name( domain, ip, saf_name )) { + fstrcpy( domain->dcname, saf_name ); + } else { + winbind_add_failed_connection_entry( + domain, saf_servername, + NT_STATUS_UNSUCCESSFUL); + } + } else { + fstrcpy( domain->dcname, saf_servername ); + } + + SAFE_FREE( saf_servername ); + } + + for (retries = 0; retries < 3; retries++) { + + int fd = -1; + BOOL retry = False; + + result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + + DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n", + domain->dcname, domain->name )); + + if (*domain->dcname + && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) + && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20))) + { + struct sockaddr_in *addrs = NULL; + int num_addrs = 0; + int dummy = 0; + + if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) { + set_domain_offline(domain); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) { + set_domain_offline(domain); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + /* 5 second timeout. */ + if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) { + fd = -1; + } + } + + if ((fd == -1) + && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd)) + { + /* This is the one place where we will + set the global winbindd offline state + to true, if a "WINBINDD_OFFLINE" entry + is found in the winbindd cache. */ + set_global_winbindd_state_offline(); + break; + } + + new_conn->cli = NULL; + + result = cm_prepare_connection(domain, fd, domain->dcname, + &new_conn->cli, &retry); + + if (!retry) + break; + } + + if (NT_STATUS_IS_OK(result)) { + + winbindd_set_locator_kdc_envs(domain); + + if (domain->online == False) { + /* We're changing state from offline to online. */ + set_global_winbindd_state_online(); + } + set_domain_online(domain); + } else { + /* Ensure we setup the retry handler. */ + set_domain_offline(domain); + } + + talloc_destroy(mem_ctx); + return result; +} + +/* Close down all open pipes on a connection. */ + +void invalidate_cm_connection(struct winbindd_cm_conn *conn) +{ + /* We're closing down a possibly dead + connection. Don't have impossibly long (10s) timeouts. */ + + if (conn->cli) { + cli_set_timeout(conn->cli, 1000); /* 1 second. */ + } + + if (conn->samr_pipe != NULL) { + if (!cli_rpc_pipe_close(conn->samr_pipe)) { + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); + } + } + conn->samr_pipe = NULL; + } + + if (conn->lsa_pipe != NULL) { + if (!cli_rpc_pipe_close(conn->lsa_pipe)) { + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); + } + } + conn->lsa_pipe = NULL; + } + + if (conn->netlogon_pipe != NULL) { + if (!cli_rpc_pipe_close(conn->netlogon_pipe)) { + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); + } + } + conn->netlogon_pipe = NULL; + } + + if (conn->cli) { + cli_shutdown(conn->cli); + } + + conn->cli = NULL; +} + +void close_conns_after_fork(void) +{ + struct winbindd_domain *domain; + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->conn.cli == NULL) + continue; + + if (domain->conn.cli->fd == -1) + continue; + + close(domain->conn.cli->fd); + domain->conn.cli->fd = -1; + } +} + +static BOOL connection_ok(struct winbindd_domain *domain) +{ + if (domain->conn.cli == NULL) { + DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL " + "cli!\n", domain->dcname, domain->name)); + return False; + } + + if (!domain->conn.cli->initialised) { + DEBUG(3, ("connection_ok: Connection to %s for domain %s was never " + "initialised!\n", domain->dcname, domain->name)); + return False; + } + + if (domain->conn.cli->fd == -1) { + DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was " + "never started (fd == -1)\n", + domain->dcname, domain->name)); + return False; + } + + if (domain->online == False) { + DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name)); + return False; + } + + return True; +} + +/* Initialize a new connection up to the RPC BIND. + Bypass online status check so always does network calls. */ + +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) +{ + NTSTATUS result; + + /* Internal connections never use the network. */ + if (domain->internal) { + domain->initialized = True; + return NT_STATUS_OK; + } + + if (connection_ok(domain)) { + if (!domain->initialized) { + set_dc_type_and_flags(domain); + } + return NT_STATUS_OK; + } + + invalidate_cm_connection(&domain->conn); + + result = cm_open_connection(domain, &domain->conn); + + if (NT_STATUS_IS_OK(result) && !domain->initialized) { + set_dc_type_and_flags(domain); + } + + return result; +} + +NTSTATUS init_dc_connection(struct winbindd_domain *domain) +{ + if (domain->initialized && !domain->online) { + /* We check for online status elsewhere. */ + return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + } + + return init_dc_connection_network(domain); +} + +/****************************************************************************** + Set the trust flags (direction and forest location) for a domain +******************************************************************************/ + +static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) +{ + struct winbindd_domain *our_domain; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + struct ds_domain_trust *domains = NULL; + int count = 0; + int i; + uint32 flags = (DS_DOMAIN_IN_FOREST | + DS_DOMAIN_DIRECT_OUTBOUND | + DS_DOMAIN_DIRECT_INBOUND); + struct rpc_pipe_client *cli; + TALLOC_CTX *mem_ctx = NULL; + + DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name )); + + /* Our primary domain doesn't need to worry about trust flags. + Force it to go through the network setup */ + if ( domain->primary ) { + return False; + } + + our_domain = find_our_domain(); + + if ( !connection_ok(our_domain) ) { + DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n")); + return False; + } + + /* This won't work unless our domain is AD */ + + if ( !our_domain->active_directory ) { + return False; + } + + /* Use DsEnumerateDomainTrusts to get us the trust direction + and type */ + + result = cm_connect_netlogon(our_domain, &cli); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open " + "a connection to %s for PIPE_NETLOGON (%s)\n", + domain->name, nt_errstr(result))); + return False; + } + + if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) { + DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n")); + return False; + } + + result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, + cli->cli->desthost, + flags, &domains, + (unsigned int *)&count); + + /* Now find the domain name and get the flags */ + + for ( i=0; iname, domains[i].netbios_domain ) ) { + domain->domain_flags = domains[i].flags; + domain->domain_type = domains[i].trust_type; + domain->domain_trust_attribs = domains[i].trust_attributes; + + if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL ) + domain->active_directory = True; + + /* This flag is only set if the domain is *our* + primary domain and the primary domain is in + native mode */ + + domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE); + + DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin " + "native mode.\n", domain->name, + domain->native_mode ? "" : "NOT ")); + + DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s" + "running active directory.\n", domain->name, + domain->active_directory ? "" : "NOT ")); + + + domain->initialized = True; + + if ( !winbindd_can_contact_domain( domain) ) + domain->internal = True; + + break; + } + } + + talloc_destroy( mem_ctx ); + + return domain->initialized; +} + +/****************************************************************************** + We can 'sense' certain things about the DC by it's replies to certain + questions. + + This tells us if this particular remote server is Active Directory, and if it + is native mode. +******************************************************************************/ + +static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) +{ + NTSTATUS result; + DS_DOMINFO_CTR ctr; + TALLOC_CTX *mem_ctx = NULL; + struct rpc_pipe_client *cli; + POLICY_HND pol; + + char *domain_name = NULL; + char *dns_name = NULL; + char *forest_name = NULL; + DOM_SID *dom_sid = NULL; + + ZERO_STRUCT( ctr ); + + if (!connection_ok(domain)) { + return; + } + + DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); + + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, + &result); + + if (cli == NULL) { + DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " + "PI_LSARPC_DS on domain %s: (%s)\n", + domain->name, nt_errstr(result))); + + /* if this is just a non-AD domain we need to continue + * identifying so that we can in the end return with + * domain->initialized = True - gd */ + + goto no_lsarpc_ds; + } + + result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx, + DsRolePrimaryDomainInfoBasic, + &ctr); + cli_rpc_pipe_close(cli); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo " + "on domain %s failed: (%s)\n", + domain->name, nt_errstr(result))); + + /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for + * every opcode on the LSARPC_DS pipe, continue with + * no_lsarpc_ds mode here as well to get domain->initialized + * set - gd */ + + if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) { + goto no_lsarpc_ds; + } + + return; + } + + if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) && + !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) { + domain->native_mode = True; + } else { + domain->native_mode = False; + } + +no_lsarpc_ds: + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); + + if (cli == NULL) { + DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " + "PI_LSARPC on domain %s: (%s)\n", + domain->name, nt_errstr(result))); + cli_rpc_pipe_close(cli); + return; + } + + mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", + domain->name); + if (!mem_ctx) { + DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n")); + cli_rpc_pipe_close(cli); + return; + } + + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); + + if (NT_STATUS_IS_OK(result)) { + /* This particular query is exactly what Win2k clients use + to determine that the DC is active directory */ + result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol, + 12, &domain_name, + &dns_name, &forest_name, + NULL, &dom_sid); + } + + if (NT_STATUS_IS_OK(result)) { + domain->active_directory = True; + + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dns_name) + fstrcpy(domain->alt_name, dns_name); + + if ( forest_name ) + fstrcpy(domain->forest_name, forest_name); + + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + } else { + domain->active_directory = False; + + result = rpccli_lsa_open_policy(cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = rpccli_lsa_query_info_policy(cli, mem_ctx, + &pol, 5, &domain_name, + &dom_sid); + + if (NT_STATUS_IS_OK(result)) { + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + } + } +done: + + DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n", + domain->name, domain->native_mode ? "" : "NOT ")); + + DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n", + domain->name, domain->active_directory ? "" : "NOT ")); + + cli_rpc_pipe_close(cli); + + talloc_destroy(mem_ctx); + + domain->initialized = True; +} + +/********************************************************************** + Set the domain_flags (trust attributes, domain operating modes, etc... +***********************************************************************/ + +static void set_dc_type_and_flags( struct winbindd_domain *domain ) +{ + /* we always have to contact our primary domain */ + + if ( domain->primary ) { + DEBUG(10,("set_dc_type_and_flags: setting up flags for " + "primary domain\n")); + set_dc_type_and_flags_connect( domain ); + return; + } + + /* Use our DC to get the information if possible */ + + if ( !set_dc_type_and_flags_trustinfo( domain ) ) { + /* Otherwise, fallback to contacting the + domain directly */ + set_dc_type_and_flags_connect( domain ); + } + + return; +} + + + +/********************************************************************** +***********************************************************************/ + +static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, + struct dcinfo **ppdc) +{ + NTSTATUS result; + struct rpc_pipe_client *netlogon_pipe; + + if (lp_client_schannel() == False) { + return False; + } + + result = cm_connect_netlogon(domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + return False; + } + + /* Return a pointer to the struct dcinfo from the + netlogon pipe. */ + + *ppdc = domain->conn.netlogon_pipe->dc; + return True; +} + +NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **cli, POLICY_HND *sam_handle) +{ + struct winbindd_cm_conn *conn; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring conn_pwd; + struct dcinfo *p_dcinfo; + + result = init_dc_connection(domain); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + conn = &domain->conn; + + if (conn->samr_pipe != NULL) { + goto done; + } + + /* + * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated + * sign and sealed pipe using the machine account password by + * preference. If we can't - try schannel, if that fails, try + * anonymous. + */ + + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if ((conn->cli->user_name[0] == '\0') || + (conn->cli->domain[0] == '\0') || + (conn_pwd[0] == '\0')) { + DEBUG(10, ("cm_connect_sam: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + + /* We have an authenticated connection. Use a NTLMSSP SPNEGO + authenticated SAMR pipe with sign & seal. */ + conn->samr_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, + conn->cli->user_name, + conn_pwd, &result); + + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect to SAMR " + "pipe for domain %s using NTLMSSP " + "authenticated pipe: user %s\\%s. Error was " + "%s\n", domain->name, conn->cli->domain, + conn->cli->user_name, nt_errstr(result))); + goto schannel; + } + + DEBUG(10,("cm_connect_sam: connected to SAMR pipe for " + "domain %s using NTLMSSP authenticated " + "pipe: user %s\\%s\n", domain->name, + conn->cli->domain, conn->cli->user_name )); + + result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); + if (NT_STATUS_IS_OK(result)) { + goto open_domain; + } + DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect " + "failed for domain %s, error was %s. Trying schannel\n", + domain->name, nt_errstr(result) )); + cli_rpc_pipe_close(conn->samr_pipe); + + schannel: + + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + + if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + /* If this call fails - conn->cli can now be NULL ! */ + DEBUG(10, ("cm_connect_sam: Could not get schannel auth info " + "for domain %s, trying anon\n", domain->name)); + goto anonymous; + } + conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key + (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &result); + + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " + "domain %s using schannel. Error was %s\n", + domain->name, nt_errstr(result) )); + goto anonymous; + } + DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using " + "schannel.\n", domain->name )); + + result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); + if (NT_STATUS_IS_OK(result)) { + goto open_domain; + } + DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed " + "for domain %s, error was %s. Trying anonymous\n", + domain->name, nt_errstr(result) )); + cli_rpc_pipe_close(conn->samr_pipe); + + anonymous: + + /* Finally fall back to anonymous. */ + conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, + &result); + + if (conn->samr_pipe == NULL) { + result = NT_STATUS_PIPE_NOT_AVAILABLE; + goto done; + } + + result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed " + "for domain %s Error was %s\n", + domain->name, nt_errstr(result) )); + goto done; + } + + open_domain: + result = rpccli_samr_open_domain(conn->samr_pipe, + mem_ctx, + &conn->sam_connect_handle, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &domain->sid, + &conn->sam_domain_handle); + + done: + + if (!NT_STATUS_IS_OK(result)) { + invalidate_cm_connection(conn); + return result; + } + + *cli = conn->samr_pipe; + *sam_handle = conn->sam_domain_handle; + return result; +} + +NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **cli, POLICY_HND *lsa_policy) +{ + struct winbindd_cm_conn *conn; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring conn_pwd; + struct dcinfo *p_dcinfo; + + result = init_dc_connection(domain); + if (!NT_STATUS_IS_OK(result)) + return result; + + conn = &domain->conn; + + if (conn->lsa_pipe != NULL) { + goto done; + } + + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if ((conn->cli->user_name[0] == '\0') || + (conn->cli->domain[0] == '\0') || + (conn_pwd[0] == '\0')) { + DEBUG(10, ("cm_connect_lsa: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + + /* We have an authenticated connection. Use a NTLMSSP SPNEGO + * authenticated LSA pipe with sign & seal. */ + conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp + (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, conn->cli->user_name, conn_pwd, &result); + + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " + "domain %s using NTLMSSP authenticated pipe: user " + "%s\\%s. Error was %s. Trying schannel.\n", + domain->name, conn->cli->domain, + conn->cli->user_name, nt_errstr(result))); + goto schannel; + } + + DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using " + "NTLMSSP authenticated pipe: user %s\\%s\n", + domain->name, conn->cli->domain, conn->cli->user_name )); + + result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->lsa_policy); + if (NT_STATUS_IS_OK(result)) { + goto done; + } + + DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying " + "schannel\n")); + + cli_rpc_pipe_close(conn->lsa_pipe); + + schannel: + + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + + if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + /* If this call fails - conn->cli can now be NULL ! */ + DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info " + "for domain %s, trying anon\n", domain->name)); + goto anonymous; + } + conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key + (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &result); + + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " + "domain %s using schannel. Error was %s\n", + domain->name, nt_errstr(result) )); + goto anonymous; + } + DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using " + "schannel.\n", domain->name )); + + result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->lsa_policy); + if (NT_STATUS_IS_OK(result)) { + goto done; + } + + DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying " + "anonymous\n")); + + cli_rpc_pipe_close(conn->lsa_pipe); + + anonymous: + + conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC, + &result); + if (conn->lsa_pipe == NULL) { + result = NT_STATUS_PIPE_NOT_AVAILABLE; + goto done; + } + + result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->lsa_policy); + done: + if (!NT_STATUS_IS_OK(result)) { + invalidate_cm_connection(conn); + return result; + } + + *cli = conn->lsa_pipe; + *lsa_policy = conn->lsa_policy; + return result; +} + +/**************************************************************************** + Open the netlogon pipe to this DC. Use schannel if specified in client conf. + session key stored in conn->netlogon_pipe->dc->sess_key. +****************************************************************************/ + +NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + struct rpc_pipe_client **cli) +{ + struct winbindd_cm_conn *conn; + NTSTATUS result; + + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint8 mach_pwd[16]; + uint32 sec_chan_type; + const char *account_name; + struct rpc_pipe_client *netlogon_pipe = NULL; + + *cli = NULL; + + result = init_dc_connection(domain); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + conn = &domain->conn; + + if (conn->netlogon_pipe != NULL) { + *cli = conn->netlogon_pipe; + return NT_STATUS_OK; + } + + if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, + &result); + if (netlogon_pipe == NULL) { + return result; + } + + if ((!IS_DC) && (!domain->primary)) { + /* Clear the schannel request bit and drop down */ + neg_flags &= ~NETLOGON_NEG_SCHANNEL; + goto no_schannel; + } + + if (lp_client_schannel() != False) { + neg_flags |= NETLOGON_NEG_SCHANNEL; + } + + /* if we are a DC and this is a trusted domain, then we need to use our + domain name in the net_req_auth2() request */ + + if ( IS_DC + && !strequal(domain->name, lp_workgroup()) + && lp_allow_trusted_domains() ) + { + account_name = lp_workgroup(); + } else { + account_name = domain->primary ? + global_myname() : domain->name; + } + + if (account_name == NULL) { + cli_rpc_pipe_close(netlogon_pipe); + return NT_STATUS_NO_MEMORY; + } + + result = rpccli_netlogon_setup_creds( + netlogon_pipe, + domain->dcname, /* server name. */ + domain->name, /* domain name */ + global_myname(), /* client name */ + account_name, /* machine account */ + mach_pwd, /* machine password */ + sec_chan_type, /* from get_trust_pw */ + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { + cli_rpc_pipe_close(netlogon_pipe); + return result; + } + + if ((lp_client_schannel() == True) && + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + DEBUG(3, ("Server did not offer schannel\n")); + cli_rpc_pipe_close(netlogon_pipe); + return NT_STATUS_ACCESS_DENIED; + } + + no_schannel: + if ((lp_client_schannel() == False) || + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + + /* + * NetSamLogonEx only works for schannel + */ + domain->can_do_samlogon_ex = False; + + /* We're done - just keep the existing connection to NETLOGON + * open */ + conn->netlogon_pipe = netlogon_pipe; + *cli = conn->netlogon_pipe; + return NT_STATUS_OK; + } + + /* Using the credentials from the first pipe, open a signed and sealed + second netlogon pipe. The session key is stored in the schannel + part of the new pipe auth struct. + */ + + conn->netlogon_pipe = + cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + netlogon_pipe->dc, + &result); + + /* We can now close the initial netlogon pipe. */ + cli_rpc_pipe_close(netlogon_pipe); + + if (conn->netlogon_pipe == NULL) { + DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " + "was %s\n", nt_errstr(result))); + + /* make sure we return something besides OK */ + return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; + } + + /* + * Try NetSamLogonEx for AD domains + */ + domain->can_do_samlogon_ex = domain->active_directory; + + *cli = conn->netlogon_pipe; + return NT_STATUS_OK; +} diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c new file mode 100644 index 0000000000..65dcbe5a00 --- /dev/null +++ b/source3/winbindd/winbindd_cred_cache.c @@ -0,0 +1,802 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - krb5 credential cache functions + and in-memory cache functions. + + Copyright (C) Guenther Deschner 2005-2006 + Copyright (C) Jeremy Allison 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* uncomment this to do fast debugging on the krb5 ticket renewal event */ +#ifdef DEBUG_KRB5_TKT_RENEWAL +#undef DEBUG_KRB5_TKT_RENEWAL +#endif + +#define MAX_CCACHES 100 + +static struct WINBINDD_CCACHE_ENTRY *ccache_list; + +/* The Krb5 ticket refresh handler should be scheduled + at one-half of the period from now till the tkt + expiration */ +#define KRB5_EVENT_REFRESH_TIME(x) ((x) - (((x) - time(NULL))/2)) + +/**************************************************************** + Find an entry by name. +****************************************************************/ + +static struct WINBINDD_CCACHE_ENTRY *get_ccache_by_username(const char *username) +{ + struct WINBINDD_CCACHE_ENTRY *entry; + + for (entry = ccache_list; entry; entry = entry->next) { + if (strequal(entry->username, username)) { + return entry; + } + } + return NULL; +} + +/**************************************************************** + How many do we have ? +****************************************************************/ + +static int ccache_entry_count(void) +{ + struct WINBINDD_CCACHE_ENTRY *entry; + int i = 0; + + for (entry = ccache_list; entry; entry = entry->next) { + i++; + } + return i; +} + +/**************************************************************** + Do the work of refreshing the ticket. +****************************************************************/ + +static void krb5_ticket_refresh_handler(struct event_context *event_ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct WINBINDD_CCACHE_ENTRY *entry = + talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY); +#ifdef HAVE_KRB5 + int ret; + time_t new_start; + struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr; +#endif + + DEBUG(10,("krb5_ticket_refresh_handler called\n")); + DEBUGADD(10,("event called for: %s, %s\n", + entry->ccname, entry->username)); + + TALLOC_FREE(entry->event); + +#ifdef HAVE_KRB5 + + /* Kinit again if we have the user password and we can't renew the old + * tgt anymore */ + + if ((entry->renew_until < time(NULL)) && cred_ptr && cred_ptr->pass) { + + set_effective_uid(entry->uid); + + ret = kerberos_kinit_password_ext(entry->principal_name, + cred_ptr->pass, + 0, /* hm, can we do time correction here ? */ + &entry->refresh_time, + &entry->renew_until, + entry->ccname, + False, /* no PAC required anymore */ + True, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL); + gain_root_privilege(); + + if (ret) { + DEBUG(3,("krb5_ticket_refresh_handler: " + "could not re-kinit: %s\n", + error_message(ret))); + TALLOC_FREE(entry->event); + return; + } + + DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit " + "for: %s in ccache: %s\n", + entry->principal_name, entry->ccname)); + +#if defined(DEBUG_KRB5_TKT_RENEWAL) + new_start = time(NULL) + 30; +#else + /* The tkt should be refreshed at one-half the period + from now to the expiration time */ + new_start = KRB5_EVENT_REFRESH_TIME(entry->refresh_time); +#endif + goto done; + } + + set_effective_uid(entry->uid); + + ret = smb_krb5_renew_ticket(entry->ccname, + entry->principal_name, + entry->service, + &new_start); +#if defined(DEBUG_KRB5_TKT_RENEWAL) + new_start = time(NULL) + 30; +#else + new_start = KRB5_EVENT_REFRESH_TIME(new_start); +#endif + + gain_root_privilege(); + + if (ret) { + DEBUG(3,("krb5_ticket_refresh_handler: " + "could not renew tickets: %s\n", + error_message(ret))); + /* maybe we are beyond the renewing window */ + + /* avoid breaking the renewal chain: retry in + * lp_winbind_cache_time() seconds when the KDC was not + * available right now. */ + + if (ret == KRB5_KDC_UNREACH) { + new_start = time(NULL) + + MAX(30, lp_winbind_cache_time()); + goto done; + } + + return; + } + +done: + + entry->event = event_add_timed(winbind_event_context(), entry, + timeval_set(new_start, 0), + "krb5_ticket_refresh_handler", + krb5_ticket_refresh_handler, + entry); + +#endif +} + +/**************************************************************** + Do the work of regaining a ticket when coming from offline auth. +****************************************************************/ + +static void krb5_ticket_gain_handler(struct event_context *event_ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct WINBINDD_CCACHE_ENTRY *entry = + talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY); +#ifdef HAVE_KRB5 + int ret; + struct timeval t; + struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr; + struct winbindd_domain *domain = NULL; +#endif + + DEBUG(10,("krb5_ticket_gain_handler called\n")); + DEBUGADD(10,("event called for: %s, %s\n", + entry->ccname, entry->username)); + + TALLOC_FREE(entry->event); + +#ifdef HAVE_KRB5 + + if (!cred_ptr || !cred_ptr->pass) { + DEBUG(10,("krb5_ticket_gain_handler: no memory creds\n")); + return; + } + + if ((domain = find_domain_from_name(entry->realm)) == NULL) { + DEBUG(0,("krb5_ticket_gain_handler: unknown domain\n")); + return; + } + + if (!domain->online) { + goto retry_later; + } + + set_effective_uid(entry->uid); + + ret = kerberos_kinit_password_ext(entry->principal_name, + cred_ptr->pass, + 0, /* hm, can we do time correction here ? */ + &entry->refresh_time, + &entry->renew_until, + entry->ccname, + False, /* no PAC required anymore */ + True, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL); + gain_root_privilege(); + + if (ret) { + DEBUG(3,("krb5_ticket_gain_handler: " + "could not kinit: %s\n", + error_message(ret))); + goto retry_later; + } + + DEBUG(10,("krb5_ticket_gain_handler: " + "successful kinit for: %s in ccache: %s\n", + entry->principal_name, entry->ccname)); + + goto got_ticket; + + retry_later: + + t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); + + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + "krb5_ticket_gain_handler", + krb5_ticket_gain_handler, + entry); + + return; + + got_ticket: + +#if defined(DEBUG_KRB5_TKT_RENEWAL) + t = timeval_set(time(NULL) + 30, 0); +#else + t = timeval_set(KRB5_EVENT_REFRESH_TIME(entry->refresh_time), 0); +#endif + + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + "krb5_ticket_refresh_handler", + krb5_ticket_refresh_handler, + entry); + + return; +#endif +} + +/**************************************************************** + Check if an ccache entry exists. +****************************************************************/ + +BOOL ccache_entry_exists(const char *username) +{ + struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); + return (entry != NULL); +} + +/**************************************************************** + Ensure we're changing the correct entry. +****************************************************************/ + +BOOL ccache_entry_identical(const char *username, + uid_t uid, + const char *ccname) +{ + struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); + + if (!entry) { + return False; + } + + if (entry->uid != uid) { + DEBUG(0,("cache_entry_identical: uid's differ: %u != %u\n", + (unsigned int)entry->uid, (unsigned int)uid)); + return False; + } + if (!strcsequal(entry->ccname, ccname)) { + DEBUG(0,("cache_entry_identical: " + "ccnames differ: (cache) %s != (client) %s\n", + entry->ccname, ccname)); + return False; + } + return True; +} + +NTSTATUS add_ccache_to_list(const char *princ_name, + const char *ccname, + const char *service, + const char *username, + const char *realm, + uid_t uid, + time_t create_time, + time_t ticket_end, + time_t renew_until, + BOOL postponed_request) +{ + struct WINBINDD_CCACHE_ENTRY *entry = NULL; + struct timeval t; + + if ((username == NULL && princ_name == NULL) || + ccname == NULL || uid < 0) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (ccache_entry_count() + 1 > MAX_CCACHES) { + DEBUG(10,("add_ccache_to_list: " + "max number of ccaches reached\n")); + return NT_STATUS_NO_MORE_ENTRIES; + } + + /* Reference count old entries */ + entry = get_ccache_by_username(username); + if (entry) { + /* Check cached entries are identical. */ + if (!ccache_entry_identical(username, uid, ccname)) { + return NT_STATUS_INVALID_PARAMETER; + } + entry->ref_count++; + DEBUG(10,("add_ccache_to_list: " + "ref count on entry %s is now %d\n", + username, entry->ref_count)); + /* FIXME: in this case we still might want to have a krb5 cred + * event handler created - gd*/ + return NT_STATUS_OK; + } + + entry = TALLOC_P(NULL, struct WINBINDD_CCACHE_ENTRY); + if (!entry) { + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCTP(entry); + + if (username) { + entry->username = talloc_strdup(entry, username); + if (!entry->username) { + goto no_mem; + } + } + if (princ_name) { + entry->principal_name = talloc_strdup(entry, princ_name); + if (!entry->principal_name) { + goto no_mem; + } + } + if (service) { + entry->service = talloc_strdup(entry, service); + if (!entry->service) { + goto no_mem; + } + } + + entry->ccname = talloc_strdup(entry, ccname); + if (!entry->ccname) { + goto no_mem; + } + + entry->realm = talloc_strdup(entry, realm); + if (!entry->realm) { + goto no_mem; + } + + entry->create_time = create_time; + entry->renew_until = renew_until; + entry->uid = uid; + entry->ref_count = 1; + + if (!lp_winbind_refresh_tickets() || renew_until <= 0) { + goto add_entry; + } + + if (postponed_request) { + t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + "krb5_ticket_gain_handler", + krb5_ticket_gain_handler, + entry); + } else { + /* Renew at 1/2 the ticket expiration time */ +#if defined(DEBUG_KRB5_TKT_RENEWAL) + t = timeval_set(time(NULL)+30, 0); +#else + t = timeval_set(KRB5_EVENT_REFRESH_TIME(ticket_end), 0); +#endif + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + "krb5_ticket_refresh_handler", + krb5_ticket_refresh_handler, + entry); + } + + if (!entry->event) { + goto no_mem; + } + + DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n")); + + add_entry: + + DLIST_ADD(ccache_list, entry); + + DEBUG(10,("add_ccache_to_list: " + "added ccache [%s] for user [%s] to the list\n", + ccname, username)); + + return NT_STATUS_OK; + + no_mem: + + TALLOC_FREE(entry); + return NT_STATUS_NO_MEMORY; +} + +/******************************************************************* + Remove a WINBINDD_CCACHE_ENTRY entry and the krb5 ccache if no longer + referenced. + *******************************************************************/ + +NTSTATUS remove_ccache(const char *username) +{ + struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); + NTSTATUS status = NT_STATUS_OK; + #ifdef HAVE_KRB5 + krb5_error_code ret; +#endif + + if (!entry) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (entry->ref_count <= 0) { + DEBUG(0,("remove_ccache: logic error. " + "ref count for user %s = %d\n", + username, entry->ref_count)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + entry->ref_count--; + + if (entry->ref_count > 0) { + DEBUG(10,("remove_ccache: entry %s ref count now %d\n", + username, entry->ref_count)); + return NT_STATUS_OK; + } + + /* no references any more */ + + DLIST_REMOVE(ccache_list, entry); + TALLOC_FREE(entry->event); /* unregisters events */ + +#ifdef HAVE_KRB5 + ret = ads_kdestroy(entry->ccname); + + /* we ignore the error when there has been no credential cache */ + if (ret == KRB5_FCC_NOFILE) { + ret = 0; + } else if (ret) { + DEBUG(0,("remove_ccache: " + "failed to destroy user krb5 ccache %s with: %s\n", + entry->ccname, error_message(ret))); + } else { + DEBUG(10,("remove_ccache: " + "successfully destroyed krb5 ccache %s for user %s\n", + entry->ccname, username)); + } + status = krb5_to_nt_status(ret); +#endif + + TALLOC_FREE(entry); + DEBUG(10,("remove_ccache: removed ccache for user %s\n", username)); + + return status; +} + +/******************************************************************* + In memory credentials cache code. +*******************************************************************/ + +static struct WINBINDD_MEMORY_CREDS *memory_creds_list; + +/*********************************************************** + Find an entry on the list by name. +***********************************************************/ + +struct WINBINDD_MEMORY_CREDS *find_memory_creds_by_name(const char *username) +{ + struct WINBINDD_MEMORY_CREDS *p; + + for (p = memory_creds_list; p; p = p->next) { + if (strequal(p->username, username)) { + return p; + } + } + return NULL; +} + +/*********************************************************** + Store the required creds and mlock them. +***********************************************************/ + +static NTSTATUS store_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp, + const char *pass) +{ +#if !defined(HAVE_MLOCK) + return NT_STATUS_OK; +#else + /* new_entry->nt_hash is the base pointer for the block + of memory pointed into by new_entry->lm_hash and + new_entry->pass (if we're storing plaintext). */ + + memcredp->len = NT_HASH_LEN + LM_HASH_LEN; + if (pass) { + memcredp->len += strlen(pass)+1; + } + + +#if defined(LINUX) + /* aligning the memory on on x86_64 and compiling + with gcc 4.1 using -O2 causes a segv in the + next memset() --jerry */ + memcredp->nt_hash = SMB_MALLOC_ARRAY(unsigned char, memcredp->len); +#else + /* On non-linux platforms, mlock()'d memory must be aligned */ + memcredp->nt_hash = SMB_MEMALIGN_ARRAY(unsigned char, + getpagesize(), memcredp->len); +#endif + if (!memcredp->nt_hash) { + return NT_STATUS_NO_MEMORY; + } + memset(memcredp->nt_hash, 0x0, memcredp->len); + + memcredp->lm_hash = memcredp->nt_hash + NT_HASH_LEN; + +#ifdef DEBUG_PASSWORD + DEBUG(10,("mlocking memory: %p\n", memcredp->nt_hash)); +#endif + if ((mlock(memcredp->nt_hash, memcredp->len)) == -1) { + DEBUG(0,("failed to mlock memory: %s (%d)\n", + strerror(errno), errno)); + SAFE_FREE(memcredp->nt_hash); + return map_nt_error_from_unix(errno); + } + +#ifdef DEBUG_PASSWORD + DEBUG(10,("mlocked memory: %p\n", memcredp->nt_hash)); +#endif + + /* Create and store the password hashes. */ + E_md4hash(pass, memcredp->nt_hash); + E_deshash(pass, memcredp->lm_hash); + + if (pass) { + memcredp->pass = (char *)memcredp->lm_hash + LM_HASH_LEN; + memcpy(memcredp->pass, pass, + memcredp->len - NT_HASH_LEN - LM_HASH_LEN); + } + + return NT_STATUS_OK; +#endif +} + +/*********************************************************** + Destroy existing creds. +***********************************************************/ + +static NTSTATUS delete_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp) +{ +#if !defined(HAVE_MUNLOCK) + return NT_STATUS_OK; +#else + if (munlock(memcredp->nt_hash, memcredp->len) == -1) { + DEBUG(0,("failed to munlock memory: %s (%d)\n", + strerror(errno), errno)); + return map_nt_error_from_unix(errno); + } + memset(memcredp->nt_hash, '\0', memcredp->len); + SAFE_FREE(memcredp->nt_hash); + memcredp->nt_hash = NULL; + memcredp->lm_hash = NULL; + memcredp->pass = NULL; + memcredp->len = 0; + return NT_STATUS_OK; +#endif +} + +/*********************************************************** + Replace the required creds with new ones (password change). +***********************************************************/ + +static NTSTATUS winbindd_replace_memory_creds_internal(struct WINBINDD_MEMORY_CREDS *memcredp, + const char *pass) +{ + NTSTATUS status = delete_memory_creds(memcredp); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return store_memory_creds(memcredp, pass); +} + +/************************************************************* + Store credentials in memory in a list. +*************************************************************/ + +static NTSTATUS winbindd_add_memory_creds_internal(const char *username, + uid_t uid, + const char *pass) +{ + /* Shortcut to ensure we don't store if no mlock. */ +#if !defined(HAVE_MLOCK) || !defined(HAVE_MUNLOCK) + return NT_STATUS_OK; +#else + NTSTATUS status; + struct WINBINDD_MEMORY_CREDS *memcredp = NULL; + + memcredp = find_memory_creds_by_name(username); + if (uid == (uid_t)-1) { + DEBUG(0,("winbindd_add_memory_creds_internal: " + "invalid uid for user %s.\n", username)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (memcredp) { + /* Already exists. Increment the reference count and replace stored creds. */ + if (uid != memcredp->uid) { + DEBUG(0,("winbindd_add_memory_creds_internal: " + "uid %u for user %s doesn't " + "match stored uid %u. Replacing.\n", + (unsigned int)uid, username, + (unsigned int)memcredp->uid)); + memcredp->uid = uid; + } + memcredp->ref_count++; + DEBUG(10,("winbindd_add_memory_creds_internal: " + "ref count for user %s is now %d\n", + username, memcredp->ref_count)); + return winbindd_replace_memory_creds_internal(memcredp, pass); + } + + memcredp = TALLOC_ZERO_P(NULL, struct WINBINDD_MEMORY_CREDS); + if (!memcredp) { + return NT_STATUS_NO_MEMORY; + } + memcredp->username = talloc_strdup(memcredp, username); + if (!memcredp->username) { + talloc_destroy(memcredp); + return NT_STATUS_NO_MEMORY; + } + + status = store_memory_creds(memcredp, pass); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(memcredp); + return status; + } + + memcredp->uid = uid; + memcredp->ref_count = 1; + DLIST_ADD(memory_creds_list, memcredp); + + DEBUG(10,("winbindd_add_memory_creds_internal: " + "added entry for user %s\n", username)); + + return NT_STATUS_OK; +#endif +} + +/************************************************************* + Store users credentials in memory. If we also have a + struct WINBINDD_CCACHE_ENTRY for this username with a + refresh timer, then store the plaintext of the password + and associate the new credentials with the struct WINBINDD_CCACHE_ENTRY. +*************************************************************/ + +NTSTATUS winbindd_add_memory_creds(const char *username, + uid_t uid, + const char *pass) +{ + struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); + NTSTATUS status; + + status = winbindd_add_memory_creds_internal(username, uid, pass); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (entry) { + struct WINBINDD_MEMORY_CREDS *memcredp = NULL; + memcredp = find_memory_creds_by_name(username); + if (memcredp) { + entry->cred_ptr = memcredp; + } + } + + return status; +} + +/************************************************************* + Decrement the in-memory ref count - delete if zero. +*************************************************************/ + +NTSTATUS winbindd_delete_memory_creds(const char *username) +{ + struct WINBINDD_MEMORY_CREDS *memcredp = NULL; + struct WINBINDD_CCACHE_ENTRY *entry = NULL; + NTSTATUS status = NT_STATUS_OK; + + memcredp = find_memory_creds_by_name(username); + entry = get_ccache_by_username(username); + + if (!memcredp) { + DEBUG(10,("winbindd_delete_memory_creds: unknown user %s\n", + username)); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (memcredp->ref_count <= 0) { + DEBUG(0,("winbindd_delete_memory_creds: logic error. " + "ref count for user %s = %d\n", + username, memcredp->ref_count)); + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + memcredp->ref_count--; + if (memcredp->ref_count <= 0) { + delete_memory_creds(memcredp); + DLIST_REMOVE(memory_creds_list, memcredp); + talloc_destroy(memcredp); + DEBUG(10,("winbindd_delete_memory_creds: " + "deleted entry for user %s\n", + username)); + } else { + DEBUG(10,("winbindd_delete_memory_creds: " + "entry for user %s ref_count now %d\n", + username, memcredp->ref_count)); + } + + if (entry) { + /* Ensure we have no dangling references to this. */ + entry->cred_ptr = NULL; + } + + return status; +} + +/*********************************************************** + Replace the required creds with new ones (password change). +***********************************************************/ + +NTSTATUS winbindd_replace_memory_creds(const char *username, + const char *pass) +{ + struct WINBINDD_MEMORY_CREDS *memcredp = NULL; + + memcredp = find_memory_creds_by_name(username); + if (!memcredp) { + DEBUG(10,("winbindd_replace_memory_creds: unknown user %s\n", + username)); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + DEBUG(10,("winbindd_replace_memory_creds: replaced creds for user %s\n", + username)); + + return winbindd_replace_memory_creds_internal(memcredp, pass); +} diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c new file mode 100644 index 0000000000..62facb6769 --- /dev/null +++ b/source3/winbindd/winbindd_creds.c @@ -0,0 +1,162 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - cached credentials funcions + + Copyright (C) Guenther Deschner 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +#define MAX_CACHED_LOGINS 10 + +NTSTATUS winbindd_get_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + NET_USER_INFO_3 **info3, + const uint8 *cached_nt_pass[NT_HASH_LEN], + const uint8 *cred_salt[NT_HASH_LEN]) +{ + NET_USER_INFO_3 *info; + NTSTATUS status; + + status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass, cred_salt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + info = netsamlogon_cache_get(mem_ctx, sid); + if (info == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + *info3 = info; + + return NT_STATUS_OK; +} + + +NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass, + NET_USER_INFO_3 *info3, + const DOM_SID *user_sid) +{ + NTSTATUS status; + uchar nt_pass[NT_HASH_LEN]; + DOM_SID cred_sid; + + if (info3 != NULL) { + + DOM_SID sid; + sid_copy(&sid, &(info3->dom_sid.sid)); + sid_append_rid(&sid, info3->user_rid); + sid_copy(&cred_sid, &sid); + info3->user_flgs |= LOGON_CACHED_ACCOUNT; + + } else if (user_sid != NULL) { + + sid_copy(&cred_sid, user_sid); + + } else if (user != NULL) { + + /* do lookup ourself */ + + enum lsa_SidType type; + + if (!lookup_cached_name(mem_ctx, + domain->name, + user, + &cred_sid, + &type)) { + return NT_STATUS_NO_SUCH_USER; + } + } else { + return NT_STATUS_INVALID_PARAMETER; + } + + if (pass) { + + int count = 0; + + status = wcache_count_cached_creds(domain, &count); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + DEBUG(11,("we have %d cached creds\n", count)); + + if (count + 1 > MAX_CACHED_LOGINS) { + + DEBUG(10,("need to delete the oldest cached login\n")); + + status = wcache_remove_oldest_cached_creds(domain, &cred_sid); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("failed to remove oldest cached cred: %s\n", + nt_errstr(status))); + return status; + } + } + + E_md4hash(pass, nt_pass); + + dump_data_pw("nt_pass", nt_pass, NT_HASH_LEN); + + status = wcache_save_creds(domain, mem_ctx, &cred_sid, nt_pass); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + if (info3 != NULL && user != NULL) { + if (!netsamlogon_cache_store(user, info3)) { + return NT_STATUS_ACCESS_DENIED; + } + } + + return NT_STATUS_OK; +} + +NTSTATUS winbindd_update_creds_by_info3(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass, + NET_USER_INFO_3 *info3) +{ + return winbindd_store_creds(domain, mem_ctx, user, pass, info3, NULL); +} + +NTSTATUS winbindd_update_creds_by_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const char *pass) +{ + return winbindd_store_creds(domain, mem_ctx, NULL, pass, NULL, sid); +} + +NTSTATUS winbindd_update_creds_by_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass) +{ + return winbindd_store_creds(domain, mem_ctx, user, pass, NULL, NULL); +} + + diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c new file mode 100644 index 0000000000..67cf6abc2b --- /dev/null +++ b/source3/winbindd/winbindd_dual.c @@ -0,0 +1,1130 @@ +/* + Unix SMB/CIFS implementation. + + Winbind child daemons + + Copyright (C) Andrew Tridgell 2002 + Copyright (C) Volker Lendecke 2004,2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + * We fork a child per domain to be able to act non-blocking in the main + * winbind daemon. A domain controller thousands of miles away being being + * slow replying with a 10.000 user list should not hold up netlogon calls + * that can be handled locally. + */ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +extern BOOL override_logfile; + +/* Read some data from a client connection */ + +static void child_read_request(struct winbindd_cli_state *state) +{ + ssize_t len; + + /* Read data */ + + len = read_data(state->sock, (char *)&state->request, + sizeof(state->request)); + + if (len != sizeof(state->request)) { + DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len)); + state->finished = True; + return; + } + + if (state->request.extra_len == 0) { + state->request.extra_data.data = NULL; + return; + } + + DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len)); + + state->request.extra_data.data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data.data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data.data[state->request.extra_len] = '\0'; + + len = read_data(state->sock, state->request.extra_data.data, + state->request.extra_len); + + if (len != state->request.extra_len) { + DEBUG(0, ("Could not read extra data\n")); + state->finished = True; + return; + } +} + +/* + * Machinery for async requests sent to children. You set up a + * winbindd_request, select a child to query, and issue a async_request + * call. When the request is completed, the callback function you specified is + * called back with the private pointer you gave to async_request. + */ + +struct winbindd_async_request { + struct winbindd_async_request *next, *prev; + TALLOC_CTX *mem_ctx; + struct winbindd_child *child; + struct winbindd_request *request; + struct winbindd_response *response; + void (*continuation)(void *private_data, BOOL success); + struct timed_event *reply_timeout_event; + pid_t child_pid; /* pid of the child we're waiting on. Used to detect + a restart of the child (child->pid != child_pid). */ + void *private_data; +}; + +static void async_main_request_sent(void *private_data, BOOL success); +static void async_request_sent(void *private_data, BOOL success); +static void async_reply_recv(void *private_data, BOOL success); +static void schedule_async_request(struct winbindd_child *child); + +void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + struct winbindd_request *request, + struct winbindd_response *response, + void (*continuation)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_async_request *state; + + SMB_ASSERT(continuation != NULL); + + state = TALLOC_P(mem_ctx, struct winbindd_async_request); + + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + continuation(private_data, False); + return; + } + + state->mem_ctx = mem_ctx; + state->child = child; + state->request = request; + state->response = response; + state->continuation = continuation; + state->private_data = private_data; + + DLIST_ADD_END(child->requests, state, struct winbindd_async_request *); + + schedule_async_request(child); + + return; +} + +static void async_main_request_sent(void *private_data, BOOL success) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data, struct winbindd_async_request); + + if (!success) { + DEBUG(5, ("Could not send async request\n")); + + state->response->length = sizeof(struct winbindd_response); + state->response->result = WINBINDD_ERROR; + state->continuation(state->private_data, False); + return; + } + + if (state->request->extra_len == 0) { + async_request_sent(private_data, True); + return; + } + + setup_async_write(&state->child->event, state->request->extra_data.data, + state->request->extra_len, + async_request_sent, state); +} + +/**************************************************************** + Handler triggered if the child winbindd doesn't respond within + a given timeout. +****************************************************************/ + +static void async_request_timeout_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data, struct winbindd_async_request); + + DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. " + "Closing connection to it.\n", + state->child_pid )); + + /* Deal with the reply - set to error. */ + async_reply_recv(private_data, False); +} + +/************************************************************** + Common function called on both async send and recv fail. + Cleans up the child and schedules the next request. +**************************************************************/ + +static void async_request_fail(struct winbindd_async_request *state) +{ + DLIST_REMOVE(state->child->requests, state); + + TALLOC_FREE(state->reply_timeout_event); + + SMB_ASSERT(state->child_pid != (pid_t)0); + + /* If not already reaped, send kill signal to child. */ + if (state->child->pid == state->child_pid) { + kill(state->child_pid, SIGTERM); + + /* + * Close the socket to the child. + */ + winbind_child_died(state->child_pid); + } + + state->response->length = sizeof(struct winbindd_response); + state->response->result = WINBINDD_ERROR; + state->continuation(state->private_data, False); +} + +static void async_request_sent(void *private_data_data, BOOL success) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data_data, struct winbindd_async_request); + + if (!success) { + DEBUG(5, ("Could not send async request to child pid %u\n", + (unsigned int)state->child_pid )); + async_request_fail(state); + return; + } + + /* Request successfully sent to the child, setup the wait for reply */ + + setup_async_read(&state->child->event, + &state->response->result, + sizeof(state->response->result), + async_reply_recv, state); + + /* + * Set up a timeout of 300 seconds for the response. + * If we don't get it close the child socket and + * report failure. + */ + + state->reply_timeout_event = event_add_timed(winbind_event_context(), + NULL, + timeval_current_ofs(300,0), + "async_request_timeout", + async_request_timeout_handler, + state); + if (!state->reply_timeout_event) { + smb_panic("async_request_sent: failed to add timeout handler.\n"); + } +} + +static void async_reply_recv(void *private_data, BOOL success) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data, struct winbindd_async_request); + struct winbindd_child *child = state->child; + + TALLOC_FREE(state->reply_timeout_event); + + state->response->length = sizeof(struct winbindd_response); + + if (!success) { + DEBUG(5, ("Could not receive async reply from child pid %u\n", + (unsigned int)state->child_pid )); + + cache_cleanup_response(state->child_pid); + async_request_fail(state); + return; + } + + SMB_ASSERT(cache_retrieve_response(state->child_pid, + state->response)); + + cache_cleanup_response(state->child_pid); + + DLIST_REMOVE(child->requests, state); + + schedule_async_request(child); + + state->continuation(state->private_data, True); +} + +static BOOL fork_domain_child(struct winbindd_child *child); + +static void schedule_async_request(struct winbindd_child *child) +{ + struct winbindd_async_request *request = child->requests; + + if (request == NULL) { + return; + } + + if (child->event.flags != 0) { + return; /* Busy */ + } + + if ((child->pid == 0) && (!fork_domain_child(child))) { + /* Cancel all outstanding requests */ + + while (request != NULL) { + /* request might be free'd in the continuation */ + struct winbindd_async_request *next = request->next; + request->continuation(request->private_data, False); + request = next; + } + return; + } + + /* Now we know who we're sending to - remember the pid. */ + request->child_pid = child->pid; + + setup_async_write(&child->event, request->request, + sizeof(*request->request), + async_main_request_sent, request); + + return; +} + +struct domain_request_state { + TALLOC_CTX *mem_ctx; + struct winbindd_domain *domain; + struct winbindd_request *request; + struct winbindd_response *response; + void (*continuation)(void *private_data_data, BOOL success); + void *private_data_data; +}; + +static void domain_init_recv(void *private_data_data, BOOL success); + +void async_domain_request(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + struct winbindd_request *request, + struct winbindd_response *response, + void (*continuation)(void *private_data_data, BOOL success), + void *private_data_data) +{ + struct domain_request_state *state; + + if (domain->initialized) { + async_request(mem_ctx, &domain->child, request, response, + continuation, private_data_data); + return; + } + + state = TALLOC_P(mem_ctx, struct domain_request_state); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + continuation(private_data_data, False); + return; + } + + state->mem_ctx = mem_ctx; + state->domain = domain; + state->request = request; + state->response = response; + state->continuation = continuation; + state->private_data_data = private_data_data; + + init_child_connection(domain, domain_init_recv, state); +} + +static void domain_init_recv(void *private_data_data, BOOL success) +{ + struct domain_request_state *state = + talloc_get_type_abort(private_data_data, struct domain_request_state); + + if (!success) { + DEBUG(5, ("Domain init returned an error\n")); + state->continuation(state->private_data_data, False); + return; + } + + async_request(state->mem_ctx, &state->domain->child, + state->request, state->response, + state->continuation, state->private_data_data); +} + +static void recvfrom_child(void *private_data_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data_data, struct winbindd_cli_state); + enum winbindd_result result = state->response.result; + + /* This is an optimization: The child has written directly to the + * response buffer. The request itself is still in pending state, + * state that in the result code. */ + + state->response.result = WINBINDD_PENDING; + + if ((!success) || (result != WINBINDD_OK)) { + request_error(state); + return; + } + + request_ok(state); +} + +void sendto_child(struct winbindd_cli_state *state, + struct winbindd_child *child) +{ + async_request(state->mem_ctx, child, &state->request, + &state->response, recvfrom_child, state); +} + +void sendto_domain(struct winbindd_cli_state *state, + struct winbindd_domain *domain) +{ + async_domain_request(state->mem_ctx, domain, + &state->request, &state->response, + recvfrom_child, state); +} + + +struct winbindd_child_dispatch_table { + enum winbindd_cmd cmd; + enum winbindd_result (*fn)(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + const char *winbindd_cmd_name; +}; + +static struct winbindd_child_dispatch_table child_dispatch_table[] = { + + { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, + { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, + { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, + { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, + { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, + { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, + { WINBINDD_DSGETDCNAME, winbindd_dual_dsgetdcname, "DSGETDCNAME" }, + { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, + { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, + { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, + { WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" }, + { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, + { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, + { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, + { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, + { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, +#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ + { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, +#endif /* end DISABLED */ + { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, + { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, + { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, + { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, + { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, + { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, + { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, + { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, + { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, + { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, + { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, + { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, + { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, + { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, + { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, + /* End of list */ + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; + +static void child_process_request(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct winbindd_child_dispatch_table *table; + + /* Free response data - we may be interrupted and receive another + command before being able to send this data off. */ + + state->response.result = WINBINDD_ERROR; + state->response.length = sizeof(struct winbindd_response); + + /* as all requests in the child are sync, we can use talloc_tos() */ + state->mem_ctx = talloc_tos(); + + /* Process command */ + + for (table = child_dispatch_table; table->fn; table++) { + if (state->request.cmd == table->cmd) { + DEBUG(10,("process_request: request fn %s\n", + table->winbindd_cmd_name )); + state->response.result = table->fn(domain, state); + break; + } + } + + if (!table->fn) { + DEBUG(10,("process_request: unknown request fn number %d\n", + (int)state->request.cmd )); + state->response.result = WINBINDD_ERROR; + } +} + +void setup_domain_child(struct winbindd_domain *domain, + struct winbindd_child *child, + const char *explicit_logfile) +{ + if (explicit_logfile != NULL) { + pstr_sprintf(child->logfilename, "%s/log.winbindd-%s", + dyn_LOGFILEBASE, explicit_logfile); + } else if (domain != NULL) { + pstr_sprintf(child->logfilename, "%s/log.wb-%s", + dyn_LOGFILEBASE, domain->name); + } else { + smb_panic("Internal error: domain == NULL && " + "explicit_logfile == NULL"); + } + + child->domain = domain; +} + +struct winbindd_child *children = NULL; + +void winbind_child_died(pid_t pid) +{ + struct winbindd_child *child; + + for (child = children; child != NULL; child = child->next) { + if (child->pid == pid) { + break; + } + } + + if (child == NULL) { + DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid)); + return; + } + + remove_fd_event(&child->event); + close(child->event.fd); + child->event.fd = 0; + child->event.flags = 0; + child->pid = 0; + + schedule_async_request(child); +} + +/* Ensure any negative cache entries with the netbios or realm names are removed. */ + +void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain) +{ + flush_negative_conn_cache_for_domain(domain->name); + if (*domain->alt_name) { + flush_negative_conn_cache_for_domain(domain->alt_name); + } +} + +/* Set our domains as offline and forward the offline message to our children. */ + +void winbind_msg_offline(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child; + struct winbindd_domain *domain; + + DEBUG(10,("winbind_msg_offline: got offline message.\n")); + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("winbind_msg_offline: rejecting offline message.\n")); + return; + } + + /* Set our global state as offline. */ + if (!set_global_winbindd_state_offline()) { + DEBUG(10,("winbind_msg_offline: offline request failed.\n")); + return; + } + + /* Set all our domains as offline. */ + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name)); + set_domain_offline(domain); + } + + for (child = children; child != NULL; child = child->next) { + /* Don't send message to internal childs. We've already + done so above. */ + if (!child->domain || winbindd_internal_child(child)) { + continue; + } + + /* Or internal domains (this should not be possible....) */ + if (child->domain->internal) { + continue; + } + + /* Each winbindd child should only process requests for one domain - make sure + we only set it online / offline for that domain. */ + + DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n", + (unsigned int)child->pid, domain->name )); + + messaging_send_buf(msg_ctx, pid_to_procid(child->pid), + MSG_WINBIND_OFFLINE, + (uint8 *)child->domain->name, + strlen(child->domain->name)+1); + } +} + +/* Set our domains as online and forward the online message to our children. */ + +void winbind_msg_online(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child; + struct winbindd_domain *domain; + + DEBUG(10,("winbind_msg_online: got online message.\n")); + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("winbind_msg_online: rejecting online message.\n")); + return; + } + + /* Set our global state as online. */ + set_global_winbindd_state_online(); + + smb_nscd_flush_user_cache(); + smb_nscd_flush_group_cache(); + + /* Set all our domains as online. */ + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name)); + + winbindd_flush_negative_conn_cache(domain); + set_domain_online_request(domain); + + /* Send an online message to the idmap child when our + primary domain comes back online */ + + if ( domain->primary ) { + struct winbindd_child *idmap = idmap_child(); + + if ( idmap->pid != 0 ) { + messaging_send_buf(msg_ctx, + pid_to_procid(idmap->pid), + MSG_WINBIND_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); + } + + } + } + + for (child = children; child != NULL; child = child->next) { + /* Don't send message to internal childs. */ + if (!child->domain || winbindd_internal_child(child)) { + continue; + } + + /* Or internal domains (this should not be possible....) */ + if (child->domain->internal) { + continue; + } + + /* Each winbindd child should only process requests for one domain - make sure + we only set it online / offline for that domain. */ + + DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n", + (unsigned int)child->pid, child->domain->name )); + + messaging_send_buf(msg_ctx, pid_to_procid(child->pid), + MSG_WINBIND_ONLINE, + (uint8 *)child->domain->name, + strlen(child->domain->name)+1); + } +} + +/* Forward the online/offline messages to our children. */ +void winbind_msg_onlinestatus(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child; + + DEBUG(10,("winbind_msg_onlinestatus: got onlinestatus message.\n")); + + for (child = children; child != NULL; child = child->next) { + if (child->domain && child->domain->primary) { + DEBUG(10,("winbind_msg_onlinestatus: " + "sending message to pid %u of primary domain.\n", + (unsigned int)child->pid)); + messaging_send_buf(msg_ctx, pid_to_procid(child->pid), + MSG_WINBIND_ONLINESTATUS, + (uint8 *)data->data, + data->length); + break; + } + } +} + +void winbind_msg_dump_event_list(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child; + + DEBUG(10,("winbind_msg_dump_event_list received\n")); + + dump_event_list(winbind_event_context()); + + for (child = children; child != NULL; child = child->next) { + + DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n", + (unsigned int)child->pid)); + + messaging_send_buf(msg_ctx, pid_to_procid(child->pid), + MSG_DUMP_EVENT_LIST, + NULL, 0); + } + +} + +static void account_lockout_policy_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct winbindd_child *child = + (struct winbindd_child *)private_data; + TALLOC_CTX *mem_ctx = NULL; + struct winbindd_methods *methods; + SAM_UNK_INFO_12 lockout_policy; + NTSTATUS result; + + DEBUG(10,("account_lockout_policy_handler called\n")); + + TALLOC_FREE(child->lockout_policy_event); + + if ( !winbindd_can_contact_domain( child->domain ) ) { + DEBUG(10,("account_lockout_policy_handler: Removing myself since I " + "do not have an incoming trust to domain %s\n", + child->domain->name)); + + return; + } + + methods = child->domain->methods; + + mem_ctx = talloc_init("account_lockout_policy_handler ctx"); + if (!mem_ctx) { + result = NT_STATUS_NO_MEMORY; + } else { + result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy); + } + TALLOC_FREE(mem_ctx); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n", + nt_errstr(result))); + } + + child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL, + timeval_current_ofs(3600, 0), + "account_lockout_policy_handler", + account_lockout_policy_handler, + child); +} + +/* Deal with a request to go offline. */ + +static void child_msg_offline(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_domain *domain; + const char *domainname = (const char *)data->data; + + if (data->data == NULL || data->length == 0) { + return; + } + + DEBUG(5,("child_msg_offline received for domain %s.\n", domainname)); + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("child_msg_offline: rejecting offline message.\n")); + return; + } + + /* Mark the requested domain offline. */ + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + if (strequal(domain->name, domainname)) { + DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name)); + set_domain_offline(domain); + } + } +} + +/* Deal with a request to go online. */ + +static void child_msg_online(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_domain *domain; + const char *domainname = (const char *)data->data; + + if (data->data == NULL || data->length == 0) { + return; + } + + DEBUG(5,("child_msg_online received for domain %s.\n", domainname)); + + if (!lp_winbind_offline_logon()) { + DEBUG(10,("child_msg_online: rejecting online message.\n")); + return; + } + + /* Set our global state as online. */ + set_global_winbindd_state_online(); + + /* Try and mark everything online - delete any negative cache entries + to force a reconnect now. */ + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + if (strequal(domain->name, domainname)) { + DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name)); + winbindd_flush_negative_conn_cache(domain); + set_domain_online_request(domain); + } + } +} + +static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx) +{ + struct winbindd_domain *domain; + char *buf = NULL; + + if ((buf = talloc_asprintf(mem_ctx, "global:%s ", + get_global_winbindd_state_offline() ? + "Offline":"Online")) == NULL) { + return NULL; + } + + for (domain = domain_list(); domain; domain = domain->next) { + if ((buf = talloc_asprintf_append(buf, "%s:%s ", + domain->name, + domain->online ? + "Online":"Offline")) == NULL) { + return NULL; + } + } + + buf = talloc_asprintf_append(buf, "\n"); + + DEBUG(5,("collect_onlinestatus: %s", buf)); + + return buf; +} + +static void child_msg_onlinestatus(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + TALLOC_CTX *mem_ctx; + const char *message; + struct server_id *sender; + + DEBUG(5,("winbind_msg_onlinestatus received.\n")); + + if (!data->data) { + return; + } + + sender = (struct server_id *)data->data; + + mem_ctx = talloc_init("winbind_msg_onlinestatus"); + if (mem_ctx == NULL) { + return; + } + + message = collect_onlinestatus(mem_ctx); + if (message == NULL) { + talloc_destroy(mem_ctx); + return; + } + + messaging_send_buf(msg_ctx, *sender, MSG_WINBIND_ONLINESTATUS, + (uint8 *)message, strlen(message) + 1); + + talloc_destroy(mem_ctx); +} + +static void child_msg_dump_event_list(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + DEBUG(5,("child_msg_dump_event_list received\n")); + + dump_event_list(winbind_event_context()); +} + + +static BOOL fork_domain_child(struct winbindd_child *child) +{ + int fdpair[2]; + struct winbindd_cli_state state; + struct winbindd_domain *domain; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) { + DEBUG(0, ("Could not open child pipe: %s\n", + strerror(errno))); + return False; + } + + ZERO_STRUCT(state); + state.pid = sys_getpid(); + + /* Stop zombies */ + CatchChild(); + + child->pid = sys_fork(); + + if (child->pid == -1) { + DEBUG(0, ("Could not fork: %s\n", strerror(errno))); + return False; + } + + if (child->pid != 0) { + /* Parent */ + close(fdpair[0]); + child->next = child->prev = NULL; + DLIST_ADD(children, child); + child->event.fd = fdpair[1]; + child->event.flags = 0; + child->requests = NULL; + add_fd_event(&child->event); + return True; + } + + /* Child */ + + state.sock = fdpair[0]; + close(fdpair[1]); + + /* tdb needs special fork handling */ + if (tdb_reopen_all(1) == -1) { + DEBUG(0,("tdb_reopen_all failed.\n")); + _exit(0); + } + + close_conns_after_fork(); + + if (!override_logfile) { + lp_set_logfile(child->logfilename); + reopen_logs(); + } + + /* + * For clustering, we need to re-init our ctdbd connection after the + * fork + */ + if (!NT_STATUS_IS_OK(messaging_reinit(winbind_messaging_context()))) + exit(1); + + /* Don't handle the same messages as our parent. */ + messaging_deregister(winbind_messaging_context(), + MSG_SMB_CONF_UPDATED, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_SHUTDOWN, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_OFFLINE, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_ONLINE, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_ONLINESTATUS, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_DUMP_EVENT_LIST, NULL); + + /* Handle online/offline messages. */ + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_OFFLINE, child_msg_offline); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_ONLINE, child_msg_online); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus); + messaging_register(winbind_messaging_context(), NULL, + MSG_DUMP_EVENT_LIST, child_msg_dump_event_list); + + if ( child->domain ) { + child->domain->startup = True; + child->domain->startup_time = time(NULL); + } + + /* Ensure we have no pending check_online events other + than one for this domain. */ + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain != child->domain) { + TALLOC_FREE(domain->check_online_event); + } + } + + /* Ensure we're not handling an event inherited from + our parent. */ + + cancel_named_event(winbind_event_context(), + "krb5_ticket_refresh_handler"); + + /* We might be in the idmap child...*/ + if (child->domain && !(child->domain->internal) && + lp_winbind_offline_logon()) { + + set_domain_online_request(child->domain); + + child->lockout_policy_event = event_add_timed( + winbind_event_context(), NULL, timeval_zero(), + "account_lockout_policy_handler", + account_lockout_policy_handler, + child); + } + + while (1) { + + int ret; + fd_set read_fds; + struct timeval t; + struct timeval *tp; + struct timeval now; + TALLOC_CTX *frame = talloc_stackframe(); + + run_events(winbind_event_context(), 0, NULL, NULL); + + GetTimeOfDay(&now); + + if (child->domain && child->domain->startup && + (now.tv_sec > child->domain->startup_time + 30)) { + /* No longer in "startup" mode. */ + DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n", + child->domain->name )); + child->domain->startup = False; + } + + tp = get_timed_events_timeout(winbind_event_context(), &t); + if (tp) { + DEBUG(11,("select will use timeout of %u.%u seconds\n", + (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec )); + } + + /* Handle messages */ + + message_dispatch(winbind_messaging_context()); + + FD_ZERO(&read_fds); + FD_SET(state.sock, &read_fds); + + ret = sys_select(state.sock + 1, &read_fds, NULL, NULL, tp); + + if (ret == 0) { + DEBUG(11,("nothing is ready yet, continue\n")); + TALLOC_FREE(frame); + continue; + } + + if (ret == -1 && errno == EINTR) { + /* We got a signal - continue. */ + TALLOC_FREE(frame); + continue; + } + + if (ret == -1 && errno != EINTR) { + DEBUG(0,("select error occured\n")); + TALLOC_FREE(frame); + perror("select"); + return False; + } + + /* fetch a request from the main daemon */ + child_read_request(&state); + + if (state.finished) { + /* we lost contact with our parent */ + exit(0); + } + + DEBUG(4,("child daemon request %d\n", (int)state.request.cmd)); + + ZERO_STRUCT(state.response); + state.request.null_term = '\0'; + child_process_request(child->domain, &state); + + SAFE_FREE(state.request.extra_data.data); + + cache_store_response(sys_getpid(), &state.response); + + SAFE_FREE(state.response.extra_data.data); + + /* We just send the result code back, the result + * structure needs to be fetched via the + * winbindd_cache. Hmm. That needs fixing... */ + + if (write_data(state.sock, + (const char *)&state.response.result, + sizeof(state.response.result)) != + sizeof(state.response.result)) { + DEBUG(0, ("Could not write result\n")); + exit(1); + } + TALLOC_FREE(frame); + } +} diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c new file mode 100644 index 0000000000..9a4b02f734 --- /dev/null +++ b/source3/winbindd/winbindd_group.c @@ -0,0 +1,1746 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + Copyright (C) Jeremy Allison 2001. + Copyright (C) Gerald (Jerry) Carter 2003. + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +extern BOOL opt_nocache; + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static void add_member(const char *domain, const char *user, + char **pp_members, size_t *p_num_members) +{ + fstring name; + + fill_domain_username(name, domain, user, True); + safe_strcat(name, ",", sizeof(name)-1); + string_append(pp_members, name); + *p_num_members += 1; +} + +/********************************************************************** + Add member users resulting from sid. Expand if it is a domain group. +**********************************************************************/ + +static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_num_members) +{ + DOM_SID dom_sid; + uint32 rid; + struct winbindd_domain *domain; + size_t i; + + char *domain_name = NULL; + char *name = NULL; + enum lsa_SidType type; + + uint32 num_names; + DOM_SID *sid_mem; + char **names; + uint32 *types; + + NTSTATUS result; + + TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid"); + + if (mem_ctx == NULL) { + DEBUG(1, ("talloc_init failed\n")); + return; + } + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + domain = find_lookup_domain_from_sid(sid); + + if (domain == NULL) { + DEBUG(3, ("Could not find domain for sid %s\n", + sid_string_static(sid))); + goto done; + } + + result = domain->methods->sid_to_name(domain, mem_ctx, sid, + &domain_name, &name, &type); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("sid_to_name failed for sid %s\n", + sid_string_static(sid))); + goto done; + } + + DEBUG(10, ("Found name %s, type %d\n", name, type)); + + if (type == SID_NAME_USER) { + add_member(domain_name, name, pp_members, p_num_members); + goto done; + } + + if (type != SID_NAME_DOM_GRP) { + DEBUG(10, ("Alias member %s neither user nor group, ignore\n", + name)); + goto done; + } + + /* Expand the domain group, this must be done via the target domain */ + + domain = find_domain_from_sid(sid); + + if (domain == NULL) { + DEBUG(3, ("Could not find domain from SID %s\n", + sid_string_static(sid))); + goto done; + } + + result = domain->methods->lookup_groupmem(domain, mem_ctx, + sid, &num_names, + &sid_mem, &names, + &types); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("Could not lookup group members for %s: %s\n", + name, nt_errstr(result))); + goto done; + } + + for (i=0; iname, names[i], pp_members, p_num_members); + } + + done: + talloc_destroy(mem_ctx); + return; +} + +static BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain, + DOM_SID *group_sid, + size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len) +{ + DOM_SID *members; + size_t i, num_members; + + *num_gr_mem = 0; + *gr_mem = NULL; + *gr_mem_len = 0; + + if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members, + &num_members))) + return True; + + for (i=0; igr_gid = unix_gid; + + /* Group name and password */ + + safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1); + safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1); + + return True; +} + +/*********************************************************************** + If "enum users" is set to false, and the group being looked + up is the Domain Users SID: S-1-5-domain-513, then for the + list of members check if the querying user is in that group, + and if so only return that user as the gr_mem array. + We can change this to a different parameter than "enum users" + if neccessaey, or parameterize the group list we do this for. +***********************************************************************/ + +static BOOL fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + struct winbindd_cli_state *state, + DOM_SID *group_sid, + enum lsa_SidType group_name_type, + size_t *num_gr_mem, char **gr_mem, + size_t *gr_mem_len) +{ + DOM_SID querying_user_sid; + DOM_SID *pquerying_user_sid = NULL; + uint32 num_groups = 0; + DOM_SID *user_sids = NULL; + BOOL u_in_group = False; + NTSTATUS status; + int i; + unsigned int buf_len = 0; + char *buf = NULL; + + DEBUG(10,("fill_grent_mem_domain_users: domain %s\n", + domain->name )); + + if (state) { + uid_t ret_uid = (uid_t)-1; + if (sys_getpeereid(state->sock, &ret_uid)==0) { + /* We know who's asking - look up their SID if + it's one we've mapped before. */ + status = idmap_uid_to_sid(&querying_user_sid, ret_uid); + if (NT_STATUS_IS_OK(status)) { + pquerying_user_sid = &querying_user_sid; + DEBUG(10,("fill_grent_mem_domain_users: querying uid %u -> %s\n", + (unsigned int)ret_uid, + sid_string_static(pquerying_user_sid) )); + } + } + } + + /* Only look up if it was a winbindd user in this domain. */ + if (pquerying_user_sid && + (sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) { + + DEBUG(10,("fill_grent_mem_domain_users: querying user = %s\n", + sid_string_static(pquerying_user_sid) )); + + status = domain->methods->lookup_usergroups(domain, + mem_ctx, + pquerying_user_sid, + &num_groups, + &user_sids); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("fill_grent_mem_domain_users: lookup_usergroups failed " + "for sid %s in domain %s (error: %s)\n", + sid_string_static(pquerying_user_sid), + domain->name, + nt_errstr(status))); + return False; + } + + for (i = 0; i < num_groups; i++) { + if (sid_equal(group_sid, &user_sids[i])) { + /* User is in Domain Users, add their name + as the only group member. */ + u_in_group = True; + break; + } + } + } + + if (u_in_group) { + size_t len = 0; + char *domainname = NULL; + char *username = NULL; + fstring name; + enum lsa_SidType type; + + DEBUG(10,("fill_grent_mem_domain_users: sid %s in 'Domain Users' in domain %s\n", + sid_string_static(pquerying_user_sid), domain->name )); + + status = domain->methods->sid_to_name(domain, mem_ctx, + pquerying_user_sid, + &domainname, + &username, + &type); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("could not lookup username for user " + "sid %s in domain %s (error: %s)\n", + sid_string_static(pquerying_user_sid), + domain->name, + nt_errstr(status))); + return False; + } + fill_domain_username(name, domain->name, username, True); + len = strlen(name); + buf_len = len + 1; + if (!(buf = (char *)SMB_MALLOC(buf_len))) { + DEBUG(1, ("out of memory\n")); + return False; + } + memcpy(buf, name, buf_len); + + DEBUG(10,("fill_grent_mem_domain_users: user %s in " + "'Domain Users' in domain %s\n", + name, domain->name )); + + /* user is the only member */ + *num_gr_mem = 1; + } + + *gr_mem = buf; + *gr_mem_len = buf_len; + + DEBUG(10, ("fill_grent_mem_domain_users: num_mem = %u, len = %u, mem = %s\n", + (unsigned int)*num_gr_mem, + (unsigned int)buf_len, *num_gr_mem ? buf : "NULL")); + + return True; +} + +/*********************************************************************** + Add names to a list. Assumes a canonical version of the string + in DOMAIN\user +***********************************************************************/ + +static int namecmp( const void *a, const void *b ) +{ + return StrCaseCmp( * (char * const *) a, * (char * const *) b); +} + +static NTSTATUS add_names_to_list( TALLOC_CTX *ctx, + char ***list, uint32 *n_list, + char **names, uint32 n_names ) +{ + char **new_list = NULL; + uint32 n_new_list = 0; + int i, j; + + if ( !names || (n_names == 0) ) + return NT_STATUS_OK; + + /* Alloc the maximum size we'll need */ + + if ( *list == NULL ) { + if ( (new_list = TALLOC_ARRAY( ctx, char *, n_names )) == NULL ) + return NT_STATUS_NO_MEMORY; + n_new_list = n_names; + } else { + new_list = TALLOC_REALLOC_ARRAY( ctx, *list, char *, + (*n_list) + n_names ); + if ( !new_list ) + return NT_STATUS_NO_MEMORY; + n_new_list = (*n_list) + n_names; + } + + /* Add all names */ + + for ( i=*n_list, j=0; imethods->lookup_groupmem(d, tmp_ctx, + &glist[i], &num_names, + &sid_mem, &names, + &name_types); + if ( !NT_STATUS_IS_OK(status) ) + goto out; + + /* Separate users and groups into two lists */ + + for ( j=0; jname))) + return False; + + DEBUG(10, ("group SID %s\n", sid_string_static(group_sid))); + + /* Initialize with no members */ + + *num_gr_mem = 0; + + /* HACK ALERT!! This whole routine does not cope with group members + * from more than one domain, ie aliases. Thus we have to work it out + * ourselves in a special routine. */ + + if (domain->internal) { + result = fill_passdb_alias_grmem(domain, group_sid, + num_gr_mem, + gr_mem, gr_mem_len); + goto done; + } + + /* Verify name type */ + + if ( !((group_name_type==SID_NAME_DOM_GRP) || + ((group_name_type==SID_NAME_ALIAS) && domain->primary)) ) + { + DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", + sid_string_static(group_sid), domain->name, + group_name_type)); + goto done; + } + + /* OPTIMIZATION / HACK. See comment in + fill_grent_mem_domusers() */ + + sid_peek_rid( group_sid, &group_rid ); + if (!lp_winbind_enum_users() && group_rid == DOMAIN_GROUP_RID_USERS) { + result = fill_grent_mem_domusers( mem_ctx, domain, state, + group_sid, group_name_type, + num_gr_mem, gr_mem, + gr_mem_len ); + goto done; + } + + /* Real work goes here. Create a list of group names to + expand startign with the initial one. Pass that to + expand_groups() which returns a list of more group names + to expand. Do this up to the max search depth. */ + + if ( (glist = TALLOC_ARRAY(mem_ctx, DOM_SID, 1 )) == NULL ) { + result = False; + DEBUG(0,("fill_grent_mem: talloc failure!\n")); + goto done; + } + sid_copy( &glist[0], group_sid ); + n_glist = 1; + + for ( i=0; i 0) { + buf[buf_ndx - 1] = '\0'; + } + + *gr_mem = buf; + *gr_mem_len = buf_len; + + DEBUG(10, ("num_mem = %u, len = %u, mem = %s\n", (unsigned int)*num_gr_mem, + (unsigned int)buf_len, *num_gr_mem ? buf : "NULL")); + result = True; + +done: + + talloc_destroy(mem_ctx); + + DEBUG(10, ("fill_grent_mem returning %d\n", result)); + + return result; +} + +static void winbindd_getgrsid( struct winbindd_cli_state *state, DOM_SID group_sid ); + +static void getgrnam_recv( void *private_data, BOOL success, const DOM_SID *sid, + enum lsa_SidType type ) +{ + struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data; + + if (!success) { + DEBUG(5,("getgrnam_recv: lookupname failed!\n")); + request_error(state); + return; + } + + if ( (type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) ) { + DEBUG(5,("getgrnam_recv: not a group!\n")); + request_error(state); + return; + } + + winbindd_getgrsid( state, *sid ); +} + + +/* Return a group structure from a group name */ + +void winbindd_getgrnam(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, name_group; + char *tmp; + + /* Ensure null termination */ + state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; + + DEBUG(3, ("[%5lu]: getgrnam %s\n", (unsigned long)state->pid, + state->request.data.groupname)); + + /* Parse domain and groupname */ + + memset(name_group, 0, sizeof(fstring)); + + tmp = state->request.data.groupname; + + name_domain[0] = '\0'; + name_group[0] = '\0'; + + parse_domain_user(tmp, name_domain, name_group); + + /* if no domain or our local domain and no local tdb group, default to + * our local domain for aliases */ + + if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) { + fstrcpy(name_domain, get_global_sam_name()); + } + + /* Get info for the domain */ + + if ((domain = find_domain_from_name(name_domain)) == NULL) { + DEBUG(3, ("could not get domain sid for domain %s\n", + name_domain)); + request_error(state); + return; + } + /* should we deal with users for our domain? */ + + if ( lp_winbind_trusted_domains_only() && domain->primary) { + DEBUG(7,("winbindd_getgrnam: My domain -- rejecting " + "getgrnam() for %s\\%s.\n", name_domain, name_group)); + request_error(state); + return; + } + + /* Get rid and name type from name */ + + ws_name_replace( name_group, WB_REPLACE_CHAR ); + + winbindd_lookupname_async( state->mem_ctx, domain->name, name_group, + getgrnam_recv, WINBINDD_GETGRNAM, state ); +} + +struct getgrsid_state { + struct winbindd_cli_state *state; + struct winbindd_domain *domain; + char *group_name; + enum lsa_SidType group_type; + uid_t gid; + DOM_SID group_sid; +}; + +static void getgrsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) + { + struct getgrsid_state *s = + (struct getgrsid_state *)private_data; + struct winbindd_domain *domain; + size_t gr_mem_len; + size_t num_gr_mem; + char *gr_mem; + fstring dom_name, group_name; + + if (!success) { + DEBUG(5,("getgrsid_sid2gid_recv: sid2gid failed!\n")); + request_error(s->state); + return; + } + + s->gid = gid; + + if ( !parse_domain_user( s->group_name, dom_name, group_name ) ) { + DEBUG(5,("getgrsid_sid2gid_recv: parse_domain_user() failed!\n")); + request_error(s->state); + return; + } + + + /* Fill in group structure */ + + if ( (domain = find_domain_from_name_noinit(dom_name)) == NULL ) { + DEBUG(1,("Can't find domain from name (%s)\n", dom_name)); + request_error(s->state); + return; + } + + if (!fill_grent(&s->state->response.data.gr, dom_name, group_name, gid) || + !fill_grent_mem(domain, s->state, &s->group_sid, s->group_type, + &num_gr_mem, &gr_mem, &gr_mem_len)) + { + request_error(s->state); + return; + } + + s->state->response.data.gr.num_gr_mem = (uint32)num_gr_mem; + + /* Group membership lives at start of extra data */ + + s->state->response.data.gr.gr_mem_ofs = 0; + + s->state->response.length += gr_mem_len; + s->state->response.extra_data.data = gr_mem; + + request_ok(s->state); + } + +static void getgrsid_lookupsid_recv( void *private_data, BOOL success, + const char *dom_name, const char *name, + enum lsa_SidType name_type ) +{ + struct getgrsid_state *s = (struct getgrsid_state *)private_data; + + if (!success) { + DEBUG(5,("getgrsid_lookupsid_recv: lookupsid failed!\n")); + request_error(s->state); + return; + } + + /* either it's a domain group, a domain local group, or a + local group in an internal domain */ + + if ( !( (name_type==SID_NAME_DOM_GRP) || + ((name_type==SID_NAME_ALIAS) && + (s->domain->primary || s->domain->internal)) ) ) + { + DEBUG(1, ("name '%s\\%s' is not a local or domain group: %d\n", + dom_name, name, name_type)); + request_error(s->state); + return; +} + + if ( (s->group_name = talloc_asprintf( s->state->mem_ctx, + "%s\\%s", + dom_name, name )) == NULL ) +{ + DEBUG(1, ("getgrsid_lookupsid_recv: talloc_asprintf() Failed!\n")); + request_error(s->state); + return; + } + + s->group_type = name_type; + + winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid, + getgrsid_sid2gid_recv, s); + } + +static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID group_sid ) + { + struct getgrsid_state *s; + + if ( (s = TALLOC_ZERO_P(state->mem_ctx, struct getgrsid_state)) == NULL ) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + s->state = state; + + if ( (s->domain = find_domain_from_sid_noinit(&group_sid)) == NULL ) { + DEBUG(3, ("Could not find domain for sid %s\n", + sid_string_static(&group_sid))); + request_error(state); + return; + } + + sid_copy(&s->group_sid, &group_sid); + + winbindd_lookupsid_async( s->state->mem_ctx, &group_sid, + getgrsid_lookupsid_recv, s ); +} + + +static void getgrgid_recv(void *private_data, BOOL success, const char *sid) +{ + struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); + enum lsa_SidType name_type; + DOM_SID group_sid; + + if (success) { + DEBUG(10,("getgrgid_recv: gid %lu has sid %s\n", + (unsigned long)(state->request.data.gid), sid)); + + string_to_sid(&group_sid, sid); + winbindd_getgrsid(state, group_sid); + return; + } + + /* Ok, this might be "ours", i.e. an alias */ + if (pdb_gid_to_sid(state->request.data.gid, &group_sid) && + lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) && + (name_type == SID_NAME_ALIAS)) { + /* Hey, got an alias */ + DEBUG(10,("getgrgid_recv: we have an alias with gid %lu and sid %s\n", + (unsigned long)(state->request.data.gid), sid)); + winbindd_getgrsid(state, group_sid); + return; + } + + DEBUG(1, ("could not convert gid %lu to sid\n", + (unsigned long)state->request.data.gid)); + request_error(state); +} + +/* Return a group structure from a gid number */ +void winbindd_getgrgid(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + /* always use the async interface */ + winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, getgrgid_recv, state); +} + +/* + * set/get/endgrent functions + */ + +/* "Rewind" file pointer for group database enumeration */ + +static BOOL winbindd_setgrent_internal(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + + DEBUG(3, ("[%5lu]: setgrent\n", (unsigned long)state->pid)); + + /* Check user has enabled this */ + + if (!lp_winbind_enum_groups()) { + return False; + } + + /* Free old static data if it exists */ + + if (state->getgrent_state != NULL) { + free_getent_state(state->getgrent_state); + state->getgrent_state = NULL; + } + + /* Create sam pipes for each domain we know about */ + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + struct getent_state *domain_state; + + /* Create a state record for this domain */ + + /* don't add our domaina if we are a PDC or if we + are a member of a Samba domain */ + + if ( lp_winbind_trusted_domains_only() && domain->primary ) + { + continue; + } + + + if ((domain_state = SMB_MALLOC_P(struct getent_state)) == NULL) { + DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n")); + return False; + } + + ZERO_STRUCTP(domain_state); + + fstrcpy(domain_state->domain_name, domain->name); + + /* Add to list of open domains */ + + DLIST_ADD(state->getgrent_state, domain_state); + } + + state->getgrent_initialized = True; + return True; +} + +void winbindd_setgrent(struct winbindd_cli_state *state) +{ + if (winbindd_setgrent_internal(state)) { + request_ok(state); + } else { + request_error(state); + } +} + +/* Close file pointer to ntdom group database */ + +void winbindd_endgrent(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: endgrent\n", (unsigned long)state->pid)); + + free_getent_state(state->getgrent_state); + state->getgrent_initialized = False; + state->getgrent_state = NULL; + request_ok(state); +} + +/* Get the list of domain groups and domain aliases for a domain. We fill in + the sam_entries and num_sam_entries fields with domain group information. + The dispinfo_ndx field is incremented to the index of the next group to + fetch. Return True if some groups were returned, False otherwise. */ + +static BOOL get_sam_group_entries(struct getent_state *ent) +{ + NTSTATUS status; + uint32 num_entries; + struct acct_info *name_list = NULL; + TALLOC_CTX *mem_ctx; + BOOL result = False; + struct acct_info *sam_grp_entries = NULL; + struct winbindd_domain *domain; + + if (ent->got_sam_entries) + return False; + + if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)", + ent->domain_name))) { + DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n")); + return False; + } + + /* Free any existing group info */ + + SAFE_FREE(ent->sam_entries); + ent->num_sam_entries = 0; + ent->got_sam_entries = True; + + /* Enumerate domain groups */ + + num_entries = 0; + + if (!(domain = find_domain_from_name(ent->domain_name))) { + DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name)); + goto done; + } + + /* always get the domain global groups */ + + status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s\n", nt_errstr(status))); + result = False; + goto done; + } + + /* Copy entries into return buffer */ + + if (num_entries) { + if ( !(name_list = SMB_MALLOC_ARRAY(struct acct_info, num_entries)) ) { + DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n", + num_entries)); + result = False; + goto done; + } + memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) ); + } + + ent->num_sam_entries = num_entries; + + /* get the domain local groups if we are a member of a native win2k domain + and are not using LDAP to get the groups */ + + if ( ( lp_security() != SEC_ADS && domain->native_mode + && domain->primary) || domain->internal ) + { + DEBUG(4,("get_sam_group_entries: %s domain; enumerating local groups as well\n", + domain->native_mode ? "Native Mode 2k":"BUILTIN or local")); + + status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); + + if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n")); + num_entries = 0; + } + else + DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries)); + + /* Copy entries into return buffer */ + + if ( num_entries ) { + if ( !(name_list = SMB_REALLOC_ARRAY( name_list, struct acct_info, ent->num_sam_entries+num_entries)) ) + { + DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n", + num_entries)); + result = False; + goto done; + } + + memcpy( &name_list[ent->num_sam_entries], sam_grp_entries, + num_entries * sizeof(struct acct_info) ); + } + + ent->num_sam_entries += num_entries; + } + + + /* Fill in remaining fields */ + + ent->sam_entries = name_list; + ent->sam_entry_index = 0; + + result = (ent->num_sam_entries > 0); + + done: + talloc_destroy(mem_ctx); + + return result; +} + +/* Fetch next group entry from ntdom database */ + +#define MAX_GETGRENT_GROUPS 500 + +void winbindd_getgrent(struct winbindd_cli_state *state) +{ + struct getent_state *ent; + struct winbindd_gr *group_list = NULL; + int num_groups, group_list_ndx, gr_mem_list_len = 0; + char *gr_mem_list = NULL; + + DEBUG(3, ("[%5lu]: getgrent\n", (unsigned long)state->pid)); + + /* Check user has enabled this */ + + if (!lp_winbind_enum_groups()) { + request_error(state); + return; + } + + num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries); + + if (num_groups == 0) { + request_error(state); + return; + } + + if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) { + request_error(state); + return; + } + + memset(state->response.extra_data.data, '\0', + num_groups * sizeof(struct winbindd_gr) ); + + state->response.data.num_entries = 0; + + group_list = (struct winbindd_gr *)state->response.extra_data.data; + + if (!state->getgrent_initialized) + winbindd_setgrent_internal(state); + + if (!(ent = state->getgrent_state)) { + request_error(state); + return; + } + + /* Start sending back groups */ + + for (group_list_ndx = 0; group_list_ndx < num_groups; ) { + struct acct_info *name_list = NULL; + fstring domain_group_name; + uint32 result; + gid_t group_gid; + size_t gr_mem_len; + char *gr_mem; + DOM_SID group_sid; + struct winbindd_domain *domain; + + /* Do we need to fetch another chunk of groups? */ + + tryagain: + + DEBUG(10, ("entry_index = %d, num_entries = %d\n", + ent->sam_entry_index, ent->num_sam_entries)); + + if (ent->num_sam_entries == ent->sam_entry_index) { + + while(ent && !get_sam_group_entries(ent)) { + struct getent_state *next_ent; + + DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name)); + + /* Free state information for this domain */ + + SAFE_FREE(ent->sam_entries); + + next_ent = ent->next; + DLIST_REMOVE(state->getgrent_state, ent); + + SAFE_FREE(ent); + ent = next_ent; + } + + /* No more domains */ + + if (!ent) + break; + } + + name_list = (struct acct_info *)ent->sam_entries; + + if (!(domain = + find_domain_from_name(ent->domain_name))) { + DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); + result = False; + goto done; + } + + /* Lookup group info */ + + sid_copy(&group_sid, &domain->sid); + sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); + + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid))) { + union unid_t id; + enum lsa_SidType type; + + DEBUG(10, ("SID %s not in idmap\n", + sid_string_static(&group_sid))); + + if (!pdb_sid_to_id(&group_sid, &id, &type)) { + DEBUG(1, ("could not look up gid for group " + "%s\n", + name_list[ent->sam_entry_index].acct_name)); + ent->sam_entry_index++; + goto tryagain; + } + + if ((type != SID_NAME_DOM_GRP) && + (type != SID_NAME_ALIAS) && + (type != SID_NAME_WKN_GRP)) { + DEBUG(1, ("Group %s is a %s, not a group\n", + sid_type_lookup(type), + name_list[ent->sam_entry_index].acct_name)); + ent->sam_entry_index++; + goto tryagain; + } + group_gid = id.gid; + } + + DEBUG(10, ("got gid %lu for group %lu\n", (unsigned long)group_gid, + (unsigned long)name_list[ent->sam_entry_index].rid)); + + /* Fill in group entry */ + + fill_domain_username(domain_group_name, ent->domain_name, + name_list[ent->sam_entry_index].acct_name, True); + + result = fill_grent(&group_list[group_list_ndx], + ent->domain_name, + name_list[ent->sam_entry_index].acct_name, + group_gid); + + /* Fill in group membership entry */ + + if (result) { + size_t num_gr_mem = 0; + DOM_SID member_sid; + group_list[group_list_ndx].num_gr_mem = 0; + gr_mem = NULL; + gr_mem_len = 0; + + /* Get group membership */ + if (state->request.cmd == WINBINDD_GETGRLST) { + result = True; + } else { + sid_copy(&member_sid, &domain->sid); + sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid); + result = fill_grent_mem( + domain, + NULL, + &member_sid, + SID_NAME_DOM_GRP, + &num_gr_mem, + &gr_mem, &gr_mem_len); + + group_list[group_list_ndx].num_gr_mem = (uint32)num_gr_mem; + } + } + + if (result) { + /* Append to group membership list */ + gr_mem_list = (char *)SMB_REALLOC( + gr_mem_list, gr_mem_list_len + gr_mem_len); + + if (!gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) { + DEBUG(0, ("out of memory\n")); + gr_mem_list_len = 0; + break; + } + + DEBUG(10, ("list_len = %d, mem_len = %u\n", + gr_mem_list_len, (unsigned int)gr_mem_len)); + + memcpy(&gr_mem_list[gr_mem_list_len], gr_mem, + gr_mem_len); + + SAFE_FREE(gr_mem); + + group_list[group_list_ndx].gr_mem_ofs = + gr_mem_list_len; + + gr_mem_list_len += gr_mem_len; + } + + ent->sam_entry_index++; + + /* Add group to return list */ + + if (result) { + + DEBUG(10, ("adding group num_entries = %d\n", + state->response.data.num_entries)); + + group_list_ndx++; + state->response.data.num_entries++; + + state->response.length += + sizeof(struct winbindd_gr); + + } else { + DEBUG(0, ("could not lookup domain group %s\n", + domain_group_name)); + } + } + + /* Copy the list of group memberships to the end of the extra data */ + + if (group_list_ndx == 0) + goto done; + + state->response.extra_data.data = SMB_REALLOC( + state->response.extra_data.data, + group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len); + + if (!state->response.extra_data.data) { + DEBUG(0, ("out of memory\n")); + group_list_ndx = 0; + SAFE_FREE(gr_mem_list); + request_error(state); + return; + } + + memcpy(&((char *)state->response.extra_data.data) + [group_list_ndx * sizeof(struct winbindd_gr)], + gr_mem_list, gr_mem_list_len); + + state->response.length += gr_mem_list_len; + + DEBUG(10, ("returning %d groups, length = %d\n", + group_list_ndx, gr_mem_list_len)); + + /* Out of domains */ + + done: + + SAFE_FREE(gr_mem_list); + + if (group_list_ndx > 0) + request_ok(state); + else + request_error(state); +} + +/* List domain groups without mapping to unix ids */ + +void winbindd_list_groups(struct winbindd_cli_state *state) +{ + uint32 total_entries = 0; + struct winbindd_domain *domain; + const char *which_domain; + char *extra_data = NULL; + unsigned int extra_data_len = 0, i; + + DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid)); + + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + + /* Enumerate over trusted domains */ + + for (domain = domain_list(); domain; domain = domain->next) { + struct getent_state groups; + + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + + ZERO_STRUCT(groups); + + /* Get list of sam groups */ + + fstrcpy(groups.domain_name, domain->name); + + get_sam_group_entries(&groups); + + if (groups.num_sam_entries == 0) { + /* this domain is empty or in an error state */ + continue; + } + + /* keep track the of the total number of groups seen so + far over all domains */ + total_entries += groups.num_sam_entries; + + /* Allocate some memory for extra data. Note that we limit + account names to sizeof(fstring) = 128 characters. */ + extra_data = (char *)SMB_REALLOC( + extra_data, sizeof(fstring) * total_entries); + + if (!extra_data) { + DEBUG(0,("failed to enlarge buffer!\n")); + request_error(state); + return; + } + + /* Pack group list into extra data fields */ + for (i = 0; i < groups.num_sam_entries; i++) { + char *group_name = ((struct acct_info *) + groups.sam_entries)[i].acct_name; + fstring name; + + fill_domain_username(name, domain->name, group_name, True); + /* Append to extra data */ + memcpy(&extra_data[extra_data_len], name, + strlen(name)); + extra_data_len += strlen(name); + extra_data[extra_data_len++] = ','; + } + + SAFE_FREE(groups.sam_entries); + } + + /* Assign extra_data fields in response structure */ + if (extra_data) { + extra_data[extra_data_len - 1] = '\0'; + state->response.extra_data.data = extra_data; + state->response.length += extra_data_len; + } + + /* No domains may have responded but that's still OK so don't + return an error. */ + + request_ok(state); +} + +/* Get user supplementary groups. This is much quicker than trying to + invert the groups database. We merge the groups from the gids and + other_sids info3 fields as trusted domain, universal group + memberships, and nested groups (win2k native mode only) are not + returned by the getgroups RPC call but are present in the info3. */ + +struct getgroups_state { + struct winbindd_cli_state *state; + struct winbindd_domain *domain; + char *domname; + char *username; + DOM_SID user_sid; + + const DOM_SID *token_sids; + size_t i, num_token_sids; + + gid_t *token_gids; + size_t num_token_gids; +}; + +static void getgroups_usersid_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type); +static void getgroups_tokensids_recv(void *private_data, BOOL success, + DOM_SID *token_sids, size_t num_token_sids); +static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid); + +void winbindd_getgroups(struct winbindd_cli_state *state) +{ + struct getgroups_state *s; + + /* Ensure null termination */ + state->request.data.username + [sizeof(state->request.data.username)-1]='\0'; + + DEBUG(3, ("[%5lu]: getgroups %s\n", (unsigned long)state->pid, + state->request.data.username)); + + /* Parse domain and username */ + + s = TALLOC_P(state->mem_ctx, struct getgroups_state); + if (s == NULL) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + s->state = state; + + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); + + if (!parse_domain_user_talloc(state->mem_ctx, + state->request.data.username, + &s->domname, &s->username)) { + DEBUG(5, ("Could not parse domain user: %s\n", + state->request.data.username)); + + /* error out if we do not have nested group support */ + + if ( !lp_winbind_nested_groups() ) { + request_error(state); + return; + } + + s->domname = talloc_strdup( state->mem_ctx, get_global_sam_name() ); + s->username = talloc_strdup( state->mem_ctx, state->request.data.username ); + } + + /* Get info for the domain */ + + s->domain = find_domain_from_name_noinit(s->domname); + + if (s->domain == NULL) { + DEBUG(7, ("could not find domain entry for domain %s\n", + s->domname)); + request_error(state); + return; + } + + if ( s->domain->primary && lp_winbind_trusted_domains_only()) { + DEBUG(7,("winbindd_getgroups: My domain -- rejecting " + "getgroups() for %s\\%s.\n", s->domname, + s->username)); + request_error(state); + return; + } + + /* Get rid and name type from name. The following costs 1 packet */ + + winbindd_lookupname_async(state->mem_ctx, s->domname, s->username, + getgroups_usersid_recv, WINBINDD_GETGROUPS, s); +} + +static void getgroups_usersid_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type) +{ + struct getgroups_state *s = + (struct getgroups_state *)private_data; + + if ((!success) || + ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))) { + request_error(s->state); + return; + } + + sid_copy(&s->user_sid, sid); + + winbindd_gettoken_async(s->state->mem_ctx, &s->user_sid, + getgroups_tokensids_recv, s); +} + +static void getgroups_tokensids_recv(void *private_data, BOOL success, + DOM_SID *token_sids, size_t num_token_sids) +{ + struct getgroups_state *s = + (struct getgroups_state *)private_data; + + /* We need at least the user sid and the primary group in the token, + * otherwise it's an error */ + + if ((!success) || (num_token_sids < 2)) { + request_error(s->state); + return; + } + + s->token_sids = token_sids; + s->num_token_sids = num_token_sids; + s->i = 0; + + s->token_gids = NULL; + s->num_token_gids = 0; + + getgroups_sid2gid_recv(s, False, 0); +} + +static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid) +{ + struct getgroups_state *s = + (struct getgroups_state *)private_data; + + if (success) { + if (!add_gid_to_array_unique(s->state->mem_ctx, gid, + &s->token_gids, + &s->num_token_gids)) { + return; + } + } + + if (s->i < s->num_token_sids) { + const DOM_SID *sid = &s->token_sids[s->i]; + s->i += 1; + + if (sid_equal(sid, &s->user_sid)) { + getgroups_sid2gid_recv(s, False, 0); + return; + } + + winbindd_sid2gid_async(s->state->mem_ctx, sid, + getgroups_sid2gid_recv, s); + return; + } + + s->state->response.data.num_entries = s->num_token_gids; + /* s->token_gids are talloced */ + s->state->response.extra_data.data = smb_xmemdup(s->token_gids, s->num_token_gids * sizeof(gid_t)); + s->state->response.length += s->num_token_gids * sizeof(gid_t); + request_ok(s->state); +} + +/* Get user supplementary sids. This is equivalent to the + winbindd_getgroups() function but it involves a SID->SIDs mapping + rather than a NAME->SID->SIDS->GIDS mapping, which means we avoid + idmap. This call is designed to be used with applications that need + to do ACL evaluation themselves. Note that the cached info3 data is + not used + + this function assumes that the SID that comes in is a user SID. If + you pass in another type of SID then you may get unpredictable + results. +*/ + +static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids, + size_t num_sids); + +void winbindd_getusersids(struct winbindd_cli_state *state) +{ + DOM_SID *user_sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + user_sid = TALLOC_P(state->mem_ctx, DOM_SID); + if (user_sid == NULL) { + DEBUG(1, ("talloc failed\n")); + request_error(state); + return; + } + + if (!string_to_sid(user_sid, state->request.data.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + winbindd_gettoken_async(state->mem_ctx, user_sid, getusersids_recv, + state); +} + +static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids, + size_t num_sids) +{ + struct winbindd_cli_state *state = + (struct winbindd_cli_state *)private_data; + char *ret = NULL; + unsigned ofs, ret_size = 0; + size_t i; + + if (!success) { + request_error(state); + return; + } + + /* work out the response size */ + for (i = 0; i < num_sids; i++) { + const char *s = sid_string_static(&sids[i]); + ret_size += strlen(s) + 1; + } + + /* build the reply */ + ret = (char *)SMB_MALLOC(ret_size); + if (!ret) { + DEBUG(0, ("malloc failed\n")); + request_error(state); + return; + } + ofs = 0; + for (i = 0; i < num_sids; i++) { + const char *s = sid_string_static(&sids[i]); + safe_strcpy(ret + ofs, s, ret_size - ofs - 1); + ofs += strlen(ret+ofs) + 1; + } + + /* Send data back to client */ + state->response.data.num_entries = num_sids; + state->response.extra_data.data = ret; + state->response.length += ret_size; + request_ok(state); +} + +void winbindd_getuserdomgroups(struct winbindd_cli_state *state) +{ + DOM_SID user_sid; + struct winbindd_domain *domain; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + if (!string_to_sid(&user_sid, state->request.data.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + /* Get info for the domain */ + if ((domain = find_domain_from_sid_noinit(&user_sid)) == NULL) { + DEBUG(0,("could not find domain entry for sid %s\n", + sid_string_static(&user_sid))); + request_error(state); + return; + } + + sendto_domain(state, domain); +} + +enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID user_sid; + NTSTATUS status; + + char *sidstring; + ssize_t len; + DOM_SID *groups; + uint32 num_groups; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + if (!string_to_sid(&user_sid, state->request.data.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + return WINBINDD_ERROR; + } + + status = domain->methods->lookup_usergroups(domain, state->mem_ctx, + &user_sid, &num_groups, + &groups); + if (!NT_STATUS_IS_OK(status)) + return WINBINDD_ERROR; + + if (num_groups == 0) { + state->response.data.num_entries = 0; + state->response.extra_data.data = NULL; + return WINBINDD_OK; + } + + if (!print_sidlist(state->mem_ctx, groups, num_groups, &sidstring, &len)) { + DEBUG(0, ("talloc failed\n")); + return WINBINDD_ERROR; + } + + state->response.extra_data.data = SMB_STRDUP(sidstring); + if (!state->response.extra_data.data) { + return WINBINDD_ERROR; + } + state->response.length += len+1; + state->response.data.num_entries = num_groups; + + return WINBINDD_OK; +} diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c new file mode 100644 index 0000000000..9c3f634534 --- /dev/null +++ b/source3/winbindd/winbindd_misc.c @@ -0,0 +1,634 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - miscellaneous other functions + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Bartlett 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* Check the machine account password is valid */ + +void winbindd_check_machine_acct(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: check machine account\n", + (unsigned long)state->pid)); + + sendto_domain(state, find_our_domain()); +} + +enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + int num_retries = 0; + struct winbindd_domain *contact_domain; + + DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid)); + + /* Get trust account password */ + + again: + + contact_domain = find_our_domain(); + + /* This call does a cli_nt_setup_creds() which implicitly checks + the trust account password. */ + + invalidate_cm_connection(&contact_domain->conn); + + { + struct rpc_pipe_client *netlogon_pipe; + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); + } + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + + /* There is a race condition between fetching the trust account + password and the periodic machine password change. So it's + possible that the trust account password has been changed on us. + We are returned NT_STATUS_ACCESS_DENIED if this happens. */ + +#define MAX_RETRIES 8 + + if ((num_retries < MAX_RETRIES) && + NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) { + num_retries++; + goto again; + } + + /* Pass back result code - zero for success, other values for + specific failures. */ + + DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ? + "good" : "bad")); + + done: + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", + state->response.data.auth.nt_status_string)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +void winbindd_list_trusted_domains(struct winbindd_cli_state *state) +{ + struct winbindd_domain *d = NULL; + int extra_data_len = 0; + char *extra_data = NULL; + + DEBUG(3, ("[%5lu]: list trusted domains\n", + (unsigned long)state->pid)); + + for ( d=domain_list(); d; d=d->next ) { + if ( !extra_data ) { + extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s", + d->name, + d->alt_name ? d->alt_name : d->name, + sid_string_static(&d->sid)); + } else { + extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s", + extra_data, + d->name, + d->alt_name ? d->alt_name : d->name, + sid_string_static(&d->sid)); + } + } + + extra_data_len = 0; + if (extra_data != NULL) { + extra_data_len = strlen(extra_data); + } + + if (extra_data_len > 0) { + state->response.extra_data.data = SMB_STRDUP(extra_data); + state->response.length += extra_data_len+1; + } + + TALLOC_FREE( extra_data ); + + request_ok(state); +} + +enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + uint32 i, num_domains; + char **names, **alt_names; + DOM_SID *sids; + int extra_data_len = 0; + char *extra_data; + NTSTATUS result; + BOOL have_own_domain = False; + + DEBUG(3, ("[%5lu]: list trusted domains\n", + (unsigned long)state->pid)); + + result = domain->methods->trusted_domains(domain, state->mem_ctx, + &num_domains, &names, + &alt_names, &sids); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n", + nt_errstr(result) )); + return WINBINDD_ERROR; + } + + extra_data = talloc_strdup(state->mem_ctx, ""); + + if (num_domains > 0) + extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s", + names[0], + alt_names[0] ? alt_names[0] : names[0], + sid_string_static(&sids[0])); + + for (i=1; imem_ctx, "%s\n%s\\%s\\%s", + extra_data, + names[i], + alt_names[i] ? alt_names[i] : names[i], + sid_string_static(&sids[i])); + /* add our primary domain */ + + for (i=0; iname)) { + have_own_domain = True; + break; + } + } + + if (state->request.data.list_all_domains && !have_own_domain) { + extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s", + extra_data, + domain->name, + domain->alt_name ? domain->alt_name : domain->name, + sid_string_static(&domain->sid)); + } + + /* This is a bit excessive, but the extra data sooner or later will be + talloc'ed */ + + extra_data_len = 0; + if (extra_data != NULL) { + extra_data_len = strlen(extra_data); + } + + if (extra_data_len > 0) { + state->response.extra_data.data = SMB_STRDUP(extra_data); + state->response.length += extra_data_len+1; + } + + return WINBINDD_OK; +} + +void winbindd_getdcname(struct winbindd_cli_state *state) +{ + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + sendto_domain(state, find_our_domain()); +} + +enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + fstring dcname_slash; + char *p; + struct rpc_pipe_client *netlogon_pipe; + NTSTATUS result; + WERROR werr; + unsigned int orig_timeout; + + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + result = cm_connect_netlogon(domain, &netlogon_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("Can't contact the NETLOGON pipe\n")); + return WINBINDD_ERROR; + } + + /* This call can take a long time - allow the server to time out. + 35 seconds should do it. */ + + orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); + + werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, domain->dcname, + state->request.domain_name, + dcname_slash); + /* And restore our original timeout. */ + cli_set_timeout(netlogon_pipe->cli, orig_timeout); + + if (!W_ERROR_IS_OK(werr)) { + DEBUG(5, ("Error requesting DCname for domain %s: %s\n", + state->request.domain_name, dos_errstr(werr))); + return WINBINDD_ERROR; + } + + p = dcname_slash; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } + + fstrcpy(state->response.data.dc_name, p); + return WINBINDD_OK; +} + +static struct winbindd_child static_locator_child; + +void init_locator_child(void) +{ + setup_domain_child(NULL, &static_locator_child, "locator"); +} + +struct winbindd_child *locator_child(void) +{ + return &static_locator_child; +} + +void winbindd_dsgetdcname(struct winbindd_cli_state *state) +{ + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + sendto_child(state, locator_child()); +} + +enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + const char *dc = NULL; + + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, + NULL, NULL, state->request.flags, &info); + + if (!NT_STATUS_IS_OK(result)) { + return WINBINDD_ERROR; + } + + if (info->domain_controller_address) { + dc = info->domain_controller_address; + if ((dc[0] == '\\') && (dc[1] == '\\')) { + dc += 2; + } + } + + if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { + dc = info->domain_controller_name; + } + + if (!dc || !*dc) { + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.dc_name, dc); + + return WINBINDD_OK; +} + + +struct sequence_state { + TALLOC_CTX *mem_ctx; + struct winbindd_cli_state *cli_state; + struct winbindd_domain *domain; + struct winbindd_request *request; + struct winbindd_response *response; + char *extra_data; +}; + +static void sequence_recv(void *private_data, BOOL success); + +void winbindd_show_sequence(struct winbindd_cli_state *state) +{ + struct sequence_state *seq; + + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + + if (strlen(state->request.domain_name) > 0) { + struct winbindd_domain *domain; + domain = find_domain_from_name_noinit( + state->request.domain_name); + if (domain == NULL) { + request_error(state); + return; + } + sendto_domain(state, domain); + return; + } + + /* Ask all domains in sequence, collect the results in sequence_recv */ + + seq = TALLOC_P(state->mem_ctx, struct sequence_state); + if (seq == NULL) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + seq->mem_ctx = state->mem_ctx; + seq->cli_state = state; + seq->domain = domain_list(); + if (seq->domain == NULL) { + DEBUG(0, ("domain list empty\n")); + request_error(state); + return; + } + seq->request = TALLOC_ZERO_P(state->mem_ctx, + struct winbindd_request); + seq->response = TALLOC_ZERO_P(state->mem_ctx, + struct winbindd_response); + seq->extra_data = talloc_strdup(state->mem_ctx, ""); + + if ((seq->request == NULL) || (seq->response == NULL) || + (seq->extra_data == NULL)) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + seq->request->length = sizeof(*seq->request); + seq->request->cmd = WINBINDD_SHOW_SEQUENCE; + fstrcpy(seq->request->domain_name, seq->domain->name); + + async_domain_request(state->mem_ctx, seq->domain, + seq->request, seq->response, + sequence_recv, seq); +} + +static void sequence_recv(void *private_data, BOOL success) +{ + struct sequence_state *state = + (struct sequence_state *)private_data; + uint32 seq = DOM_SEQUENCE_NONE; + + if ((success) && (state->response->result == WINBINDD_OK)) + seq = state->response->data.domain_info.sequence_number; + + if (seq == DOM_SEQUENCE_NONE) { + state->extra_data = talloc_asprintf(state->mem_ctx, + "%s%s : DISCONNECTED\n", + state->extra_data, + state->domain->name); + } else { + state->extra_data = talloc_asprintf(state->mem_ctx, + "%s%s : %d\n", + state->extra_data, + state->domain->name, seq); + } + + state->domain->sequence_number = seq; + + state->domain = state->domain->next; + + if (state->domain == NULL) { + struct winbindd_cli_state *cli_state = state->cli_state; + cli_state->response.length = + sizeof(cli_state->response) + + strlen(state->extra_data) + 1; + cli_state->response.extra_data.data = + SMB_STRDUP(state->extra_data); + request_ok(cli_state); + return; + } + + /* Ask the next domain */ + fstrcpy(state->request->domain_name, state->domain->name); + async_domain_request(state->mem_ctx, state->domain, + state->request, state->response, + sequence_recv, state); +} + +/* This is the child-only version of --sequence. It only allows for a single + * domain (ie "our" one) to be displayed. */ + +enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid)); + + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + + domain->methods->sequence_number(domain, &domain->sequence_number); + + state->response.data.domain_info.sequence_number = + domain->sequence_number; + + return WINBINDD_OK; +} + +struct domain_info_state { + struct winbindd_domain *domain; + struct winbindd_cli_state *cli_state; +}; + +static void domain_info_init_recv(void *private_data, BOOL success); + +void winbindd_domain_info(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + + DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid, + state->request.domain_name)); + + domain = find_domain_from_name_noinit(state->request.domain_name); + + if (domain == NULL) { + DEBUG(3, ("Did not find domain [%s]\n", + state->request.domain_name)); + request_error(state); + return; + } + + if (!domain->initialized) { + struct domain_info_state *istate; + + istate = TALLOC_P(state->mem_ctx, struct domain_info_state); + if (istate == NULL) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + istate->cli_state = state; + istate->domain = domain; + + init_child_connection(domain, domain_info_init_recv, istate); + + return; + } + + fstrcpy(state->response.data.domain_info.name, + domain->name); + fstrcpy(state->response.data.domain_info.alt_name, + domain->alt_name); + fstrcpy(state->response.data.domain_info.sid, + sid_string_static(&domain->sid)); + + state->response.data.domain_info.native_mode = + domain->native_mode; + state->response.data.domain_info.active_directory = + domain->active_directory; + state->response.data.domain_info.primary = + domain->primary; + state->response.data.domain_info.sequence_number = + domain->sequence_number; + + request_ok(state); +} + +static void domain_info_init_recv(void *private_data, BOOL success) +{ + struct domain_info_state *istate = + (struct domain_info_state *)private_data; + struct winbindd_cli_state *state = istate->cli_state; + struct winbindd_domain *domain = istate->domain; + + DEBUG(10, ("Got back from child init: %d\n", success)); + + if ((!success) || (!domain->initialized)) { + DEBUG(5, ("Could not init child for domain %s\n", + domain->name)); + request_error(state); + return; + } + + fstrcpy(state->response.data.domain_info.name, + domain->name); + fstrcpy(state->response.data.domain_info.alt_name, + domain->alt_name); + fstrcpy(state->response.data.domain_info.sid, + sid_string_static(&domain->sid)); + + state->response.data.domain_info.native_mode = + domain->native_mode; + state->response.data.domain_info.active_directory = + domain->active_directory; + state->response.data.domain_info.primary = + domain->primary; + state->response.data.domain_info.sequence_number = + domain->sequence_number; + + request_ok(state); +} + +void winbindd_ping(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid)); + request_ok(state); +} + +/* List various tidbits of information */ + +void winbindd_info(struct winbindd_cli_state *state) +{ + + DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid)); + + state->response.data.info.winbind_separator = *lp_winbind_separator(); + fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING); + request_ok(state); +} + +/* Tell the client the current interface version */ + +void winbindd_interface_version(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: request interface version\n", + (unsigned long)state->pid)); + + state->response.data.interface_version = WINBIND_INTERFACE_VERSION; + request_ok(state); +} + +/* What domain are we a member of? */ + +void winbindd_domain_name(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid)); + + fstrcpy(state->response.data.domain_name, lp_workgroup()); + request_ok(state); +} + +/* What's my name again? */ + +void winbindd_netbios_name(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: request netbios name\n", + (unsigned long)state->pid)); + + fstrcpy(state->response.data.netbios_name, global_myname()); + request_ok(state); +} + +/* Where can I find the privilaged pipe? */ + +void winbindd_priv_pipe_dir(struct winbindd_cli_state *state) +{ + + DEBUG(3, ("[%5lu]: request location of privileged pipe\n", + (unsigned long)state->pid)); + + state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir()); + if (!state->response.extra_data.data) { + DEBUG(0, ("malloc failed\n")); + request_error(state); + return; + } + + /* must add one to length to copy the 0 for string termination */ + state->response.length += + strlen((char *)state->response.extra_data.data) + 1; + + request_ok(state); +} + diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c new file mode 100644 index 0000000000..50b24864b5 --- /dev/null +++ b/source3/winbindd/winbindd_pam.c @@ -0,0 +1,2382 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - pam auth funcions + + Copyright (C) Andrew Tridgell 2000 + Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Guenther Deschner 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) +{ + fstring str_sid; + + state->response.data.auth.info3.logon_time = + nt_time_to_unix(info3->logon_time); + state->response.data.auth.info3.logoff_time = + nt_time_to_unix(info3->logoff_time); + state->response.data.auth.info3.kickoff_time = + nt_time_to_unix(info3->kickoff_time); + state->response.data.auth.info3.pass_last_set_time = + nt_time_to_unix(info3->pass_last_set_time); + state->response.data.auth.info3.pass_can_change_time = + nt_time_to_unix(info3->pass_can_change_time); + state->response.data.auth.info3.pass_must_change_time = + nt_time_to_unix(info3->pass_must_change_time); + + state->response.data.auth.info3.logon_count = info3->logon_count; + state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count; + + state->response.data.auth.info3.user_rid = info3->user_rid; + state->response.data.auth.info3.group_rid = info3->group_rid; + sid_to_string(str_sid, &(info3->dom_sid.sid)); + fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); + + state->response.data.auth.info3.num_groups = info3->num_groups; + state->response.data.auth.info3.user_flgs = info3->user_flgs; + + state->response.data.auth.info3.acct_flags = info3->acct_flags; + state->response.data.auth.info3.num_other_sids = info3->num_other_sids; + + unistr2_to_ascii(state->response.data.auth.info3.user_name, + &info3->uni_user_name, -1); + unistr2_to_ascii(state->response.data.auth.info3.full_name, + &info3->uni_full_name, -1); + unistr2_to_ascii(state->response.data.auth.info3.logon_script, + &info3->uni_logon_script, -1); + unistr2_to_ascii(state->response.data.auth.info3.profile_path, + &info3->uni_profile_path, -1); + unistr2_to_ascii(state->response.data.auth.info3.home_dir, + &info3->uni_home_dir, -1); + unistr2_to_ascii(state->response.data.auth.info3.dir_drive, + &info3->uni_dir_drive, -1); + + unistr2_to_ascii(state->response.data.auth.info3.logon_srv, + &info3->uni_logon_srv, -1); + unistr2_to_ascii(state->response.data.auth.info3.logon_dom, + &info3->uni_logon_dom, -1); + + return NT_STATUS_OK; +} + +static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) +{ + prs_struct ps; + uint32 size; + if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { + return NT_STATUS_NO_MEMORY; + } + if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { + prs_mem_free(&ps); + return NT_STATUS_UNSUCCESSFUL; + } + + size = prs_data_size(&ps); + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_MALLOC(size); + if (!state->response.extra_data.data) { + prs_mem_free(&ps); + return NT_STATUS_NO_MEMORY; + } + memset( state->response.extra_data.data, '\0', size ); + prs_copy_all_data_out((char *)state->response.extra_data.data, &ps); + state->response.length += size; + prs_mem_free(&ps); + return NT_STATUS_OK; +} + +static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + const NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + /* We've been asked to return the unix username, per + 'winbind use default domain' settings and the like */ + + fstring username_out; + const char *nt_username, *nt_domain; + + if (!(nt_domain = unistr2_tdup(mem_ctx, + &info3->uni_logon_dom))) { + /* If the server didn't give us one, just use the one + * we sent them */ + nt_domain = name_domain; + } + + if (!(nt_username = unistr2_tdup(mem_ctx, + &info3->uni_user_name))) { + /* If the server didn't give us one, just use the one + * we sent them */ + nt_username = name_user; + } + + fill_domain_username(username_out, nt_domain, nt_username, + True); + + DEBUG(5,("Setting unix username to [%s]\n", username_out)); + + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_STRDUP(username_out); + if (!state->response.extra_data.data) { + return NT_STATUS_NO_MEMORY; + } + state->response.length += + strlen((const char *)state->response.extra_data.data)+1; + + return NT_STATUS_OK; +} + +static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + const NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + char *afsname = NULL; + char *cell; + + afsname = talloc_strdup(mem_ctx, lp_afs_username_map()); + if (afsname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + afsname = talloc_string_sub(mem_ctx, + lp_afs_username_map(), + "%D", name_domain); + afsname = talloc_string_sub(mem_ctx, afsname, + "%u", name_user); + afsname = talloc_string_sub(mem_ctx, afsname, + "%U", name_user); + + { + DOM_SID user_sid; + fstring sidstr; + + sid_copy(&user_sid, &info3->dom_sid.sid); + sid_append_rid(&user_sid, info3->user_rid); + sid_to_string(sidstr, &user_sid); + afsname = talloc_string_sub(mem_ctx, afsname, + "%s", sidstr); + } + + if (afsname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + strlower_m(afsname); + + DEBUG(10, ("Generating token for user %s\n", afsname)); + + cell = strchr(afsname, '@'); + + if (cell == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *cell = '\0'; + cell += 1; + + /* Append an AFS token string */ + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = + afs_createtoken_str(afsname, cell); + + if (state->response.extra_data.data != NULL) { + state->response.length += + strlen((const char *)state->response.extra_data.data)+1; + } + + return NT_STATUS_OK; +} + +static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, + NET_USER_INFO_3 *info3, + const char *group_sid) +/** + * Check whether a user belongs to a group or list of groups. + * + * @param mem_ctx talloc memory context. + * @param info3 user information, including group membership info. + * @param group_sid One or more groups , separated by commas. + * + * @return NT_STATUS_OK on success, + * NT_STATUS_LOGON_FAILURE if the user does not belong, + * or other NT_STATUS_IS_ERR(status) for other kinds of failure. + */ +{ + DOM_SID *require_membership_of_sid; + size_t num_require_membership_of_sid; + fstring req_sid; + const char *p; + DOM_SID sid; + size_t i; + struct nt_user_token *token; + NTSTATUS status; + + /* Parse the 'required group' SID */ + + if (!group_sid || !group_sid[0]) { + /* NO sid supplied, all users may access */ + return NT_STATUS_OK; + } + + if (!(token = TALLOC_ZERO_P(mem_ctx, struct nt_user_token))) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + num_require_membership_of_sid = 0; + require_membership_of_sid = NULL; + + p = group_sid; + + while (next_token(&p, req_sid, ",", sizeof(req_sid))) { + if (!string_to_sid(&sid, req_sid)) { + DEBUG(0, ("check_info3_in_group: could not parse %s " + "as a SID!", req_sid)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!add_sid_to_array(mem_ctx, &sid, + &require_membership_of_sid, + &num_require_membership_of_sid)) { + DEBUG(0, ("add_sid_to_array failed\n")); + return NT_STATUS_NO_MEMORY; + } + } + + status = sid_array_from_info3(mem_ctx, info3, + &token->user_sids, + &token->num_sids, + True); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!NT_STATUS_IS_OK(status = add_aliases(get_global_sam_sid(), + token)) + || !NT_STATUS_IS_OK(status = add_aliases(&global_sid_Builtin, + token))) { + DEBUG(3, ("could not add aliases: %s\n", + nt_errstr(status))); + return status; + } + + debug_nt_user_token(DBGC_CLASS, 10, token); + + for (i=0; irequest.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) { + domain = find_domain_from_name_noinit(domain_name); + if (domain == NULL) { + DEBUG(3, ("Authentication for domain [%s] skipped " + "as it is not a trusted domain\n", + domain_name)); + } else { + return domain; + } + } + + return find_our_domain(); +} + +static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) +{ + resp->data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); + + /* we might have given a more useful error above */ + if (*resp->data.auth.error_string == '\0') + fstrcpy(resp->data.auth.error_string, + get_friendly_nt_error_msg(result)); + resp->data.auth.pam_error = nt_status_to_pam(result); +} + +static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_1 password_policy; + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(5,("fillup_password_policy: No inbound trust to " + "contact domain %s\n", domain->name)); + return NT_STATUS_NOT_SUPPORTED; + } + + methods = domain->methods; + + status = methods->password_policy(domain, state->mem_ctx, &password_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + state->response.data.auth.policy.min_length_password = + password_policy.min_length_password; + state->response.data.auth.policy.password_history = + password_policy.password_history; + state->response.data.auth.policy.password_properties = + password_policy.password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs(&(password_policy.expire)); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs(&(password_policy.min_passwordage)); + + return NT_STATUS_OK; +} + +static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint16 *max_allowed_bad_attempts) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_12 lockout_policy; + + *max_allowed_bad_attempts = 0; + + methods = domain->methods; + + status = methods->lockout_policy(domain, mem_ctx, &lockout_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout; + + return NT_STATUS_OK; +} + +static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *password_properties) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_1 password_policy; + + *password_properties = 0; + + methods = domain->methods; + + status = methods->password_policy(domain, mem_ctx, &password_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + *password_properties = password_policy.password_properties; + + return NT_STATUS_OK; +} + +#ifdef HAVE_KRB5 + +static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, + const char *type, + uid_t uid, + BOOL *internal_ccache) +{ + /* accept FILE and WRFILE as krb5_cc_type from the client and then + * build the full ccname string based on the user's uid here - + * Guenther*/ + + const char *gen_cc = NULL; + + *internal_ccache = True; + + if (uid == -1) { + goto memory_ccache; + } + + if (!type || type[0] == '\0') { + goto memory_ccache; + } + + if (strequal(type, "FILE")) { + gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid); + } else if (strequal(type, "WRFILE")) { + gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid); + } else { + DEBUG(10,("we don't allow to set a %s type ccache\n", type)); + goto memory_ccache; + } + + *internal_ccache = False; + goto done; + + memory_ccache: + gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache"); + + done: + if (gen_cc == NULL) { + DEBUG(0,("out of memory\n")); + return NULL; + } + + DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":"")); + + return gen_cc; +} + +static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc) +{ + const char *type = state->request.data.auth.krb5_cc_type; + + state->response.data.auth.krb5ccname[0] = '\0'; + + if (type[0] == '\0') { + return; + } + + if (!strequal(type, "FILE") && + !strequal(type, "WRFILE")) { + DEBUG(10,("won't return krbccname for a %s type ccache\n", + type)); + return; + } + + fstrcpy(state->response.data.auth.krb5ccname, cc); +} + +#endif + +static uid_t get_uid_from_state(struct winbindd_cli_state *state) +{ + uid_t uid = -1; + + uid = state->request.data.auth.uid; + + if (uid < 0) { + DEBUG(1,("invalid uid: '%d'\n", uid)); + return -1; + } + return uid; +} + +/********************************************************************** + Authenticate a user with a clear text password using Kerberos and fill up + ccache if required + **********************************************************************/ + +static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ +#ifdef HAVE_KRB5 + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + krb5_error_code krb5_ret; + const char *cc = NULL; + const char *principal_s = NULL; + const char *service = NULL; + char *realm = NULL; + fstring name_domain, name_user; + time_t ticket_lifetime = 0; + time_t renewal_until = 0; + uid_t uid = -1; + ADS_STRUCT *ads; + time_t time_offset = 0; + BOOL internal_ccache = True; + + ZERO_STRUCTP(info3); + + *info3 = NULL; + + /* 1st step: + * prepare a krb5_cc_cache string for the user */ + + uid = get_uid_from_state(state); + if (uid == -1) { + DEBUG(0,("no valid uid\n")); + } + + cc = generate_krb5_ccache(state->mem_ctx, + state->request.data.auth.krb5_cc_type, + state->request.data.auth.uid, + &internal_ccache); + if (cc == NULL) { + return NT_STATUS_NO_MEMORY; + } + + + /* 2nd step: + * get kerberos properties */ + + if (domain->private_data) { + ads = (ADS_STRUCT *)domain->private_data; + time_offset = ads->auth.time_offset; + } + + + /* 3rd step: + * do kerberos auth and setup ccache as the user */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + realm = domain->alt_name; + strupper_m(realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + if (principal_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm); + if (service == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* if this is a user ccache, we need to act as the user to let the krb5 + * library handle the chown, etc. */ + + /************************ ENTERING NON-ROOT **********************/ + + if (!internal_ccache) { + set_effective_uid(uid); + DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid)); + } + + result = kerberos_return_info3_from_pac(state->mem_ctx, + principal_s, + state->request.data.auth.pass, + time_offset, + &ticket_lifetime, + &renewal_until, + cc, + True, + True, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + info3); + if (!internal_ccache) { + gain_root_privilege(); + } + + /************************ RETURNED TO ROOT **********************/ + + if (!NT_STATUS_IS_OK(result)) { + goto failed; + } + + DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", + principal_s)); + + /* if we had a user's ccache then return that string for the pam + * environment */ + + if (!internal_ccache) { + + setup_return_cc_name(state, cc); + + result = add_ccache_to_list(principal_s, + cc, + service, + state->request.data.auth.user, + realm, + uid, + time(NULL), + ticket_lifetime, + renewal_until, + False); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", + nt_errstr(result))); + } + } else { + + /* need to delete the memory cred cache, it is not used anymore */ + + krb5_ret = ads_kdestroy(cc); + if (krb5_ret) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not destroy krb5 credential cache: " + "%s\n", error_message(krb5_ret))); + } + + } + + return NT_STATUS_OK; + +failed: + + /* we could have created a new credential cache with a valid tgt in it + * but we werent able to get or verify the service ticket for this + * local host and therefor didn't get the PAC, we need to remove that + * cache entirely now */ + + krb5_ret = ads_kdestroy(cc); + if (krb5_ret) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not destroy krb5 credential cache: " + "%s\n", error_message(krb5_ret))); + } + + if (!NT_STATUS_IS_OK(remove_ccache(state->request.data.auth.user))) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not remove ccache for user %s\n", + state->request.data.auth.user)); + } + + return result; +#else + return NT_STATUS_NOT_SUPPORTED; +#endif /* HAVE_KRB5 */ +} + +/**************************************************************** +****************************************************************/ + +static BOOL check_request_flags(uint32_t flags) +{ + uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | + WBFLAG_PAM_UNIX_NAME | + WBFLAG_PAM_INFO3_NDR; + + if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || + ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || + ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || + !(flags & flags_edata) ) { + return True; + } + + DEBUG(1,("check_request_flags: invalid request flags\n")); + + return False; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS append_data(struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + NTSTATUS result; + uint32_t flags = state->request.flags; + + if (flags & WBFLAG_PAM_USER_SESSION_KEY) { + memcpy(state->response.data.auth.user_session_key, + info3->user_sess_key, + sizeof(state->response.data.auth.user_session_key) + /* 16 */); + } + + if (flags & WBFLAG_PAM_LMKEY) { + memcpy(state->response.data.auth.first_8_lm_hash, + info3->lm_sess_key, + sizeof(state->response.data.auth.first_8_lm_hash) + /* 8 */); + } + + if (flags & WBFLAG_PAM_INFO3_TEXT) { + result = append_info3_as_txt(state->mem_ctx, state, info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append INFO3 (TXT): %s\n", + nt_errstr(result))); + return result; + } + } + + /* currently, anything from here on potentially overwrites extra_data. */ + + if (flags & WBFLAG_PAM_INFO3_NDR) { + result = append_info3_as_ndr(state->mem_ctx, state, info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append INFO3 (NDR): %s\n", + nt_errstr(result))); + return result; + } + } + + if (flags & WBFLAG_PAM_UNIX_NAME) { + result = append_unix_username(state->mem_ctx, state, info3, + name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append Unix Username: %s\n", + nt_errstr(result))); + return result; + } + } + + if (flags & WBFLAG_PAM_AFS_TOKEN) { + result = append_afs_token(state->mem_ctx, state, info3, + name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append AFS token: %s\n", + nt_errstr(result))); + return result; + } + } + + return NT_STATUS_OK; +} + +void winbindd_pam_auth(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, name_user; + NTSTATUS result; + + /* Ensure null termination */ + state->request.data.auth.user + [sizeof(state->request.data.auth.user)-1]='\0'; + + /* Ensure null termination */ + state->request.data.auth.pass + [sizeof(state->request.data.auth.pass)-1]='\0'; + + DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + /* Parse domain and username */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + + if (!canonicalize_username(state->request.data.auth.user, + name_domain, name_user)) { + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + domain = find_auth_domain(state, name_domain); + + if (domain == NULL) { + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + sendto_domain(state, domain); + return; + done: + set_auth_errors(&state->response, result); + DEBUG(5, ("Plain text authentication for %s returned %s " + "(PAM: %d)\n", + state->request.data.auth.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); +} + +NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + NTSTATUS result = NT_STATUS_LOGON_FAILURE; + uint16 max_allowed_bad_attempts; + fstring name_domain, name_user; + DOM_SID sid; + enum lsa_SidType type; + uchar new_nt_pass[NT_HASH_LEN]; + const uint8 *cached_nt_pass; + const uint8 *cached_salt; + NET_USER_INFO_3 *my_info3; + time_t kickoff_time, must_change_time; + BOOL password_good = False; +#ifdef HAVE_KRB5 + struct winbindd_tdc_domain *tdc_domain = NULL; +#endif + + *info3 = NULL; + + ZERO_STRUCTP(info3); + + DEBUG(10,("winbindd_dual_pam_auth_cached\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + + if (!lookup_cached_name(state->mem_ctx, + name_domain, + name_user, + &sid, + &type)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n")); + return NT_STATUS_NO_SUCH_USER; + } + + if (type != SID_NAME_USER) { + DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type))); + return NT_STATUS_LOGON_FAILURE; + } + + result = winbindd_get_creds(domain, + state->mem_ctx, + &sid, + &my_info3, + &cached_nt_pass, + &cached_salt); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result))); + return result; + } + + *info3 = my_info3; + + E_md4hash(state->request.data.auth.pass, new_nt_pass); + + dump_data_pw("new_nt_pass", new_nt_pass, NT_HASH_LEN); + dump_data_pw("cached_nt_pass", cached_nt_pass, NT_HASH_LEN); + if (cached_salt) { + dump_data_pw("cached_salt", cached_salt, NT_HASH_LEN); + } + + if (cached_salt) { + /* In this case we didn't store the nt_hash itself, + but the MD5 combination of salt + nt_hash. */ + uchar salted_hash[NT_HASH_LEN]; + E_md5hash(cached_salt, new_nt_pass, salted_hash); + + password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ? + True : False; + } else { + /* Old cached cred - direct store of nt_hash (bad bad bad !). */ + password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ? + True : False; + } + + if (password_good) { + + /* User *DOES* know the password, update logon_time and reset + * bad_pw_count */ + + my_info3->user_flgs |= LOGON_CACHED_ACCOUNT; + + if (my_info3->acct_flags & ACB_AUTOLOCK) { + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + + if (my_info3->acct_flags & ACB_DISABLED) { + return NT_STATUS_ACCOUNT_DISABLED; + } + + if (my_info3->acct_flags & ACB_WSTRUST) { + return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + } + + if (my_info3->acct_flags & ACB_SVRTRUST) { + return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; + } + + if (my_info3->acct_flags & ACB_DOMTRUST) { + return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; + } + + if (!(my_info3->acct_flags & ACB_NORMAL)) { + DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", + my_info3->acct_flags)); + return NT_STATUS_LOGON_FAILURE; + } + + kickoff_time = nt_time_to_unix(my_info3->kickoff_time); + if (kickoff_time != 0 && time(NULL) > kickoff_time) { + return NT_STATUS_ACCOUNT_EXPIRED; + } + + must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); + if (must_change_time != 0 && must_change_time < time(NULL)) { + /* we allow grace logons when the password has expired */ + my_info3->user_flgs |= LOGON_GRACE_LOGON; + /* return NT_STATUS_PASSWORD_EXPIRED; */ + goto success; + } + +#ifdef HAVE_KRB5 + if ((state->request.flags & WBFLAG_PAM_KRB5) && + ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && + (tdc_domain->trust_type & DS_DOMAIN_TRUST_TYPE_UPLEVEL)) { + + uid_t uid = -1; + const char *cc = NULL; + char *realm = NULL; + const char *principal_s = NULL; + const char *service = NULL; + BOOL internal_ccache = False; + + uid = get_uid_from_state(state); + if (uid == -1) { + DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + cc = generate_krb5_ccache(state->mem_ctx, + state->request.data.auth.krb5_cc_type, + state->request.data.auth.uid, + &internal_ccache); + if (cc == NULL) { + return NT_STATUS_NO_MEMORY; + } + + realm = domain->alt_name; + strupper_m(realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + if (principal_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm); + if (service == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!internal_ccache) { + + setup_return_cc_name(state, cc); + + result = add_ccache_to_list(principal_s, + cc, + service, + state->request.data.auth.user, + domain->alt_name, + uid, + time(NULL), + time(NULL) + lp_winbind_cache_time(), + time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + True); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed " + "to add ccache to list: %s\n", + nt_errstr(result))); + } + } + } +#endif /* HAVE_KRB5 */ + success: + /* FIXME: we possibly should handle logon hours as well (does xp when + * offline?) see auth/auth_sam.c:sam_account_ok for details */ + + unix_to_nt_time(&my_info3->logon_time, time(NULL)); + my_info3->bad_pw_count = 0; + + result = winbindd_update_creds_by_info3(domain, + state->mem_ctx, + state->request.data.auth.user, + state->request.data.auth.pass, + my_info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n", + nt_errstr(result))); + return result; + } + + return NT_STATUS_OK; + + } + + /* User does *NOT* know the correct password, modify info3 accordingly */ + + /* failure of this is not critical */ + result = get_max_bad_attempts_from_lockout_policy(domain, state->mem_ctx, &max_allowed_bad_attempts); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. " + "Won't be able to honour account lockout policies\n")); + } + + /* increase counter */ + my_info3->bad_pw_count++; + + if (max_allowed_bad_attempts == 0) { + goto failed; + } + + /* lockout user */ + if (my_info3->bad_pw_count >= max_allowed_bad_attempts) { + + uint32 password_properties; + + result = get_pwd_properties(domain, state->mem_ctx, &password_properties); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n")); + } + + if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || + (password_properties & DOMAIN_LOCKOUT_ADMINS)) { + my_info3->acct_flags |= ACB_AUTOLOCK; + } + } + +failed: + result = winbindd_update_creds_by_info3(domain, + state->mem_ctx, + state->request.data.auth.user, + NULL, + my_info3); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", + nt_errstr(result))); + } + + return NT_STATUS_LOGON_FAILURE; +} + +NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + struct winbindd_domain *contact_domain; + fstring name_domain, name_user; + NTSTATUS result; + + DEBUG(10,("winbindd_dual_pam_auth_kerberos\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + /* what domain should we contact? */ + + if ( IS_DC ) { + if (!(contact_domain = find_domain_from_name(name_domain))) { + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + } else { + if (is_myname(name_domain)) { + DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + contact_domain = find_domain_from_name(name_domain); + if (contact_domain == NULL) { + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); + + contact_domain = find_our_domain(); + } + } + + if (contact_domain->initialized && + contact_domain->active_directory) { + goto try_login; + } + + if (!contact_domain->initialized) { + init_dc_connection(contact_domain); + } + + if (!contact_domain->active_directory) { + DEBUG(3,("krb5 auth requested but domain is not Active Directory\n")); + return NT_STATUS_INVALID_LOGON_TYPE; + } +try_login: + result = winbindd_raw_kerberos_login(contact_domain, state, info3); +done: + return result; +} + +NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + + struct rpc_pipe_client *netlogon_pipe; + uchar chal[8]; + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; + int attempts = 0; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + struct winbindd_domain *contact_domain; + fstring name_domain, name_user; + BOOL retry; + NTSTATUS result; + NET_USER_INFO_3 *my_info3; + + ZERO_STRUCTP(info3); + + *info3 = NULL; + + my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3); + if (my_info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + + DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + /* do password magic */ + + + generate_random_buffer(chal, 8); + if (lp_client_ntlmv2_auth()) { + DATA_BLOB server_chal; + DATA_BLOB names_blob; + DATA_BLOB nt_response; + DATA_BLOB lm_response; + server_chal = data_blob_talloc(state->mem_ctx, chal, 8); + + /* note that the 'workgroup' here is a best guess - we don't know + the server's domain at this point. The 'server name' is also + dodgy... + */ + names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); + + if (!SMBNTLMv2encrypt(name_user, name_domain, + state->request.data.auth.pass, + &server_chal, + &names_blob, + &lm_response, &nt_response, NULL)) { + data_blob_free(&names_blob); + data_blob_free(&server_chal); + DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + data_blob_free(&names_blob); + data_blob_free(&server_chal); + lm_resp = data_blob_talloc(state->mem_ctx, lm_response.data, + lm_response.length); + nt_resp = data_blob_talloc(state->mem_ctx, nt_response.data, + nt_response.length); + data_blob_free(&lm_response); + data_blob_free(&nt_response); + + } else { + if (lp_client_lanman_auth() + && SMBencrypt(state->request.data.auth.pass, + chal, + local_lm_response)) { + lm_resp = data_blob_talloc(state->mem_ctx, + local_lm_response, + sizeof(local_lm_response)); + } else { + lm_resp = data_blob_null; + } + SMBNTencrypt(state->request.data.auth.pass, + chal, + local_nt_response); + + nt_resp = data_blob_talloc(state->mem_ctx, + local_nt_response, + sizeof(local_nt_response)); + } + + /* what domain should we contact? */ + + if ( IS_DC ) { + if (!(contact_domain = find_domain_from_name(name_domain))) { + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + } else { + if (is_myname(name_domain)) { + DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + contact_domain = find_our_domain(); + } + + /* check authentication loop */ + + do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client + *cli, TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + NET_USER_INFO_3 *info3); + + ZERO_STRUCTP(my_info3); + retry = False; + + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + 0, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + my_info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + + attempts += 1; + + /* We have to try a second time as cm_connect_netlogon + might not yet have noticed that the DC has killed + our connection. */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + retry = True; + continue; + } + + /* if we get access denied, a possible cause was that we had + and open connection to the DC, but someone changed our + machine account password out from underneath us using 'net + rpc changetrustpw' */ + + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth: sam_logon returned " + "ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. " + "Killing connections to domain %s\n", + name_domain)); + invalidate_cm_connection(&contact_domain->conn); + retry = True; + } + + } while ( (attempts < 2) && retry ); + + /* handle the case where a NT4 DC does not fill in the acct_flags in + * the samlogon reply info3. When accurate info3 is required by the + * caller, we look up the account flags ourselve - gd */ + + if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && + (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) { + + struct rpc_pipe_client *samr_pipe; + POLICY_HND samr_domain_handle, user_pol; + SAM_USERINFO_CTR *user_ctr; + NTSTATUS status_tmp; + uint32 acct_flags; + + ZERO_STRUCT(user_ctr); + + status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, + &samr_pipe, &samr_domain_handle); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not open handle to SAMR pipe: %s\n", + nt_errstr(status_tmp))); + goto done; + } + + status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx, + &samr_domain_handle, + MAXIMUM_ALLOWED_ACCESS, + my_info3->user_rid, &user_pol); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not open user handle on SAMR pipe: %s\n", + nt_errstr(status_tmp))); + goto done; + } + + status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx, + &user_pol, 16, &user_ctr); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not query user info on SAMR pipe: %s\n", + nt_errstr(status_tmp))); + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + goto done; + } + + acct_flags = user_ctr->info.id16->acb_info; + + if (acct_flags == 0) { + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + goto done; + } + + my_info3->acct_flags = acct_flags; + + DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); + + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + } + + *info3 = my_info3; +done: + return result; +} + +enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_LOGON_FAILURE; + NTSTATUS krb5_result = NT_STATUS_OK; + fstring name_domain, name_user; + NET_USER_INFO_3 *info3 = NULL; + + /* Ensure null termination */ + state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; + + /* Ensure null termination */ + state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; + + DEBUG(3, ("[%5lu]: dual pam auth %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + /* Parse domain and username */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + if (domain->online == False) { + result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + if (domain->startup) { + /* Logons are very important to users. If we're offline and + we get a request within the first 30 seconds of startup, + try very hard to find a DC and go online. */ + + DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth " + "request in startup mode.\n", domain->name )); + + winbindd_flush_negative_conn_cache(domain); + result = init_dc_connection(domain); + } + } + + DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline")); + + /* Check for Kerberos authentication */ + if (domain->online && (state->request.flags & WBFLAG_PAM_KRB5)) { + + result = winbindd_dual_pam_auth_kerberos(domain, state, &info3); + /* save for later */ + krb5_result = result; + + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n")); + goto process_result; + } else { + DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result))); + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) || + NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n")); + set_domain_offline( domain ); + goto cached_logon; + } + + /* there are quite some NT_STATUS errors where there is no + * point in retrying with a samlogon, we explictly have to take + * care not to increase the bad logon counter on the DC */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) || + NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) || + NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) || + NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) || + NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) || + NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) || + NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) || + NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) || + NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) || + NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { + goto process_result; + } + + if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) { + DEBUG(3,("falling back to samlogon\n")); + goto sam_logon; + } else { + goto cached_logon; + } + } + +sam_logon: + /* Check for Samlogon authentication */ + if (domain->online) { + result = winbindd_dual_pam_auth_samlogon(domain, state, &info3); + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n")); + /* add the Krb5 err if we have one */ + if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) { + info3->user_flgs |= LOGON_KRB5_FAIL_CLOCK_SKEW; + } + goto process_result; + } + + DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", + nt_errstr(result))); + + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) || + NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) + { + DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n")); + set_domain_offline( domain ); + goto cached_logon; + } + + if (domain->online) { + /* We're still online - fail. */ + goto done; + } + } + +cached_logon: + /* Check for Cached logons */ + if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && + lp_winbind_offline_logon()) { + + result = winbindd_dual_pam_auth_cached(domain, state, &info3); + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n")); + goto process_result; + } else { + DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result))); + goto done; + } + } + +process_result: + + if (NT_STATUS_IS_OK(result)) { + + DOM_SID user_sid; + + /* In all codepaths where result == NT_STATUS_OK info3 must have + been initialized. */ + if (!info3) { + result = NT_STATUS_INTERNAL_ERROR; + goto done; + } + + netsamlogon_cache_store(name_user, info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + + /* save name_to_sid info as early as possible (only if + this is our primary domain so we don't invalidate + the cache entry by storing the seq_num for the wrong + domain). */ + if ( domain->primary ) { + sid_compose(&user_sid, &info3->dom_sid.sid, + info3->user_rid); + cache_name2sid(domain, name_domain, name_user, + SID_NAME_USER, &user_sid); + } + + /* Check if the user is in the right group */ + + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, + state->request.data.auth.require_membership_of_sid))) { + DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", + state->request.data.auth.user, + state->request.data.auth.require_membership_of_sid)); + goto done; + } + + result = append_data(state, info3, name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { + + /* Store in-memory creds for single-signon using ntlm_auth. */ + result = winbindd_add_memory_creds(state->request.data.auth.user, + get_uid_from_state(state), + state->request.data.auth.pass); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result))); + goto done; + } + + if (lp_winbind_offline_logon()) { + result = winbindd_store_creds(domain, + state->mem_ctx, + state->request.data.auth.user, + state->request.data.auth.pass, + info3, NULL); + if (!NT_STATUS_IS_OK(result)) { + + /* Release refcount. */ + winbindd_delete_memory_creds(state->request.data.auth.user); + + DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); + goto done; + } + } + } + + result = fillup_password_policy(domain, state); + + if (!NT_STATUS_IS_OK(result) + && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) + { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); + goto done; + } + + result = NT_STATUS_OK; + } + +done: + /* give us a more useful (more correct?) error code */ + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + result = NT_STATUS_NO_LOGON_SERVERS; + } + + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + + /* we might have given a more useful error above */ + if (!*state->response.data.auth.error_string) + fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", + state->request.data.auth.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + + +/********************************************************************** + Challenge Response Authentication Protocol +**********************************************************************/ + +void winbindd_pam_auth_crap(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain = NULL; + const char *domain_name = NULL; + NTSTATUS result; + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + if (!state->privileged) { + char *error_string = NULL; + DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access " + "denied. !\n")); + DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions " + "on %s are set correctly.\n", + get_winbind_priv_pipe_dir())); + /* send a better message than ACCESS_DENIED */ + error_string = talloc_asprintf(state->mem_ctx, + "winbind client not authorized " + "to use winbindd_pam_auth_crap." + " Ensure permissions on %s " + "are set correctly.", + get_winbind_priv_pipe_dir()); + fstrcpy(state->response.data.auth.error_string, error_string); + result = NT_STATUS_ACCESS_DENIED; + goto done; + } + + /* Ensure null termination */ + state->request.data.auth_crap.user + [sizeof(state->request.data.auth_crap.user)-1]=0; + state->request.data.auth_crap.domain + [sizeof(state->request.data.auth_crap.domain)-1]=0; + + DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n", + (unsigned long)state->pid, + state->request.data.auth_crap.domain, + state->request.data.auth_crap.user)); + + if (*state->request.data.auth_crap.domain != '\0') { + domain_name = state->request.data.auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + domain_name = lp_workgroup(); + } + + if (domain_name != NULL) + domain = find_auth_domain(state, domain_name); + + if (domain != NULL) { + sendto_domain(state, domain); + return; + } + + result = NT_STATUS_NO_SUCH_USER; + + done: + set_auth_errors(&state->response, result); + DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n", + state->request.data.auth_crap.domain, + state->request.data.auth_crap.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; +} + + +enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + NET_USER_INFO_3 info3; + struct rpc_pipe_client *netlogon_pipe; + const char *name_user = NULL; + const char *name_domain = NULL; + const char *workstation; + struct winbindd_domain *contact_domain; + int attempts = 0; + BOOL retry; + + DATA_BLOB lm_resp, nt_resp; + + /* This is child-only, so no check for privileged access is needed + anymore */ + + /* Ensure null termination */ + state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]=0; + state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]=0; + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + name_user = state->request.data.auth_crap.user; + + if (*state->request.data.auth_crap.domain) { + name_domain = state->request.data.auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + name_domain = lp_workgroup(); + } else { + DEBUG(5,("no domain specified with username (%s) - failing auth\n", + name_user)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, + name_domain, name_user)); + + if (*state->request.data.auth_crap.workstation) { + workstation = state->request.data.auth_crap.workstation; + } else { + workstation = global_myname(); + } + + if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) + || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { + DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", + state->request.data.auth_crap.lm_resp_len, + state->request.data.auth_crap.nt_resp_len)); + result = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, + state->request.data.auth_crap.lm_resp_len); + nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, + state->request.data.auth_crap.nt_resp_len); + + /* what domain should we contact? */ + + if ( IS_DC ) { + if (!(contact_domain = find_domain_from_name(name_domain))) { + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth_crap.user, name_domain, name_user, name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + } else { + if (is_myname(name_domain)) { + DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + contact_domain = find_our_domain(); + } + + do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client + *cli, TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + NET_USER_INFO_3 *info3); + + ZERO_STRUCT(info3); + retry = False; + + netlogon_pipe = NULL; + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", + nt_errstr(result))); + goto done; + } + + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + + attempts += 1; + + /* We have to try a second time as cm_connect_netlogon + might not yet have noticed that the DC has killed + our connection. */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + retry = True; + continue; + } + + /* if we get access denied, a possible cause was that we had and open + connection to the DC, but someone changed our machine account password + out from underneath us using 'net rpc changetrustpw' */ + + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth: sam_logon returned " + "ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. " + "Killing connections to domain %s\n", + name_domain)); + invalidate_cm_connection(&contact_domain->conn); + retry = True; + } + + } while ( (attempts < 2) && retry ); + + if (NT_STATUS_IS_OK(result)) { + + netsamlogon_cache_store(name_user, &info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + + /* Check if the user is in the right group */ + + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth_crap.require_membership_of_sid))) { + DEBUG(3, ("User %s is not in the required group (%s), so " + "crap authentication is rejected\n", + state->request.data.auth_crap.user, + state->request.data.auth_crap.require_membership_of_sid)); + goto done; + } + + result = append_data(state, &info3, name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + } + +done: + + /* give us a more useful (more correct?) error code */ + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + result = NT_STATUS_NO_LOGON_SERVERS; + } + + if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) { + result = nt_status_squash(result); + } + + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + + /* we might have given a more useful error above */ + if (!*state->response.data.auth.error_string) { + fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + } + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", + name_domain, + name_user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +/* Change a user password */ + +void winbindd_pam_chauthtok(struct winbindd_cli_state *state) +{ + fstring domain, user; + struct winbindd_domain *contact_domain; + + DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid, + state->request.data.chauthtok.user)); + + /* Setup crap */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + + if (!canonicalize_username(state->request.data.chauthtok.user, domain, user)) { + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s" + "(PAM: %d)\n", + state->request.data.auth.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; + } + + contact_domain = find_domain_from_name(domain); + if (!contact_domain) { + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", + state->request.data.chauthtok.user, domain, user, domain)); + request_error(state); + return; + } + + sendto_domain(state, contact_domain); +} + +enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, + struct winbindd_cli_state *state) +{ + char *oldpass; + char *newpass = NULL; + POLICY_HND dom_pol; + struct rpc_pipe_client *cli; + BOOL got_info = False; + SAM_UNK_INFO_1 info; + SAMR_CHANGE_REJECT reject; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring domain, user; + + DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!parse_domain_user(state->request.data.chauthtok.user, domain, user)) { + goto done; + } + + /* Change password */ + + oldpass = state->request.data.chauthtok.oldpass; + newpass = state->request.data.chauthtok.newpass; + + /* Initialize reject reason */ + state->response.data.auth.reject_reason = Undefined; + + /* Get sam handle */ + + result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, + &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); + goto done; + } + + result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject); + + /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { + state->response.data.auth.policy.min_length_password = + info.min_length_password; + state->response.data.auth.policy.password_history = + info.password_history; + state->response.data.auth.policy.password_properties = + info.password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs(&info.expire); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs(&info.min_passwordage); + + state->response.data.auth.reject_reason = + reject.reject_reason; + + got_info = True; + } + + /* only fallback when the chgpasswd3 call is not supported */ + if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) || + (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || + (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { + + DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", + nt_errstr(result))); + + result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass); + + /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. + Map to the same status code as Windows 2003. */ + + if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) { + result = NT_STATUS_PASSWORD_RESTRICTION; + } + } + +done: + + if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { + + /* Update the single sign-on memory creds. */ + result = winbindd_replace_memory_creds(state->request.data.chauthtok.user, + newpass); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result))); + goto process_result; + } + + if (lp_winbind_offline_logon()) { + result = winbindd_update_creds_by_name(contact_domain, + state->mem_ctx, user, + newpass); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); + goto process_result; + } + } + } + + if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { + + NTSTATUS policy_ret; + + policy_ret = fillup_password_policy(contact_domain, state); + + /* failure of this is non critical, it will just provide no + * additional information to the client why the change has + * failed - Guenther */ + + if (!NT_STATUS_IS_OK(policy_ret)) { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret))); + goto process_result; + } + } + +process_result: + + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + domain, + user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +void winbindd_pam_logoff(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, user; + uid_t caller_uid = (uid_t)-1; + uid_t request_uid = state->request.data.logoff.uid; + + DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid, + state->request.data.logoff.user)); + + /* Ensure null termination */ + state->request.data.logoff.user + [sizeof(state->request.data.logoff.user)-1]='\0'; + + state->request.data.logoff.krb5ccname + [sizeof(state->request.data.logoff.krb5ccname)-1]='\0'; + + if (request_uid == (gid_t)-1) { + goto failed; + } + + if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) { + goto failed; + } + + if ((domain = find_auth_domain(state, name_domain)) == NULL) { + goto failed; + } + + if ((sys_getpeereid(state->sock, &caller_uid)) != 0) { + DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", + strerror(errno))); + goto failed; + } + + switch (caller_uid) { + case -1: + goto failed; + case 0: + /* root must be able to logoff any user - gd */ + state->request.data.logoff.uid = request_uid; + break; + default: + if (caller_uid != request_uid) { + DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n")); + goto failed; + } + state->request.data.logoff.uid = caller_uid; + break; + } + + sendto_domain(state, domain); + return; + + failed: + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("Pam Logoff for %s returned %s " + "(PAM: %d)\n", + state->request.data.logoff.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; +} + +enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_NOT_SUPPORTED; + + DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid, + state->request.data.logoff.user)); + + if (!(state->request.flags & WBFLAG_PAM_KRB5)) { + result = NT_STATUS_OK; + goto process_result; + } + + if (state->request.data.logoff.krb5ccname[0] == '\0') { + result = NT_STATUS_OK; + goto process_result; + } + +#ifdef HAVE_KRB5 + + if (state->request.data.logoff.uid < 0) { + DEBUG(0,("winbindd_pam_logoff: invalid uid\n")); + goto process_result; + } + + /* what we need here is to find the corresponding krb5 ccache name *we* + * created for a given username and destroy it */ + + if (!ccache_entry_exists(state->request.data.logoff.user)) { + result = NT_STATUS_OK; + DEBUG(10,("winbindd_pam_logoff: no entry found.\n")); + goto process_result; + } + + if (!ccache_entry_identical(state->request.data.logoff.user, + state->request.data.logoff.uid, + state->request.data.logoff.krb5ccname)) { + DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n")); + goto process_result; + } + + result = remove_ccache(state->request.data.logoff.user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("winbindd_pam_logoff: failed to remove ccache: %s\n", + nt_errstr(result))); + goto process_result; + } + +#else + result = NT_STATUS_NOT_SUPPORTED; +#endif + +process_result: + + winbindd_delete_memory_creds(state->request.data.logoff.user); + + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +/* Change user password with auth crap*/ + +void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain = NULL; + const char *domain_name = NULL; + + /* Ensure null termination */ + state->request.data.chng_pswd_auth_crap.user[ + sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; + state->request.data.chng_pswd_auth_crap.domain[ + sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; + + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", + (unsigned long)state->pid, + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user)); + + if (*state->request.data.chng_pswd_auth_crap.domain != '\0') { + domain_name = state->request.data.chng_pswd_auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + domain_name = lp_workgroup(); + } + + if (domain_name != NULL) + domain = find_domain_from_name(domain_name); + + if (domain != NULL) { + DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: " + "%s\n", (unsigned long)state->pid,domain->name)); + sendto_domain(state, domain); + return; + } + + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n", + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; +} + +enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state) +{ + NTSTATUS result; + DATA_BLOB new_nt_password; + DATA_BLOB old_nt_hash_enc; + DATA_BLOB new_lm_password; + DATA_BLOB old_lm_hash_enc; + fstring domain,user; + POLICY_HND dom_pol; + struct winbindd_domain *contact_domain = domainSt; + struct rpc_pipe_client *cli; + + /* Ensure null termination */ + state->request.data.chng_pswd_auth_crap.user[ + sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; + state->request.data.chng_pswd_auth_crap.domain[ + sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; + *domain = 0; + *user = 0; + + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", + (unsigned long)state->pid, + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user)); + + if (lp_winbind_offline_logon()) { + DEBUG(0,("Refusing password change as winbind offline logons are enabled. ")); + DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n")); + result = NT_STATUS_ACCESS_DENIED; + goto done; + } + + if (*state->request.data.chng_pswd_auth_crap.domain) { + fstrcpy(domain,state->request.data.chng_pswd_auth_crap.domain); + } else { + parse_domain_user(state->request.data.chng_pswd_auth_crap.user, + domain, user); + + if(!*domain) { + DEBUG(3,("no domain specified with username (%s) - " + "failing auth\n", + state->request.data.chng_pswd_auth_crap.user)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + } + + if (!*domain && lp_winbind_use_default_domain()) { + fstrcpy(domain,(char *)lp_workgroup()); + } + + if(!*user) { + fstrcpy(user, state->request.data.chng_pswd_auth_crap.user); + } + + DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", + (unsigned long)state->pid, domain, user)); + + /* Change password */ + new_nt_password = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.new_nt_pswd, + state->request.data.chng_pswd_auth_crap.new_nt_pswd_len); + + old_nt_hash_enc = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.old_nt_hash_enc, + state->request.data.chng_pswd_auth_crap.old_nt_hash_enc_len); + + if(state->request.data.chng_pswd_auth_crap.new_lm_pswd_len > 0) { + new_lm_password = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.new_lm_pswd, + state->request.data.chng_pswd_auth_crap.new_lm_pswd_len); + + old_lm_hash_enc = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.old_lm_hash_enc, + state->request.data.chng_pswd_auth_crap.old_lm_hash_enc_len); + } else { + new_lm_password.length = 0; + old_lm_hash_enc.length = 0; + } + + /* Get sam handle */ + + result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); + goto done; + } + + result = rpccli_samr_chng_pswd_auth_crap( + cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, + new_lm_password, old_lm_hash_enc); + + done: + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); + fstrcpy(state->response.data.auth.error_string, + get_friendly_nt_error_msg(result)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + domain, user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c new file mode 100644 index 0000000000..5c36c0c327 --- /dev/null +++ b/source3/winbindd/winbindd_passdb.c @@ -0,0 +1,467 @@ +/* + Unix SMB/CIFS implementation. + + Winbind rpc backend functions + + Copyright (C) Tim Potter 2000-2001,2003 + Copyright (C) Simo Sorce 2003 + Copyright (C) Volker Lendecke 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* Query display info for a domain. This returns enough information plus a + bit extra to give an overview of domain users for the User Manager + application. */ +static NTSTATUS query_user_list(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info) +{ + /* We don't have users */ + *num_entries = 0; + *info = NULL; + return NT_STATUS_OK; +} + +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + /* We don't have domain groups */ + *num_entries = 0; + *info = NULL; + return NT_STATUS_OK; +} + +/* List all domain groups */ + +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + struct pdb_search *search; + struct samr_displayentry *aliases; + int i; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + search = pdb_search_aliases(&domain->sid); + if (search == NULL) goto done; + + *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases); + if (*num_entries == 0) goto done; + + *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); + if (*info == NULL) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0; i<*num_entries; i++) { + fstrcpy((*info)[i].acct_name, aliases[i].account_name); + fstrcpy((*info)[i].acct_desc, aliases[i].description); + (*info)[i].rid = aliases[i].rid; + } + + result = NT_STATUS_OK; + done: + pdb_search_destroy(search); + return result; +} + +/* convert a single name to a sid in a domain */ +static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd original_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type) +{ + uint32 flags = LOOKUP_NAME_ALL; + + switch ( original_cmd ) { + case WINBINDD_LOOKUPNAME: + /* This call is ok */ + break; + default: + /* Avoid any NSS calls in the lookup_name by default */ + flags |= LOOKUP_NAME_EXPLICIT; + DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n")); + break; + } + + DEBUG(10, ("Finding name %s\n", name)); + + if ( !lookup_name( mem_ctx, name, flags, NULL, NULL, sid, type ) ) { + return NT_STATUS_NONE_MAPPED; + } + + return NT_STATUS_OK; +} + +/* + convert a domain SID to a user or group name +*/ +static NTSTATUS sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type) +{ + const char *dom, *nam; + + DEBUG(10, ("Converting SID %s\n", sid_string_static(sid))); + + /* Paranoia check */ + if (!sid_check_is_in_builtin(sid) && + !sid_check_is_in_our_domain(sid) && + !sid_check_is_in_unix_users(sid) && + !sid_check_is_unix_users(sid) && + !sid_check_is_in_unix_groups(sid) && + !sid_check_is_unix_groups(sid) ) + { + DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with " + "passdb backend\n", sid_string_static(sid))); + return NT_STATUS_NONE_MAPPED; + } + + if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) { + return NT_STATUS_NONE_MAPPED; + } + + *domain_name = talloc_strdup(mem_ctx, dom); + *name = talloc_strdup(mem_ctx, nam); + + return NT_STATUS_OK; +} + +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types) +{ + return NT_STATUS_UNSUCCESSFUL; +} + +/* Lookup user information from a rid or username. */ +static NTSTATUS query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + WINBIND_USERINFO *user_info) +{ + return NT_STATUS_NO_SUCH_USER; +} + +/* Lookup groups a user is a member of. I wish Unix had a call like this! */ +static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *num_groups, DOM_SID **user_gids) +{ + NTSTATUS result; + DOM_SID *groups = NULL; + gid_t *gids = NULL; + size_t ngroups = 0; + struct samu *user; + + if ( (user = samu_new(mem_ctx)) == NULL ) { + return NT_STATUS_NO_MEMORY; + } + + if ( !pdb_getsampwsid( user, user_sid ) ) { + return NT_STATUS_NO_SUCH_USER; + } + + result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups ); + + TALLOC_FREE( user ); + + *num_groups = (uint32)ngroups; + *user_gids = groups; + + return result; +} + +static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID *sids, + uint32 *p_num_aliases, uint32 **rids) +{ + NTSTATUS result; + size_t num_aliases = 0; + + result = pdb_enum_alias_memberships(mem_ctx, &domain->sid, + sids, num_sids, rids, &num_aliases); + + *p_num_aliases = num_aliases; + return result; +} + +/* Lookup group membership given a rid. */ +static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, uint32 *num_names, + DOM_SID **sid_mem, char ***names, + uint32 **name_types) +{ + size_t i, num_members, num_mapped; + uint32 *rids; + NTSTATUS result; + const DOM_SID **sids; + struct lsa_dom_info *lsa_domains; + struct lsa_name_info *lsa_names; + TALLOC_CTX *tmp_ctx; + + if (!sid_check_is_in_our_domain(group_sid)) { + /* There's no groups, only aliases in BUILTIN */ + return NT_STATUS_NO_SUCH_GROUP; + } + + if (!(tmp_ctx = talloc_init("lookup_groupmem"))) { + return NT_STATUS_NO_MEMORY; + } + + result = pdb_enum_group_members(tmp_ctx, group_sid, &rids, + &num_members); + if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(tmp_ctx); + return result; + } + + if (num_members == 0) { + *num_names = 0; + *sid_mem = NULL; + *names = NULL; + *name_types = NULL; + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; + } + + *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members); + *names = TALLOC_ARRAY(mem_ctx, char *, num_members); + *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members); + sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members); + + if (((*sid_mem) == NULL) || ((*names) == NULL) || + ((*name_types) == NULL) || (sids == NULL)) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + /* + * Prepare an array of sid pointers for the lookup_sids calling + * convention. + */ + + for (i=0; isid, rids[i])) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_INTERNAL_ERROR; + } + sids[i] = sid; + } + + result = lookup_sids(tmp_ctx, num_members, sids, 1, + &lsa_domains, &lsa_names); + if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(tmp_ctx); + return result; + } + + num_mapped = 0; + for (i=0; iname))) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + sid_copy(&(*dom_sids)[i], &domains[i]->sid); + } + + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; +} + +/* the rpc backend methods are exposed via this structure */ +struct winbindd_methods passdb_methods = { + False, + query_user_list, + enum_dom_groups, + enum_local_groups, + name_to_sid, + sid_to_name, + rids_to_names, + query_user, + lookup_usergroups, + lookup_useraliases, + lookup_groupmem, + sequence_number, + lockout_policy, + password_policy, + trusted_domains, +}; diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c new file mode 100644 index 0000000000..a1f96a0359 --- /dev/null +++ b/source3/winbindd/winbindd_reconnect.c @@ -0,0 +1,316 @@ +/* + Unix SMB/CIFS implementation. + + Wrapper around winbindd_rpc.c to centralize retry logic. + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +extern struct winbindd_methods msrpc_methods; + +/* List all users */ +static NTSTATUS query_user_list(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info) +{ + NTSTATUS result; + + result = msrpc_methods.query_user_list(domain, mem_ctx, + num_entries, info); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.query_user_list(domain, mem_ctx, + num_entries, info); + return result; +} + +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + NTSTATUS result; + + result = msrpc_methods.enum_dom_groups(domain, mem_ctx, + num_entries, info); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.enum_dom_groups(domain, mem_ctx, + num_entries, info); + return result; +} + +/* List all domain groups */ + +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + NTSTATUS result; + + result = msrpc_methods.enum_local_groups(domain, mem_ctx, + num_entries, info); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.enum_local_groups(domain, mem_ctx, + num_entries, info); + + return result; +} + +/* convert a single name to a sid in a domain */ +static NTSTATUS name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd orig_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type) +{ + NTSTATUS result; + + result = msrpc_methods.name_to_sid(domain, mem_ctx, orig_cmd, + domain_name, name, + sid, type); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.name_to_sid(domain, mem_ctx, orig_cmd, + domain_name, name, + sid, type); + + return result; +} + +/* + convert a domain SID to a user or group name +*/ +static NTSTATUS sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type) +{ + NTSTATUS result; + + result = msrpc_methods.sid_to_name(domain, mem_ctx, sid, + domain_name, name, type); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.sid_to_name(domain, mem_ctx, sid, + domain_name, name, type); + + return result; +} + +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types) +{ + NTSTATUS result; + + result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, + rids, num_rids, + domain_name, names, types); + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, + rids, num_rids, + domain_name, names, + types); + } + + return result; +} + +/* Lookup user information from a rid or username. */ +static NTSTATUS query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + WINBIND_USERINFO *user_info) +{ + NTSTATUS result; + + result = msrpc_methods.query_user(domain, mem_ctx, user_sid, + user_info); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.query_user(domain, mem_ctx, user_sid, + user_info); + + return result; +} + +/* Lookup groups a user is a member of. I wish Unix had a call like this! */ +static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *num_groups, DOM_SID **user_gids) +{ + NTSTATUS result; + + result = msrpc_methods.lookup_usergroups(domain, mem_ctx, + user_sid, num_groups, + user_gids); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.lookup_usergroups(domain, mem_ctx, + user_sid, num_groups, + user_gids); + + return result; +} + +static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID *sids, + uint32 *num_aliases, uint32 **alias_rids) +{ + NTSTATUS result; + + result = msrpc_methods.lookup_useraliases(domain, mem_ctx, + num_sids, sids, + num_aliases, + alias_rids); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.lookup_useraliases(domain, mem_ctx, + num_sids, sids, + num_aliases, + alias_rids); + + return result; +} + +/* Lookup group membership given a rid. */ +static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, uint32 *num_names, + DOM_SID **sid_mem, char ***names, + uint32 **name_types) +{ + NTSTATUS result; + + result = msrpc_methods.lookup_groupmem(domain, mem_ctx, + group_sid, num_names, + sid_mem, names, + name_types); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.lookup_groupmem(domain, mem_ctx, + group_sid, num_names, + sid_mem, names, + name_types); + + return result; +} + +/* find the sequence number for a domain */ +static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) +{ + NTSTATUS result; + + result = msrpc_methods.sequence_number(domain, seq); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.sequence_number(domain, seq); + + return result; +} + +/* find the lockout policy of a domain */ +static NTSTATUS lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_12 *policy) +{ + NTSTATUS result; + + result = msrpc_methods.lockout_policy(domain, mem_ctx, policy); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.lockout_policy(domain, mem_ctx, policy); + + return result; +} + +/* find the password policy of a domain */ +static NTSTATUS password_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_1 *policy) +{ + NTSTATUS result; + + result = msrpc_methods.password_policy(domain, mem_ctx, policy); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.password_policy(domain, mem_ctx, policy); + + return result; +} + +/* get a list of trusted domains */ +static NTSTATUS trusted_domains(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + char ***names, + char ***alt_names, + DOM_SID **dom_sids) +{ + NTSTATUS result; + + result = msrpc_methods.trusted_domains(domain, mem_ctx, + num_domains, names, + alt_names, dom_sids); + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + result = msrpc_methods.trusted_domains(domain, mem_ctx, + num_domains, names, + alt_names, dom_sids); + + return result; +} + +/* the rpc backend methods are exposed via this structure */ +struct winbindd_methods reconnect_methods = { + False, + query_user_list, + enum_dom_groups, + enum_local_groups, + name_to_sid, + sid_to_name, + rids_to_names, + query_user, + lookup_usergroups, + lookup_useraliases, + lookup_groupmem, + sequence_number, + lockout_policy, + password_policy, + trusted_domains, +}; diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c new file mode 100644 index 0000000000..6d2dd35080 --- /dev/null +++ b/source3/winbindd/winbindd_rpc.c @@ -0,0 +1,1111 @@ +/* + Unix SMB/CIFS implementation. + + Winbind rpc backend functions + + Copyright (C) Tim Potter 2000-2001,2003 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + + +/* Query display info for a domain. This returns enough information plus a + bit extra to give an overview of domain users for the User Manager + application. */ +static NTSTATUS query_user_list(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + WINBIND_USERINFO **info) +{ + NTSTATUS result; + POLICY_HND dom_pol; + unsigned int i, start_idx; + uint32 loop_count; + struct rpc_pipe_client *cli; + + DEBUG(3,("rpc: query_user_list\n")); + + *num_entries = 0; + *info = NULL; + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("query_user_list: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + i = start_idx = 0; + loop_count = 0; + + do { + uint32 num_dom_users, j; + uint32 max_entries, max_size; + SAM_DISPINFO_CTR ctr; + SAM_DISPINFO_1 info1; + + ZERO_STRUCT( ctr ); + ZERO_STRUCT( info1 ); + ctr.sam.info1 = &info1; + + /* this next bit is copied from net_user_list_internal() */ + + get_query_dispinfo_params(loop_count, &max_entries, + &max_size); + + result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol, + &start_idx, 1, + &num_dom_users, + max_entries, max_size, + &ctr); + + loop_count++; + + *num_entries += num_dom_users; + + *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO, + *num_entries); + + if (!(*info)) { + return NT_STATUS_NO_MEMORY; + } + + for (j = 0; j < num_dom_users; i++, j++) { + fstring username, fullname; + uint32 rid = ctr.sam.info1->sam[j].rid_user; + + unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1); + unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1); + + (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); + (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); + (*info)[i].homedir = NULL; + (*info)[i].shell = NULL; + sid_compose(&(*info)[i].user_sid, &domain->sid, rid); + + /* For the moment we set the primary group for + every user to be the Domain Users group. + There are serious problems with determining + the actual primary group for large domains. + This should really be made into a 'winbind + force group' smb.conf parameter or + something like that. */ + + sid_compose(&(*info)[i].group_sid, &domain->sid, + DOMAIN_GROUP_RID_USERS); + } + + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); + + return result; +} + +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + POLICY_HND dom_pol; + NTSTATUS status; + uint32 start = 0; + struct rpc_pipe_client *cli; + + *num_entries = 0; + *info = NULL; + + DEBUG(3,("rpc: enum_dom_groups\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(status)) + return status; + + do { + struct acct_info *info2 = NULL; + uint32 count = 0; + TALLOC_CTX *mem_ctx2; + + mem_ctx2 = talloc_init("enum_dom_groups[rpc]"); + + /* start is updated by this call. */ + status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol, + &start, + 0xFFFF, /* buffer size? */ + &info2, &count); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + talloc_destroy(mem_ctx2); + break; + } + + (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, + struct acct_info, + (*num_entries) + count); + if (! *info) { + talloc_destroy(mem_ctx2); + return NT_STATUS_NO_MEMORY; + } + + memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); + (*num_entries) += count; + talloc_destroy(mem_ctx2); + } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); + + return NT_STATUS_OK; +} + +/* List all domain groups */ + +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + POLICY_HND dom_pol; + NTSTATUS result; + struct rpc_pipe_client *cli; + + *num_entries = 0; + *info = NULL; + + DEBUG(3,("rpc: enum_local_groups\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + do { + struct acct_info *info2 = NULL; + uint32 count = 0, start = *num_entries; + TALLOC_CTX *mem_ctx2; + + mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]"); + + result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol, + &start, 0xFFFF, &info2, + &count); + + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) + { + talloc_destroy(mem_ctx2); + return result; + } + + (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, + struct acct_info, + (*num_entries) + count); + if (! *info) { + talloc_destroy(mem_ctx2); + return NT_STATUS_NO_MEMORY; + } + + memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); + (*num_entries) += count; + talloc_destroy(mem_ctx2); + + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); + + return NT_STATUS_OK; +} + +/* convert a single name to a sid in a domain */ +NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd original_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type) +{ + NTSTATUS result; + DOM_SID *sids = NULL; + enum lsa_SidType *types = NULL; + char *full_name = NULL; + struct rpc_pipe_client *cli; + POLICY_HND lsa_policy; + + if (name == NULL || *name=='\0') { + full_name = talloc_asprintf(mem_ctx, "%s", domain_name); + } else if (domain_name == NULL || *domain_name == '\0') { + full_name = talloc_asprintf(mem_ctx, "%s", name); + } else { + full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name); + } + if (!full_name) { + DEBUG(0, ("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(3,("rpc: name_to_sid name=%s\n", full_name)); + + ws_name_return( full_name, WB_REPLACE_CHAR ); + + DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name )); + + result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy); + if (!NT_STATUS_IS_OK(result)) + return result; + + result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, + (const char**) &full_name, NULL, 1, &sids, &types); + + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Return rid and type if lookup successful */ + + sid_copy(sid, &sids[0]); + *type = types[0]; + + return NT_STATUS_OK; +} + +/* + convert a domain SID to a user or group name +*/ +NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type) +{ + char **domains; + char **names; + enum lsa_SidType *types; + NTSTATUS result; + struct rpc_pipe_client *cli; + POLICY_HND lsa_policy; + + DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid), + domain->name )); + + result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n", + nt_errstr(result))); + return result; + } + + + result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy, + 1, sid, &domains, &names, &types); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n", + nt_errstr(result))); + return result; + } + + *type = (enum lsa_SidType)types[0]; + *domain_name = domains[0]; + *name = names[0]; + + ws_name_replace( *name, WB_REPLACE_CHAR ); + + DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); + return NT_STATUS_OK; +} + +NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types) +{ + char **domains; + NTSTATUS result; + struct rpc_pipe_client *cli; + POLICY_HND lsa_policy; + DOM_SID *sids; + size_t i; + char **ret_names; + + DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name )); + + if (num_rids) { + sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids); + if (sids == NULL) { + return NT_STATUS_NO_MEMORY; + } + } else { + sids = NULL; + } + + for (i=0; isid, user_sid, &user_rid)) + return NT_STATUS_UNSUCCESSFUL; + + user_info->homedir = NULL; + user_info->shell = NULL; + user_info->primary_gid = (gid_t)-1; + + /* try netsamlogon cache first */ + + if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + { + + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(user_sid))); + + sid_compose(&user_info->user_sid, &domain->sid, user->user_rid); + sid_compose(&user_info->group_sid, &domain->sid, + user->group_rid); + + user_info->acct_name = unistr2_tdup(mem_ctx, + &user->uni_user_name); + user_info->full_name = unistr2_tdup(mem_ctx, + &user->uni_full_name); + + TALLOC_FREE(user); + + return NT_STATUS_OK; + } + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("query_user: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("query_user: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + /* no cache; hit the wire */ + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Get user handle */ + result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol, + SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, + &user_pol); + + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Get user info */ + result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, + 0x15, &ctr); + + rpccli_samr_close(cli, mem_ctx, &user_pol); + + if (!NT_STATUS_IS_OK(result)) + return result; + + sid_compose(&user_info->user_sid, &domain->sid, user_rid); + sid_compose(&user_info->group_sid, &domain->sid, + ctr->info.id21->group_rid); + user_info->acct_name = unistr2_tdup(mem_ctx, + &ctr->info.id21->uni_user_name); + user_info->full_name = unistr2_tdup(mem_ctx, + &ctr->info.id21->uni_full_name); + user_info->homedir = NULL; + user_info->shell = NULL; + user_info->primary_gid = (gid_t)-1; + + return NT_STATUS_OK; +} + +/* Lookup groups a user is a member of. I wish Unix had a call like this! */ +static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *num_groups, DOM_SID **user_grpsids) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + POLICY_HND dom_pol, user_pol; + uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + DOM_GID *user_groups; + unsigned int i; + fstring sid_string; + uint32 user_rid; + struct rpc_pipe_client *cli; + + DEBUG(3,("rpc: lookup_usergroups sid=%s\n", + sid_to_string(sid_string, user_sid))); + + if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) + return NT_STATUS_UNSUCCESSFUL; + + *num_groups = 0; + *user_grpsids = NULL; + + /* so lets see if we have a cached user_info_3 */ + result = lookup_usergroups_cached(domain, mem_ctx, user_sid, + num_groups, user_grpsids); + + if (NT_STATUS_IS_OK(result)) { + return NT_STATUS_OK; + } + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n", + domain->name)); + + /* Tell the cache manager not to remember this one */ + + return NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + /* no cache; hit the wire */ + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Get user handle */ + result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol, + des_access, user_rid, &user_pol); + + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Query user rids */ + result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, + num_groups, &user_groups); + + rpccli_samr_close(cli, mem_ctx, &user_pol); + + if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) + return result; + + (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups); + if (!(*user_grpsids)) + return NT_STATUS_NO_MEMORY; + + for (i=0;i<(*num_groups);i++) { + sid_copy(&((*user_grpsids)[i]), &domain->sid); + sid_append_rid(&((*user_grpsids)[i]), + user_groups[i].g_rid); + } + + return NT_STATUS_OK; +} + +NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID *sids, + uint32 *num_aliases, uint32 **alias_rids) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + POLICY_HND dom_pol; + DOM_SID2 *query_sids; + uint32 num_query_sids = 0; + int i; + struct rpc_pipe_client *cli; + uint32 *alias_rids_query, num_aliases_query; + int rangesize = MAX_SAM_ENTRIES_W2K; + uint32 total_sids = 0; + int num_queries = 1; + + *num_aliases = 0; + *alias_rids = NULL; + + DEBUG(3,("rpc: lookup_useraliases\n")); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + do { + /* prepare query */ + + num_query_sids = MIN(num_sids - total_sids, rangesize); + + DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", + num_queries, num_query_sids)); + + if (num_query_sids) { + query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids); + if (query_sids == NULL) { + return NT_STATUS_NO_MEMORY; + } + } else { + query_sids = NULL; + } + + for (i=0; iname, + sid_to_string(sid_string, group_sid))); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + + if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) + return NT_STATUS_UNSUCCESSFUL; + + *num_names = 0; + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) + return result; + + result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol, + des_access, group_rid, &group_pol); + + if (!NT_STATUS_IS_OK(result)) + return result; + + /* Step #1: Get a list of user rids that are the members of the + group. */ + + /* This call can take a long time - allow the server to time out. + 35 seconds should do it. */ + + orig_timeout = cli_set_timeout(cli->cli, 35000); + + result = rpccli_samr_query_groupmem(cli, mem_ctx, + &group_pol, num_names, &rid_mem, + name_types); + + /* And restore our original timeout. */ + cli_set_timeout(cli->cli, orig_timeout); + + rpccli_samr_close(cli, mem_ctx, &group_pol); + + if (!NT_STATUS_IS_OK(result)) + return result; + + if (!*num_names) { + names = NULL; + name_types = NULL; + sid_mem = NULL; + return NT_STATUS_OK; + } + + /* Step #2: Convert list of rids into list of usernames. Do this + in bunches of ~1000 to avoid crashing NT4. It looks like there + is a buffer overflow or something like that lurking around + somewhere. */ + +#define MAX_LOOKUP_RIDS 900 + + *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names); + *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names); + *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names); + + for (j=0;j<(*num_names);j++) + sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]); + + if (*num_names>0 && (!*names || !*name_types)) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { + int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); + uint32 tmp_num_names = 0; + char **tmp_names = NULL; + uint32 *tmp_types = NULL; + + /* Lookup a chunk of rids */ + + result = rpccli_samr_lookup_rids(cli, mem_ctx, + &dom_pol, + num_lookup_rids, + &rid_mem[i], + &tmp_num_names, + &tmp_names, &tmp_types); + + /* see if we have a real error (and yes the + STATUS_SOME_UNMAPPED is the one returned from 2k) */ + + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) + return result; + + /* Copy result into array. The talloc system will take + care of freeing the temporary arrays later on. */ + + memcpy(&(*names)[i], tmp_names, sizeof(char *) * + tmp_num_names); + + memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * + tmp_num_names); + + total_names += tmp_num_names; + } + + *num_names = total_names; + + return NT_STATUS_OK; +} + +#ifdef HAVE_LDAP + +#include + +static int get_ldap_seq(const char *server, int port, uint32 *seq) +{ + int ret = -1; + struct timeval to; + const char *attrs[] = {"highestCommittedUSN", NULL}; + LDAPMessage *res = NULL; + char **values = NULL; + LDAP *ldp = NULL; + + *seq = DOM_SEQUENCE_NONE; + + /* + * Parameterised (5) second timeout on open. This is needed as the + * search timeout doesn't seem to apply to doing an open as well. JRA. + */ + + ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout()); + if (ldp == NULL) + return -1; + + /* Timeout if no response within 20 seconds. */ + to.tv_sec = 10; + to.tv_usec = 0; + + if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", + CONST_DISCARD(char **, attrs), 0, &to, &res)) + goto done; + + if (ldap_count_entries(ldp, res) != 1) + goto done; + + values = ldap_get_values(ldp, res, "highestCommittedUSN"); + if (!values || !values[0]) + goto done; + + *seq = atoi(values[0]); + ret = 0; + + done: + + if (values) + ldap_value_free(values); + if (res) + ldap_msgfree(res); + if (ldp) + ldap_unbind(ldp); + return ret; +} + +/********************************************************************** + Get the sequence number for a Windows AD native mode domain using + LDAP queries. +**********************************************************************/ + +static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq) +{ + int ret = -1; + fstring ipstr; + + fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr)); + if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) { + DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence " + "number for Domain (%s) from DC (%s)\n", + domain->name, ipstr)); + } + return ret; +} + +#endif /* HAVE_LDAP */ + +/* find the sequence number for a domain */ +static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) +{ + TALLOC_CTX *mem_ctx; + SAM_UNK_CTR ctr; + NTSTATUS result; + POLICY_HND dom_pol; + BOOL got_seq_num = False; + struct rpc_pipe_client *cli; + + DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("sequence_number: No incoming trust for domain %s\n", + domain->name)); + *seq = time(NULL); + return NT_STATUS_OK; + } + + *seq = DOM_SEQUENCE_NONE; + + if (!(mem_ctx = talloc_init("sequence_number[rpc]"))) + return NT_STATUS_NO_MEMORY; + +#ifdef HAVE_LDAP + if ( domain->active_directory ) + { + int res; + + DEBUG(8,("using get_ldap_seq() to retrieve the " + "sequence number\n")); + + res = get_ldap_sequence_number( domain, seq ); + if (res == 0) + { + result = NT_STATUS_OK; + DEBUG(10,("domain_sequence_number: LDAP for " + "domain %s is %u\n", + domain->name, *seq)); + goto done; + } + + DEBUG(10,("domain_sequence_number: failed to get LDAP " + "sequence number for domain %s\n", + domain->name )); + } +#endif /* HAVE_LDAP */ + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Query domain info */ + + result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr); + + if (NT_STATUS_IS_OK(result)) { + *seq = ctr.info.inf8.seq_num; + got_seq_num = True; + goto seq_num; + } + + /* retry with info-level 2 in case the dc does not support info-level 8 + * (like all older samba2 and samba3 dc's - Guenther */ + + result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr); + + if (NT_STATUS_IS_OK(result)) { + *seq = ctr.info.inf2.seq_num; + got_seq_num = True; + } + + seq_num: + if (got_seq_num) { + DEBUG(10,("domain_sequence_number: for domain %s is %u\n", + domain->name, (unsigned)*seq)); + } else { + DEBUG(10,("domain_sequence_number: failed to get sequence " + "number (%u) for domain %s\n", + (unsigned)*seq, domain->name )); + } + + done: + + talloc_destroy(mem_ctx); + + return result; +} + +/* get a list of trusted domains */ +static NTSTATUS trusted_domains(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + char ***names, + char ***alt_names, + DOM_SID **dom_sids) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 enum_ctx = 0; + struct rpc_pipe_client *cli; + POLICY_HND lsa_policy; + + DEBUG(3,("rpc: trusted_domains\n")); + + *num_domains = 0; + *names = NULL; + *alt_names = NULL; + *dom_sids = NULL; + + result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy); + if (!NT_STATUS_IS_OK(result)) + return result; + + result = STATUS_MORE_ENTRIES; + + while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { + uint32 start_idx, num; + char **tmp_names; + DOM_SID *tmp_sids; + int i; + + result = rpccli_lsa_enum_trust_dom(cli, mem_ctx, + &lsa_policy, &enum_ctx, + &num, &tmp_names, + &tmp_sids); + + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) + break; + + start_idx = *num_domains; + *num_domains += num; + *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names, + char *, *num_domains); + *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids, + DOM_SID, *num_domains); + *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names, + char *, *num_domains); + if ((*names == NULL) || (*dom_sids == NULL) || + (*alt_names == NULL)) + return NT_STATUS_NO_MEMORY; + + for (i=0; iname)); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_NOT_SUPPORTED; + } + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + *lockout_policy = ctr.info.inf12; + + DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", + ctr.info.inf12.bad_attempt_lockout)); + + done: + + return result; +} + +/* find the password policy for a domain */ +NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + SAM_UNK_INFO_1 *password_policy) +{ + NTSTATUS result; + struct rpc_pipe_client *cli; + POLICY_HND dom_pol; + SAM_UNK_CTR ctr; + + DEBUG(10,("rpc: fetch password policy for %s\n", domain->name)); + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_NOT_SUPPORTED; + } + + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + *password_policy = ctr.info.inf1; + + DEBUG(10,("msrpc_password_policy: min_length_password %d\n", + ctr.info.inf1.min_length_password)); + + done: + + return result; +} + + +/* the rpc backend methods are exposed via this structure */ +struct winbindd_methods msrpc_methods = { + False, + query_user_list, + enum_dom_groups, + enum_local_groups, + msrpc_name_to_sid, + msrpc_sid_to_name, + msrpc_rids_to_names, + query_user, + lookup_usergroups, + msrpc_lookup_useraliases, + lookup_groupmem, + sequence_number, + msrpc_lockout_policy, + msrpc_password_policy, + trusted_domains, +}; diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c new file mode 100644 index 0000000000..48e84d35e5 --- /dev/null +++ b/source3/winbindd/winbindd_sid.c @@ -0,0 +1,560 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - sid related functions + + Copyright (C) Tim Potter 2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* Convert a string */ + +static void lookupsid_recv(void *private_data, BOOL success, + const char *dom_name, const char *name, + enum lsa_SidType type); + +void winbindd_lookupsid(struct winbindd_cli_state *state) +{ + DOM_SID sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, + state->request.data.sid)); + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(5, ("%s not a SID\n", state->request.data.sid)); + request_error(state); + return; + } + + winbindd_lookupsid_async(state->mem_ctx, &sid, lookupsid_recv, state); +} + +static void lookupsid_recv(void *private_data, BOOL success, + const char *dom_name, const char *name, + enum lsa_SidType type) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("lookupsid returned an error\n")); + request_error(state); + return; + } + + fstrcpy(state->response.data.name.dom_name, dom_name); + fstrcpy(state->response.data.name.name, name); + state->response.data.name.type = type; + request_ok(state); +} + +/** + * Look up the SID for a qualified name. + **/ + +static void lookupname_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type); + +void winbindd_lookupname(struct winbindd_cli_state *state) +{ + char *name_domain, *name_user; + char *p; + + /* Ensure null termination */ + state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0'; + + /* Ensure null termination */ + state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0'; + + /* cope with the name being a fully qualified name */ + p = strstr(state->request.data.name.name, lp_winbind_separator()); + if (p) { + *p = 0; + name_domain = state->request.data.name.name; + name_user = p+1; + } else { + name_domain = state->request.data.name.dom_name; + name_user = state->request.data.name.name; + } + + DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, + name_domain, lp_winbind_separator(), name_user)); + + winbindd_lookupname_async(state->mem_ctx, name_domain, name_user, + lookupname_recv, WINBINDD_LOOKUPNAME, + state); +} + +static void lookupname_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("lookupname returned an error\n")); + request_error(state); + return; + } + + sid_to_string(state->response.data.sid.sid, sid); + state->response.data.sid.type = type; + request_ok(state); + return; +} + +void winbindd_lookuprids(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + DOM_SID domain_sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid)); + + if (!string_to_sid(&domain_sid, state->request.data.sid)) { + DEBUG(5, ("Could not convert %s to SID\n", + state->request.data.sid)); + request_error(state); + return; + } + + domain = find_lookup_domain_from_sid(&domain_sid); + if (domain == NULL) { + DEBUG(10, ("Could not find domain for name %s\n", + state->request.domain_name)); + request_error(state); + return; + } + + sendto_domain(state, domain); +} + +static struct winbindd_child static_idmap_child; + +void init_idmap_child(void) +{ + setup_domain_child(NULL, &static_idmap_child, "idmap"); +} + +struct winbindd_child *idmap_child(void) +{ + return &static_idmap_child; +} + +/* Convert a sid to a uid. We assume we only have one rid attached to the + sid. */ + +static void sid2uid_recv(void *private_data, BOOL success, uid_t uid) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not convert sid %s\n", + state->request.data.sid)); + request_error(state); + return; + } + + state->response.data.uid = uid; + request_ok(state); +} + +static void sid2uid_lookupsid_recv( void *private_data, BOOL success, + const char *domain_name, + const char *name, + enum lsa_SidType type) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + DOM_SID sid; + + if (!success) { + DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n", + state->request.data.sid)); + request_error(state); + return; + } + + if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) { + DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n", + state->request.data.sid)); + request_error(state); + return; + } + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + /* always use the async interface (may block) */ + winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state); +} + +void winbindd_sid_to_uid(struct winbindd_cli_state *state) +{ + DOM_SID sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, + state->request.data.sid)); + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + /* Validate the SID as a user. Hopefully this will hit cache. + Needed to prevent DoS by exhausting the uid allocation + range from random SIDs. */ + + winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state ); +} + +/* Convert a sid to a gid. We assume we only have one rid attached to the + sid.*/ + +static void sid2gid_recv(void *private_data, BOOL success, gid_t gid) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not convert sid %s\n", + state->request.data.sid)); + request_error(state); + return; + } + + state->response.data.gid = gid; + request_ok(state); +} + +static void sid2gid_lookupsid_recv( void *private_data, BOOL success, + const char *domain_name, + const char *name, + enum lsa_SidType type) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + DOM_SID sid; + + if (!success) { + DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n", + state->request.data.sid)); + request_error(state); + return; + } + + if ( (type!=SID_NAME_DOM_GRP) && + (type!=SID_NAME_ALIAS) && + (type!=SID_NAME_WKN_GRP) ) + { + DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n", + state->request.data.sid)); + request_error(state); + return; + } + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + /* always use the async interface (may block) */ + winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state); +} + +void winbindd_sid_to_gid(struct winbindd_cli_state *state) +{ + DOM_SID sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, + state->request.data.sid)); + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + /* Validate the SID as a group. Hopefully this will hit cache. + Needed to prevent DoS by exhausting the uid allocation + range from random SIDs. */ + + winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state ); +} + +static void sids2xids_recv(void *private_data, BOOL success, void *data, int len) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not convert sids to xids\n")); + request_error(state); + return; + } + + state->response.extra_data.data = data; + state->response.length = sizeof(state->response) + len; + request_ok(state); +} + +void winbindd_sids_to_unixids(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid)); + + winbindd_sids2xids_async(state->mem_ctx, + state->request.extra_data.data, + state->request.extra_len, + sids2xids_recv, state); +} + +static void set_mapping_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not set sid mapping\n")); + request_error(state); + return; + } + + request_ok(state); +} + +void winbindd_set_mapping(struct winbindd_cli_state *state) +{ + struct id_map map; + DOM_SID sid; + + DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid)); + + if ( ! state->privileged) { + DEBUG(0, ("Only root is allowed to set mappings!\n")); + request_error(state); + return; + } + + if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.sid)); + request_error(state); + return; + } + + map.sid = &sid; + map.xid.id = state->request.data.dual_idmapset.id; + map.xid.type = state->request.data.dual_idmapset.type; + + winbindd_set_mapping_async(state->mem_ctx, &map, + set_mapping_recv, state); +} + +static void set_hwm_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not set sid mapping\n")); + request_error(state); + return; + } + + request_ok(state); +} + +void winbindd_set_hwm(struct winbindd_cli_state *state) +{ + struct unixid xid; + + DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid)); + + if ( ! state->privileged) { + DEBUG(0, ("Only root is allowed to set mappings!\n")); + request_error(state); + return; + } + + xid.id = state->request.data.dual_idmapset.id; + xid.type = state->request.data.dual_idmapset.type; + + winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state); +} + +/* Convert a uid to a sid */ + +static void uid2sid_recv(void *private_data, BOOL success, const char *sid) +{ + struct winbindd_cli_state *state = + (struct winbindd_cli_state *)private_data; + + if (success) { + DEBUG(10,("uid2sid: uid %lu has sid %s\n", + (unsigned long)(state->request.data.uid), sid)); + fstrcpy(state->response.data.sid.sid, sid); + state->response.data.sid.type = SID_NAME_USER; + request_ok(state); + return; + } + + request_error(state); + return; +} + +void winbindd_uid_to_sid(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + /* always go via the async interface (may block) */ + winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state); +} + +/* Convert a gid to a sid */ + +static void gid2sid_recv(void *private_data, BOOL success, const char *sid) +{ + struct winbindd_cli_state *state = + (struct winbindd_cli_state *)private_data; + + if (success) { + DEBUG(10,("gid2sid: gid %lu has sid %s\n", + (unsigned long)(state->request.data.gid), sid)); + fstrcpy(state->response.data.sid.sid, sid); + state->response.data.sid.type = SID_NAME_DOM_GRP; + request_ok(state); + return; + } + + request_error(state); + return; +} + + +void winbindd_gid_to_sid(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + /* always use async calls (may block) */ + winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state); +} + +void winbindd_allocate_uid(struct winbindd_cli_state *state) +{ + if ( !state->privileged ) { + DEBUG(2, ("winbindd_allocate_uid: non-privileged access " + "denied!\n")); + request_error(state); + return; + } + + sendto_child(state, idmap_child()); +} + +enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + + if (!NT_STATUS_IS_OK(idmap_allocate_uid(&xid))) { + return WINBINDD_ERROR; + } + state->response.data.uid = xid.id; + return WINBINDD_OK; +} + +void winbindd_allocate_gid(struct winbindd_cli_state *state) +{ + if ( !state->privileged ) { + DEBUG(2, ("winbindd_allocate_gid: non-privileged access " + "denied!\n")); + request_error(state); + return; + } + + sendto_child(state, idmap_child()); +} + +enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + + if (!NT_STATUS_IS_OK(idmap_allocate_gid(&xid))) { + return WINBINDD_ERROR; + } + state->response.data.gid = xid.id; + return WINBINDD_OK; +} + +static void dump_maps_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + DEBUG(5, ("Could not dump maps\n")); + request_error(state); + return; + } + + request_ok(state); +} + +void winbindd_dump_maps(struct winbindd_cli_state *state) +{ + if ( ! state->privileged) { + DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n")); + request_error(state); + return; + } + + DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid)); + + winbindd_dump_maps_async(state->mem_ctx, + state->request.extra_data.data, + state->request.extra_len, + dump_maps_recv, state); +} + diff --git a/source3/winbindd/winbindd_sockinit.c b/source3/winbindd/winbindd_sockinit.c new file mode 100644 index 0000000000..50c53a5045 --- /dev/null +++ b/source3/winbindd/winbindd_sockinit.c @@ -0,0 +1,126 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Tim Potter 2000-2001 + Copyright (C) 2001 by Martin Pool + Copyright (C) James Peach 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#include "smb_launchd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* Open the winbindd socket */ + +static int _winbindd_socket = -1; +static int _winbindd_priv_socket = -1; +static BOOL unlink_winbindd_socket = True; + +static int open_winbindd_socket(void) +{ + if (_winbindd_socket == -1) { + _winbindd_socket = create_pipe_sock( + WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755); + DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", + _winbindd_socket)); + } + + return _winbindd_socket; +} + +static int open_winbindd_priv_socket(void) +{ + if (_winbindd_priv_socket == -1) { + _winbindd_priv_socket = create_pipe_sock( + get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750); + DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n", + _winbindd_priv_socket)); + } + + return _winbindd_priv_socket; +} + +/* Close the winbindd socket */ + +static void close_winbindd_socket(void) +{ + if (_winbindd_socket != -1) { + DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", + _winbindd_socket)); + close(_winbindd_socket); + _winbindd_socket = -1; + } + if (_winbindd_priv_socket != -1) { + DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", + _winbindd_priv_socket)); + close(_winbindd_priv_socket); + _winbindd_priv_socket = -1; + } +} + +BOOL winbindd_init_sockets(int *public_sock, int *priv_sock, + int *idle_timeout_sec) +{ + struct smb_launch_info linfo; + + if (smb_launchd_checkin_names(&linfo, "WinbindPublicPipe", + "WinbindPrivilegedPipe", NULL)) { + if (linfo.num_sockets != 2) { + DEBUG(0, ("invalid launchd configuration, " + "expected 2 sockets but got %d\n", + linfo.num_sockets)); + return False; + } + + *public_sock = _winbindd_socket = linfo.socket_list[0]; + *priv_sock = _winbindd_priv_socket = linfo.socket_list[1]; + *idle_timeout_sec = linfo.idle_timeout_secs; + + unlink_winbindd_socket = False; + + smb_launchd_checkout(&linfo); + return True; + } else { + *public_sock = open_winbindd_socket(); + *priv_sock = open_winbindd_priv_socket(); + *idle_timeout_sec = -1; + + if (*public_sock == -1 || *priv_sock == -1) { + DEBUG(0, ("failed to open winbindd pipes: %s\n", + errno ? strerror(errno) : "unknown error")); + return False; + } + + return True; + } +} + +void winbindd_release_sockets(void) +{ + pstring path; + + close_winbindd_socket(); + + /* Remove socket file */ + if (unlink_winbindd_socket) { + pstr_sprintf(path, "%s/%s", + WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); + unlink(path); + } +} + diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c new file mode 100644 index 0000000000..fac2832f56 --- /dev/null +++ b/source3/winbindd/winbindd_user.c @@ -0,0 +1,875 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - user related functions + + Copyright (C) Tim Potter 2000 + Copyright (C) Jeremy Allison 2001. + Copyright (C) Gerald (Jerry) Carter 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static BOOL fillup_pw_field(const char *lp_template, + const char *username, + const char *domname, + uid_t uid, + gid_t gid, + const char *in, + fstring out) +{ + char *templ; + + if (out == NULL) + return False; + + /* The substitution of %U and %D in the 'template + homedir' is done by talloc_sub_specified() below. + If we have an in string (which means the value has already + been set in the nss_info backend), then use that. + Otherwise use the template value passed in. */ + + if ( in && !strequal(in,"") && lp_security() == SEC_ADS ) { + templ = talloc_sub_specified(NULL, in, + username, domname, + uid, gid); + } else { + templ = talloc_sub_specified(NULL, lp_template, + username, domname, + uid, gid); + } + + if (!templ) + return False; + + safe_strcpy(out, templ, sizeof(fstring) - 1); + TALLOC_FREE(templ); + + return True; + +} +/* Fill a pwent structure with information we have obtained */ + +static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, + DOM_SID *user_sid, DOM_SID *group_sid, + char *full_name, char *homedir, char *shell, + struct winbindd_pw *pw) +{ + fstring output_username; + fstring sid_string; + + if (!pw || !dom_name || !user_name) + return False; + + /* Resolve the uid number */ + + if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) { + DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); + return False; + } + + /* Resolve the gid number */ + + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) { + DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); + return False; + } + + strlower_m(user_name); + + /* Username */ + + fill_domain_username(output_username, dom_name, user_name, True); + + safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); + + /* Full name (gecos) */ + + safe_strcpy(pw->pw_gecos, full_name, sizeof(pw->pw_gecos) - 1); + + /* Home directory and shell */ + + if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, + pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir)) + return False; + + if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, + pw->pw_uid, pw->pw_gid, shell, pw->pw_shell)) + return False; + + /* Password - set to "*" as we can't generate anything useful here. + Authentication can be done using the pam_winbind module. */ + + safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1); + + return True; +} + +/* Wrapper for domain->methods->query_user, only on the parent->child pipe */ + +enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + WINBIND_USERINFO user_info; + NTSTATUS status; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, + state->request.data.sid)); + + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(5, ("%s not a SID\n", state->request.data.sid)); + return WINBINDD_ERROR; + } + + status = domain->methods->query_user(domain, state->mem_ctx, + &sid, &user_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("error getting user info for sid %s\n", + sid_string_static(&sid))); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.user_info.acct_name, user_info.acct_name); + fstrcpy(state->response.data.user_info.full_name, user_info.full_name); + fstrcpy(state->response.data.user_info.homedir, user_info.homedir); + fstrcpy(state->response.data.user_info.shell, user_info.shell); + state->response.data.user_info.primary_gid = user_info.primary_gid; + if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid, + &state->response.data.user_info.group_rid)) { + DEBUG(1, ("Could not extract group rid out of %s\n", + sid_string_static(&sid))); + return WINBINDD_ERROR; + } + + return WINBINDD_OK; +} + +struct getpwsid_state { + struct winbindd_cli_state *state; + struct winbindd_domain *domain; + char *username; + char *fullname; + char *homedir; + char *shell; + DOM_SID user_sid; + uid_t uid; + DOM_SID group_sid; + gid_t gid; +}; + +static void getpwsid_queryuser_recv(void *private_data, BOOL success, + const char *acct_name, + const char *full_name, + const char *homedir, + const char *shell, + uint32 gid, + uint32 group_rid); +static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid); +static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid); + +static void winbindd_getpwsid(struct winbindd_cli_state *state, + const DOM_SID *sid) +{ + struct getpwsid_state *s; + + s = TALLOC_ZERO_P(state->mem_ctx, struct getpwsid_state); + if (s == NULL) { + DEBUG(0, ("talloc failed\n")); + goto error; + } + + s->state = state; + s->domain = find_domain_from_sid_noinit(sid); + if (s->domain == NULL) { + DEBUG(3, ("Could not find domain for sid %s\n", + sid_string_static(sid))); + goto error; + } + + sid_copy(&s->user_sid, sid); + + query_user_async(s->state->mem_ctx, s->domain, sid, + getpwsid_queryuser_recv, s); + return; + + error: + request_error(state); +} + +static void getpwsid_queryuser_recv(void *private_data, BOOL success, + const char *acct_name, + const char *full_name, + const char *homedir, + const char *shell, + uint32 gid, + uint32 group_rid) +{ + fstring username; + struct getpwsid_state *s = + talloc_get_type_abort(private_data, struct getpwsid_state); + + if (!success) { + DEBUG(5, ("Could not query domain %s SID %s\n", s->domain->name, + sid_string_static(&s->user_sid))); + request_error(s->state); + return; + } + + if ( acct_name && *acct_name ) { + fstrcpy( username, acct_name ); + } else { + char *domain_name = NULL; + enum lsa_SidType type; + char *user_name = NULL; + struct winbindd_domain *domain = NULL; + + domain = find_lookup_domain_from_sid(&s->user_sid); + if (domain == NULL) { + DEBUG(5, ("find_lookup_domain_from_sid(%s) failed\n", + sid_string_static(&s->user_sid))); + request_error(s->state); + return; + } + winbindd_lookup_name_by_sid(s->state->mem_ctx, domain, + &s->user_sid, &domain_name, + &user_name, &type ); + + /* If this still fails we ar4e done. Just error out */ + if ( !user_name ) { + DEBUG(5,("Could not obtain a name for SID %s\n", + sid_string_static(&s->user_sid))); + request_error(s->state); + return; + } + + fstrcpy( username, user_name ); + } + + strlower_m( username ); + s->username = talloc_strdup(s->state->mem_ctx, username); + + ws_name_replace( s->username, WB_REPLACE_CHAR ); + + s->fullname = talloc_strdup(s->state->mem_ctx, full_name); + s->homedir = talloc_strdup(s->state->mem_ctx, homedir); + s->shell = talloc_strdup(s->state->mem_ctx, shell); + s->gid = gid; + sid_copy(&s->group_sid, &s->domain->sid); + sid_append_rid(&s->group_sid, group_rid); + + winbindd_sid2uid_async(s->state->mem_ctx, &s->user_sid, + getpwsid_sid2uid_recv, s); +} + +static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid) +{ + struct getpwsid_state *s = + talloc_get_type_abort(private_data, struct getpwsid_state); + + if (!success) { + DEBUG(5, ("Could not query uid for user %s\\%s\n", + s->domain->name, s->username)); + request_error(s->state); + return; + } + + s->uid = uid; + winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid, + getpwsid_sid2gid_recv, s); +} + +static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) +{ + struct getpwsid_state *s = + talloc_get_type_abort(private_data, struct getpwsid_state); + struct winbindd_pw *pw; + fstring output_username; + + /* allow the nss backend to override the primary group ID. + If the gid has already been set, then keep it. + This makes me feel dirty. If the nss backend already + gave us a gid, we don't really care whether the sid2gid() + call worked or not. --jerry */ + + if ( s->gid == (gid_t)-1 ) { + + if (!success) { + DEBUG(5, ("Could not query gid for user %s\\%s\n", + s->domain->name, s->username)); + goto failed; + } + + /* take what the sid2gid() call gave us */ + s->gid = gid; + } + + pw = &s->state->response.data.pw; + pw->pw_uid = s->uid; + pw->pw_gid = s->gid; + fill_domain_username(output_username, s->domain->name, s->username, True); + safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); + safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1); + + if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, + pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) { + DEBUG(5, ("Could not compose homedir\n")); + goto failed; + } + + if (!fillup_pw_field(lp_template_shell(), s->username, s->domain->name, + pw->pw_uid, pw->pw_gid, s->shell, pw->pw_shell)) { + DEBUG(5, ("Could not compose shell\n")); + goto failed; + } + + /* Password - set to "*" as we can't generate anything useful here. + Authentication can be done using the pam_winbind module. */ + + safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1); + + request_ok(s->state); + return; + + failed: + request_error(s->state); +} + +/* Return a password structure from a username. */ + +static void getpwnam_name2sid_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type); + +void winbindd_getpwnam(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring domname, username; + + /* Ensure null termination */ + state->request.data.username[sizeof(state->request.data.username)-1]='\0'; + + DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid, + state->request.data.username)); + + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); + + if (!parse_domain_user(state->request.data.username, domname, + username)) { + DEBUG(5, ("Could not parse domain user: %s\n", + state->request.data.username)); + request_error(state); + return; + } + + /* Get info for the domain */ + + domain = find_domain_from_name(domname); + + if (domain == NULL) { + DEBUG(7, ("could not find domain entry for domain %s. " + "Using primary domain\n", domname)); + if ( (domain = find_our_domain()) == NULL ) { + DEBUG(0,("Cannot find my primary domain structure!\n")); + request_error(state); + return; + } + } + + if ( strequal(domname, lp_workgroup()) && lp_winbind_trusted_domains_only() ) { + DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", + domname, username)); + request_error(state); + return; + } + + /* Get rid and name type from name. The following costs 1 packet */ + + winbindd_lookupname_async(state->mem_ctx, domname, username, + getpwnam_name2sid_recv, WINBINDD_GETPWNAM, + state); +} + +static void getpwnam_name2sid_recv(void *private_data, BOOL success, + const DOM_SID *sid, enum lsa_SidType type) +{ + struct winbindd_cli_state *state = + (struct winbindd_cli_state *)private_data; + fstring domname, username; + + if (!success) { + DEBUG(5, ("Could not lookup name for user %s\n", + state->request.data.username)); + request_error(state); + return; + } + + if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) { + DEBUG(5, ("%s is not a user\n", state->request.data.username)); + request_error(state); + return; + } + + if ( parse_domain_user(state->request.data.username, domname, username) ) { + check_domain_trusted( domname, sid ); + } + + + + winbindd_getpwsid(state, sid); +} + +static void getpwuid_recv(void *private_data, BOOL success, const char *sid) +{ + struct winbindd_cli_state *state = + (struct winbindd_cli_state *)private_data; + DOM_SID user_sid; + + if (!success) { + DEBUG(10,("uid2sid_recv: uid [%lu] to sid mapping failed\n.", + (unsigned long)(state->request.data.uid))); + request_error(state); + return; + } + + DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n", + (unsigned long)(state->request.data.uid), sid)); + + string_to_sid(&user_sid, sid); + winbindd_getpwsid(state, &user_sid); +} + +/* Return a password structure given a uid number */ +void winbindd_getpwuid(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: getpwuid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + /* always query idmap via the async interface */ + /* if this turns to be too slow we will add here a direct query to the cache */ + winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, getpwuid_recv, state); +} + +/* + * set/get/endpwent functions + */ + +/* Rewind file pointer for ntdom passwd database */ + +static BOOL winbindd_setpwent_internal(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + + DEBUG(3, ("[%5lu]: setpwent\n", (unsigned long)state->pid)); + + /* Check user has enabled this */ + + if (!lp_winbind_enum_users()) { + return False; + } + + /* Free old static data if it exists */ + + if (state->getpwent_state != NULL) { + free_getent_state(state->getpwent_state); + state->getpwent_state = NULL; + } + +#if 0 /* JERRY */ + /* add any local users we have */ + + if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL ) + return False; + + ZERO_STRUCTP(domain_state); + + /* Add to list of open domains */ + + DLIST_ADD(state->getpwent_state, domain_state); +#endif + + /* Create sam pipes for each domain we know about */ + + for(domain = domain_list(); domain != NULL; domain = domain->next) { + struct getent_state *domain_state; + + + /* don't add our domaina if we are a PDC or if we + are a member of a Samba domain */ + + if ( (IS_DC || lp_winbind_trusted_domains_only()) + && strequal(domain->name, lp_workgroup()) ) + { + continue; + } + + /* Create a state record for this domain */ + + if ((domain_state = SMB_MALLOC_P(struct getent_state)) == NULL) { + DEBUG(0, ("malloc failed\n")); + return False; + } + + ZERO_STRUCTP(domain_state); + + fstrcpy(domain_state->domain_name, domain->name); + + /* Add to list of open domains */ + + DLIST_ADD(state->getpwent_state, domain_state); + } + + state->getpwent_initialized = True; + return True; +} + +void winbindd_setpwent(struct winbindd_cli_state *state) +{ + if (winbindd_setpwent_internal(state)) { + request_ok(state); + } else { + request_error(state); + } +} + +/* Close file pointer to ntdom passwd database */ + +void winbindd_endpwent(struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: endpwent\n", (unsigned long)state->pid)); + + free_getent_state(state->getpwent_state); + state->getpwent_initialized = False; + state->getpwent_state = NULL; + request_ok(state); +} + +/* Get partial list of domain users for a domain. We fill in the sam_entries, + and num_sam_entries fields with domain user information. The dispinfo_ndx + field is incremented to the index of the next user to fetch. Return True if + some users were returned, False otherwise. */ + +static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + uint32 num_entries; + WINBIND_USERINFO *info; + struct getpwent_user *name_list = NULL; + struct winbindd_domain *domain; + struct winbindd_methods *methods; + unsigned int i; + + if (ent->num_sam_entries) + return False; + + if (!(domain = find_domain_from_name(ent->domain_name))) { + DEBUG(3, ("no such domain %s in get_sam_user_entries\n", + ent->domain_name)); + return False; + } + + methods = domain->methods; + + /* Free any existing user info */ + + SAFE_FREE(ent->sam_entries); + ent->num_sam_entries = 0; + + /* Call query_user_list to get a list of usernames and user rids */ + + num_entries = 0; + + status = methods->query_user_list(domain, mem_ctx, &num_entries, + &info); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("get_sam_user_entries: query_user_list failed with %s\n", + nt_errstr(status) )); + return False; + } + + if (num_entries) { + name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries); + + if (!name_list) { + DEBUG(0,("get_sam_user_entries realloc failed.\n")); + return False; + } + } + + for (i = 0; i < num_entries; i++) { + /* Store account name and gecos */ + if (!info[i].acct_name) { + fstrcpy(name_list[ent->num_sam_entries + i].name, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].name, + info[i].acct_name); + } + if (!info[i].full_name) { + fstrcpy(name_list[ent->num_sam_entries + i].gecos, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].gecos, + info[i].full_name); + } + if (!info[i].homedir) { + fstrcpy(name_list[ent->num_sam_entries + i].homedir, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].homedir, + info[i].homedir); + } + if (!info[i].shell) { + fstrcpy(name_list[ent->num_sam_entries + i].shell, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].shell, + info[i].shell); + } + + + /* User and group ids */ + sid_copy(&name_list[ent->num_sam_entries+i].user_sid, + &info[i].user_sid); + sid_copy(&name_list[ent->num_sam_entries+i].group_sid, + &info[i].group_sid); + } + + ent->num_sam_entries += num_entries; + + /* Fill in remaining fields */ + + ent->sam_entries = name_list; + ent->sam_entry_index = 0; + return ent->num_sam_entries > 0; +} + +/* Fetch next passwd entry from ntdom database */ + +#define MAX_GETPWENT_USERS 500 + +void winbindd_getpwent(struct winbindd_cli_state *state) +{ + struct getent_state *ent; + struct winbindd_pw *user_list; + int num_users, user_list_ndx; + + DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)state->pid)); + + /* Check user has enabled this */ + + if (!lp_winbind_enum_users()) { + request_error(state); + return; + } + + /* Allocate space for returning a chunk of users */ + + num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries); + + if (num_users == 0) { + request_error(state); + return; + } + + if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) { + request_error(state); + return; + } + + memset(state->response.extra_data.data, 0, num_users * + sizeof(struct winbindd_pw)); + + user_list = (struct winbindd_pw *)state->response.extra_data.data; + + if (!state->getpwent_initialized) + winbindd_setpwent_internal(state); + + if (!(ent = state->getpwent_state)) { + request_error(state); + return; + } + + /* Start sending back users */ + + for (user_list_ndx = 0; user_list_ndx < num_users; ) { + struct getpwent_user *name_list = NULL; + uint32 result; + + /* Do we need to fetch another chunk of users? */ + + if (ent->num_sam_entries == ent->sam_entry_index) { + + while(ent && + !get_sam_user_entries(ent, state->mem_ctx)) { + struct getent_state *next_ent; + + /* Free state information for this domain */ + + SAFE_FREE(ent->sam_entries); + + next_ent = ent->next; + DLIST_REMOVE(state->getpwent_state, ent); + + SAFE_FREE(ent); + ent = next_ent; + } + + /* No more domains */ + + if (!ent) + break; + } + + name_list = (struct getpwent_user *)ent->sam_entries; + + /* Lookup user info */ + + result = winbindd_fill_pwent( + ent->domain_name, + name_list[ent->sam_entry_index].name, + &name_list[ent->sam_entry_index].user_sid, + &name_list[ent->sam_entry_index].group_sid, + name_list[ent->sam_entry_index].gecos, + name_list[ent->sam_entry_index].homedir, + name_list[ent->sam_entry_index].shell, + &user_list[user_list_ndx]); + + /* Add user to return list */ + + if (result) { + + user_list_ndx++; + state->response.data.num_entries++; + state->response.length += + sizeof(struct winbindd_pw); + + } else + DEBUG(1, ("could not lookup domain user %s\n", + name_list[ent->sam_entry_index].name)); + + ent->sam_entry_index++; + + } + + /* Out of domains */ + + if (user_list_ndx > 0) + request_ok(state); + else + request_error(state); +} + +/* List domain users without mapping to unix ids */ + +void winbindd_list_users(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + WINBIND_USERINFO *info; + const char *which_domain; + uint32 num_entries = 0, total_entries = 0; + char *extra_data = NULL; + int extra_data_len = 0; + enum winbindd_result rv = WINBINDD_ERROR; + + DEBUG(3, ("[%5lu]: list users\n", (unsigned long)state->pid)); + + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + + /* Enumerate over trusted domains */ + + for (domain = domain_list(); domain; domain = domain->next) { + NTSTATUS status; + struct winbindd_methods *methods; + unsigned int i; + + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + + methods = domain->methods; + + /* Query display info */ + status = methods->query_user_list(domain, state->mem_ctx, + &num_entries, &info); + + if (!NT_STATUS_IS_OK(status)) { + continue; + } + + if (num_entries == 0) + continue; + + /* Allocate some memory for extra data */ + total_entries += num_entries; + + extra_data = (char *)SMB_REALLOC( + extra_data, sizeof(fstring) * total_entries); + + if (!extra_data) { + DEBUG(0,("failed to enlarge buffer!\n")); + goto done; + } + + /* Pack user list into extra data fields */ + + for (i = 0; i < num_entries; i++) { + fstring acct_name, name; + + if (!info[i].acct_name) { + fstrcpy(acct_name, ""); + } else { + fstrcpy(acct_name, info[i].acct_name); + } + + fill_domain_username(name, domain->name, acct_name, True); + + /* Append to extra data */ + memcpy(&extra_data[extra_data_len], name, + strlen(name)); + extra_data_len += strlen(name); + extra_data[extra_data_len++] = ','; + } + } + + /* Assign extra_data fields in response structure */ + + if (extra_data) { + extra_data[extra_data_len - 1] = '\0'; + state->response.extra_data.data = extra_data; + state->response.length += extra_data_len; + } + + /* No domains responded but that's still OK so don't return an + error. */ + + rv = WINBINDD_OK; + + done: + + if (rv == WINBINDD_OK) + request_ok(state); + else + request_error(state); +} diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c new file mode 100644 index 0000000000..37d29e1765 --- /dev/null +++ b/source3/winbindd/winbindd_util.c @@ -0,0 +1,1460 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000-2001 + Copyright (C) 2001 by Martin Pool + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +extern struct winbindd_methods cache_methods; +extern struct winbindd_methods passdb_methods; + +/** + * @file winbindd_util.c + * + * Winbind daemon for NT domain authentication nss module. + **/ + +/* The list of trusted domains. Note that the list can be deleted and + recreated using the init_domain_list() function so pointers to + individual winbindd_domain structures cannot be made. Keep a copy of + the domain name instead. */ + +static struct winbindd_domain *_domain_list; + +/** + When was the last scan of trusted domains done? + + 0 == not ever +*/ + +static time_t last_trustdom_scan; + +struct winbindd_domain *domain_list(void) +{ + /* Initialise list */ + + if ((!_domain_list) && (!init_domain_list())) { + smb_panic("Init_domain_list failed"); + } + + return _domain_list; +} + +/* Free all entries in the trusted domain list */ + +void free_domain_list(void) +{ + struct winbindd_domain *domain = _domain_list; + + while(domain) { + struct winbindd_domain *next = domain->next; + + DLIST_REMOVE(_domain_list, domain); + SAFE_FREE(domain); + domain = next; + } +} + +static BOOL is_internal_domain(const DOM_SID *sid) +{ + if (sid == NULL) + return False; + + if ( IS_DC ) + return sid_check_is_builtin(sid); + + return (sid_check_is_domain(sid) || sid_check_is_builtin(sid)); +} + +static BOOL is_in_internal_domain(const DOM_SID *sid) +{ + if (sid == NULL) + return False; + + if ( IS_DC ) + return sid_check_is_in_builtin(sid); + + return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid)); +} + + +/* Add a trusted domain to our list of domains */ +static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, + struct winbindd_methods *methods, + const DOM_SID *sid) +{ + struct winbindd_domain *domain; + const char *alternative_name = NULL; + + /* ignore alt_name if we are not in an AD domain */ + + if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) { + alternative_name = alt_name; + } + + /* We can't call domain_list() as this function is called from + init_domain_list() and we'll get stuck in a loop. */ + for (domain = _domain_list; domain; domain = domain->next) { + if (strequal(domain_name, domain->name) || + strequal(domain_name, domain->alt_name)) + { + break; + } + + if (alternative_name && *alternative_name) + { + if (strequal(alternative_name, domain->name) || + strequal(alternative_name, domain->alt_name)) + { + break; + } + } + + if (sid) + { + if (is_null_sid(sid)) { + continue; + } + + if (sid_equal(sid, &domain->sid)) { + break; + } + } + } + + /* See if we found a match. Check if we need to update the + SID. */ + + if ( domain && sid) { + if ( sid_equal( &domain->sid, &global_sid_NULL ) ) + sid_copy( &domain->sid, sid ); + + return domain; + } + + /* Create new domain entry */ + + if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL) + return NULL; + + /* Fill in fields */ + + ZERO_STRUCTP(domain); + + /* prioritise the short name */ + if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) { + fstrcpy(domain->name, alternative_name); + fstrcpy(domain->alt_name, domain_name); + } else { + fstrcpy(domain->name, domain_name); + if (alternative_name) { + fstrcpy(domain->alt_name, alternative_name); + } + } + + domain->methods = methods; + domain->backend = NULL; + domain->internal = is_internal_domain(sid); + domain->sequence_number = DOM_SEQUENCE_NONE; + domain->last_seq_check = 0; + domain->initialized = False; + domain->online = is_internal_domain(sid); + domain->check_online_timeout = 0; + if (sid) { + sid_copy(&domain->sid, sid); + } + + /* Link to domain list */ + DLIST_ADD(_domain_list, domain); + + wcache_tdc_add_domain( domain ); + + DEBUG(2,("Added domain %s %s %s\n", + domain->name, domain->alt_name, + &domain->sid?sid_string_static(&domain->sid):"")); + + return domain; +} + +/******************************************************************** + rescan our domains looking for new trusted domains +********************************************************************/ + +struct trustdom_state { + TALLOC_CTX *mem_ctx; + BOOL primary; + BOOL forest_root; + struct winbindd_response *response; +}; + +static void trustdom_recv(void *private_data, BOOL success); +static void rescan_forest_root_trusts( void ); +static void rescan_forest_trusts( void ); + +static void add_trusted_domains( struct winbindd_domain *domain ) +{ + TALLOC_CTX *mem_ctx; + struct winbindd_request *request; + struct winbindd_response *response; + uint32 fr_flags = (DS_DOMAIN_TREE_ROOT|DS_DOMAIN_IN_FOREST); + + struct trustdom_state *state; + + mem_ctx = talloc_init("add_trusted_domains"); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_init failed\n")); + return; + } + + request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request); + response = TALLOC_P(mem_ctx, struct winbindd_response); + state = TALLOC_P(mem_ctx, struct trustdom_state); + + if ((request == NULL) || (response == NULL) || (state == NULL)) { + DEBUG(0, ("talloc failed\n")); + talloc_destroy(mem_ctx); + return; + } + + state->mem_ctx = mem_ctx; + state->response = response; + + /* Flags used to know how to continue the forest trust search */ + + state->primary = domain->primary; + state->forest_root = ((domain->domain_flags & fr_flags) == fr_flags ); + + request->length = sizeof(*request); + request->cmd = WINBINDD_LIST_TRUSTDOM; + + async_domain_request(mem_ctx, domain, request, response, + trustdom_recv, state); +} + +static void trustdom_recv(void *private_data, BOOL success) +{ + struct trustdom_state *state = + talloc_get_type_abort(private_data, struct trustdom_state); + struct winbindd_response *response = state->response; + char *p; + + if ((!success) || (response->result != WINBINDD_OK)) { + DEBUG(1, ("Could not receive trustdoms\n")); + talloc_destroy(state->mem_ctx); + return; + } + + p = (char *)response->extra_data.data; + + while ((p != NULL) && (*p != '\0')) { + char *q, *sidstr, *alt_name; + DOM_SID sid; + struct winbindd_domain *domain; + char *alternate_name = NULL; + + alt_name = strchr(p, '\\'); + if (alt_name == NULL) { + DEBUG(0, ("Got invalid trustdom response\n")); + break; + } + + *alt_name = '\0'; + alt_name += 1; + + sidstr = strchr(alt_name, '\\'); + if (sidstr == NULL) { + DEBUG(0, ("Got invalid trustdom response\n")); + break; + } + + *sidstr = '\0'; + sidstr += 1; + + q = strchr(sidstr, '\n'); + if (q != NULL) + *q = '\0'; + + if (!string_to_sid(&sid, sidstr)) { + /* Allow NULL sid for sibling domains */ + if ( strcmp(sidstr,"S-0-0") == 0) { + sid_copy( &sid, &global_sid_NULL); + } else { + DEBUG(0, ("Got invalid trustdom response\n")); + break; + } + } + + /* use the real alt_name if we have one, else pass in NULL */ + + if ( !strequal( alt_name, "(null)" ) ) + alternate_name = alt_name; + + /* If we have an existing domain structure, calling + add_trusted_domain() will update the SID if + necessary. This is important because we need the + SID for sibling domains */ + + if ( find_domain_from_name_noinit(p) != NULL ) { + domain = add_trusted_domain(p, alternate_name, + &cache_methods, + &sid); + } else { + domain = add_trusted_domain(p, alternate_name, + &cache_methods, + &sid); + if (domain) { + setup_domain_child(domain, &domain->child, NULL); + } + } + p=q; + if (p != NULL) + p += 1; + } + + SAFE_FREE(response->extra_data.data); + + /* + Cases to consider when scanning trusts: + (a) we are calling from a child domain (primary && !forest_root) + (b) we are calling from the root of the forest (primary && forest_root) + (c) we are calling from a trusted forest domain (!primary + && !forest_root) + */ + + if ( state->primary ) { + /* If this is our primary domain and we are not the in the + forest root, we have to scan the root trusts first */ + + if ( !state->forest_root ) + rescan_forest_root_trusts(); + else + rescan_forest_trusts(); + + } else if ( state->forest_root ) { + /* Once we have done root forest trust search, we can + go on to search thing trusted forests */ + + rescan_forest_trusts(); + } + + talloc_destroy(state->mem_ctx); + + return; +} + +/******************************************************************** + Scan the trusts of our forest root +********************************************************************/ + +static void rescan_forest_root_trusts( void ) +{ + struct winbindd_tdc_domain *dom_list = NULL; + size_t num_trusts = 0; + int i; + + /* The only transitive trusts supported by Windows 2003 AD are + (a) Parent-Child, (b) Tree-Root, and (c) Forest. The + first two are handled in forest and listed by + DsEnumerateDomainTrusts(). Forest trusts are not so we + have to do that ourselves. */ + + if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) ) + return; + + for ( i=0; iname, d->alt_name )); + + d->domain_flags = dom_list[i].trust_flags; + d->domain_type = dom_list[i].trust_type; + d->domain_trust_attribs = dom_list[i].trust_attribs; + + add_trusted_domains( d ); + + break; + } + + TALLOC_FREE( dom_list ); + + return; +} + +/******************************************************************** + scan the transitive forest trists (not our own) +********************************************************************/ + + +static void rescan_forest_trusts( void ) +{ + struct winbindd_domain *d = NULL; + struct winbindd_tdc_domain *dom_list = NULL; + size_t num_trusts = 0; + int i; + + /* The only transitive trusts supported by Windows 2003 AD are + (a) Parent-Child, (b) Tree-Root, and (c) Forest. The + first two are handled in forest and listed by + DsEnumerateDomainTrusts(). Forest trusts are not so we + have to do that ourselves. */ + + if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) ) + return; + + for ( i=0; iinternal || d->primary ) ) + continue; + + if ( (flags & DS_DOMAIN_DIRECT_INBOUND) && + (type == DS_DOMAIN_TRUST_TYPE_UPLEVEL) && + (attribs == DS_DOMAIN_TRUST_ATTRIB_FOREST_TRANSITIVE) ) + { + /* add the trusted domain if we don't know + about it */ + + if ( !d ) { + d = add_trusted_domain( dom_list[i].domain_name, + dom_list[i].dns_name, + &cache_methods, + &dom_list[i].sid ); + } + + DEBUG(10,("Following trust path for domain %s (%s)\n", + d->name, d->alt_name )); + add_trusted_domains( d ); + } + } + + TALLOC_FREE( dom_list ); + + return; +} + +/********************************************************************* + The process of updating the trusted domain list is a three step + async process: + (a) ask our domain + (b) ask the root domain in our forest + (c) ask the a DC in any Win2003 trusted forests +*********************************************************************/ + +void rescan_trusted_domains( void ) +{ + time_t now = time(NULL); + + /* see if the time has come... */ + + if ((now >= last_trustdom_scan) && + ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) + return; + + /* clear the TRUSTDOM cache first */ + + wcache_tdc_clear(); + + /* this will only add new domains we didn't already know about + in the domain_list()*/ + + add_trusted_domains( find_our_domain() ); + + last_trustdom_scan = now; + + return; +} + +struct init_child_state { + TALLOC_CTX *mem_ctx; + struct winbindd_domain *domain; + struct winbindd_request *request; + struct winbindd_response *response; + void (*continuation)(void *private_data, BOOL success); + void *private_data; +}; + +static void init_child_recv(void *private_data, BOOL success); +static void init_child_getdc_recv(void *private_data, BOOL success); + +enum winbindd_result init_child_connection(struct winbindd_domain *domain, + void (*continuation)(void *private_data, + BOOL success), + void *private_data) +{ + TALLOC_CTX *mem_ctx; + struct winbindd_request *request; + struct winbindd_response *response; + struct init_child_state *state; + struct winbindd_domain *request_domain; + + mem_ctx = talloc_init("init_child_connection"); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_init failed\n")); + return WINBINDD_ERROR; + } + + request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request); + response = TALLOC_P(mem_ctx, struct winbindd_response); + state = TALLOC_P(mem_ctx, struct init_child_state); + + if ((request == NULL) || (response == NULL) || (state == NULL)) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(mem_ctx); + continuation(private_data, False); + return WINBINDD_ERROR; + } + + request->length = sizeof(*request); + + state->mem_ctx = mem_ctx; + state->domain = domain; + state->request = request; + state->response = response; + state->continuation = continuation; + state->private_data = private_data; + + if (IS_DC || domain->primary || domain->internal ) { + /* The primary domain has to find the DC name itself */ + request->cmd = WINBINDD_INIT_CONNECTION; + fstrcpy(request->domain_name, domain->name); + request->data.init_conn.is_primary = domain->internal ? False : True; + fstrcpy(request->data.init_conn.dcname, ""); + async_request(mem_ctx, &domain->child, request, response, + init_child_recv, state); + return WINBINDD_PENDING; + } + + /* This is *not* the primary domain, let's ask our DC about a DC + * name */ + + request->cmd = WINBINDD_GETDCNAME; + fstrcpy(request->domain_name, domain->name); + + request_domain = find_our_domain(); + async_domain_request(mem_ctx, request_domain, request, response, + init_child_getdc_recv, state); + return WINBINDD_PENDING; +} + +static void init_child_getdc_recv(void *private_data, BOOL success) +{ + struct init_child_state *state = + talloc_get_type_abort(private_data, struct init_child_state); + const char *dcname = ""; + + DEBUG(10, ("Received getdcname response\n")); + + if (success && (state->response->result == WINBINDD_OK)) { + dcname = state->response->data.dc_name; + } + + state->request->cmd = WINBINDD_INIT_CONNECTION; + fstrcpy(state->request->domain_name, state->domain->name); + state->request->data.init_conn.is_primary = False; + fstrcpy(state->request->data.init_conn.dcname, dcname); + + async_request(state->mem_ctx, &state->domain->child, + state->request, state->response, + init_child_recv, state); +} + +static void init_child_recv(void *private_data, BOOL success) +{ + struct init_child_state *state = + talloc_get_type_abort(private_data, struct init_child_state); + + DEBUG(5, ("Received child initialization response for domain %s\n", + state->domain->name)); + + if ((!success) || (state->response->result != WINBINDD_OK)) { + DEBUG(3, ("Could not init child\n")); + state->continuation(state->private_data, False); + talloc_destroy(state->mem_ctx); + return; + } + + fstrcpy(state->domain->name, + state->response->data.domain_info.name); + fstrcpy(state->domain->alt_name, + state->response->data.domain_info.alt_name); + string_to_sid(&state->domain->sid, + state->response->data.domain_info.sid); + state->domain->native_mode = + state->response->data.domain_info.native_mode; + state->domain->active_directory = + state->response->data.domain_info.active_directory; + state->domain->sequence_number = + state->response->data.domain_info.sequence_number; + + init_dc_connection(state->domain); + + if (state->continuation != NULL) + state->continuation(state->private_data, True); + talloc_destroy(state->mem_ctx); +} + +enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + /* Ensure null termination */ + state->request.domain_name + [sizeof(state->request.domain_name)-1]='\0'; + state->request.data.init_conn.dcname + [sizeof(state->request.data.init_conn.dcname)-1]='\0'; + + if (strlen(state->request.data.init_conn.dcname) > 0) { + fstrcpy(domain->dcname, state->request.data.init_conn.dcname); + } + + init_dc_connection(domain); + + if (!domain->initialized) { + /* If we return error here we can't do any cached authentication, + but we may be in disconnected mode and can't initialize correctly. + Do what the previous code did and just return without initialization, + once we go online we'll re-initialize. + */ + DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization " + "online = %d\n", domain->name, (int)domain->online )); + } + + fstrcpy(state->response.data.domain_info.name, domain->name); + fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); + fstrcpy(state->response.data.domain_info.sid, + sid_string_static(&domain->sid)); + + state->response.data.domain_info.native_mode + = domain->native_mode; + state->response.data.domain_info.active_directory + = domain->active_directory; + state->response.data.domain_info.primary + = domain->primary; + state->response.data.domain_info.sequence_number = + domain->sequence_number; + + return WINBINDD_OK; +} + +/* Look up global info for the winbind daemon */ +BOOL init_domain_list(void) +{ + struct winbindd_domain *domain; + int role = lp_server_role(); + + /* Free existing list */ + free_domain_list(); + + /* Add ourselves as the first entry. */ + + if ( role == ROLE_DOMAIN_MEMBER ) { + DOM_SID our_sid; + + if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) { + DEBUG(0, ("Could not fetch our SID - did we join?\n")); + return False; + } + + domain = add_trusted_domain( lp_workgroup(), lp_realm(), + &cache_methods, &our_sid); + if (domain) { + domain->primary = True; + setup_domain_child(domain, &domain->child, NULL); + + /* Even in the parent winbindd we'll need to + talk to the DC, so try and see if we can + contact it. Theoretically this isn't neccessary + as the init_dc_connection() in init_child_recv() + will do this, but we can start detecting the DC + early here. */ + set_domain_online_request(domain); + } + } + + /* Local SAM */ + + domain = add_trusted_domain(get_global_sam_name(), NULL, + &passdb_methods, get_global_sam_sid()); + if (domain) { + if ( role != ROLE_DOMAIN_MEMBER ) { + domain->primary = True; + } + setup_domain_child(domain, &domain->child, NULL); + } + + /* BUILTIN domain */ + + domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, + &global_sid_Builtin); + if (domain) { + setup_domain_child(domain, &domain->child, NULL); + } + + return True; +} + +void check_domain_trusted( const char *name, const DOM_SID *user_sid ) +{ + struct winbindd_domain *domain; + DOM_SID dom_sid; + uint32 rid; + + domain = find_domain_from_name_noinit( name ); + if ( domain ) + return; + + sid_copy( &dom_sid, user_sid ); + if ( !sid_split_rid( &dom_sid, &rid ) ) + return; + + /* add the newly discovered trusted domain */ + + domain = add_trusted_domain( name, NULL, &cache_methods, + &dom_sid); + + if ( !domain ) + return; + + /* assume this is a trust from a one-way transitive + forest trust */ + + domain->active_directory = True; + domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND; + domain->domain_type = DS_DOMAIN_TRUST_TYPE_UPLEVEL; + domain->internal = False; + domain->online = True; + + setup_domain_child(domain, &domain->child, NULL); + + wcache_tdc_add_domain( domain ); + + return; +} + +/** + * Given a domain name, return the struct winbindd domain info for it + * + * @note Do *not* pass lp_workgroup() to this function. domain_list + * may modify it's value, and free that pointer. Instead, our local + * domain may be found by calling find_our_domain(). + * directly. + * + * + * @return The domain structure for the named domain, if it is working. + */ + +struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name) +{ + struct winbindd_domain *domain; + + /* Search through list */ + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + if (strequal(domain_name, domain->name) || + (domain->alt_name[0] && + strequal(domain_name, domain->alt_name))) { + return domain; + } + } + + /* Not found */ + + return NULL; +} + +struct winbindd_domain *find_domain_from_name(const char *domain_name) +{ + struct winbindd_domain *domain; + + domain = find_domain_from_name_noinit(domain_name); + + if (domain == NULL) + return NULL; + + if (!domain->initialized) + init_dc_connection(domain); + + return domain; +} + +/* Given a domain sid, return the struct winbindd domain info for it */ + +struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid) +{ + struct winbindd_domain *domain; + + /* Search through list */ + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + if (sid_compare_domain(sid, &domain->sid) == 0) + return domain; + } + + /* Not found */ + + return NULL; +} + +/* Given a domain sid, return the struct winbindd domain info for it */ + +struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid) +{ + struct winbindd_domain *domain; + + domain = find_domain_from_sid_noinit(sid); + + if (domain == NULL) + return NULL; + + if (!domain->initialized) + init_dc_connection(domain); + + return domain; +} + +struct winbindd_domain *find_our_domain(void) +{ + struct winbindd_domain *domain; + + /* Search through list */ + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + if (domain->primary) + return domain; + } + + smb_panic("Could not find our domain"); + return NULL; +} + +struct winbindd_domain *find_root_domain(void) +{ + struct winbindd_domain *ours = find_our_domain(); + + if ( !ours ) + return NULL; + + if ( strlen(ours->forest_name) == 0 ) + return NULL; + + return find_domain_from_name( ours->forest_name ); +} + +struct winbindd_domain *find_builtin_domain(void) +{ + DOM_SID sid; + struct winbindd_domain *domain; + + string_to_sid(&sid, "S-1-5-32"); + domain = find_domain_from_sid(&sid); + + if (domain == NULL) { + smb_panic("Could not find BUILTIN domain"); + } + + return domain; +} + +/* Find the appropriate domain to lookup a name or SID */ + +struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid) +{ + /* SIDs in the S-1-22-{1,2} domain should be handled by our passdb */ + + if ( sid_check_is_in_unix_groups(sid) || + sid_check_is_unix_groups(sid) || + sid_check_is_in_unix_users(sid) || + sid_check_is_unix_users(sid) ) + { + return find_domain_from_sid(get_global_sam_sid()); + } + + /* A DC can't ask the local smbd for remote SIDs, here winbindd is the + * one to contact the external DC's. On member servers the internal + * domains are different: These are part of the local SAM. */ + + DEBUG(10, ("find_lookup_domain_from_sid(%s)\n", + sid_string_static(sid))); + + if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) { + DEBUG(10, ("calling find_domain_from_sid\n")); + return find_domain_from_sid(sid); + } + + /* On a member server a query for SID or name can always go to our + * primary DC. */ + + DEBUG(10, ("calling find_our_domain\n")); + return find_our_domain(); +} + +struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name) +{ + if ( strequal(domain_name, unix_users_domain_name() ) || + strequal(domain_name, unix_groups_domain_name() ) ) + { + return find_domain_from_name_noinit( get_global_sam_name() ); + } + + if (IS_DC || strequal(domain_name, "BUILTIN") || + strequal(domain_name, get_global_sam_name())) + return find_domain_from_name_noinit(domain_name); + + /* The "Unix User" and "Unix Group" domain our handled by passdb */ + + return find_our_domain(); +} + +/* Lookup a sid in a domain from a name */ + +BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx, + enum winbindd_cmd orig_cmd, + struct winbindd_domain *domain, + const char *domain_name, + const char *name, DOM_SID *sid, + enum lsa_SidType *type) +{ + NTSTATUS result; + + /* Lookup name */ + result = domain->methods->name_to_sid(domain, mem_ctx, orig_cmd, + domain_name, name, sid, type); + + /* Return sid and type if lookup successful */ + if (!NT_STATUS_IS_OK(result)) { + *type = SID_NAME_UNKNOWN; + } + + return NT_STATUS_IS_OK(result); +} + +/** + * @brief Lookup a name in a domain from a sid. + * + * @param sid Security ID you want to look up. + * @param name On success, set to the name corresponding to @p sid. + * @param dom_name On success, set to the 'domain name' corresponding to @p sid. + * @param type On success, contains the type of name: alias, group or + * user. + * @retval True if the name exists, in which case @p name and @p type + * are set, otherwise False. + **/ +BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + DOM_SID *sid, + char **dom_name, + char **name, + enum lsa_SidType *type) +{ + NTSTATUS result; + + *dom_name = NULL; + *name = NULL; + + /* Lookup name */ + + result = domain->methods->sid_to_name(domain, mem_ctx, sid, dom_name, name, type); + + /* Return name and type if successful */ + + if (NT_STATUS_IS_OK(result)) { + return True; + } + + *type = SID_NAME_UNKNOWN; + + return False; +} + +/* Free state information held for {set,get,end}{pw,gr}ent() functions */ + +void free_getent_state(struct getent_state *state) +{ + struct getent_state *temp; + + /* Iterate over state list */ + + temp = state; + + while(temp != NULL) { + struct getent_state *next; + + /* Free sam entries then list entry */ + + SAFE_FREE(state->sam_entries); + DLIST_REMOVE(state, state); + next = temp->next; + + SAFE_FREE(temp); + temp = next; + } +} + +/* Is this a domain which we may assume no DOMAIN\ prefix? */ + +static BOOL assume_domain(const char *domain) +{ + /* never assume the domain on a standalone server */ + + if ( lp_server_role() == ROLE_STANDALONE ) + return False; + + /* domain member servers may possibly assume for the domain name */ + + if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) { + if ( !strequal(lp_workgroup(), domain) ) + return False; + + if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() ) + return True; + } + + /* only left with a domain controller */ + + if ( strequal(get_global_sam_name(), domain) ) { + return True; + } + + return False; +} + +/* Parse a string of the form DOMAIN\user into a domain and a user */ + +BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) +{ + char *p = strchr(domuser,*lp_winbind_separator()); + + if ( !p ) { + fstrcpy(user, domuser); + + if ( assume_domain(lp_workgroup())) { + fstrcpy(domain, lp_workgroup()); + } else if ((p = strchr(domuser, '@')) != NULL) { + fstrcpy(domain, ""); + } else { + return False; + } + } else { + fstrcpy(user, p+1); + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + } + + strupper_m(domain); + + return True; +} + +BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, + char **domain, char **user) +{ + fstring fstr_domain, fstr_user; + if (!parse_domain_user(domuser, fstr_domain, fstr_user)) { + return False; + } + *domain = talloc_strdup(mem_ctx, fstr_domain); + *user = talloc_strdup(mem_ctx, fstr_user); + return ((*domain != NULL) && (*user != NULL)); +} + +/* Ensure an incoming username from NSS is fully qualified. Replace the + incoming fstring with DOMAIN user. Returns the same + values as parse_domain_user() but also replaces the incoming username. + Used to ensure all names are fully qualified within winbindd. + Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth. + The protocol definitions of auth_crap, chng_pswd_auth_crap + really should be changed to use this instead of doing things + by hand. JRA. */ + +BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user) +{ + if (!parse_domain_user(username_inout, domain, user)) { + return False; + } + slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s", + domain, *lp_winbind_separator(), + user); + return True; +} + +/* + Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and + 'winbind separator' options. + This means: + - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is + lp_workgroup() + + If we are a PDC or BDC, and this is for our domain, do likewise. + + Also, if omit DOMAIN if 'winbind trusted domains only = true', as the + username is then unqualified in unix + + We always canonicalize as UPPERCASE DOMAIN, lowercase username. +*/ +void fill_domain_username(fstring name, const char *domain, const char *user, BOOL can_assume) +{ + fstring tmp_user; + + fstrcpy(tmp_user, user); + strlower_m(tmp_user); + + if (can_assume && assume_domain(domain)) { + strlcpy(name, tmp_user, sizeof(fstring)); + } else { + slprintf(name, sizeof(fstring) - 1, "%s%c%s", + domain, *lp_winbind_separator(), + tmp_user); + } +} + +/* + * Winbindd socket accessor functions + */ + +char *get_winbind_priv_pipe_dir(void) +{ + return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR); +} + +/* + * Client list accessor functions + */ + +static struct winbindd_cli_state *_client_list; +static int _num_clients; + +/* Return list of all connected clients */ + +struct winbindd_cli_state *winbindd_client_list(void) +{ + return _client_list; +} + +/* Add a connection to the list */ + +void winbindd_add_client(struct winbindd_cli_state *cli) +{ + DLIST_ADD(_client_list, cli); + _num_clients++; +} + +/* Remove a client from the list */ + +void winbindd_remove_client(struct winbindd_cli_state *cli) +{ + DLIST_REMOVE(_client_list, cli); + _num_clients--; +} + +/* Close all open clients */ + +void winbindd_kill_all_clients(void) +{ + struct winbindd_cli_state *cl = winbindd_client_list(); + + DEBUG(10, ("winbindd_kill_all_clients: going postal\n")); + + while (cl) { + struct winbindd_cli_state *next; + + next = cl->next; + winbindd_remove_client(cl); + cl = next; + } +} + +/* Return number of open clients */ + +int winbindd_num_clients(void) +{ + return _num_clients; +} + +NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *p_num_groups, DOM_SID **user_sids) +{ + NET_USER_INFO_3 *info3 = NULL; + NTSTATUS status = NT_STATUS_NO_MEMORY; + int i; + size_t num_groups = 0; + DOM_SID group_sid, primary_group; + + DEBUG(3,(": lookup_usergroups_cached\n")); + + *user_sids = NULL; + num_groups = 0; + *p_num_groups = 0; + + info3 = netsamlogon_cache_get(mem_ctx, user_sid); + + if (info3 == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (info3->num_groups == 0) { + TALLOC_FREE(info3); + return NT_STATUS_UNSUCCESSFUL; + } + + /* always add the primary group to the sid array */ + sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid); + + if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) { + TALLOC_FREE(info3); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; inum_groups; i++) { + sid_copy(&group_sid, &info3->dom_sid.sid); + sid_append_rid(&group_sid, info3->gids[i].g_rid); + + if (!add_sid_to_array(mem_ctx, &group_sid, user_sids, + &num_groups)) { + TALLOC_FREE(info3); + return NT_STATUS_NO_MEMORY; + } + } + + /* Add any Universal groups in the other_sids list */ + + for (i=0; inum_other_sids; i++) { + /* Skip Domain local groups outside our domain. + We'll get these from the getsidaliases() RPC call. */ + if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE) + continue; + + if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid, + user_sids, &num_groups)) + { + TALLOC_FREE(info3); + return NT_STATUS_NO_MEMORY; + } + } + + + TALLOC_FREE(info3); + *p_num_groups = num_groups; + status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; + + DEBUG(3,(": lookup_usergroups_cached succeeded\n")); + + return status; +} + +/********************************************************************* + We use this to remove spaces from user and group names +********************************************************************/ + +void ws_name_replace( char *name, char replace ) +{ + char replace_char[2] = { 0x0, 0x0 }; + + if ( !lp_winbind_normalize_names() || (replace == '\0') ) + return; + + replace_char[0] = replace; + all_string_sub( name, " ", replace_char, 0 ); + + return; +} + +/********************************************************************* + We use this to do the inverse of ws_name_replace() +********************************************************************/ + +void ws_name_return( char *name, char replace ) +{ + char replace_char[2] = { 0x0, 0x0 }; + + if ( !lp_winbind_normalize_names() || (replace == '\0') ) + return; + + replace_char[0] = replace; + all_string_sub( name, replace_char, " ", 0 ); + + return; +} + +/********************************************************************* + ********************************************************************/ + +BOOL winbindd_can_contact_domain( struct winbindd_domain *domain ) +{ + /* We can contact the domain if it is our primary domain */ + + if ( domain->primary ) + return True; + + /* Can always contact a domain that is in out forest */ + + if ( domain->domain_flags & DS_DOMAIN_IN_FOREST ) + return True; + + /* We cannot contact the domain if it is running AD and + we have no inbound trust */ + + if ( domain->active_directory && + ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) + { + return False; + } + + /* Assume everything else is ok (probably not true but what + can you do?) */ + + return True; +} + +/********************************************************************* + ********************************************************************/ + +BOOL winbindd_internal_child(struct winbindd_child *child) +{ + if ((child == idmap_child()) || (child == locator_child())) { + return True; + } + + return False; +} + +#ifdef HAVE_KRB5_LOCATE_PLUGIN_H + +/********************************************************************* + ********************************************************************/ + +static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain) +{ + char *var = NULL; + const char *kdc = NULL; + int lvl = 11; + + if (!domain || !domain->alt_name || !*domain->alt_name) { + return; + } + + if (domain->initialized && !domain->active_directory) { + DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n", + domain->alt_name)); + return; + } + + kdc = inet_ntoa(domain->dcaddr.sin_addr); + if (!kdc) { + DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n", + domain->alt_name)); + kdc = domain->dcname; + } + + if (!kdc || !*kdc) { + DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n", + domain->alt_name)); + return; + } + + if (asprintf(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, + strupper_static(domain->alt_name)) == -1) { + return; + } + + DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n", + var, kdc)); + + setenv(var, kdc, 1); + free(var); +} + +/********************************************************************* + ********************************************************************/ + +void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain) +{ + struct winbindd_domain *our_dom = find_our_domain(); + + winbindd_set_locator_kdc_env(domain); + + if (domain != our_dom) { + winbindd_set_locator_kdc_env(our_dom); + } +} + +/********************************************************************* + ********************************************************************/ + +void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) +{ + char *var = NULL; + + if (!domain || !domain->alt_name || !*domain->alt_name) { + return; + } + + if (asprintf(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, + strupper_static(domain->alt_name)) == -1) { + return; + } + + unsetenv(var); + free(var); +} +#else + +void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain) +{ + return; +} + +void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) +{ + return; +} + +#endif /* HAVE_KRB5_LOCATE_PLUGIN_H */ diff --git a/source3/winbindd/winbindd_wins.c b/source3/winbindd/winbindd_wins.c new file mode 100644 index 0000000000..f84dfdf2de --- /dev/null +++ b/source3/winbindd/winbindd_wins.c @@ -0,0 +1,234 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - WINS related functions + + Copyright (C) Andrew Tridgell 1999 + Copyright (C) Herb Lewis 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* Use our own create socket code so we don't recurse.... */ + +static int wins_lookup_open_socket_in(void) +{ + struct sockaddr_in sock; + int val=1; + int res; + + memset((char *)&sock,'\0',sizeof(sock)); + +#ifdef HAVE_SOCK_SIN_LEN + sock.sin_len = sizeof(sock); +#endif + sock.sin_port = 0; + sock.sin_family = AF_INET; + sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); + res = socket(AF_INET, SOCK_DGRAM, 0); + if (res == -1) + return -1; + + setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); +#ifdef SO_REUSEPORT + setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); +#endif /* SO_REUSEPORT */ + + /* now we've got a socket - we need to bind it */ + + if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { + close(res); + return(-1); + } + + set_socket_options(res,"SO_BROADCAST"); + + return res; +} + + +static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) +{ + int fd; + struct in_addr ip; + struct nmb_name nname; + NODE_STATUS_STRUCT *status; + + fd = wins_lookup_open_socket_in(); + if (fd == -1) + return NULL; + + make_nmb_name(&nname, "*", 0); + ip = *interpret_addr2(addr); + status = node_status_query(fd,&nname,ip, count, NULL); + + close(fd); + return status; +} + +static struct in_addr *lookup_byname_backend(const char *name, int *count) +{ + int fd; + struct ip_service *ret = NULL; + struct in_addr *return_ip = NULL; + int j, i, flags = 0; + + *count = 0; + + /* always try with wins first */ + if (NT_STATUS_IS_OK(resolve_wins(name,0x20,&ret,count))) { + if ( *count == 0 ) + return NULL; + if ( (return_ip = SMB_MALLOC_ARRAY(struct in_addr, *count)) == NULL ) { + free( ret ); + return NULL; + } + + /* copy the IP addresses */ + for ( i=0; i<(*count); i++ ) + return_ip[i] = ret[i].ip; + + free( ret ); + return return_ip; + } + + fd = wins_lookup_open_socket_in(); + if (fd == -1) { + return NULL; + } + + /* uggh, we have to broadcast to each interface in turn */ + for (j=iface_count() - 1; + j >= 0; + j--) { + struct in_addr *bcast = iface_n_bcast(j); + return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); + if (return_ip) { + break; + } + } + + close(fd); + return return_ip; +} + +/* Get hostname from IP */ + +void winbindd_wins_byip(struct winbindd_cli_state *state) +{ + fstring response; + int i, count, maxlen, size; + NODE_STATUS_STRUCT *status; + + /* Ensure null termination */ + state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; + + DEBUG(3, ("[%5lu]: wins_byip %s\n", (unsigned long)state->pid, + state->request.data.winsreq)); + + *response = '\0'; + maxlen = sizeof(response) - 1; + + if ((status = lookup_byaddr_backend(state->request.data.winsreq, &count))){ + size = strlen(state->request.data.winsreq); + if (size > maxlen) { + SAFE_FREE(status); + request_error(state); + return; + } + fstrcat(response,state->request.data.winsreq); + fstrcat(response,"\t"); + for (i = 0; i < count; i++) { + /* ignore group names */ + if (status[i].flags & 0x80) continue; + if (status[i].type == 0x20) { + size = sizeof(status[i].name) + strlen(response); + if (size > maxlen) { + SAFE_FREE(status); + request_error(state); + return; + } + fstrcat(response, status[i].name); + fstrcat(response, " "); + } + } + /* make last character a newline */ + response[strlen(response)-1] = '\n'; + SAFE_FREE(status); + } + fstrcpy(state->response.data.winsresp,response); + request_ok(state); +} + +/* Get IP from hostname */ + +void winbindd_wins_byname(struct winbindd_cli_state *state) +{ + struct in_addr *ip_list; + int i, count, maxlen, size; + fstring response; + char * addr; + + /* Ensure null termination */ + state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; + + DEBUG(3, ("[%5lu]: wins_byname %s\n", (unsigned long)state->pid, + state->request.data.winsreq)); + + *response = '\0'; + maxlen = sizeof(response) - 1; + + if ((ip_list = lookup_byname_backend(state->request.data.winsreq,&count))){ + for (i = count; i ; i--) { + addr = inet_ntoa(ip_list[i-1]); + size = strlen(addr); + if (size > maxlen) { + SAFE_FREE(ip_list); + request_error(state); + return; + } + if (i != 0) { + /* Clear out the newline character */ + /* But only if there is something in there, + otherwise we clobber something in the stack */ + if (strlen(response)) + response[strlen(response)-1] = ' '; + } + fstrcat(response,addr); + fstrcat(response,"\t"); + } + size = strlen(state->request.data.winsreq) + strlen(response); + if (size > maxlen) { + SAFE_FREE(ip_list); + request_error(state); + return; + } + fstrcat(response,state->request.data.winsreq); + fstrcat(response,"\n"); + SAFE_FREE(ip_list); + } else { + request_error(state); + return; + } + + fstrcpy(state->response.data.winsresp,response); + + request_ok(state); +} -- cgit From ab9d7bf4f950a78d9ca7973294d133290c99096c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 17:42:10 +0000 Subject: r25165: Use talloc_asprintf_append_buffer with an unmodified string. Jeremy. (This used to be commit fe30a523dfc77cc373145624246fd3ad5c62b9ac) --- source3/winbindd/idmap_ad.c | 14 +++++++------- source3/winbindd/idmap_ldap.c | 8 ++++---- source3/winbindd/winbindd_dual.c | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 41dbb471f9..b2d41e436c 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -315,7 +315,7 @@ again: ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST); } - u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)", + u_filter = talloc_asprintf_append_buffer(u_filter, "(%s=%lu)", ad_schema->posix_uidnumber_attr, (unsigned long)ids[idx]->xid.id); CHECK_ALLOC_DONE(u_filter); @@ -329,7 +329,7 @@ again: ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP); } - g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)", + g_filter = talloc_asprintf_append_buffer(g_filter, "(%s=%lu)", ad_schema->posix_gidnumber_attr, (unsigned long)ids[idx]->xid.id); CHECK_ALLOC_DONE(g_filter); @@ -344,16 +344,16 @@ again: filter = talloc_asprintf(memctx, "(|"); CHECK_ALLOC_DONE(filter); if ( u_filter) { - filter = talloc_asprintf_append(filter, "%s))", u_filter); + filter = talloc_asprintf_append_buffer(filter, "%s))", u_filter); CHECK_ALLOC_DONE(filter); TALLOC_FREE(u_filter); } if ( g_filter) { - filter = talloc_asprintf_append(filter, "%s))", g_filter); + filter = talloc_asprintf_append_buffer(filter, "%s))", g_filter); CHECK_ALLOC_DONE(filter); TALLOC_FREE(g_filter); } - filter = talloc_asprintf_append(filter, ")"); + filter = talloc_asprintf_append_buffer(filter, ")"); CHECK_ALLOC_DONE(filter); rc = ads_search_retry(ads, &res, filter, attrs); @@ -535,12 +535,12 @@ again: for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) { sidstr = sid_binstring(ids[idx]->sid); - filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr); + filter = talloc_asprintf_append_buffer(filter, "(objectSid=%s)", sidstr); free(sidstr); CHECK_ALLOC_DONE(filter); } - filter = talloc_asprintf_append(filter, "))"); + filter = talloc_asprintf_append_buffer(filter, "))"); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]\n", filter)); diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 3b63915b05..9daf084ce1 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -955,12 +955,12 @@ again: bidx = idx; for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { - filter = talloc_asprintf_append(filter, "(%s=%lu)", + filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)", (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber, (unsigned long)ids[idx]->xid.id); CHECK_ALLOC_DONE(filter); } - filter = talloc_asprintf_append(filter, "))"); + filter = talloc_asprintf_append_buffer(filter, "))"); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]\n", filter)); } else { @@ -1185,12 +1185,12 @@ again: bidx = idx; for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { - filter = talloc_asprintf_append(filter, "(%s=%s)", + filter = talloc_asprintf_append_buffer(filter, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_string_static(ids[idx]->sid)); CHECK_ALLOC_DONE(filter); } - filter = talloc_asprintf_append(filter, "))"); + filter = talloc_asprintf_append_buffer(filter, "))"); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]", filter)); } else { diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 67cf6abc2b..d9a42c31dc 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -858,7 +858,7 @@ static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx) } for (domain = domain_list(); domain; domain = domain->next) { - if ((buf = talloc_asprintf_append(buf, "%s:%s ", + if ((buf = talloc_asprintf_append_buffer(buf, "%s:%s ", domain->name, domain->online ? "Online":"Offline")) == NULL) { @@ -866,7 +866,7 @@ static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx) } } - buf = talloc_asprintf_append(buf, "\n"); + buf = talloc_asprintf_append_buffer(buf, "\n"); DEBUG(5,("collect_onlinestatus: %s", buf)); -- cgit From 0805a4bc715f055fd68c5e27bd46eadfb101e1b9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Sep 2007 17:19:57 +0000 Subject: r25236: make it possible to alter WINBINDD_SOCKET_DIR via "winbindd:socket dir=/path/to/dir" for usage in make test metze (This used to be commit 5566cf01e827edf60c0235a661d95dd376210108) --- source3/winbindd/winbindd_sockinit.c | 4 ++-- source3/winbindd/winbindd_util.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_sockinit.c b/source3/winbindd/winbindd_sockinit.c index 50c53a5045..886b67fb47 100644 --- a/source3/winbindd/winbindd_sockinit.c +++ b/source3/winbindd/winbindd_sockinit.c @@ -35,7 +35,7 @@ static int open_winbindd_socket(void) { if (_winbindd_socket == -1) { _winbindd_socket = create_pipe_sock( - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755); + get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755); DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", _winbindd_socket)); } @@ -119,7 +119,7 @@ void winbindd_release_sockets(void) /* Remove socket file */ if (unlink_winbindd_socket) { pstr_sprintf(path, "%s/%s", - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); + get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME); unlink(path); } } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 37d29e1765..c1600823fc 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1158,6 +1158,11 @@ void fill_domain_username(fstring name, const char *domain, const char *user, BO * Winbindd socket accessor functions */ +const char *get_winbind_pipe_dir(void) +{ + return lp_parm_const_string(-1, "winbindd", "socket dir", WINBINDD_SOCKET_DIR); +} + char *get_winbind_priv_pipe_dir(void) { return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR); -- cgit From 1edf050ad8682f2cd0781babf9b9db132e1e7493 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Sep 2007 19:05:54 +0000 Subject: r25241: remove sequence_number out of WINBINDD_DOMAIN_INFO call as this is always answered by the winbindd parent and will most times return old sequence number values. metze (This used to be commit 9caf54c868e8c0109730860e772c9cc404e2f899) --- source3/winbindd/winbindd_misc.c | 8 ++------ source3/winbindd/winbindd_util.c | 4 ---- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 9c3f634534..1f23bf1bee 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -410,7 +410,7 @@ static void sequence_recv(void *private_data, BOOL success) uint32 seq = DOM_SEQUENCE_NONE; if ((success) && (state->response->result == WINBINDD_OK)) - seq = state->response->data.domain_info.sequence_number; + seq = state->response->data.sequence_number; if (seq == DOM_SEQUENCE_NONE) { state->extra_data = talloc_asprintf(state->mem_ctx, @@ -459,7 +459,7 @@ enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain, domain->methods->sequence_number(domain, &domain->sequence_number); - state->response.data.domain_info.sequence_number = + state->response.data.sequence_number = domain->sequence_number; return WINBINDD_OK; @@ -519,8 +519,6 @@ void winbindd_domain_info(struct winbindd_cli_state *state) domain->active_directory; state->response.data.domain_info.primary = domain->primary; - state->response.data.domain_info.sequence_number = - domain->sequence_number; request_ok(state); } @@ -554,8 +552,6 @@ static void domain_info_init_recv(void *private_data, BOOL success) domain->active_directory; state->response.data.domain_info.primary = domain->primary; - state->response.data.domain_info.sequence_number = - domain->sequence_number; request_ok(state); } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index c1600823fc..0175990f0c 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -631,8 +631,6 @@ static void init_child_recv(void *private_data, BOOL success) state->response->data.domain_info.native_mode; state->domain->active_directory = state->response->data.domain_info.active_directory; - state->domain->sequence_number = - state->response->data.domain_info.sequence_number; init_dc_connection(state->domain); @@ -677,8 +675,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai = domain->active_directory; state->response.data.domain_info.primary = domain->primary; - state->response.data.domain_info.sequence_number = - domain->sequence_number; return WINBINDD_OK; } -- cgit From 6f5869461cb0a1ac0bdba931a7f7469503154ce3 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 19 Sep 2007 22:11:09 +0000 Subject: r25247: Rename the rpccli_lsa_lookup_sids_all() function to rpccli_lsa_lookup_sids() and remove the old rpccli_lsa_lookup_sids() function. The old function would fail due to server limits when requesting to resolve too many sids at once (20480 for W2k3). The new version passes the list of sids in hunks to the server. It has up to now been used (and tested) in the winbindd_ads lookup_groupmem() function, and I think the time has come to replace the actual function with this correct version. Michael (This used to be commit 1194d4f36ef720747e62dde31881c295e44e4a76) --- source3/winbindd/winbindd_ads.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 65cc00bb97..488967ed09 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1049,13 +1049,13 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, goto done; } - status = rpccli_lsa_lookup_sids_all(cli, tmp_ctx, - &lsa_policy, - num_nocache, - sid_mem_nocache, - &domains_nocache, - &names_nocache, - &name_types_nocache); + status = rpccli_lsa_lookup_sids(cli, tmp_ctx, + &lsa_policy, + num_nocache, + sid_mem_nocache, + &domains_nocache, + &names_nocache, + &name_types_nocache); if (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) -- cgit From 8ad224663576b32a4bcd43f808851d2cdde34656 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 20 Sep 2007 18:37:34 +0000 Subject: r25260: add trusted domains always to the end of the list. Now BUILTIN is always the first domain followed by the domain of our own SAM DB and the primary domain (in member server mode). metze (This used to be commit b8d67b78aa1c35e4e7e61050c1fccbb6d76d9fd7) --- source3/winbindd/winbindd_util.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 0175990f0c..0e6ba1c043 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -186,7 +186,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const } /* Link to domain list */ - DLIST_ADD(_domain_list, domain); + DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *); wcache_tdc_add_domain( domain ); @@ -688,6 +688,25 @@ BOOL init_domain_list(void) /* Free existing list */ free_domain_list(); + /* BUILTIN domain */ + + domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, + &global_sid_Builtin); + if (domain) { + setup_domain_child(domain, &domain->child, NULL); + } + + /* Local SAM */ + + domain = add_trusted_domain(get_global_sam_name(), NULL, + &passdb_methods, get_global_sam_sid()); + if (domain) { + if ( role != ROLE_DOMAIN_MEMBER ) { + domain->primary = True; + } + setup_domain_child(domain, &domain->child, NULL); + } + /* Add ourselves as the first entry. */ if ( role == ROLE_DOMAIN_MEMBER ) { @@ -714,25 +733,6 @@ BOOL init_domain_list(void) } } - /* Local SAM */ - - domain = add_trusted_domain(get_global_sam_name(), NULL, - &passdb_methods, get_global_sam_sid()); - if (domain) { - if ( role != ROLE_DOMAIN_MEMBER ) { - domain->primary = True; - } - setup_domain_child(domain, &domain->child, NULL); - } - - /* BUILTIN domain */ - - domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, - &global_sid_Builtin); - if (domain) { - setup_domain_child(domain, &domain->child, NULL); - } - return True; } -- cgit From 4ab70e8438361fd41b71c959d0d20137959a51ea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 21 Sep 2007 09:35:53 +0000 Subject: r25270: for internal domains we should not ask a remote DC. metze (This used to be commit 579ed8ae87e449dbd5e4f78609754df0556fbf68) --- source3/winbindd/winbindd_misc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 1f23bf1bee..30386cc6eb 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -209,12 +209,21 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain * void winbindd_getdcname(struct winbindd_cli_state *state) { + struct winbindd_domain *domain; + state->request.domain_name [sizeof(state->request.domain_name)-1] = '\0'; DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid, state->request.domain_name)); + domain = find_domain_from_name_noinit(state->request.domain_name); + if (domain && domain->internal) { + fstrcpy(state->response.data.dc_name, global_myname()); + request_ok(state); + return; + } + sendto_domain(state, find_our_domain()); } -- cgit From 4fab9cf625278dd032a808b5c1bb8f2aec1bd0f2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 09:52:28 +0000 Subject: r25272: Fix a bunch of callers of pull_ucs2 that passed -1 for dest_len. Michael (This used to be commit a4f53fe22569a63fe7b196971ac6c28a676ee4e8) --- source3/winbindd/winbindd_pam.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 50b24864b5..c4db691d05 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -61,22 +61,22 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.num_other_sids = info3->num_other_sids; unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, -1); + &info3->uni_user_name, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, -1); + &info3->uni_full_name, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, -1); + &info3->uni_logon_script, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, -1); + &info3->uni_profile_path, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, -1); + &info3->uni_home_dir, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, -1); + &info3->uni_dir_drive, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, -1); + &info3->uni_logon_srv, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, -1); + &info3->uni_logon_dom, sizeof(fstring)); return NT_STATUS_OK; } -- cgit From c1284b8eb8585f05a49866d2f93d25f5665b5cf8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Sep 2007 09:58:36 +0000 Subject: r25273: unistrX_to_ascii calls pull_ucs2 - ensure it's never called with -1 (these calls were wrong anyway, target was an fstring, not a pstring). Found by Michael Adam , now to check all other uses. Michael - this version uses sizeof(target) not sizeof(fstring). This way is more future proof. Jeremy. (This used to be commit 9ed3046633b6949c68c9aed61b8e9444601cf101) --- source3/winbindd/winbindd_pam.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c4db691d05..8f78209586 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -61,22 +61,22 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.num_other_sids = info3->num_other_sids; unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, sizeof(fstring)); + &info3->uni_user_name, sizeof(state->response.data.auth.info3.user_name)); unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, sizeof(fstring)); + &info3->uni_full_name, sizeof(state->response.data.auth.info3.full_name)); unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, sizeof(fstring)); + &info3->uni_logon_script, sizeof(state->response.data.auth.info3.logon_script)); unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, sizeof(fstring)); + &info3->uni_profile_path, sizeof(state->response.data.auth.info3.profile_path)); unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, sizeof(fstring)); + &info3->uni_home_dir, sizeof(state->response.data.auth.info3.home_dir)); unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, sizeof(fstring)); + &info3->uni_dir_drive, sizeof(state->response.data.auth.info3.dir_drive)); unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, sizeof(fstring)); + &info3->uni_logon_srv, sizeof(state->response.data.auth.info3.logon_srv)); unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, sizeof(fstring)); + &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); return NT_STATUS_OK; } -- cgit From ba93d0e5c8418eb11a5fa0bb48c1ec3a0ebd403b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 21 Sep 2007 10:25:33 +0000 Subject: r25275: w2k3 (as PDC emulator) returns WERR_NO_SUCH_DOMAIN to netlogon_getanydcname() when called for it's own domain. So we should use netlogon_getdcname() which returns WERR_OK:-) gd: feel free to usage rpccli_netlogon_dsr_getdcname(), but please make sure the new WINBIND-STRUCT-GETDCNAME test is still passing. metze (This used to be commit 9a9c164366a252ab8268b687699d54048ced993f) --- source3/winbindd/winbindd_misc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 30386cc6eb..5513e1790b 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -236,6 +236,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, NTSTATUS result; WERROR werr; unsigned int orig_timeout; + struct winbindd_domain *req_domain; state->request.domain_name [sizeof(state->request.domain_name)-1] = '\0'; @@ -255,9 +256,18 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); - werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, domain->dcname, - state->request.domain_name, - dcname_slash); + req_domain = find_domain_from_name_noinit(state->request.domain_name); + if (req_domain == domain) { + werr = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, + domain->dcname, + state->request.domain_name, + dcname_slash); + } else { + werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, + domain->dcname, + state->request.domain_name, + dcname_slash); + } /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); -- cgit From 6873d5446e4cee76b022bfc0d33e9e8380e796c0 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 12:24:43 +0000 Subject: r25287: Eliminate a handful of red bars and overly long lines I just came across. Michael (This used to be commit bf12f0c0f843f088c7fa2d1eca3298a3d76e9761) --- source3/winbindd/winbindd_pam.c | 72 +++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 8f78209586..f823e1d7b2 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -7,17 +7,17 @@ Copyright (C) Tim Potter 2001 Copyright (C) Andrew Bartlett 2001-2002 Copyright (C) Guenther Deschner 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -27,23 +27,23 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) +static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) { fstring str_sid; - state->response.data.auth.info3.logon_time = + state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); - state->response.data.auth.info3.logoff_time = + state->response.data.auth.info3.logoff_time = nt_time_to_unix(info3->logoff_time); - state->response.data.auth.info3.kickoff_time = + state->response.data.auth.info3.kickoff_time = nt_time_to_unix(info3->kickoff_time); - state->response.data.auth.info3.pass_last_set_time = + state->response.data.auth.info3.pass_last_set_time = nt_time_to_unix(info3->pass_last_set_time); - state->response.data.auth.info3.pass_can_change_time = + state->response.data.auth.info3.pass_can_change_time = nt_time_to_unix(info3->pass_can_change_time); - state->response.data.auth.info3.pass_must_change_time = + state->response.data.auth.info3.pass_must_change_time = nt_time_to_unix(info3->pass_must_change_time); state->response.data.auth.info3.logon_count = info3->logon_count; @@ -60,30 +60,38 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.acct_flags = info3->acct_flags; state->response.data.auth.info3.num_other_sids = info3->num_other_sids; - unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, sizeof(state->response.data.auth.info3.user_name)); - unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, sizeof(state->response.data.auth.info3.full_name)); - unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, sizeof(state->response.data.auth.info3.logon_script)); - unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, sizeof(state->response.data.auth.info3.profile_path)); - unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, sizeof(state->response.data.auth.info3.home_dir)); - unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, sizeof(state->response.data.auth.info3.dir_drive)); - - unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, sizeof(state->response.data.auth.info3.logon_srv)); - unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); + unistr2_to_ascii(state->response.data.auth.info3.user_name, + &info3->uni_user_name, + sizeof(state->response.data.auth.info3.user_name)); + unistr2_to_ascii(state->response.data.auth.info3.full_name, + &info3->uni_full_name, + sizeof(state->response.data.auth.info3.full_name)); + unistr2_to_ascii(state->response.data.auth.info3.logon_script, + &info3->uni_logon_script, + sizeof(state->response.data.auth.info3.logon_script)); + unistr2_to_ascii(state->response.data.auth.info3.profile_path, + &info3->uni_profile_path, + sizeof(state->response.data.auth.info3.profile_path)); + unistr2_to_ascii(state->response.data.auth.info3.home_dir, + &info3->uni_home_dir, + sizeof(state->response.data.auth.info3.home_dir)); + unistr2_to_ascii(state->response.data.auth.info3.dir_drive, + &info3->uni_dir_drive, + sizeof(state->response.data.auth.info3.dir_drive)); + + unistr2_to_ascii(state->response.data.auth.info3.logon_srv, + &info3->uni_logon_srv, + sizeof(state->response.data.auth.info3.logon_srv)); + unistr2_to_ascii(state->response.data.auth.info3.logon_dom, + &info3->uni_logon_dom, + sizeof(state->response.data.auth.info3.logon_dom)); return NT_STATUS_OK; } -static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) +static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) { prs_struct ps; uint32 size; -- cgit From c97fe37ea3d92a631e8da17c21dafae1db15e97b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 14:37:35 +0000 Subject: r25294: Tidy up callers of unistr2_to_ascii() to pass sizeof(target_area) to the maxeln parameter instead of sizeof(target_area) - 1 (or even sizeof(fstring) - 1 in some places. I hope these were really all there were. Michael (This used to be commit 9a28be220df622322857dfe102fa35e108f932dc) --- source3/winbindd/winbindd_rpc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 6d2dd35080..283b4f36e9 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -96,8 +96,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, fstring username, fullname; uint32 rid = ctr.sam.info1->sam[j].rid_user; - unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1); - unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1); + unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)); + unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)); (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); -- cgit From 3529156971e17c7ec13f6a6243f7b613e4666cdd Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 28 Sep 2007 03:54:42 +0000 Subject: r25400: Windows 2008 (Longhorn) Interop fixes for AD specific auth2 flags, and client fixes. Patch from Todd Stetcher . (This used to be commit 8304ccba7346597425307e260e88647e49081f68) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 9ffb3dfb23..f08789052d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2141,7 +2141,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; -- cgit From 5221ebb299081da6a806362212c6a8ceb9cc70a8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 28 Sep 2007 18:15:34 +0000 Subject: r25407: Revert Longhorn join patch as it is not correct for the 3.2 tree. The translate_name() used by cli_session_setup_spnego() cann rely Winbindd since it is needed by the join process (and hence before Winbind can be run). (This used to be commit 00a93ed336c5f36643e6e33bd277608eaf05677c) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index f08789052d..9ffb3dfb23 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2141,7 +2141,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; -- cgit From adf5ac6f60d3e611386bbce3ef7556b8d8efd996 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 10:54:33 +0000 Subject: r25567: make do_async() non static metze (This used to be commit badc714d7f82f8d7c21ecfeab137efb57e970210) --- source3/winbindd/winbindd_async.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 5d31ff0a41..f616984b81 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -57,12 +57,12 @@ static void do_async_recv(void *private_data, BOOL success) state->c, state->private_data); } -static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, - const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data), - void *c, void *private_data) +void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) { struct do_async_state *state; -- cgit From 2f6fbb1c534386e0eac73a523d0ff4f954637cff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:11:46 +0000 Subject: r25568: move idmap related functions into their own file. the final goal is to have 3 child dispatch tables 'domain', 'idmap' and 'locator' instead of one. metze (This used to be commit 97c63f1b95190f3bcc1d9f34765934c97ffb720c) --- source3/winbindd/winbindd_async.c | 741 ------------------------------------ source3/winbindd/winbindd_idmap.c | 778 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 778 insertions(+), 741 deletions(-) create mode 100644 source3/winbindd/winbindd_idmap.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index f616984b81..00c20529c5 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -111,581 +111,6 @@ void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, &state->response, do_async_recv, state); } -static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_mapping\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_mapping returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_MAPPING; - request.data.dual_idmapset.id = map->xid.id; - request.data.dual_idmapset.type = map->xid.type; - sid_to_string(request.data.dual_idmapset.sid, map->sid); - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct id_map map; - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); - - if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) - return WINBINDD_ERROR; - - map.sid = &sid; - map.xid.id = state->request.data.dual_idmapset.id; - map.xid.type = state->request.data.dual_idmapset.type; - map.status = ID_MAPPED; - - result = idmap_set_mapping(&map); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_hwm\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_hwm returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_HWM; - request.data.dual_idmapset.id = xid->id; - request.data.dual_idmapset.type = xid->type; - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct unixid xid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); - - xid.id = state->request.data.dual_idmapset.id; - xid.type = state->request.data.dual_idmapset.type; - - switch (xid.type) { - case ID_TYPE_UID: - result = idmap_set_uid_hwm(&xid); - break; - case ID_TYPE_GID: - result = idmap_set_gid_hwm(&xid); - break; - default: - return WINBINDD_ERROR; - } - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, void *, int) = - (void (*)(void *, BOOL, void *, int))c; - - if (!success) { - DEBUG(5, ("Could not trigger sids2xids\n")); - cont(private_data, False, NULL, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sids2xids returned an error\n")); - cont(private_data, False, NULL, 0); - return; - } - - cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); -} - -void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, - void (*cont)(void *private_data, BOOL success, void *data, int len), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SIDS2XIDS; - request.extra_data.data = (char *)sids; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID *sids; - struct unixid *xids; - struct id_map **ids; - NTSTATUS result; - int num, i; - - DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); - - if (state->request.extra_len == 0) { - DEBUG(0, ("Invalid buffer size!\n")); - return WINBINDD_ERROR; - } - - sids = (DOM_SID *)state->request.extra_data.data; - num = state->request.extra_len / sizeof(DOM_SID); - - ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); - if ( ! ids) { - DEBUG(0, ("Out of memory!\n")); - return WINBINDD_ERROR; - } - for (i = 0; i < num; i++) { - ids[i] = TALLOC_P(ids, struct id_map); - if ( ! ids[i]) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - ids[i]->sid = &sids[i]; - } - - result = idmap_sids_to_unixids(ids); - - if (NT_STATUS_IS_OK(result)) { - - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; - } - } - - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; - - } else { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); - talloc_free(ids); - return WINBINDD_ERROR; - } - - talloc_free(ids); - return WINBINDD_OK; -} - -static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} - -void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2UID; - sid_to_string(request.data.dual_sid2id.sid, sid); - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find uid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2NAME; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, uid2name_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.uid)); - - pw = getpwuid(state->request.data.uid); - if (pw == NULL) { - DEBUG(5, ("User %lu not found\n", - (unsigned long)state->request.data.uid)); - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.name, pw->pw_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, - uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2UID; - fstrcpy(request.data.username, name); - do_async(mem_ctx, idmap_child(), &request, name2uid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - /* Ensure null termination */ - state->request.data.username - [sizeof(state->request.data.username)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, - state->request.data.username)); - - pw = getpwnam(state->request.data.username); - if (pw == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.uid = pw->pw_uid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} -#endif /* not used */ - -static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} - -void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2GID; - sid_to_string(request.data.dual_sid2id.sid, sid); - - DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", - request.data.dual_sid2id.sid)); - - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find gid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_gid(&sid, &state->response.data.gid); - - DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2NAME; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, gid2name_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.gid)); - - gr = getgrgid(state->request.data.gid); - if (gr == NULL) - return WINBINDD_ERROR; - - fstrcpy(state->response.data.name.name, gr->gr_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, - gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2GID; - fstrcpy(request.data.groupname, name); - do_async(mem_ctx, idmap_child(), &request, name2gid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - /* Ensure null termination */ - state->request.data.groupname - [sizeof(state->request.data.groupname)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, - state->request.data.groupname)); - - gr = getgrnam(state->request.data.groupname); - if (gr == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.gid = gr->gr_gid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} -#endif /* not used */ - struct lookupsid_state { DOM_SID sid; void *caller_private_data; @@ -1527,169 +952,3 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, do_async_domain(mem_ctx, domain, &request, query_user_recv, (void *)cont, private_data); } - -/* The following uid2sid/gid2sid functions has been contributed by - * Keith Reynolds */ - -static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2SID; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: uid to sid %lu\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.uid)); - - /* Find sid for this uid and return it, possibly ask the slow remote idmap */ - result = idmap_uid_to_sid(&sid, state->request.data.uid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_USER; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2SID; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: gid %lu to sid\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.gid)); - - /* Find sid for this gid and return it, possibly ask the slow remote idmap */ - result = idmap_gid_to_sid(&sid, state->request.data.gid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - DEBUG(10, ("[%5lu]: retrieved sid: %s\n", - (unsigned long)state->pid, - state->response.data.sid.sid)); - state->response.data.sid.type = SID_NAME_DOM_GRP; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = - (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger a map dump\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap dump maps returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_DUMP_MAPS; - request.extra_data.data = (char *)data; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); - - idmap_dump_maps((char *)state->request.extra_data.data); - - return WINBINDD_OK; -} - diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c new file mode 100644 index 0000000000..3ae88c4c5d --- /dev/null +++ b/source3/winbindd/winbindd_idmap.c @@ -0,0 +1,778 @@ +/* + Unix SMB/CIFS implementation. + + Async helpers for blocking functions + + Copyright (C) Volker Lendecke 2005 + Copyright (C) Gerald Carter 2006 + + The helpers always consist of three functions: + + * A request setup function that takes the necessary parameters together + with a continuation function that is to be called upon completion + + * A private continuation function that is internal only. This is to be + called by the lower-level functions in do_async(). Its only task is to + properly call the continuation function named above. + + * A worker function that is called inside the appropriate child process. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_mapping\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_mapping returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_MAPPING; + request.data.dual_idmapset.id = map->xid.id; + request.data.dual_idmapset.type = map->xid.type; + sid_to_string(request.data.dual_idmapset.sid, map->sid); + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct id_map map; + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); + + if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) + return WINBINDD_ERROR; + + map.sid = &sid; + map.xid.id = state->request.data.dual_idmapset.id; + map.xid.type = state->request.data.dual_idmapset.type; + map.status = ID_MAPPED; + + result = idmap_set_mapping(&map); + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_hwm\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_hwm returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_HWM; + request.data.dual_idmapset.id = xid->id; + request.data.dual_idmapset.type = xid->type; + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); + + xid.id = state->request.data.dual_idmapset.id; + xid.type = state->request.data.dual_idmapset.type; + + switch (xid.type) { + case ID_TYPE_UID: + result = idmap_set_uid_hwm(&xid); + break; + case ID_TYPE_GID: + result = idmap_set_gid_hwm(&xid); + break; + default: + return WINBINDD_ERROR; + } + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, void *, int) = + (void (*)(void *, BOOL, void *, int))c; + + if (!success) { + DEBUG(5, ("Could not trigger sids2xids\n")); + cont(private_data, False, NULL, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sids2xids returned an error\n")); + cont(private_data, False, NULL, 0); + return; + } + + cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); +} + +void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, + void (*cont)(void *private_data, BOOL success, void *data, int len), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SIDS2XIDS; + request.extra_data.data = (char *)sids; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID *sids; + struct unixid *xids; + struct id_map **ids; + NTSTATUS result; + int num, i; + + DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); + + if (state->request.extra_len == 0) { + DEBUG(0, ("Invalid buffer size!\n")); + return WINBINDD_ERROR; + } + + sids = (DOM_SID *)state->request.extra_data.data; + num = state->request.extra_len / sizeof(DOM_SID); + + ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); + if ( ! ids) { + DEBUG(0, ("Out of memory!\n")); + return WINBINDD_ERROR; + } + for (i = 0; i < num; i++) { + ids[i] = TALLOC_P(ids, struct id_map); + if ( ! ids[i]) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + ids[i]->sid = &sids[i]; + } + + result = idmap_sids_to_unixids(ids); + + if (NT_STATUS_IS_OK(result)) { + + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } + } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; + + } else { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; + } + + talloc_free(ids); + return WINBINDD_OK; +} + +static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} + +void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2UID; + sid_to_string(request.data.dual_sid2id.sid, sid); + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2NAME; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, uid2name_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + pw = getpwuid(state->request.data.uid); + if (pw == NULL) { + DEBUG(5, ("User %lu not found\n", + (unsigned long)state->request.data.uid)); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.name.name, pw->pw_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2UID; + fstrcpy(request.data.username, name); + do_async(mem_ctx, idmap_child(), &request, name2uid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + /* Ensure null termination */ + state->request.data.username + [sizeof(state->request.data.username)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, + state->request.data.username)); + + pw = getpwnam(state->request.data.username); + if (pw == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.uid = pw->pw_uid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} +#endif /* not used */ + +static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} + +void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2GID; + sid_to_string(request.data.dual_sid2id.sid, sid); + + DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", + request.data.dual_sid2id.sid)); + + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find gid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_gid(&sid, &state->response.data.gid); + + DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2NAME; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, gid2name_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + gr = getgrgid(state->request.data.gid); + if (gr == NULL) + return WINBINDD_ERROR; + + fstrcpy(state->response.data.name.name, gr->gr_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2GID; + fstrcpy(request.data.groupname, name); + do_async(mem_ctx, idmap_child(), &request, name2gid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + /* Ensure null termination */ + state->request.data.groupname + [sizeof(state->request.data.groupname)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, + state->request.data.groupname)); + + gr = getgrnam(state->request.data.groupname); + if (gr == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.gid = gr->gr_gid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} +#endif /* not used */ + +/* The following uid2sid/gid2sid functions has been contributed by + * Keith Reynolds */ + +static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2SID; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: uid to sid %lu\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.uid)); + + /* Find sid for this uid and return it, possibly ask the slow remote idmap */ + result = idmap_uid_to_sid(&sid, state->request.data.uid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_USER; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2SID; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: gid %lu to sid\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.gid)); + + /* Find sid for this gid and return it, possibly ask the slow remote idmap */ + result = idmap_gid_to_sid(&sid, state->request.data.gid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + DEBUG(10, ("[%5lu]: retrieved sid: %s\n", + (unsigned long)state->pid, + state->response.data.sid.sid)); + state->response.data.sid.type = SID_NAME_DOM_GRP; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = + (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger a map dump\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap dump maps returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_DUMP_MAPS; + request.extra_data.data = (char *)data; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); + + idmap_dump_maps((char *)state->request.extra_data.data); + + return WINBINDD_OK; +} -- cgit From f3581f319fee956c3d8302eed15ec3fdfa948ec4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:13:36 +0000 Subject: r25569: move more idmap stuff into winbindd_idmap.c metze (This used to be commit 953229f040580071f6ee09413f67f7edd3227728) --- source3/winbindd/winbindd_idmap.c | 12 ++++++++++++ source3/winbindd/winbindd_sid.c | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 3ae88c4c5d..608948787e 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -37,6 +37,18 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +static struct winbindd_child static_idmap_child; + +void init_idmap_child(void) +{ + setup_domain_child(NULL, &static_idmap_child, "idmap"); +} + +struct winbindd_child *idmap_child(void) +{ + return &static_idmap_child; +} + static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 48e84d35e5..b607db2b19 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -152,18 +152,6 @@ void winbindd_lookuprids(struct winbindd_cli_state *state) sendto_domain(state, domain); } -static struct winbindd_child static_idmap_child; - -void init_idmap_child(void) -{ - setup_domain_child(NULL, &static_idmap_child, "idmap"); -} - -struct winbindd_child *idmap_child(void) -{ - return &static_idmap_child; -} - /* Convert a sid to a uid. We assume we only have one rid attached to the sid. */ -- cgit From 971cc997debc82a86a653757d0fb16c8d748345f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:15:28 +0000 Subject: r25570: move code of the locator child into its own file metze (This used to be commit 2dbc168e543b84d05b85bc0a44aa8fc10adc4511) --- source3/winbindd/winbindd_locator.c | 90 +++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_misc.c | 64 -------------------------- 2 files changed, 90 insertions(+), 64 deletions(-) create mode 100644 source3/winbindd/winbindd_locator.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c new file mode 100644 index 0000000000..52b6dc06f1 --- /dev/null +++ b/source3/winbindd/winbindd_locator.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - miscellaneous other functions + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Bartlett 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static struct winbindd_child static_locator_child; + +void init_locator_child(void) +{ + setup_domain_child(NULL, &static_locator_child, "locator"); +} + +struct winbindd_child *locator_child(void) +{ + return &static_locator_child; +} + +void winbindd_dsgetdcname(struct winbindd_cli_state *state) +{ + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + sendto_child(state, locator_child()); +} + +enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + const char *dc = NULL; + + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, + NULL, NULL, state->request.flags, &info); + + if (!NT_STATUS_IS_OK(result)) { + return WINBINDD_ERROR; + } + + if (info->domain_controller_address) { + dc = info->domain_controller_address; + if ((dc[0] == '\\') && (dc[1] == '\\')) { + dc += 2; + } + } + + if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { + dc = info->domain_controller_name; + } + + if (!dc || !*dc) { + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.dc_name, dc); + + return WINBINDD_OK; +} diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 5513e1790b..987926e398 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -289,70 +289,6 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, return WINBINDD_OK; } -static struct winbindd_child static_locator_child; - -void init_locator_child(void) -{ - setup_domain_child(NULL, &static_locator_child, "locator"); -} - -struct winbindd_child *locator_child(void) -{ - return &static_locator_child; -} - -void winbindd_dsgetdcname(struct winbindd_cli_state *state) -{ - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - sendto_child(state, locator_child()); -} - -enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - NTSTATUS result; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; - const char *dc = NULL; - - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, - NULL, NULL, state->request.flags, &info); - - if (!NT_STATUS_IS_OK(result)) { - return WINBINDD_ERROR; - } - - if (info->domain_controller_address) { - dc = info->domain_controller_address; - if ((dc[0] == '\\') && (dc[1] == '\\')) { - dc += 2; - } - } - - if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { - dc = info->domain_controller_name; - } - - if (!dc || !*dc) { - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.dc_name, dc); - - return WINBINDD_OK; -} - - struct sequence_state { TALLOC_CTX *mem_ctx; struct winbindd_cli_state *cli_state; -- cgit From 3c3b9afe7f229a69d051db8a08ece6ec9349e0a0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 12:25:57 +0000 Subject: r25571: split up child_dispatch_table into domain, idmap and locator tables metze (This used to be commit abbb36a37c1dba2218a6c7ec31739eba5f250127) --- source3/winbindd/winbindd.h | 13 ++++++++++++ source3/winbindd/winbindd_dual.c | 40 +++++++++---------------------------- source3/winbindd/winbindd_idmap.c | 30 +++++++++++++++++++++++++++- source3/winbindd/winbindd_locator.c | 18 ++++++++++++++--- source3/winbindd/winbindd_util.c | 27 +++++++++++++++++++------ 5 files changed, 87 insertions(+), 41 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index e7119c332f..d61254af4a 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -134,6 +134,17 @@ struct winbindd_async_request; /* Async child */ +struct winbindd_domain; + +struct winbindd_child_dispatch_table { + enum winbindd_cmd cmd; + enum winbindd_result (*fn)(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + const char *winbindd_cmd_name; +}; + +extern const struct winbindd_child_dispatch_table domain_dispatch_table[]; + struct winbindd_child { struct winbindd_child *next, *prev; @@ -144,6 +155,8 @@ struct winbindd_child { struct fd_event event; struct timed_event *lockout_policy_event; struct winbindd_async_request *requests; + + const struct winbindd_child_dispatch_table *table; }; /* Structures to hold per domain information */ diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index d9a42c31dc..7e53fbbbee 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -408,23 +408,14 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } +const struct winbindd_child_dispatch_table domain_dispatch_table[] = { -struct winbindd_child_dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -static struct winbindd_child_dispatch_table child_dispatch_table[] = { - { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, - { WINBINDD_DSGETDCNAME, winbindd_dual_dsgetdcname, "DSGETDCNAME" }, { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, @@ -432,23 +423,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = { { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, - { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, -#endif /* end DISABLED */ - { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, - { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, - { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, - { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, - { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, - { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, - { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, - { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, - { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, - { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, @@ -457,10 +432,11 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = { { WINBINDD_NUM_CMDS, NULL, "NONE" } }; -static void child_process_request(struct winbindd_domain *domain, +static void child_process_request(struct winbindd_child *child, struct winbindd_cli_state *state) { - struct winbindd_child_dispatch_table *table; + struct winbindd_domain *domain = child->domain; + const struct winbindd_child_dispatch_table *table = child->table; /* Free response data - we may be interrupted and receive another command before being able to send this data off. */ @@ -473,7 +449,7 @@ static void child_process_request(struct winbindd_domain *domain, /* Process command */ - for (table = child_dispatch_table; table->fn; table++) { + for (; table->fn; table++) { if (state->request.cmd == table->cmd) { DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name )); @@ -483,7 +459,7 @@ static void child_process_request(struct winbindd_domain *domain, } if (!table->fn) { - DEBUG(10,("process_request: unknown request fn number %d\n", + DEBUG(1 ,("child_process_request: unknown request fn number %d\n", (int)state->request.cmd )); state->response.result = WINBINDD_ERROR; } @@ -491,6 +467,7 @@ static void child_process_request(struct winbindd_domain *domain, void setup_domain_child(struct winbindd_domain *domain, struct winbindd_child *child, + const struct winbindd_child_dispatch_table *table, const char *explicit_logfile) { if (explicit_logfile != NULL) { @@ -505,6 +482,7 @@ void setup_domain_child(struct winbindd_domain *domain, } child->domain = domain; + child->table = table; } struct winbindd_child *children = NULL; @@ -1106,7 +1084,7 @@ static BOOL fork_domain_child(struct winbindd_child *child) ZERO_STRUCT(state.response); state.request.null_term = '\0'; - child_process_request(child->domain, &state); + child_process_request(child, &state); SAFE_FREE(state.request.extra_data.data); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 608948787e..f590813de3 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -37,11 +37,16 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +static const struct winbindd_child_dispatch_table idmap_dispatch_table[]; + static struct winbindd_child static_idmap_child; void init_idmap_child(void) { - setup_domain_child(NULL, &static_idmap_child, "idmap"); + setup_domain_child(NULL, + &static_idmap_child, + idmap_dispatch_table, + "idmap"); } struct winbindd_child *idmap_child(void) @@ -788,3 +793,26 @@ enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, return WINBINDD_OK; } + +static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { + + { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, + { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, +#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ + { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, +#endif /* end DISABLED */ + { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, + { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, + { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, + { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, + { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, + { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, + { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, + { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, + { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, + { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, + { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, + /* End of list */ + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 52b6dc06f1..ade2c1539b 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -26,11 +26,17 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND + +static const struct winbindd_child_dispatch_table locator_dispatch_table[]; + static struct winbindd_child static_locator_child; void init_locator_child(void) { - setup_domain_child(NULL, &static_locator_child, "locator"); + setup_domain_child(NULL, + &static_locator_child, + locator_dispatch_table, + "locator"); } struct winbindd_child *locator_child(void) @@ -49,8 +55,8 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state) sendto_child(state, locator_child()); } -enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, - struct winbindd_cli_state *state) +static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) { NTSTATUS result; struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; @@ -88,3 +94,9 @@ enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, return WINBINDD_OK; } + +static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { + { WINBINDD_DSGETDCNAME, dual_dsgetdcname, "DSGETDCNAME" }, + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 0e6ba1c043..49d20c527e 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -324,7 +324,10 @@ static void trustdom_recv(void *private_data, BOOL success) &cache_methods, &sid); if (domain) { - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } } p=q; @@ -693,7 +696,10 @@ BOOL init_domain_list(void) domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, &global_sid_Builtin); if (domain) { - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } /* Local SAM */ @@ -704,7 +710,10 @@ BOOL init_domain_list(void) if ( role != ROLE_DOMAIN_MEMBER ) { domain->primary = True; } - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } /* Add ourselves as the first entry. */ @@ -721,8 +730,11 @@ BOOL init_domain_list(void) &cache_methods, &our_sid); if (domain) { domain->primary = True; - setup_domain_child(domain, &domain->child, NULL); - + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); + /* Even in the parent winbindd we'll need to talk to the DC, so try and see if we can contact it. Theoretically this isn't neccessary @@ -767,7 +779,10 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid ) domain->internal = False; domain->online = True; - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); wcache_tdc_add_domain( domain ); -- cgit From 3ddbc3deb287a33b49d5898310b357007cffd68b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 8 Oct 2007 12:56:57 +0000 Subject: r25573: Add my (C) as well (This used to be commit a024e27e7136deb87aeed995348a1c494a850ce6) --- source3/winbindd/winbindd_idmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index f590813de3..e8b06104b2 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -5,6 +5,7 @@ Copyright (C) Volker Lendecke 2005 Copyright (C) Gerald Carter 2006 + Copyright (C) Simo Sorce 2007 The helpers always consist of three functions: -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/winbindd/winbindd.c | 131 +++--- source3/winbindd/winbindd.h | 21 - source3/winbindd/winbindd_async.c | 753 +++++++++++++++++++++++++++++++- source3/winbindd/winbindd_cm.c | 11 - source3/winbindd/winbindd_dual.c | 40 +- source3/winbindd/winbindd_idmap.c | 819 ----------------------------------- source3/winbindd/winbindd_locator.c | 102 ----- source3/winbindd/winbindd_misc.c | 64 +++ source3/winbindd/winbindd_pam.c | 78 +--- source3/winbindd/winbindd_sid.c | 12 + source3/winbindd/winbindd_sockinit.c | 126 ------ source3/winbindd/winbindd_util.c | 75 +++- 12 files changed, 973 insertions(+), 1259 deletions(-) delete mode 100644 source3/winbindd/winbindd_idmap.c delete mode 100644 source3/winbindd/winbindd_locator.c delete mode 100644 source3/winbindd/winbindd_sockinit.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 17915fb01b..81f07c4c8c 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -7,7 +7,6 @@ Copyright (C) Andrew Tridgell 2002 Copyright (C) Jelmer Vernooij 2003 Copyright (C) Volker Lendecke 2004 - Copyright (C) James Peach 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +29,7 @@ #define DBGC_CLASS DBGC_WINBIND BOOL opt_nocache = False; +static BOOL interactive = False; extern BOOL override_logfile; @@ -129,8 +129,13 @@ static void flush_caches(void) static void terminate(void) { + pstring path; + + /* Remove socket file */ + pstr_sprintf(path, "%s/%s", + get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME); + unlink(path); - winbindd_release_sockets(); idmap_close(); trustdom_cache_shutdown(); @@ -791,14 +796,23 @@ static BOOL remove_idle_client(void) simultaneous connections while remaining impervious to many denial of service attacks. */ -static int process_loop(int listen_sock, int listen_priv_sock) +static void process_loop(void) { struct winbindd_cli_state *state; struct fd_event *ev; fd_set r_fds, w_fds; - int maxfd, selret; + int maxfd, listen_sock, listen_priv_sock, selret; struct timeval timeout, ev_timeout; + /* Open Sockets here to get stuff going ASAP */ + listen_sock = open_winbindd_socket(); + listen_priv_sock = open_winbindd_priv_socket(); + + if (listen_sock == -1 || listen_priv_sock == -1) { + perror("open_winbind_socket"); + exit(1); + } + /* We'll be doing this a lot */ /* Handle messages */ @@ -963,58 +977,6 @@ static int process_loop(int listen_sock, int listen_priv_sock) winbind_child_died(pid); } } - - - return winbindd_num_clients(); -} - -static void winbindd_process_loop(enum smb_server_mode server_mode) -{ - int idle_timeout_sec; - struct timeval starttime; - int listen_public, listen_priv; - - errno = 0; - if (!winbindd_init_sockets(&listen_public, &listen_priv, - &idle_timeout_sec)) { - terminate(); - } - - starttime = timeval_current(); - - if (listen_public == -1 || listen_priv == -1) { - DEBUG(0, ("failed to open winbindd pipes: %s\n", - errno ? strerror(errno) : "unknown error")); - terminate(); - } - - for (;;) { - TALLOC_CTX *frame = talloc_stackframe(); - int clients = process_loop(listen_public, listen_priv); - - /* Don't bother figuring out the idle time if we won't be - * timing out anyway. - */ - if (idle_timeout_sec < 0) { - TALLOC_FREE(frame); - continue; - } - - if (clients == 0 && server_mode == SERVER_MODE_FOREGROUND) { - struct timeval now; - - now = timeval_current(); - if (timeval_elapsed2(&starttime, &now) > - (double)idle_timeout_sec) { - DEBUG(0, ("idle for %d secs, exitting\n", - idle_timeout_sec)); - terminate(); - } - } else { - starttime = timeval_current(); - } - TALLOC_FREE(frame); - } } /* Main function */ @@ -1022,18 +984,17 @@ static void winbindd_process_loop(enum smb_server_mode server_mode) int main(int argc, char **argv, char **envp) { pstring logfile; - BOOL log_stdout = False; - BOOL no_process_group = False; - - enum smb_server_mode server_mode = SERVER_MODE_DAEMON; - + static BOOL is_daemon = False; + static BOOL Fork = True; + static BOOL log_stdout = False; + static BOOL no_process_group = False; struct poptOption long_options[] = { POPT_AUTOHELP { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, - { "foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, "Daemon in foreground mode" }, + { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, { "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, - { "daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, "Become a daemon (default)" }, - { "interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, "Interactive mode" }, + { "daemon", 'D', POPT_ARG_NONE, NULL, 'D', "Become a daemon (default)" }, + { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, POPT_COMMON_SAMBA POPT_TABLEEND @@ -1072,6 +1033,15 @@ int main(int argc, char **argv, char **envp) while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { + /* Don't become a daemon */ + case 'D': + is_daemon = True; + break; + case 'i': + interactive = True; + log_stdout = True; + Fork = False; + break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); @@ -1080,15 +1050,16 @@ int main(int argc, char **argv, char **envp) } } - if (server_mode == SERVER_MODE_INTERACTIVE) { - log_stdout = True; - if (DEBUGLEVEL >= 9) { - talloc_enable_leak_report(); - } + if (is_daemon && interactive) { + d_fprintf(stderr,"\nERROR: " + "Option -i|--interactive is not allowed together with -D|--daemon\n\n"); + poptPrintUsage(pc, stderr, 0); + exit(1); } - if (log_stdout && server_mode == SERVER_MODE_DAEMON) { - printf("Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"); + if (log_stdout && Fork) { + d_fprintf(stderr, "\nERROR: " + "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n"); poptPrintUsage(pc, stderr, 0); exit(1); } @@ -1161,12 +1132,8 @@ int main(int argc, char **argv, char **envp) CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ CatchSignal(SIGHUP, sighup_handler); - if (server_mode == SERVER_MODE_DAEMON) { - DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(True, no_process_group); - } else if (server_mode == SERVER_MODE_FOREGROUND) { - become_daemon(False, no_process_group); - } + if (!interactive) + become_daemon(Fork, no_process_group); pidfile_create("winbindd"); @@ -1189,9 +1156,8 @@ int main(int argc, char **argv, char **envp) * If we're interactive we want to set our own process group for * signal management. */ - if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { + if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); - } #endif TimeInit(); @@ -1248,7 +1214,12 @@ int main(int argc, char **argv, char **envp) smb_nscd_flush_group_cache(); /* Loop waiting for requests */ - winbindd_process_loop(server_mode); + + while (1) { + TALLOC_CTX *frame = talloc_stackframe(); + process_loop(); + TALLOC_FREE(frame); + } return 0; } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index d61254af4a..ebede0f007 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -134,17 +134,6 @@ struct winbindd_async_request; /* Async child */ -struct winbindd_domain; - -struct winbindd_child_dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -extern const struct winbindd_child_dispatch_table domain_dispatch_table[]; - struct winbindd_child { struct winbindd_child *next, *prev; @@ -155,8 +144,6 @@ struct winbindd_child { struct fd_event event; struct timed_event *lockout_policy_event; struct winbindd_async_request *requests; - - const struct winbindd_child_dispatch_table *table; }; /* Structures to hold per domain information */ @@ -178,14 +165,6 @@ struct winbindd_domain { time_t startup_time; /* When we set "startup" true. */ BOOL startup; /* are we in the first 30 seconds after startup_time ? */ - BOOL can_do_samlogon_ex; /* Due to the lack of finer control what type - * of DC we have, let us try to do a - * credential-chain less samlogon_ex call - * with AD and schannel. If this fails with - * DCERPC_FAULT_OP_RNG_ERROR, then set this - * to False. This variable is around so that - * we don't have to try _ex every time. */ - /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 00c20529c5..5d31ff0a41 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -57,12 +57,12 @@ static void do_async_recv(void *private_data, BOOL success) state->c, state->private_data); } -void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, - const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data), - void *c, void *private_data) +static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) { struct do_async_state *state; @@ -111,6 +111,581 @@ void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, &state->response, do_async_recv, state); } +static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_mapping\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_mapping returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_MAPPING; + request.data.dual_idmapset.id = map->xid.id; + request.data.dual_idmapset.type = map->xid.type; + sid_to_string(request.data.dual_idmapset.sid, map->sid); + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct id_map map; + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); + + if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) + return WINBINDD_ERROR; + + map.sid = &sid; + map.xid.id = state->request.data.dual_idmapset.id; + map.xid.type = state->request.data.dual_idmapset.type; + map.status = ID_MAPPED; + + result = idmap_set_mapping(&map); + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_hwm\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_hwm returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_HWM; + request.data.dual_idmapset.id = xid->id; + request.data.dual_idmapset.type = xid->type; + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); + + xid.id = state->request.data.dual_idmapset.id; + xid.type = state->request.data.dual_idmapset.type; + + switch (xid.type) { + case ID_TYPE_UID: + result = idmap_set_uid_hwm(&xid); + break; + case ID_TYPE_GID: + result = idmap_set_gid_hwm(&xid); + break; + default: + return WINBINDD_ERROR; + } + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, void *, int) = + (void (*)(void *, BOOL, void *, int))c; + + if (!success) { + DEBUG(5, ("Could not trigger sids2xids\n")); + cont(private_data, False, NULL, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sids2xids returned an error\n")); + cont(private_data, False, NULL, 0); + return; + } + + cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); +} + +void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, + void (*cont)(void *private_data, BOOL success, void *data, int len), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SIDS2XIDS; + request.extra_data.data = (char *)sids; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID *sids; + struct unixid *xids; + struct id_map **ids; + NTSTATUS result; + int num, i; + + DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); + + if (state->request.extra_len == 0) { + DEBUG(0, ("Invalid buffer size!\n")); + return WINBINDD_ERROR; + } + + sids = (DOM_SID *)state->request.extra_data.data; + num = state->request.extra_len / sizeof(DOM_SID); + + ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); + if ( ! ids) { + DEBUG(0, ("Out of memory!\n")); + return WINBINDD_ERROR; + } + for (i = 0; i < num; i++) { + ids[i] = TALLOC_P(ids, struct id_map); + if ( ! ids[i]) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + ids[i]->sid = &sids[i]; + } + + result = idmap_sids_to_unixids(ids); + + if (NT_STATUS_IS_OK(result)) { + + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } + } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; + + } else { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; + } + + talloc_free(ids); + return WINBINDD_OK; +} + +static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} + +void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2UID; + sid_to_string(request.data.dual_sid2id.sid, sid); + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2NAME; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, uid2name_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + pw = getpwuid(state->request.data.uid); + if (pw == NULL) { + DEBUG(5, ("User %lu not found\n", + (unsigned long)state->request.data.uid)); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.name.name, pw->pw_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2UID; + fstrcpy(request.data.username, name); + do_async(mem_ctx, idmap_child(), &request, name2uid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + /* Ensure null termination */ + state->request.data.username + [sizeof(state->request.data.username)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, + state->request.data.username)); + + pw = getpwnam(state->request.data.username); + if (pw == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.uid = pw->pw_uid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} +#endif /* not used */ + +static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} + +void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, BOOL success, gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2GID; + sid_to_string(request.data.dual_sid2id.sid, sid); + + DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", + request.data.dual_sid2id.sid)); + + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find gid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_gid(&sid, &state->response.data.gid); + + DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2NAME; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, gid2name_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + gr = getgrgid(state->request.data.gid); + if (gr == NULL) + return WINBINDD_ERROR; + + fstrcpy(state->response.data.name.name, gr->gr_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, BOOL success, + gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2GID; + fstrcpy(request.data.groupname, name); + do_async(mem_ctx, idmap_child(), &request, name2gid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + /* Ensure null termination */ + state->request.data.groupname + [sizeof(state->request.data.groupname)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, + state->request.data.groupname)); + + gr = getgrnam(state->request.data.groupname); + if (gr == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.gid = gr->gr_gid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} +#endif /* not used */ + struct lookupsid_state { DOM_SID sid; void *caller_private_data; @@ -952,3 +1527,169 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, do_async_domain(mem_ctx, domain, &request, query_user_recv, (void *)cont, private_data); } + +/* The following uid2sid/gid2sid functions has been contributed by + * Keith Reynolds */ + +static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2SID; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: uid to sid %lu\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.uid)); + + /* Find sid for this uid and return it, possibly ask the slow remote idmap */ + result = idmap_uid_to_sid(&sid, state->request.data.uid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_USER; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ, const char *sid) = + (void (*)(void *, BOOL, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, BOOL success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2SID; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: gid %lu to sid\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.gid)); + + /* Find sid for this gid and return it, possibly ask the slow remote idmap */ + result = idmap_gid_to_sid(&sid, state->request.data.gid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + DEBUG(10, ("[%5lu]: retrieved sid: %s\n", + (unsigned long)state->pid, + state->response.data.sid.sid)); + state->response.data.sid.type = SID_NAME_DOM_GRP; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, BOOL succ) = + (void (*)(void *, BOOL))c; + + if (!success) { + DEBUG(5, ("Could not trigger a map dump\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap dump maps returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, + void (*cont)(void *private_data, BOOL success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_DUMP_MAPS; + request.extra_data.data = (char *)data; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); + + idmap_dump_maps((char *)state->request.extra_data.data); + + return WINBINDD_OK; +} + diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 9ffb3dfb23..e12b13cbbd 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2224,12 +2224,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - - /* - * NetSamLogonEx only works for schannel - */ - domain->can_do_samlogon_ex = False; - /* We're done - just keep the existing connection to NETLOGON * open */ conn->netlogon_pipe = netlogon_pipe; @@ -2261,11 +2255,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; } - /* - * Try NetSamLogonEx for AD domains - */ - domain->can_do_samlogon_ex = domain->active_directory; - *cli = conn->netlogon_pipe; return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 7e53fbbbee..d9a42c31dc 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -408,14 +408,23 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } -const struct winbindd_child_dispatch_table domain_dispatch_table[] = { +struct winbindd_child_dispatch_table { + enum winbindd_cmd cmd; + enum winbindd_result (*fn)(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + const char *winbindd_cmd_name; +}; + +static struct winbindd_child_dispatch_table child_dispatch_table[] = { + { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, + { WINBINDD_DSGETDCNAME, winbindd_dual_dsgetdcname, "DSGETDCNAME" }, { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, @@ -423,7 +432,23 @@ const struct winbindd_child_dispatch_table domain_dispatch_table[] = { { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, + { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, + { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, +#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ + { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, +#endif /* end DISABLED */ + { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, + { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, + { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, + { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, + { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, + { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, + { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, + { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, + { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, + { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, + { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, @@ -432,11 +457,10 @@ const struct winbindd_child_dispatch_table domain_dispatch_table[] = { { WINBINDD_NUM_CMDS, NULL, "NONE" } }; -static void child_process_request(struct winbindd_child *child, +static void child_process_request(struct winbindd_domain *domain, struct winbindd_cli_state *state) { - struct winbindd_domain *domain = child->domain; - const struct winbindd_child_dispatch_table *table = child->table; + struct winbindd_child_dispatch_table *table; /* Free response data - we may be interrupted and receive another command before being able to send this data off. */ @@ -449,7 +473,7 @@ static void child_process_request(struct winbindd_child *child, /* Process command */ - for (; table->fn; table++) { + for (table = child_dispatch_table; table->fn; table++) { if (state->request.cmd == table->cmd) { DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name )); @@ -459,7 +483,7 @@ static void child_process_request(struct winbindd_child *child, } if (!table->fn) { - DEBUG(1 ,("child_process_request: unknown request fn number %d\n", + DEBUG(10,("process_request: unknown request fn number %d\n", (int)state->request.cmd )); state->response.result = WINBINDD_ERROR; } @@ -467,7 +491,6 @@ static void child_process_request(struct winbindd_child *child, void setup_domain_child(struct winbindd_domain *domain, struct winbindd_child *child, - const struct winbindd_child_dispatch_table *table, const char *explicit_logfile) { if (explicit_logfile != NULL) { @@ -482,7 +505,6 @@ void setup_domain_child(struct winbindd_domain *domain, } child->domain = domain; - child->table = table; } struct winbindd_child *children = NULL; @@ -1084,7 +1106,7 @@ static BOOL fork_domain_child(struct winbindd_child *child) ZERO_STRUCT(state.response); state.request.null_term = '\0'; - child_process_request(child, &state); + child_process_request(child->domain, &state); SAFE_FREE(state.request.extra_data.data); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c deleted file mode 100644 index e8b06104b2..0000000000 --- a/source3/winbindd/winbindd_idmap.c +++ /dev/null @@ -1,819 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Async helpers for blocking functions - - Copyright (C) Volker Lendecke 2005 - Copyright (C) Gerald Carter 2006 - Copyright (C) Simo Sorce 2007 - - The helpers always consist of three functions: - - * A request setup function that takes the necessary parameters together - with a continuation function that is to be called upon completion - - * A private continuation function that is internal only. This is to be - called by the lower-level functions in do_async(). Its only task is to - properly call the continuation function named above. - - * A worker function that is called inside the appropriate child process. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -static const struct winbindd_child_dispatch_table idmap_dispatch_table[]; - -static struct winbindd_child static_idmap_child; - -void init_idmap_child(void) -{ - setup_domain_child(NULL, - &static_idmap_child, - idmap_dispatch_table, - "idmap"); -} - -struct winbindd_child *idmap_child(void) -{ - return &static_idmap_child; -} - -static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_mapping\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_mapping returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_MAPPING; - request.data.dual_idmapset.id = map->xid.id; - request.data.dual_idmapset.type = map->xid.type; - sid_to_string(request.data.dual_idmapset.sid, map->sid); - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct id_map map; - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); - - if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) - return WINBINDD_ERROR; - - map.sid = &sid; - map.xid.id = state->request.data.dual_idmapset.id; - map.xid.type = state->request.data.dual_idmapset.type; - map.status = ID_MAPPED; - - result = idmap_set_mapping(&map); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_hwm\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_hwm returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_HWM; - request.data.dual_idmapset.id = xid->id; - request.data.dual_idmapset.type = xid->type; - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct unixid xid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); - - xid.id = state->request.data.dual_idmapset.id; - xid.type = state->request.data.dual_idmapset.type; - - switch (xid.type) { - case ID_TYPE_UID: - result = idmap_set_uid_hwm(&xid); - break; - case ID_TYPE_GID: - result = idmap_set_gid_hwm(&xid); - break; - default: - return WINBINDD_ERROR; - } - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, void *, int) = - (void (*)(void *, BOOL, void *, int))c; - - if (!success) { - DEBUG(5, ("Could not trigger sids2xids\n")); - cont(private_data, False, NULL, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sids2xids returned an error\n")); - cont(private_data, False, NULL, 0); - return; - } - - cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); -} - -void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, - void (*cont)(void *private_data, BOOL success, void *data, int len), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SIDS2XIDS; - request.extra_data.data = (char *)sids; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID *sids; - struct unixid *xids; - struct id_map **ids; - NTSTATUS result; - int num, i; - - DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); - - if (state->request.extra_len == 0) { - DEBUG(0, ("Invalid buffer size!\n")); - return WINBINDD_ERROR; - } - - sids = (DOM_SID *)state->request.extra_data.data; - num = state->request.extra_len / sizeof(DOM_SID); - - ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); - if ( ! ids) { - DEBUG(0, ("Out of memory!\n")); - return WINBINDD_ERROR; - } - for (i = 0; i < num; i++) { - ids[i] = TALLOC_P(ids, struct id_map); - if ( ! ids[i]) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - ids[i]->sid = &sids[i]; - } - - result = idmap_sids_to_unixids(ids); - - if (NT_STATUS_IS_OK(result)) { - - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; - } - } - - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; - - } else { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); - talloc_free(ids); - return WINBINDD_ERROR; - } - - talloc_free(ids); - return WINBINDD_OK; -} - -static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} - -void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2UID; - sid_to_string(request.data.dual_sid2id.sid, sid); - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find uid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2NAME; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, uid2name_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.uid)); - - pw = getpwuid(state->request.data.uid); - if (pw == NULL) { - DEBUG(5, ("User %lu not found\n", - (unsigned long)state->request.data.uid)); - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.name, pw->pw_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, - uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2UID; - fstrcpy(request.data.username, name); - do_async(mem_ctx, idmap_child(), &request, name2uid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - /* Ensure null termination */ - state->request.data.username - [sizeof(state->request.data.username)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, - state->request.data.username)); - - pw = getpwnam(state->request.data.username); - if (pw == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.uid = pw->pw_uid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} -#endif /* not used */ - -static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} - -void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2GID; - sid_to_string(request.data.dual_sid2id.sid, sid); - - DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", - request.data.dual_sid2id.sid)); - - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find gid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_gid(&sid, &state->response.data.gid); - - DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2NAME; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, gid2name_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.gid)); - - gr = getgrgid(state->request.data.gid); - if (gr == NULL) - return WINBINDD_ERROR; - - fstrcpy(state->response.data.name.name, gr->gr_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, - gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2GID; - fstrcpy(request.data.groupname, name); - do_async(mem_ctx, idmap_child(), &request, name2gid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - /* Ensure null termination */ - state->request.data.groupname - [sizeof(state->request.data.groupname)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, - state->request.data.groupname)); - - gr = getgrnam(state->request.data.groupname); - if (gr == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.gid = gr->gr_gid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} -#endif /* not used */ - -/* The following uid2sid/gid2sid functions has been contributed by - * Keith Reynolds */ - -static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2SID; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: uid to sid %lu\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.uid)); - - /* Find sid for this uid and return it, possibly ask the slow remote idmap */ - result = idmap_uid_to_sid(&sid, state->request.data.uid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_USER; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2SID; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: gid %lu to sid\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.gid)); - - /* Find sid for this gid and return it, possibly ask the slow remote idmap */ - result = idmap_gid_to_sid(&sid, state->request.data.gid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - DEBUG(10, ("[%5lu]: retrieved sid: %s\n", - (unsigned long)state->pid, - state->response.data.sid.sid)); - state->response.data.sid.type = SID_NAME_DOM_GRP; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, BOOL succ) = - (void (*)(void *, BOOL))c; - - if (!success) { - DEBUG(5, ("Could not trigger a map dump\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap dump maps returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, - void (*cont)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_DUMP_MAPS; - request.extra_data.data = (char *)data; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); - - idmap_dump_maps((char *)state->request.extra_data.data); - - return WINBINDD_OK; -} - -static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { - - { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, - { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, -#endif /* end DISABLED */ - { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, - { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, - { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, - { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, - { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, - { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, - { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, - { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, - { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, - { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } -}; diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c deleted file mode 100644 index ade2c1539b..0000000000 --- a/source3/winbindd/winbindd_locator.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - miscellaneous other functions - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Bartlett 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - - -static const struct winbindd_child_dispatch_table locator_dispatch_table[]; - -static struct winbindd_child static_locator_child; - -void init_locator_child(void) -{ - setup_domain_child(NULL, - &static_locator_child, - locator_dispatch_table, - "locator"); -} - -struct winbindd_child *locator_child(void) -{ - return &static_locator_child; -} - -void winbindd_dsgetdcname(struct winbindd_cli_state *state) -{ - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - sendto_child(state, locator_child()); -} - -static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - NTSTATUS result; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; - const char *dc = NULL; - - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, - NULL, NULL, state->request.flags, &info); - - if (!NT_STATUS_IS_OK(result)) { - return WINBINDD_ERROR; - } - - if (info->domain_controller_address) { - dc = info->domain_controller_address; - if ((dc[0] == '\\') && (dc[1] == '\\')) { - dc += 2; - } - } - - if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { - dc = info->domain_controller_name; - } - - if (!dc || !*dc) { - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.dc_name, dc); - - return WINBINDD_OK; -} - -static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { - { WINBINDD_DSGETDCNAME, dual_dsgetdcname, "DSGETDCNAME" }, - - { WINBINDD_NUM_CMDS, NULL, "NONE" } -}; diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 987926e398..5513e1790b 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -289,6 +289,70 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, return WINBINDD_OK; } +static struct winbindd_child static_locator_child; + +void init_locator_child(void) +{ + setup_domain_child(NULL, &static_locator_child, "locator"); +} + +struct winbindd_child *locator_child(void) +{ + return &static_locator_child; +} + +void winbindd_dsgetdcname(struct winbindd_cli_state *state) +{ + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + sendto_child(state, locator_child()); +} + +enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + const char *dc = NULL; + + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, + NULL, NULL, state->request.flags, &info); + + if (!NT_STATUS_IS_OK(result)) { + return WINBINDD_ERROR; + } + + if (info->domain_controller_address) { + dc = info->domain_controller_address; + if ((dc[0] == '\\') && (dc[1] == '\\')) { + dc += 2; + } + } + + if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { + dc = info->domain_controller_name; + } + + if (!dc || !*dc) { + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.dc_name, dc); + + return WINBINDD_OK; +} + + struct sequence_state { TALLOC_CTX *mem_ctx; struct winbindd_cli_state *cli_state; diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f823e1d7b2..78128521c4 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1261,17 +1261,6 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client - *cli, TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - NET_USER_INFO_3 *info3); ZERO_STRUCTP(my_info3); retry = False; @@ -1283,11 +1272,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - logon_fn = contact_domain->can_do_samlogon_ex - ? rpccli_netlogon_sam_network_logon_ex - : rpccli_netlogon_sam_network_logon; - - result = logon_fn(netlogon_pipe, + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, state->mem_ctx, 0, contact_domain->dcname, /* server name */ @@ -1298,16 +1283,6 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, lm_resp, nt_resp, my_info3); - - if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) - && contact_domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; - continue; - } - attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -1803,18 +1778,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client - *cli, TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - NET_USER_INFO_3 *info3); - ZERO_STRUCT(info3); retry = False; @@ -1827,32 +1790,19 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - logon_fn = contact_domain->can_do_samlogon_ex - ? rpccli_netlogon_sam_network_logon_ex - : rpccli_netlogon_sam_network_logon; - - result = logon_fn(netlogon_pipe, - state->mem_ctx, - state->request.data.auth_crap.logon_parameters, - contact_domain->dcname, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, - &info3); - - if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) - && contact_domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; - continue; - } - + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + attempts += 1; /* We have to try a second time as cm_connect_netlogon diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index b607db2b19..48e84d35e5 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -152,6 +152,18 @@ void winbindd_lookuprids(struct winbindd_cli_state *state) sendto_domain(state, domain); } +static struct winbindd_child static_idmap_child; + +void init_idmap_child(void) +{ + setup_domain_child(NULL, &static_idmap_child, "idmap"); +} + +struct winbindd_child *idmap_child(void) +{ + return &static_idmap_child; +} + /* Convert a sid to a uid. We assume we only have one rid attached to the sid. */ diff --git a/source3/winbindd/winbindd_sockinit.c b/source3/winbindd/winbindd_sockinit.c deleted file mode 100644 index 886b67fb47..0000000000 --- a/source3/winbindd/winbindd_sockinit.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Copyright (C) Tim Potter 2000-2001 - Copyright (C) 2001 by Martin Pool - Copyright (C) James Peach 2007 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "winbindd.h" -#include "smb_launchd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Open the winbindd socket */ - -static int _winbindd_socket = -1; -static int _winbindd_priv_socket = -1; -static BOOL unlink_winbindd_socket = True; - -static int open_winbindd_socket(void) -{ - if (_winbindd_socket == -1) { - _winbindd_socket = create_pipe_sock( - get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755); - DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", - _winbindd_socket)); - } - - return _winbindd_socket; -} - -static int open_winbindd_priv_socket(void) -{ - if (_winbindd_priv_socket == -1) { - _winbindd_priv_socket = create_pipe_sock( - get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750); - DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n", - _winbindd_priv_socket)); - } - - return _winbindd_priv_socket; -} - -/* Close the winbindd socket */ - -static void close_winbindd_socket(void) -{ - if (_winbindd_socket != -1) { - DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", - _winbindd_socket)); - close(_winbindd_socket); - _winbindd_socket = -1; - } - if (_winbindd_priv_socket != -1) { - DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", - _winbindd_priv_socket)); - close(_winbindd_priv_socket); - _winbindd_priv_socket = -1; - } -} - -BOOL winbindd_init_sockets(int *public_sock, int *priv_sock, - int *idle_timeout_sec) -{ - struct smb_launch_info linfo; - - if (smb_launchd_checkin_names(&linfo, "WinbindPublicPipe", - "WinbindPrivilegedPipe", NULL)) { - if (linfo.num_sockets != 2) { - DEBUG(0, ("invalid launchd configuration, " - "expected 2 sockets but got %d\n", - linfo.num_sockets)); - return False; - } - - *public_sock = _winbindd_socket = linfo.socket_list[0]; - *priv_sock = _winbindd_priv_socket = linfo.socket_list[1]; - *idle_timeout_sec = linfo.idle_timeout_secs; - - unlink_winbindd_socket = False; - - smb_launchd_checkout(&linfo); - return True; - } else { - *public_sock = open_winbindd_socket(); - *priv_sock = open_winbindd_priv_socket(); - *idle_timeout_sec = -1; - - if (*public_sock == -1 || *priv_sock == -1) { - DEBUG(0, ("failed to open winbindd pipes: %s\n", - errno ? strerror(errno) : "unknown error")); - return False; - } - - return True; - } -} - -void winbindd_release_sockets(void) -{ - pstring path; - - close_winbindd_socket(); - - /* Remove socket file */ - if (unlink_winbindd_socket) { - pstr_sprintf(path, "%s/%s", - get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME); - unlink(path); - } -} - diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 49d20c527e..c2fe09eead 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -35,6 +35,7 @@ extern struct winbindd_methods passdb_methods; * Winbind daemon for NT domain authentication nss module. **/ + /* The list of trusted domains. Note that the list can be deleted and recreated using the init_domain_list() function so pointers to individual winbindd_domain structures cannot be made. Keep a copy of @@ -324,10 +325,7 @@ static void trustdom_recv(void *private_data, BOOL success) &cache_methods, &sid); if (domain) { - setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + setup_domain_child(domain, &domain->child, NULL); } } p=q; @@ -696,10 +694,7 @@ BOOL init_domain_list(void) domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, &global_sid_Builtin); if (domain) { - setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + setup_domain_child(domain, &domain->child, NULL); } /* Local SAM */ @@ -710,10 +705,7 @@ BOOL init_domain_list(void) if ( role != ROLE_DOMAIN_MEMBER ) { domain->primary = True; } - setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + setup_domain_child(domain, &domain->child, NULL); } /* Add ourselves as the first entry. */ @@ -730,11 +722,8 @@ BOOL init_domain_list(void) &cache_methods, &our_sid); if (domain) { domain->primary = True; - setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); - + setup_domain_child(domain, &domain->child, NULL); + /* Even in the parent winbindd we'll need to talk to the DC, so try and see if we can contact it. Theoretically this isn't neccessary @@ -779,10 +768,7 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid ) domain->internal = False; domain->online = True; - setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + setup_domain_child(domain, &domain->child, NULL); wcache_tdc_add_domain( domain ); @@ -1179,6 +1165,53 @@ char *get_winbind_priv_pipe_dir(void) return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR); } +/* Open the winbindd socket */ + +static int _winbindd_socket = -1; +static int _winbindd_priv_socket = -1; + +int open_winbindd_socket(void) +{ + if (_winbindd_socket == -1) { + _winbindd_socket = create_pipe_sock( + get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755); + DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", + _winbindd_socket)); + } + + return _winbindd_socket; +} + +int open_winbindd_priv_socket(void) +{ + if (_winbindd_priv_socket == -1) { + _winbindd_priv_socket = create_pipe_sock( + get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750); + DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n", + _winbindd_priv_socket)); + } + + return _winbindd_priv_socket; +} + +/* Close the winbindd socket */ + +void close_winbindd_socket(void) +{ + if (_winbindd_socket != -1) { + DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", + _winbindd_socket)); + close(_winbindd_socket); + _winbindd_socket = -1; + } + if (_winbindd_priv_socket != -1) { + DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", + _winbindd_priv_socket)); + close(_winbindd_priv_socket); + _winbindd_priv_socket = -1; + } +} + /* * Client list accessor functions */ -- cgit From 8e54530b52fd256137740107e9fdf000f00a7a30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Oct 2007 18:25:16 -0700 Subject: Add start of IPv6 implementation. Currently most of this is avoiding IPv6 in winbindd, but moves most of the socket functions that were wrongly in lib/util.c into lib/util_sock.c and provides generic IPv4/6 independent versions of most things. Still lots of work to do, but now I can see how I'll fix the access check code. Nasty part that remains is the name resolution code which is used to returning arrays of in_addr structs. Jeremy. (This used to be commit 3f6bd0e1ec5cc6670f3d08f76fc2cd94c9cd1a08) --- source3/winbindd/winbindd_cm.c | 4 ++-- source3/winbindd/winbindd_wins.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index e12b13cbbd..4ff9fce96f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1292,7 +1292,7 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx, *addr = addrs[fd_index]; - if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) { + if (*dcnames[fd_index] != '\0' && !is_ipaddress_v4(dcnames[fd_index])) { /* Ok, we've got a name for the DC */ fstrcpy(dcname, dcnames[fd_index]); return True; @@ -1336,7 +1336,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, saf_servername, domain->name )); /* convert an ip address to a name */ - if ( is_ipaddress( saf_servername ) ) { + if ( is_ipaddress_v4( saf_servername ) ) { fstring saf_name; struct in_addr ip; diff --git a/source3/winbindd/winbindd_wins.c b/source3/winbindd/winbindd_wins.c index f84dfdf2de..2ee6f69b66 100644 --- a/source3/winbindd/winbindd_wins.c +++ b/source3/winbindd/winbindd_wins.c @@ -118,7 +118,10 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) for (j=iface_count() - 1; j >= 0; j--) { - struct in_addr *bcast = iface_n_bcast(j); + const struct in_addr *bcast = iface_n_bcast_v4(j); + if (!bcast) { + continue; + } return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); if (return_ip) { break; -- cgit From 1a2d1628f7ae761457656bcf95a6f3d2eb630ff2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Oct 2007 18:47:41 -0700 Subject: Added missing is_ipaddress is_ipaddress_v4 not in initial port from old svn code. Jeremy. (This used to be commit 169c5857b7e7922fe3fffef997ced0e014e925a8) --- source3/winbindd/winbindd_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 5513e1790b..366f58a403 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -339,7 +339,7 @@ enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, } } - if ((!dc || !is_ipaddress(dc)) && info->domain_controller_name) { + if ((!dc || !is_ipaddress_v4(dc)) && info->domain_controller_name) { dc = info->domain_controller_name; } -- cgit From b111d543a580694f2909c75a280a42a27bbe6dd0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 16 Oct 2007 14:16:03 -0400 Subject: Fix default domains support using compat syntax. Without this fix idmap_rid can't be used with the compatible syntax. Includes fix to keep trusted domains working (This used to be commit 8c770c367c71d118651964fef63e2fd0fa4a05a5) --- source3/winbindd/idmap.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 2c7acc185c..022a2291a3 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -251,12 +251,6 @@ NTSTATUS idmap_close(void) return NT_STATUS_OK; } -/********************************************************************** - Initialise idmap cache and a remote backend (if configured). -**********************************************************************/ - -static const char *idmap_default_domain[] = { "default domain", NULL }; - /**************************************************************************** ****************************************************************************/ @@ -291,6 +285,7 @@ NTSTATUS idmap_init(void) char *compat_backend = NULL; char *compat_params = NULL; const char **dom_list = NULL; + const char *default_domain = NULL; char *alloc_backend = NULL; BOOL default_already_defined = False; BOOL pri_dom_is_in_list = False; @@ -331,10 +326,6 @@ NTSTATUS idmap_init(void) compat = 1; compat_backend = talloc_strdup(idmap_ctx, *compat_list); - if (compat_backend == NULL ) { - ret = NT_STATUS_NO_MEMORY; - goto done; - } /* strip any leading idmap_ prefix of */ if (strncmp(*compat_list, "idmap_", 6) == 0 ) { @@ -349,6 +340,11 @@ NTSTATUS idmap_init(void) *compat_list); } + if (compat_backend == NULL ) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + /* separate the backend and module arguements */ if ((p = strchr(compat_backend, ':')) != NULL) { *p = '\0'; @@ -365,7 +361,25 @@ NTSTATUS idmap_init(void) } if ( ! dom_list) { - dom_list = idmap_default_domain; + /* generate a list with our main domain */ + char ** dl; + + dl = talloc_array(idmap_ctx, char *, 2); + if (dl == NULL) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + dl[0] = talloc_strdup(dl, lp_workgroup()); + if (dl[0] == NULL) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + /* terminate */ + dl[1] = NULL; + + dom_list = dl; + default_domain = dl[0]; } /*************************** @@ -386,7 +400,8 @@ NTSTATUS idmap_init(void) continue; } - if (strequal(dom_list[i], lp_workgroup())) { + if ((dom_list[i] != default_domain) && + strequal(dom_list[i], lp_workgroup())) { pri_dom_is_in_list = True; } /* init domain */ @@ -407,10 +422,10 @@ NTSTATUS idmap_init(void) "default", False); if (dom->default_domain || - strequal(dom_list[i], idmap_default_domain[0])) { + (default_domain && strequal(dom_list[i], default_domain))) { /* make sure this is set even when we match - * idmap_default_domain[0] */ + * default_domain */ dom->default_domain = True; if (default_already_defined) { -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/winbindd/idmap.c | 8 +- source3/winbindd/idmap_ad.c | 2 +- source3/winbindd/idmap_cache.c | 2 +- source3/winbindd/idmap_ldap.c | 8 +- source3/winbindd/idmap_nss.c | 4 +- source3/winbindd/idmap_tdb.c | 14 +-- source3/winbindd/nss_info.c | 2 +- source3/winbindd/winbindd.c | 58 +++++------ source3/winbindd/winbindd.h | 44 ++++---- source3/winbindd/winbindd_ads.c | 2 +- source3/winbindd/winbindd_async.c | 168 +++++++++++++++--------------- source3/winbindd/winbindd_cache.c | 52 ++++----- source3/winbindd/winbindd_ccache_access.c | 4 +- source3/winbindd/winbindd_cm.c | 36 +++---- source3/winbindd/winbindd_cred_cache.c | 6 +- source3/winbindd/winbindd_dual.c | 32 +++--- source3/winbindd/winbindd_group.c | 46 ++++---- source3/winbindd/winbindd_misc.c | 10 +- source3/winbindd/winbindd_pam.c | 16 +-- source3/winbindd/winbindd_passdb.c | 2 +- source3/winbindd/winbindd_rpc.c | 2 +- source3/winbindd/winbindd_sid.c | 28 ++--- source3/winbindd/winbindd_user.c | 26 ++--- source3/winbindd/winbindd_util.c | 44 ++++---- 24 files changed, 308 insertions(+), 308 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 022a2291a3..9800e32505 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -45,7 +45,7 @@ struct idmap_cache_ctx; struct idmap_alloc_context { const char *params; struct idmap_alloc_methods *methods; - BOOL initialized; + bool initialized; }; static TALLOC_CTX *idmap_ctx = NULL; @@ -104,7 +104,7 @@ static struct idmap_alloc_methods *get_alloc_methods( return NULL; } -BOOL idmap_is_offline(void) +bool idmap_is_offline(void) { return ( lp_winbind_offline_logon() && get_global_winbindd_state_offline() ); @@ -287,8 +287,8 @@ NTSTATUS idmap_init(void) const char **dom_list = NULL; const char *default_domain = NULL; char *alloc_backend = NULL; - BOOL default_already_defined = False; - BOOL pri_dom_is_in_list = False; + bool default_already_defined = False; + bool pri_dom_is_in_list = False; int compat = 0; int i; diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index b2d41e436c..0d190eb4a1 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -58,7 +58,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) { ADS_STRUCT *ads; ADS_STATUS status; - BOOL local = False; + bool local = False; fstring dc_name; struct in_addr dc_ip; diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 4f01cb1392..6455f5ee69 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -301,7 +301,7 @@ failed: return NT_STATUS_INTERNAL_DB_CORRUPTION; } -BOOL idmap_cache_is_negative(const char *val) +bool idmap_cache_is_negative(const char *val) { if ( ! strcmp("IDMAP/NEGATIVE", val)) { return True; diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 9daf084ce1..a980d54bbe 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -39,7 +39,7 @@ struct idmap_ldap_context { char *suffix; char *user_dn; uint32_t filter_low_id, filter_high_id; /* Filter range */ - BOOL anon; + bool anon; }; struct idmap_ldap_alloc_context { @@ -78,7 +78,7 @@ static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx, char *secret = NULL; const char *tmp = NULL; char *user_dn = NULL; - BOOL anon = False; + bool anon = False; /* assume anonymous if we don't have a specified user */ @@ -897,7 +897,7 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, const char *gidNumber; const char **attr_list; char *filter = NULL; - BOOL multi = False; + bool multi = False; int idx = 0; int bidx = 0; int count; @@ -1127,7 +1127,7 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, const char *gidNumber; const char **attr_list; char *filter = NULL; - BOOL multi = False; + bool multi = False; int idx = 0; int bidx = 0; int count; diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index 5bb2389c93..fa9f2c9681 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -59,7 +59,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma struct group *gr; const char *name; enum lsa_SidType type; - BOOL ret; + bool ret; switch (ids[i]->xid.type) { case ID_TYPE_UID: @@ -150,7 +150,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma enum lsa_SidType type; const char *dom_name = NULL; const char *name = NULL; - BOOL ret; + bool ret; /* by default calls to winbindd are disabled the following call will not recurse so this is safe */ diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 97000689fa..881377bda6 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -54,7 +54,7 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state fstring keystr; fstring dom_name; TDB_DATA key2; - BOOL *failed = (BOOL *)state; + bool *failed = (bool *)state; DEBUG(10,("Converting %s\n", (const char *)key.dptr)); @@ -114,11 +114,11 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state Convert the idmap database from an older version. *****************************************************************************/ -static BOOL idmap_tdb_upgrade(const char *idmap_name) +static bool idmap_tdb_upgrade(const char *idmap_name) { int32 vers; - BOOL bigendianheader; - BOOL failed = False; + bool bigendianheader; + bool failed = False; TDB_CONTEXT *idmap_tdb; DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); @@ -205,7 +205,7 @@ static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx) SMB_STRUCT_STAT stbuf; char *tdbfile = NULL; int32 version; - BOOL tdb_is_new = False; + bool tdb_is_new = False; if (idmap_tdb_open_ref_count) { /* the tdb has already been opened */ idmap_tdb_open_ref_count++; @@ -284,7 +284,7 @@ done: /* NEVER use tdb_close() except for the conversion routines that are guaranteed * to run only when the database is opened the first time, always use this function. */ -BOOL idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx) +bool idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx) { if (tdbctx != idmap_tdb_common_ctx) { DEBUG(0, ("ERROR: Invalid tdb context!")); @@ -408,7 +408,7 @@ static NTSTATUS idmap_tdb_alloc_init( const char *params ) static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid) { - BOOL ret; + bool ret; const char *hwmkey; const char *hwmtype; uint32_t high_hwm; diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c index ea51e9dde8..daa3dd037d 100644 --- a/source3/winbindd/nss_info.c +++ b/source3/winbindd/nss_info.c @@ -82,7 +82,7 @@ static struct nss_function_entry *nss_get_backend(const char *name ) /******************************************************************** *******************************************************************/ -static BOOL parse_nss_parm( const char *config, char **backend, char **domain ) +static bool parse_nss_parm( const char *config, char **backend, char **domain ) { char *p; char *q; diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 81f07c4c8c..97bbe063ba 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -28,10 +28,10 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -BOOL opt_nocache = False; -static BOOL interactive = False; +bool opt_nocache = False; +static bool interactive = False; -extern BOOL override_logfile; +extern bool override_logfile; struct event_context *winbind_event_context(void) { @@ -56,9 +56,9 @@ struct messaging_context *winbind_messaging_context(void) /* Reload configuration */ -static BOOL reload_services_file(void) +static bool reload_services_file(void) { - BOOL ret; + bool ret; if (lp_loaded()) { pstring fname; @@ -153,7 +153,7 @@ static void terminate(void) exit(0); } -static BOOL do_sigterm; +static bool do_sigterm; static void termination_handler(int signum) { @@ -161,7 +161,7 @@ static void termination_handler(int signum) sys_select_signal(signum); } -static BOOL do_sigusr2; +static bool do_sigusr2; static void sigusr2_handler(int signum) { @@ -169,7 +169,7 @@ static void sigusr2_handler(int signum) sys_select_signal(SIGUSR2); } -static BOOL do_sighup; +static bool do_sighup; static void sighup_handler(int signum) { @@ -177,7 +177,7 @@ static void sighup_handler(int signum) sys_select_signal(SIGHUP); } -static BOOL do_sigchld; +static bool do_sigchld; static void sigchld_handler(int signum) { @@ -478,7 +478,7 @@ static void rw_callback(struct fd_event *event, int flags) */ void setup_async_read(struct fd_event *event, void *data, size_t length, - void (*finished)(void *private_data, BOOL success), + void (*finished)(void *private_data, bool success), void *private_data) { SMB_ASSERT(event->flags == 0); @@ -492,7 +492,7 @@ void setup_async_read(struct fd_event *event, void *data, size_t length, } void setup_async_write(struct fd_event *event, void *data, size_t length, - void (*finished)(void *private_data, BOOL success), + void (*finished)(void *private_data, bool success), void *private_data) { SMB_ASSERT(event->flags == 0); @@ -515,15 +515,15 @@ void setup_async_write(struct fd_event *event, void *data, size_t length, * to call request_finished which schedules sending the response. */ -static void request_len_recv(void *private_data, BOOL success); -static void request_recv(void *private_data, BOOL success); -static void request_main_recv(void *private_data, BOOL success); +static void request_len_recv(void *private_data, bool success); +static void request_recv(void *private_data, bool success); +static void request_main_recv(void *private_data, bool success); static void request_finished(struct winbindd_cli_state *state); -void request_finished_cont(void *private_data, BOOL success); -static void response_main_sent(void *private_data, BOOL success); -static void response_extra_sent(void *private_data, BOOL success); +void request_finished_cont(void *private_data, bool success); +static void response_main_sent(void *private_data, bool success); +static void response_extra_sent(void *private_data, bool success); -static void response_extra_sent(void *private_data, BOOL success) +static void response_extra_sent(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -545,7 +545,7 @@ static void response_extra_sent(void *private_data, BOOL success) request_len_recv, state); } -static void response_main_sent(void *private_data, BOOL success) +static void response_main_sent(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -591,7 +591,7 @@ void request_ok(struct winbindd_cli_state *state) request_finished(state); } -void request_finished_cont(void *private_data, BOOL success) +void request_finished_cont(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -602,7 +602,7 @@ void request_finished_cont(void *private_data, BOOL success) request_error(state); } -static void request_len_recv(void *private_data, BOOL success) +static void request_len_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -624,7 +624,7 @@ static void request_len_recv(void *private_data, BOOL success) request_main_recv, state); } -static void request_main_recv(void *private_data, BOOL success) +static void request_main_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -665,7 +665,7 @@ static void request_main_recv(void *private_data, BOOL success) state->request.extra_len, request_recv, state); } -static void request_recv(void *private_data, BOOL success) +static void request_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -680,7 +680,7 @@ static void request_recv(void *private_data, BOOL success) /* Process a new connection by adding it to the client connection list */ -static void new_connection(int listen_sock, BOOL privileged) +static void new_connection(int listen_sock, bool privileged) { struct sockaddr_un sunaddr; struct winbindd_cli_state *state; @@ -764,7 +764,7 @@ static void remove_client(struct winbindd_cli_state *state) /* Shutdown client connection which has been idle for the longest time */ -static BOOL remove_idle_client(void) +static bool remove_idle_client(void) { struct winbindd_cli_state *state, *remove_state = NULL; time_t last_access = 0; @@ -984,10 +984,10 @@ static void process_loop(void) int main(int argc, char **argv, char **envp) { pstring logfile; - static BOOL is_daemon = False; - static BOOL Fork = True; - static BOOL log_stdout = False; - static BOOL no_process_group = False; + static bool is_daemon = False; + static bool Fork = True; + static bool log_stdout = False; + static bool no_process_group = False; struct poptOption long_options[] = { POPT_AUTOHELP { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index ebede0f007..5fc083f7a9 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -49,13 +49,13 @@ struct fd_event { void (*handler)(struct fd_event *fde, int flags); void *data; size_t length, done; - void (*finished)(void *private_data, BOOL success); + void (*finished)(void *private_data, bool success); void *private_data; }; struct sid_ctr { DOM_SID *sid; - BOOL finished; + bool finished; const char *domain; const char *name; enum lsa_SidType type; @@ -66,17 +66,17 @@ struct winbindd_cli_state { int sock; /* Open socket from client */ struct fd_event fd_event; pid_t pid; /* pid of client */ - BOOL finished; /* Can delete from list */ - BOOL write_extra_data; /* Write extra_data field */ + bool finished; /* Can delete from list */ + bool write_extra_data; /* Write extra_data field */ time_t last_access; /* Time of last access (read or write) */ - BOOL privileged; /* Is the client 'privileged' */ + bool privileged; /* Is the client 'privileged' */ TALLOC_CTX *mem_ctx; /* memory per request */ struct winbindd_request request; /* Request from client */ struct winbindd_response response; /* Respose to client */ - BOOL getpwent_initialized; /* Has getpwent_state been + bool getpwent_initialized; /* Has getpwent_state been * initialized? */ - BOOL getgrent_initialized; /* Has getgrent_state been + bool getgrent_initialized; /* Has getgrent_state been * initialized? */ struct getent_state *getpwent_state; /* State for getpwent() */ struct getent_state *getgrent_state; /* State for getgrent() */ @@ -88,7 +88,7 @@ struct getent_state { struct getent_state *prev, *next; void *sam_entries; uint32 sam_entry_index, num_sam_entries; - BOOL got_sam_entries; + bool got_sam_entries; fstring domain_name; }; @@ -156,14 +156,14 @@ struct winbindd_domain { uint32 domain_flags; /* Domain flags from rpc_ds.h */ uint32 domain_type; /* Domain type from rpc_ds.h */ uint32 domain_trust_attribs; /* Trust attribs from rpc_ds.h */ - BOOL initialized; /* Did we already ask for the domain mode? */ - BOOL native_mode; /* is this a win2k domain in native mode ? */ - BOOL active_directory; /* is this a win2k active directory ? */ - BOOL primary; /* is this our primary domain ? */ - BOOL internal; /* BUILTIN and member SAM */ - BOOL online; /* is this domain available ? */ + bool initialized; /* Did we already ask for the domain mode? */ + bool native_mode; /* is this a win2k domain in native mode ? */ + bool active_directory; /* is this a win2k active directory ? */ + bool primary; /* is this our primary domain ? */ + bool internal; /* BUILTIN and member SAM */ + bool online; /* is this domain available ? */ time_t startup_time; /* When we set "startup" true. */ - BOOL startup; /* are we in the first 30 seconds after startup_time ? */ + bool startup; /* are we in the first 30 seconds after startup_time ? */ /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; @@ -209,7 +209,7 @@ struct winbindd_domain { struct winbindd_methods { /* does this backend provide a consistent view of the data? (ie. is the primary group always correct) */ - BOOL consistent; + bool consistent; /* get a list of users, returning a WINBIND_USERINFO for each one */ NTSTATUS (*query_user_list)(struct winbindd_domain *domain, @@ -318,16 +318,16 @@ typedef struct { /* Filled out by IDMAP backends */ struct winbindd_idmap_methods { /* Called when backend is first loaded */ - BOOL (*init)(void); + bool (*init)(void); - BOOL (*get_sid_from_uid)(uid_t uid, DOM_SID *sid); - BOOL (*get_sid_from_gid)(gid_t gid, DOM_SID *sid); + bool (*get_sid_from_uid)(uid_t uid, DOM_SID *sid); + bool (*get_sid_from_gid)(gid_t gid, DOM_SID *sid); - BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); - BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); + bool (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); + bool (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); /* Called when backend is unloaded */ - BOOL (*close)(void); + bool (*close)(void); /* Called to dump backend status */ void (*status)(void); }; diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 488967ed09..3f3f06e3fd 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -273,7 +273,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, LDAPMessage *msg = NULL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; const char *filter; - BOOL enum_dom_local_groups = False; + bool enum_dom_local_groups = False; *num_entries = 0; diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 5d31ff0a41..ae549d0fcf 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -42,13 +42,13 @@ struct do_async_state { struct winbindd_request request; struct winbindd_response response; void (*cont)(TALLOC_CTX *mem_ctx, - BOOL success, + bool success, struct winbindd_response *response, void *c, void *private_data); void *c, *private_data; }; -static void do_async_recv(void *private_data, BOOL success) +static void do_async_recv(void *private_data, bool success) { struct do_async_state *state = talloc_get_type_abort(private_data, struct do_async_state); @@ -59,7 +59,7 @@ static void do_async_recv(void *private_data, BOOL success) static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + void (*cont)(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data), void *c, void *private_data) @@ -86,7 +86,7 @@ static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + void (*cont)(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data), void *c, void *private_data) @@ -111,11 +111,11 @@ void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, &state->response, do_async_recv, state); } -static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; if (!success) { DEBUG(5, ("Could not trigger idmap_set_mapping\n")); @@ -133,7 +133,7 @@ static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, - void (*cont)(void *private_data, BOOL success), + void (*cont)(void *private_data, bool success), void *private_data) { struct winbindd_request request; @@ -168,11 +168,11 @@ enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; + void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; if (!success) { DEBUG(5, ("Could not trigger idmap_set_hwm\n")); @@ -190,7 +190,7 @@ static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, - void (*cont)(void *private_data, BOOL success), + void (*cont)(void *private_data, bool success), void *private_data) { struct winbindd_request request; @@ -227,12 +227,12 @@ enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, void *, int) = - (void (*)(void *, BOOL, void *, int))c; + void (*cont)(void *priv, bool succ, void *, int) = + (void (*)(void *, bool, void *, int))c; if (!success) { DEBUG(5, ("Could not trigger sids2xids\n")); @@ -250,7 +250,7 @@ static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, - void (*cont)(void *private_data, BOOL success, void *data, int len), + void (*cont)(void *private_data, bool success, void *data, int len), void *private_data) { struct winbindd_request request; @@ -329,12 +329,12 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, return WINBINDD_OK; } -static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; + void (*cont)(void *priv, bool succ, uid_t uid) = + (void (*)(void *, bool, uid_t))c; if (!success) { DEBUG(5, ("Could not trigger sid2uid\n")); @@ -352,7 +352,7 @@ static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, uid_t uid), + void (*cont)(void *private_data, bool success, uid_t uid), void *private_data) { struct winbindd_request request; @@ -386,12 +386,12 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, } #if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data); void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, const char *name), void *private_data) { @@ -424,12 +424,12 @@ enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, } #if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; + void (*cont)(void *priv, bool succ, const char *name) = + (void (*)(void *, bool, const char *))c; if (!success) { DEBUG(5, ("Could not trigger uid2name\n")); @@ -446,12 +446,12 @@ static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, cont(private_data, True, response->data.name.name); } -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data); static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, uid_t uid), void *private_data) { @@ -486,12 +486,12 @@ enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, } #if 0 /* not used */ -static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, uid_t uid) = - (void (*)(void *, BOOL, uid_t))c; + void (*cont)(void *priv, bool succ, uid_t uid) = + (void (*)(void *, bool, uid_t))c; if (!success) { DEBUG(5, ("Could not trigger name2uid\n")); @@ -509,12 +509,12 @@ static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, } #endif /* not used */ -static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; + void (*cont)(void *priv, bool succ, gid_t gid) = + (void (*)(void *, bool, gid_t))c; if (!success) { DEBUG(5, ("Could not trigger sid2gid\n")); @@ -532,7 +532,7 @@ static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, gid_t gid), + void (*cont)(void *private_data, bool success, gid_t gid), void *private_data) { struct winbindd_request request; @@ -571,12 +571,12 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void gid2name_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *name) = - (void (*)(void *, BOOL, const char *))c; + void (*cont)(void *priv, bool succ, const char *name) = + (void (*)(void *, bool, const char *))c; if (!success) { DEBUG(5, ("Could not trigger gid2name\n")); @@ -594,7 +594,7 @@ static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, const char *name), void *private_data) { @@ -623,12 +623,12 @@ enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, } #if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data); static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, gid_t gid), void *private_data) { @@ -663,12 +663,12 @@ enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, } #if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, gid_t gid) = - (void (*)(void *, BOOL, gid_t))c; + void (*cont)(void *priv, bool succ, gid_t gid) = + (void (*)(void *, bool, gid_t))c; if (!success) { DEBUG(5, ("Could not trigger name2gid\n")); @@ -692,13 +692,13 @@ struct lookupsid_state { }; -static void lookupsid_recv2(TALLOC_CTX *mem_ctx, BOOL success, +static void lookupsid_recv2(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *dom_name, + void (*cont)(void *priv, bool succ, const char *dom_name, const char *name, enum lsa_SidType type) = - (void (*)(void *, BOOL, const char *, const char *, + (void (*)(void *, bool, const char *, const char *, enum lsa_SidType))c; struct lookupsid_state *s = talloc_get_type_abort(private_data, struct lookupsid_state); @@ -720,13 +720,13 @@ static void lookupsid_recv2(TALLOC_CTX *mem_ctx, BOOL success, (enum lsa_SidType)response->data.name.type); } -static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void lookupsid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *dom_name, + void (*cont)(void *priv, bool succ, const char *dom_name, const char *name, enum lsa_SidType type) = - (void (*)(void *, BOOL, const char *, const char *, + (void (*)(void *, bool, const char *, const char *, enum lsa_SidType))c; struct lookupsid_state *s = talloc_get_type_abort(private_data, struct lookupsid_state); @@ -764,7 +764,7 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, const char *dom_name, const char *name, enum lsa_SidType type), @@ -850,13 +850,13 @@ struct lookupname_state { }; -static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, +static void lookupname_recv2(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, + void (*cont)(void *priv, bool succ, const DOM_SID *sid, enum lsa_SidType type) = - (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; + (void (*)(void *, bool, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; struct lookupname_state *s = talloc_get_type_abort( private_data, struct lookupname_state ); @@ -889,13 +889,13 @@ static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, This is the first callback after contacting our own domain ********************************************************************/ -static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, + void (*cont)(void *priv, bool succ, const DOM_SID *sid, enum lsa_SidType type) = - (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; + (void (*)(void *, bool, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; struct lookupname_state *s = talloc_get_type_abort( private_data, struct lookupname_state ); @@ -948,7 +948,7 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name, const char *name, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type), enum winbindd_cmd orig_cmd, @@ -1024,7 +1024,7 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } -BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, +bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, size_t num_sids, char **result, ssize_t *len) { size_t i; @@ -1044,7 +1044,7 @@ BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, return True; } -static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, +static bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, DOM_SID **sids, size_t *num_sids) { char *p, *q; @@ -1074,7 +1074,7 @@ static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, return True; } -static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, +static bool parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, uint32 **rids, size_t *num_rids) { char *p; @@ -1158,13 +1158,13 @@ enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain, return WINBINDD_OK; } -static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void getsidaliases_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, + void (*cont)(void *priv, bool succ, DOM_SID *aliases, size_t num_aliases) = - (void (*)(void *, BOOL, DOM_SID *, size_t))c; + (void (*)(void *, bool, DOM_SID *, size_t))c; char *aliases_str; DOM_SID *sids = NULL; size_t num_sids = 0; @@ -1204,7 +1204,7 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sids, size_t num_sids, void (*cont)(void *private_data, - BOOL success, + bool success, const DOM_SID *aliases, size_t num_aliases), void *private_data) @@ -1324,20 +1324,20 @@ struct gettoken_state { struct winbindd_domain *builtin_domain; DOM_SID *sids; size_t num_sids; - void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids); + void (*cont)(void *private_data, bool success, DOM_SID *sids, size_t num_sids); void *private_data; }; -static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, +static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data); -static void gettoken_recvaliases(void *private_data, BOOL success, +static void gettoken_recvaliases(void *private_data, bool success, const DOM_SID *aliases, size_t num_aliases); void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, DOM_SID *sids, size_t num_sids), void *private_data) { @@ -1376,7 +1376,7 @@ void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, NULL, state); } -static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, +static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { @@ -1434,7 +1434,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, gettoken_recvaliases, state); } -static void gettoken_recvaliases(void *private_data, BOOL success, +static void gettoken_recvaliases(void *private_data, bool success, const DOM_SID *aliases, size_t num_aliases) { @@ -1479,14 +1479,14 @@ static void gettoken_recvaliases(void *private_data, BOOL success, state->cont(state->private_data, True, state->sids, state->num_sids); } -static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void query_user_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *acct_name, + void (*cont)(void *priv, bool succ, const char *acct_name, const char *full_name, const char *homedir, const char *shell, uint32 gid, uint32 group_rid) = - (void (*)(void *, BOOL, const char *, const char *, + (void (*)(void *, bool, const char *, const char *, const char *, const char *, uint32, uint32))c; if (!success) { @@ -1511,7 +1511,7 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success, void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, const DOM_SID *sid, - void (*cont)(void *private_data, BOOL success, + void (*cont)(void *private_data, bool success, const char *acct_name, const char *full_name, const char *homedir, @@ -1531,12 +1531,12 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, /* The following uid2sid/gid2sid functions has been contributed by * Keith Reynolds */ -static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; + void (*cont)(void *priv, bool succ, const char *sid) = + (void (*)(void *, bool, const char *))c; if (!success) { DEBUG(5, ("Could not trigger uid2sid\n")); @@ -1554,7 +1554,7 @@ static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, BOOL success, const char *sid), + void (*cont)(void *private_data, bool success, const char *sid), void *private_data) { struct winbindd_request request; @@ -1588,12 +1588,12 @@ enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, return WINBINDD_ERROR; } -static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *sid) = - (void (*)(void *, BOOL, const char *))c; + void (*cont)(void *priv, bool succ, const char *sid) = + (void (*)(void *, bool, const char *))c; if (!success) { DEBUG(5, ("Could not trigger gid2sid\n")); @@ -1611,7 +1611,7 @@ static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, BOOL success, const char *sid), + void (*cont)(void *private_data, bool success, const char *sid), void *private_data) { struct winbindd_request request; @@ -1648,12 +1648,12 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, return WINBINDD_ERROR; } -static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, +static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ) = - (void (*)(void *, BOOL))c; + void (*cont)(void *priv, bool succ) = + (void (*)(void *, bool))c; if (!success) { DEBUG(5, ("Could not trigger a map dump\n")); @@ -1671,7 +1671,7 @@ static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success, } void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, - void (*cont)(void *private_data, BOOL success), + void (*cont)(void *private_data, bool success), void *private_data) { struct winbindd_request request; diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index e5090dfacf..f3aa0fce42 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -33,7 +33,7 @@ #define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION" extern struct winbindd_methods reconnect_methods; -extern BOOL opt_nocache; +extern bool opt_nocache; #ifdef HAVE_ADS extern struct winbindd_methods ads_methods; #endif @@ -57,7 +57,7 @@ static const char *non_centry_keys[] = { Is this key a non-centry type ? ************************************************************************/ -static BOOL is_non_centry_key(TDB_DATA kbuf) +static bool is_non_centry_key(TDB_DATA kbuf) { int i; @@ -80,7 +80,7 @@ static BOOL is_non_centry_key(TDB_DATA kbuf) and sets this to true if the first query fails and there's an entry in the cache tdb telling us to stay offline. */ -static BOOL global_winbindd_offline_state; +static bool global_winbindd_offline_state; struct winbind_cache { TDB_CONTEXT *tdb; @@ -204,7 +204,7 @@ static void centry_free(struct cache_entry *centry) free(centry); } -static BOOL centry_check_bytes(struct cache_entry *centry, size_t nbytes) +static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes) { if (centry->len - centry->ofs < nbytes) { DEBUG(0,("centry corruption? needed %u bytes, have %d\n", @@ -343,7 +343,7 @@ static char *centry_hash16(struct cache_entry *centry, TALLOC_CTX *mem_ctx) /* pull a sid from a cache entry, using the supplied talloc context */ -static BOOL centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID *sid) +static bool centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID *sid) { char *sid_string; sid_string = centry_string(centry, mem_ctx); @@ -367,9 +367,9 @@ static NTSTATUS centry_ntstatus(struct cache_entry *centry) /* the server is considered down if it can't give us a sequence number */ -static BOOL wcache_server_down(struct winbindd_domain *domain) +static bool wcache_server_down(struct winbindd_domain *domain) { - BOOL ret; + bool ret; if (!wcache->tdb) return False; @@ -458,7 +458,7 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) then always refresh it, no matter how recently we fetched it */ -static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) +static void refresh_sequence_number(struct winbindd_domain *domain, bool force) { NTSTATUS status; unsigned time_diff; @@ -532,7 +532,7 @@ done: /* decide if a cache entry has expired */ -static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry) +static bool centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry) { /* If we've been told to be offline - stay in that state... */ if (lp_winbind_offline_logon() && global_winbindd_offline_state) { @@ -1525,8 +1525,8 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); size_t i; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - BOOL have_mapped; - BOOL have_unmapped; + bool have_mapped; + bool have_unmapped; *domain_name = NULL; *names = NULL; @@ -2263,7 +2263,7 @@ void wcache_invalidate_cache(void) } } -BOOL init_wcache(void) +bool init_wcache(void) { if (wcache == NULL) { wcache = SMB_XMALLOC_P(struct winbind_cache); @@ -2293,9 +2293,9 @@ BOOL init_wcache(void) only opener. ************************************************************************/ -BOOL initialize_winbindd_cache(void) +bool initialize_winbindd_cache(void) { - BOOL cache_bad = True; + bool cache_bad = True; uint32 vers; if (!init_wcache()) { @@ -2382,7 +2382,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response) return; } -BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) +bool cache_retrieve_response(pid_t pid, struct winbindd_response * response) { TDB_DATA data; fstring key_str; @@ -2451,7 +2451,7 @@ void cache_cleanup_response(pid_t pid) } -BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, +bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **domain_name, char **name, enum lsa_SidType *type) { @@ -2487,7 +2487,7 @@ BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, return NT_STATUS_IS_OK(status); } -BOOL lookup_cached_name(TALLOC_CTX *mem_ctx, +bool lookup_cached_name(TALLOC_CTX *mem_ctx, const char *domain_name, const char *name, DOM_SID *sid, @@ -2498,7 +2498,7 @@ BOOL lookup_cached_name(TALLOC_CTX *mem_ctx, struct cache_entry *centry = NULL; NTSTATUS status; fstring uname; - BOOL original_online_state; + bool original_online_state; domain = find_lookup_domain_from_name(domain_name); if (domain == NULL) { @@ -2744,7 +2744,7 @@ done: } /* Change the global online/offline state. */ -BOOL set_global_winbindd_state_offline(void) +bool set_global_winbindd_state_offline(void) { TDB_DATA data; @@ -2805,7 +2805,7 @@ void set_global_winbindd_state_online(void) tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE"); } -BOOL get_global_winbindd_state_offline(void) +bool get_global_winbindd_state_offline(void) { return global_winbindd_offline_state; } @@ -3413,14 +3413,14 @@ int winbindd_validate_cache_nobackup(void) /********************************************************************* ********************************************************************/ -static BOOL add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, +static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, struct winbindd_tdc_domain **domains, size_t *num_domains ) { struct winbindd_tdc_domain *list = NULL; size_t idx; int i; - BOOL set_only = False; + bool set_only = False; /* don't allow duplicates */ @@ -3622,7 +3622,7 @@ static size_t unpack_tdc_domains( unsigned char *buf, int buflen, /********************************************************************* ********************************************************************/ -static BOOL wcache_tdc_store_list( struct winbindd_tdc_domain *domains, size_t num_domains ) +static bool wcache_tdc_store_list( struct winbindd_tdc_domain *domains, size_t num_domains ) { TDB_DATA key = make_tdc_key( lp_workgroup() ); TDB_DATA data = { NULL, 0 }; @@ -3657,7 +3657,7 @@ static BOOL wcache_tdc_store_list( struct winbindd_tdc_domain *domains, size_t n /********************************************************************* ********************************************************************/ -BOOL wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_domains ) +bool wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_domains ) { TDB_DATA key = make_tdc_key( lp_workgroup() ); TDB_DATA data = { NULL, 0 }; @@ -3688,11 +3688,11 @@ BOOL wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_do /********************************************************************* ********************************************************************/ -BOOL wcache_tdc_add_domain( struct winbindd_domain *domain ) +bool wcache_tdc_add_domain( struct winbindd_domain *domain ) { struct winbindd_tdc_domain *dom_list = NULL; size_t num_domains = 0; - BOOL ret = False; + bool ret = False; DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, " "flags = 0x%x, attributes = 0x%x, type = 0x%x\n", diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c index 99c5c0c4d1..a696db1031 100644 --- a/source3/winbindd/winbindd_ccache_access.c +++ b/source3/winbindd/winbindd_ccache_access.c @@ -27,7 +27,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -static BOOL client_can_access_ccache_entry(uid_t client_uid, +static bool client_can_access_ccache_entry(uid_t client_uid, struct WINBINDD_MEMORY_CREDS *entry) { if (client_uid == entry->uid || client_uid == 0) { @@ -122,7 +122,7 @@ done: return status; } -static BOOL check_client_uid(struct winbindd_cli_state *state, uid_t uid) +static bool check_client_uid(struct winbindd_cli_state *state, uid_t uid) { int ret; uid_t ret_uid; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 4ff9fce96f..055563d815 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -70,11 +70,11 @@ struct dc_name_ip { }; extern struct winbindd_methods reconnect_methods; -extern BOOL override_logfile; +extern bool override_logfile; static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain); static void set_dc_type_and_flags( struct winbindd_domain *domain ); -static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, +static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs); /**************************************************************** @@ -166,7 +166,7 @@ static void msg_try_to_go_online(struct messaging_context *msg, parent. ****************************************************************/ -static BOOL fork_child_dc_connect(struct winbindd_domain *domain) +static bool fork_child_dc_connect(struct winbindd_domain *domain) { struct dc_name_ip *dcs = NULL; int num_dcs = 0; @@ -558,7 +558,7 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) } } -static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, +static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, fstring dcname, struct in_addr *dc_ip) { struct winbindd_domain *our_domain = NULL; @@ -641,12 +641,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, const int sockfd, const char *controller, struct cli_state **cli, - BOOL *retry) + bool *retry) { char *machine_password, *machine_krb5_principal, *machine_account; char *ipc_username, *ipc_domain, *ipc_password; - BOOL got_mutex; + bool got_mutex; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -890,7 +890,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, return result; } -static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, +static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, const char *dcname, struct in_addr ip, struct dc_name_ip **dcs, int *num) { @@ -910,7 +910,7 @@ static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, return True; } -static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx, +static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, struct in_addr ip, uint16 port, struct sockaddr_in **addrs, int *num) { @@ -934,7 +934,7 @@ static void mailslot_name(struct in_addr dc_ip, fstring name) fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr); } -static BOOL send_getdc_request(struct in_addr dc_ip, +static bool send_getdc_request(struct in_addr dc_ip, const char *domain_name, const DOM_SID *sid) { @@ -988,7 +988,7 @@ static BOOL send_getdc_request(struct in_addr dc_ip, dc_ip); } -static BOOL receive_getdc_response(struct in_addr dc_ip, +static bool receive_getdc_response(struct in_addr dc_ip, const char *domain_name, fstring dc_name) { @@ -1060,7 +1060,7 @@ static BOOL receive_getdc_response(struct in_addr dc_ip, convert an ip to a name *******************************************************************/ -static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name ) +static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name ) { struct ip_service ip_list; @@ -1148,7 +1148,7 @@ static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip the dcs[] with results. *******************************************************************/ -static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, +static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs) { fstring dcname; @@ -1156,7 +1156,7 @@ static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct ip_service *ip_list = NULL; int iplist_size = 0; int i; - BOOL is_our_domain; + bool is_our_domain; enum security_types sec = (enum security_types)lp_security(); is_our_domain = strequal(domain->name, lp_workgroup()); @@ -1231,7 +1231,7 @@ static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, return True; } -static BOOL find_new_dc(TALLOC_CTX *mem_ctx, +static bool find_new_dc(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, fstring dcname, struct sockaddr_in *addr, int *fd) { @@ -1358,7 +1358,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, for (retries = 0; retries < 3; retries++) { int fd = -1; - BOOL retry = False; + bool retry = False; result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; @@ -1492,7 +1492,7 @@ void close_conns_after_fork(void) } } -static BOOL connection_ok(struct winbindd_domain *domain) +static bool connection_ok(struct winbindd_domain *domain) { if (domain->conn.cli == NULL) { DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL " @@ -1566,7 +1566,7 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain) Set the trust flags (direction and forest location) for a domain ******************************************************************************/ -static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) +static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) { struct winbindd_domain *our_domain; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -1848,7 +1848,7 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain ) /********************************************************************** ***********************************************************************/ -static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, +static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc) { NTSTATUS result; diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index 65dcbe5a00..311b1d1822 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -284,7 +284,7 @@ static void krb5_ticket_gain_handler(struct event_context *event_ctx, Check if an ccache entry exists. ****************************************************************/ -BOOL ccache_entry_exists(const char *username) +bool ccache_entry_exists(const char *username) { struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); return (entry != NULL); @@ -294,7 +294,7 @@ BOOL ccache_entry_exists(const char *username) Ensure we're changing the correct entry. ****************************************************************/ -BOOL ccache_entry_identical(const char *username, +bool ccache_entry_identical(const char *username, uid_t uid, const char *ccname) { @@ -327,7 +327,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name, time_t create_time, time_t ticket_end, time_t renew_until, - BOOL postponed_request) + bool postponed_request) { struct WINBINDD_CCACHE_ENTRY *entry = NULL; struct timeval t; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index d9a42c31dc..932fc328cf 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -33,7 +33,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -extern BOOL override_logfile; +extern bool override_logfile; /* Read some data from a client connection */ @@ -94,22 +94,22 @@ struct winbindd_async_request { struct winbindd_child *child; struct winbindd_request *request; struct winbindd_response *response; - void (*continuation)(void *private_data, BOOL success); + void (*continuation)(void *private_data, bool success); struct timed_event *reply_timeout_event; pid_t child_pid; /* pid of the child we're waiting on. Used to detect a restart of the child (child->pid != child_pid). */ void *private_data; }; -static void async_main_request_sent(void *private_data, BOOL success); -static void async_request_sent(void *private_data, BOOL success); -static void async_reply_recv(void *private_data, BOOL success); +static void async_main_request_sent(void *private_data, bool success); +static void async_request_sent(void *private_data, bool success); +static void async_reply_recv(void *private_data, bool success); static void schedule_async_request(struct winbindd_child *child); void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, struct winbindd_request *request, struct winbindd_response *response, - void (*continuation)(void *private_data, BOOL success), + void (*continuation)(void *private_data, bool success), void *private_data) { struct winbindd_async_request *state; @@ -138,7 +138,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, return; } -static void async_main_request_sent(void *private_data, BOOL success) +static void async_main_request_sent(void *private_data, bool success) { struct winbindd_async_request *state = talloc_get_type_abort(private_data, struct winbindd_async_request); @@ -211,7 +211,7 @@ static void async_request_fail(struct winbindd_async_request *state) state->continuation(state->private_data, False); } -static void async_request_sent(void *private_data_data, BOOL success) +static void async_request_sent(void *private_data_data, bool success) { struct winbindd_async_request *state = talloc_get_type_abort(private_data_data, struct winbindd_async_request); @@ -247,7 +247,7 @@ static void async_request_sent(void *private_data_data, BOOL success) } } -static void async_reply_recv(void *private_data, BOOL success) +static void async_reply_recv(void *private_data, bool success) { struct winbindd_async_request *state = talloc_get_type_abort(private_data, struct winbindd_async_request); @@ -278,7 +278,7 @@ static void async_reply_recv(void *private_data, BOOL success) state->continuation(state->private_data, True); } -static BOOL fork_domain_child(struct winbindd_child *child); +static bool fork_domain_child(struct winbindd_child *child); static void schedule_async_request(struct winbindd_child *child) { @@ -319,17 +319,17 @@ struct domain_request_state { struct winbindd_domain *domain; struct winbindd_request *request; struct winbindd_response *response; - void (*continuation)(void *private_data_data, BOOL success); + void (*continuation)(void *private_data_data, bool success); void *private_data_data; }; -static void domain_init_recv(void *private_data_data, BOOL success); +static void domain_init_recv(void *private_data_data, bool success); void async_domain_request(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct winbindd_request *request, struct winbindd_response *response, - void (*continuation)(void *private_data_data, BOOL success), + void (*continuation)(void *private_data_data, bool success), void *private_data_data) { struct domain_request_state *state; @@ -357,7 +357,7 @@ void async_domain_request(TALLOC_CTX *mem_ctx, init_child_connection(domain, domain_init_recv, state); } -static void domain_init_recv(void *private_data_data, BOOL success) +static void domain_init_recv(void *private_data_data, bool success) { struct domain_request_state *state = talloc_get_type_abort(private_data_data, struct domain_request_state); @@ -373,7 +373,7 @@ static void domain_init_recv(void *private_data_data, BOOL success) state->continuation, state->private_data_data); } -static void recvfrom_child(void *private_data_data, BOOL success) +static void recvfrom_child(void *private_data_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data_data, struct winbindd_cli_state); @@ -920,7 +920,7 @@ static void child_msg_dump_event_list(struct messaging_context *msg, } -static BOOL fork_domain_child(struct winbindd_child *child) +static bool fork_domain_child(struct winbindd_child *child) { int fdpair[2]; struct winbindd_cli_state state; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 9a4b02f734..30e274ff86 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -25,7 +25,7 @@ #include "includes.h" #include "winbindd.h" -extern BOOL opt_nocache; +extern bool opt_nocache; #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -142,7 +142,7 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu return; } -static BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain, +static bool fill_passdb_alias_grmem(struct winbindd_domain *domain, DOM_SID *group_sid, size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len) { @@ -177,7 +177,7 @@ static BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain, /* Fill a grent structure from various other information */ -static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name, +static bool fill_grent(struct winbindd_gr *gr, const char *dom_name, const char *gr_name, gid_t unix_gid) { fstring full_group_name; @@ -203,7 +203,7 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name, if neccessaey, or parameterize the group list we do this for. ***********************************************************************/ -static BOOL fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, +static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct winbindd_cli_state *state, DOM_SID *group_sid, @@ -215,7 +215,7 @@ static BOOL fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, DOM_SID *pquerying_user_sid = NULL; uint32 num_groups = 0; DOM_SID *user_sids = NULL; - BOOL u_in_group = False; + bool u_in_group = False; NTSTATUS status; int i; unsigned int buf_len = 0; @@ -437,7 +437,7 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, if ( name_types[j] == SID_NAME_DOM_GRP || name_types[j] == SID_NAME_ALIAS ) { - BOOL ret; + bool ret; ret = add_sid_to_array_unique( ctx, &sid_mem[j], @@ -468,7 +468,7 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, Fill in the group membership field of a NT group given by group_sid ***********************************************************************/ -static BOOL fill_grent_mem(struct winbindd_domain *domain, +static bool fill_grent_mem(struct winbindd_domain *domain, struct winbindd_cli_state *state, DOM_SID *group_sid, enum lsa_SidType group_name_type, @@ -477,7 +477,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, uint32 num_names = 0; unsigned int buf_len = 0, buf_ndx = 0, i; char **names = NULL, *buf = NULL; - BOOL result = False; + bool result = False; TALLOC_CTX *mem_ctx; uint32 group_rid; DOM_SID *glist = NULL; @@ -642,7 +642,7 @@ done: static void winbindd_getgrsid( struct winbindd_cli_state *state, DOM_SID group_sid ); -static void getgrnam_recv( void *private_data, BOOL success, const DOM_SID *sid, +static void getgrnam_recv( void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type ) { struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data; @@ -729,7 +729,7 @@ struct getgrsid_state { DOM_SID group_sid; }; -static void getgrsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) +static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) { struct getgrsid_state *s = (struct getgrsid_state *)private_data; @@ -782,7 +782,7 @@ static void getgrsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) request_ok(s->state); } -static void getgrsid_lookupsid_recv( void *private_data, BOOL success, +static void getgrsid_lookupsid_recv( void *private_data, bool success, const char *dom_name, const char *name, enum lsa_SidType name_type ) { @@ -848,7 +848,7 @@ static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID g } -static void getgrgid_recv(void *private_data, BOOL success, const char *sid) +static void getgrgid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); enum lsa_SidType name_type; @@ -895,7 +895,7 @@ void winbindd_getgrgid(struct winbindd_cli_state *state) /* "Rewind" file pointer for group database enumeration */ -static BOOL winbindd_setgrent_internal(struct winbindd_cli_state *state) +static bool winbindd_setgrent_internal(struct winbindd_cli_state *state) { struct winbindd_domain *domain; @@ -974,13 +974,13 @@ void winbindd_endgrent(struct winbindd_cli_state *state) The dispinfo_ndx field is incremented to the index of the next group to fetch. Return True if some groups were returned, False otherwise. */ -static BOOL get_sam_group_entries(struct getent_state *ent) +static bool get_sam_group_entries(struct getent_state *ent) { NTSTATUS status; uint32 num_entries; struct acct_info *name_list = NULL; TALLOC_CTX *mem_ctx; - BOOL result = False; + bool result = False; struct acct_info *sam_grp_entries = NULL; struct winbindd_domain *domain; @@ -1443,11 +1443,11 @@ struct getgroups_state { size_t num_token_gids; }; -static void getgroups_usersid_recv(void *private_data, BOOL success, +static void getgroups_usersid_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type); -static void getgroups_tokensids_recv(void *private_data, BOOL success, +static void getgroups_tokensids_recv(void *private_data, bool success, DOM_SID *token_sids, size_t num_token_sids); -static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid); +static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid); void winbindd_getgroups(struct winbindd_cli_state *state) { @@ -1515,7 +1515,7 @@ void winbindd_getgroups(struct winbindd_cli_state *state) getgroups_usersid_recv, WINBINDD_GETGROUPS, s); } -static void getgroups_usersid_recv(void *private_data, BOOL success, +static void getgroups_usersid_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type) { struct getgroups_state *s = @@ -1533,7 +1533,7 @@ static void getgroups_usersid_recv(void *private_data, BOOL success, getgroups_tokensids_recv, s); } -static void getgroups_tokensids_recv(void *private_data, BOOL success, +static void getgroups_tokensids_recv(void *private_data, bool success, DOM_SID *token_sids, size_t num_token_sids) { struct getgroups_state *s = @@ -1557,7 +1557,7 @@ static void getgroups_tokensids_recv(void *private_data, BOOL success, getgroups_sid2gid_recv(s, False, 0); } -static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid) +static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid) { struct getgroups_state *s = (struct getgroups_state *)private_data; @@ -1603,7 +1603,7 @@ static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid) results. */ -static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids, +static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, size_t num_sids); void winbindd_getusersids(struct winbindd_cli_state *state) @@ -1631,7 +1631,7 @@ void winbindd_getusersids(struct winbindd_cli_state *state) state); } -static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids, +static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, size_t num_sids) { struct winbindd_cli_state *state = diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 366f58a403..dc2e35884e 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -145,7 +145,7 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain * int extra_data_len = 0; char *extra_data; NTSTATUS result; - BOOL have_own_domain = False; + bool have_own_domain = False; DEBUG(3, ("[%5lu]: list trusted domains\n", (unsigned long)state->pid)); @@ -362,7 +362,7 @@ struct sequence_state { char *extra_data; }; -static void sequence_recv(void *private_data, BOOL success); +static void sequence_recv(void *private_data, bool success); void winbindd_show_sequence(struct winbindd_cli_state *state) { @@ -422,7 +422,7 @@ void winbindd_show_sequence(struct winbindd_cli_state *state) sequence_recv, seq); } -static void sequence_recv(void *private_data, BOOL success) +static void sequence_recv(void *private_data, bool success) { struct sequence_state *state = (struct sequence_state *)private_data; @@ -489,7 +489,7 @@ struct domain_info_state { struct winbindd_cli_state *cli_state; }; -static void domain_info_init_recv(void *private_data, BOOL success); +static void domain_info_init_recv(void *private_data, bool success); void winbindd_domain_info(struct winbindd_cli_state *state) { @@ -542,7 +542,7 @@ void winbindd_domain_info(struct winbindd_cli_state *state) request_ok(state); } -static void domain_info_init_recv(void *private_data, BOOL success) +static void domain_info_init_recv(void *private_data, bool success) { struct domain_info_state *istate = (struct domain_info_state *)private_data; diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 78128521c4..640eb5a519 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -444,7 +444,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *type, uid_t uid, - BOOL *internal_ccache) + bool *internal_ccache) { /* accept FILE and WRFILE as krb5_cc_type from the client and then * build the full ccname string based on the user's uid here - @@ -545,7 +545,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid_t uid = -1; ADS_STRUCT *ads; time_t time_offset = 0; - BOOL internal_ccache = True; + bool internal_ccache = True; ZERO_STRUCTP(info3); @@ -695,7 +695,7 @@ failed: /**************************************************************** ****************************************************************/ -static BOOL check_request_flags(uint32_t flags) +static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | WBFLAG_PAM_UNIX_NAME | @@ -846,7 +846,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, const uint8 *cached_salt; NET_USER_INFO_3 *my_info3; time_t kickoff_time, must_change_time; - BOOL password_good = False; + bool password_good = False; #ifdef HAVE_KRB5 struct winbindd_tdc_domain *tdc_domain = NULL; #endif @@ -967,7 +967,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, char *realm = NULL; const char *principal_s = NULL; const char *service = NULL; - BOOL internal_ccache = False; + bool internal_ccache = False; uid = get_uid_from_state(state); if (uid == -1) { @@ -1161,7 +1161,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, unsigned char local_nt_response[24]; struct winbindd_domain *contact_domain; fstring name_domain, name_user; - BOOL retry; + bool retry; NTSTATUS result; NET_USER_INFO_3 *my_info3; @@ -1707,7 +1707,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, const char *workstation; struct winbindd_domain *contact_domain; int attempts = 0; - BOOL retry; + bool retry; DATA_BLOB lm_resp, nt_resp; @@ -1927,7 +1927,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact char *newpass = NULL; POLICY_HND dom_pol; struct rpc_pipe_client *cli; - BOOL got_info = False; + bool got_info = False; SAM_UNK_INFO_1 info; SAMR_CHANGE_REJECT reject; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 5c36c0c327..cfb934eb60 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -322,7 +322,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, /* find the sequence number for a domain */ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { - BOOL result; + bool result; time_t seq_num; result = pdb_get_seq_num(&seq_num); diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 283b4f36e9..7035f6bffb 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -869,7 +869,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) SAM_UNK_CTR ctr; NTSTATUS result; POLICY_HND dom_pol; - BOOL got_seq_num = False; + bool got_seq_num = False; struct rpc_pipe_client *cli; DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 48e84d35e5..f405f36d1b 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -27,7 +27,7 @@ /* Convert a string */ -static void lookupsid_recv(void *private_data, BOOL success, +static void lookupsid_recv(void *private_data, bool success, const char *dom_name, const char *name, enum lsa_SidType type); @@ -50,7 +50,7 @@ void winbindd_lookupsid(struct winbindd_cli_state *state) winbindd_lookupsid_async(state->mem_ctx, &sid, lookupsid_recv, state); } -static void lookupsid_recv(void *private_data, BOOL success, +static void lookupsid_recv(void *private_data, bool success, const char *dom_name, const char *name, enum lsa_SidType type) { @@ -73,7 +73,7 @@ static void lookupsid_recv(void *private_data, BOOL success, * Look up the SID for a qualified name. **/ -static void lookupname_recv(void *private_data, BOOL success, +static void lookupname_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type); void winbindd_lookupname(struct winbindd_cli_state *state) @@ -106,7 +106,7 @@ void winbindd_lookupname(struct winbindd_cli_state *state) state); } -static void lookupname_recv(void *private_data, BOOL success, +static void lookupname_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type) { struct winbindd_cli_state *state = @@ -167,7 +167,7 @@ struct winbindd_child *idmap_child(void) /* Convert a sid to a uid. We assume we only have one rid attached to the sid. */ -static void sid2uid_recv(void *private_data, BOOL success, uid_t uid) +static void sid2uid_recv(void *private_data, bool success, uid_t uid) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -183,7 +183,7 @@ static void sid2uid_recv(void *private_data, BOOL success, uid_t uid) request_ok(state); } -static void sid2uid_lookupsid_recv( void *private_data, BOOL success, +static void sid2uid_lookupsid_recv( void *private_data, bool success, const char *domain_name, const char *name, enum lsa_SidType type) @@ -244,7 +244,7 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state) /* Convert a sid to a gid. We assume we only have one rid attached to the sid.*/ -static void sid2gid_recv(void *private_data, BOOL success, gid_t gid) +static void sid2gid_recv(void *private_data, bool success, gid_t gid) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -260,7 +260,7 @@ static void sid2gid_recv(void *private_data, BOOL success, gid_t gid) request_ok(state); } -static void sid2gid_lookupsid_recv( void *private_data, BOOL success, +static void sid2gid_lookupsid_recv( void *private_data, bool success, const char *domain_name, const char *name, enum lsa_SidType type) @@ -321,7 +321,7 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state) winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state ); } -static void sids2xids_recv(void *private_data, BOOL success, void *data, int len) +static void sids2xids_recv(void *private_data, bool success, void *data, int len) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -347,7 +347,7 @@ void winbindd_sids_to_unixids(struct winbindd_cli_state *state) sids2xids_recv, state); } -static void set_mapping_recv(void *private_data, BOOL success) +static void set_mapping_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -389,7 +389,7 @@ void winbindd_set_mapping(struct winbindd_cli_state *state) set_mapping_recv, state); } -static void set_hwm_recv(void *private_data, BOOL success) +static void set_hwm_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -423,7 +423,7 @@ void winbindd_set_hwm(struct winbindd_cli_state *state) /* Convert a uid to a sid */ -static void uid2sid_recv(void *private_data, BOOL success, const char *sid) +static void uid2sid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; @@ -452,7 +452,7 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state) /* Convert a gid to a sid */ -static void gid2sid_recv(void *private_data, BOOL success, const char *sid) +static void gid2sid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; @@ -528,7 +528,7 @@ enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain, return WINBINDD_OK; } -static void dump_maps_recv(void *private_data, BOOL success) +static void dump_maps_recv(void *private_data, bool success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index fac2832f56..01cdd0a9d3 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -27,7 +27,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -static BOOL fillup_pw_field(const char *lp_template, +static bool fillup_pw_field(const char *lp_template, const char *username, const char *domname, uid_t uid, @@ -67,7 +67,7 @@ static BOOL fillup_pw_field(const char *lp_template, } /* Fill a pwent structure with information we have obtained */ -static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, +static bool winbindd_fill_pwent(char *dom_name, char *user_name, DOM_SID *user_sid, DOM_SID *group_sid, char *full_name, char *homedir, char *shell, struct winbindd_pw *pw) @@ -178,15 +178,15 @@ struct getpwsid_state { gid_t gid; }; -static void getpwsid_queryuser_recv(void *private_data, BOOL success, +static void getpwsid_queryuser_recv(void *private_data, bool success, const char *acct_name, const char *full_name, const char *homedir, const char *shell, uint32 gid, uint32 group_rid); -static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid); -static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid); +static void getpwsid_sid2uid_recv(void *private_data, bool success, uid_t uid); +static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid); static void winbindd_getpwsid(struct winbindd_cli_state *state, const DOM_SID *sid) @@ -217,7 +217,7 @@ static void winbindd_getpwsid(struct winbindd_cli_state *state, request_error(state); } -static void getpwsid_queryuser_recv(void *private_data, BOOL success, +static void getpwsid_queryuser_recv(void *private_data, bool success, const char *acct_name, const char *full_name, const char *homedir, @@ -282,7 +282,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success, getpwsid_sid2uid_recv, s); } -static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid) +static void getpwsid_sid2uid_recv(void *private_data, bool success, uid_t uid) { struct getpwsid_state *s = talloc_get_type_abort(private_data, struct getpwsid_state); @@ -299,7 +299,7 @@ static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid) getpwsid_sid2gid_recv, s); } -static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) +static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid) { struct getpwsid_state *s = talloc_get_type_abort(private_data, struct getpwsid_state); @@ -357,7 +357,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) /* Return a password structure from a username. */ -static void getpwnam_name2sid_recv(void *private_data, BOOL success, +static void getpwnam_name2sid_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type); void winbindd_getpwnam(struct winbindd_cli_state *state) @@ -409,7 +409,7 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) state); } -static void getpwnam_name2sid_recv(void *private_data, BOOL success, +static void getpwnam_name2sid_recv(void *private_data, bool success, const DOM_SID *sid, enum lsa_SidType type) { struct winbindd_cli_state *state = @@ -438,7 +438,7 @@ static void getpwnam_name2sid_recv(void *private_data, BOOL success, winbindd_getpwsid(state, sid); } -static void getpwuid_recv(void *private_data, BOOL success, const char *sid) +static void getpwuid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; @@ -475,7 +475,7 @@ void winbindd_getpwuid(struct winbindd_cli_state *state) /* Rewind file pointer for ntdom passwd database */ -static BOOL winbindd_setpwent_internal(struct winbindd_cli_state *state) +static bool winbindd_setpwent_internal(struct winbindd_cli_state *state) { struct winbindd_domain *domain; @@ -568,7 +568,7 @@ void winbindd_endpwent(struct winbindd_cli_state *state) field is incremented to the index of the next user to fetch. Return True if some users were returned, False otherwise. */ -static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) +static bool get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) { NTSTATUS status; uint32 num_entries; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index c2fe09eead..54bb5a24b7 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -77,7 +77,7 @@ void free_domain_list(void) } } -static BOOL is_internal_domain(const DOM_SID *sid) +static bool is_internal_domain(const DOM_SID *sid) { if (sid == NULL) return False; @@ -88,7 +88,7 @@ static BOOL is_internal_domain(const DOM_SID *sid) return (sid_check_is_domain(sid) || sid_check_is_builtin(sid)); } -static BOOL is_in_internal_domain(const DOM_SID *sid) +static bool is_in_internal_domain(const DOM_SID *sid) { if (sid == NULL) return False; @@ -204,12 +204,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const struct trustdom_state { TALLOC_CTX *mem_ctx; - BOOL primary; - BOOL forest_root; + bool primary; + bool forest_root; struct winbindd_response *response; }; -static void trustdom_recv(void *private_data, BOOL success); +static void trustdom_recv(void *private_data, bool success); static void rescan_forest_root_trusts( void ); static void rescan_forest_trusts( void ); @@ -253,7 +253,7 @@ static void add_trusted_domains( struct winbindd_domain *domain ) trustdom_recv, state); } -static void trustdom_recv(void *private_data, BOOL success) +static void trustdom_recv(void *private_data, bool success) { struct trustdom_state *state = talloc_get_type_abort(private_data, struct trustdom_state); @@ -518,16 +518,16 @@ struct init_child_state { struct winbindd_domain *domain; struct winbindd_request *request; struct winbindd_response *response; - void (*continuation)(void *private_data, BOOL success); + void (*continuation)(void *private_data, bool success); void *private_data; }; -static void init_child_recv(void *private_data, BOOL success); -static void init_child_getdc_recv(void *private_data, BOOL success); +static void init_child_recv(void *private_data, bool success); +static void init_child_getdc_recv(void *private_data, bool success); enum winbindd_result init_child_connection(struct winbindd_domain *domain, void (*continuation)(void *private_data, - BOOL success), + bool success), void *private_data) { TALLOC_CTX *mem_ctx; @@ -585,7 +585,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain, return WINBINDD_PENDING; } -static void init_child_getdc_recv(void *private_data, BOOL success) +static void init_child_getdc_recv(void *private_data, bool success) { struct init_child_state *state = talloc_get_type_abort(private_data, struct init_child_state); @@ -607,7 +607,7 @@ static void init_child_getdc_recv(void *private_data, BOOL success) init_child_recv, state); } -static void init_child_recv(void *private_data, BOOL success) +static void init_child_recv(void *private_data, bool success) { struct init_child_state *state = talloc_get_type_abort(private_data, struct init_child_state); @@ -681,7 +681,7 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai } /* Look up global info for the winbind daemon */ -BOOL init_domain_list(void) +bool init_domain_list(void) { struct winbindd_domain *domain; int role = lp_server_role(); @@ -951,7 +951,7 @@ struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name) /* Lookup a sid in a domain from a name */ -BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx, +bool winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx, enum winbindd_cmd orig_cmd, struct winbindd_domain *domain, const char *domain_name, @@ -983,7 +983,7 @@ BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx, * @retval True if the name exists, in which case @p name and @p type * are set, otherwise False. **/ -BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx, +bool winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, DOM_SID *sid, char **dom_name, @@ -1036,7 +1036,7 @@ void free_getent_state(struct getent_state *state) /* Is this a domain which we may assume no DOMAIN\ prefix? */ -static BOOL assume_domain(const char *domain) +static bool assume_domain(const char *domain) { /* never assume the domain on a standalone server */ @@ -1064,7 +1064,7 @@ static BOOL assume_domain(const char *domain) /* Parse a string of the form DOMAIN\user into a domain and a user */ -BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) +bool parse_domain_user(const char *domuser, fstring domain, fstring user) { char *p = strchr(domuser,*lp_winbind_separator()); @@ -1089,7 +1089,7 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) return True; } -BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, +bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, char **domain, char **user) { fstring fstr_domain, fstr_user; @@ -1110,7 +1110,7 @@ BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, really should be changed to use this instead of doing things by hand. JRA. */ -BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user) +bool canonicalize_username(fstring username_inout, fstring domain, fstring user) { if (!parse_domain_user(username_inout, domain, user)) { return False; @@ -1135,7 +1135,7 @@ BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user) We always canonicalize as UPPERCASE DOMAIN, lowercase username. */ -void fill_domain_username(fstring name, const char *domain, const char *user, BOOL can_assume) +void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume) { fstring tmp_user; @@ -1376,7 +1376,7 @@ void ws_name_return( char *name, char replace ) /********************************************************************* ********************************************************************/ -BOOL winbindd_can_contact_domain( struct winbindd_domain *domain ) +bool winbindd_can_contact_domain( struct winbindd_domain *domain ) { /* We can contact the domain if it is our primary domain */ @@ -1406,7 +1406,7 @@ BOOL winbindd_can_contact_domain( struct winbindd_domain *domain ) /********************************************************************* ********************************************************************/ -BOOL winbindd_internal_child(struct winbindd_child *child) +bool winbindd_internal_child(struct winbindd_child *child) { if ((child == idmap_child()) || (child == locator_child())) { return True; -- cgit From 7f82fbad50906866bbb6c0950795644f1c18b099 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 19 Oct 2007 10:34:06 +0200 Subject: fix startup of smbd, nmbd, winbindd jra: POPT_ARG_VAL arguments need int values. I assume there're more places like this in the cmdline tools. Please fix this properly, as my commit is just a hack to get make test working again. in samba4 we have a workaround for this see smbd/server.c metze (This used to be commit 9cb1937fe8601e526b5c924930500e0a3b52abd5) --- source3/winbindd/winbindd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 97bbe063ba..057790a541 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -984,10 +984,10 @@ static void process_loop(void) int main(int argc, char **argv, char **envp) { pstring logfile; - static bool is_daemon = False; - static bool Fork = True; - static bool log_stdout = False; - static bool no_process_group = False; + static int is_daemon = False; + static int Fork = True; + static int log_stdout = False; + static int no_process_group = False; struct poptOption long_options[] = { POPT_AUTOHELP { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, -- cgit From 61e482cfdfec09ed01225320ba6a4acd47081f63 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 19 Oct 2007 13:03:44 +0200 Subject: Merge Tridge's fix for the winbind 32/64bit padding. Guenther (This used to be commit 36578b22f12a7de21df5a795d7702c10d19b1f3d) --- source3/winbindd/winbindd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 057790a541..d5f24d7aa2 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -613,8 +613,8 @@ static void request_len_recv(void *private_data, bool success) } if (*(uint32 *)(&state->request) != sizeof(state->request)) { - DEBUG(0,("request_len_recv: Invalid request size received: %d\n", - *(uint32 *)(&state->request))); + DEBUG(0,("request_len_recv: Invalid request size received: %d (expected %u)\n", + *(uint32_t *)(&state->request), (uint32_t)sizeof(state->request))); state->finished = True; return; } -- cgit From 9a85533914119fb995fb61555c9f6e0018d4d181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2007 11:38:36 -0700 Subject: Fix the popt / bool issues. Some places we used BOOL where we meant int. Fix this. Thanks to metze for pointing this out. Jeremy. (This used to be commit 793a9d24a163cb6cf5a3a0aa5ae30e9f8cf4744a) --- source3/winbindd/winbindd.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index d5f24d7aa2..8449795e13 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -984,18 +984,24 @@ static void process_loop(void) int main(int argc, char **argv, char **envp) { pstring logfile; - static int is_daemon = False; - static int Fork = True; - static int log_stdout = False; - static int no_process_group = False; + static bool is_daemon = False; + static bool Fork = True; + static bool log_stdout = False; + static bool no_process_group = False; + enum { + OPT_DAEMON = 1000, + OPT_FORK, + OPT_NO_PROCESS_GROUP, + OPT_LOG_STDOUT + }; struct poptOption long_options[] = { POPT_AUTOHELP - { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, - { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, - { "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, - { "daemon", 'D', POPT_ARG_NONE, NULL, 'D', "Become a daemon (default)" }, + { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, + { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" }, + { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, + { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" }, { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, - { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, + { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" }, POPT_COMMON_SAMBA POPT_TABLEEND }; @@ -1034,7 +1040,7 @@ int main(int argc, char **argv, char **envp) while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { /* Don't become a daemon */ - case 'D': + case OPT_DAEMON: is_daemon = True; break; case 'i': @@ -1042,6 +1048,18 @@ int main(int argc, char **argv, char **envp) log_stdout = True; Fork = False; break; + case OPT_FORK: + Fork = false; + break; + case OPT_NO_PROCESS_GROUP: + no_process_group = true; + break; + case OPT_LOG_STDOUT: + log_stdout = true; + break; + case 'n': + opt_nocache = true; + break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); -- cgit From 8f391ae47176f1acaef2e1f448b1c0168a069cf9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 19 Oct 2007 23:21:01 +0200 Subject: Fix an incompatible pointer type warning (This used to be commit 3c50caa9620899f982cd4a833356d965f47ec843) --- source3/winbindd/idmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 9800e32505..e89ad735b6 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -362,9 +362,9 @@ NTSTATUS idmap_init(void) if ( ! dom_list) { /* generate a list with our main domain */ - char ** dl; + const char ** dl; - dl = talloc_array(idmap_ctx, char *, 2); + dl = talloc_array(idmap_ctx, const char *, 2); if (dl == NULL) { ret = NT_STATUS_NO_MEMORY; goto done; -- cgit From e5cedc7611f1dd4441cdde5ebb2857d8476eb450 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 10:54:33 +0000 Subject: r25567: make do_async() non static metze (cherry picked from commit badc714d7f82f8d7c21ecfeab137efb57e970210) (This used to be commit d623b2fa710cfe7ef85b7e9dd84b274b081841ae) --- source3/winbindd/winbindd_async.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index ae549d0fcf..b937b9d195 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -57,12 +57,12 @@ static void do_async_recv(void *private_data, bool success) state->c, state->private_data); } -static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, - const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data), - void *c, void *private_data) +void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) { struct do_async_state *state; -- cgit From 1e9e1b6fca4c3c10d9e37a7b980859ff40e352e0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:11:46 +0000 Subject: r25568: move idmap related functions into their own file. the final goal is to have 3 child dispatch tables 'domain', 'idmap' and 'locator' instead of one. metze (cherry picked from commit 97c63f1b95190f3bcc1d9f34765934c97ffb720c) (This used to be commit a1c354866c04a305aa28a287dc6c72db1aa845a9) --- source3/winbindd/winbindd_async.c | 741 ------------------------------------ source3/winbindd/winbindd_idmap.c | 778 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 778 insertions(+), 741 deletions(-) create mode 100644 source3/winbindd/winbindd_idmap.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index b937b9d195..611ca03001 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -111,581 +111,6 @@ void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, &state->response, do_async_recv, state); } -static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_mapping\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_mapping returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, - void (*cont)(void *private_data, bool success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_MAPPING; - request.data.dual_idmapset.id = map->xid.id; - request.data.dual_idmapset.type = map->xid.type; - sid_to_string(request.data.dual_idmapset.sid, map->sid); - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct id_map map; - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); - - if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) - return WINBINDD_ERROR; - - map.sid = &sid; - map.xid.id = state->request.data.dual_idmapset.id; - map.xid.type = state->request.data.dual_idmapset.type; - map.status = ID_MAPPED; - - result = idmap_set_mapping(&map); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; - - if (!success) { - DEBUG(5, ("Could not trigger idmap_set_hwm\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap_set_hwm returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, - void (*cont)(void *private_data, bool success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SET_HWM; - request.data.dual_idmapset.id = xid->id; - request.data.dual_idmapset.type = xid->type; - - do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct unixid xid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); - - xid.id = state->request.data.dual_idmapset.id; - xid.type = state->request.data.dual_idmapset.type; - - switch (xid.type) { - case ID_TYPE_UID: - result = idmap_set_uid_hwm(&xid); - break; - case ID_TYPE_GID: - result = idmap_set_gid_hwm(&xid); - break; - default: - return WINBINDD_ERROR; - } - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, void *, int) = - (void (*)(void *, bool, void *, int))c; - - if (!success) { - DEBUG(5, ("Could not trigger sids2xids\n")); - cont(private_data, False, NULL, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sids2xids returned an error\n")); - cont(private_data, False, NULL, 0); - return; - } - - cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); -} - -void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, - void (*cont)(void *private_data, bool success, void *data, int len), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SIDS2XIDS; - request.extra_data.data = (char *)sids; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID *sids; - struct unixid *xids; - struct id_map **ids; - NTSTATUS result; - int num, i; - - DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); - - if (state->request.extra_len == 0) { - DEBUG(0, ("Invalid buffer size!\n")); - return WINBINDD_ERROR; - } - - sids = (DOM_SID *)state->request.extra_data.data; - num = state->request.extra_len / sizeof(DOM_SID); - - ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); - if ( ! ids) { - DEBUG(0, ("Out of memory!\n")); - return WINBINDD_ERROR; - } - for (i = 0; i < num; i++) { - ids[i] = TALLOC_P(ids, struct id_map); - if ( ! ids[i]) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - ids[i]->sid = &sids[i]; - } - - result = idmap_sids_to_unixids(ids); - - if (NT_STATUS_IS_OK(result)) { - - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; - } - } - - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; - - } else { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); - talloc_free(ids); - return WINBINDD_ERROR; - } - - talloc_free(ids); - return WINBINDD_OK; -} - -static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, uid_t uid) = - (void (*)(void *, bool, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} - -void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, bool success, uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2UID; - sid_to_string(request.data.dual_sid2id.sid, sid); - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find uid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, bool success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2NAME; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, uid2name_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.uid)); - - pw = getpwuid(state->request.data.uid); - if (pw == NULL) { - DEBUG(5, ("User %lu not found\n", - (unsigned long)state->request.data.uid)); - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.name, pw->pw_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *name) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, bool success, - uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2UID; - fstrcpy(request.data.username, name); - do_async(mem_ctx, idmap_child(), &request, name2uid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - /* Ensure null termination */ - state->request.data.username - [sizeof(state->request.data.username)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, - state->request.data.username)); - - pw = getpwnam(state->request.data.username); - if (pw == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.uid = pw->pw_uid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, uid_t uid) = - (void (*)(void *, bool, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} -#endif /* not used */ - -static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, gid_t gid) = - (void (*)(void *, bool, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger sid2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sid2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} - -void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - void (*cont)(void *private_data, bool success, gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SID2GID; - sid_to_string(request.data.dual_sid2id.sid, sid); - - DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", - request.data.dual_sid2id.sid)); - - do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, - state->request.data.dual_sid2id.sid)); - - if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.dual_sid2id.sid)); - return WINBINDD_ERROR; - } - - /* Find gid for this sid and return it, possibly ask the slow remote idmap */ - - result = idmap_sid_to_gid(&sid, &state->response.data.gid); - - DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -static void gid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *name) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, bool success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2NAME; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, gid2name_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.gid)); - - gr = getgrgid(state->request.data.gid); - if (gr == NULL) - return WINBINDD_ERROR; - - fstrcpy(state->response.data.name.name, gr->gr_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, bool success, - gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2GID; - fstrcpy(request.data.groupname, name); - do_async(mem_ctx, idmap_child(), &request, name2gid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - /* Ensure null termination */ - state->request.data.groupname - [sizeof(state->request.data.groupname)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, - state->request.data.groupname)); - - gr = getgrnam(state->request.data.groupname); - if (gr == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.gid = gr->gr_gid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, gid_t gid) = - (void (*)(void *, bool, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} -#endif /* not used */ - struct lookupsid_state { DOM_SID sid; void *caller_private_data; @@ -1527,169 +952,3 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, do_async_domain(mem_ctx, domain, &request, query_user_recv, (void *)cont, private_data); } - -/* The following uid2sid/gid2sid functions has been contributed by - * Keith Reynolds */ - -static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *sid) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, bool success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2SID; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: uid to sid %lu\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.uid)); - - /* Find sid for this uid and return it, possibly ask the slow remote idmap */ - result = idmap_uid_to_sid(&sid, state->request.data.uid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_USER; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *sid) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2sid\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2sid returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.sid.sid); -} - -void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, bool success, const char *sid), - void *private_data) -{ - struct winbindd_request request; - - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2SID; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID sid; - NTSTATUS result; - - DEBUG(3,("[%5lu]: gid %lu to sid\n", - (unsigned long)state->pid, - (unsigned long) state->request.data.gid)); - - /* Find sid for this gid and return it, possibly ask the slow remote idmap */ - result = idmap_gid_to_sid(&sid, state->request.data.gid); - - if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); - DEBUG(10, ("[%5lu]: retrieved sid: %s\n", - (unsigned long)state->pid, - state->response.data.sid.sid)); - state->response.data.sid.type = SID_NAME_DOM_GRP; - return WINBINDD_OK; - } - - return WINBINDD_ERROR; -} - -static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ) = - (void (*)(void *, bool))c; - - if (!success) { - DEBUG(5, ("Could not trigger a map dump\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap dump maps returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, - void (*cont)(void *private_data, bool success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_DUMP_MAPS; - request.extra_data.data = (char *)data; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); - - idmap_dump_maps((char *)state->request.extra_data.data); - - return WINBINDD_OK; -} - diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c new file mode 100644 index 0000000000..5f0243b2f4 --- /dev/null +++ b/source3/winbindd/winbindd_idmap.c @@ -0,0 +1,778 @@ +/* + Unix SMB/CIFS implementation. + + Async helpers for blocking functions + + Copyright (C) Volker Lendecke 2005 + Copyright (C) Gerald Carter 2006 + + The helpers always consist of three functions: + + * A request setup function that takes the necessary parameters together + with a continuation function that is to be called upon completion + + * A private continuation function that is internal only. This is to be + called by the lower-level functions in do_async(). Its only task is to + properly call the continuation function named above. + + * A worker function that is called inside the appropriate child process. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_mapping\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_mapping returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, + void (*cont)(void *private_data, bool success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_MAPPING; + request.data.dual_idmapset.id = map->xid.id; + request.data.dual_idmapset.type = map->xid.type; + sid_to_string(request.data.dual_idmapset.sid, map->sid); + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct id_map map; + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid)); + + if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) + return WINBINDD_ERROR; + + map.sid = &sid; + map.xid.id = state->request.data.dual_idmapset.id; + map.xid.type = state->request.data.dual_idmapset.type; + map.status = ID_MAPPED; + + result = idmap_set_mapping(&map); + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c; + + if (!success) { + DEBUG(5, ("Could not trigger idmap_set_hwm\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap_set_hwm returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, + void (*cont)(void *private_data, bool success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SET_HWM; + request.data.dual_idmapset.id = xid->id; + request.data.dual_idmapset.type = xid->type; + + do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct unixid xid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid)); + + xid.id = state->request.data.dual_idmapset.id; + xid.type = state->request.data.dual_idmapset.type; + + switch (xid.type) { + case ID_TYPE_UID: + result = idmap_set_uid_hwm(&xid); + break; + case ID_TYPE_GID: + result = idmap_set_gid_hwm(&xid); + break; + default: + return WINBINDD_ERROR; + } + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, void *, int) = + (void (*)(void *, bool, void *, int))c; + + if (!success) { + DEBUG(5, ("Could not trigger sids2xids\n")); + cont(private_data, False, NULL, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sids2xids returned an error\n")); + cont(private_data, False, NULL, 0); + return; + } + + cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); +} + +void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, + void (*cont)(void *private_data, bool success, void *data, int len), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SIDS2XIDS; + request.extra_data.data = (char *)sids; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID *sids; + struct unixid *xids; + struct id_map **ids; + NTSTATUS result; + int num, i; + + DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); + + if (state->request.extra_len == 0) { + DEBUG(0, ("Invalid buffer size!\n")); + return WINBINDD_ERROR; + } + + sids = (DOM_SID *)state->request.extra_data.data; + num = state->request.extra_len / sizeof(DOM_SID); + + ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); + if ( ! ids) { + DEBUG(0, ("Out of memory!\n")); + return WINBINDD_ERROR; + } + for (i = 0; i < num; i++) { + ids[i] = TALLOC_P(ids, struct id_map); + if ( ! ids[i]) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + ids[i]->sid = &sids[i]; + } + + result = idmap_sids_to_unixids(ids); + + if (NT_STATUS_IS_OK(result)) { + + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } + + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } + } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; + + } else { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; + } + + talloc_free(ids); + return WINBINDD_OK; +} + +static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, uid_t uid) = + (void (*)(void *, bool, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} + +void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, bool success, uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2UID; + sid_to_string(request.data.dual_sid2id.sid, sid); + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data); + +void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, bool success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2NAME; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, uid2name_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); + + pw = getpwuid(state->request.data.uid); + if (pw == NULL) { + DEBUG(5, ("User %lu not found\n", + (unsigned long)state->request.data.uid)); + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.name.name, pw->pw_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, const char *name) = + (void (*)(void *, bool, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, bool success, + uid_t uid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2UID; + fstrcpy(request.data.username, name); + do_async(mem_ctx, idmap_child(), &request, name2uid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct passwd *pw; + + /* Ensure null termination */ + state->request.data.username + [sizeof(state->request.data.username)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, + state->request.data.username)); + + pw = getpwnam(state->request.data.username); + if (pw == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.uid = pw->pw_uid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, uid_t uid) = + (void (*)(void *, bool, uid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2uid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2uid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.uid); +} +#endif /* not used */ + +static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, gid_t gid) = + (void (*)(void *, bool, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger sid2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("sid2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} + +void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, bool success, gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_SID2GID; + sid_to_string(request.data.dual_sid2id.sid, sid); + + DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", + request.data.dual_sid2id.sid)); + + do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, + state->request.data.dual_sid2id.sid)); + + if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) { + DEBUG(1, ("Could not get convert sid %s from string\n", + state->request.data.dual_sid2id.sid)); + return WINBINDD_ERROR; + } + + /* Find gid for this sid and return it, possibly ask the slow remote idmap */ + + result = idmap_sid_to_gid(&sid, &state->response.data.gid); + + DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +static void gid2name_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, const char *name) = + (void (*)(void *, bool, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2name\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2name returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.name.name); +} + +void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, bool success, + const char *name), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2NAME; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, gid2name_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); + + gr = getgrgid(state->request.data.gid); + if (gr == NULL) + return WINBINDD_ERROR; + + fstrcpy(state->response.data.name.name, gr->gr_name); + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data); + +static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, + void (*cont)(void *private_data, bool success, + gid_t gid), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_NAME2GID; + fstrcpy(request.data.groupname, name); + do_async(mem_ctx, idmap_child(), &request, name2gid_recv, + (void *)cont, private_data); +} +#endif /* not used */ + +enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct group *gr; + + /* Ensure null termination */ + state->request.data.groupname + [sizeof(state->request.data.groupname)-1] = '\0'; + + DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, + state->request.data.groupname)); + + gr = getgrnam(state->request.data.groupname); + if (gr == NULL) { + return WINBINDD_ERROR; + } + + state->response.data.gid = gr->gr_gid; + return WINBINDD_OK; +} + +#if 0 /* not used */ +static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, gid_t gid) = + (void (*)(void *, bool, gid_t))c; + + if (!success) { + DEBUG(5, ("Could not trigger name2gid\n")); + cont(private_data, False, 0); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("name2gid returned an error\n")); + cont(private_data, False, 0); + return; + } + + cont(private_data, True, response->data.gid); +} +#endif /* not used */ + +/* The following uid2sid/gid2sid functions has been contributed by + * Keith Reynolds */ + +static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, const char *sid) = + (void (*)(void *, bool, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger uid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("uid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, bool success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_UID2SID; + request.data.uid = uid; + do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: uid to sid %lu\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.uid)); + + /* Find sid for this uid and return it, possibly ask the slow remote idmap */ + result = idmap_uid_to_sid(&sid, state->request.data.uid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_USER; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, const char *sid) = + (void (*)(void *, bool, const char *))c; + + if (!success) { + DEBUG(5, ("Could not trigger gid2sid\n")); + cont(private_data, False, NULL); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("gid2sid returned an error\n")); + cont(private_data, False, NULL); + return; + } + + cont(private_data, True, response->data.sid.sid); +} + +void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, bool success, const char *sid), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_GID2SID; + request.data.gid = gid; + do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DOM_SID sid; + NTSTATUS result; + + DEBUG(3,("[%5lu]: gid %lu to sid\n", + (unsigned long)state->pid, + (unsigned long) state->request.data.gid)); + + /* Find sid for this gid and return it, possibly ask the slow remote idmap */ + result = idmap_gid_to_sid(&sid, state->request.data.gid); + + if (NT_STATUS_IS_OK(result)) { + sid_to_string(state->response.data.sid.sid, &sid); + DEBUG(10, ("[%5lu]: retrieved sid: %s\n", + (unsigned long)state->pid, + state->response.data.sid.sid)); + state->response.data.sid.type = SID_NAME_DOM_GRP; + return WINBINDD_OK; + } + + return WINBINDD_ERROR; +} + +static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ) = + (void (*)(void *, bool))c; + + if (!success) { + DEBUG(5, ("Could not trigger a map dump\n")); + cont(private_data, False); + return; + } + + if (response->result != WINBINDD_OK) { + DEBUG(5, ("idmap dump maps returned an error\n")); + cont(private_data, False); + return; + } + + cont(private_data, True); +} + +void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, + void (*cont)(void *private_data, bool success), + void *private_data) +{ + struct winbindd_request request; + ZERO_STRUCT(request); + request.cmd = WINBINDD_DUAL_DUMP_MAPS; + request.extra_data.data = (char *)data; + request.extra_len = size; + do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); + + idmap_dump_maps((char *)state->request.extra_data.data); + + return WINBINDD_OK; +} -- cgit From 58e049efa3392e2ebfb39f4e63c876aace7b6e7b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:13:36 +0000 Subject: r25569: move more idmap stuff into winbindd_idmap.c metze (cherry picked from commit 953229f040580071f6ee09413f67f7edd3227728) (This used to be commit 590954407b5badfb9d6b8fb55077dc6a520fb816) --- source3/winbindd/winbindd_idmap.c | 12 ++++++++++++ source3/winbindd/winbindd_sid.c | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 5f0243b2f4..1d6beb3778 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -37,6 +37,18 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +static struct winbindd_child static_idmap_child; + +void init_idmap_child(void) +{ + setup_domain_child(NULL, &static_idmap_child, "idmap"); +} + +struct winbindd_child *idmap_child(void) +{ + return &static_idmap_child; +} + static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index f405f36d1b..601971e36b 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -152,18 +152,6 @@ void winbindd_lookuprids(struct winbindd_cli_state *state) sendto_domain(state, domain); } -static struct winbindd_child static_idmap_child; - -void init_idmap_child(void) -{ - setup_domain_child(NULL, &static_idmap_child, "idmap"); -} - -struct winbindd_child *idmap_child(void) -{ - return &static_idmap_child; -} - /* Convert a sid to a uid. We assume we only have one rid attached to the sid. */ -- cgit From 6ded271f7719483faee19aba502d787a279c1689 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 11:15:28 +0000 Subject: r25570: move code of the locator child into its own file metze (This used to be commit 56640908a6367acfdfd53568a0d329c13330e5eb) --- source3/winbindd/winbindd_locator.c | 90 +++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_misc.c | 64 -------------------------- 2 files changed, 90 insertions(+), 64 deletions(-) create mode 100644 source3/winbindd/winbindd_locator.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c new file mode 100644 index 0000000000..3fcb9de7a8 --- /dev/null +++ b/source3/winbindd/winbindd_locator.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - miscellaneous other functions + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Bartlett 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static struct winbindd_child static_locator_child; + +void init_locator_child(void) +{ + setup_domain_child(NULL, &static_locator_child, "locator"); +} + +struct winbindd_child *locator_child(void) +{ + return &static_locator_child; +} + +void winbindd_dsgetdcname(struct winbindd_cli_state *state) +{ + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + sendto_child(state, locator_child()); +} + +enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + const char *dc = NULL; + + state->request.domain_name + [sizeof(state->request.domain_name)-1] = '\0'; + + DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + state->request.domain_name)); + + result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, + NULL, NULL, state->request.flags, &info); + + if (!NT_STATUS_IS_OK(result)) { + return WINBINDD_ERROR; + } + + if (info->domain_controller_address) { + dc = info->domain_controller_address; + if ((dc[0] == '\\') && (dc[1] == '\\')) { + dc += 2; + } + } + + if ((!dc || !is_ipaddress_v4(dc)) && info->domain_controller_name) { + dc = info->domain_controller_name; + } + + if (!dc || !*dc) { + return WINBINDD_ERROR; + } + + fstrcpy(state->response.data.dc_name, dc); + + return WINBINDD_OK; +} diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index dc2e35884e..9d77879e76 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -289,70 +289,6 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, return WINBINDD_OK; } -static struct winbindd_child static_locator_child; - -void init_locator_child(void) -{ - setup_domain_child(NULL, &static_locator_child, "locator"); -} - -struct winbindd_child *locator_child(void) -{ - return &static_locator_child; -} - -void winbindd_dsgetdcname(struct winbindd_cli_state *state) -{ - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - sendto_child(state, locator_child()); -} - -enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - NTSTATUS result; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; - const char *dc = NULL; - - state->request.domain_name - [sizeof(state->request.domain_name)-1] = '\0'; - - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, - state->request.domain_name)); - - result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, - NULL, NULL, state->request.flags, &info); - - if (!NT_STATUS_IS_OK(result)) { - return WINBINDD_ERROR; - } - - if (info->domain_controller_address) { - dc = info->domain_controller_address; - if ((dc[0] == '\\') && (dc[1] == '\\')) { - dc += 2; - } - } - - if ((!dc || !is_ipaddress_v4(dc)) && info->domain_controller_name) { - dc = info->domain_controller_name; - } - - if (!dc || !*dc) { - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.dc_name, dc); - - return WINBINDD_OK; -} - - struct sequence_state { TALLOC_CTX *mem_ctx; struct winbindd_cli_state *cli_state; -- cgit From 3d9a578064d46e595a51af5896a51db47bd2da4e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Oct 2007 12:25:57 +0000 Subject: r25571: split up child_dispatch_table into domain, idmap and locator tables metze (cherry picked from commit abbb36a37c1dba2218a6c7ec31739eba5f250127) (This used to be commit 5af1b45ed31043f952ec141d0f5f2973aec69d1a) --- source3/winbindd/winbindd.h | 13 ++++++++++++ source3/winbindd/winbindd_dual.c | 40 +++++++++---------------------------- source3/winbindd/winbindd_idmap.c | 30 +++++++++++++++++++++++++++- source3/winbindd/winbindd_locator.c | 18 ++++++++++++++--- source3/winbindd/winbindd_util.c | 27 +++++++++++++++++++------ 5 files changed, 87 insertions(+), 41 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 5fc083f7a9..e4b1396cac 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -134,6 +134,17 @@ struct winbindd_async_request; /* Async child */ +struct winbindd_domain; + +struct winbindd_child_dispatch_table { + enum winbindd_cmd cmd; + enum winbindd_result (*fn)(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + const char *winbindd_cmd_name; +}; + +extern const struct winbindd_child_dispatch_table domain_dispatch_table[]; + struct winbindd_child { struct winbindd_child *next, *prev; @@ -144,6 +155,8 @@ struct winbindd_child { struct fd_event event; struct timed_event *lockout_policy_event; struct winbindd_async_request *requests; + + const struct winbindd_child_dispatch_table *table; }; /* Structures to hold per domain information */ diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 932fc328cf..c96941531a 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -408,23 +408,14 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } +const struct winbindd_child_dispatch_table domain_dispatch_table[] = { -struct winbindd_child_dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -static struct winbindd_child_dispatch_table child_dispatch_table[] = { - { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, - { WINBINDD_DSGETDCNAME, winbindd_dual_dsgetdcname, "DSGETDCNAME" }, { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, @@ -432,23 +423,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = { { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, - { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, -#endif /* end DISABLED */ - { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, - { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, - { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, - { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, - { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, - { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, - { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, - { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, - { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, - { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, @@ -457,10 +432,11 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = { { WINBINDD_NUM_CMDS, NULL, "NONE" } }; -static void child_process_request(struct winbindd_domain *domain, +static void child_process_request(struct winbindd_child *child, struct winbindd_cli_state *state) { - struct winbindd_child_dispatch_table *table; + struct winbindd_domain *domain = child->domain; + const struct winbindd_child_dispatch_table *table = child->table; /* Free response data - we may be interrupted and receive another command before being able to send this data off. */ @@ -473,7 +449,7 @@ static void child_process_request(struct winbindd_domain *domain, /* Process command */ - for (table = child_dispatch_table; table->fn; table++) { + for (; table->fn; table++) { if (state->request.cmd == table->cmd) { DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name )); @@ -483,7 +459,7 @@ static void child_process_request(struct winbindd_domain *domain, } if (!table->fn) { - DEBUG(10,("process_request: unknown request fn number %d\n", + DEBUG(1 ,("child_process_request: unknown request fn number %d\n", (int)state->request.cmd )); state->response.result = WINBINDD_ERROR; } @@ -491,6 +467,7 @@ static void child_process_request(struct winbindd_domain *domain, void setup_domain_child(struct winbindd_domain *domain, struct winbindd_child *child, + const struct winbindd_child_dispatch_table *table, const char *explicit_logfile) { if (explicit_logfile != NULL) { @@ -505,6 +482,7 @@ void setup_domain_child(struct winbindd_domain *domain, } child->domain = domain; + child->table = table; } struct winbindd_child *children = NULL; @@ -1106,7 +1084,7 @@ static bool fork_domain_child(struct winbindd_child *child) ZERO_STRUCT(state.response); state.request.null_term = '\0'; - child_process_request(child->domain, &state); + child_process_request(child, &state); SAFE_FREE(state.request.extra_data.data); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 1d6beb3778..437af41872 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -37,11 +37,16 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +static const struct winbindd_child_dispatch_table idmap_dispatch_table[]; + static struct winbindd_child static_idmap_child; void init_idmap_child(void) { - setup_domain_child(NULL, &static_idmap_child, "idmap"); + setup_domain_child(NULL, + &static_idmap_child, + idmap_dispatch_table, + "idmap"); } struct winbindd_child *idmap_child(void) @@ -788,3 +793,26 @@ enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, return WINBINDD_OK; } + +static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { + + { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, + { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, +#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ + { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, +#endif /* end DISABLED */ + { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, + { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, + { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, + { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, + { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, + { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, + { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, + { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, + { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, + { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, + { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, + /* End of list */ + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 3fcb9de7a8..7db2e2ada0 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -26,11 +26,17 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND + +static const struct winbindd_child_dispatch_table locator_dispatch_table[]; + static struct winbindd_child static_locator_child; void init_locator_child(void) { - setup_domain_child(NULL, &static_locator_child, "locator"); + setup_domain_child(NULL, + &static_locator_child, + locator_dispatch_table, + "locator"); } struct winbindd_child *locator_child(void) @@ -49,8 +55,8 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state) sendto_child(state, locator_child()); } -enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, - struct winbindd_cli_state *state) +static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state) { NTSTATUS result; struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; @@ -88,3 +94,9 @@ enum winbindd_result winbindd_dual_dsgetdcname(struct winbindd_domain *domain, return WINBINDD_OK; } + +static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { + { WINBINDD_DSGETDCNAME, dual_dsgetdcname, "DSGETDCNAME" }, + + { WINBINDD_NUM_CMDS, NULL, "NONE" } +}; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 54bb5a24b7..8970c1faf9 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -325,7 +325,10 @@ static void trustdom_recv(void *private_data, bool success) &cache_methods, &sid); if (domain) { - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } } p=q; @@ -694,7 +697,10 @@ bool init_domain_list(void) domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, &global_sid_Builtin); if (domain) { - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } /* Local SAM */ @@ -705,7 +711,10 @@ bool init_domain_list(void) if ( role != ROLE_DOMAIN_MEMBER ) { domain->primary = True; } - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); } /* Add ourselves as the first entry. */ @@ -722,8 +731,11 @@ bool init_domain_list(void) &cache_methods, &our_sid); if (domain) { domain->primary = True; - setup_domain_child(domain, &domain->child, NULL); - + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); + /* Even in the parent winbindd we'll need to talk to the DC, so try and see if we can contact it. Theoretically this isn't neccessary @@ -768,7 +780,10 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid ) domain->internal = False; domain->online = True; - setup_domain_child(domain, &domain->child, NULL); + setup_domain_child(domain, + &domain->child, + domain_dispatch_table, + NULL); wcache_tdc_add_domain( domain ); -- cgit From 5e8086e9a2c6bc2d68b06d7c70261bf0f75636db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 8 Oct 2007 12:56:57 +0000 Subject: r25573: Add my (C) as well (cherry picked from commit a024e27e7136deb87aeed995348a1c494a850ce6) (This used to be commit 37ee6f498b175b8f3b7e75eba8dd7c709327384c) --- source3/winbindd/winbindd_idmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 437af41872..250b2d2e85 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -5,6 +5,7 @@ Copyright (C) Volker Lendecke 2005 Copyright (C) Gerald Carter 2006 + Copyright (C) Simo Sorce 2007 The helpers always consist of three functions: -- cgit From 6a6c549cdc24ae49aced26020cc7b08da921e537 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Oct 2007 13:19:35 +0200 Subject: handle wellknown sids in winbindd_passwd.c metze (This used to be commit 251bd4ea4cdd0a751ed3b91562272221af148e37) --- source3/winbindd/winbindd_passdb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index cfb934eb60..f925ac2153 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -140,7 +140,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, !sid_check_is_in_unix_users(sid) && !sid_check_is_unix_users(sid) && !sid_check_is_in_unix_groups(sid) && - !sid_check_is_unix_groups(sid) ) + !sid_check_is_unix_groups(sid) && + !sid_check_is_in_wellknown_domain(sid)) { DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with " "passdb backend\n", sid_string_static(sid))); -- cgit From f88b7a076be74a29a3bf876b4e2705f4a1ecf42b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Oct 2007 14:16:54 -0700 Subject: This is a large patch (sorry). Migrate from struct in_addr to struct sockaddr_storage in most places that matter (ie. not the nmbd and NetBIOS lookups). This passes make test on an IPv4 box, but I'll have to do more work/testing on IPv6 enabled boxes. This should now give us a framework for testing and finishing the IPv6 migration. It's at the state where someone with a working IPv6 setup should (theorecically) be able to type : smbclient //ipv6-address/share and have it work. Jeremy. (This used to be commit 98e154c3125d5732c37a72d74b0eb5cd7b6155fd) --- source3/winbindd/winbindd.h | 2 +- source3/winbindd/winbindd_ads.c | 18 ++--- source3/winbindd/winbindd_cm.c | 169 +++++++++++++++++++++++++-------------- source3/winbindd/winbindd_rpc.c | 16 ++-- source3/winbindd/winbindd_util.c | 6 +- source3/winbindd/winbindd_wins.c | 74 +++++++++-------- 6 files changed, 172 insertions(+), 113 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index e4b1396cac..454a4b9698 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -191,7 +191,7 @@ struct winbindd_domain { /* A working DC */ fstring dcname; - struct sockaddr_in dcaddr; + struct sockaddr_storage dcaddr; /* Sequence number stuff */ diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 3f3f06e3fd..6549c6d7d2 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -40,7 +40,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ADS_STRUCT *ads; ADS_STATUS status; fstring dc_name; - struct in_addr dc_ip; + struct sockaddr_storage dc_ss; DEBUG(10,("ads_cached_connection\n")); @@ -66,7 +66,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ads_destroy( &ads ); ads_kdestroy("MEMORY:winbind_ccache"); domain->private_data = NULL; - } + } } /* we don't want this to affect the users ccache */ @@ -99,7 +99,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - /* always give preference to the alt_name in our + /* always give preference to the alt_name in our primary domain if possible */ if ( !domain->primary ) @@ -116,14 +116,14 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME; /* Setup the server affinity cache. We don't reaally care - about the name. Just setup affinity and the KRB5_CONFIG + about the name. Just setup affinity and the KRB5_CONFIG file. */ - get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip ); - + get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ss ); + status = ads_connect(ads); if (!ADS_ERR_OK(status) || !ads->config.realm) { - DEBUG(1,("ads_connect for domain %s failed: %s\n", + DEBUG(1,("ads_connect for domain %s failed: %s\n", domain->name, ads_errstr(status))); ads_destroy(&ads); @@ -138,8 +138,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) return NULL; } - /* set the flag that says we don't own the memory even - though we do so that ads_destroy() won't destroy the + /* set the flag that says we don't own the memory even + though we do so that ads_destroy() won't destroy the structure we pass back by reference */ ads->is_mine = False; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 055563d815..4c9ae0365f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -66,7 +66,7 @@ struct dc_name_ip { fstring name; - struct in_addr ip; + struct sockaddr_storage ss; }; extern struct winbindd_methods reconnect_methods; @@ -559,7 +559,8 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) } static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, - fstring dcname, struct in_addr *dc_ip) + fstring dcname, + struct sockaddr_storage *dc_ss) { struct winbindd_domain *our_domain = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -625,7 +626,7 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname)); - if (!resolve_name(dcname, dc_ip, 0x20)) { + if (!resolve_name(dcname, dc_ss, 0x20)) { return False; } @@ -891,7 +892,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, } static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, - const char *dcname, struct in_addr ip, + const char *dcname, struct sockaddr_storage *pss, struct dc_name_ip **dcs, int *num) { if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) { @@ -905,26 +906,23 @@ static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, return False; fstrcpy((*dcs)[*num].name, dcname); - (*dcs)[*num].ip = ip; + (*dcs)[*num].ss = *pss; *num += 1; return True; } static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, - struct in_addr ip, uint16 port, - struct sockaddr_in **addrs, int *num) + struct sockaddr_storage *pss, uint16 port, + struct sockaddr_storage **addrs, int *num) { - *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1); + *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1); if (*addrs == NULL) { *num = 0; return False; } - (*addrs)[*num].sin_family = PF_INET; - putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip); - (*addrs)[*num].sin_port = htons(port); - + (*addrs)[*num] = *pss; *num += 1; return True; } @@ -934,15 +932,21 @@ static void mailslot_name(struct in_addr dc_ip, fstring name) fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr); } -static bool send_getdc_request(struct in_addr dc_ip, +static bool send_getdc_request(struct sockaddr_storage *dc_ss, const char *domain_name, const DOM_SID *sid) { - pstring outbuf; + char outbuf[1024]; + struct in_addr dc_ip; char *p; fstring my_acct_name; fstring my_mailslot; + if (dc_ss->ss_family != AF_INET) { + return false; + } + + dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; mailslot_name(dc_ip, my_mailslot); memset(outbuf, '\0', sizeof(outbuf)); @@ -958,13 +962,23 @@ static bool send_getdc_request(struct in_addr dc_ip, SIVAL(p, 0, 0); /* The sender's token ... */ p += 2; - p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True); + p += dos_PutUniCode(p, global_myname(), + sizeof(outbuf) - PTR_DIFF(p, outbuf), True); fstr_sprintf(my_acct_name, "%s$", global_myname()); - p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True); + p += dos_PutUniCode(p, my_acct_name, + sizeof(outbuf) - PTR_DIFF(p, outbuf), True); + + if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + return false; + } memcpy(p, my_mailslot, strlen(my_mailslot)+1); p += strlen(my_mailslot)+1; + if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) { + return false; + } + SIVAL(p, 0, 0x80); p+=4; @@ -972,8 +986,15 @@ static bool send_getdc_request(struct in_addr dc_ip, p+=4; p = ALIGN4(p, outbuf); + if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) { + return false; + } sid_linearize(p, sid_size(sid), sid); + if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + return false; + } + p += sid_size(sid); SIVAL(p, 0, 1); @@ -985,10 +1006,10 @@ static bool send_getdc_request(struct in_addr dc_ip, False, "\\MAILSLOT\\NET\\NTLOGON", 0, outbuf, PTR_DIFF(p, outbuf), global_myname(), 0, domain_name, 0x1c, - dc_ip); + dc_ss); } -static bool receive_getdc_response(struct in_addr dc_ip, +static bool receive_getdc_response(struct sockaddr_storage *dc_ss, const char *domain_name, fstring dc_name) { @@ -997,7 +1018,12 @@ static bool receive_getdc_response(struct in_addr dc_ip, char *buf, *p; fstring dcname, user, domain; int len; + struct in_addr dc_ip; + if (dc_ss->ss_family != AF_INET) { + return false; + } + dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; mailslot_name(dc_ip, my_mailslot); packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot); @@ -1060,11 +1086,13 @@ static bool receive_getdc_response(struct in_addr dc_ip, convert an ip to a name *******************************************************************/ -static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name ) +static bool dcip_to_name(const struct winbindd_domain *domain, + struct sockaddr_storage *pss, + fstring name ) { struct ip_service ip_list; - ip_list.ip = ip; + ip_list.ss = *pss; ip_list.port = 0; #ifdef WITH_ADS @@ -1073,11 +1101,14 @@ static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip if (lp_security() == SEC_ADS) { ADS_STRUCT *ads; + char addr[INET6_ADDRSTRLEN]; + + print_sockaddr(addr, sizeof(addr), pss); ads = ads_init(domain->alt_name, domain->name, NULL); ads->auth.flags |= ADS_AUTH_NO_BIND; - if (ads_try_connect( ads, inet_ntoa(ip) ) ) { + if (ads_try_connect(ads, addr)) { /* We got a cldap packet. */ fstrcpy(name, ads->config.ldap_server_name); namecache_store(name, 0x20, 1, &ip_list); @@ -1095,7 +1126,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip create_local_private_krb5_conf_for_domain(domain->alt_name, domain->name, sitename, - ip); + pss); SAFE_FREE(sitename); } else { @@ -1103,7 +1134,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip create_local_private_krb5_conf_for_domain(domain->alt_name, domain->name, NULL, - ip); + pss); } winbindd_set_locator_kdc_envs(domain); @@ -1121,12 +1152,12 @@ static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip #endif /* try GETDC requests next */ - - if (send_getdc_request(ip, domain->name, &domain->sid)) { + + if (send_getdc_request(pss, domain->name, &domain->sid)) { int i; smb_msleep(100); for (i=0; i<5; i++) { - if (receive_getdc_response(ip, domain->name, name)) { + if (receive_getdc_response(pss, domain->name, name)) { namecache_store(name, 0x20, 1, &ip_list); return True; } @@ -1136,7 +1167,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip /* try node status request */ - if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) { + if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) { namecache_store(name, 0x20, 1, &ip_list); return True; } @@ -1152,7 +1183,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs) { fstring dcname; - struct in_addr ip; + struct sockaddr_storage ss; struct ip_service *ip_list = NULL; int iplist_size = 0; int i; @@ -1161,12 +1192,14 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, is_our_domain = strequal(domain->name, lp_workgroup()); - if ( !is_our_domain - && get_dc_name_via_netlogon(domain, dcname, &ip) - && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) ) + if ( !is_our_domain + && get_dc_name_via_netlogon(domain, dcname, &ss) + && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) ) { + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), &ss); DEBUG(10, ("Retrieved DC %s at %s via netlogon\n", - dcname, inet_ntoa(ip))); + dcname, addr)); return True; } @@ -1182,7 +1215,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, We deliberately don't care about the return here. */ - get_dc_name(domain->name, domain->alt_name, dcname, &ip); + get_dc_name(domain->name, domain->alt_name, dcname, &ss); sitename = sitename_fetch(domain->alt_name); if (sitename) { @@ -1191,8 +1224,15 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True); for ( i=0; iname, inet_ntoa(ip_list[i].ip), - ip_list[i].ip, dcs, num_dcs); + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), + &ip_list[i].ss); + add_one_dc_unique(mem_ctx, + domain->name, + addr, + &ip_list[i].ss, + dcs, + num_dcs); } SAFE_FREE(ip_list); @@ -1204,8 +1244,15 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True); for ( i=0; iname, inet_ntoa(ip_list[i].ip), - ip_list[i].ip, dcs, num_dcs); + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), + &ip_list[i].ss); + add_one_dc_unique(mem_ctx, + domain->name, + addr, + &ip_list[i].ss, + dcs, + num_dcs); } } @@ -1222,8 +1269,11 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, the ip now in to make the failed connection cache work */ for ( i=0; iname, inet_ntoa(ip_list[i].ip), - ip_list[i].ip, dcs, num_dcs); + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), + &ip_list[i].ss); + add_one_dc_unique(mem_ctx, domain->name, addr, + &ip_list[i].ss, dcs, num_dcs); } SAFE_FREE( ip_list ); @@ -1233,7 +1283,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, static bool find_new_dc(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, - fstring dcname, struct sockaddr_in *addr, int *fd) + fstring dcname, struct sockaddr_storage *pss, int *fd) { struct dc_name_ip *dcs = NULL; int num_dcs = 0; @@ -1241,7 +1291,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, const char **dcnames = NULL; int num_dcnames = 0; - struct sockaddr_in *addrs = NULL; + struct sockaddr_storage *addrs = NULL; int num_addrs = 0; int i, fd_index; @@ -1256,7 +1306,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, &dcnames, &num_dcnames)) { return False; } - if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445, + if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445, &addrs, &num_addrs)) { return False; } @@ -1265,7 +1315,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, &dcnames, &num_dcnames)) { return False; } - if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139, + if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139, &addrs, &num_addrs)) { return False; } @@ -1278,28 +1328,29 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, return False; /* 5 second timeout. */ - if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) - { + if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) { for (i=0; iname, inet_ntoa(dcs[i].ip), strerror(errno) )); + domain->name, ab, strerror(errno) )); winbind_add_failed_connection_entry(domain, dcs[i].name, NT_STATUS_UNSUCCESSFUL); } return False; } - *addr = addrs[fd_index]; + *pss = addrs[fd_index]; - if (*dcnames[fd_index] != '\0' && !is_ipaddress_v4(dcnames[fd_index])) { + if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) { /* Ok, we've got a name for the DC */ fstrcpy(dcname, dcnames[fd_index]); return True; } /* Try to figure out the name */ - if (dcip_to_name( domain, addr->sin_addr, dcname )) { + if (dcip_to_name(domain, pss, dcname)) { return True; } @@ -1336,12 +1387,15 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, saf_servername, domain->name )); /* convert an ip address to a name */ - if ( is_ipaddress_v4( saf_servername ) ) { + if (is_ipaddress( saf_servername ) ) { fstring saf_name; - struct in_addr ip; + struct sockaddr_storage ss; - ip = *interpret_addr2( saf_servername ); - if (dcip_to_name( domain, ip, saf_name )) { + if (!interpret_string_addr(&ss, saf_servername, + AI_NUMERICHOST)) { + return NT_STATUS_UNSUCCESSFUL; + } + if (dcip_to_name( domain, &ss, saf_name )) { fstrcpy( domain->dcname, saf_name ); } else { winbind_add_failed_connection_entry( @@ -1356,7 +1410,6 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, } for (retries = 0; retries < 3; retries++) { - int fd = -1; bool retry = False; @@ -1367,18 +1420,18 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, if (*domain->dcname && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) - && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20))) + && (resolve_name(domain->dcname, &domain->dcaddr, 0x20))) { - struct sockaddr_in *addrs = NULL; + struct sockaddr_storage *addrs = NULL; int num_addrs = 0; int dummy = 0; - if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) { + if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) { set_domain_offline(domain); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } - if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) { + if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) { set_domain_offline(domain); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 7035f6bffb..55212a84b8 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -843,20 +843,20 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq) /********************************************************************** Get the sequence number for a Windows AD native mode domain using - LDAP queries. + LDAP queries. **********************************************************************/ static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq) { int ret = -1; - fstring ipstr; + char addr[INET6_ADDRSTRLEN]; - fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr)); - if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) { + print_sockaddr(addr, sizeof(addr), &domain->dcaddr); + if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) { DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence " - "number for Domain (%s) from DC (%s)\n", - domain->name, ipstr)); - } + "number for Domain (%s) from DC (%s)\n", + domain->name, addr)); + } return ret; } @@ -877,7 +877,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(10,("sequence_number: No incoming trust for domain %s\n", domain->name)); - *seq = time(NULL); + *seq = time(NULL); return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 8970c1faf9..5c8c8ea13d 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1438,6 +1438,7 @@ bool winbindd_internal_child(struct winbindd_child *child) static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain) { char *var = NULL; + char addr[INET6_ADDRSTRLEN]; const char *kdc = NULL; int lvl = 11; @@ -1451,8 +1452,9 @@ static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain) return; } - kdc = inet_ntoa(domain->dcaddr.sin_addr); - if (!kdc) { + print_sockaddr(addr, sizeof(addr), &domain->dcaddr); + kdc = addr; + if (!*kdc) { DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n", domain->alt_name)); kdc = domain->dcname; diff --git a/source3/winbindd/winbindd_wins.c b/source3/winbindd/winbindd_wins.c index 2ee6f69b66..4a3d2682b6 100644 --- a/source3/winbindd/winbindd_wins.c +++ b/source3/winbindd/winbindd_wins.c @@ -64,10 +64,10 @@ static int wins_lookup_open_socket_in(void) } -static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) +static NODE_STATUS_STRUCT *lookup_byaddr_backend(const char *addr, int *count) { int fd; - struct in_addr ip; + struct sockaddr_storage ss; struct nmb_name nname; NODE_STATUS_STRUCT *status; @@ -76,18 +76,21 @@ static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) return NULL; make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count, NULL); + if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) { + return NULL; + } + status = node_status_query(fd, &nname, &ss, count, NULL); close(fd); return status; } -static struct in_addr *lookup_byname_backend(const char *name, int *count) +static struct sockaddr_storage *lookup_byname_backend(const char *name, + int *count) { int fd; struct ip_service *ret = NULL; - struct in_addr *return_ip = NULL; + struct sockaddr_storage *return_ss = NULL; int j, i, flags = 0; *count = 0; @@ -96,17 +99,17 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) if (NT_STATUS_IS_OK(resolve_wins(name,0x20,&ret,count))) { if ( *count == 0 ) return NULL; - if ( (return_ip = SMB_MALLOC_ARRAY(struct in_addr, *count)) == NULL ) { + if ( (return_ss = SMB_MALLOC_ARRAY(struct sockaddr_storage, *count)) == NULL ) { free( ret ); return NULL; } /* copy the IP addresses */ - for ( i=0; i<(*count); i++ ) - return_ip[i] = ret[i].ip; - + for ( i=0; i<(*count); i++ ) + return_ss[i] = ret[i].ss; + free( ret ); - return return_ip; + return return_ss; } fd = wins_lookup_open_socket_in(); @@ -118,18 +121,18 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) for (j=iface_count() - 1; j >= 0; j--) { - const struct in_addr *bcast = iface_n_bcast_v4(j); - if (!bcast) { + const struct sockaddr_storage *bcast_ss = iface_n_bcast(j); + if (!bcast_ss) { continue; } - return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (return_ip) { + return_ss = name_query(fd,name,0x20,True,True,bcast_ss,count, &flags, NULL); + if (return_ss) { break; } } close(fd); - return return_ip; + return return_ss; } /* Get hostname from IP */ @@ -184,10 +187,10 @@ void winbindd_wins_byip(struct winbindd_cli_state *state) void winbindd_wins_byname(struct winbindd_cli_state *state) { - struct in_addr *ip_list; + struct sockaddr_storage *ip_list = NULL; int i, count, maxlen, size; fstring response; - char * addr; + char addr[INET6_ADDRSTRLEN]; /* Ensure null termination */ state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; @@ -200,29 +203,30 @@ void winbindd_wins_byname(struct winbindd_cli_state *state) if ((ip_list = lookup_byname_backend(state->request.data.winsreq,&count))){ for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr); - if (size > maxlen) { - SAFE_FREE(ip_list); - request_error(state); - return; - } - if (i != 0) { - /* Clear out the newline character */ - /* But only if there is something in there, - otherwise we clobber something in the stack */ - if (strlen(response)) - response[strlen(response)-1] = ' '; - } - fstrcat(response,addr); - fstrcat(response,"\t"); + print_sockaddr(addr, sizeof(addr), &ip_list[i-1]); + size = strlen(addr); + if (size > maxlen) { + SAFE_FREE(ip_list); + request_error(state); + return; + } + if (i != 0) { + /* Clear out the newline character */ + /* But only if there is something in there, + otherwise we clobber something in the stack */ + if (strlen(response)) { + response[strlen(response)-1] = ' '; + } + } + fstrcat(response,addr); + fstrcat(response,"\t"); } size = strlen(state->request.data.winsreq) + strlen(response); if (size > maxlen) { SAFE_FREE(ip_list); request_error(state); return; - } + } fstrcat(response,state->request.data.winsreq); fstrcat(response,"\n"); SAFE_FREE(ip_list); -- cgit From a97b33baad5bbce7e8004346aa3a812ec4f91f0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Oct 2007 21:15:07 +0200 Subject: Two patches Hi! Can you check and push them? Thanks, Volker From b488af5905e2dee12a1a72a3b40801ae5c26f24f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Oct 2007 14:20:09 +0200 Subject: [PATCH] Fix some warnings and errors (This used to be commit e17d3e10e860c96b6d5208e5fe51e43b8e58c174) --- source3/winbindd/idmap_ad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 0d190eb4a1..50f7914f85 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -60,7 +60,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) ADS_STATUS status; bool local = False; fstring dc_name; - struct in_addr dc_ip; + struct sockaddr_storage dc_ip; if (ad_idmap_ads != NULL) { -- cgit From 851ef9e22f5f58202b0c5594b4432941afb0e130 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Oct 2007 15:44:27 +0100 Subject: start smbd, nmbd and winbindd with the same startup message at debug level 0. metze (This used to be commit 95f76ae7a52c6b22db22d03fed6b0848d2a61bee) --- source3/winbindd/winbindd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 8449795e13..ee993efca5 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1091,9 +1091,8 @@ int main(int argc, char **argv, char **envp) setup_logging("winbindd", log_stdout); reopen_logs(); - DEBUG(1, ("winbindd version %s started.\n%s\n", - SAMBA_VERSION_STRING, - COPYRIGHT_STARTUP_MESSAGE) ); + DEBUG(0,("winbindd version %s started.\n", SAMBA_VERSION_STRING)); + DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); if (!reload_services_file()) { DEBUG(0, ("error opening config file\n")); -- cgit From 88ee61625a5de5e443d14c54eab91a90d87cda85 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Thu, 1 Nov 2007 15:53:44 -0400 Subject: Patch 2 of 3 from Debian Samba packagers: The point is doing the following associations: - non discardable state data (all TDB files that may need to be backed up) go to statedir - shared data (codepage stuff) go to codepagedir The patch *does not change* the default location for these directories. So, there is no behaviour change when applying it. The main change is for samba developers who have to think when dealing with files that previously pertained to libdir whether they: - go in statedir - go in codepagedir - stay in libdir (This used to be commit d6cdbfd875bb2653e831d314726c3240beb0a96b) --- source3/winbindd/idmap_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 881377bda6..1ec7085a3b 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -221,7 +221,7 @@ static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx) } /* use the old database if present */ - tdbfile = talloc_strdup(ctx, lock_path("winbindd_idmap.tdb")); + tdbfile = talloc_strdup(ctx, state_path("winbindd_idmap.tdb")); if (!tdbfile) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; -- cgit From 36441da4240f3e3a296eed65f0796b25b7b05a3a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Nov 2007 11:12:56 -0800 Subject: Remove the horror that was the global smb_rw_error. Each cli struct has it's own local copy of this variable, so use that in client code. In the smbd server, add one static to smbd/proccess.c and use that inside smbd. Fix a bunch of places where smb_rw_error could be set by calling read_data() in places where we weren't reading from the SMB client socket (ie. winbindd). Jeremy. (This used to be commit 255c2adf7b6ef30932b5bb9f142ccef4a5d3d0db) --- source3/winbindd/winbindd_dual.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index c96941531a..c15af710f4 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -44,7 +44,7 @@ static void child_read_request(struct winbindd_cli_state *state) /* Read data */ len = read_data(state->sock, (char *)&state->request, - sizeof(state->request)); + sizeof(state->request), NULL); if (len != sizeof(state->request)) { DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len)); @@ -72,7 +72,7 @@ static void child_read_request(struct winbindd_cli_state *state) state->request.extra_data.data[state->request.extra_len] = '\0'; len = read_data(state->sock, state->request.extra_data.data, - state->request.extra_len); + state->request.extra_len, NULL); if (len != state->request.extra_len) { DEBUG(0, ("Could not read extra data\n")); -- cgit From 68be9a820059ee96dd26c527efd7c14e679d3f2c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2007 14:19:52 -0800 Subject: More pstring removal. This one was tricky. I had to add one horror (pstring_clean_name()) which will have to remain until I've removed all pstrings from the client code. Jeremy. (This used to be commit 1ea3ac80146b83c2522b69e7747c823366a2b47d) --- source3/winbindd/winbindd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index ee993efca5..2167cfcdfc 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1007,6 +1007,7 @@ int main(int argc, char **argv, char **envp) }; poptContext pc; int opt; + TALLOC_CTX *frame = talloc_stackframe(); /* glibc (?) likes to print "User defined signal 1" and exit if a SIGUSR[12] is received before a handler is installed */ @@ -1232,8 +1233,9 @@ int main(int argc, char **argv, char **envp) /* Loop waiting for requests */ + TALLOC_FREE(frame); while (1) { - TALLOC_CTX *frame = talloc_stackframe(); + frame = talloc_stackframe(); process_loop(); TALLOC_FREE(frame); } -- cgit From 2545457268610ab8fe71911bab167b4aeebc4ca3 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Tue, 20 Nov 2007 13:24:03 -0600 Subject: Prevent segv in winbindd running on a DC using the "idmap backend" syntax. The number of domains should be counted as they are added and not assumed to match the loop counter. manually cherry-picked 8ad2826c48a0d4d26abc3bb209860c776f55822f (This used to be commit 99b75cada2c4caaec5d30c8351080f0a41e44bd1) --- source3/winbindd/idmap.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index e89ad735b6..6756c2a23b 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -387,7 +387,7 @@ NTSTATUS idmap_init(void) */ DEBUG(1, ("Initializing idmap domains\n")); - for (i = 0; dom_list[i]; i++) { + for (i=0, num_domains=0; dom_list[i]; i++) { const char *parm_backend; char *config_option; @@ -395,7 +395,7 @@ NTSTATUS idmap_init(void) if (strequal(dom_list[i], "BUILTIN") || strequal(dom_list[i], get_global_sam_name())) { - DEBUG(0,("idmap_init: Ignoring invalid domain %s\n", + DEBUG(0,("idmap_init: Ignoring domain %s\n", dom_list[i])); continue; } @@ -503,13 +503,17 @@ NTSTATUS idmap_init(void) ret = NT_STATUS_NO_MEMORY; goto done; } - idmap_domains[i] = dom; + idmap_domains[num_domains] = dom; /* save default domain position for future uses */ if (dom->default_domain) { - def_dom_num = i; + def_dom_num = num_domains; } + /* Bump counter to next available slot */ + + num_domains++; + DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", dom->name, parm_backend, dom->default_domain?"":"not ", @@ -518,9 +522,6 @@ NTSTATUS idmap_init(void) talloc_free(config_option); } - /* save the number of domains we have */ - num_domains = i; - /* automatically add idmap_nss backend if needed */ if ((lp_server_role() == ROLE_DOMAIN_MEMBER) && ( ! pri_dom_is_in_list) && -- cgit From 66298d808034bb606478ff66aa156bda4e7e3f2a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Nov 2007 17:18:16 -0800 Subject: More pstring elimination. Jeremy. (This used to be commit 15074de938539e7a9c527d9a6d81792adc2ac3d0) --- source3/winbindd/winbindd.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 2167cfcdfc..4194b55894 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -61,9 +61,8 @@ static bool reload_services_file(void) bool ret; if (lp_loaded()) { - pstring fname; + const char *fname = lp_configfile(); - pstrcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { pstrcpy(dyn_CONFIGFILE,fname); } @@ -129,12 +128,14 @@ static void flush_caches(void) static void terminate(void) { - pstring path; + char *path = NULL; /* Remove socket file */ - pstr_sprintf(path, "%s/%s", - get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME); - unlink(path); + if (asprintf(&path, "%s/%s", + get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) { + unlink(path); + SAFE_FREE(path); + } idmap_close(); @@ -983,7 +984,6 @@ static void process_loop(void) int main(int argc, char **argv, char **envp) { - pstring logfile; static bool is_daemon = False; static bool Fork = True; static bool log_stdout = False; @@ -1086,8 +1086,12 @@ int main(int argc, char **argv, char **envp) poptFreeContext(pc); if (!override_logfile) { - pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); + char *logfile = NULL; + if (asprintf(&logfile,"%s/log.winbindd", + dyn_LOGFILEBASE) > 0) { + lp_set_logfile(logfile); + SAFE_FREE(logfile); + } } setup_logging("winbindd", log_stdout); reopen_logs(); -- cgit From e68bbe3548df2400022a86af4681bcdf89481e9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Nov 2007 10:10:52 -0800 Subject: Add set_sockaddr_port function for winbindd. Jeremy. (This used to be commit 4b47052694285a1d1d313dfd61bd17011d62948d) --- source3/winbindd/winbindd_cm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 4c9ae0365f..f8e76b0299 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -923,6 +923,8 @@ static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, } (*addrs)[*num] = *pss; + set_sockaddr_port(&(*addrs)[*num], port); + *num += 1; return True; } -- cgit From 6b6655edd90850d09c7711fc3b9fe98271e3e625 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2007 14:35:30 -0800 Subject: Remove pstrings from everything except srv_spoolss_nt.c. Jeremy. (This used to be commit 0002a9e96b0ef78316295a6eb94ff29b64e2f988) --- source3/winbindd/winbindd_ads.c | 4 ++-- source3/winbindd/winbindd_pam.c | 4 ++-- source3/winbindd/winbindd_rpc.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 6549c6d7d2..71ce3dd364 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -440,8 +440,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, sid_compose(&info->user_sid, &domain->sid, user->user_rid); sid_compose(&info->group_sid, &domain->sid, user->group_rid); - info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name); - info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name); + info->acct_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_user_name); + info->full_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_full_name); nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, &info->homedir, &info->shell, &info->full_name, diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 640eb5a519..4b052a8576 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -129,14 +129,14 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, fstring username_out; const char *nt_username, *nt_domain; - if (!(nt_domain = unistr2_tdup(mem_ctx, + if (!(nt_domain = unistr2_to_ascii_talloc(mem_ctx, &info3->uni_logon_dom))) { /* If the server didn't give us one, just use the one * we sent them */ nt_domain = name_domain; } - if (!(nt_username = unistr2_tdup(mem_ctx, + if (!(nt_username = unistr2_to_ascii_talloc(mem_ctx, &info3->uni_user_name))) { /* If the server didn't give us one, just use the one * we sent them */ diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 55212a84b8..dd45060412 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -436,9 +436,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain, sid_compose(&user_info->group_sid, &domain->sid, user->group_rid); - user_info->acct_name = unistr2_tdup(mem_ctx, + user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_user_name); - user_info->full_name = unistr2_tdup(mem_ctx, + user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_full_name); TALLOC_FREE(user); @@ -484,9 +484,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain, sid_compose(&user_info->user_sid, &domain->sid, user_rid); sid_compose(&user_info->group_sid, &domain->sid, ctr->info.id21->group_rid); - user_info->acct_name = unistr2_tdup(mem_ctx, + user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, &ctr->info.id21->uni_user_name); - user_info->full_name = unistr2_tdup(mem_ctx, + user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, &ctr->info.id21->uni_full_name); user_info->homedir = NULL; user_info->shell = NULL; -- cgit From d2cf97aeba14a4d336fb57b01f19bd5a08dcb003 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Nov 2007 13:24:54 -0800 Subject: Remove the explicit TALLOC_CTX * from cli_struct. Make us very explicit about how long a talloc ctx should last. Jeremy. (This used to be commit ba9e2be2b5a59684e854609f9d82ea1633448c62) --- source3/winbindd/winbindd_cm.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index f8e76b0299..7da7a82343 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1744,6 +1744,13 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) return; } + mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", + domain->name); + if (!mem_ctx) { + DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n")); + return; + } + DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, @@ -1761,7 +1768,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) goto no_lsarpc_ds; } - result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx, + result = rpccli_ds_getprimarydominfo(cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr); cli_rpc_pipe_close(cli); @@ -1780,6 +1787,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) goto no_lsarpc_ds; } + TALLOC_FREE(mem_ctx); return; } @@ -1798,14 +1806,7 @@ no_lsarpc_ds: "PI_LSARPC on domain %s: (%s)\n", domain->name, nt_errstr(result))); cli_rpc_pipe_close(cli); - return; - } - - mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", - domain->name); - if (!mem_ctx) { - DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n")); - cli_rpc_pipe_close(cli); + TALLOC_FREE(mem_ctx); return; } @@ -1866,8 +1867,8 @@ done: domain->name, domain->active_directory ? "" : "NOT ")); cli_rpc_pipe_close(cli); - - talloc_destroy(mem_ctx); + + TALLOC_FREE(mem_ctx); domain->initialized = True; } -- cgit From df141905fa389bc4d86bce33d1a763164e120457 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Dec 2007 14:11:45 -0800 Subject: Last pstring here. Jeremy. (This used to be commit 98d86dcbd898f48748bbfbe1066a7014d25392d1) --- source3/winbindd/winbindd_cm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 7da7a82343..b64937da23 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -208,10 +208,12 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) close_conns_after_fork(); if (!override_logfile) { - pstring logfile; - pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - reopen_logs(); + char *logfile; + if (asprintf(&logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE) > 0) { + lp_set_logfile(logfile); + SAFE_FREE(logfile); + reopen_logs(); + } } mem_ctx = talloc_init("fork_child_dc_connect"); -- cgit From 328a57e1ca5fc0e0206fdb565d5951912e84dc5e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Dec 2007 17:57:46 -0800 Subject: Remove more pstrings, from the winbindd protocol def and inside winbindd. Remove unused pstring types. Jeremy. (This used to be commit 9ccac8abb0420393569dbca73e7daf2742aa1099) --- source3/winbindd/winbindd.h | 8 ++++---- source3/winbindd/winbindd_dual.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 454a4b9698..248bcff92b 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -150,7 +150,7 @@ struct winbindd_child { pid_t pid; struct winbindd_domain *domain; - pstring logfilename; + char *logfilename; struct fd_event event; struct timed_event *lockout_policy_event; @@ -166,8 +166,8 @@ struct winbindd_domain { fstring alt_name; /* alt Domain name, if any (FQDN for ADS) */ fstring forest_name; /* Name of the AD forest we're in */ DOM_SID sid; /* SID for this domain */ - uint32 domain_flags; /* Domain flags from rpc_ds.h */ - uint32 domain_type; /* Domain type from rpc_ds.h */ + uint32 domain_flags; /* Domain flags from rpc_ds.h */ + uint32 domain_type; /* Domain type from rpc_ds.h */ uint32 domain_trust_attribs; /* Trust attribs from rpc_ds.h */ bool initialized; /* Did we already ask for the domain mode? */ bool native_mode; /* is this a win2k domain in native mode ? */ @@ -187,7 +187,7 @@ struct winbindd_domain { /* Private data for the backends (used for connection cache) */ - void *private_data; + void *private_data; /* A working DC */ fstring dcname; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index c15af710f4..91e60cca36 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -471,11 +471,15 @@ void setup_domain_child(struct winbindd_domain *domain, const char *explicit_logfile) { if (explicit_logfile != NULL) { - pstr_sprintf(child->logfilename, "%s/log.winbindd-%s", - dyn_LOGFILEBASE, explicit_logfile); + if (asprintf(&child->logfilename, "%s/log.winbindd-%s", + dyn_LOGFILEBASE, explicit_logfile) < 0) { + smb_panic("Internal error: asprintf failed"); + } } else if (domain != NULL) { - pstr_sprintf(child->logfilename, "%s/log.wb-%s", - dyn_LOGFILEBASE, domain->name); + if (asprintf(&child->logfilename, "%s/log.wb-%s", + dyn_LOGFILEBASE, domain->name) < 0) { + smb_panic("Internal error: asprintf failed"); + } } else { smb_panic("Internal error: domain == NULL && " "explicit_logfile == NULL"); @@ -507,6 +511,7 @@ void winbind_child_died(pid_t pid) child->event.fd = 0; child->event.flags = 0; child->pid = 0; + SAFE_FREE(child->logfilename); schedule_async_request(child); } -- cgit From 78c6ee0090f4122bc25baaacb5546517ad4b7bc6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Nov 2007 17:27:54 +0100 Subject: Remove some globals (This used to be commit 31d0a846db08d845e6cdfd85def4ac1c34031e02) --- source3/winbindd/winbindd_util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 5c8c8ea13d..56ae4f27bb 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1466,8 +1466,8 @@ static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain) return; } - if (asprintf(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, - strupper_static(domain->alt_name)) == -1) { + if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, + domain->alt_name) == -1) { return; } @@ -1503,8 +1503,8 @@ void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) return; } - if (asprintf(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, - strupper_static(domain->alt_name)) == -1) { + if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS, + domain->alt_name) == -1) { return; } -- cgit From bf13b9f180caf95d88a6c282cbd12c73a9cbe338 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Dec 2007 17:14:12 +0100 Subject: Fix a debug message (missing newline). Michael (This used to be commit 2a1755327f6cef6c969308e9ebcb238048535533) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 6756c2a23b..d2c13ab8b7 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -920,7 +920,7 @@ static NTSTATUS idmap_can_map(const struct id_map *map, if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) { /* huh, couldn't find a suitable domain, * let's just leave it unmapped */ - DEBUG(10, ("Could not find idmap backend for SID %s", + DEBUG(10, ("Could not find idmap backend for SID %s\n", sid_string_static(map->sid))); return NT_STATUS_NO_SUCH_DOMAIN; } -- cgit From c436c5aa0f27b72d392772cfd4dbdbc5a1e591e5 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 6 Dec 2007 01:49:37 +0100 Subject: Improve a debug message. Michael (This used to be commit 1ea3ec9271f56f7aec8a01681f5eb4adcbfe0588) --- source3/winbindd/winbindd_async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 611ca03001..c0254412e5 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -384,7 +384,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, struct lookupname_state *s; if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) { - DEBUG(5, ("Could not find domain for name %s\n", dom_name)); + DEBUG(5, ("Could not find domain for name '%s'\n", dom_name)); cont(private_data, False, NULL, SID_NAME_UNKNOWN); return; } -- cgit From acf15ae730c95443681404c76b67ccfca0253d8b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 12:26:32 -0800 Subject: Don't build rpctorture anymore - not maintained. Just remove. Remove all vestiges of pstring (except for smbctool as noted in previous commit). Jeremy (This used to be commit 4c32a22ac50ada3275d2ffba3c1aa08bee7d1549) --- source3/winbindd/winbindd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 4194b55894..53571d6002 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -64,7 +64,7 @@ static bool reload_services_file(void) const char *fname = lp_configfile(); if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); + strlcpy(dyn_CONFIGFILE,fname,sizeof(dyn_CONFIGFILE)); } } -- cgit From 42cfffae80480eae4381902fff3f7c61f858a933 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 17:32:32 -0800 Subject: Remove next_token - all uses must now be next_token_talloc. No more temptations to use static length strings. Jeremy. (This used to be commit ec003f39369910dee852b7cafb883ddaa321c2de) --- source3/winbindd/winbindd_pam.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4b052a8576..4eda0fcada 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -222,9 +222,9 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, +static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3, - const char *group_sid) + const char *group_sid) /** * Check whether a user belongs to a group or list of groups. * @@ -239,15 +239,16 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, { DOM_SID *require_membership_of_sid; size_t num_require_membership_of_sid; - fstring req_sid; + char *req_sid; const char *p; DOM_SID sid; size_t i; struct nt_user_token *token; + TALLOC_CTX *frame = NULL; NTSTATUS status; /* Parse the 'required group' SID */ - + if (!group_sid || !group_sid[0]) { /* NO sid supplied, all users may access */ return NT_STATUS_OK; @@ -263,10 +264,12 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, p = group_sid; - while (next_token(&p, req_sid, ",", sizeof(req_sid))) { + frame = talloc_stackframe(); + while (next_token_talloc(frame, &p, &req_sid, ",")) { if (!string_to_sid(&sid, req_sid)) { DEBUG(0, ("check_info3_in_group: could not parse %s " "as a SID!", req_sid)); + TALLOC_FREE(frame); return NT_STATUS_INVALID_PARAMETER; } @@ -274,10 +277,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, &require_membership_of_sid, &num_require_membership_of_sid)) { DEBUG(0, ("add_sid_to_array failed\n")); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } } + TALLOC_FREE(frame); + status = sid_array_from_info3(mem_ctx, info3, &token->user_sids, &token->num_sids, -- cgit From 7faee02d0d351c5c039e8f1be7e82ce3a93cbe96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Dec 2007 11:30:37 -0800 Subject: Remove the char[1024] strings from dynconfig. Replace them with malloc'ing accessor functions. Should save a lot of static space :-). Jeremy. (This used to be commit 52dc5eaef2106015b3a8b659e818bdb15ad94b05) --- source3/winbindd/idmap.c | 2 +- source3/winbindd/winbindd.c | 8 ++++---- source3/winbindd/winbindd_cm.c | 2 +- source3/winbindd/winbindd_dual.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index d2c13ab8b7..af8ec17b4e 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -333,7 +333,7 @@ NTSTATUS idmap_init(void) DEBUG(0, ("WARNING: idmap backend uses obsolete" " and deprecated 'idmap_' prefix.\n" "Please replace 'idmap_%s' by '%s' in" - " %s\n", q, q, dyn_CONFIGFILE)); + " %s\n", q, q, get_dyn_CONFIGFILE())); compat_backend = talloc_strdup(idmap_ctx, q); } else { compat_backend = talloc_strdup(idmap_ctx, diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 53571d6002..598ec8e428 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -63,13 +63,13 @@ static bool reload_services_file(void) if (lp_loaded()) { const char *fname = lp_configfile(); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - strlcpy(dyn_CONFIGFILE,fname,sizeof(dyn_CONFIGFILE)); + if (file_exist(fname,NULL) && !strcsequal(fname,get_dyn_CONFIGFILE())) { + set_dyn_CONFIGFILE(fname); } } reopen_logs(); - ret = lp_load(dyn_CONFIGFILE,False,False,True,True); + ret = lp_load(get_dyn_CONFIGFILE(),False,False,True,True); reopen_logs(); load_interfaces(); @@ -1088,7 +1088,7 @@ int main(int argc, char **argv, char **envp) if (!override_logfile) { char *logfile = NULL; if (asprintf(&logfile,"%s/log.winbindd", - dyn_LOGFILEBASE) > 0) { + get_dyn_LOGFILEBASE()) > 0) { lp_set_logfile(logfile); SAFE_FREE(logfile); } diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index b64937da23..3f6544965d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -209,7 +209,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) if (!override_logfile) { char *logfile; - if (asprintf(&logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE) > 0) { + if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) { lp_set_logfile(logfile); SAFE_FREE(logfile); reopen_logs(); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 91e60cca36..1e76c12d4b 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -472,12 +472,12 @@ void setup_domain_child(struct winbindd_domain *domain, { if (explicit_logfile != NULL) { if (asprintf(&child->logfilename, "%s/log.winbindd-%s", - dyn_LOGFILEBASE, explicit_logfile) < 0) { + get_dyn_LOGFILEBASE(), explicit_logfile) < 0) { smb_panic("Internal error: asprintf failed"); } } else if (domain != NULL) { if (asprintf(&child->logfilename, "%s/log.wb-%s", - dyn_LOGFILEBASE, domain->name) < 0) { + get_dyn_LOGFILEBASE(), domain->name) < 0) { smb_panic("Internal error: asprintf failed"); } } else { -- cgit From 92482e5667c9bc5ea99f4ffd1b6eab2847a6805a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 10 Dec 2007 19:19:54 +0100 Subject: idmap: add a const to idmap_dump_maps() metze (This used to be commit de31913f0a4fd407d935ec4e27a6123ab7847ab5) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index af8ec17b4e..e825ed9da7 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1490,7 +1490,7 @@ done: Dump backend status. **************************************************************************/ -void idmap_dump_maps(char *logfile) +void idmap_dump_maps(const char *logfile) { NTSTATUS ret; struct unixid allid; -- cgit From 35608af51d4f01c5fe4ed1d91c9261dcaa49f4af Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Dec 2007 16:00:45 +0100 Subject: winbindd: rename child table struct elements Add struct_ prefix to struct based protocol specific elemetens struct winbindd_child_dispatch_table. metze (This used to be commit 4ab9a8aab72a8406659a72e87b2d2a1ec2a2eabf) --- source3/winbindd/winbindd.h | 8 +-- source3/winbindd/winbindd_dual.c | 112 +++++++++++++++++++++++++----------- source3/winbindd/winbindd_idmap.c | 77 +++++++++++++++++++------ source3/winbindd/winbindd_locator.c | 10 +++- 4 files changed, 150 insertions(+), 57 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 248bcff92b..d76e9b5921 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -137,10 +137,10 @@ struct winbindd_async_request; struct winbindd_domain; struct winbindd_child_dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - const char *winbindd_cmd_name; + const char *name; + enum winbindd_cmd struct_cmd; + enum winbindd_result (*struct_fn)(struct winbindd_domain *domain, + struct winbindd_cli_state *state); }; extern const struct winbindd_child_dispatch_table domain_dispatch_table[]; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 1e76c12d4b..08ce7f4f55 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -409,27 +409,77 @@ void sendto_domain(struct winbindd_cli_state *state, } const struct winbindd_child_dispatch_table domain_dispatch_table[] = { - - { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, - { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, - { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, - { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, - { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, - { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, - { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, - { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, - { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, - { WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" }, - { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, - { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, - { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, - { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, - { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, - { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } + { + .name = "LOOKUPSID", + .struct_cmd = WINBINDD_LOOKUPSID, + .struct_fn = winbindd_dual_lookupsid, + },{ + .name = "LOOKUPNAME", + .struct_cmd = WINBINDD_LOOKUPNAME, + .struct_fn = winbindd_dual_lookupname, + },{ + .name = "LOOKUPRIDS", + .struct_cmd = WINBINDD_LOOKUPRIDS, + .struct_fn = winbindd_dual_lookuprids, + },{ + .name = "LIST_TRUSTDOM", + .struct_cmd = WINBINDD_LIST_TRUSTDOM, + .struct_fn = winbindd_dual_list_trusted_domains, + },{ + .name = "INIT_CONNECTION", + .struct_cmd = WINBINDD_INIT_CONNECTION, + .struct_fn = winbindd_dual_init_connection, + },{ + .name = "GETDCNAME", + .struct_cmd = WINBINDD_GETDCNAME, + .struct_fn = winbindd_dual_getdcname, + },{ + .name = "SHOW_SEQUENCE", + .struct_cmd = WINBINDD_SHOW_SEQUENCE, + .struct_fn = winbindd_dual_show_sequence, + },{ + .name = "PAM_AUTH", + .struct_cmd = WINBINDD_PAM_AUTH, + .struct_fn = winbindd_dual_pam_auth, + },{ + .name = "AUTH_CRAP", + .struct_cmd = WINBINDD_PAM_AUTH_CRAP, + .struct_fn = winbindd_dual_pam_auth_crap, + },{ + .name = "PAM_LOGOFF", + .struct_cmd = WINBINDD_PAM_LOGOFF, + .struct_fn = winbindd_dual_pam_logoff, + },{ + .name = "CHNG_PSWD_AUTH_CRAP", + .struct_cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, + .struct_fn = winbindd_dual_pam_chng_pswd_auth_crap, + },{ + .name = "PAM_CHAUTHTOK", + .struct_cmd = WINBINDD_PAM_CHAUTHTOK, + .struct_fn = winbindd_dual_pam_chauthtok, + },{ + .name = "CHECK_MACHACC", + .struct_cmd = WINBINDD_CHECK_MACHACC, + .struct_fn = winbindd_dual_check_machine_acct, + },{ + .name = "DUAL_USERINFO", + .struct_cmd = WINBINDD_DUAL_USERINFO, + .struct_fn = winbindd_dual_userinfo, + },{ + .name = "GETUSERDOMGROUPS", + .struct_cmd = WINBINDD_GETUSERDOMGROUPS, + .struct_fn = winbindd_dual_getuserdomgroups, + },{ + .name = "GETSIDALIASES", + .struct_cmd = WINBINDD_DUAL_GETSIDALIASES, + .struct_fn = winbindd_dual_getsidaliases, + },{ + .name = "CCACHE_NTLM_AUTH", + .struct_cmd = WINBINDD_CCACHE_NTLMAUTH, + .struct_fn = winbindd_dual_ccache_ntlm_auth, + },{ + .name = NULL, + } }; static void child_process_request(struct winbindd_child *child, @@ -449,20 +499,18 @@ static void child_process_request(struct winbindd_child *child, /* Process command */ - for (; table->fn; table++) { - if (state->request.cmd == table->cmd) { - DEBUG(10,("process_request: request fn %s\n", - table->winbindd_cmd_name )); - state->response.result = table->fn(domain, state); - break; + for (; table->name; table++) { + if (state->request.cmd == table->struct_cmd) { + DEBUG(10,("child_process_request: request fn %s\n", + table->name)); + state->response.result = table->struct_fn(domain, state); + return; } } - if (!table->fn) { - DEBUG(1 ,("child_process_request: unknown request fn number %d\n", - (int)state->request.cmd )); - state->response.result = WINBINDD_ERROR; - } + DEBUG(1 ,("child_process_request: unknown request fn number %d\n", + (int)state->request.cmd)); + state->response.result = WINBINDD_ERROR; } void setup_domain_child(struct winbindd_domain *domain, diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 250b2d2e85..379e7b51ea 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -796,24 +796,65 @@ enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, } static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { - - { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, - { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, + { + .name = "DUAL_SID2UID", + .struct_cmd = WINBINDD_DUAL_SID2UID, + .struct_fn = winbindd_dual_sid2uid, + },{ + .name = "DUAL_SID2GID", + .struct_cmd = WINBINDD_DUAL_SID2GID, + .struct_fn = winbindd_dual_sid2gid, #if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, + },{ + .name = "DUAL_SIDS2XIDS", + .struct_cmd = WINBINDD_DUAL_SIDS2XIDS, + .struct_fn = winbindd_dual_sids2xids, #endif /* end DISABLED */ - { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, - { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, - { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, - { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, - { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, - { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, - { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, - { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, - { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, - { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } + },{ + .name = "DUAL_UID2SID", + .struct_cmd = WINBINDD_DUAL_UID2SID, + .struct_fn = winbindd_dual_uid2sid, + },{ + .name = "DUAL_GID2SID", + .struct_cmd = WINBINDD_DUAL_GID2SID, + .struct_fn = winbindd_dual_gid2sid, + },{ + .name = "DUAL_UID2NAME", + .struct_cmd = WINBINDD_DUAL_UID2NAME, + .struct_fn = winbindd_dual_uid2name, + },{ + .name = "DUAL_NAME2UID", + .struct_cmd = WINBINDD_DUAL_NAME2UID, + .struct_fn = winbindd_dual_name2uid, + },{ + .name = "DUAL_GID2NAME", + .struct_cmd = WINBINDD_DUAL_GID2NAME, + .struct_fn = winbindd_dual_gid2name, + },{ + .name = "DUAL_NAME2GID", + .struct_cmd = WINBINDD_DUAL_NAME2GID, + .struct_fn = winbindd_dual_name2gid, + },{ + .name = "DUAL_SET_MAPPING", + .struct_cmd = WINBINDD_DUAL_SET_MAPPING, + .struct_fn = winbindd_dual_set_mapping, + },{ + .name = "DUAL_SET_HWMS", + .struct_cmd = WINBINDD_DUAL_SET_HWM, + .struct_fn = winbindd_dual_set_hwm, + },{ + .name = "DUAL_DUMP_MAPS", + .struct_cmd = WINBINDD_DUAL_DUMP_MAPS, + .struct_fn = winbindd_dual_dump_maps, + },{ + .name = "ALLOCATE_UID", + .struct_cmd = WINBINDD_ALLOCATE_UID, + .struct_fn = winbindd_dual_allocate_uid, + },{ + .name = "ALLOCATE_GID", + .struct_cmd = WINBINDD_ALLOCATE_GID, + .struct_fn = winbindd_dual_allocate_gid, + },{ + .name = NULL, + } }; diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 7db2e2ada0..67bafc7c07 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -96,7 +96,11 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, } static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { - { WINBINDD_DSGETDCNAME, dual_dsgetdcname, "DSGETDCNAME" }, - - { WINBINDD_NUM_CMDS, NULL, "NONE" } + { + .name = "DSGETDCNAME", + .struct_cmd = WINBINDD_DSGETDCNAME, + .struct_fn = dual_dsgetdcname, + },{ + .name = NULL, + } }; -- cgit From af3cc957f003444ef1f0ef13afbed2ed4e8ea264 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Dec 2007 15:08:18 +0100 Subject: winbindd: pass const char *logfile to winbindd_dump_maps_async() metze (This used to be commit a52237e3a10aa4ac15cd9e7b859a54c46bfa9cdf) --- source3/winbindd/winbindd_idmap.c | 6 +++--- source3/winbindd/winbindd_sid.c | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 379e7b51ea..be090afbf1 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -772,15 +772,15 @@ static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, bool success, cont(private_data, True); } -void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size, +void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, const char *logfile, void (*cont)(void *private_data, bool success), void *private_data) { struct winbindd_request request; ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_DUMP_MAPS; - request.extra_data.data = (char *)data; - request.extra_len = size; + request.extra_data.data = discard_const(logfile); + request.extra_len = strlen(logfile)+1; do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, (void *)cont, private_data); } diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 601971e36b..c01c6f04ab 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -532,6 +532,8 @@ static void dump_maps_recv(void *private_data, bool success) void winbindd_dump_maps(struct winbindd_cli_state *state) { + const char *logfile; + if ( ! state->privileged) { DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n")); request_error(state); @@ -540,9 +542,15 @@ void winbindd_dump_maps(struct winbindd_cli_state *state) DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid)); - winbindd_dump_maps_async(state->mem_ctx, - state->request.extra_data.data, - state->request.extra_len, - dump_maps_recv, state); + logfile = talloc_strndup(state->mem_ctx, + (const char *)state->request.extra_data.data, + state->request.extra_len); + if (!logfile) { + request_error(state); + return; + } + + winbindd_dump_maps_async(state->mem_ctx, logfile, + dump_maps_recv, state); } -- cgit From 3728c8b6d963756a24b0788344baeedfb4b9c2d7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Dec 2007 09:02:23 +0100 Subject: winbindd: remove unused WINBINDD_DUAL_NAME2*ID and WINBINDD_DUAL_*ID2NAME calls WINBINDD_DUAL_UID2NAME WINBINDD_DUAL_NAME2UID WINBINDD_DUAL_GID2NAME WINBINDD_DUAL_NAME2GID metze (This used to be commit fd4499ee438e4947990200db529363d51bd2c956) --- source3/winbindd/winbindd_idmap.c | 255 -------------------------------------- 1 file changed, 255 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index be090afbf1..dd63e18236 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -329,130 +329,6 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, - void (*cont)(void *private_data, bool success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_UID2NAME; - request.data.uid = uid; - do_async(mem_ctx, idmap_child(), &request, uid2name_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.uid)); - - pw = getpwuid(state->request.data.uid); - if (pw == NULL) { - DEBUG(5, ("User %lu not found\n", - (unsigned long)state->request.data.uid)); - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.name, pw->pw_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void uid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *name) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger uid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("uid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, bool success, - uid_t uid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2UID; - fstrcpy(request.data.username, name); - do_async(mem_ctx, idmap_child(), &request, name2uid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct passwd *pw; - - /* Ensure null termination */ - state->request.data.username - [sizeof(state->request.data.username)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, - state->request.data.username)); - - pw = getpwnam(state->request.data.username); - if (pw == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.uid = pw->pw_uid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2uid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, uid_t uid) = - (void (*)(void *, bool, uid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2uid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2uid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.uid); -} -#endif /* not used */ - static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) @@ -515,121 +391,6 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -static void gid2name_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, const char *name) = - (void (*)(void *, bool, const char *))c; - - if (!success) { - DEBUG(5, ("Could not trigger gid2name\n")); - cont(private_data, False, NULL); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("gid2name returned an error\n")); - cont(private_data, False, NULL); - return; - } - - cont(private_data, True, response->data.name.name); -} - -void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, - void (*cont)(void *private_data, bool success, - const char *name), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_GID2NAME; - request.data.gid = gid; - do_async(mem_ctx, idmap_child(), &request, gid2name_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.gid)); - - gr = getgrgid(state->request.data.gid); - if (gr == NULL) - return WINBINDD_ERROR; - - fstrcpy(state->response.data.name.name, gr->gr_name); - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data); - -static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, - void (*cont)(void *private_data, bool success, - gid_t gid), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_NAME2GID; - fstrcpy(request.data.groupname, name); - do_async(mem_ctx, idmap_child(), &request, name2gid_recv, - (void *)cont, private_data); -} -#endif /* not used */ - -enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct group *gr; - - /* Ensure null termination */ - state->request.data.groupname - [sizeof(state->request.data.groupname)-1] = '\0'; - - DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, - state->request.data.groupname)); - - gr = getgrnam(state->request.data.groupname); - if (gr == NULL) { - return WINBINDD_ERROR; - } - - state->response.data.gid = gr->gr_gid; - return WINBINDD_OK; -} - -#if 0 /* not used */ -static void name2gid_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, gid_t gid) = - (void (*)(void *, bool, gid_t))c; - - if (!success) { - DEBUG(5, ("Could not trigger name2gid\n")); - cont(private_data, False, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("name2gid returned an error\n")); - cont(private_data, False, 0); - return; - } - - cont(private_data, True, response->data.gid); -} -#endif /* not used */ - /* The following uid2sid/gid2sid functions has been contributed by * Keith Reynolds */ @@ -818,22 +579,6 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { .name = "DUAL_GID2SID", .struct_cmd = WINBINDD_DUAL_GID2SID, .struct_fn = winbindd_dual_gid2sid, - },{ - .name = "DUAL_UID2NAME", - .struct_cmd = WINBINDD_DUAL_UID2NAME, - .struct_fn = winbindd_dual_uid2name, - },{ - .name = "DUAL_NAME2UID", - .struct_cmd = WINBINDD_DUAL_NAME2UID, - .struct_fn = winbindd_dual_name2uid, - },{ - .name = "DUAL_GID2NAME", - .struct_cmd = WINBINDD_DUAL_GID2NAME, - .struct_fn = winbindd_dual_gid2name, - },{ - .name = "DUAL_NAME2GID", - .struct_cmd = WINBINDD_DUAL_NAME2GID, - .struct_fn = winbindd_dual_name2gid, },{ .name = "DUAL_SET_MAPPING", .struct_cmd = WINBINDD_DUAL_SET_MAPPING, -- cgit From 38f8d32d10f7486ee570275aff185994697203f3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Dec 2007 09:51:56 +0100 Subject: winbindd: remove unused WINBINDD_DUMP_MAPS support Also the design of this function was really bad, instead do the dump into a file, the client should get back the list of mappings. metze (This used to be commit ce7fe8acf41e90553431c7cda6823700701835c7) --- source3/winbindd/idmap.c | 67 --------------------------------------- source3/winbindd/winbindd.c | 2 -- source3/winbindd/winbindd_idmap.c | 49 ---------------------------- source3/winbindd/winbindd_sid.c | 39 ----------------------- 4 files changed, 157 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index e825ed9da7..6b4af10f6f 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1486,73 +1486,6 @@ done: return ret; } -/************************************************************************** - Dump backend status. -**************************************************************************/ - -void idmap_dump_maps(const char *logfile) -{ - NTSTATUS ret; - struct unixid allid; - struct id_map *maps; - int num_maps; - FILE *dump; - int i; - - if (! NT_STATUS_IS_OK(ret = idmap_init())) { - return; - } - - dump = fopen(logfile, "w"); - if ( ! dump) { - DEBUG(0, ("Unable to open open stream for file [%s], " - "errno: %d\n", logfile, errno)); - return; - } - - if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) { - allid.type = ID_TYPE_UID; - allid.id = 0; - idmap_alloc_ctx->methods->get_id_hwm(&allid); - fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id); - - allid.type = ID_TYPE_GID; - allid.id = 0; - idmap_alloc_ctx->methods->get_id_hwm(&allid); - fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id); - } - - maps = talloc(idmap_ctx, struct id_map); - num_maps = 0; - - for (i = 0; i < num_domains; i++) { - if (idmap_domains[i]->methods->dump_data) { - idmap_domains[i]->methods->dump_data(idmap_domains[i], - &maps, &num_maps); - } - } - - for (i = 0; i < num_maps; i++) { - switch (maps[i].xid.type) { - case ID_TYPE_UID: - fprintf(dump, "UID %lu %s\n", - (unsigned long)maps[i].xid.id, - sid_string_static(maps[i].sid)); - break; - case ID_TYPE_GID: - fprintf(dump, "GID %lu %s\n", - (unsigned long)maps[i].xid.id, - sid_string_static(maps[i].sid)); - break; - case ID_TYPE_NOT_SPECIFIED: - break; - } - } - - fflush(dump); - fclose(dump); -} - char *idmap_fetch_secret(const char *backend, bool alloc, const char *domain, const char *identity) { diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 598ec8e428..b695c2e95e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -331,8 +331,6 @@ static struct winbindd_dispatch_table { /* Miscellaneous */ - { WINBINDD_DUMP_MAPS, winbindd_dump_maps, "DUMP_MAPS" }, - { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" }, { WINBINDD_PING, winbindd_ping, "PING" }, { WINBINDD_INFO, winbindd_info, "INFO" }, diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index dd63e18236..cc5cf1e848 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -511,51 +511,6 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, return WINBINDD_ERROR; } -static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ) = - (void (*)(void *, bool))c; - - if (!success) { - DEBUG(5, ("Could not trigger a map dump\n")); - cont(private_data, False); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("idmap dump maps returned an error\n")); - cont(private_data, False); - return; - } - - cont(private_data, True); -} - -void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, const char *logfile, - void (*cont)(void *private_data, bool success), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_DUMP_MAPS; - request.extra_data.data = discard_const(logfile); - request.extra_len = strlen(logfile)+1; - do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid)); - - idmap_dump_maps((char *)state->request.extra_data.data); - - return WINBINDD_OK; -} - static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { { .name = "DUAL_SID2UID", @@ -587,10 +542,6 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { .name = "DUAL_SET_HWMS", .struct_cmd = WINBINDD_DUAL_SET_HWM, .struct_fn = winbindd_dual_set_hwm, - },{ - .name = "DUAL_DUMP_MAPS", - .struct_cmd = WINBINDD_DUAL_DUMP_MAPS, - .struct_fn = winbindd_dual_dump_maps, },{ .name = "ALLOCATE_UID", .struct_cmd = WINBINDD_ALLOCATE_UID, diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index c01c6f04ab..302460c942 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -515,42 +515,3 @@ enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain, state->response.data.gid = xid.id; return WINBINDD_OK; } - -static void dump_maps_recv(void *private_data, bool success) -{ - struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); - - if (!success) { - DEBUG(5, ("Could not dump maps\n")); - request_error(state); - return; - } - - request_ok(state); -} - -void winbindd_dump_maps(struct winbindd_cli_state *state) -{ - const char *logfile; - - if ( ! state->privileged) { - DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n")); - request_error(state); - return; - } - - DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid)); - - logfile = talloc_strndup(state->mem_ctx, - (const char *)state->request.extra_data.data, - state->request.extra_len); - if (!logfile) { - request_error(state); - return; - } - - winbindd_dump_maps_async(state->mem_ctx, logfile, - dump_maps_recv, state); -} - -- cgit From d818a93d073f5c15ffbb3b769348d25e49bc9848 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 23 Nov 2007 10:54:48 +0100 Subject: Don't restart winbind if a corrupted tdb is found during initialization. The tdb is validated before it gets initialized. Since then sighandlers changed a restart isn't needed anymore. (This used to be commit aabe9b33fcaed8af98b1ed6b736253e196d87d48) --- source3/winbindd/winbindd.c | 24 +++++++++--------------- source3/winbindd/winbindd_cache.c | 3 +-- 2 files changed, 10 insertions(+), 17 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index b695c2e95e..07cf22618e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1157,20 +1157,6 @@ int main(int argc, char **argv, char **envp) pidfile_create("winbindd"); - /* Ensure all cache and idmap caches are consistent - before we startup. */ - - if (winbindd_validate_cache()) { - /* We have a bad cache, but luckily we - just deleted it. Restart ourselves */ - int i; - /* Ensure we have no open low fd's. */ - for (i = 3; i < 100; i++) { - close(i); - } - return execve(argv[0], argv, envp); - } - #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for @@ -1188,7 +1174,15 @@ int main(int argc, char **argv, char **envp) DEBUG(0, ("unable to initialize messaging system\n")); exit(1); } - + + /* + * Ensure all cache and idmap caches are consistent + * before we startup. + */ + if (winbindd_validate_cache() < 0) { + DEBUG(0, ("corrupted tdb found, trying to restore backup\n")); + } + /* Initialize cache (ensure version is correct). */ if (!initialize_winbindd_cache()) { exit(1); diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index f3aa0fce42..7ec8208f4b 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -3338,8 +3338,7 @@ static void validate_panic(const char *const why) /*********************************************************************** Try and validate every entry in the winbindd cache. If we fail here, - delete the cache tdb and return non-zero - the caller (main winbindd - function) will restart us as we don't know if we crashed or not. + delete the cache tdb and return non-zero. ***********************************************************************/ int winbindd_validate_cache(void) -- cgit From 4884f5d23af41a0b88b98a0485cb3935beb820fe Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 08:52:20 +0100 Subject: In cm_prepare_connection(), only get auth user creds if we need to. Michael (This used to be commit 164bfb25d7b5cfeffeb4d81958b7629a11ca5d5e) --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 3f6544965d..0a96e04052 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -676,8 +676,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -795,6 +793,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, (*cli)->use_kerberos = False; + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && (strlen(ipc_username) > 0)) { -- cgit From 5d9c97703432bbca7d45948708b5b21a3718559a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 12:47:28 +0100 Subject: Streamline logic in cm_connect_netlogon() by retrieving trust password only, when it will be used. Michael (This used to be commit cdc60d8ae8c0ef804206b20b451e9557f97d4439) --- source3/winbindd/winbindd_cm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0a96e04052..d5c8b9955f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2219,10 +2219,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); if (netlogon_pipe == NULL) { @@ -2234,11 +2230,16 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags &= ~NETLOGON_NEG_SCHANNEL; goto no_schannel; } - + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; } + if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { + cli_rpc_pipe_close(netlogon_pipe); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + /* if we are a DC and this is a trusted domain, then we need to use our domain name in the net_req_auth2() request */ -- cgit From f793c99ca54d62cb8142607e8449f5b5b3a5e79d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 13:05:44 +0100 Subject: Let get_trust_pw() determine the machine_account_name to use. Up to now each caller used its own logic. This eliminates code paths where there was a special treatment of the following situation: the domain given is not our workgroup (i.e. our own domain) and we are not a DC (i.e. it is not a typical trusted domain situation). In situation the given domain name was previously used as the machine account name, resulting in an account name of DOMAIN\\DOMAIN$, which does not seem very reasonable to me. get_trust_pw would not have obtained a password in this situation anyways. I hope I have not missed an important point here! Michael (This used to be commit 6ced4a7f88798dc449a667d63bc29bf6c569291f) --- source3/winbindd/winbindd_cm.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d5c8b9955f..adb9d11edc 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,27 +2235,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC - && !strequal(domain->name, lp_workgroup()) - && lp_allow_trusted_domains() ) + if (!get_trust_pw(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { - account_name = lp_workgroup(); - } else { - account_name = domain->primary ? - global_myname() : domain->name; - } - - if (account_name == NULL) { cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_NO_MEMORY; + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } result = rpccli_netlogon_setup_creds( -- cgit From 31f221ed9316c8dc2f4911d7b8ddcdf8b74367db Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:07:32 +0100 Subject: Rename get_trust_pw() to get_trust_pw_hash(). Michael (This used to be commit 0cde7ac9cb39a0026a38ccf66dbecefc12931074) --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index adb9d11edc..d8040d79ac 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,8 +2235,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &account_name, - &sec_chan_type)) + if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; -- cgit From a493c7baac311e9ac0a560e4412d07df150f4407 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 15:39:36 +0100 Subject: Streamline and fix logic of cm_prepare_connection(). Do not attempt to do a session setup when in a trusted domain situation (this gives STATUS_NOLOGON_TRUSTED_DOMAIN_ACCOUNT). Use get_trust_pw_clear to get machine trust account. Only call this when the results is really used. Use the proper domain and account name for session setup. Michael (This used to be commit 18c66a364e0ddc4960769871ca190944f7fe5c44) --- source3/winbindd/winbindd_cm.c | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d8040d79ac..00d9092dc3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -646,8 +646,13 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, bool *retry) { - char *machine_password, *machine_krb5_principal, *machine_account; - char *ipc_username, *ipc_domain, *ipc_password; + char *machine_password = NULL; + char *machine_krb5_principal = NULL; + char *machine_account = NULL; + const char *account_name = NULL; + char *ipc_username = NULL; + char *ipc_domain = NULL; + char *ipc_password = NULL; bool got_mutex; @@ -661,21 +666,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n", controller, domain->name )); - machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, - NULL); - - if (asprintf(&machine_account, "%s$", global_myname()) == -1) { - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), - lp_realm()) == -1) { - SAFE_FREE(machine_account); - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -732,10 +722,32 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = NT_STATUS_UNSUCCESSFUL; goto done; } - - if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { + + if (!is_trusted_domain_situation(domain->name) && + (*cli)->protocol >= PROTOCOL_NT1 && + (*cli)->capabilities & CAP_EXTENDED_SECURITY) + { ADS_STATUS ads_status; + if (!get_trust_pw_clear(domain->name, &machine_password, + &account_name, NULL)) + { + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + + if (asprintf(&machine_account, "%s$", account_name) == -1) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, + lp_realm()) == -1) + { + result = NT_STATUS_NO_MEMORY; + goto done; + } + if (lp_security() == SEC_ADS) { /* Try a krb5 session */ @@ -750,7 +762,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ads_status = cli_session_setup_spnego(*cli, machine_krb5_principal, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4,("failed kerberos session setup with %s\n", @@ -760,7 +772,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } @@ -770,12 +782,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(5, ("connecting to %s from %s with username " "[%s]\\[%s]\n", controller, global_myname(), - lp_workgroup(), machine_account)); + domain->name, machine_account)); ads_status = cli_session_setup_spnego(*cli, machine_account, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4, ("authenticated session setup failed with %s\n", ads_errstr(ads_status))); @@ -784,12 +796,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } - /* Fall back to non-kerberos session setup */ + /* Fall back to non-kerberos session setup with auth_user */ (*cli)->use_kerberos = False; -- cgit From 13e0e4bdf25d00bdf021851d4f5a9e906212c357 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:32:38 +0100 Subject: Refactor out assembling of trust creds (pw, account name, principal). Michael (This used to be commit 481f18b20d6d5ee12c62120a3559bb16cc98e465) --- source3/winbindd/winbindd_cm.c | 55 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 00d9092dc3..cc7a0cc671 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -635,6 +635,40 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, return True; } +/** + * Helper function to assemble trust password and account name + */ +static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, + char **machine_password, + char **machine_account, + char **machine_krb5_principal) +{ + const char *account_name; + + if (!get_trust_pw_clear(domain->name, machine_password, + &account_name, NULL)) + { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + if ((machine_account != NULL) && + (asprintf(machine_account, "%s$", account_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + /* this is at least correct when domain is our domain, + * which is the only case, when this is currently used: */ + if ((machine_krb5_principal != NULL) && + (asprintf(machine_krb5_principal, "%s$@%s", account_name, + domain->alt_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + /************************************************************************ Given a fd with a just-connected TCP connection to a DC, open a connection to the pipe. @@ -649,7 +683,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, char *machine_password = NULL; char *machine_krb5_principal = NULL; char *machine_account = NULL; - const char *account_name = NULL; char *ipc_username = NULL; char *ipc_domain = NULL; char *ipc_password = NULL; @@ -729,22 +762,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, { ADS_STATUS ads_status; - if (!get_trust_pw_clear(domain->name, &machine_password, - &account_name, NULL)) - { - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - if (asprintf(&machine_account, "%s$", account_name) == -1) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, - lp_realm()) == -1) - { - result = NT_STATUS_NO_MEMORY; + result = get_trust_creds(domain, &machine_password, + &machine_account, + &machine_krb5_principal); + if (!NT_STATUS_IS_OK(result)) { goto done; } -- cgit From 9104d2bf79e92ccdca3e6406bda9f0facea89ddb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:34:39 +0100 Subject: Make cm_connect_sam() try harder to connect autheticated. Even if the session setup was anonymous, try and collect trust creds with get_trust_creds() and use these before falling back to schannel. This is the first attempt to fix interdomain trusts. (get password policy and stuff) Michael (This used to be commit e180bbd45452435e981192028a0ad90078c04236) --- source3/winbindd/winbindd_cm.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index cc7a0cc671..cb366a293c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1968,6 +1968,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring conn_pwd; struct dcinfo *p_dcinfo; + char *machine_password = NULL; + char *machine_account = NULL; + char *domain_name = NULL; result = init_dc_connection(domain); if (!NT_STATUS_IS_OK(result)) { @@ -1990,34 +1993,46 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, pwd_get_cleartext(&conn->cli->pwd, conn_pwd); if ((conn->cli->user_name[0] == '\0') || (conn->cli->domain[0] == '\0') || - (conn_pwd[0] == '\0')) { - DEBUG(10, ("cm_connect_sam: No no user available for " - "domain %s, trying schannel\n", conn->cli->domain)); + (conn_pwd[0] == '\0')) + { + result = get_trust_creds(domain, &machine_password, + &machine_account, NULL); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("cm_connect_sam: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + domain_name = domain->name; goto schannel; + } else { + machine_password = conn_pwd; + machine_account = conn->cli->user_name; + domain_name = conn->cli->domain; } + /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ conn->samr_pipe = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, - conn->cli->domain, - conn->cli->user_name, - conn_pwd, &result); + domain_name, + machine_account, + machine_password, &result); if (conn->samr_pipe == NULL) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " "pipe for domain %s using NTLMSSP " "authenticated pipe: user %s\\%s. Error was " - "%s\n", domain->name, conn->cli->domain, - conn->cli->user_name, nt_errstr(result))); + "%s\n", domain->name, domain_name, + machine_account, nt_errstr(result))); goto schannel; } DEBUG(10,("cm_connect_sam: connected to SAMR pipe for " "domain %s using NTLMSSP authenticated " "pipe: user %s\\%s\n", domain->name, - conn->cli->domain, conn->cli->user_name )); + domain_name, machine_account)); result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, @@ -2102,6 +2117,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, *cli = conn->samr_pipe; *sam_handle = conn->sam_domain_handle; + SAFE_FREE(machine_password); + SAFE_FREE(machine_account); return result; } -- cgit From 873f14ae408d5fa151f8e4f83c3dfe0c9b8a4d2d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Dec 2007 12:27:57 +0100 Subject: winbindd: move domain child specific stuff into its own file metze (This used to be commit 075d315e0f72d506b70040da10940e4af131b4e2) --- source3/winbindd/winbindd.h | 2 - source3/winbindd/winbindd_domain.c | 111 ++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual.c | 99 ++++---------------------------- source3/winbindd/winbindd_idmap.c | 7 +-- source3/winbindd/winbindd_locator.c | 7 +-- source3/winbindd/winbindd_util.c | 20 ++----- 6 files changed, 132 insertions(+), 114 deletions(-) create mode 100644 source3/winbindd/winbindd_domain.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index d76e9b5921..6bf6e6c68f 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -143,8 +143,6 @@ struct winbindd_child_dispatch_table { struct winbindd_cli_state *state); }; -extern const struct winbindd_child_dispatch_table domain_dispatch_table[]; - struct winbindd_child { struct winbindd_child *next, *prev; diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c new file mode 100644 index 0000000000..1b758cdf40 --- /dev/null +++ b/source3/winbindd/winbindd_domain.c @@ -0,0 +1,111 @@ +/* + Unix SMB/CIFS implementation. + + Winbind domain child functions + + Copyright (C) Stefan Metzmacher 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static const struct winbindd_child_dispatch_table domain_dispatch_table[]; + +void setup_domain_child(struct winbindd_domain *domain, + struct winbindd_child *child) +{ + setup_child(child, domain_dispatch_table, + "log.wb", domain->name); + + child->domain = domain; +} + +static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { + { + .name = "LOOKUPSID", + .struct_cmd = WINBINDD_LOOKUPSID, + .struct_fn = winbindd_dual_lookupsid, + },{ + .name = "LOOKUPNAME", + .struct_cmd = WINBINDD_LOOKUPNAME, + .struct_fn = winbindd_dual_lookupname, + },{ + .name = "LOOKUPRIDS", + .struct_cmd = WINBINDD_LOOKUPRIDS, + .struct_fn = winbindd_dual_lookuprids, + },{ + .name = "LIST_TRUSTDOM", + .struct_cmd = WINBINDD_LIST_TRUSTDOM, + .struct_fn = winbindd_dual_list_trusted_domains, + },{ + .name = "INIT_CONNECTION", + .struct_cmd = WINBINDD_INIT_CONNECTION, + .struct_fn = winbindd_dual_init_connection, + },{ + .name = "GETDCNAME", + .struct_cmd = WINBINDD_GETDCNAME, + .struct_fn = winbindd_dual_getdcname, + },{ + .name = "SHOW_SEQUENCE", + .struct_cmd = WINBINDD_SHOW_SEQUENCE, + .struct_fn = winbindd_dual_show_sequence, + },{ + .name = "PAM_AUTH", + .struct_cmd = WINBINDD_PAM_AUTH, + .struct_fn = winbindd_dual_pam_auth, + },{ + .name = "AUTH_CRAP", + .struct_cmd = WINBINDD_PAM_AUTH_CRAP, + .struct_fn = winbindd_dual_pam_auth_crap, + },{ + .name = "PAM_LOGOFF", + .struct_cmd = WINBINDD_PAM_LOGOFF, + .struct_fn = winbindd_dual_pam_logoff, + },{ + .name = "CHNG_PSWD_AUTH_CRAP", + .struct_cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, + .struct_fn = winbindd_dual_pam_chng_pswd_auth_crap, + },{ + .name = "PAM_CHAUTHTOK", + .struct_cmd = WINBINDD_PAM_CHAUTHTOK, + .struct_fn = winbindd_dual_pam_chauthtok, + },{ + .name = "CHECK_MACHACC", + .struct_cmd = WINBINDD_CHECK_MACHACC, + .struct_fn = winbindd_dual_check_machine_acct, + },{ + .name = "DUAL_USERINFO", + .struct_cmd = WINBINDD_DUAL_USERINFO, + .struct_fn = winbindd_dual_userinfo, + },{ + .name = "GETUSERDOMGROUPS", + .struct_cmd = WINBINDD_GETUSERDOMGROUPS, + .struct_fn = winbindd_dual_getuserdomgroups, + },{ + .name = "GETSIDALIASES", + .struct_cmd = WINBINDD_DUAL_GETSIDALIASES, + .struct_fn = winbindd_dual_getsidaliases, + },{ + .name = "CCACHE_NTLM_AUTH", + .struct_cmd = WINBINDD_CCACHE_NTLMAUTH, + .struct_fn = winbindd_dual_ccache_ntlm_auth, + },{ + .name = NULL, + } +}; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 08ce7f4f55..778886d8e2 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -408,80 +408,6 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } -const struct winbindd_child_dispatch_table domain_dispatch_table[] = { - { - .name = "LOOKUPSID", - .struct_cmd = WINBINDD_LOOKUPSID, - .struct_fn = winbindd_dual_lookupsid, - },{ - .name = "LOOKUPNAME", - .struct_cmd = WINBINDD_LOOKUPNAME, - .struct_fn = winbindd_dual_lookupname, - },{ - .name = "LOOKUPRIDS", - .struct_cmd = WINBINDD_LOOKUPRIDS, - .struct_fn = winbindd_dual_lookuprids, - },{ - .name = "LIST_TRUSTDOM", - .struct_cmd = WINBINDD_LIST_TRUSTDOM, - .struct_fn = winbindd_dual_list_trusted_domains, - },{ - .name = "INIT_CONNECTION", - .struct_cmd = WINBINDD_INIT_CONNECTION, - .struct_fn = winbindd_dual_init_connection, - },{ - .name = "GETDCNAME", - .struct_cmd = WINBINDD_GETDCNAME, - .struct_fn = winbindd_dual_getdcname, - },{ - .name = "SHOW_SEQUENCE", - .struct_cmd = WINBINDD_SHOW_SEQUENCE, - .struct_fn = winbindd_dual_show_sequence, - },{ - .name = "PAM_AUTH", - .struct_cmd = WINBINDD_PAM_AUTH, - .struct_fn = winbindd_dual_pam_auth, - },{ - .name = "AUTH_CRAP", - .struct_cmd = WINBINDD_PAM_AUTH_CRAP, - .struct_fn = winbindd_dual_pam_auth_crap, - },{ - .name = "PAM_LOGOFF", - .struct_cmd = WINBINDD_PAM_LOGOFF, - .struct_fn = winbindd_dual_pam_logoff, - },{ - .name = "CHNG_PSWD_AUTH_CRAP", - .struct_cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, - .struct_fn = winbindd_dual_pam_chng_pswd_auth_crap, - },{ - .name = "PAM_CHAUTHTOK", - .struct_cmd = WINBINDD_PAM_CHAUTHTOK, - .struct_fn = winbindd_dual_pam_chauthtok, - },{ - .name = "CHECK_MACHACC", - .struct_cmd = WINBINDD_CHECK_MACHACC, - .struct_fn = winbindd_dual_check_machine_acct, - },{ - .name = "DUAL_USERINFO", - .struct_cmd = WINBINDD_DUAL_USERINFO, - .struct_fn = winbindd_dual_userinfo, - },{ - .name = "GETUSERDOMGROUPS", - .struct_cmd = WINBINDD_GETUSERDOMGROUPS, - .struct_fn = winbindd_dual_getuserdomgroups, - },{ - .name = "GETSIDALIASES", - .struct_cmd = WINBINDD_DUAL_GETSIDALIASES, - .struct_fn = winbindd_dual_getsidaliases, - },{ - .name = "CCACHE_NTLM_AUTH", - .struct_cmd = WINBINDD_CCACHE_NTLMAUTH, - .struct_fn = winbindd_dual_ccache_ntlm_auth, - },{ - .name = NULL, - } -}; - static void child_process_request(struct winbindd_child *child, struct winbindd_cli_state *state) { @@ -513,27 +439,22 @@ static void child_process_request(struct winbindd_child *child, state->response.result = WINBINDD_ERROR; } -void setup_domain_child(struct winbindd_domain *domain, - struct winbindd_child *child, - const struct winbindd_child_dispatch_table *table, - const char *explicit_logfile) +void setup_child(struct winbindd_child *child, + const struct winbindd_child_dispatch_table *table, + const char *logprefix, + const char *logname) { - if (explicit_logfile != NULL) { - if (asprintf(&child->logfilename, "%s/log.winbindd-%s", - get_dyn_LOGFILEBASE(), explicit_logfile) < 0) { - smb_panic("Internal error: asprintf failed"); - } - } else if (domain != NULL) { - if (asprintf(&child->logfilename, "%s/log.wb-%s", - get_dyn_LOGFILEBASE(), domain->name) < 0) { + if (logprefix && logname) { + if (asprintf(&child->logfilename, "%s/%s-%s", + get_dyn_LOGFILEBASE(), logprefix, logname) < 0) { smb_panic("Internal error: asprintf failed"); } } else { - smb_panic("Internal error: domain == NULL && " - "explicit_logfile == NULL"); + smb_panic("Internal error: logprefix == NULL && " + "logname == NULL"); } - child->domain = domain; + child->domain = NULL; child->table = table; } diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index cc5cf1e848..6f7b562415 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -44,10 +44,9 @@ static struct winbindd_child static_idmap_child; void init_idmap_child(void) { - setup_domain_child(NULL, - &static_idmap_child, - idmap_dispatch_table, - "idmap"); + setup_child(&static_idmap_child, + idmap_dispatch_table, + "log.winbindd", "idmap"); } struct winbindd_child *idmap_child(void) diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 67bafc7c07..ee497ebf32 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -33,10 +33,9 @@ static struct winbindd_child static_locator_child; void init_locator_child(void) { - setup_domain_child(NULL, - &static_locator_child, - locator_dispatch_table, - "locator"); + setup_child(&static_locator_child, + locator_dispatch_table, + "log.winbindd", "locator"); } struct winbindd_child *locator_child(void) diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 56ae4f27bb..2389a4be13 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -326,9 +326,7 @@ static void trustdom_recv(void *private_data, bool success) &sid); if (domain) { setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + &domain->child); } } p=q; @@ -698,9 +696,7 @@ bool init_domain_list(void) &global_sid_Builtin); if (domain) { setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + &domain->child); } /* Local SAM */ @@ -712,9 +708,7 @@ bool init_domain_list(void) domain->primary = True; } setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + &domain->child); } /* Add ourselves as the first entry. */ @@ -732,9 +726,7 @@ bool init_domain_list(void) if (domain) { domain->primary = True; setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + &domain->child); /* Even in the parent winbindd we'll need to talk to the DC, so try and see if we can @@ -781,9 +773,7 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid ) domain->online = True; setup_domain_child(domain, - &domain->child, - domain_dispatch_table, - NULL); + &domain->child); wcache_tdc_add_domain( domain ); -- cgit From 105635e23c5c77c5efed727bbc686650406ab82e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:10:58 +0100 Subject: Use sid_string_talloc where we have a tmp talloc ctx (This used to be commit f00ab810d2540679bec109498ac89e1eafe18f03) --- source3/winbindd/idmap_ldap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index a980d54bbe..17e9eefe43 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -1166,7 +1166,7 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, - sid_string_static(ids[0]->sid)); + sid_string_talloc(memctx, ids[0]->sid)); CHECK_ALLOC_DONE(filter); DEBUG(10, ("Filter: [%s]\n", filter)); } else { @@ -1187,7 +1187,8 @@ again: for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) { filter = talloc_asprintf_append_buffer(filter, "(%s=%s)", LDAP_ATTRIBUTE_SID, - sid_string_static(ids[idx]->sid)); + sid_string_talloc(memctx, + ids[idx]->sid)); CHECK_ALLOC_DONE(filter); } filter = talloc_asprintf_append_buffer(filter, "))"); @@ -1385,7 +1386,7 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id); CHECK_ALLOC_DONE(id_str); - sid = talloc_strdup(memctx, sid_string_static(map->sid)); + sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid)); CHECK_ALLOC_DONE(sid); dn = talloc_asprintf(memctx, "%s=%s,%s", -- cgit From 900288a2b86abd247f9eb4cd15dc5617a17cfef1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:11:36 +0100 Subject: Replace sid_string_static by sid_string_dbg in DEBUGs (This used to be commit bb35e794ec129805e874ceba882bcc1e84791a09) --- source3/winbindd/idmap.c | 12 ++++++------ source3/winbindd/idmap_ad.c | 6 ++---- source3/winbindd/idmap_ldap.c | 6 ++---- source3/winbindd/idmap_rid.c | 2 +- source3/winbindd/idmap_util.c | 12 ++++++------ source3/winbindd/winbindd_ads.c | 33 ++++++++++++++++----------------- source3/winbindd/winbindd_async.c | 4 ++-- source3/winbindd/winbindd_cache.c | 18 ++++++++++-------- source3/winbindd/winbindd_group.c | 31 ++++++++++++++++--------------- source3/winbindd/winbindd_idmap.c | 4 +++- source3/winbindd/winbindd_pam.c | 2 +- source3/winbindd/winbindd_passdb.c | 4 ++-- source3/winbindd/winbindd_rpc.c | 17 ++++++----------- source3/winbindd/winbindd_user.c | 21 +++++++++++---------- source3/winbindd/winbindd_util.c | 5 ++--- 15 files changed, 86 insertions(+), 91 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 6b4af10f6f..c1b4e10adf 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -912,7 +912,7 @@ static NTSTATUS idmap_can_map(const struct id_map *map, "our primary domain when is True\n")); DEBUGADD(10, ("Leave [%s] unmapped\n", - sid_string_static(map->sid))); + sid_string_dbg(map->sid))); return NT_STATUS_UNSUCCESSFUL; } } @@ -921,7 +921,7 @@ static NTSTATUS idmap_can_map(const struct id_map *map, /* huh, couldn't find a suitable domain, * let's just leave it unmapped */ DEBUG(10, ("Could not find idmap backend for SID %s\n", - sid_string_static(map->sid))); + sid_string_dbg(map->sid))); return NT_STATUS_NO_SUCH_DOMAIN; } @@ -929,7 +929,7 @@ static NTSTATUS idmap_can_map(const struct id_map *map, /* ouch the domain is read only, * let's just leave it unmapped */ DEBUG(10, ("idmap backend for SID %s is READONLY!\n", - sid_string_static(map->sid))); + sid_string_dbg(map->sid))); return NT_STATUS_UNSUCCESSFUL; } @@ -983,7 +983,7 @@ static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map) map->status = ID_MAPPED; DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", - sid_string_static(map->sid), + sid_string_dbg(map->sid), (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", (unsigned long)map->xid.id)); ret = dom->methods->set_mapping(dom, map); @@ -1006,7 +1006,7 @@ static NTSTATUS idmap_backends_set_mapping(const struct id_map *map) NTSTATUS ret; DEBUG(10, ("Setting mapping %s <-> %s %lu\n", - sid_string_static(map->sid), + sid_string_dbg(map->sid), (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", (unsigned long)map->xid.id)); @@ -1150,7 +1150,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) } DEBUG(10,("SID %s is being handled by %s\n", - sid_string_static(ids[i]->sid), + sid_string_dbg(ids[i]->sid), dom ? dom->name : "none" )); idx = find_idmap_domain_index( dom ); diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 50f7914f85..0d7c068844 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -441,8 +441,7 @@ again: /* mapped */ map->status = ID_MAPPED; - DEBUG(10, ("Mapped %s -> %lu (%d)\n", - sid_string_static(map->sid), + DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid), (unsigned long)map->xid.id, map->xid.type)); } @@ -628,8 +627,7 @@ again: map->xid.id = id; map->status = ID_MAPPED; - DEBUG(10, ("Mapped %s -> %lu (%d)\n", - sid_string_static(map->sid), + DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid), (unsigned long)map->xid.id, map->xid.type)); } diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 17e9eefe43..fa80fae5d8 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -1065,8 +1065,7 @@ again: /* mapped */ map->status = ID_MAPPED; - DEBUG(10, ("Mapped %s -> %lu (%d)\n", - sid_string_static(map->sid), + DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid), (unsigned long)map->xid.id, map->xid.type)); } @@ -1298,8 +1297,7 @@ again: map->xid.id = id; map->status = ID_MAPPED; - DEBUG(10, ("Mapped %s -> %lu (%d)\n", - sid_string_static(map->sid), + DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid), (unsigned long)map->xid.id, map->xid.type)); } diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c index 8e5f1302f7..f1cd77853c 100644 --- a/source3/winbindd/idmap_rid.c +++ b/source3/winbindd/idmap_rid.c @@ -237,7 +237,7 @@ static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_ma ( ! NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) { /* some fatal error occurred, log it */ DEBUG(3, ("Unexpected error resolving a SID (%s)\n", - sid_string_static(ids[i]->sid))); + sid_string_dbg(ids[i]->sid))); } } diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 077c599739..bf06cd8472 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -101,7 +101,7 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) struct id_map map; struct id_map *maps[2]; - DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid))); + DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_UID; @@ -112,13 +112,13 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", - sid_string_static(sid))); + sid_string_dbg(sid))); return ret; } if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_UID)) { DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n", - sid_string_static(sid), + sid_string_dbg(sid), map.status, map.xid.type, map.xid.id)); @@ -141,7 +141,7 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) struct id_map map; struct id_map *maps[2]; - DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_static(sid))); + DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_GID; @@ -152,13 +152,13 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", - sid_string_static(sid))); + sid_string_dbg(sid))); return ret; } if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) { DEBUG(10, ("sid [%s] not mapped to a gid [%u,%u,%u]\n", - sid_string_static(sid), + sid_string_dbg(sid), map.status, map.xid.type, map.xid.id)); diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 71ce3dd364..c9b2a52388 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -435,7 +435,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); sid_compose(&info->user_sid, &domain->sid, user->user_rid); sid_compose(&info->group_sid, &domain->sid, user->group_rid); @@ -490,14 +490,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain, free(sidstr); if (!ADS_ERR_OK(rc) || !msg) { DEBUG(1,("query_user(sid=%s) ads_search: %s\n", - sid_string_static(sid), ads_errstr(rc))); + sid_string_dbg(sid), ads_errstr(rc))); goto done; } count = ads_count_replies(ads, msg); if (count != 1) { DEBUG(1,("query_user(sid=%s): Not found\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto done; } @@ -513,7 +513,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { DEBUG(1,("No primary group for %s !?\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto done; } @@ -756,7 +756,6 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, int i; DOM_SID primary_group; uint32 primary_group_rid; - fstring sid_string; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; size_t num_groups = 0; @@ -790,8 +789,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (!ADS_ERR_OK(rc)) { status = ads_ntstatus(rc); - DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", - sid_to_string(sid_string, sid), ads_errstr(rc))); + DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: " + "%s\n", sid_string_dbg(sid), ads_errstr(rc))); goto done; } @@ -800,13 +799,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, status = NT_STATUS_UNSUCCESSFUL; DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: " "invalid number of results (count=%d)\n", - sid_to_string(sid_string, sid), count)); + sid_string_dbg(sid), count)); goto done; } if (!msg) { DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n", - sid_to_string(sid_string, sid))); + sid_string_dbg(sid))); status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -819,7 +818,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) { DEBUG(1,("%s: No primary group for sid=%s !?\n", - domain->name, sid_to_string(sid_string, sid))); + domain->name, sid_string_dbg(sid))); goto done; } @@ -885,7 +884,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n", - sid_to_string(sid_string, sid))); + sid_string_dbg(sid))); done: ads_memfree(ads, user_dn); ads_msgfree(ads, msg); @@ -920,7 +919,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *tmp_ctx = NULL; DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, - sid_string_static(group_sid))); + sid_string_dbg(group_sid))); *num_names = 0; @@ -1018,8 +1017,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, goto done; } if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name, &name_type)) { - DEBUG(10,("ads: lookup_groupmem: got sid %s from cache\n", - sid_string_static(&sid))); + DEBUG(10,("ads: lookup_groupmem: got sid %s from " + "cache\n", sid_string_dbg(&sid))); sid_copy(&(*sid_mem)[*num_names], &sid); (*names)[*num_names] = talloc_asprintf(*names, "%s%c%s", domain_name, @@ -1030,8 +1029,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, (*num_names)++; } else { - DEBUG(10, ("ads: lookup_groupmem: sid %s not found in cache\n", - sid_string_static(&sid))); + DEBUG(10, ("ads: lookup_groupmem: sid %s not found in " + "cache\n", sid_string_dbg(&sid))); sid_copy(&(sid_mem_nocache)[num_nocache], &sid); num_nocache++; } @@ -1096,7 +1095,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, status = NT_STATUS_OK; DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n", - sid_string_static(group_sid))); + sid_string_dbg(group_sid))); done: diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index c0254412e5..6cd85a2694 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -202,7 +202,7 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, domain = find_lookup_domain_from_sid(sid); if (domain == NULL) { DEBUG(5, ("Could not find domain for sid %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN); return; } @@ -788,7 +788,7 @@ void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, domain = find_domain_from_sid_noinit(user_sid); if (domain == NULL) { DEBUG(5, ("Could not find domain from SID %s\n", - sid_string_static(user_sid))); + sid_string_dbg(user_sid))); cont(private_data, False, NULL, 0); return; } diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 7ec8208f4b..c4554a2ad4 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -855,8 +855,8 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, fstrcpy(uname, name); strupper_m(uname); centry_end(centry, "NS/%s/%s", domain_name, uname); - DEBUG(10,("wcache_save_name_to_sid: %s\\%s -> %s (%s)\n", domain_name, uname, - sid_string_static(sid), nt_errstr(status))); + DEBUG(10,("wcache_save_name_to_sid: %s\\%s -> %s (%s)\n", domain_name, + uname, sid_string_dbg(sid), nt_errstr(status))); centry_free(centry); } @@ -1010,7 +1010,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid)); if (!centry) { DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n", - sid_string_static(sid))); + sid_string_dbg(sid))); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -1023,7 +1023,9 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, *cached_nt_pass = (const uint8 *)centry_hash16(centry, mem_ctx); if (*cached_nt_pass == NULL) { - const char *sidstr = sid_string_static(sid); + fstring sidstr; + + sid_to_string(sidstr, sid); /* Bad (old) cred cache. Delete and pretend we don't have it. */ @@ -1049,7 +1051,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, status = centry->status; DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status: %s\n", - sid_string_static(sid), nt_errstr(status) )); + sid_string_dbg(sid), nt_errstr(status) )); centry_free(centry); return status; @@ -3696,7 +3698,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain ) DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, " "flags = 0x%x, attributes = 0x%x, type = 0x%x\n", domain->name, domain->alt_name, - sid_string_static(&domain->sid), + sid_string_dbg(&domain->sid), domain->domain_flags, domain->domain_trust_attribs, domain->domain_type)); @@ -3815,7 +3817,7 @@ static void wcache_save_user_pwinfo(struct winbindd_domain *domain, centry_end(centry, "NSS/PWINFO/%s", sid_string_static(user_sid) ); - DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_static(user_sid) )); + DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_dbg(user_sid) )); centry_free(centry); } @@ -3847,7 +3849,7 @@ NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, centry_free(centry); DEBUG(10,("nss_get_info_cached: [Cached] - user_sid %s\n", - sid_string_static(user_sid))); + sid_string_dbg(user_sid))); return NT_STATUS_OK; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 30e274ff86..dc8cebf92f 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -77,7 +77,7 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu if (domain == NULL) { DEBUG(3, ("Could not find domain for sid %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto done; } @@ -86,7 +86,7 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("sid_to_name failed for sid %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto done; } @@ -109,7 +109,7 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu if (domain == NULL) { DEBUG(3, ("Could not find domain from SID %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto done; } @@ -126,7 +126,7 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu for (i=0; i %s\n", (unsigned int)ret_uid, - sid_string_static(pquerying_user_sid) )); + sid_string_dbg(pquerying_user_sid))); } } } @@ -244,7 +244,7 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, (sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) { DEBUG(10,("fill_grent_mem_domain_users: querying user = %s\n", - sid_string_static(pquerying_user_sid) )); + sid_string_dbg(pquerying_user_sid) )); status = domain->methods->lookup_usergroups(domain, mem_ctx, @@ -254,7 +254,7 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("fill_grent_mem_domain_users: lookup_usergroups failed " "for sid %s in domain %s (error: %s)\n", - sid_string_static(pquerying_user_sid), + sid_string_dbg(pquerying_user_sid), domain->name, nt_errstr(status))); return False; @@ -278,7 +278,8 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, enum lsa_SidType type; DEBUG(10,("fill_grent_mem_domain_users: sid %s in 'Domain Users' in domain %s\n", - sid_string_static(pquerying_user_sid), domain->name )); + sid_string_dbg(pquerying_user_sid), + domain->name )); status = domain->methods->sid_to_name(domain, mem_ctx, pquerying_user_sid, @@ -288,7 +289,7 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("could not lookup username for user " "sid %s in domain %s (error: %s)\n", - sid_string_static(pquerying_user_sid), + sid_string_dbg(pquerying_user_sid), domain->name, nt_errstr(status))); return False; @@ -488,7 +489,7 @@ static bool fill_grent_mem(struct winbindd_domain *domain, if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) return False; - DEBUG(10, ("group SID %s\n", sid_string_static(group_sid))); + DEBUG(10, ("group SID %s\n", sid_string_dbg(group_sid))); /* Initialize with no members */ @@ -511,8 +512,8 @@ static bool fill_grent_mem(struct winbindd_domain *domain, ((group_name_type==SID_NAME_ALIAS) && domain->primary)) ) { DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", - sid_string_static(group_sid), domain->name, - group_name_type)); + sid_string_dbg(group_sid), + domain->name, group_name_type)); goto done; } @@ -836,7 +837,7 @@ static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID g if ( (s->domain = find_domain_from_sid_noinit(&group_sid)) == NULL ) { DEBUG(3, ("Could not find domain for sid %s\n", - sid_string_static(&group_sid))); + sid_string_dbg(&group_sid))); request_error(state); return; } @@ -1191,7 +1192,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state) enum lsa_SidType type; DEBUG(10, ("SID %s not in idmap\n", - sid_string_static(&group_sid))); + sid_string_dbg(&group_sid))); if (!pdb_sid_to_id(&group_sid, &id, &type)) { DEBUG(1, ("could not look up gid for group " @@ -1690,7 +1691,7 @@ void winbindd_getuserdomgroups(struct winbindd_cli_state *state) /* Get info for the domain */ if ((domain = find_domain_from_sid_noinit(&user_sid)) == NULL) { DEBUG(0,("could not find domain entry for sid %s\n", - sid_string_static(&user_sid))); + sid_string_dbg(&user_sid))); request_error(state); return; } diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 6f7b562415..ebea6a7495 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -385,7 +385,9 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, result = idmap_sid_to_gid(&sid, &state->response.data.gid); - DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid)); + DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", + NT_STATUS_V(result), sid_string_dbg(&sid), + state->response.data.gid)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4eda0fcada..8a372a3a8c 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -304,7 +304,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, debug_nt_user_token(DBGC_CLASS, 10, token); for (i=0; iname )); + DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid), + domain->name )); result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy); if (!NT_STATUS_IS_OK(result)) { @@ -409,13 +409,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; SAM_USERINFO_CTR *ctr; - fstring sid_string; uint32 user_rid; NET_USER_INFO_3 *user; struct rpc_pipe_client *cli; - DEBUG(3,("rpc: query_user sid=%s\n", - sid_to_string(sid_string, user_sid))); + DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid))); if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) return NT_STATUS_UNSUCCESSFUL; @@ -430,7 +428,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", - sid_string_static(user_sid))); + sid_string_dbg(user_sid))); sid_compose(&user_info->user_sid, &domain->sid, user->user_rid); sid_compose(&user_info->group_sid, &domain->sid, @@ -506,12 +504,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; DOM_GID *user_groups; unsigned int i; - fstring sid_string; uint32 user_rid; struct rpc_pipe_client *cli; - DEBUG(3,("rpc: lookup_usergroups sid=%s\n", - sid_to_string(sid_string, user_sid))); + DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid))); if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) return NT_STATUS_UNSUCCESSFUL; @@ -677,12 +673,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, uint32 *rid_mem = NULL; uint32 group_rid; unsigned int j; - fstring sid_string; struct rpc_pipe_client *cli; unsigned int orig_timeout; DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, - sid_to_string(sid_string, group_sid))); + sid_string_dbg(group_sid))); if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n", diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 01cdd0a9d3..6241d84fe6 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -73,7 +73,6 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, struct winbindd_pw *pw) { fstring output_username; - fstring sid_string; if (!pw || !dom_name || !user_name) return False; @@ -81,14 +80,16 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, /* Resolve the uid number */ if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) { - DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); + DEBUG(1, ("error getting user id for sid %s\n", + sid_string_dbg(user_sid))); return False; } /* Resolve the gid number */ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) { - DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); + DEBUG(1, ("error getting group id for sid %s\n", + sid_string_dbg(group_sid))); return False; } @@ -146,7 +147,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, &sid, &user_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("error getting user info for sid %s\n", - sid_string_static(&sid))); + sid_string_dbg(&sid))); return WINBINDD_ERROR; } @@ -158,7 +159,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid, &state->response.data.user_info.group_rid)) { DEBUG(1, ("Could not extract group rid out of %s\n", - sid_string_static(&sid))); + sid_string_dbg(&sid))); return WINBINDD_ERROR; } @@ -203,7 +204,7 @@ static void winbindd_getpwsid(struct winbindd_cli_state *state, s->domain = find_domain_from_sid_noinit(sid); if (s->domain == NULL) { DEBUG(3, ("Could not find domain for sid %s\n", - sid_string_static(sid))); + sid_string_dbg(sid))); goto error; } @@ -230,8 +231,8 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, talloc_get_type_abort(private_data, struct getpwsid_state); if (!success) { - DEBUG(5, ("Could not query domain %s SID %s\n", s->domain->name, - sid_string_static(&s->user_sid))); + DEBUG(5, ("Could not query domain %s SID %s\n", + s->domain->name, sid_string_dbg(&s->user_sid))); request_error(s->state); return; } @@ -247,7 +248,7 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, domain = find_lookup_domain_from_sid(&s->user_sid); if (domain == NULL) { DEBUG(5, ("find_lookup_domain_from_sid(%s) failed\n", - sid_string_static(&s->user_sid))); + sid_string_dbg(&s->user_sid))); request_error(s->state); return; } @@ -258,7 +259,7 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, /* If this still fails we ar4e done. Just error out */ if ( !user_name ) { DEBUG(5,("Could not obtain a name for SID %s\n", - sid_string_static(&s->user_sid))); + sid_string_dbg(&s->user_sid))); request_error(s->state); return; } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 2389a4be13..b552aac709 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -193,7 +193,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const DEBUG(2,("Added domain %s %s %s\n", domain->name, domain->alt_name, - &domain->sid?sid_string_static(&domain->sid):"")); + &domain->sid?sid_string_dbg(&domain->sid):"")); return domain; } @@ -922,8 +922,7 @@ struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid) * one to contact the external DC's. On member servers the internal * domains are different: These are part of the local SAM. */ - DEBUG(10, ("find_lookup_domain_from_sid(%s)\n", - sid_string_static(sid))); + DEBUG(10, ("find_lookup_domain_from_sid(%s)\n", sid_string_dbg(sid))); if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) { DEBUG(10, ("calling find_domain_from_sid\n")); -- cgit From 54ae9dfcbce727ae3107f21eee68762502acda60 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:49:15 +0100 Subject: Use sid_string_talloc where we have a tmp talloc ctx (This used to be commit 0a911d38b8f4be382a9df60f9c6de0c500464b3a) --- source3/winbindd/winbindd_misc.c | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 9d77879e76..43ec5c6d9a 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -108,16 +108,16 @@ void winbindd_list_trusted_domains(struct winbindd_cli_state *state) for ( d=domain_list(); d; d=d->next ) { if ( !extra_data ) { - extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s", - d->name, - d->alt_name ? d->alt_name : d->name, - sid_string_static(&d->sid)); + extra_data = talloc_asprintf( + state->mem_ctx, "%s\\%s\\%s", + d->name, d->alt_name ? d->alt_name : d->name, + sid_string_talloc(state->mem_ctx, &d->sid)); } else { - extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s", - extra_data, - d->name, - d->alt_name ? d->alt_name : d->name, - sid_string_static(&d->sid)); + extra_data = talloc_asprintf( + state->mem_ctx, "%s\n%s\\%s\\%s", + extra_data, d->name, + d->alt_name ? d->alt_name : d->name, + sid_string_talloc(state->mem_ctx, &d->sid)); } } @@ -163,17 +163,18 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain * extra_data = talloc_strdup(state->mem_ctx, ""); if (num_domains > 0) - extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s", - names[0], - alt_names[0] ? alt_names[0] : names[0], - sid_string_static(&sids[0])); + extra_data = talloc_asprintf( + state->mem_ctx, "%s\\%s\\%s", + names[0], alt_names[0] ? alt_names[0] : names[0], + sid_string_talloc(state->mem_ctx, &sids[0])); for (i=1; imem_ctx, "%s\n%s\\%s\\%s", - extra_data, - names[i], - alt_names[i] ? alt_names[i] : names[i], - sid_string_static(&sids[i])); + extra_data = talloc_asprintf( + state->mem_ctx, "%s\n%s\\%s\\%s", + extra_data, names[i], + alt_names[i] ? alt_names[i] : names[i], + sid_string_talloc(state->mem_ctx, &sids[i])); + /* add our primary domain */ for (i=0; irequest.data.list_all_domains && !have_own_domain) { - extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s", - extra_data, - domain->name, - domain->alt_name ? domain->alt_name : domain->name, - sid_string_static(&domain->sid)); + extra_data = talloc_asprintf( + state->mem_ctx, "%s\n%s\\%s\\%s", + extra_data, domain->name, + domain->alt_name ? domain->alt_name : domain->name, + sid_string_talloc(state->mem_ctx, &domain->sid)); } /* This is a bit excessive, but the extra data sooner or later will be -- cgit From d899b8c56ad6556baf2d2374704cc8cd1b15d5ad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:58:28 +0100 Subject: Use sid_to_string directly It seems a bit pointless to do a fstrcpy(dst, sid_string_static(src)) (This used to be commit c221c246b10e2dbbd54a9af2dc45de2eae237380) --- source3/winbindd/winbindd_async.c | 6 +++--- source3/winbindd/winbindd_misc.c | 6 ++---- source3/winbindd/winbindd_util.c | 3 +-- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 6cd85a2694..1c30558058 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -175,7 +175,7 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, bool success, ZERO_STRUCT(request); request.cmd = WINBINDD_LOOKUPSID; - fstrcpy(request.data.sid, sid_string_static(&s->sid)); + sid_to_string(request.data.sid, &s->sid); do_async_domain(mem_ctx, root_domain, &request, lookupsid_recv2, (void *)cont, s); @@ -209,7 +209,7 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, ZERO_STRUCT(request); request.cmd = WINBINDD_LOOKUPSID; - fstrcpy(request.data.sid, sid_string_static(sid)); + sid_to_string(request.data.sid, sid); if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupsid_state)) == NULL ) { DEBUG(0, ("winbindd_lookupsid_async: talloc failed\n")); @@ -795,7 +795,7 @@ void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, ZERO_STRUCT(request); request.cmd = WINBINDD_GETUSERDOMGROUPS; - fstrcpy(request.data.sid, sid_string_static(user_sid)); + sid_to_string(request.data.sid, user_sid); do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups, NULL, state); diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 43ec5c6d9a..2771faf152 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -466,8 +466,7 @@ void winbindd_domain_info(struct winbindd_cli_state *state) domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - fstrcpy(state->response.data.domain_info.sid, - sid_string_static(&domain->sid)); + sid_to_string(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; @@ -499,8 +498,7 @@ static void domain_info_init_recv(void *private_data, bool success) domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - fstrcpy(state->response.data.domain_info.sid, - sid_string_static(&domain->sid)); + sid_to_string(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index b552aac709..5ac1eb64da 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -668,8 +668,7 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai fstrcpy(state->response.data.domain_info.name, domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - fstrcpy(state->response.data.domain_info.sid, - sid_string_static(&domain->sid)); + sid_to_string(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; -- cgit From 14ef4cdec1ab6be55c97d0f32780cbddbcdde218 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 22:00:39 +0100 Subject: Replace sid_string_static with sid_to_string This adds 28 fstrings on the stack, but I think an fstring on the stack is still far better than a static one. (This used to be commit c7c885078be8fd3024c186044ac28275d7609679) --- source3/winbindd/idmap_cache.c | 5 ++++- source3/winbindd/idmap_tdb.c | 12 +++++++++--- source3/winbindd/winbindd_async.c | 3 ++- source3/winbindd/winbindd_cache.c | 36 ++++++++++++++++++++++++------------ source3/winbindd/winbindd_group.c | 6 ++++-- 5 files changed, 43 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 6455f5ee69..4e286f88c0 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -77,7 +77,10 @@ void idmap_cache_shutdown(struct idmap_cache_ctx *cache) NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct id_map *id) { - *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", sid_string_static(id->sid)); + fstring sidstr; + + *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", + sid_to_string(sidstr, id->sid)); if ( ! *sidkey) { DEBUG(1, ("failed to build sidkey, OOM?\n")); return NT_STATUS_NO_MEMORY; diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 1ec7085a3b..d693c357f7 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -712,8 +712,10 @@ static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map TDB_DATA data; char *keystr; unsigned long rec_id = 0; + fstring tmp; - if ((keystr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + if ((keystr = talloc_asprintf(ctx, "%s", + sid_to_string(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -864,6 +866,7 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_ NTSTATUS ret; TDB_DATA ksid, kid, data; char *ksidstr, *kidstr; + fstring tmp; /* make sure we initialized */ if ( ! dom->initialized) { @@ -905,7 +908,8 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_ goto done; } - if ((ksidstr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + if ((ksidstr = talloc_asprintf( + ctx, "%s", sid_to_string(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -977,6 +981,7 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct NTSTATUS ret; TDB_DATA ksid, kid, data; char *ksidstr, *kidstr; + fstring tmp; /* make sure we initialized */ if ( ! dom->initialized) { @@ -1018,7 +1023,8 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct goto done; } - if ((ksidstr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + if ((ksidstr = talloc_asprintf( + ctx, "%s", sid_to_string(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 1c30558058..0971476f44 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -458,8 +458,9 @@ bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, *len = 0; *result = NULL; for (i=0; itdb) { @@ -966,7 +966,7 @@ NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID return NT_STATUS_INVALID_SID; } - fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid)); + fstr_sprintf(key_str, "CRED/%s", sid_to_string(tmp, sid)); data = tdb_fetch(cache->tdb, string_tdb_data(key_str)); if (!data.dptr) { @@ -991,6 +991,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, NTSTATUS status; time_t t; uint32 rid; + fstring tmp; if (!cache->tdb) { return NT_STATUS_INTERNAL_DB_ERROR; @@ -1007,7 +1008,8 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, /* Try and get a salted cred first. If we can't fall back to an unsalted cred. */ - centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid)); + centry = wcache_fetch(cache, domain, "CRED/%s", + sid_to_string(tmp, sid)); if (!centry) { DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n", sid_string_dbg(sid))); @@ -1555,6 +1557,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, for (i=0; itdb) goto do_query; - centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid)); + centry = wcache_fetch(cache, domain, "U/%s", + sid_to_string(tmp, user_sid)); /* If we have an access denied cache entry and a cached info3 in the samlogon cache then do a query. This will force the rpc back end @@ -1852,8 +1857,9 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, * resulting might come from any of the SIDs. */ for (i=0; itdb, string_tdb_data(key_str)); @@ -3526,6 +3533,8 @@ static int pack_tdc_domains( struct winbindd_tdc_domain *domains, /* now pack each domain trust record */ for ( i=0; i 0 ) { DEBUG(10,("pack_tdc_domains: Packing domain %s (%s)\n", domains[i].domain_name, @@ -3535,7 +3544,7 @@ static int pack_tdc_domains( struct winbindd_tdc_domain *domains, len += tdb_pack( buffer+len, buflen-len, "fffddd", domains[i].domain_name, domains[i].dns_name, - sid_string_static(&domains[i].sid), + sid_to_string(tmp, &domains[i].sid), domains[i].trust_flags, domains[i].trust_attribs, domains[i].trust_type ); @@ -3806,6 +3815,7 @@ static void wcache_save_user_pwinfo(struct winbindd_domain *domain, uint32 gid) { struct cache_entry *centry; + fstring tmp; if ( (centry = centry_start(domain, status)) == NULL ) return; @@ -3815,7 +3825,7 @@ static void wcache_save_user_pwinfo(struct winbindd_domain *domain, centry_put_string( centry, gecos ); centry_put_uint32( centry, gid ); - centry_end(centry, "NSS/PWINFO/%s", sid_string_static(user_sid) ); + centry_end(centry, "NSS/PWINFO/%s", sid_to_string(tmp, user_sid) ); DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_dbg(user_sid) )); @@ -3832,11 +3842,13 @@ NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS nt_status; + fstring tmp; if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "NSS/PWINFO/%s", sid_string_static(user_sid)); + centry = wcache_fetch(cache, domain, "NSS/PWINFO/%s", + sid_to_string(tmp, user_sid)); if (!centry) goto do_query; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index dc8cebf92f..49562a112c 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1648,7 +1648,8 @@ static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, /* work out the response size */ for (i = 0; i < num_sids; i++) { - const char *s = sid_string_static(&sids[i]); + fstring s; + sid_to_string(s, &sids[i]); ret_size += strlen(s) + 1; } @@ -1661,7 +1662,8 @@ static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, } ofs = 0; for (i = 0; i < num_sids; i++) { - const char *s = sid_string_static(&sids[i]); + fstring s; + sid_to_string(s, &sids[i]); safe_strcpy(ret + ofs, s, ret_size - ofs - 1); ofs += strlen(ret+ofs) + 1; } -- cgit From 2e07c2ade89f4ff281c61f74cb88e09990cf5f46 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 22:47:30 +0100 Subject: s/sid_to_string/sid_to_fstring/ least surprise for callers (This used to be commit eb523ba77697346a365589101aac379febecd546) --- source3/winbindd/idmap_cache.c | 2 +- source3/winbindd/idmap_tdb.c | 10 ++++----- source3/winbindd/winbindd_async.c | 12 +++++------ source3/winbindd/winbindd_cache.c | 45 ++++++++++++++++++++++----------------- source3/winbindd/winbindd_group.c | 4 ++-- source3/winbindd/winbindd_idmap.c | 10 ++++----- source3/winbindd/winbindd_misc.c | 4 ++-- source3/winbindd/winbindd_pam.c | 4 ++-- source3/winbindd/winbindd_sid.c | 2 +- source3/winbindd/winbindd_util.c | 2 +- 10 files changed, 50 insertions(+), 45 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 4e286f88c0..cf46196ebe 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -80,7 +80,7 @@ NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct i fstring sidstr; *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", - sid_to_string(sidstr, id->sid)); + sid_to_fstring(sidstr, id->sid)); if ( ! *sidkey) { DEBUG(1, ("failed to build sidkey, OOM?\n")); return NT_STATUS_NO_MEMORY; diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index d693c357f7..e5f605361b 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -86,7 +86,7 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state sid_copy(&sid, &domain->sid); sid_append_rid(&sid, rid); - sid_to_string(keystr, &sid); + sid_to_fstring(keystr, &sid); key2 = string_term_tdb_data(keystr); if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) { @@ -714,8 +714,8 @@ static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map unsigned long rec_id = 0; fstring tmp; - if ((keystr = talloc_asprintf(ctx, "%s", - sid_to_string(tmp, map->sid))) == NULL) { + if ((keystr = talloc_asprintf( + ctx, "%s", sid_to_fstring(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -909,7 +909,7 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_ } if ((ksidstr = talloc_asprintf( - ctx, "%s", sid_to_string(tmp, map->sid))) == NULL) { + ctx, "%s", sid_to_fstring(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -1024,7 +1024,7 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct } if ((ksidstr = talloc_asprintf( - ctx, "%s", sid_to_string(tmp, map->sid))) == NULL) { + ctx, "%s", sid_to_fstring(tmp, map->sid))) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 0971476f44..76724582a1 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -175,7 +175,7 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, bool success, ZERO_STRUCT(request); request.cmd = WINBINDD_LOOKUPSID; - sid_to_string(request.data.sid, &s->sid); + sid_to_fstring(request.data.sid, &s->sid); do_async_domain(mem_ctx, root_domain, &request, lookupsid_recv2, (void *)cont, s); @@ -209,7 +209,7 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, ZERO_STRUCT(request); request.cmd = WINBINDD_LOOKUPSID; - sid_to_string(request.data.sid, sid); + sid_to_fstring(request.data.sid, sid); if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupsid_state)) == NULL ) { DEBUG(0, ("winbindd_lookupsid_async: talloc failed\n")); @@ -443,7 +443,7 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_ERROR; } - sid_to_string(state->response.data.sid.sid, &sid); + sid_to_fstring(state->response.data.sid.sid, &sid); state->response.data.sid.type = type; return WINBINDD_OK; @@ -460,7 +460,7 @@ bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, for (i=0; i %s (%s)\n", sid_string, name, nt_errstr(status))); centry_free(centry); @@ -902,7 +902,8 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI centry_put_uint32(centry, info->primary_gid); centry_put_sid(centry, &info->user_sid); centry_put_sid(centry, &info->group_sid); - centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid)); + centry_end(centry, "U/%s", sid_to_fstring(sid_string, + &info->user_sid)); DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name)); centry_free(centry); } @@ -966,7 +967,7 @@ NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID return NT_STATUS_INVALID_SID; } - fstr_sprintf(key_str, "CRED/%s", sid_to_string(tmp, sid)); + fstr_sprintf(key_str, "CRED/%s", sid_to_fstring(tmp, sid)); data = tdb_fetch(cache->tdb, string_tdb_data(key_str)); if (!data.dptr) { @@ -1009,7 +1010,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, fall back to an unsalted cred. */ centry = wcache_fetch(cache, domain, "CRED/%s", - sid_to_string(tmp, sid)); + sid_to_fstring(tmp, sid)); if (!centry) { DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n", sid_string_dbg(sid))); @@ -1027,7 +1028,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain, if (*cached_nt_pass == NULL) { fstring sidstr; - sid_to_string(sidstr, sid); + sid_to_fstring(sidstr, sid); /* Bad (old) cred cache. Delete and pretend we don't have it. */ @@ -1095,7 +1096,7 @@ NTSTATUS wcache_save_creds(struct winbindd_domain *domain, centry_put_hash16(centry, salted_hash); centry_put_hash16(centry, cred_salt); - centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid)); + centry_end(centry, "CRED/%s", sid_to_fstring(sid_string, sid)); DEBUG(10,("wcache_save_creds: %s\n", sid_string)); @@ -1470,7 +1471,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); + centry = wcache_fetch(cache, domain, "SN/%s", + sid_to_fstring(sid_string, sid)); if (!centry) goto do_query; @@ -1565,7 +1567,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, } centry = wcache_fetch(cache, domain, "SN/%s", - sid_to_string(tmp, &sid)); + sid_to_fstring(tmp, &sid)); if (!centry) { goto do_query; } @@ -1687,7 +1689,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, goto do_query; centry = wcache_fetch(cache, domain, "U/%s", - sid_to_string(tmp, user_sid)); + sid_to_fstring(tmp, user_sid)); /* If we have an access denied cache entry and a cached info3 in the samlogon cache then do a query. This will force the rpc back end @@ -1759,7 +1761,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (!cache->tdb) goto do_query; - centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); + centry = wcache_fetch(cache, domain, "UG/%s", + sid_to_fstring(sid_string, user_sid)); /* If we have an access denied cache entry and a cached info3 in the samlogon cache then do a query. This will force the rpc back end @@ -1826,7 +1829,7 @@ do_query: centry_put_sid(centry, &(*user_gids)[i]); } - centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid)); + centry_end(centry, "UG/%s", sid_to_fstring(sid_string, user_sid)); centry_free(centry); skip_save: @@ -1859,7 +1862,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, for (i=0; itdb) goto do_query; - centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); + centry = wcache_fetch(cache, domain, "GM/%s", + sid_to_fstring(sid_string, group_sid)); if (!centry) goto do_query; @@ -1999,7 +2003,7 @@ do_query: centry_put_string(centry, (*names)[i]); centry_put_uint32(centry, (*name_types)[i]); } - centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid)); + centry_end(centry, "GM/%s", sid_to_fstring(sid_string, group_sid)); centry_free(centry); skip_save: @@ -2480,7 +2484,8 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, return False; } - centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(tmp, sid)); + centry = wcache_fetch(cache, domain, "SN/%s", + sid_to_fstring(tmp, sid)); if (centry == NULL) { return False; } @@ -2690,7 +2695,7 @@ NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DEBUG(11,("we already have an entry, deleting that\n")); - fstr_sprintf(key_str, "CRED/%s", sid_to_string(tmp, sid)); + fstr_sprintf(key_str, "CRED/%s", sid_to_fstring(tmp, sid)); tdb_delete(cache->tdb, string_tdb_data(key_str)); @@ -3544,7 +3549,7 @@ static int pack_tdc_domains( struct winbindd_tdc_domain *domains, len += tdb_pack( buffer+len, buflen-len, "fffddd", domains[i].domain_name, domains[i].dns_name, - sid_to_string(tmp, &domains[i].sid), + sid_to_fstring(tmp, &domains[i].sid), domains[i].trust_flags, domains[i].trust_attribs, domains[i].trust_type ); @@ -3825,7 +3830,7 @@ static void wcache_save_user_pwinfo(struct winbindd_domain *domain, centry_put_string( centry, gecos ); centry_put_uint32( centry, gid ); - centry_end(centry, "NSS/PWINFO/%s", sid_to_string(tmp, user_sid) ); + centry_end(centry, "NSS/PWINFO/%s", sid_to_fstring(tmp, user_sid) ); DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_dbg(user_sid) )); @@ -3848,7 +3853,7 @@ NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, goto do_query; centry = wcache_fetch(cache, domain, "NSS/PWINFO/%s", - sid_to_string(tmp, user_sid)); + sid_to_fstring(tmp, user_sid)); if (!centry) goto do_query; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 49562a112c..140943cc2c 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1649,7 +1649,7 @@ static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, /* work out the response size */ for (i = 0; i < num_sids; i++) { fstring s; - sid_to_string(s, &sids[i]); + sid_to_fstring(s, &sids[i]); ret_size += strlen(s) + 1; } @@ -1663,7 +1663,7 @@ static void getusersids_recv(void *private_data, bool success, DOM_SID *sids, ofs = 0; for (i = 0; i < num_sids; i++) { fstring s; - sid_to_string(s, &sids[i]); + sid_to_fstring(s, &sids[i]); safe_strcpy(ret + ofs, s, ret_size - ofs - 1); ofs += strlen(ret+ofs) + 1; } diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index ebea6a7495..3c7aa2d0c2 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -84,7 +84,7 @@ void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, request.cmd = WINBINDD_DUAL_SET_MAPPING; request.data.dual_idmapset.id = map->xid.id; request.data.dual_idmapset.type = map->xid.type; - sid_to_string(request.data.dual_idmapset.sid, map->sid); + sid_to_fstring(request.data.dual_idmapset.sid, map->sid); do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv, (void *)cont, private_data); @@ -301,7 +301,7 @@ void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, struct winbindd_request request; ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_SID2UID; - sid_to_string(request.data.dual_sid2id.sid, sid); + sid_to_fstring(request.data.dual_sid2id.sid, sid); do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, (void *)cont, private_data); } @@ -357,7 +357,7 @@ void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, struct winbindd_request request; ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_SID2GID; - sid_to_string(request.data.dual_sid2id.sid, sid); + sid_to_fstring(request.data.dual_sid2id.sid, sid); DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", request.data.dual_sid2id.sid)); @@ -444,7 +444,7 @@ enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, result = idmap_uid_to_sid(&sid, state->request.data.uid); if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); + sid_to_fstring(state->response.data.sid.sid, &sid); state->response.data.sid.type = SID_NAME_USER; return WINBINDD_OK; } @@ -501,7 +501,7 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, result = idmap_gid_to_sid(&sid, state->request.data.gid); if (NT_STATUS_IS_OK(result)) { - sid_to_string(state->response.data.sid.sid, &sid); + sid_to_fstring(state->response.data.sid.sid, &sid); DEBUG(10, ("[%5lu]: retrieved sid: %s\n", (unsigned long)state->pid, state->response.data.sid.sid)); diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 2771faf152..8c3ef5bb6f 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -466,7 +466,7 @@ void winbindd_domain_info(struct winbindd_cli_state *state) domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - sid_to_string(state->response.data.domain_info.sid, &domain->sid); + sid_to_fstring(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; @@ -498,7 +498,7 @@ static void domain_info_init_recv(void *private_data, bool success) domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - sid_to_string(state->response.data.domain_info.sid, &domain->sid); + sid_to_fstring(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 8a372a3a8c..5133239258 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -51,7 +51,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.user_rid = info3->user_rid; state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_string(str_sid, &(info3->dom_sid.sid)); + sid_to_fstring(str_sid, &(info3->dom_sid.sid)); fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); state->response.data.auth.info3.num_groups = info3->num_groups; @@ -187,7 +187,7 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, sid_copy(&user_sid, &info3->dom_sid.sid); sid_append_rid(&user_sid, info3->user_rid); - sid_to_string(sidstr, &user_sid); + sid_to_fstring(sidstr, &user_sid); afsname = talloc_string_sub(mem_ctx, afsname, "%s", sidstr); } diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 302460c942..0e8e6ca00b 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -118,7 +118,7 @@ static void lookupname_recv(void *private_data, bool success, return; } - sid_to_string(state->response.data.sid.sid, sid); + sid_to_fstring(state->response.data.sid.sid, sid); state->response.data.sid.type = type; request_ok(state); return; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 5ac1eb64da..70468b6bcd 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -668,7 +668,7 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai fstrcpy(state->response.data.domain_info.name, domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); - sid_to_string(state->response.data.domain_info.sid, &domain->sid); + sid_to_fstring(state->response.data.domain_info.sid, &domain->sid); state->response.data.domain_info.native_mode = domain->native_mode; -- cgit From d9553e8fd19a0832f3fbd19ffcc595a701d87e34 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Mon, 17 Dec 2007 17:33:48 -0600 Subject: Fix a segv in winbindd caused by trying to free an fstring. Make a copy of the machine_password and machine_account strings in all conditional paths so that SAFE_FREE() will always be valid. (This used to be commit 194c4640b158457a6d0d5ea91e28d41d619c77de) --- source3/winbindd/winbindd_cm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index cb366a293c..6c5633c2b2 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2005,11 +2005,15 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, domain_name = domain->name; goto schannel; } else { - machine_password = conn_pwd; - machine_account = conn->cli->user_name; + machine_password = SMB_STRDUP(conn_pwd); + machine_account = SMB_STRDUP(conn->cli->user_name); domain_name = conn->cli->domain; } + if (!machine_password || !machine_account) { + result = NT_STATUS_NO_MEMORY; + goto done; + } /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ -- cgit From a62cc944435fb9964c765cb9495f18308823ac8f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 18 Dec 2007 01:55:48 +0100 Subject: Fix logic error in cm_connect_sam(). Don't fall back to schannel when trust creds could be obtained. This is still not complete, but I am getting closer. Michael (This used to be commit 7c9fa597d684a25822b4db6615f28336f2d64ef3) --- source3/winbindd/winbindd_cm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 6c5633c2b2..8ea815535f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2003,7 +2003,6 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto schannel; } domain_name = domain->name; - goto schannel; } else { machine_password = SMB_STRDUP(conn_pwd); machine_account = SMB_STRDUP(conn->cli->user_name); -- cgit From e518e19bc0000019f131354f55e9f5b55f6a2c5e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Dec 2007 15:02:59 +0100 Subject: Remove Get_Pwnam and its associated static variable All callers are replaced by Get_Pwnam_alloc (This used to be commit 735f59315497113aebadcf9ad387e3dbfffa284a) --- source3/winbindd/idmap_nss.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index fa9f2c9681..46c24d7fcb 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -145,7 +145,6 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma } for (i = 0; ids[i]; i++) { - struct passwd *pw; struct group *gr; enum lsa_SidType type; const char *dom_name = NULL; @@ -166,17 +165,20 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma } switch (type) { - case SID_NAME_USER: + case SID_NAME_USER: { + struct passwd *pw; /* this will find also all lower case name and use username level */ - - pw = Get_Pwnam(name); + + pw = Get_Pwnam_alloc(talloc_tos(), name); if (pw) { ids[i]->xid.id = pw->pw_uid; ids[i]->xid.type = ID_TYPE_UID; ids[i]->status = ID_MAPPED; } + TALLOC_FREE(pw); break; + } case SID_NAME_DOM_GRP: case SID_NAME_ALIAS: -- cgit From e3bb148b941e67b5caea3db2c8ef9efc984598fa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 19 Dec 2007 17:53:14 +0100 Subject: Only retrieve password policies in pam_auth when WBFLAG_PAM_GET_PWD_POLICY is set. This essentially re-establishes r14496 (2155bb0535656f294bd054d6a0a7d16a9a71c31b) which was undone in r17723 (43bd8c00abb38eb23a1497a255d194fb1bbffffb) for reasons that are unclear to me. Maybe I am being too naive. Now we do again only retrieve the password policy when called from the pam_winbind module. This fixes logons delegated to AD trusted domain controllers: We need to connect to the sam to retrieve the password policy. But auhtenticated session setup is not possible when contacting the trusted domain dc and afterwards, SamrConnect also fails with whatever credentials and method used. Michael (This used to be commit 6d765e0de523211a2d0b43a2c4c4117f5f0c662f) --- source3/winbindd/winbindd_pam.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 5133239258..7a9014a82f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1593,13 +1593,16 @@ process_result: } } - result = fillup_password_policy(domain, state); - if (!NT_STATUS_IS_OK(result) - && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) - { - DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); - goto done; + if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { + result = fillup_password_policy(domain, state); + + if (!NT_STATUS_IS_OK(result) + && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) + { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); + goto done; + } } result = NT_STATUS_OK; -- cgit From 8ded1df76739363259edce0515b097510e342595 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 21 Dec 2007 15:12:40 +0100 Subject: Kill fstring in getdcname & getanydcname return. Guenther (This used to be commit b7383818168863a7ba43c2456f8c44e96e76707a) --- source3/winbindd/winbindd_cm.c | 4 ++-- source3/winbindd/winbindd_misc.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 8ea815535f..7fb42a6dca 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -570,7 +570,7 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, WERROR werr; TALLOC_CTX *mem_ctx; unsigned int orig_timeout; - fstring tmp; + char *tmp = NULL; char *p; /* Hmmmm. We can only open one connection to the NETLOGON pipe at the @@ -602,7 +602,7 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname, - domain->name, tmp); + domain->name, &tmp); /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 8c3ef5bb6f..76f2554122 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -231,7 +231,7 @@ void winbindd_getdcname(struct winbindd_cli_state *state) enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, struct winbindd_cli_state *state) { - fstring dcname_slash; + char *dcname_slash = NULL; char *p; struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; @@ -262,12 +262,12 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, werr = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname, state->request.domain_name, - dcname_slash); + &dcname_slash); } else { werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, domain->dcname, state->request.domain_name, - dcname_slash); + &dcname_slash); } /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); -- cgit From 98bc591c4fac3a26796c596b55b735739d96c76b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Dec 2007 16:43:02 -0800 Subject: Add NT error to debug to try and track this down. Jermey. (This used to be commit a1482b09150f4d292965c77bc73d47fb14f5eb85) --- source3/winbindd/winbindd_group.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 140943cc2c..fbd2fee692 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1045,7 +1045,10 @@ static bool get_sam_group_entries(struct getent_state *ent) status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n")); + DEBUG(3,("get_sam_group_entries: " + "Failed to enumerate " + "domain local groups with error %s!\n", + nt_errstr(status))); num_entries = 0; } else -- cgit From a59280792cab616f5b269960ab68bc44ccc1fd38 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Dec 2007 22:16:31 +0100 Subject: Remove tiny code duplication sid_size did the same as ndr_size_dom_sid (This used to be commit 8aec5d09ba023413bd8ecbdfbc7d23904df94389) --- source3/winbindd/winbindd_cm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 7fb42a6dca..6a4f531c5f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -978,6 +978,7 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss, char *p; fstring my_acct_name; fstring my_mailslot; + size_t sid_size; if (dc_ss->ss_family != AF_INET) { return false; @@ -1019,7 +1020,9 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss, SIVAL(p, 0, 0x80); p+=4; - SIVAL(p, 0, sid_size(sid)); + sid_size = ndr_size_dom_sid(sid, 0); + + SIVAL(p, 0, sid_size); p+=4; p = ALIGN4(p, outbuf); @@ -1027,12 +1030,12 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss, return false; } - sid_linearize(p, sid_size(sid), sid); - if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + sid_linearize(p, sid_size, sid); + if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { return false; } - p += sid_size(sid); + p += sid_size; SIVAL(p, 0, 1); SSVAL(p, 4, 0xffff); -- cgit From f10074e84b41d141958912c3fb9f2c6fdbba68b3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Dec 2007 14:43:32 -0800 Subject: Use correct size value for linearize call. Jeremy. (This used to be commit a5df44f5b7887d10c1e1a0b7a3dd05bcf31015e1) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 6a4f531c5f..33674d2cf7 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1030,10 +1030,10 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss, return false; } - sid_linearize(p, sid_size, sid); if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { return false; } + sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid); p += sid_size; -- cgit From 9a45dcef4d7c0f85d371afb2f7e09ae63bb7ae65 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 4 Jan 2008 13:31:07 -0600 Subject: When connecting to an AD DC, use the DsGetDCName variant. This allows us to deal with child domains in transitive forest trusts. It also allows us to fill in the forest name to the target domain to the struct winbindd_domain *. (This used to be commit ed30516bb0f55f9ba466debf91b6e33d1c28a484) --- source3/winbindd/winbindd_cm.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 33674d2cf7..99e401d53f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -601,8 +601,34 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); - werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname, + if (our_domain->active_directory) { + struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL; + + werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe, + mem_ctx, + our_domain->dcname, + domain->name, + NULL, + NULL, + DS_RETURN_DNS_NAME, + &domain_info); + if (W_ERROR_IS_OK(werr)) { + fstrcpy(tmp, domain_info->domain_controller_name); + if (strlen(domain->alt_name) == 0) { + fstrcpy(domain->alt_name, + CONST_DISCARD(char*, domain_info->domain_name)); + } + if (strlen(domain->forest_name) == 0) { + fstrcpy(domain->forest_name, + CONST_DISCARD(char*, domain_info->dns_forest_name)); + } + } + } else { + + werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, + our_domain->dcname, domain->name, &tmp); + } /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); @@ -1869,9 +1895,17 @@ no_lsarpc_ds: if (dns_name) fstrcpy(domain->alt_name, dns_name); - if ( forest_name ) + /* See if we can set some domain trust flags about + ourself */ + + if ( forest_name ) { fstrcpy(domain->forest_name, forest_name); + if (strequal(domain->forest_name, domain->alt_name)) { + domain->domain_flags = DS_DOMAIN_TREE_ROOT; + } + } + if (dom_sid) sid_copy(&domain->sid, dom_sid); } else { -- cgit From bcc2a6a9d759adc52ed9176bd1153da4b5a79722 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 4 Jan 2008 13:32:58 -0600 Subject: Ensure that winbindd_getgroups() can deal with a UPN name. A user logging in via GDM was not getting a complete list of supplementary groups in his/her token. This is because getgroup() was not able to find the winbindd_domain* using the DNS name. Fallback to matching the DNS name is the short name match failes. (This used to be commit 2030a8de19a2c7c735a8aa367dd953e4a5c447b8) --- source3/winbindd/winbindd_group.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index fbd2fee692..62e8d1c40b 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1494,9 +1494,18 @@ void winbindd_getgroups(struct winbindd_cli_state *state) s->username = talloc_strdup( state->mem_ctx, state->request.data.username ); } - /* Get info for the domain */ + /* Get info for the domain (either by short domain name or + DNS name in the case of a UPN) */ s->domain = find_domain_from_name_noinit(s->domname); + if (!s->domain) { + char *p = strchr(s->username, '@'); + + if (p) { + s->domain = find_domain_from_name_noinit(p+1); + } + + } if (s->domain == NULL) { DEBUG(7, ("could not find domain entry for domain %s\n", -- cgit From 4093b0632cda821f331f9ff50c51aa63c799292f Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 4 Jan 2008 13:34:10 -0600 Subject: Add a missing check for dealing with a one-way trust in query_user(). (This used to be commit f89e356bdaa203ef0a3ce6b8bd52170afa68a2c9) --- source3/winbindd/winbindd_rpc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index ffb47692cb..f5e1226447 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -456,6 +456,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain, return NT_STATUS_OK; } + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(10,("query_user: No incoming trust for domain %s\n", + domain->name)); + return NT_STATUS_OK; + } + /* no cache; hit the wire */ result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); -- cgit From 84a50e21541e4c3a0bfb70d5d501dc4b7e6f9714 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 4 Jan 2008 13:35:41 -0600 Subject: Fix the inherited trust flags when spidering the trust heirarchy. Also *do not* clear the trust list when rescanning or else it is possible to suffer from a race condition where no trusted domains can be found. (This used to be commit e7164a252bf213a74d6eeac5aa04645eed5be241) --- source3/winbindd/winbindd_ads.c | 12 ++++++++++++ source3/winbindd/winbindd_util.c | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index c9b2a52388..3aba824b0b 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1270,12 +1270,24 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, d.domain_type = domains[i].trust_type; d.domain_trust_attribs = domains[i].trust_attributes; } else { + /* Look up the record in the cache */ + struct winbindd_tdc_domain *parent; + DEBUG(10,("trusted_domains(ads): Inheriting trust " "flags for domain %s\n", d.alt_name)); + + parent = wcache_tdc_fetch_domain(NULL, domain->name); + if (parent) { + d.domain_flags = parent->trust_flags; + d.domain_type = parent->trust_type; + d.domain_trust_attribs = parent->trust_attribs; + } else { d.domain_flags = domain->domain_flags; d.domain_type = domain->domain_type; d.domain_trust_attribs = domain->domain_trust_attribs; } + TALLOC_FREE(parent); + } wcache_tdc_add_domain( &d ); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 70468b6bcd..cc12d4b7ea 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -500,9 +500,13 @@ void rescan_trusted_domains( void ) ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) return; - /* clear the TRUSTDOM cache first */ - - wcache_tdc_clear(); + /* I use to clear the cache here and start over but that + caused problems in child processes that needed the + trust dom list early on. Removing it means we + could have some trusted domains listed that have been + removed from our primary domain's DC until a full + restart. This should be ok since I think this is what + Windows does as well. */ /* this will only add new domains we didn't already know about in the domain_list()*/ -- cgit From 18699d003b1d4460ffb36db61860e6c31acbf1cb Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 26 Nov 2007 11:44:30 +0100 Subject: Prevent winbindd from segfaulting due to corrupted cache tdb. If we try to flush the caches and due to a corrupted tdb we and have no tdb context close the tdb and validate it. Initialize the cache afterwards again. (This used to be commit d0c0f91fb9f3438a18c6f47ed894f525beb75cbf) --- source3/winbindd/winbindd.c | 18 +++++++++++++++++- source3/winbindd/winbindd_cache.c | 22 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 07cf22618e..dfad50bf96 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -121,7 +121,23 @@ static void flush_caches(void) otherwise cached access denied errors due to restrict anonymous hang around until the sequence number changes. */ - wcache_invalidate_cache(); + if (wcache_invalidate_cache() < 0) { + DEBUG(0, ("invalidating the cache failed; revalidate the cache\n")); + /* Close the cache to be able to valdite the cache */ + close_winbindd_cache(); + /* + * Ensure all cache and idmap caches are consistent + * before we initialize the cache again. + */ + if (winbindd_validate_cache() < 0) { + DEBUG(0, ("corrupted tdb found, trying to restore backup\n")); + } + + /* Initialize cache again. */ + if (!initialize_winbindd_cache()) { + exit(1); + } + } } /* Handle the signal by unlinking socket and exiting */ diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index f63c7a5b2f..62a68aa8aa 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2261,7 +2261,7 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain, netsamlogon_clear_cached_user(cache->tdb, info3); } -void wcache_invalidate_cache(void) +int wcache_invalidate_cache(void) { struct winbindd_domain *domain; @@ -2270,9 +2270,15 @@ void wcache_invalidate_cache(void) DEBUG(10, ("wcache_invalidate_cache: invalidating cache " "entries for %s\n", domain->name)); - if (cache) - tdb_traverse(cache->tdb, traverse_fn, NULL); + if (cache) { + if (cache->tdb) { + tdb_traverse(cache->tdb, traverse_fn, NULL); + } else { + return -1; + } + } } + return 0; } bool init_wcache(void) @@ -2354,6 +2360,16 @@ bool initialize_winbindd_cache(void) return True; } +void close_winbindd_cache() +{ + if (!wcache) + return; + if (wcache->tdb) { + tdb_close(wcache->tdb); + wcache->tdb = NULL; + } +} + void cache_store_response(pid_t pid, struct winbindd_response *response) { fstring key_str; -- cgit From c4d3f1b0f5345086e18cb4740e7a0c4fa222089a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 10:41:09 +0100 Subject: Add some braces to if statement. Michael (This used to be commit 66fc1db1d19d11792d9506b06ad914d88b7e0663) --- source3/winbindd/winbindd_cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 62a68aa8aa..9602a128a6 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2362,8 +2362,9 @@ bool initialize_winbindd_cache(void) void close_winbindd_cache() { - if (!wcache) + if (!wcache) { return; + } if (wcache->tdb) { tdb_close(wcache->tdb); wcache->tdb = NULL; -- cgit From 696cf4d3c013f99d034c19c6762bf71c7c1ee8a6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 10:59:14 +0100 Subject: Make wcache_invalidate_cache() return bool, not int. Michael (This used to be commit dba24ceae78ffc49200b647838b6bf3657275add) --- source3/winbindd/winbindd.c | 2 +- source3/winbindd/winbindd_cache.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index dfad50bf96..8ebae3f16d 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -121,7 +121,7 @@ static void flush_caches(void) otherwise cached access denied errors due to restrict anonymous hang around until the sequence number changes. */ - if (wcache_invalidate_cache() < 0) { + if (!wcache_invalidate_cache()) { DEBUG(0, ("invalidating the cache failed; revalidate the cache\n")); /* Close the cache to be able to valdite the cache */ close_winbindd_cache(); diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 9602a128a6..19becab1a6 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2261,7 +2261,7 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain, netsamlogon_clear_cached_user(cache->tdb, info3); } -int wcache_invalidate_cache(void) +bool wcache_invalidate_cache(void) { struct winbindd_domain *domain; @@ -2274,11 +2274,11 @@ int wcache_invalidate_cache(void) if (cache->tdb) { tdb_traverse(cache->tdb, traverse_fn, NULL); } else { - return -1; + return false; } } } - return 0; + return true; } bool init_wcache(void) -- cgit From 0818d41697e839741b642efb8377f43686c33b7b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 11:19:27 +0100 Subject: Fix a comment. Michael (This used to be commit 62d6d4fff2edcce04e793d2a2f877cb3f4fedbdb) --- source3/winbindd/winbindd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 8ebae3f16d..5e9900d1d6 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -130,7 +130,8 @@ static void flush_caches(void) * before we initialize the cache again. */ if (winbindd_validate_cache() < 0) { - DEBUG(0, ("corrupted tdb found, trying to restore backup\n")); + DEBUG(0, ("winbindd cache tdb corrupt and no backup " + "could be restore.\n")); } /* Initialize cache again. */ -- cgit From d82702c21881120726065240af6db0fac3c4fef6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 11:27:54 +0100 Subject: Use the proper boolean constants. Michael (This used to be commit 6f673b7f10c145d88e6a6d3072b5f8cd98837304) --- source3/winbindd/winbindd_cache.c | 186 +++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 93 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 19becab1a6..fc71868517 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -62,7 +62,7 @@ static bool is_non_centry_key(TDB_DATA kbuf) int i; if (kbuf.dptr == NULL || kbuf.dsize == 0) { - return False; + return false; } for (i = 0; non_centry_keys[i] != NULL; i++) { size_t namelen = strlen(non_centry_keys[i]); @@ -70,10 +70,10 @@ static bool is_non_centry_key(TDB_DATA kbuf) continue; } if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) { - return True; + return true; } } - return False; + return false; } /* Global online/offline state - False when online. winbindd starts up online @@ -210,9 +210,9 @@ static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes) DEBUG(0,("centry corruption? needed %u bytes, have %d\n", (unsigned int)nbytes, centry->len - centry->ofs)); - return False; + return false; } - return True; + return true; } /* @@ -348,9 +348,9 @@ static bool centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID char *sid_string; sid_string = centry_string(centry, mem_ctx); if ((sid_string == NULL) || (!string_to_sid(sid, sid_string))) { - return False; + return false; } - return True; + return true; } @@ -372,7 +372,7 @@ static bool wcache_server_down(struct winbindd_domain *domain) bool ret; if (!wcache->tdb) - return False; + return false; ret = (domain->sequence_number == DOM_SEQUENCE_NONE); @@ -454,7 +454,7 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) } /* - refresh the domain sequence number. If force is True + refresh the domain sequence number. If force is true then always refresh it, no matter how recently we fetched it */ @@ -538,7 +538,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s if (lp_winbind_offline_logon() && global_winbindd_offline_state) { DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n", keystr, domain->name )); - return False; + return false; } /* when the domain is offline return the cached entry. @@ -547,7 +547,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s if (!domain->online) { DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n", keystr, domain->name )); - return False; + return false; } /* if the server is OK and our cache entry came from when it was down then @@ -556,7 +556,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s (centry->sequence_number == DOM_SEQUENCE_NONE)) { DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n", keystr, domain->name )); - return True; + return true; } /* if the server is down or the cache entry is not older than the @@ -565,14 +565,14 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s centry->sequence_number == domain->sequence_number) { DEBUG(10,("centry_expired: Key %s for domain %s is good.\n", keystr, domain->name )); - return False; + return false; } DEBUG(10,("centry_expired: Key %s for domain %s expired\n", keystr, domain->name )); /* it's expired */ - return True; + return true; } static struct cache_entry *wcache_fetch_raw(char *kstr) @@ -625,7 +625,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, return NULL; } - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); va_start(ap, format); smb_xvasprintf(&kstr, format, ap); @@ -1189,7 +1189,7 @@ do_query: (retry++ < 5)); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -1280,7 +1280,7 @@ do_query: status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -1364,7 +1364,7 @@ do_query: status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -1437,7 +1437,7 @@ do_query: domain_name, name, sid, type); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); if (domain->online && (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) { @@ -1510,7 +1510,7 @@ do_query: status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type); /* We can't save the name to sid mapping here, as with sid history a @@ -1554,7 +1554,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, goto error; } - have_mapped = have_unmapped = False; + have_mapped = have_unmapped = false; for (i=0; istatus)) { char *dom; - have_mapped = True; + have_mapped = true; (*types)[i] = (enum lsa_SidType)centry_uint32(centry); dom = centry_string(centry, mem_ctx); @@ -1590,7 +1590,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, (*names)[i] = centry_string(centry, *names); } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) { - have_unmapped = True; + have_unmapped = true; } else { /* something's definitely wrong */ @@ -1647,7 +1647,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, return result; } - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); for (i=0; ibackend->query_user(domain, mem_ctx, user_sid, info); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); wcache_save_user(domain, status, info); return status; @@ -1819,7 +1819,7 @@ do_query: goto skip_save; /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -1912,7 +1912,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, num_aliases, alias_rids); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -1993,7 +1993,7 @@ do_query: sid_mem, names, name_types); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) goto skip_save; @@ -2013,7 +2013,7 @@ skip_save: /* find the sequence number for a domain */ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); *seq = domain->sequence_number; @@ -2104,7 +2104,7 @@ do_query: the main parent and always to make the query. --jerry */ /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); centry = centry_start(domain, status); if (!centry) @@ -2170,7 +2170,7 @@ do_query: status = domain->backend->lockout_policy(domain, mem_ctx, policy); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); wcache_save_lockout_policy(domain, status, policy); return status; @@ -2221,7 +2221,7 @@ do_query: status = domain->backend->password_policy(domain, mem_ctx, policy); /* and save it */ - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); wcache_save_password_policy(domain, status, policy); return status; @@ -2289,7 +2289,7 @@ bool init_wcache(void) } if (wcache->tdb != NULL) - return True; + return true; /* when working offline we must not clear the cache on restart */ wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), @@ -2299,10 +2299,10 @@ bool init_wcache(void) if (wcache->tdb == NULL) { DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); - return False; + return false; } - return True; + return true; } /************************************************************************ @@ -2313,18 +2313,18 @@ bool init_wcache(void) bool initialize_winbindd_cache(void) { - bool cache_bad = True; + bool cache_bad = true; uint32 vers; if (!init_wcache()) { DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n")); - return False; + return false; } /* Check version number. */ if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) && vers == WINBINDD_CACHE_VERSION) { - cache_bad = False; + cache_bad = false; } if (cache_bad) { @@ -2339,25 +2339,25 @@ bool initialize_winbindd_cache(void) DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ", lock_path("winbindd_cache.tdb"), strerror(errno) )); - return False; + return false; } if (!init_wcache()) { DEBUG(0,("initialize_winbindd_cache: re-initialization " "init_wcache failed.\n")); - return False; + return false; } /* Write the version. */ if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) { DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n", tdb_errorstr(wcache->tdb) )); - return False; + return false; } } tdb_close(wcache->tdb); wcache->tdb = NULL; - return True; + return true; } void close_winbindd_cache() @@ -2417,7 +2417,7 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response) fstring key_str; if (!init_wcache()) - return False; + return false; DEBUG(10, ("Retrieving response for pid %d\n", pid)); @@ -2425,17 +2425,17 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response) data = tdb_fetch(wcache->tdb, string_tdb_data(key_str)); if (data.dptr == NULL) - return False; + return false; if (data.dsize != sizeof(*response)) - return False; + return false; memcpy(response, data.dptr, data.dsize); SAFE_FREE(data.dptr); if (response->length == sizeof(*response)) { response->extra_data.data = NULL; - return True; + return true; } /* There's extra data */ @@ -2448,19 +2448,19 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response) if (data.dptr == NULL) { DEBUG(0, ("Did not find extra data\n")); - return False; + return false; } if (data.dsize != (response->length - sizeof(*response))) { DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize)); SAFE_FREE(data.dptr); - return False; + return false; } dump_data(11, (uint8 *)data.dptr, data.dsize); response->extra_data.data = data.dptr; - return True; + return true; } void cache_cleanup_response(pid_t pid) @@ -2492,19 +2492,19 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, domain = find_lookup_domain_from_sid(sid); if (domain == NULL) { - return False; + return false; } cache = get_cache(domain); if (cache->tdb == NULL) { - return False; + return false; } centry = wcache_fetch(cache, domain, "SN/%s", sid_to_fstring(tmp, sid)); if (centry == NULL) { - return False; + return false; } if (NT_STATUS_IS_OK(centry->status)) { @@ -2533,13 +2533,13 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx, domain = find_lookup_domain_from_name(domain_name); if (domain == NULL) { - return False; + return false; } cache = get_cache(domain); if (cache->tdb == NULL) { - return False; + return false; } fstrcpy(uname, name); @@ -2549,12 +2549,12 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx, offline so the cache won't expire the entry */ original_online_state = domain->online; - domain->online = False; + domain->online = false; centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname); domain->online = original_online_state; if (centry == NULL) { - return False; + return false; } if (NT_STATUS_IS_OK(centry->status)) { @@ -2572,7 +2572,7 @@ void cache_name2sid(struct winbindd_domain *domain, const char *domain_name, const char *name, enum lsa_SidType type, const DOM_SID *sid) { - refresh_sequence_number(domain, False); + refresh_sequence_number(domain, false); wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name, sid, type); } @@ -2786,17 +2786,17 @@ bool set_global_winbindd_state_offline(void) if (wcache == NULL || wcache->tdb == NULL) { DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n")); - return False; + return false; } if (!lp_winbind_offline_logon()) { DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n")); - return False; + return false; } if (global_winbindd_offline_state) { /* Already offline. */ - return True; + return true; } data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" ); @@ -2804,12 +2804,12 @@ bool set_global_winbindd_state_offline(void) if (!data.dptr || data.dsize != 4) { DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n")); SAFE_FREE(data.dptr); - return False; + return false; } else { DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n")); - global_winbindd_offline_state = True; + global_winbindd_offline_state = true; SAFE_FREE(data.dptr); - return True; + return true; } } @@ -2826,7 +2826,7 @@ void set_global_winbindd_state_online(void) /* Already online. */ return; } - global_winbindd_offline_state = False; + global_winbindd_offline_state = false; if (!wcache->tdb) { return; @@ -2863,8 +2863,8 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat /* huh? corrupt cache? */ DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr)); centry_free(centry); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return NULL; } @@ -2879,7 +2879,7 @@ static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbu if (dbuf.dsize != 8) { DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n", keystr, (unsigned int)dbuf.dsize )); - state->bad_entry = True; + state->bad_entry = true; return 1; } return 0; @@ -3174,8 +3174,8 @@ static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, if (dbuf.dsize == 0) { DEBUG(0,("validate_dr: Corrupt cache for key %s (len == 0) ?\n", keystr)); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return 1; } @@ -3190,8 +3190,8 @@ static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, if (dbuf.dsize == 0) { DEBUG(0,("validate_de: Corrupt cache for key %s (len == 0) ?\n", keystr)); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return 1; } @@ -3234,8 +3234,8 @@ static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr, if (dbuf.dsize == 0) { DEBUG(0, ("validate_trustdomcache: Corrupt cache for " "key %s (len ==0) ?\n", keystr)); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return 1; } @@ -3250,8 +3250,8 @@ static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db if (dbuf.dsize != 4) { DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n", keystr, (unsigned int)dbuf.dsize )); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return 1; } DEBUG(10,("validate_offline: %s ok\n", keystr)); @@ -3265,8 +3265,8 @@ static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_D DEBUG(0, ("validate_cache_version: Corrupt cache for " "key %s (len %u != 4) ?\n", keystr, (unsigned int)dbuf.dsize)); - state->bad_entry = True; - state->success = False; + state->bad_entry = true; + state->success = false; return 1; } @@ -3355,8 +3355,8 @@ static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_D dump_data(0, (uint8 *)kbuf.dptr, kbuf.dsize); DEBUG(0,("data :\n")); dump_data(0, (uint8 *)dbuf.dptr, dbuf.dsize); - v_state->unknown_key = True; - v_state->success = False; + v_state->unknown_key = true; + v_state->success = false; return 1; /* terminate. */ } @@ -3450,7 +3450,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, struct winbindd_tdc_domain *list = NULL; size_t idx; int i; - bool set_only = False; + bool set_only = false; /* don't allow duplicates */ @@ -3462,7 +3462,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, DEBUG(10,("add_wbdomain_to_tdc_array: Found existing record for %s\n", new_dom->name)); idx = i; - set_only = True; + set_only = true; break; } @@ -3483,7 +3483,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, } if ( !list ) - return False; + return false; list[idx].domain_name = talloc_strdup( list, new_dom->name ); list[idx].dns_name = talloc_strdup( list, new_dom->alt_name ); @@ -3505,7 +3505,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, *num_domains = idx + 1; } - return True; + return true; } /********************************************************************* @@ -3661,7 +3661,7 @@ static bool wcache_tdc_store_list( struct winbindd_tdc_domain *domains, size_t n int ret; if ( !key.dptr ) - return False; + return false; /* See if we were asked to delete the cache entry */ @@ -3698,23 +3698,23 @@ bool wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_do *num_domains = 0; if ( !key.dptr ) - return False; + return false; data = tdb_fetch( wcache->tdb, key ); SAFE_FREE( key.dptr ); if ( !data.dptr ) - return False; + return false; *num_domains = unpack_tdc_domains( data.dptr, data.dsize, domains ); SAFE_FREE( data.dptr ); if ( !*domains ) - return False; + return false; - return True; + return true; } /********************************************************************* @@ -3724,7 +3724,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain ) { struct winbindd_tdc_domain *dom_list = NULL; size_t num_domains = 0; - bool ret = False; + bool ret = false; DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, " "flags = 0x%x, attributes = 0x%x, type = 0x%x\n", @@ -3735,7 +3735,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain ) domain->domain_type)); if ( !init_wcache() ) { - return False; + return false; } /* fetch the list */ @@ -3756,7 +3756,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain ) /* Success */ - ret = True; + ret = true; done: TALLOC_FREE( dom_list ); @@ -3776,7 +3776,7 @@ struct winbindd_tdc_domain * wcache_tdc_fetch_domain( TALLOC_CTX *ctx, const cha DEBUG(10,("wcache_tdc_fetch_domain: Searching for domain %s\n", name)); if ( !init_wcache() ) { - return False; + return false; } /* fetch the list */ @@ -3909,7 +3909,7 @@ do_query: /* the cache backend methods are exposed via this structure */ struct winbindd_methods cache_methods = { - True, + true, query_user_list, enum_dom_groups, enum_local_groups, -- cgit From cab9aa525dbbf4ba65acb43763298bfb30d4fca4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 7 Jan 2008 14:51:11 +0100 Subject: Fix build warning. Guenther (This used to be commit 73233a06d6f0f1346c48b465750af4b532cd7306) --- source3/winbindd/winbindd_cm.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 99e401d53f..a9155a5763 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -74,7 +74,7 @@ extern bool override_logfile; static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain); static void set_dc_type_and_flags( struct winbindd_domain *domain ); -static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, +static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs); /**************************************************************** @@ -560,7 +560,7 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) } } -static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, +static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, fstring dcname, struct sockaddr_storage *dc_ss) { @@ -600,12 +600,12 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, 35 seconds should do it. */ orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); - + if (our_domain->active_directory) { struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL; - - werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe, - mem_ctx, + + werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe, + mem_ctx, our_domain->dcname, domain->name, NULL, @@ -615,19 +615,21 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, if (W_ERROR_IS_OK(werr)) { fstrcpy(tmp, domain_info->domain_controller_name); if (strlen(domain->alt_name) == 0) { - fstrcpy(domain->alt_name, - CONST_DISCARD(char*, domain_info->domain_name)); + fstrcpy(domain->alt_name, + domain_info->domain_name); } if (strlen(domain->forest_name) == 0) { - fstrcpy(domain->forest_name, - CONST_DISCARD(char*, domain_info->dns_forest_name)); + fstrcpy(domain->forest_name, + domain_info->dns_forest_name); } - } + } } else { - - werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, + + werr = rpccli_netlogon_getanydcname(netlogon_pipe, + mem_ctx, our_domain->dcname, - domain->name, &tmp); + domain->name, + &tmp); } /* And restore our original timeout. */ @@ -1245,7 +1247,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain, the dcs[] with results. *******************************************************************/ -static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, +static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs) { fstring dcname; @@ -1348,7 +1350,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, } static bool find_new_dc(TALLOC_CTX *mem_ctx, - const struct winbindd_domain *domain, + struct winbindd_domain *domain, fstring dcname, struct sockaddr_storage *pss, int *fd) { struct dc_name_ip *dcs = NULL; -- cgit From de53e47c76cc6dfdc8056be1e376549b9e8a94a4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 23:02:50 +0100 Subject: Fix prototype: Add a void to an empty function parameter list. Michael (This used to be commit 3f89aea8e4df3a2de8c5e4c6f4e417567adb2d67) --- source3/winbindd/winbindd_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index fc71868517..c293861492 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2360,7 +2360,7 @@ bool initialize_winbindd_cache(void) return true; } -void close_winbindd_cache() +void close_winbindd_cache(void) { if (!wcache) { return; -- cgit From f3603d5a5ab878d45b67bf0f33e2beca50d0af2d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 9 Jan 2008 00:11:31 +0100 Subject: Convert add_sid_to_array() add_sid_to_array_unique() to return NTSTATUS. Michael (This used to be commit 6b2b9a60ef857ec31da5fea631535205fbdede4a) --- source3/winbindd/winbindd_ads.c | 39 +++++++++++++++++++++------------------ source3/winbindd/winbindd_async.c | 20 ++++++++++++++------ source3/winbindd/winbindd_group.c | 15 ++++++--------- source3/winbindd/winbindd_pam.c | 9 +++++---- source3/winbindd/winbindd_util.c | 21 ++++++++++++--------- 5 files changed, 58 insertions(+), 46 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 3aba824b0b..f963669825 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -596,8 +596,9 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, num_groups = 0; /* always add the primary group to the sid array */ - if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) { - status = NT_STATUS_NO_MEMORY; + status = add_sid_to_array(mem_ctx, primary_group, user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -615,10 +616,10 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, if (sid_check_is_in_builtin(&group_sid)) { continue; } - - if (!add_sid_to_array(mem_ctx, &group_sid, user_sids, - &num_groups)) { - status = NT_STATUS_NO_MEMORY; + + status = add_sid_to_array(mem_ctx, &group_sid, + user_sids, &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } } @@ -684,8 +685,9 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, num_groups = 0; /* always add the primary group to the sid array */ - if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) { - status = NT_STATUS_NO_MEMORY; + status = add_sid_to_array(mem_ctx, primary_group, user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -720,10 +722,10 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, if (sid_check_is_in_builtin(&group_sids[i])) { continue; } - - if (!add_sid_to_array(mem_ctx, &group_sids[i], user_sids, - &num_groups)) { - status = NT_STATUS_NO_MEMORY; + + status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -861,8 +863,9 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, *user_sids = NULL; num_groups = 0; - if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) { - status = NT_STATUS_NO_MEMORY; + status = add_sid_to_array(mem_ctx, &primary_group, user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -872,10 +875,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (sid_check_is_in_builtin(&sids[i])) { continue; } - - if (!add_sid_to_array_unique(mem_ctx, &sids[i], - user_sids, &num_groups)) { - status = NT_STATUS_NO_MEMORY; + + status = add_sid_to_array_unique(mem_ctx, &sids[i], + user_sids, &num_groups); + if (!NT_STATUS_IS_OK(status)) { goto done; } } diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 76724582a1..ab32ee0c76 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -492,7 +492,9 @@ static bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, DEBUG(0, ("Could not parse sid %s\n", p)); return False; } - if (!add_sid_to_array(mem_ctx, &sid, sids, num_sids)) { + if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids, + num_sids))) + { return False; } p = q; @@ -714,7 +716,9 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, DEBUGADD(10, (" rid %d\n", alias_rids[i])); sid_copy(&sid, &domain->sid); sid_append_rid(&sid, alias_rids[i]); - if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) { + result = add_sid_to_array(state->mem_ctx, &sid, &sids, + &num_sids); + if (!NT_STATUS_IS_OK(result)) { return WINBINDD_ERROR; } } @@ -832,8 +836,9 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success, state->sids = NULL; state->num_sids = 0; - if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids, - &state->num_sids)) { + if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &state->user_sid, + &state->sids, &state->num_sids))) + { DEBUG(0, ("Out of memory\n")); state->cont(state->private_data, False, NULL, 0); return; @@ -874,8 +879,11 @@ static void gettoken_recvaliases(void *private_data, bool success, } for (i=0; imem_ctx, &aliases[i], - &state->sids, &state->num_sids)) { + if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx, + &aliases[i], + &state->sids, + &state->num_sids))) + { DEBUG(0, ("Out of memory\n")); state->cont(state->private_data, False, NULL, 0); return; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 62e8d1c40b..6a704cf290 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -438,18 +438,15 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, if ( name_types[j] == SID_NAME_DOM_GRP || name_types[j] == SID_NAME_ALIAS ) { - bool ret; - - ret = add_sid_to_array_unique( ctx, - &sid_mem[j], - &new_groups, - &new_groups_size ); - if ( !ret ) { - status = NT_STATUS_NO_MEMORY; + status = add_sid_to_array_unique(ctx, + &sid_mem[j], + &new_groups, + &new_groups_size); + if (NT_STATUS_IS_OK(status)) { goto out; } - continue; + continue; } } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 7a9014a82f..525096b0a2 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -273,12 +273,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_PARAMETER; } - if (!add_sid_to_array(mem_ctx, &sid, - &require_membership_of_sid, - &num_require_membership_of_sid)) { + status = add_sid_to_array(mem_ctx, &sid, + &require_membership_of_sid, + &num_require_membership_of_sid); + if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("add_sid_to_array failed\n")); TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; + return status; } } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index cc12d4b7ea..dc48fdef8b 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1304,19 +1304,22 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, /* always add the primary group to the sid array */ sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid); - if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) { + status = add_sid_to_array(mem_ctx, &primary_group, user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); - return NT_STATUS_NO_MEMORY; + return status; } for (i=0; inum_groups; i++) { sid_copy(&group_sid, &info3->dom_sid.sid); sid_append_rid(&group_sid, info3->gids[i].g_rid); - if (!add_sid_to_array(mem_ctx, &group_sid, user_sids, - &num_groups)) { + status = add_sid_to_array(mem_ctx, &group_sid, user_sids, + &num_groups); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); - return NT_STATUS_NO_MEMORY; + return status; } } @@ -1328,11 +1331,11 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE) continue; - if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid, - user_sids, &num_groups)) - { + status = add_sid_to_array(mem_ctx, &info3->other_sids[i].sid, + user_sids, &num_groups); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); - return NT_STATUS_NO_MEMORY; + return status; } } -- cgit From c79ce2ffa3f7d00ce6a2cd6008c203e3042b0b02 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 11 Jan 2008 15:32:20 +0100 Subject: As long as DsGetDcName is not part of libnetapi, lowercase the fn name. Guenther (This used to be commit 19a980f52044a170618629e5b0484c1f6b586e5f) --- source3/winbindd/winbindd_locator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index ee497ebf32..05bd74af25 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -48,7 +48,7 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state) state->request.domain_name [sizeof(state->request.domain_name)-1] = '\0'; - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid, state->request.domain_name)); sendto_child(state, locator_child()); @@ -64,10 +64,10 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, state->request.domain_name [sizeof(state->request.domain_name)-1] = '\0'; - DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid, + DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid, state->request.domain_name)); - result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name, + result = dsgetdcname(state->mem_ctx, NULL, state->request.domain_name, NULL, NULL, state->request.flags, &info); if (!NT_STATUS_IS_OK(result)) { -- cgit From 6fa81523f86c5e136bf3ab2c5b0c9032570d3b96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2008 22:44:33 -0800 Subject: Ensure we don't access an uninitialized variable (CID 535 - actually false but easy to shut up :-). Jeremy. (This used to be commit 4038bb3a9485943db58d9fe30947e11522ce283d) --- source3/winbindd/winbindd_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index f5e1226447..34ba0498e0 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -308,7 +308,7 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, { char **domains; char **names; - enum lsa_SidType *types; + enum lsa_SidType *types = NULL; NTSTATUS result; struct rpc_pipe_client *cli; POLICY_HND lsa_policy; -- cgit From c920764b1960f86482a24d4b4462664b07d4f1a9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 15 Jan 2008 16:40:02 +0100 Subject: Apply const to rpccli_lsa_query_info_policy() and rpccli_lsa_query_info_policy2(). Guenther (This used to be commit 7a3fe68bef7acde9d9f8a7a44ce7e9432f3c5a95) --- source3/winbindd/winbindd_cm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a9155a5763..908228717e 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1799,9 +1799,9 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) struct rpc_pipe_client *cli; POLICY_HND pol; - char *domain_name = NULL; - char *dns_name = NULL; - char *forest_name = NULL; + const char *domain_name = NULL; + const char *dns_name = NULL; + const char *forest_name = NULL; DOM_SID *dom_sid = NULL; ZERO_STRUCT( ctr ); -- cgit From 3bd3483fab4b55c36c276ccaf607a5ed3f1c6f29 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:27:29 +0300 Subject: idmap TDB2 backend, used for clustered Samba setups. This uses 2 tdb files. One is permanent, and is in shared storage on the cluster (using "tdb:idmap2.tdb =" in smb.conf). The other is a temporary cache tdb on local storage. Signed-off-by: Alexander Bokovoy (This used to be commit b6df7e7709365fb620867ad8954bc5bf24496775) --- source3/winbindd/idmap_tdb2.c | 1014 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1014 insertions(+) create mode 100644 source3/winbindd/idmap_tdb2.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c new file mode 100644 index 0000000000..fa106aa134 --- /dev/null +++ b/source3/winbindd/idmap_tdb2.c @@ -0,0 +1,1014 @@ +/* + Unix SMB/CIFS implementation. + + idmap TDB2 backend, used for clustered Samba setups. + + This uses 2 tdb files. One is permanent, and is in shared storage + on the cluster (using "tdb:idmap2.tdb =" in smb.conf). The other is a + temporary cache tdb on local storage. + + Copyright (C) Andrew Tridgell 2007 + + This is heavily based upon idmap_tdb.c, which is: + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Jeremy Allison 2006 + Copyright (C) Simo Sorce 2003-2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/* High water mark keys */ +#define HWM_GROUP "GROUP HWM" +#define HWM_USER "USER HWM" + +static struct idmap_tdb2_state { + /* User and group id pool */ + uid_t low_uid, high_uid; /* Range of uids to allocate */ + gid_t low_gid, high_gid; /* Range of gids to allocate */ + const char *idmap_script; +} idmap_tdb2_state; + + + +/* tdb context for the local cache tdb */ +static TDB_CONTEXT *idmap_tdb2_tmp; + +/* handle to the permanent tdb */ +static struct db_context *idmap_tdb2_perm; + +/* + open the cache tdb + */ +static NTSTATUS idmap_tdb2_open_cache_db(void) +{ + const char *db_path; + + if (idmap_tdb2_tmp) { + /* its already open */ + return NT_STATUS_OK; + } + + db_path = lock_path("idmap2_cache.tdb"); + + /* Open idmap repository */ + if (!(idmap_tdb2_tmp = tdb_open_log(db_path, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644))) { + DEBUG(0, ("Unable to open cache idmap database '%s'\n", db_path)); + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + + +static NTSTATUS idmap_tdb2_alloc_load(void); + +/* + open the permanent tdb + */ +static NTSTATUS idmap_tdb2_open_perm_db(void) +{ + char *db_path; + + if (idmap_tdb2_perm) { + /* its already open */ + return NT_STATUS_OK; + } + + db_path = lp_parm_talloc_string(-1, "tdb", "idmap2.tdb", NULL); + if (db_path == NULL) { + /* fall back to the private directory, which, despite + its name, is usually on shared storage */ + db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir()); + } + NT_STATUS_HAVE_NO_MEMORY(db_path); + + /* Open idmap repository */ + idmap_tdb2_perm = db_open(NULL, db_path, 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0644); + TALLOC_FREE(db_path); + + if (idmap_tdb2_perm == NULL) { + DEBUG(0, ("Unable to open permanent idmap database '%s'\n", + db_path)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* load the ranges and high/low water marks */ + return idmap_tdb2_alloc_load(); +} + + +/* + load the idmap allocation ranges and high/low water marks +*/ +static NTSTATUS idmap_tdb2_alloc_load(void) +{ + const char *range; + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + + /* load ranges */ + idmap_tdb2_state.low_uid = 0; + idmap_tdb2_state.high_uid = 0; + idmap_tdb2_state.low_gid = 0; + idmap_tdb2_state.high_gid = 0; + + /* see if a idmap script is configured */ + idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL); + + if (idmap_tdb2_state.idmap_script) { + DEBUG(1, ("using idmap script '%s'\n", idmap_tdb2_state.idmap_script)); + } + + range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); + if (range && range[0]) { + unsigned low_id, high_id; + if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { + if (low_id < high_id) { + idmap_tdb2_state.low_gid = idmap_tdb2_state.low_uid = low_id; + idmap_tdb2_state.high_gid = idmap_tdb2_state.high_uid = high_id; + } else { + DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range)); + } + } else { + DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range)); + } + } + + /* Create high water marks for group and user id */ + if (lp_idmap_uid(&low_uid, &high_uid)) { + idmap_tdb2_state.low_uid = low_uid; + idmap_tdb2_state.high_uid = high_uid; + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + idmap_tdb2_state.low_gid = low_gid; + idmap_tdb2_state.high_gid = high_gid; + } + + if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) { + DEBUG(1, ("idmap uid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + return NT_STATUS_UNSUCCESSFUL; + } else { + uint32 low_id; + + if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + HWM_USER)) == -1) || + (low_id < idmap_tdb2_state.low_uid)) { + if (dbwrap_store_int32( + idmap_tdb2_perm, HWM_USER, + idmap_tdb2_state.low_uid) == -1) { + DEBUG(0, ("Unable to initialise user hwm in idmap database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + } + } + + if (idmap_tdb2_state.high_gid <= idmap_tdb2_state.low_gid) { + DEBUG(1, ("idmap gid range missing or invalid\n")); + DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); + return NT_STATUS_UNSUCCESSFUL; + } else { + uint32 low_id; + + if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + HWM_GROUP)) == -1) || + (low_id < idmap_tdb2_state.low_gid)) { + if (dbwrap_store_int32( + idmap_tdb2_perm, HWM_GROUP, + idmap_tdb2_state.low_gid) == -1) { + DEBUG(0, ("Unable to initialise group hwm in idmap database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + } + } + + return NT_STATUS_OK; +} + + +/* + Initialise idmap alloc database. +*/ +static NTSTATUS idmap_tdb2_alloc_init(const char *params) +{ + /* nothing to do - we want to avoid opening the permanent + database if possible. Instead we load the params when we + first need it. */ + return NT_STATUS_OK; +} + + +/* + Allocate a new id. +*/ +static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) +{ + bool ret; + const char *hwmkey; + const char *hwmtype; + uint32_t high_hwm; + uint32_t hwm; + NTSTATUS status; + + status = idmap_tdb2_open_perm_db(); + NT_STATUS_NOT_OK_RETURN(status); + + /* Get current high water mark */ + switch (xid->type) { + + case ID_TYPE_UID: + hwmkey = HWM_USER; + hwmtype = "UID"; + high_hwm = idmap_tdb2_state.high_uid; + break; + + case ID_TYPE_GID: + hwmkey = HWM_GROUP; + hwmtype = "GID"; + high_hwm = idmap_tdb2_state.high_gid; + break; + + default: + DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); + return NT_STATUS_INVALID_PARAMETER; + } + + if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + /* check it is in the range */ + if (hwm > high_hwm) { + DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* fetch a new id and increment it */ + ret = dbwrap_change_uint32_atomic(idmap_tdb2_perm, hwmkey, &hwm, 1); + if (ret == -1) { + DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > high_hwm) { + DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + return NT_STATUS_UNSUCCESSFUL; + } + + xid->id = hwm; + DEBUG(10,("New %s = %d\n", hwmtype, hwm)); + + return NT_STATUS_OK; +} + +/* + Get current highest id. +*/ +static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid) +{ + const char *hwmkey; + const char *hwmtype; + uint32_t hwm; + uint32_t high_hwm; + + /* Get current high water mark */ + switch (xid->type) { + + case ID_TYPE_UID: + hwmkey = HWM_USER; + hwmtype = "UID"; + high_hwm = idmap_tdb2_state.high_uid; + break; + + case ID_TYPE_GID: + hwmkey = HWM_GROUP; + hwmtype = "GID"; + high_hwm = idmap_tdb2_state.high_gid; + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + xid->id = hwm; + + /* Warn if it is out of range */ + if (hwm >= high_hwm) { + DEBUG(0, ("Warning: %s range full!! (max: %lu)\n", + hwmtype, (unsigned long)high_hwm)); + } + + return NT_STATUS_OK; +} + +/* + Set high id. +*/ +static NTSTATUS idmap_tdb2_set_hwm(struct unixid *xid) +{ + /* not supported, or we would invalidate the cache tdb on + other nodes */ + DEBUG(0,("idmap_tdb2_set_hwm not supported\n")); + return NT_STATUS_NOT_SUPPORTED; +} + +/* + Close the alloc tdb +*/ +static NTSTATUS idmap_tdb2_alloc_close(void) +{ + /* don't actually close it */ + return NT_STATUS_OK; +} + +/* + IDMAP MAPPING TDB BACKEND +*/ +struct idmap_tdb2_context { + uint32_t filter_low_id; + uint32_t filter_high_id; +}; + +/* + try fetching from the cache tdb, and if that fails then + fetch from the permanent tdb + */ +static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr) +{ + TDB_DATA ret; + NTSTATUS status; + + ret = tdb_fetch_bystring(idmap_tdb2_tmp, keystr); + if (ret.dptr != NULL) { + /* got it from cache */ + unsigned char *tmp; + + tmp = (unsigned char *)talloc_memdup(mem_ctx, ret.dptr, + ret.dsize); + SAFE_FREE(ret.dptr); + ret.dptr = tmp; + + if (ret.dptr == NULL) { + return make_tdb_data(NULL, 0); + } + return ret; + } + + status = idmap_tdb2_open_perm_db(); + if (!NT_STATUS_IS_OK(status)) { + return ret; + } + + /* fetch from the permanent tdb */ + return dbwrap_fetch_bystring(idmap_tdb2_perm, mem_ctx, keystr); +} + +/* + store into both databases + */ +static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags) +{ + NTSTATUS ret; + NTSTATUS status = idmap_tdb2_open_perm_db(); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_UNSUCCESSFUL; + } + ret = dbwrap_store_bystring(idmap_tdb2_perm, keystr, data, flags); + if (!NT_STATUS_IS_OK(ret)) { + ret = tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + } + return ret; +} + +/* + delete from both databases + */ +static NTSTATUS tdb2_delete_bystring(const char *keystr) +{ + NTSTATUS ret; + NTSTATUS status = idmap_tdb2_open_perm_db(); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_UNSUCCESSFUL; + } + ret = dbwrap_delete_bystring(idmap_tdb2_perm, keystr); + if (!NT_STATUS_IS_OK(ret)) { + ret = tdb_delete_bystring(idmap_tdb2_tmp, keystr) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + } + return ret; +} + +/* + Initialise idmap database. +*/ +static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom) +{ + NTSTATUS ret; + struct idmap_tdb2_context *ctx; + char *config_option = NULL; + const char *range; + NTSTATUS status; + + status = idmap_tdb2_open_cache_db(); + NT_STATUS_NOT_OK_RETURN(status); + + ctx = talloc(dom, struct idmap_tdb2_context); + if ( ! ctx) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto failed; + } + + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (( ! range) || + (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) || + (ctx->filter_low_id > ctx->filter_high_id)) { + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + + dom->private_data = ctx; + dom->initialized = True; + + talloc_free(config_option); + return NT_STATUS_OK; + +failed: + talloc_free(ctx); + return ret; +} + + +/* + run a script to perform a mapping + + The script should the following command lines: + + SIDTOID S-1-xxxx + IDTOSID UID xxxx + IDTOSID GID xxxx + + and should return one of the following as a single line of text + UID:xxxx + GID:xxxx + SID:xxxx + ERR:xxxx + */ +static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx, struct id_map *map, + const char *fmt, ...) +{ + va_list ap; + char *cmd; + FILE *p; + char line[64]; + unsigned long v; + + cmd = talloc_asprintf(ctx, "%s ", idmap_tdb2_state.idmap_script); + NT_STATUS_HAVE_NO_MEMORY(cmd); + + va_start(ap, fmt); + cmd = talloc_vasprintf_append(cmd, fmt, ap); + va_end(ap); + NT_STATUS_HAVE_NO_MEMORY(cmd); + + p = popen(cmd, "r"); + talloc_free(cmd); + if (p == NULL) { + return NT_STATUS_NONE_MAPPED; + } + + if (fgets(line, sizeof(line)-1, p) == NULL) { + pclose(p); + return NT_STATUS_NONE_MAPPED; + } + pclose(p); + + DEBUG(10,("idmap script gave: %s\n", line)); + + if (sscanf(line, "UID:%lu", &v) == 1) { + map->xid.id = v; + map->xid.type = ID_TYPE_UID; + } else if (sscanf(line, "GID:%lu", &v) == 1) { + map->xid.id = v; + map->xid.type = ID_TYPE_GID; + } else if (strncmp(line, "SID:S-", 6) == 0) { + if (!string_to_sid(map->sid, &line[4])) { + DEBUG(0,("Bad SID in '%s' from idmap script %s\n", + line, idmap_tdb2_state.idmap_script)); + return NT_STATUS_NONE_MAPPED; + } + } else { + DEBUG(0,("Bad reply '%s' from idmap script %s\n", + line, idmap_tdb2_state.idmap_script)); + return NT_STATUS_NONE_MAPPED; + } + + return NT_STATUS_OK; +} + + + +/* + Single id to sid lookup function. +*/ +static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_map *map) +{ + NTSTATUS ret; + TDB_DATA data; + char *keystr; + + if (!ctx || !map) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* apply filters before checking */ + if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || + (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->filter_low_id, ctx->filter_high_id)); + return NT_STATUS_NONE_MAPPED; + } + + switch (map->xid.type) { + + case ID_TYPE_UID: + keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); + break; + + case ID_TYPE_GID: + keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); + break; + + default: + DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); + return NT_STATUS_INVALID_PARAMETER; + } + + /* final SAFE_FREE safe */ + data.dptr = NULL; + + if (keystr == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10,("Fetching record %s\n", keystr)); + + /* Check if the mapping exists */ + data = tdb2_fetch_bystring(keystr, keystr); + + if (!data.dptr) { + fstring sidstr; + + DEBUG(10,("Record %s not found\n", keystr)); + if (idmap_tdb2_state.idmap_script == NULL) { + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr); + + /* store it on shared storage */ + if (!NT_STATUS_IS_OK(ret)) { + goto done; + } + + if (sid_to_string(sidstr, map->sid)) { + /* both forward and reverse mappings */ + tdb2_store_bystring(keystr, + string_term_tdb_data(sidstr), + TDB_REPLACE); + tdb2_store_bystring(sidstr, + string_term_tdb_data(keystr), + TDB_REPLACE); + } + goto done; + } + + if (!string_to_sid(map->sid, (const char *)data.dptr)) { + DEBUG(10,("INVALID SID (%s) in record %s\n", + (const char *)data.dptr, keystr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } + + DEBUG(10,("Found record %s -> %s\n", keystr, (const char *)data.dptr)); + ret = NT_STATUS_OK; + +done: + talloc_free(keystr); + return ret; +} + + +/* + Single sid to id lookup function. +*/ +static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_map *map) +{ + NTSTATUS ret; + TDB_DATA data; + char *keystr; + unsigned long rec_id = 0; + + if ((keystr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10,("Fetching record %s\n", keystr)); + + /* Check if sid is present in database */ + data = tdb2_fetch_bystring(keystr, keystr); + if (!data.dptr) { + fstring idstr; + + DEBUG(10,(__location__ " Record %s not found\n", keystr)); + + if (idmap_tdb2_state.idmap_script == NULL) { + ret = NT_STATUS_NONE_MAPPED; + goto done; + } + + ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr); + /* store it on shared storage */ + if (!NT_STATUS_IS_OK(ret)) { + goto done; + } + + snprintf(idstr, sizeof(idstr), "%cID %lu", + map->xid.type == ID_TYPE_UID?'U':'G', + (unsigned long)map->xid.id); + /* store both forward and reverse mappings */ + tdb2_store_bystring(keystr, string_term_tdb_data(idstr), + TDB_REPLACE); + tdb2_store_bystring(idstr, string_term_tdb_data(keystr), + TDB_REPLACE); + goto done; + } + + /* What type of record is this ? */ + if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */ + map->xid.id = rec_id; + map->xid.type = ID_TYPE_UID; + DEBUG(10,("Found uid record %s -> %s \n", keystr, (const char *)data.dptr )); + ret = NT_STATUS_OK; + + } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */ + map->xid.id = rec_id; + map->xid.type = ID_TYPE_GID; + DEBUG(10,("Found gid record %s -> %s \n", keystr, (const char *)data.dptr )); + ret = NT_STATUS_OK; + + } else { /* Unknown record type ! */ + DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + } + + /* apply filters before returning result */ + if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || + (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { + DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n", + map->xid.id, ctx->filter_low_id, ctx->filter_high_id)); + ret = NT_STATUS_NONE_MAPPED; + } + +done: + talloc_free(keystr); + return ret; +} + +/* + lookup a set of unix ids. +*/ +static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_tdb2_context *ctx; + NTSTATUS ret; + int i; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb2_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); + + for (i = 0; ids[i]; i++) { + ret = idmap_tdb2_id_to_sid(ctx, ids[i]); + if ( ! NT_STATUS_IS_OK(ret)) { + + /* if it is just a failed mapping continue */ + if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { + + /* make sure it is marked as unmapped */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + /* some fatal error occurred, return immediately */ + goto done; + } + + /* all ok, id is mapped */ + ids[i]->status = ID_MAPPED; + } + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/* + lookup a set of sids. +*/ +static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + struct idmap_tdb2_context *ctx; + NTSTATUS ret; + int i; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb2_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); + + for (i = 0; ids[i]; i++) { + ret = idmap_tdb2_sid_to_id(ctx, ids[i]); + if ( ! NT_STATUS_IS_OK(ret)) { + + /* if it is just a failed mapping continue */ + if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { + + /* make sure it is marked as unmapped */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + /* some fatal error occurred, return immediately */ + goto done; + } + + /* all ok, id is mapped */ + ids[i]->status = ID_MAPPED; + } + + ret = NT_STATUS_OK; + +done: + return ret; +} + + +/* + set a mapping. +*/ +static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map) +{ + struct idmap_tdb2_context *ctx; + NTSTATUS ret; + TDB_DATA data; + char *ksidstr, *kidstr; + struct db_record *update_lock = NULL; + struct db_record *rec = NULL; + + /* make sure we initialized */ + if ( ! dom->initialized) { + ret = idmap_tdb2_db_init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return ret; + } + } + + if (!map || !map->sid) { + return NT_STATUS_INVALID_PARAMETER; + } + + ksidstr = kidstr = NULL; + data.dptr = NULL; + + /* TODO: should we filter a set_mapping using low/high filters ? */ + + ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); + + switch (map->xid.type) { + + case ID_TYPE_UID: + kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); + break; + + case ID_TYPE_GID: + kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); + break; + + default: + DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (kidstr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + if (!(ksidstr = talloc_strdup(ctx, sid_string_static(map->sid)))) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr)); + + /* + * Get us the update lock. This is necessary to get the lock orders + * right, we need to deal with two records under a lock. + */ + + if (!(update_lock = idmap_tdb2_perm->fetch_locked( + idmap_tdb2_perm, ctx, + string_term_tdb_data("UPDATELOCK")))) { + DEBUG(10,("Failed to lock record %s\n", ksidstr)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* + * *DELETE* previous mappings if any. * + */ + + /* First delete indexed on SID */ + + if (((rec = idmap_tdb2_perm->fetch_locked( + idmap_tdb2_perm, update_lock, + string_term_tdb_data(ksidstr))) != NULL) + && (rec->value.dsize != 0)) { + struct db_record *rec2; + + if ((rec2 = idmap_tdb2_perm->fetch_locked( + idmap_tdb2_perm, update_lock, rec->value)) + != NULL) { + rec2->delete_rec(rec2); + TALLOC_FREE(rec2); + } + + rec->delete_rec(rec); + + tdb_delete(idmap_tdb2_tmp, rec->key); + tdb_delete(idmap_tdb2_tmp, rec->value); + } + TALLOC_FREE(rec); + + /* Now delete indexed on unix ID */ + + if (((rec = idmap_tdb2_perm->fetch_locked( + idmap_tdb2_perm, update_lock, + string_term_tdb_data(kidstr))) != NULL) + && (rec->value.dsize != 0)) { + struct db_record *rec2; + + if ((rec2 = idmap_tdb2_perm->fetch_locked( + idmap_tdb2_perm, update_lock, rec->value)) + != NULL) { + rec2->delete_rec(rec2); + TALLOC_FREE(rec2); + } + + rec->delete_rec(rec); + + tdb_delete(idmap_tdb2_tmp, rec->key); + tdb_delete(idmap_tdb2_tmp, rec->value); + } + TALLOC_FREE(rec); + + if (!NT_STATUS_IS_OK(tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr), + TDB_INSERT))) { + DEBUG(0, ("Error storing SID -> ID\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + if (!NT_STATUS_IS_OK(tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr), + TDB_INSERT))) { + DEBUG(0, ("Error storing ID -> SID\n")); + /* try to remove the previous stored SID -> ID map */ + tdb2_delete_bystring(ksidstr); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr)); + ret = NT_STATUS_OK; + +done: + talloc_free(ksidstr); + talloc_free(kidstr); + SAFE_FREE(data.dptr); + TALLOC_FREE(update_lock); + return ret; +} + +/* + remove a mapping. +*/ +static NTSTATUS idmap_tdb2_remove_mapping(struct idmap_domain *dom, const struct id_map *map) +{ + /* not supported as it would invalidate the cache tdb on other + nodes */ + DEBUG(0,("idmap_tdb2_remove_mapping not supported\n")); + return NT_STATUS_NOT_SUPPORTED; +} + +/* + Close the idmap tdb instance +*/ +static NTSTATUS idmap_tdb2_close(struct idmap_domain *dom) +{ + /* don't do anything */ + return NT_STATUS_OK; +} + + +/* + Dump all mappings out +*/ +static NTSTATUS idmap_tdb2_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps) +{ + DEBUG(0,("idmap_tdb2_dump_data not supported\n")); + return NT_STATUS_NOT_SUPPORTED; +} + +static struct idmap_methods db_methods = { + .init = idmap_tdb2_db_init, + .unixids_to_sids = idmap_tdb2_unixids_to_sids, + .sids_to_unixids = idmap_tdb2_sids_to_unixids, + .set_mapping = idmap_tdb2_set_mapping, + .remove_mapping = idmap_tdb2_remove_mapping, + .dump_data = idmap_tdb2_dump_data, + .close_fn = idmap_tdb2_close +}; + +static struct idmap_alloc_methods db_alloc_methods = { + .init = idmap_tdb2_alloc_init, + .allocate_id = idmap_tdb2_allocate_id, + .get_id_hwm = idmap_tdb2_get_hwm, + .set_id_hwm = idmap_tdb2_set_hwm, + .close_fn = idmap_tdb2_alloc_close +}; + +NTSTATUS idmap_tdb2_init(void) +{ + NTSTATUS ret; + + /* register both backends */ + ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods); + NT_STATUS_NOT_OK_RETURN(ret); + + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods); +} -- cgit From 024741500abd30ac74adfdfa88694026792ba284 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 16:50:46 +0300 Subject: Convert old sid-string handling in idmap_tdb2 to a new one (This used to be commit ee851730cef1eb506b47faf57e25789ad3c6aafa) --- source3/winbindd/idmap_tdb2.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index fa106aa134..ab89e615f7 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -610,7 +610,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m goto done; } - if (sid_to_string(sidstr, map->sid)) { + if (sid_to_fstring(sidstr, map->sid)) { /* both forward and reverse mappings */ tdb2_store_bystring(keystr, string_term_tdb_data(sidstr), @@ -648,7 +648,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m char *keystr; unsigned long rec_id = 0; - if ((keystr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) { + if ((keystr = sid_string_talloc(ctx, map->sid)) == NULL) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -859,7 +859,7 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id goto done; } - if (!(ksidstr = talloc_strdup(ctx, sid_string_static(map->sid)))) { + if (!(ksidstr = sid_string_talloc(ctx, map->sid))) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; @@ -1008,7 +1008,10 @@ NTSTATUS idmap_tdb2_init(void) /* register both backends */ ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods); - NT_STATUS_NOT_OK_RETURN(ret); + if (! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("Unable to register idmap alloc tdb2 module: %s\n", get_friendly_nt_error_msg(ret))); + return ret; + } return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods); } -- cgit From a92eb76688600efbf4a4056c2543f348e2fee8aa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 17 Jan 2008 10:24:34 +0100 Subject: Finally enable pidl generated SAMR & NETLOGON headers and clients. Guenther (This used to be commit f7100156a7df7ac3ae84e45a47153b38d9375215) --- source3/winbindd/winbindd_creds.c | 2 +- source3/winbindd/winbindd_pam.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c index 62facb6769..4dbace5bcc 100644 --- a/source3/winbindd/winbindd_creds.c +++ b/source3/winbindd/winbindd_creds.c @@ -69,7 +69,7 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, sid_copy(&sid, &(info3->dom_sid.sid)); sid_append_rid(&sid, info3->user_rid); sid_copy(&cred_sid, &sid); - info3->user_flgs |= LOGON_CACHED_ACCOUNT; + info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; } else if (user_sid != NULL) { diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 525096b0a2..0c75cb17a9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -923,7 +923,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - my_info3->user_flgs |= LOGON_CACHED_ACCOUNT; + my_info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; if (my_info3->acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; @@ -959,7 +959,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); if (must_change_time != 0 && must_change_time < time(NULL)) { /* we allow grace logons when the password has expired */ - my_info3->user_flgs |= LOGON_GRACE_LOGON; + my_info3->user_flgs |= NETLOGON_GRACE_LOGON; /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } @@ -1075,7 +1075,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, } if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || - (password_properties & DOMAIN_LOCKOUT_ADMINS)) { + (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) { my_info3->acct_flags |= ACB_AUTOLOCK; } } -- cgit From 611609ee2584cc0703c0524ae712ee385ae006f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 09:03:32 +0100 Subject: Fix a segfault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointed out by Steven Danneman on irc, thanks! Jerry, Günther, please check! (This used to be commit 9e71c89ac648040739ef2161a2e6c4299be1e35b) --- source3/winbindd/winbindd_cm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 908228717e..ef159f0670 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -613,7 +613,13 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, DS_RETURN_DNS_NAME, &domain_info); if (W_ERROR_IS_OK(werr)) { - fstrcpy(tmp, domain_info->domain_controller_name); + tmp = talloc_strdup( + mem_ctx, domain_info->domain_controller_name); + if (tmp == NULL) { + DEBUG(0, ("talloc_strdup failed\n")); + talloc_destroy(mem_ctx); + return false; + } if (strlen(domain->alt_name) == 0) { fstrcpy(domain->alt_name, domain_info->domain_name); @@ -635,11 +641,10 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); - talloc_destroy(mem_ctx); - if (!W_ERROR_IS_OK(werr)) { DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n", dos_errstr(werr))); + talloc_destroy(mem_ctx); return False; } @@ -654,6 +659,8 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, fstrcpy(dcname, p); + talloc_destroy(mem_ctx); + DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname)); if (!resolve_name(dcname, dc_ss, 0x20)) { -- cgit From 2b9ed4700ad42e627919dc372adcb5b5188e9fa0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Jan 2008 08:39:47 +0100 Subject: winbindd: remove useless strcpy metze (This used to be commit df08708fc1e8fc8e15b36db29faf35ae5ae64b65) --- source3/winbindd/winbindd_pam.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 0c75cb17a9..98c9ae2ffe 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -31,8 +31,6 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, NET_USER_INFO_3 *info3) { - fstring str_sid; - state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); state->response.data.auth.info3.logoff_time = @@ -51,8 +49,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.user_rid = info3->user_rid; state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_fstring(str_sid, &(info3->dom_sid.sid)); - fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); + sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid)); state->response.data.auth.info3.num_groups = info3->num_groups; state->response.data.auth.info3.user_flgs = info3->user_flgs; -- cgit From 5f962d9b986e163bd3cceed6f9a9eebb61fdff27 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 23 Jan 2008 12:03:51 +0100 Subject: Fix get_trust_creds() to return always an upper-cased krb5 principal (this fixes winbind krb5 session at least with heimdal). Guenther (This used to be commit 9cf3a98eacea2dd07f89245f147e002b3f49482e) --- source3/winbindd/winbindd_cm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ef159f0670..ac122fba41 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -694,11 +694,15 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, /* this is at least correct when domain is our domain, * which is the only case, when this is currently used: */ - if ((machine_krb5_principal != NULL) && - (asprintf(machine_krb5_principal, "%s$@%s", account_name, - domain->alt_name) == -1)) + if (machine_krb5_principal != NULL) { - return NT_STATUS_NO_MEMORY; + if (asprintf(machine_krb5_principal, "%s$@%s", + account_name, domain->alt_name) == -1) + { + return NT_STATUS_NO_MEMORY; + } + + strupper_m(*machine_krb5_principal); } return NT_STATUS_OK; -- cgit From 3b83f4915885edfe8f01f4f68daad6b909fe473d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jan 2008 13:52:42 +0100 Subject: Initialize _domain_list to NULL. Just to be sure the "if (!_domain_list)" in domain_list() test always works. Michael (This used to be commit 1f49065d44dd7570d5a9928359751bd36f287952) --- source3/winbindd/winbindd_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index dc48fdef8b..0381053331 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -41,7 +41,7 @@ extern struct winbindd_methods passdb_methods; individual winbindd_domain structures cannot be made. Keep a copy of the domain name instead. */ -static struct winbindd_domain *_domain_list; +static struct winbindd_domain *_domain_list = NULL; /** When was the last scan of trusted domains done? -- cgit From 20512431321388cf293431b942cbbe9263d295c9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jan 2008 14:33:22 +0100 Subject: Fix panic: Don't free the logfilename in winbind_child_died(). The child struct is immediately reused, and this results in a panic when child->logfilename == NULL. Michael (This used to be commit da131d089db98017632103aa9bbe38c98f7a3fc1) --- source3/winbindd/winbindd_dual.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 778886d8e2..e21524689b 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -480,7 +480,6 @@ void winbind_child_died(pid_t pid) child->event.fd = 0; child->event.flags = 0; child->pid = 0; - SAFE_FREE(child->logfilename); schedule_async_request(child); } -- cgit From 691c4b1a4175e3d4a073c396a2a7d8d315cd42bd Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 17 Jan 2008 10:11:11 +0100 Subject: Windows 2008 (Longhorn) auth2 flag fixes. Interop fixes for AD specific flags. Original patch from Todd Stetcher. (This used to be commit 5aadfcdaacd6f136eab9e107a88b8544e6d2105f) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ac122fba41..dbc664da8c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2302,7 +2302,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; -- cgit From af7f24d97953a4d11435be963ee8fbcf993a6841 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Jan 2008 16:10:18 +0100 Subject: Add winbindd debugging ndr_print helpers. Guenther (This used to be commit 4389e4dadbf07c176d9102b74c06e62ecfc242be) --- source3/winbindd/winbindd_ndr.c | 149 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 source3/winbindd/winbindd_ndr.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c new file mode 100644 index 0000000000..145d11913d --- /dev/null +++ b/source3/winbindd/winbindd_ndr.c @@ -0,0 +1,149 @@ +/* + * Unix SMB/CIFS implementation. + * winbindd debug helper + * Copyright (C) Guenther Deschner 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_child(struct ndr_print *ndr, + const char *name, + const struct winbindd_child *r) +{ + ndr_print_struct(ndr, name, "winbindd_child"); + ndr->depth++; + ndr_print_ptr(ndr, "next", r->next); + ndr_print_ptr(ndr, "prev", r->prev); + ndr_print_uint32(ndr, "pid", (uint32_t)r->pid); +#if 0 + ndr_print_winbindd_domain(ndr, "domain", r->domain); +#else + ndr_print_ptr(ndr, "domain", r->domain); +#endif + ndr_print_string(ndr, "logfilename", r->logfilename); + /* struct fd_event event; */ + ndr_print_ptr(ndr, "lockout_policy_event", r->lockout_policy_event); + ndr_print_ptr(ndr, "requests", r->requests); + ndr_print_ptr(ndr, "table", r->table); + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_cm_conn(struct ndr_print *ndr, + const char *name, + const struct winbindd_cm_conn *r) +{ + ndr_print_struct(ndr, name, "winbindd_cm_conn"); + ndr->depth++; + ndr_print_ptr(ndr, "cli", r->cli); + ndr_print_ptr(ndr, "samr_pipe", r->samr_pipe); + ndr_print_policy_handle(ndr, "sam_connect_handle", &r->sam_connect_handle); + ndr_print_policy_handle(ndr, "sam_domain_handle", &r->sam_domain_handle); + ndr_print_ptr(ndr, "lsa_pipe", r->lsa_pipe); + ndr_print_policy_handle(ndr, "lsa_policy", &r->lsa_policy); + ndr_print_ptr(ndr, "netlogon_pipe", r->netlogon_pipe); + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_methods(struct ndr_print *ndr, + const char *name, + const struct winbindd_methods *r) +{ + extern struct winbindd_methods ads_methods; + extern struct winbindd_methods msrpc_methods; + extern struct winbindd_methods passdb_methods; + extern struct winbindd_methods reconnect_methods; + extern struct winbindd_methods cache_methods; + + ndr_print_struct(ndr, name, "winbindd_methods"); + ndr->depth++; + + if (r == NULL) { + ndr_print_string(ndr, name, "(NULL)"); + ndr->depth--; + return; + } + + if (r == &ads_methods) { + ndr_print_string(ndr, name, "ads_methods"); + } else if (r == &msrpc_methods) { + ndr_print_string(ndr, name, "msrpc_methods"); + } else if (r == &passdb_methods) { + ndr_print_string(ndr, name, "passdb_methods"); + } else if (r == &reconnect_methods) { + ndr_print_string(ndr, name, "reconnect_methods"); + } else if (r == &cache_methods) { + ndr_print_string(ndr, name, "cache_methods"); + } else { + ndr_print_string(ndr, name, "UNKNOWN"); + } + ndr->depth--; +} + +/**************************************************************** +****************************************************************/ + +void ndr_print_winbindd_domain(struct ndr_print *ndr, + const char *name, + const struct winbindd_domain *r) +{ + if (!r) { + return; + } + + ndr_print_struct(ndr, name, "winbindd_domain"); + ndr->depth++; + ndr_print_string(ndr, "name", r->name); + ndr_print_string(ndr, "alt_name", r->alt_name); + ndr_print_string(ndr, "forest_name", r->forest_name); + ndr_print_dom_sid(ndr, "sid", &r->sid); + ndr_print_netr_TrustFlags(ndr, "domain_flags", r->domain_flags); + ndr_print_netr_TrustType(ndr, "domain_type", r->domain_type); + ndr_print_netr_TrustAttributes(ndr, "domain_trust_attribs", r->domain_trust_attribs); + ndr_print_bool(ndr, "initialized", r->initialized); + ndr_print_bool(ndr, "native_mode", r->native_mode); + ndr_print_bool(ndr, "active_directory", r->active_directory); + ndr_print_bool(ndr, "primary", r->primary); + ndr_print_bool(ndr, "internal", r->internal); + ndr_print_bool(ndr, "online", r->online); + ndr_print_time_t(ndr, "startup_time", r->startup_time); + ndr_print_bool(ndr, "startup", r->startup); + ndr_print_winbindd_methods(ndr, "methods", r->methods); + ndr_print_winbindd_methods(ndr, "backend", r->backend); + ndr_print_ptr(ndr, "private_data", r->private_data); + ndr_print_string(ndr, "dcname", r->dcname); + ndr_print_sockaddr_storage(ndr, "dcaddr", &r->dcaddr); + ndr_print_time_t(ndr, "last_seq_check", r->last_seq_check); + ndr_print_uint32(ndr, "sequence_number", r->sequence_number); + ndr_print_NTSTATUS(ndr, "last_status", r->last_status); + ndr_print_winbindd_cm_conn(ndr, "conn", &r->conn); + ndr_print_winbindd_child(ndr, "child", &r->child); + ndr_print_uint32(ndr, "check_online_timeout", r->check_online_timeout); + ndr_print_ptr(ndr, "check_online_event", r->check_online_event); + ndr->depth--; +} -- cgit From fcf42bb19c66fdf87a27354f0cd31b5aacd527d5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Jan 2008 16:19:58 +0100 Subject: Add winbind_msg_dump_domain_list to winbindd. Guenther (This used to be commit 54ad97bd8364c393de2c9471a4c14ca5b880b318) --- source3/winbindd/winbindd.c | 4 ++ source3/winbindd/winbindd_dual.c | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 5e9900d1d6..615f4a918e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1227,6 +1227,10 @@ int main(int argc, char **argv, char **envp) MSG_WINBIND_VALIDATE_CACHE, winbind_msg_validate_cache); + messaging_register(winbind_messaging_context(), NULL, + MSG_WINBIND_DUMP_DOMAIN_LIST, + winbind_msg_dump_domain_list); + netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index e21524689b..a9786d1ceb 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -676,6 +676,88 @@ void winbind_msg_dump_event_list(struct messaging_context *msg_ctx, } +void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + TALLOC_CTX *mem_ctx; + const char *message = NULL; + struct server_id *sender = NULL; + const char *domain = NULL; + char *s = NULL; + NTSTATUS status; + struct winbindd_domain *dom = NULL; + + DEBUG(5,("winbind_msg_dump_domain_list received.\n")); + + if (!data || !data->data) { + return; + } + + if (data->length < sizeof(struct server_id)) { + return; + } + + mem_ctx = talloc_init("winbind_msg_dump_domain_list"); + if (!mem_ctx) { + return; + } + + sender = (struct server_id *)data->data; + if (data->length > sizeof(struct server_id)) { + domain = (const char *)data->data+sizeof(struct server_id); + } + + if (domain) { + + DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n", + domain)); + + message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, + find_domain_from_name_noinit(domain)); + if (!message) { + talloc_destroy(mem_ctx); + return; + } + + messaging_send_buf(msg_ctx, *sender, + MSG_WINBIND_DUMP_DOMAIN_LIST, + (uint8_t *)message, strlen(message) + 1); + + talloc_destroy(mem_ctx); + + return; + } + + DEBUG(5,("winbind_msg_dump_domain_list all domains\n")); + + for (dom = domain_list(); dom; dom=dom->next) { + message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom); + if (!message) { + talloc_destroy(mem_ctx); + return; + } + + s = talloc_asprintf_append(s, "%s\n", message); + if (!s) { + talloc_destroy(mem_ctx); + return; + } + } + + status = messaging_send_buf(msg_ctx, *sender, + MSG_WINBIND_DUMP_DOMAIN_LIST, + (uint8_t *)s, strlen(s) + 1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to send message: %s\n", + nt_errstr(status))); + } + + talloc_destroy(mem_ctx); +} + static void account_lockout_policy_handler(struct event_context *ctx, struct timed_event *te, const struct timeval *now, @@ -946,6 +1028,8 @@ static bool fork_domain_child(struct winbindd_child *child) MSG_WINBIND_ONLINESTATUS, NULL); messaging_deregister(winbind_messaging_context(), MSG_DUMP_EVENT_LIST, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_WINBIND_DUMP_DOMAIN_LIST, NULL); /* Handle online/offline messages. */ messaging_register(winbind_messaging_context(), NULL, -- cgit From 6b1c45a5c2e5e3f0a3e2b7772cd55079ebe3133e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Jan 2008 17:39:29 +0100 Subject: Fix winbindd build w/o ADS. Guenther (This used to be commit 40daef4c3d822a28467ff521efca6a55a0370050) --- source3/winbindd/winbindd_ndr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c index 145d11913d..842c915c5f 100644 --- a/source3/winbindd/winbindd_ndr.c +++ b/source3/winbindd/winbindd_ndr.c @@ -74,7 +74,9 @@ void ndr_print_winbindd_methods(struct ndr_print *ndr, const char *name, const struct winbindd_methods *r) { +#ifdef HAVE_ADS extern struct winbindd_methods ads_methods; +#endif extern struct winbindd_methods msrpc_methods; extern struct winbindd_methods passdb_methods; extern struct winbindd_methods reconnect_methods; @@ -89,10 +91,12 @@ void ndr_print_winbindd_methods(struct ndr_print *ndr, return; } - if (r == &ads_methods) { - ndr_print_string(ndr, name, "ads_methods"); - } else if (r == &msrpc_methods) { + if (r == &msrpc_methods) { ndr_print_string(ndr, name, "msrpc_methods"); +#ifdef HAVE_ADS + } else if (r == &ads_methods) { + ndr_print_string(ndr, name, "ads_methods"); +#endif } else if (r == &passdb_methods) { ndr_print_string(ndr, name, "passdb_methods"); } else if (r == &reconnect_methods) { -- cgit From 614ba32b221aee268b86033ee10da4dbdb087365 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 24 Jan 2008 22:47:49 +0100 Subject: Fix assignment to request->data.init_conn.is_primary in init_child_connection(). The present assignment "request->data.init_conn.is_primary = domain->internal ? False : True" simply feels wrong. This seems to be the thing right to do: "request->data.init_conn.is_primary = domain->primary ? true : false". The question is: Does this have any purpose at all? data.init_conn.is_primary seems to be used nowhere in the whole code at all. Is it (still) needed? Michael (This used to be commit 8bb21b8b3802e7b093a3c4fb41b8550033388878) --- source3/winbindd/winbindd_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 0381053331..724cce2512 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -571,7 +571,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain, /* The primary domain has to find the DC name itself */ request->cmd = WINBINDD_INIT_CONNECTION; fstrcpy(request->domain_name, domain->name); - request->data.init_conn.is_primary = domain->internal ? False : True; + request->data.init_conn.is_primary = domain->primary ? true : false; fstrcpy(request->data.init_conn.dcname, ""); async_request(mem_ctx, &domain->child, request, response, init_child_recv, state); -- cgit From 2a542ce7727cf3eb7f64d855c70d974f02185a2a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 24 Jan 2008 22:15:33 +0100 Subject: Add a debug message winbindd_can_contact_domain() explaining the reason for failure. Michael (This used to be commit ba5373ed7f74d560a9de8620039b596b8938d1dc) --- source3/winbindd/winbindd_util.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 724cce2512..3d9ede3cdf 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1404,6 +1404,8 @@ bool winbindd_can_contact_domain( struct winbindd_domain *domain ) if ( domain->active_directory && ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) { + DEBUG(10, ("Domain is an AD domain and we have no inbound " + "trust.\n")); return False; } -- cgit From 9912f82067a4cb2e393eb81504fa4312ebfa0cd5 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 25 Jan 2008 01:21:56 +0100 Subject: Add debug message: show which domain_child is being forked. Michael (This used to be commit 373a00ae0d667d257fa93ab14c773e841f2c4f1a) --- source3/winbindd/winbindd_dual.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index a9786d1ceb..15ca564c6a 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -959,6 +959,13 @@ static bool fork_domain_child(struct winbindd_child *child) struct winbindd_cli_state state; struct winbindd_domain *domain; + if (child->domain) { + DEBUG(10, ("fork_domain_child called for domain '%s'\n", + child->domain->name)); + } else { + DEBUG(10, ("fork_domain_child called without domain.\n")); + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) { DEBUG(0, ("Could not open child pipe: %s\n", strerror(errno))); -- cgit From 05ff7fd46e19d9c1aab8524495c9b926290927c7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 25 Jan 2008 13:26:10 +0100 Subject: Use generated DSSETUP client & server rpc functions and remove the hand-written ones. Guenther (This used to be commit d5ebfccebb1f1b56b45673a506fcdb414103c43b) --- source3/winbindd/winbindd_cm.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index dbc664da8c..0c5fa0e48e 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1805,17 +1805,17 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) { NTSTATUS result; - DS_DOMINFO_CTR ctr; + WERROR werr; TALLOC_CTX *mem_ctx = NULL; struct rpc_pipe_client *cli; POLICY_HND pol; + union dssetup_DsRoleInfo info; const char *domain_name = NULL; const char *dns_name = NULL; const char *forest_name = NULL; DOM_SID *dom_sid = NULL; - ZERO_STRUCT( ctr ); if (!connection_ok(domain)) { return; @@ -1830,24 +1830,25 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); - cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP, &result); if (cli == NULL) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " - "PI_LSARPC_DS on domain %s: (%s)\n", + "PI_DSSETUP on domain %s: (%s)\n", domain->name, nt_errstr(result))); /* if this is just a non-AD domain we need to continue * identifying so that we can in the end return with * domain->initialized = True - gd */ - goto no_lsarpc_ds; + goto no_dssetup; } - result = rpccli_ds_getprimarydominfo(cli, mem_ctx, - DsRolePrimaryDomainInfoBasic, - &ctr); + result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx, + DS_ROLE_BASIC_INFORMATION, + &info, + &werr); cli_rpc_pipe_close(cli); if (!NT_STATUS_IS_OK(result)) { @@ -1856,26 +1857,26 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) domain->name, nt_errstr(result))); /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for - * every opcode on the LSARPC_DS pipe, continue with - * no_lsarpc_ds mode here as well to get domain->initialized + * every opcode on the DSSETUP pipe, continue with + * no_dssetup mode here as well to get domain->initialized * set - gd */ if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) { - goto no_lsarpc_ds; + goto no_dssetup; } TALLOC_FREE(mem_ctx); return; } - - if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) && - !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) { + + if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) && + !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) { domain->native_mode = True; } else { domain->native_mode = False; } -no_lsarpc_ds: +no_dssetup: cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); if (cli == NULL) { -- cgit From 3ca606731b99754493ab5a8d761225c637bc82dd Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 25 Jan 2008 16:40:17 +0100 Subject: Fix winbindd_can_contact_domain() on a samba DC. The check for inbound trusts is invalid when samba is a DC and has a trust with an active directory domain. This effectively prevented tusts with an AD domain on a samba DC from working (unless using "winbindd rpc only"), because an ads_connect() was never performed. Only the rpc-based winbindd methods were working properly. Jerry: Please check! Michael (This used to be commit dcd42a1e0642c69348adfaeecef7f7f2f074ac30) --- source3/winbindd/winbindd_util.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 3d9ede3cdf..d16b7423a1 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1398,10 +1398,13 @@ bool winbindd_can_contact_domain( struct winbindd_domain *domain ) if ( domain->domain_flags & DS_DOMAIN_IN_FOREST ) return True; - /* We cannot contact the domain if it is running AD and - we have no inbound trust */ + /* + * On a _member_ server, we cannot contact the domain if it + * is running AD and we have no inbound trust. + */ - if ( domain->active_directory && + if ( !IS_DC && + domain->active_directory && ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) { DEBUG(10, ("Domain is an AD domain and we have no inbound " -- cgit From fda9247770577a98606c91973f98a7e53123a40c Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Fri, 25 Jan 2008 12:18:05 -0600 Subject: Use the correct domain name when looking up the trust password. On a DC, we always use the domain name given. On a domain member, we use lp_workgroup(). This fixes a bug supporting trusted domains. (This used to be commit 8b063a414149bdf401a8f854d55ed7dc6f94cb60) --- source3/winbindd/winbindd_cm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0c5fa0e48e..94910072c3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -679,8 +679,22 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, char **machine_krb5_principal) { const char *account_name; + const char *name = NULL; + + /* If we are a DC and this is not our own domain */ + + if (IS_DC) { + name = domain->name; + } else { + struct winbindd_domain *our_domain = find_our_domain(); - if (!get_trust_pw_clear(domain->name, machine_password, + if (!our_domain) + return NT_STATUS_INVALID_SERVER_STATE; + + name = our_domain->name; + } + + if (!get_trust_pw_clear(name, machine_password, &account_name, NULL)) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; -- cgit From 235deb1b66ccfb4a264010e8ffe11a3a3682ac0d Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Fri, 25 Jan 2008 12:21:14 -0600 Subject: Always trust the domain flags in the wcache trusted domain cache. Use the flags stored in the tdb when determining if a domain can be contacted. The tdb should be considered authoratative anyways unless you know the flags in the winbindd_domain are correct (such as when first enumerating trusts). Original suggestion and patch from Steven Danneman . Manually rewritten by me for 3.2. (This used to be commit f53658a20de07a29abbe2e90917b328d00fc0024) --- source3/winbindd/winbindd_util.c | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index d16b7423a1..f6bb5750ea 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1386,36 +1386,56 @@ void ws_name_return( char *name, char replace ) /********************************************************************* ********************************************************************/ -bool winbindd_can_contact_domain( struct winbindd_domain *domain ) +bool winbindd_can_contact_domain(struct winbindd_domain *domain) { + struct winbindd_tdc_domain *tdc = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + bool ret = false; + /* We can contact the domain if it is our primary domain */ - if ( domain->primary ) - return True; + if (domain->primary) { + return true; + } - /* Can always contact a domain that is in out forest */ + /* Trust the TDC cache and not the winbindd_domain flags */ - if ( domain->domain_flags & DS_DOMAIN_IN_FOREST ) - return True; + if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) { + DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n", + domain->name)); + return false; + } + + /* Can always contact a domain that is in out forest */ + if (tdc->trust_flags & DS_DOMAIN_IN_FOREST) { + ret = true; + goto done; + } + /* * On a _member_ server, we cannot contact the domain if it * is running AD and we have no inbound trust. */ - if ( !IS_DC && + if (!IS_DC && domain->active_directory && - ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) + ((tdc->trust_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND)) { - DEBUG(10, ("Domain is an AD domain and we have no inbound " - "trust.\n")); - return False; + DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain " + "and we have no inbound trust.\n", domain->name)); + goto done; } - + /* Assume everything else is ok (probably not true but what can you do?) */ + + ret = true; + +done: + talloc_destroy(frame); - return True; + return ret; } /********************************************************************* -- cgit From 5ab43ae0d8e66a1fd4c877089df52282367be7dd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 26 Jan 2008 01:39:33 +0100 Subject: Eliminate remote tree of dsgetdcname (which will happen in libnetapi then). Guenther (This used to be commit fd490d236b1fb73a75c457b75128c9b98719418f) --- source3/winbindd/winbindd_locator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 05bd74af25..6b1cff99e0 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -67,7 +67,7 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid, state->request.domain_name)); - result = dsgetdcname(state->mem_ctx, NULL, state->request.domain_name, + result = dsgetdcname(state->mem_ctx, state->request.domain_name, NULL, NULL, state->request.flags, &info); if (!NT_STATUS_IS_OK(result)) { -- cgit From 53c600992829a44b91d5be1cac7b1fe6ab31458e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 29 Jan 2008 14:20:20 +0100 Subject: Use pidl generated call to enumerate ds trusted domains in winbindd. Guenther (This used to be commit 3a3c1aed9bfc681457aa06f706fc6fe2d9b2e903) --- source3/winbindd/winbindd_cm.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 94910072c3..c22022d79a 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1716,8 +1716,7 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) { struct winbindd_domain *our_domain; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct ds_domain_trust *domains = NULL; - int count = 0; + struct netr_DomainTrustList trusts; int i; uint32 flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND | @@ -1763,19 +1762,27 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) return False; } - result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, - cli->cli->desthost, - flags, &domains, - (unsigned int *)&count); + result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, + cli->cli->desthost, + flags, + &trusts, + NULL); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("set_dc_type_and_flags_trustinfo: " + "failed to query trusted domain list: %s\n", + nt_errstr(result))); + talloc_destroy(mem_ctx); + return false; + } /* Now find the domain name and get the flags */ - for ( i=0; iname, domains[i].netbios_domain ) ) { - domain->domain_flags = domains[i].flags; - domain->domain_type = domains[i].trust_type; - domain->domain_trust_attribs = domains[i].trust_attributes; - + for ( i=0; iname, trusts.array[i].netbios_name) ) { + domain->domain_flags = trusts.array[i].trust_flags; + domain->domain_type = trusts.array[i].trust_type; + domain->domain_trust_attribs = trusts.array[i].trust_attributes; + if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL ) domain->active_directory = True; -- cgit From e629f50a51f60f9e9e6b8aa4e68c43faa0d4158e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 29 Jan 2008 14:59:20 +0100 Subject: Use another pidl generated call to enumerate ds trusted domains in winbindd. Guenther (This used to be commit f6397fbeae6668c6d0470f968cb1506b3ce34e4a) --- source3/winbindd/winbindd_ads.c | 49 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index f963669825..9bc310474c 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1157,8 +1157,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, DOM_SID **dom_sids) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct ds_domain_trust *domains = NULL; - int count = 0; + struct netr_DomainTrustList trusts; int i; uint32 flags; struct rpc_pipe_client *cli; @@ -1194,29 +1193,27 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, domain->name, nt_errstr(result))); return NT_STATUS_UNSUCCESSFUL; } - - if ( NT_STATUS_IS_OK(result) ) { - result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, - cli->cli->desthost, - flags, &domains, - (unsigned int *)&count); - } - - if ( NT_STATUS_IS_OK(result) && count) { + + result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, + cli->cli->desthost, + flags, + &trusts, + NULL); + if ( NT_STATUS_IS_OK(result) && trusts.count) { /* Allocate memory for trusted domain names and sids */ - if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, count)) ) { + if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, trusts.count)) ) { DEBUG(0, ("trusted_domains: out of memory\n")); return NT_STATUS_NO_MEMORY; } - if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, count)) ) { + if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, trusts.count)) ) { DEBUG(0, ("trusted_domains: out of memory\n")); return NT_STATUS_NO_MEMORY; } - if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, count)) ) { + if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, trusts.count)) ) { DEBUG(0, ("trusted_domains: out of memory\n")); return NT_STATUS_NO_MEMORY; } @@ -1225,7 +1222,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, ret_count = 0; - for (i = 0; i < count; i++) { + for (i = 0; i < trusts.count; i++) { struct winbindd_domain d; /* drop external trusts if this is not our primary @@ -1233,24 +1230,24 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, domains may be less that the ones actually trusted by the DC. */ - if ( (domains[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) && + if ( (trusts.array[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) && !domain->primary ) { DEBUG(10,("trusted_domains: Skipping external trusted domain " "%s because it is outside of our primary domain\n", - domains[i].netbios_domain)); + trusts.array[i].netbios_name)); continue; } - (*names)[ret_count] = domains[i].netbios_domain; - (*alt_names)[ret_count] = domains[i].dns_domain; - sid_copy(&(*dom_sids)[ret_count], &domains[i].sid); + (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name); + (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name); + sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid); /* add to the trusted domain cache */ - fstrcpy( d.name, domains[i].netbios_domain ); - fstrcpy( d.alt_name, domains[i].dns_domain ); - sid_copy( &d.sid, &domains[i].sid ); + fstrcpy( d.name, trusts.array[i].netbios_name); + fstrcpy( d.alt_name, trusts.array[i].dns_name); + sid_copy( &d.sid, trusts.array[i].sid); /* This gets a little tricky. If we are following a transitive forest trust, then @@ -1269,9 +1266,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, we have the current trust flags and attributes */ - d.domain_flags = domains[i].flags; - d.domain_type = domains[i].trust_type; - d.domain_trust_attribs = domains[i].trust_attributes; + d.domain_flags = trusts.array[i].trust_flags; + d.domain_type = trusts.array[i].trust_type; + d.domain_trust_attribs = trusts.array[i].trust_attributes; } else { /* Look up the record in the cache */ struct winbindd_tdc_domain *parent; -- cgit From 80b2e330f939d9877352f8fbdbec3a4e0e395c7b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 29 Jan 2008 17:49:38 +0100 Subject: Remove include/rpc_ds.h and all references to it completly. Jerry, please have a look if you're fine with that. Guenther (This used to be commit beae25c808a3a03d645f247e9befcd05e3ecca2c) --- source3/winbindd/winbindd.h | 6 +++--- source3/winbindd/winbindd_ads.c | 12 ++++++------ source3/winbindd/winbindd_cm.c | 12 ++++++------ source3/winbindd/winbindd_pam.c | 2 +- source3/winbindd/winbindd_util.c | 22 +++++++++++----------- 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 6bf6e6c68f..c4c1278d73 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -164,9 +164,9 @@ struct winbindd_domain { fstring alt_name; /* alt Domain name, if any (FQDN for ADS) */ fstring forest_name; /* Name of the AD forest we're in */ DOM_SID sid; /* SID for this domain */ - uint32 domain_flags; /* Domain flags from rpc_ds.h */ - uint32 domain_type; /* Domain type from rpc_ds.h */ - uint32 domain_trust_attribs; /* Trust attribs from rpc_ds.h */ + uint32 domain_flags; /* Domain flags from netlogon.h */ + uint32 domain_type; /* Domain type from netlogon.h */ + uint32 domain_trust_attribs; /* Trust attribs from netlogon.h */ bool initialized; /* Did we already ask for the domain mode? */ bool native_mode; /* is this a win2k domain in native mode ? */ bool active_directory; /* is this a win2k active directory ? */ diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 9bc310474c..db7ceca04d 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1161,7 +1161,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, int i; uint32 flags; struct rpc_pipe_client *cli; - uint32 fr_flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_TREE_ROOT); + uint32 fr_flags = (NETR_TRUST_FLAG_IN_FOREST | NETR_TRUST_FLAG_TREEROOT); int ret_count; DEBUG(3,("ads: trusted_domains\n")); @@ -1178,11 +1178,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, if ( domain->primary || ((domain->domain_flags&fr_flags) == fr_flags) ) { - flags = DS_DOMAIN_DIRECT_OUTBOUND | - DS_DOMAIN_DIRECT_INBOUND | - DS_DOMAIN_IN_FOREST; + flags = NETR_TRUST_FLAG_OUTBOUND | + NETR_TRUST_FLAG_INBOUND | + NETR_TRUST_FLAG_IN_FOREST; } else { - flags = DS_DOMAIN_IN_FOREST; + flags = NETR_TRUST_FLAG_IN_FOREST; } result = cm_connect_netlogon(domain, &cli); @@ -1230,7 +1230,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, domains may be less that the ones actually trusted by the DC. */ - if ( (trusts.array[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) && + if ( (trusts.array[i].trust_attributes == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) && !domain->primary ) { DEBUG(10,("trusted_domains: Skipping external trusted domain " diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index c22022d79a..66787a0d6d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1718,9 +1718,9 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct netr_DomainTrustList trusts; int i; - uint32 flags = (DS_DOMAIN_IN_FOREST | - DS_DOMAIN_DIRECT_OUTBOUND | - DS_DOMAIN_DIRECT_INBOUND); + uint32 flags = (NETR_TRUST_FLAG_IN_FOREST | + NETR_TRUST_FLAG_OUTBOUND | + NETR_TRUST_FLAG_INBOUND); struct rpc_pipe_client *cli; TALLOC_CTX *mem_ctx = NULL; @@ -1783,14 +1783,14 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) domain->domain_type = trusts.array[i].trust_type; domain->domain_trust_attribs = trusts.array[i].trust_attributes; - if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL ) + if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL ) domain->active_directory = True; /* This flag is only set if the domain is *our* primary domain and the primary domain is in native mode */ - domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE); + domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE); DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin " "native mode.\n", domain->name, @@ -1937,7 +1937,7 @@ no_dssetup: fstrcpy(domain->forest_name, forest_name); if (strequal(domain->forest_name, domain->alt_name)) { - domain->domain_flags = DS_DOMAIN_TREE_ROOT; + domain->domain_flags = NETR_TRUST_FLAG_TREEROOT; } } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 98c9ae2ffe..ea9a07d388 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -964,7 +964,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, #ifdef HAVE_KRB5 if ((state->request.flags & WBFLAG_PAM_KRB5) && ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && - (tdc_domain->trust_type & DS_DOMAIN_TRUST_TYPE_UPLEVEL)) { + (tdc_domain->trust_type & NETR_TRUST_TYPE_UPLEVEL)) { uid_t uid = -1; const char *cc = NULL; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index f6bb5750ea..10779cd60a 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -218,7 +218,7 @@ static void add_trusted_domains( struct winbindd_domain *domain ) TALLOC_CTX *mem_ctx; struct winbindd_request *request; struct winbindd_response *response; - uint32 fr_flags = (DS_DOMAIN_TREE_ROOT|DS_DOMAIN_IN_FOREST); + uint32 fr_flags = (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST); struct trustdom_state *state; @@ -391,8 +391,8 @@ static void rescan_forest_root_trusts( void ) the domain_list() as our primary domain may not have been initialized. */ - if ( !(dom_list[i].trust_flags & DS_DOMAIN_TREE_ROOT) ) { - continue; + if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) { + continue; } /* Here's the forest root */ @@ -456,10 +456,10 @@ static void rescan_forest_trusts( void ) if ( d && (d->internal || d->primary ) ) continue; - - if ( (flags & DS_DOMAIN_DIRECT_INBOUND) && - (type == DS_DOMAIN_TRUST_TYPE_UPLEVEL) && - (attribs == DS_DOMAIN_TRUST_ATTRIB_FOREST_TRANSITIVE) ) + + if ( (flags & NETR_TRUST_FLAG_INBOUND) && + (type == NETR_TRUST_TYPE_UPLEVEL) && + (attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) ) { /* add the trusted domain if we don't know about it */ @@ -770,8 +770,8 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid ) forest trust */ domain->active_directory = True; - domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND; - domain->domain_type = DS_DOMAIN_TRUST_TYPE_UPLEVEL; + domain->domain_flags = NETR_TRUST_FLAG_OUTBOUND; + domain->domain_type = NETR_TRUST_TYPE_UPLEVEL; domain->internal = False; domain->online = True; @@ -1408,7 +1408,7 @@ bool winbindd_can_contact_domain(struct winbindd_domain *domain) /* Can always contact a domain that is in out forest */ - if (tdc->trust_flags & DS_DOMAIN_IN_FOREST) { + if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) { ret = true; goto done; } @@ -1420,7 +1420,7 @@ bool winbindd_can_contact_domain(struct winbindd_domain *domain) if (!IS_DC && domain->active_directory && - ((tdc->trust_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND)) + ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND)) { DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain " "and we have no inbound trust.\n", domain->name)); -- cgit From 5334b364c21599fe055b32bbbd1e8cf7488b1fa7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 30 Jan 2008 12:39:20 +0100 Subject: Remove rpccli_samr_close and use pidl generated function instead. Guenther (This used to be commit 64f0889401855ab76953bfae5db4fe4df19ad8a5) --- source3/winbindd/winbindd_pam.c | 6 +++--- source3/winbindd/winbindd_rpc.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ea9a07d388..59ca15a623 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1356,14 +1356,14 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not query user info on SAMR pipe: %s\n", nt_errstr(status_tmp))); - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); goto done; } acct_flags = user_ctr->info.id16->acb_info; if (acct_flags == 0) { - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); goto done; } @@ -1371,7 +1371,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); } *info3 = my_info3; diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 34ba0498e0..47a8d430b2 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -480,7 +480,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 0x15, &ctr); - rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_Close(cli, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) return result; @@ -555,7 +555,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, num_groups, &user_groups); - rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_Close(cli, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) return result; @@ -721,7 +721,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, /* And restore our original timeout. */ cli_set_timeout(cli->cli, orig_timeout); - rpccli_samr_close(cli, mem_ctx, &group_pol); + rpccli_samr_Close(cli, mem_ctx, &group_pol); if (!NT_STATUS_IS_OK(result)) return result; -- cgit From 42960f817a9fd439557d1be2f3ca3603a35489ce Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 1 Feb 2008 11:12:05 +0100 Subject: Use rpccli_samr_OpenDomain() all over the place. Guenther (This used to be commit e4e9d72724d547e1405b2ed4cec509d50ec88c8d) --- source3/winbindd/winbindd_cm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 66787a0d6d..d2a7663002 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2176,12 +2176,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } open_domain: - result = rpccli_samr_open_domain(conn->samr_pipe, - mem_ctx, - &conn->sam_connect_handle, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &domain->sid, - &conn->sam_domain_handle); + result = rpccli_samr_OpenDomain(conn->samr_pipe, + mem_ctx, + &conn->sam_connect_handle, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &domain->sid, + &conn->sam_domain_handle); done: -- cgit From 482eaa8e5cccd716be07f5eb1536097452214790 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 1 Feb 2008 11:24:01 +0100 Subject: Use rpccli_samr_OpenGroup() all over the place. Guenther (This used to be commit d019fc69a986937880121c2587d3fe37f995edae) --- source3/winbindd/winbindd_rpc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 47a8d430b2..b8f1982868 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -700,8 +700,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(result)) return result; - result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol, - des_access, group_rid, &group_pol); + result = rpccli_samr_OpenGroup(cli, mem_ctx, + &dom_pol, + des_access, + group_rid, + &group_pol); if (!NT_STATUS_IS_OK(result)) return result; -- cgit From 37b56c0113263a741c62100cd4b13388cb2a83fa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 1 Feb 2008 11:57:53 +0100 Subject: Use rpccli_samr_OpenUser() all over the place. Guenther (This used to be commit da90eb7653554d242da83ed98adae35ced3a2938) --- source3/winbindd/winbindd_pam.c | 9 +++++---- source3/winbindd/winbindd_rpc.c | 15 ++++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 59ca15a623..14b1621fc9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1339,10 +1339,11 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx, - &samr_domain_handle, - MAXIMUM_ALLOWED_ACCESS, - my_info3->user_rid, &user_pol); + status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx, + &samr_domain_handle, + MAXIMUM_ALLOWED_ACCESS, + my_info3->user_rid, + &user_pol); if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not open user handle on SAMR pipe: %s\n", diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index b8f1982868..0d937ef30e 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -469,9 +469,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain, return result; /* Get user handle */ - result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, - &user_pol); + result = rpccli_samr_OpenUser(cli, mem_ctx, + &dom_pol, + SEC_RIGHTS_MAXIMUM_ALLOWED, + user_rid, + &user_pol); if (!NT_STATUS_IS_OK(result)) return result; @@ -545,8 +547,11 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return result; /* Get user handle */ - result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol, - des_access, user_rid, &user_pol); + result = rpccli_samr_OpenUser(cli, mem_ctx, + &dom_pol, + des_access, + user_rid, + &user_pol); if (!NT_STATUS_IS_OK(result)) return result; -- cgit From 93a3c5b3f9927973b4ad1496f593ea147052d1e1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 1 Feb 2008 13:50:04 -0500 Subject: Fix winbindd running on a Samba DC, This patch make sure we do not try to contact smbd in the main dameon to avoid deadlocks. All the operations that require connecting to smbd are performed in the domain child anyway. (This used to be commit 9347d34b502bef70cdae8f3e8acd9796dba49581) --- source3/winbindd/winbindd_dual.c | 11 +++++++++++ source3/winbindd/winbindd_util.c | 6 ------ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 778886d8e2..2739ab542e 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -34,6 +34,7 @@ #define DBGC_CLASS DBGC_WINBIND extern bool override_logfile; +extern struct winbindd_methods cache_methods; /* Read some data from a client connection */ @@ -991,6 +992,16 @@ static bool fork_domain_child(struct winbindd_child *child) child); } + /* Special case for Winbindd on a Samba DC, + * We want to make sure the child can connect to smbd + * but not the main daemon */ + + if (child->domain && child->domain->internal && IS_DC) { + child->domain->internal = False; + child->domain->methods = &cache_methods; + child->domain->online = False; + } + while (1) { int ret; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 70468b6bcd..795209619c 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -82,9 +82,6 @@ static bool is_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; - if ( IS_DC ) - return sid_check_is_builtin(sid); - return (sid_check_is_domain(sid) || sid_check_is_builtin(sid)); } @@ -93,9 +90,6 @@ static bool is_in_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; - if ( IS_DC ) - return sid_check_is_in_builtin(sid); - return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid)); } -- cgit From b42a5d68a3ffd88fd60c64b6a75fe2d687d9c92d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 10:39:21 +0100 Subject: Convert read_data() to NTSTATUS (This used to be commit af40b71023f8c4a2133d996ea698c72b97624043) --- source3/winbindd/winbindd_dual.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 1f2972f9b2..48f37af4d0 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -40,15 +40,16 @@ extern struct winbindd_methods cache_methods; static void child_read_request(struct winbindd_cli_state *state) { - ssize_t len; + NTSTATUS status; /* Read data */ - len = read_data(state->sock, (char *)&state->request, - sizeof(state->request), NULL); + status = read_data(state->sock, (char *)&state->request, + sizeof(state->request)); - if (len != sizeof(state->request)) { - DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len)); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("child_read_request: read_data failed: %s\n", + nt_errstr(status))); state->finished = True; return; } @@ -72,11 +73,12 @@ static void child_read_request(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.extra_data.data[state->request.extra_len] = '\0'; - len = read_data(state->sock, state->request.extra_data.data, - state->request.extra_len, NULL); + status= read_data(state->sock, state->request.extra_data.data, + state->request.extra_len); - if (len != state->request.extra_len) { - DEBUG(0, ("Could not read extra data\n")); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Could not read extra data: %s\n", + nt_errstr(status))); state->finished = True; return; } -- cgit From 30dcc73d969a0761605e8649d68dc83ba24b9d67 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 28 Jan 2008 17:47:41 +0100 Subject: Fix a typo in a debug message. Michael (This used to be commit 3865a7e6a19630f8a90140accf4a6e93d4f70e6c) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 14b1621fc9..9435a328dd 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -324,7 +324,7 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, if (IS_DC) { domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { - DEBUG(3, ("Authentication for domain [%s] refused" + DEBUG(3, ("Authentication for domain [%s] refused " "as it is not a trusted domain\n", domain_name)); } -- cgit From 270ba9c238400f49d32c57a9a1bbde6ad63bb555 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 4 Feb 2008 19:43:07 +0100 Subject: Use rpccli_samr_Connect2() all over the place. Guenther (This used to be commit bdf8d562621e1a09bf83e2009dec24966e7fdf22) --- source3/winbindd/winbindd_cm.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d2a7663002..7bc449c90d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2109,13 +2109,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "pipe: user %s\\%s\n", domain->name, domain_name, machine_account)); - result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &conn->sam_connect_handle); + result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, + conn->samr_pipe->cli->desthost, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { goto open_domain; } - DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect " + DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 " "failed for domain %s, error was %s. Trying schannel\n", domain->name, nt_errstr(result) )); cli_rpc_pipe_close(conn->samr_pipe); @@ -2143,13 +2144,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using " "schannel.\n", domain->name )); - result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &conn->sam_connect_handle); + result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, + conn->samr_pipe->cli->desthost, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { goto open_domain; } - DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed " + DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed " "for domain %s, error was %s. Trying anonymous\n", domain->name, nt_errstr(result) )); cli_rpc_pipe_close(conn->samr_pipe); @@ -2165,11 +2167,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto done; } - result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &conn->sam_connect_handle); + result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, + conn->samr_pipe->cli->desthost, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn->sam_connect_handle); if (!NT_STATUS_IS_OK(result)) { - DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed " + DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed " "for domain %s Error was %s\n", domain->name, nt_errstr(result) )); goto done; -- cgit From 0c6b6b461c0cad6943fe24fd76f9723b749dc15c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 5 Feb 2008 02:45:51 +0100 Subject: Use rpccli_samr_GetAliasMembership() in winbindd and rpcclient. Guenther (This used to be commit 5c167162856fd1e13a3e04423cfc0cc936ae26b0) --- source3/winbindd/winbindd_rpc.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 0d937ef30e..7e35759348 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -585,11 +585,10 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol; - DOM_SID2 *query_sids; uint32 num_query_sids = 0; int i; struct rpc_pipe_client *cli; - uint32 *alias_rids_query, num_aliases_query; + struct samr_Ids alias_rids_query; int rangesize = MAX_SAM_ENTRIES_W2K; uint32 total_sids = 0; int num_queries = 1; @@ -611,6 +610,9 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, do { /* prepare query */ + struct lsa_SidArray sid_array; + + ZERO_STRUCT(sid_array); num_query_sids = MIN(num_sids - total_sids, rangesize); @@ -618,45 +620,48 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, num_queries, num_query_sids)); if (num_query_sids) { - query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids); - if (query_sids == NULL) { + sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids); + if (sid_array.sids == NULL) { return NT_STATUS_NO_MEMORY; } } else { - query_sids = NULL; + sid_array.sids = NULL; } for (i=0; i Date: Tue, 5 Feb 2008 10:58:37 +0100 Subject: Use rpccli_samr_QueryGroupMember() all over the place. Guenther (This used to be commit 1793ed10df7f403b85a4e52c67cbfb277b23b30b) --- source3/winbindd/winbindd_rpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 7e35759348..a318199b62 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -691,6 +691,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, unsigned int j; struct rpc_pipe_client *cli; unsigned int orig_timeout; + struct samr_RidTypeArray *rids = NULL; DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_string_dbg(group_sid))); @@ -727,9 +728,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, orig_timeout = cli_set_timeout(cli->cli, 35000); - result = rpccli_samr_query_groupmem(cli, mem_ctx, - &group_pol, num_names, &rid_mem, - name_types); + result = rpccli_samr_QueryGroupMember(cli, mem_ctx, + &group_pol, + &rids); /* And restore our original timeout. */ cli_set_timeout(cli->cli, orig_timeout); @@ -739,6 +740,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(result)) return result; + *num_names = rids->count; + rid_mem = rids->rids; + if (!*num_names) { names = NULL; name_types = NULL; -- cgit From 497eb77099e4950779d40812bf17ac1b31137b46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Feb 2008 16:51:46 -0800 Subject: Small whitespace cleanup + check for null returns on talloc_strdup. Jeremy. (This used to be commit 654484b9a2d8d2be20f02d228d53a23936d1703b) --- source3/winbindd/winbindd_async.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index ab32ee0c76..2ff5ef230d 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -283,9 +283,8 @@ static void lookupname_recv2(TALLOC_CTX *mem_ctx, bool success, enum lsa_SidType type) = (void (*)(void *, bool, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; - struct lookupname_state *s = talloc_get_type_abort( private_data, + struct lookupname_state *s = talloc_get_type_abort( private_data, struct lookupname_state ); - if (!success) { DEBUG(5, ("Could not trigger lookup_name\n")); @@ -311,7 +310,7 @@ static void lookupname_recv2(TALLOC_CTX *mem_ctx, bool success, } /******************************************************************** - This is the first callback after contacting our own domain + This is the first callback after contacting our own domain ********************************************************************/ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, @@ -322,7 +321,7 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, enum lsa_SidType type) = (void (*)(void *, bool, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; - struct lookupname_state *s = talloc_get_type_abort( private_data, + struct lookupname_state *s = talloc_get_type_abort( private_data, struct lookupname_state ); if (!success) { @@ -334,8 +333,8 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, if (response->result != WINBINDD_OK) { /* Try again using the forest root */ struct winbindd_domain *root_domain = find_root_domain(); - struct winbindd_request request; - + struct winbindd_request request; + if ( !root_domain ) { DEBUG(5,("lookupname_recv: unable to determine forest root\n")); cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); @@ -346,7 +345,7 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, request.cmd = WINBINDD_LOOKUPNAME; fstrcpy( request.data.name.dom_name, s->dom_name ); - fstrcpy( request.data.name.name, s->name ); + fstrcpy( request.data.name.name, s->name ); do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2, (void *)cont, s); @@ -381,7 +380,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, { struct winbindd_request request; struct winbindd_domain *domain; - struct lookupname_state *s; + struct lookupname_state *s; if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) { DEBUG(5, ("Could not find domain for name '%s'\n", dom_name)); @@ -403,6 +402,11 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, s->dom_name = talloc_strdup( s, dom_name ); s->name = talloc_strdup( s, name ); + if (!s->dom_name || !s->name) { + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + s->caller_private_data = private_data; do_async_domain(mem_ctx, domain, &request, lookupname_recv, -- cgit From 742fd39b7a9ecfe30b01e323a9ce1c2375c5d076 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 5 Feb 2008 17:25:07 +0100 Subject: Use rpccli_samr_QueryDomainInfo() in winbindd. Guenther (This used to be commit dd9fa33e968d4e641460fe1c6beb05dfe12fa918) --- source3/winbindd/winbindd.h | 12 ++--- source3/winbindd/winbindd_cache.c | 83 +++++++++++++++++++---------------- source3/winbindd/winbindd_dual.c | 2 +- source3/winbindd/winbindd_pam.c | 22 +++++----- source3/winbindd/winbindd_passdb.c | 14 +++--- source3/winbindd/winbindd_reconnect.c | 4 +- source3/winbindd/winbindd_rpc.c | 54 ++++++++++++++--------- 7 files changed, 106 insertions(+), 85 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index c4c1278d73..b812d69aeb 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -301,15 +301,15 @@ struct winbindd_methods { NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq); /* return the lockout policy */ - NTSTATUS (*lockout_policy)(struct winbindd_domain *domain, + NTSTATUS (*lockout_policy)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_12 *lockout_policy); - + struct samr_DomInfo12 *lockout_policy); + /* return the lockout policy */ - NTSTATUS (*password_policy)(struct winbindd_domain *domain, + NTSTATUS (*password_policy)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_1 *password_policy); - + struct samr_DomInfo1 *password_policy); + /* enumerate trusted domains */ NTSTATUS (*trusted_domains)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index c293861492..f235e401e8 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -908,7 +908,9 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI centry_free(centry); } -static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy) +static void wcache_save_lockout_policy(struct winbindd_domain *domain, + NTSTATUS status, + struct samr_DomInfo12 *lockout_policy) { struct cache_entry *centry; @@ -916,18 +918,20 @@ static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS if (!centry) return; - centry_put_nttime(centry, lockout_policy->duration); - centry_put_nttime(centry, lockout_policy->reset_count); - centry_put_uint16(centry, lockout_policy->bad_attempt_lockout); + centry_put_nttime(centry, lockout_policy->lockout_duration); + centry_put_nttime(centry, lockout_policy->lockout_window); + centry_put_uint16(centry, lockout_policy->lockout_threshold); centry_end(centry, "LOC_POL/%s", domain->name); - + DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name)); centry_free(centry); } -static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *policy) +static void wcache_save_password_policy(struct winbindd_domain *domain, + NTSTATUS status, + struct samr_DomInfo1 *policy) { struct cache_entry *centry; @@ -935,14 +939,14 @@ static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS if (!centry) return; - centry_put_uint16(centry, policy->min_length_password); - centry_put_uint16(centry, policy->password_history); + centry_put_uint16(centry, policy->min_password_length); + centry_put_uint16(centry, policy->password_history_length); centry_put_uint32(centry, policy->password_properties); - centry_put_nttime(centry, policy->expire); - centry_put_nttime(centry, policy->min_passwordage); + centry_put_nttime(centry, policy->max_password_age); + centry_put_nttime(centry, policy->min_password_age); centry_end(centry, "PWD_POL/%s", domain->name); - + DEBUG(10,("wcache_save_password_policy: %s\n", domain->name)); centry_free(centry); @@ -2131,55 +2135,56 @@ skip_save: /* get lockout policy */ static NTSTATUS lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_12 *policy){ + struct samr_DomInfo12 *policy) +{ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - + if (!cache->tdb) goto do_query; - + centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name); - + if (!centry) goto do_query; - - policy->duration = centry_nttime(centry); - policy->reset_count = centry_nttime(centry); - policy->bad_attempt_lockout = centry_uint16(centry); - + + policy->lockout_duration = centry_nttime(centry); + policy->lockout_window = centry_nttime(centry); + policy->lockout_threshold = centry_uint16(centry); + status = centry->status; - + DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status: %s\n", domain->name, nt_errstr(status) )); - + centry_free(centry); return status; - + do_query: ZERO_STRUCTP(policy); - + /* Return status value returned by seq number check */ if (!NT_STATUS_IS_OK(domain->last_status)) return domain->last_status; - + DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n", domain->name )); - - status = domain->backend->lockout_policy(domain, mem_ctx, policy); - + + status = domain->backend->lockout_policy(domain, mem_ctx, policy); + /* and save it */ refresh_sequence_number(domain, false); wcache_save_lockout_policy(domain, status, policy); - + return status; } - + /* get password policy */ static NTSTATUS password_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_1 *policy) + struct samr_DomInfo1 *policy) { struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; @@ -2187,17 +2192,17 @@ static NTSTATUS password_policy(struct winbindd_domain *domain, if (!cache->tdb) goto do_query; - + centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name); - + if (!centry) goto do_query; - policy->min_length_password = centry_uint16(centry); - policy->password_history = centry_uint16(centry); + policy->min_password_length = centry_uint16(centry); + policy->password_history_length = centry_uint16(centry); policy->password_properties = centry_uint32(centry); - policy->expire = centry_nttime(centry); - policy->min_passwordage = centry_nttime(centry); + policy->max_password_age = centry_nttime(centry); + policy->min_password_age = centry_nttime(centry); status = centry->status; @@ -2214,11 +2219,11 @@ do_query: if (!NT_STATUS_IS_OK(domain->last_status)) return domain->last_status; - + DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n", domain->name )); - status = domain->backend->password_policy(domain, mem_ctx, policy); + status = domain->backend->password_policy(domain, mem_ctx, policy); /* and save it */ refresh_sequence_number(domain, false); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 48f37af4d0..2b756b24d1 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -770,7 +770,7 @@ static void account_lockout_policy_handler(struct event_context *ctx, (struct winbindd_child *)private_data; TALLOC_CTX *mem_ctx = NULL; struct winbindd_methods *methods; - SAM_UNK_INFO_12 lockout_policy; + struct samr_DomInfo12 lockout_policy; NTSTATUS result; DEBUG(10,("account_lockout_policy_handler called\n")); diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 9435a328dd..c1a277f9b5 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -370,7 +370,7 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_1 password_policy; + struct samr_DomInfo1 password_policy; if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(5,("fillup_password_policy: No inbound trust to " @@ -386,28 +386,28 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, } state->response.data.auth.policy.min_length_password = - password_policy.min_length_password; + password_policy.min_password_length; state->response.data.auth.policy.password_history = - password_policy.password_history; + password_policy.password_history_length; state->response.data.auth.policy.password_properties = password_policy.password_properties; state->response.data.auth.policy.expire = - nt_time_to_unix_abs(&(password_policy.expire)); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs(&(password_policy.min_passwordage)); + nt_time_to_unix_abs((NTTIME *)&(password_policy.max_password_age)); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&(password_policy.min_password_age)); return NT_STATUS_OK; } static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint16 *max_allowed_bad_attempts) + uint16 *lockout_threshold) { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_12 lockout_policy; + struct samr_DomInfo12 lockout_policy; - *max_allowed_bad_attempts = 0; + *lockout_threshold = 0; methods = domain->methods; @@ -416,7 +416,7 @@ static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain return status; } - *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout; + *lockout_threshold = lockout_policy.lockout_threshold; return NT_STATUS_OK; } @@ -427,7 +427,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_1 password_policy; + struct samr_DomInfo1 password_policy; *password_properties = 0; diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 29db8be857..7c1d7bd71b 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -338,7 +338,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) static NTSTATUS lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_12 *policy) + struct samr_DomInfo12 *policy) { /* actually we have that */ return NT_STATUS_NOT_IMPLEMENTED; @@ -346,14 +346,14 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain, static NTSTATUS password_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_1 *policy) + struct samr_DomInfo1 *policy) { uint32 min_pass_len,pass_hist,password_properties; time_t u_expire, u_min_age; NTTIME nt_expire, nt_min_age; uint32 account_policy_temp; - if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) { + if ((policy = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) { return NT_STATUS_NO_MEMORY; } @@ -385,8 +385,12 @@ static NTSTATUS password_policy(struct winbindd_domain *domain, unix_to_nt_time_abs(&nt_expire, u_expire); unix_to_nt_time_abs(&nt_min_age, u_min_age); - init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, - password_properties, nt_expire, nt_min_age); + init_samr_DomInfo1(policy, + (uint16)min_pass_len, + (uint16)pass_hist, + password_properties, + nt_expire, + nt_min_age); return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c index a1f96a0359..25debccc5a 100644 --- a/source3/winbindd/winbindd_reconnect.c +++ b/source3/winbindd/winbindd_reconnect.c @@ -247,7 +247,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) /* find the lockout policy of a domain */ static NTSTATUS lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_12 *policy) + struct samr_DomInfo12 *policy) { NTSTATUS result; @@ -262,7 +262,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain, /* find the password policy of a domain */ static NTSTATUS password_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_1 *policy) + struct samr_DomInfo1 *policy) { NTSTATUS result; diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index a318199b62..98e4077a4d 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -884,7 +884,7 @@ static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq) static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { TALLOC_CTX *mem_ctx; - SAM_UNK_CTR ctr; + union samr_DomainInfo *info = NULL; NTSTATUS result; POLICY_HND dom_pol; bool got_seq_num = False; @@ -935,21 +935,27 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) /* Query domain info */ - result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr); + result = rpccli_samr_QueryDomainInfo(cli, mem_ctx, + &dom_pol, + 8, + &info); if (NT_STATUS_IS_OK(result)) { - *seq = ctr.info.inf8.seq_num; + *seq = info->info8.sequence_num; got_seq_num = True; goto seq_num; } /* retry with info-level 2 in case the dc does not support info-level 8 - * (like all older samba2 and samba3 dc's - Guenther */ + * (like all older samba2 and samba3 dc's) - Guenther */ + + result = rpccli_samr_QueryDomainInfo(cli, mem_ctx, + &dom_pol, + 2, + &info); - result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr); - if (NT_STATUS_IS_OK(result)) { - *seq = ctr.info.inf2.seq_num; + *seq = info->info2.sequence_num; got_seq_num = True; } @@ -1033,14 +1039,14 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, } /* find the lockout policy for a domain */ -NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, +NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_12 *lockout_policy) + struct samr_DomInfo12 *lockout_policy) { NTSTATUS result; struct rpc_pipe_client *cli; POLICY_HND dom_pol; - SAM_UNK_CTR ctr; + union samr_DomainInfo *info = NULL; DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name)); @@ -1055,15 +1061,18 @@ NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, goto done; } - result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr); + result = rpccli_samr_QueryDomainInfo(cli, mem_ctx, + &dom_pol, + 12, + &info); if (!NT_STATUS_IS_OK(result)) { goto done; } - *lockout_policy = ctr.info.inf12; + *lockout_policy = info->info12; - DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", - ctr.info.inf12.bad_attempt_lockout)); + DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n", + info->info12.lockout_threshold)); done: @@ -1071,14 +1080,14 @@ NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, } /* find the password policy for a domain */ -NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, +NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - SAM_UNK_INFO_1 *password_policy) + struct samr_DomInfo1 *password_policy) { NTSTATUS result; struct rpc_pipe_client *cli; POLICY_HND dom_pol; - SAM_UNK_CTR ctr; + union samr_DomainInfo *info = NULL; DEBUG(10,("rpc: fetch password policy for %s\n", domain->name)); @@ -1093,15 +1102,18 @@ NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, goto done; } - result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr); + result = rpccli_samr_QueryDomainInfo(cli, mem_ctx, + &dom_pol, + 1, + &info); if (!NT_STATUS_IS_OK(result)) { goto done; } - *password_policy = ctr.info.inf1; + *password_policy = info->info1; - DEBUG(10,("msrpc_password_policy: min_length_password %d\n", - ctr.info.inf1.min_length_password)); + DEBUG(10,("msrpc_password_policy: min_length_password %d\n", + info->info1.min_password_length)); done: -- cgit From 9c22a27aadd191d68a34dc2289f3d92dddf42d11 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 5 Feb 2008 20:14:54 +0100 Subject: Let rpccli_samr_chgpasswd3 use rpccli_samr_ChangePasswordUser3 internally. Guenther (This used to be commit ffbfd19ad7065caf05688c5748178d30115d47f4) --- source3/winbindd/winbindd_pam.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c1a277f9b5..759adb366e 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1936,8 +1936,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact POLICY_HND dom_pol; struct rpc_pipe_client *cli; bool got_info = False; - SAM_UNK_INFO_1 info; - SAMR_CHANGE_REJECT reject; + struct samr_DomInfo1 *info = NULL; + struct samr_ChangeReject *reject = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring domain, user; @@ -1965,24 +1965,29 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject); + result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, + user, + newpass, + oldpass, + &info, + &reject); /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { - state->response.data.auth.policy.min_length_password = - info.min_length_password; - state->response.data.auth.policy.password_history = - info.password_history; - state->response.data.auth.policy.password_properties = - info.password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs(&info.expire); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs(&info.min_passwordage); - - state->response.data.auth.reject_reason = - reject.reject_reason; + state->response.data.auth.policy.min_length_password = + info->min_password_length; + state->response.data.auth.policy.password_history = + info->password_history_length; + state->response.data.auth.policy.password_properties = + info->password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs((NTTIME *)&info->max_password_age); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&info->min_password_age); + + state->response.data.auth.reject_reason = + reject->reason; got_info = True; } -- cgit From bca0ef0ed769bfbee6e7041aae8256be872813c7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 7 Feb 2008 10:24:18 +0100 Subject: Use rpccli_netr_GetAnyDCName and rpccli_netr_GetDCName everywhere. Guenther (This used to be commit 8abeea9922ac09e7307730ee7695453718356873) --- source3/winbindd/winbindd_cm.c | 30 ++++++++++++++++++------------ source3/winbindd/winbindd_misc.c | 30 ++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 22 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 7bc449c90d..17afd1e3eb 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -570,8 +570,8 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, WERROR werr; TALLOC_CTX *mem_ctx; unsigned int orig_timeout; - char *tmp = NULL; - char *p; + const char *tmp = NULL; + const char *p; /* Hmmmm. We can only open one connection to the NETLOGON pipe at the * moment.... */ @@ -630,25 +630,31 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, } } } else { - - werr = rpccli_netlogon_getanydcname(netlogon_pipe, - mem_ctx, - our_domain->dcname, - domain->name, - &tmp); + result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx, + our_domain->dcname, + domain->name, + &tmp, + &werr); } /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n", + nt_errstr(result))); + talloc_destroy(mem_ctx); + return false; + } + if (!W_ERROR_IS_OK(werr)) { - DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n", + DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n", dos_errstr(werr))); talloc_destroy(mem_ctx); - return False; + return false; } - /* cli_netlogon_getanydcname gives us a name with \\ */ + /* rpccli_netr_GetAnyDCName gives us a name with \\ */ p = tmp; if (*p == '\\') { p+=1; @@ -661,7 +667,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, talloc_destroy(mem_ctx); - DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname)); + DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname)); if (!resolve_name(dcname, dc_ss, 0x20)) { return False; diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 76f2554122..c22da3e8ef 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -231,8 +231,8 @@ void winbindd_getdcname(struct winbindd_cli_state *state) enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, struct winbindd_cli_state *state) { - char *dcname_slash = NULL; - char *p; + const char *dcname_slash = NULL; + const char *p; struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; WERROR werr; @@ -259,19 +259,29 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, req_domain = find_domain_from_name_noinit(state->request.domain_name); if (req_domain == domain) { - werr = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, - domain->dcname, - state->request.domain_name, - &dcname_slash); + result = rpccli_netr_GetDcName(netlogon_pipe, + state->mem_ctx, + domain->dcname, + state->request.domain_name, + &dcname_slash, + &werr); } else { - werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, - domain->dcname, - state->request.domain_name, - &dcname_slash); + result = rpccli_netr_GetAnyDCName(netlogon_pipe, + state->mem_ctx, + domain->dcname, + state->request.domain_name, + &dcname_slash, + &werr); } /* And restore our original timeout. */ cli_set_timeout(netlogon_pipe->cli, orig_timeout); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(5,("Error requesting DCname for domain %s: %s\n", + state->request.domain_name, nt_errstr(result))); + return WINBINDD_ERROR; + } + if (!W_ERROR_IS_OK(werr)) { DEBUG(5, ("Error requesting DCname for domain %s: %s\n", state->request.domain_name, dos_errstr(werr))); -- cgit From 1c788bc36561842d08c3f62b5d3145dbe74db620 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 6 Feb 2008 16:19:20 +0100 Subject: Use rpccli_samr_GetGroupsForUser() all over the place. Guenther (This used to be commit d1c669920e88e7fecd13101c4ddfe45354c5ecdb) --- source3/winbindd/winbindd_rpc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 98e4077a4d..8e196e50ec 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -510,7 +510,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - DOM_GID *user_groups; + struct samr_RidWithAttributeArray *rid_array = NULL; unsigned int i; uint32 user_rid; struct rpc_pipe_client *cli; @@ -557,8 +557,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return result; /* Query user rids */ - result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, - num_groups, &user_groups); + result = rpccli_samr_GetGroupsForUser(cli, mem_ctx, + &user_pol, + &rid_array); + *num_groups = rid_array->count; rpccli_samr_Close(cli, mem_ctx, &user_pol); @@ -572,9 +574,9 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, for (i=0;i<(*num_groups);i++) { sid_copy(&((*user_grpsids)[i]), &domain->sid); sid_append_rid(&((*user_grpsids)[i]), - user_groups[i].g_rid); + rid_array->rids[i].rid); } - + return NT_STATUS_OK; } -- cgit From 781776d8643ba649a3c52978ff7e07511b43572d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 7 Feb 2008 20:46:02 +0100 Subject: Use rpccli_samr_QueryDisplayInfo() all over the place. Guenther (This used to be commit 66b79add353bf7a09f304eac5274cb89b23d7b06) --- source3/winbindd/winbindd_rpc.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 8e196e50ec..edcdd5f049 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -63,24 +63,26 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, do { uint32 num_dom_users, j; uint32 max_entries, max_size; - SAM_DISPINFO_CTR ctr; - SAM_DISPINFO_1 info1; + uint32_t total_size, returned_size; - ZERO_STRUCT( ctr ); - ZERO_STRUCT( info1 ); - ctr.sam.info1 = &info1; + union samr_DispInfo disp_info; /* this next bit is copied from net_user_list_internal() */ get_query_dispinfo_params(loop_count, &max_entries, &max_size); - result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol, - &start_idx, 1, - &num_dom_users, - max_entries, max_size, - &ctr); - + result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx, + &dom_pol, + 1, + start_idx, + max_entries, + max_size, + &total_size, + &returned_size, + &disp_info); + num_dom_users = disp_info.info1.count; + start_idx += disp_info.info1.count; loop_count++; *num_entries += num_dom_users; @@ -93,14 +95,13 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, } for (j = 0; j < num_dom_users; i++, j++) { - fstring username, fullname; - uint32 rid = ctr.sam.info1->sam[j].rid_user; - - unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)); - unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)); - - (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); - (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); + + uint32_t rid = disp_info.info1.entries[j].rid; + + (*info)[i].acct_name = talloc_strdup(mem_ctx, + disp_info.info1.entries[j].account_name.string); + (*info)[i].full_name = talloc_strdup(mem_ctx, + disp_info.info1.entries[j].full_name.string); (*info)[i].homedir = NULL; (*info)[i].shell = NULL; sid_compose(&(*info)[i].user_sid, &domain->sid, rid); -- cgit From ec9281fcacf5eaad2271d6956fe55308ec378a16 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 8 Feb 2008 01:52:27 +0100 Subject: Use rpccli_lsa_QueryInfoPolicy2 in winbindd. Guenther (This used to be commit ccf79cfa88c7f3a10d191f8f0eedb9d421c65f6c) --- source3/winbindd/winbindd_cm.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 17afd1e3eb..ea48dbde72 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1839,11 +1839,9 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) union dssetup_DsRoleInfo info; const char *domain_name = NULL; - const char *dns_name = NULL; - const char *forest_name = NULL; - DOM_SID *dom_sid = NULL; + DOM_SID *dom_sid = NULL; + union lsa_PolicyInformation *lsa_info = NULL; - if (!connection_ok(domain)) { return; } @@ -1921,34 +1919,39 @@ no_dssetup: if (NT_STATUS_IS_OK(result)) { /* This particular query is exactly what Win2k clients use to determine that the DC is active directory */ - result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol, - 12, &domain_name, - &dns_name, &forest_name, - NULL, &dom_sid); + result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx, + &pol, + LSA_POLICY_INFO_DNS, + &lsa_info); } if (NT_STATUS_IS_OK(result)) { domain->active_directory = True; - if (domain_name) - fstrcpy(domain->name, domain_name); + if (lsa_info->dns.name.string) { + fstrcpy(domain->name, lsa_info->dns.name.string); + } - if (dns_name) - fstrcpy(domain->alt_name, dns_name); + if (lsa_info->dns.dns_domain.string) { + fstrcpy(domain->alt_name, + lsa_info->dns.dns_domain.string); + } /* See if we can set some domain trust flags about ourself */ - if ( forest_name ) { - fstrcpy(domain->forest_name, forest_name); + if (lsa_info->dns.dns_forest.string) { + fstrcpy(domain->forest_name, + lsa_info->dns.dns_forest.string); if (strequal(domain->forest_name, domain->alt_name)) { domain->domain_flags = NETR_TRUST_FLAG_TREEROOT; } } - if (dom_sid) - sid_copy(&domain->sid, dom_sid); + if (lsa_info->dns.sid) { + sid_copy(&domain->sid, lsa_info->dns.sid); + } } else { domain->active_directory = False; -- cgit From 7520439dcac47bc60a8d5526f4acb834f177fec9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 8 Feb 2008 02:12:30 +0100 Subject: Use rpccli_lsa_QueryInfoPolicy() all over the place. Guenther (This used to be commit ce22abcea3446e4ad42e8e04654b9855b173c5a1) --- source3/winbindd/winbindd_cm.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ea48dbde72..dbdab65f70 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1837,9 +1837,6 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) struct rpc_pipe_client *cli; POLICY_HND pol; union dssetup_DsRoleInfo info; - - const char *domain_name = NULL; - DOM_SID *dom_sid = NULL; union lsa_PolicyInformation *lsa_info = NULL; if (!connection_ok(domain)) { @@ -1958,20 +1955,26 @@ no_dssetup: result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); - - if (!NT_STATUS_IS_OK(result)) + + if (!NT_STATUS_IS_OK(result)) { goto done; - - result = rpccli_lsa_query_info_policy(cli, mem_ctx, - &pol, 5, &domain_name, - &dom_sid); - + } + + result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx, + &pol, + LSA_POLICY_INFO_ACCOUNT_DOMAIN, + &lsa_info); + if (NT_STATUS_IS_OK(result)) { - if (domain_name) - fstrcpy(domain->name, domain_name); - if (dom_sid) - sid_copy(&domain->sid, dom_sid); + if (lsa_info->account_domain.name.string) { + fstrcpy(domain->name, + lsa_info->account_domain.name.string); + } + + if (lsa_info->account_domain.sid) { + sid_copy(&domain->sid, lsa_info->account_domain.sid); + } } } done: -- cgit From 7329bd24f97688597d5c61dcf00fb39f302654fe Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 8 Feb 2008 10:59:31 +0100 Subject: Fix winbindd msrpc_lookup_useraliases. Guenther (This used to be commit e196e527ae47a75f6cac09b9f89aa5619047d4d2) --- source3/winbindd/winbindd_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index edcdd5f049..fa9c1bc58d 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -633,7 +633,7 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, for (i=0; i Date: Fri, 8 Feb 2008 23:28:02 +0100 Subject: Use rpccli_netr_DsRGetDCName() in rpcclient and winbindd. Guenther (This used to be commit 4f3e97cbae3df8e12db37b8a8a0eaee947fa723a) --- source3/winbindd/winbindd_cm.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index dbdab65f70..0f536cdfb8 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -602,19 +602,20 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); if (our_domain->active_directory) { - struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL; - - werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe, - mem_ctx, - our_domain->dcname, - domain->name, - NULL, - NULL, - DS_RETURN_DNS_NAME, - &domain_info); + struct netr_DsRGetDCNameInfo *domain_info = NULL; + + result = rpccli_netr_DsRGetDCName(netlogon_pipe, + mem_ctx, + our_domain->dcname, + domain->name, + NULL, + NULL, + DS_RETURN_DNS_NAME, + &domain_info, + &werr); if (W_ERROR_IS_OK(werr)) { tmp = talloc_strdup( - mem_ctx, domain_info->domain_controller_name); + mem_ctx, domain_info->dc_unc); if (tmp == NULL) { DEBUG(0, ("talloc_strdup failed\n")); talloc_destroy(mem_ctx); @@ -626,7 +627,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, } if (strlen(domain->forest_name) == 0) { fstrcpy(domain->forest_name, - domain_info->dns_forest_name); + domain_info->forest_name); } } } else { -- cgit From 4c42f7999a876db0ec7e93f60354ef51290ad11e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 12 Feb 2008 18:13:30 +0100 Subject: Use rpccli_samr_QueryUserInfo in net and winbindd. Guenther (This used to be commit a9ff6760901a489ff8877717bdd5a2218154498f) --- source3/winbindd/winbindd_pam.c | 12 ++++++------ source3/winbindd/winbindd_rpc.c | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 759adb366e..dd27ad62f3 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1324,12 +1324,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; - SAM_USERINFO_CTR *user_ctr; + union samr_UserInfo *info = NULL; NTSTATUS status_tmp; uint32 acct_flags; - ZERO_STRUCT(user_ctr); - status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, &samr_pipe, &samr_domain_handle); @@ -1351,8 +1349,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx, - &user_pol, 16, &user_ctr); + status_tmp = rpccli_samr_QueryUserInfo(samr_pipe, state->mem_ctx, + &user_pol, + 16, + &info); if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not query user info on SAMR pipe: %s\n", @@ -1361,7 +1361,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - acct_flags = user_ctr->info.id16->acb_info; + acct_flags = info->info16.acct_flags; if (acct_flags == 0) { rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index fa9c1bc58d..2703f2f64a 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -409,7 +409,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; - SAM_USERINFO_CTR *ctr; + union samr_UserInfo *info = NULL; uint32 user_rid; NET_USER_INFO_3 *user; struct rpc_pipe_client *cli; @@ -480,8 +480,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain, return result; /* Get user info */ - result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, - 0x15, &ctr); + result = rpccli_samr_QueryUserInfo(cli, mem_ctx, + &user_pol, + 0x15, + &info); rpccli_samr_Close(cli, mem_ctx, &user_pol); @@ -490,11 +492,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain, sid_compose(&user_info->user_sid, &domain->sid, user_rid); sid_compose(&user_info->group_sid, &domain->sid, - ctr->info.id21->group_rid); - user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, - &ctr->info.id21->uni_user_name); - user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, - &ctr->info.id21->uni_full_name); + info->info21.primary_gid); + user_info->acct_name = talloc_strdup(mem_ctx, + info->info21.account_name.string); + user_info->full_name = talloc_strdup(mem_ctx, + info->info21.full_name.string); user_info->homedir = NULL; user_info->shell = NULL; user_info->primary_gid = (gid_t)-1; -- cgit From 0ba3d44f7321cb235eb214194395d5da02824690 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Feb 2008 00:25:40 +0100 Subject: Use rpccli_lsa_EnumTrustDom all over the place. Guenther (This used to be commit a25e7ffbca9c2c97dd36b0596e7cb38a72aaf9d9) --- source3/winbindd/winbindd_rpc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 2703f2f64a..326ff61122 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -1008,22 +1008,24 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, result = STATUS_MORE_ENTRIES; while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { - uint32 start_idx, num; + uint32 start_idx; char **tmp_names; DOM_SID *tmp_sids; int i; + struct lsa_DomainList dom_list; - result = rpccli_lsa_enum_trust_dom(cli, mem_ctx, - &lsa_policy, &enum_ctx, - &num, &tmp_names, - &tmp_sids); + result = rpccli_lsa_EnumTrustDom(cli, mem_ctx, + &lsa_policy, + &enum_ctx, + &dom_list, + (uint32_t)-1); if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break; start_idx = *num_domains; - *num_domains += num; + *num_domains += dom_list.count; *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names, char *, *num_domains); *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids, @@ -1035,8 +1037,8 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; for (i=0; i Date: Wed, 13 Feb 2008 01:29:52 +0100 Subject: Fix the build of winbindd, sorry. Guenther (This used to be commit c62c89c8f0d1ff8e384b88b3b192aa96f0b2183e) --- source3/winbindd/winbindd_rpc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 326ff61122..473d2a52a4 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -1009,8 +1009,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { uint32 start_idx; - char **tmp_names; - DOM_SID *tmp_sids; int i; struct lsa_DomainList dom_list; @@ -1036,9 +1034,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, (*alt_names == NULL)) return NT_STATUS_NO_MEMORY; - for (i=0; i Date: Mon, 11 Feb 2008 18:35:58 +0100 Subject: nsswitch: convert winbind_env_set(), winbind_on() and winbind_off() into macros metze (This used to be commit 5f623f54a919cc687d0ff16c16038c05a501008d) --- source3/winbindd/idmap_nss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index 46c24d7fcb..e4acd9ce65 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -87,10 +87,10 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma /* by default calls to winbindd are disabled the following call will not recurse so this is safe */ - winbind_on(); + (void)winbind_on(); /* Lookup name from PDC using lsa_lookup_names() */ ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type); - winbind_off(); + (void)winbind_off(); if (!ret) { /* TODO: how do we know if the name is really not mapped, @@ -153,9 +153,9 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma /* by default calls to winbindd are disabled the following call will not recurse so this is safe */ - winbind_on(); + (void)winbind_on(); ret = winbind_lookup_sid(ctx, ids[i]->sid, &dom_name, &name, &type); - winbind_off(); + (void)winbind_off(); if (!ret) { /* TODO: how do we know if the name is really not mapped, -- cgit From cdc07216e40df1198e9f3378fc9b23b4c8dfabdc Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Feb 2008 10:49:55 +0100 Subject: Convert last caller (in winbindd) to rpccli_samr_LookupRids. Guenther (This used to be commit 34c2566f026dbde4da10e2fc10c6960260eb6044) --- source3/winbindd/winbindd_rpc.c | 48 +++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 473d2a52a4..8136175efe 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -693,7 +693,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; uint32 *rid_mem = NULL; uint32 group_rid; - unsigned int j; + unsigned int j, r; struct rpc_pipe_client *cli; unsigned int orig_timeout; struct samr_RidTypeArray *rids = NULL; @@ -772,38 +772,40 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, if (*num_names>0 && (!*names || !*name_types)) return NT_STATUS_NO_MEMORY; - for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { - int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); - uint32 tmp_num_names = 0; - char **tmp_names = NULL; - uint32 *tmp_types = NULL; + for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { + int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); + struct lsa_Strings tmp_names; + struct samr_Ids tmp_types; - /* Lookup a chunk of rids */ + /* Lookup a chunk of rids */ - result = rpccli_samr_lookup_rids(cli, mem_ctx, - &dom_pol, - num_lookup_rids, - &rid_mem[i], - &tmp_num_names, - &tmp_names, &tmp_types); + result = rpccli_samr_LookupRids(cli, mem_ctx, + &dom_pol, + num_lookup_rids, + &rid_mem[i], + &tmp_names, + &tmp_types); /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is the one returned from 2k) */ - + if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) return result; - - /* Copy result into array. The talloc system will take - care of freeing the temporary arrays later on. */ - memcpy(&(*names)[i], tmp_names, sizeof(char *) * - tmp_num_names); + /* Copy result into array. The talloc system will take + care of freeing the temporary arrays later on. */ - memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * - tmp_num_names); - - total_names += tmp_num_names; + if (tmp_names.count != tmp_types.count) { + return NT_STATUS_UNSUCCESSFUL; + } + + for (r=0; r Date: Wed, 13 Feb 2008 11:08:49 +0100 Subject: Convert last caller (in winbindd) to rpccli_samr_EnumDomainGroups. Guenther (This used to be commit 8890bc481f60cd42d96b240b2ed8e34bc3d81f13) --- source3/winbindd/winbindd_rpc.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 8136175efe..53928225fa 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -150,19 +150,22 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, return status; do { - struct acct_info *info2 = NULL; + struct samr_SamArray *sam_array = NULL; uint32 count = 0; TALLOC_CTX *mem_ctx2; + int g; mem_ctx2 = talloc_init("enum_dom_groups[rpc]"); /* start is updated by this call. */ - status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol, - &start, - 0xFFFF, /* buffer size? */ - &info2, &count); + status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2, + &dom_pol, + &start, + &sam_array, + 0xFFFF, /* buffer size? */ + &count); - if (!NT_STATUS_IS_OK(status) && + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { talloc_destroy(mem_ctx2); break; @@ -176,7 +179,13 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); + for (g=0; g < count; g++) { + + fstrcpy((*info)[*num_entries + g].acct_name, + sam_array->entries[g].name.string); + (*info)[*num_entries + g].rid = sam_array->entries[g].idx; + } + (*num_entries) += count; talloc_destroy(mem_ctx2); } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); -- cgit From ce7d5975b48e538779c5bd10f45677b0ea23ae80 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Feb 2008 11:15:40 +0100 Subject: Convert last caller (in winbindd) to rpccli_samr_EnumDomainAliases. Guenther (This used to be commit 33a97b447c1875bf1cd5a703871a84a7fb359fec) --- source3/winbindd/winbindd_rpc.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 53928225fa..585923410f 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -220,18 +220,21 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, return result; do { - struct acct_info *info2 = NULL; + struct samr_SamArray *sam_array = NULL; uint32 count = 0, start = *num_entries; TALLOC_CTX *mem_ctx2; + int g; mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]"); - result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol, - &start, 0xFFFF, &info2, - &count); - + result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2, + &dom_pol, + &start, + &sam_array, + 0xFFFF, /* buffer size? */ + &count); if (!NT_STATUS_IS_OK(result) && - !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) + !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) { talloc_destroy(mem_ctx2); return result; @@ -245,7 +248,13 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); + for (g=0; g < count; g++) { + + fstrcpy((*info)[*num_entries + g].acct_name, + sam_array->entries[g].name.string); + (*info)[*num_entries + g].rid = sam_array->entries[g].idx; + } + (*num_entries) += count; talloc_destroy(mem_ctx2); -- cgit From 3649f728ed3a449622c4e1dbc3ebf4c3536b72f7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Jan 2008 08:43:45 +0100 Subject: winbindd: add rids and other_sids arrays in WBFLAG_PAM_INFO3_TEXT mode metze (This used to be commit c5e6dd1ca9611e2830ff773875998c01bf779a64) --- source3/winbindd/winbindd_pam.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index dd27ad62f3..e3574bbcd6 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -31,6 +31,10 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, NET_USER_INFO_3 *info3) { + char *ex; + size_t size; + uint32_t i; + state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); state->response.data.auth.info3.logoff_time = @@ -83,6 +87,42 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); + ex = talloc_strdup(mem_ctx, ""); + NT_STATUS_HAVE_NO_MEMORY(ex); + + for (i=0; i < info3->num_groups; i++) { + ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n", + info3->gids[i].g_rid, + info3->gids[i].attr); + NT_STATUS_HAVE_NO_MEMORY(ex); + } + + for (i=0; i < info3->num_other_sids; i++) { + char *sid; + + sid = dom_sid_string(mem_ctx, &info3->other_sids[i].sid); + NT_STATUS_HAVE_NO_MEMORY(sid); + + ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n", + sid, + info3->other_sids_attrib[i]); + NT_STATUS_HAVE_NO_MEMORY(ex); + + talloc_free(sid); + } + + size = talloc_get_size(ex); + + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_MALLOC(size); + if (!state->response.extra_data.data) { + return NT_STATUS_NO_MEMORY; + } + memcpy(state->response.extra_data.data, ex, size); + talloc_free(ex); + + state->response.length += size; + return NT_STATUS_OK; } @@ -703,16 +743,18 @@ static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | WBFLAG_PAM_UNIX_NAME | + WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_INFO3_NDR; if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || + ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || !(flags & flags_edata) ) { return True; } - DEBUG(1,("check_request_flags: invalid request flags\n")); + DEBUG(1,("check_request_flags: invalid request flags[0x%08X]\n",flags)); return False; } -- cgit From c6f82f1cc4a08138e5b78d1504ac4f9ea44f81ee Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 02:04:52 +0100 Subject: Getting rid of net_io_user_info3() when sending an NDR encoded netr_SamInfo3. Guenther (This used to be commit f22ba8aee2ff90e9e34db066d506fec24c52379f) --- source3/winbindd/winbindd_pam.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index e3574bbcd6..ad87fd2c67 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -128,29 +128,31 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *info3) { - prs_struct ps; - uint32 size; - if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { - prs_mem_free(&ps); - return NT_STATUS_UNSUCCESSFUL; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3, + (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("append_info3_as_ndr: failed to append\n")); + return ndr_map_error2ntstatus(ndr_err); } - size = prs_data_size(&ps); SAFE_FREE(state->response.extra_data.data); - state->response.extra_data.data = SMB_MALLOC(size); + state->response.extra_data.data = SMB_MALLOC(blob.length); if (!state->response.extra_data.data) { - prs_mem_free(&ps); + data_blob_free(&blob); return NT_STATUS_NO_MEMORY; } - memset( state->response.extra_data.data, '\0', size ); - prs_copy_all_data_out((char *)state->response.extra_data.data, &ps); - state->response.length += size; - prs_mem_free(&ps); + + memset(state->response.extra_data.data, '\0', blob.length); + memcpy(state->response.extra_data.data, blob.data, blob.length); + state->response.length += blob.length; + + data_blob_free(&blob); + return NT_STATUS_OK; } -- cgit From c25958a046bbcfc13db200430e505ac4ee9b3f27 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 02:08:12 +0100 Subject: Use netr_SamInfo3 everywhere in winbindd. Guenther (This used to be commit d9502eb75395131d5a8130ff2c4ebace106cb974) --- source3/winbindd/winbindd_ads.c | 10 +- source3/winbindd/winbindd_cache.c | 2 +- source3/winbindd/winbindd_creds.c | 14 +-- source3/winbindd/winbindd_pam.c | 203 +++++++++++++++++--------------------- source3/winbindd/winbindd_rpc.c | 14 +-- source3/winbindd/winbindd_util.c | 18 ++-- 6 files changed, 122 insertions(+), 139 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index db7ceca04d..0900d56987 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -421,7 +421,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, char *sidstr; uint32 group_rid; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - NET_USER_INFO_3 *user; + struct netr_SamInfo3 *user = NULL; DEBUG(3,("ads: query_user\n")); @@ -437,11 +437,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain, DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_dbg(sid))); - sid_compose(&info->user_sid, &domain->sid, user->user_rid); - sid_compose(&info->group_sid, &domain->sid, user->group_rid); + sid_compose(&info->user_sid, &domain->sid, user->base.rid); + sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid); - info->acct_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_user_name); - info->full_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_full_name); + info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string); + info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string); nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, &info->homedir, &info->shell, &info->full_name, diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index f235e401e8..4d81ee3960 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2248,7 +2248,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, /* Invalidate the getpwnam and getgroups entries for a winbindd domain */ void wcache_invalidate_samlogon(struct winbindd_domain *domain, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *info3) { struct winbind_cache *cache; diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c index 4dbace5bcc..9c7acd64e6 100644 --- a/source3/winbindd/winbindd_creds.c +++ b/source3/winbindd/winbindd_creds.c @@ -29,11 +29,11 @@ NTSTATUS winbindd_get_creds(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, - NET_USER_INFO_3 **info3, + struct netr_SamInfo3 **info3, const uint8 *cached_nt_pass[NT_HASH_LEN], const uint8 *cred_salt[NT_HASH_LEN]) { - NET_USER_INFO_3 *info; + struct netr_SamInfo3 *info; NTSTATUS status; status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass, cred_salt); @@ -56,7 +56,7 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *user, const char *pass, - NET_USER_INFO_3 *info3, + struct netr_SamInfo3 *info3, const DOM_SID *user_sid) { NTSTATUS status; @@ -66,10 +66,10 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, if (info3 != NULL) { DOM_SID sid; - sid_copy(&sid, &(info3->dom_sid.sid)); - sid_append_rid(&sid, info3->user_rid); + sid_copy(&sid, info3->base.domain_sid); + sid_append_rid(&sid, info3->base.rid); sid_copy(&cred_sid, &sid); - info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; + info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; } else if (user_sid != NULL) { @@ -138,7 +138,7 @@ NTSTATUS winbindd_update_creds_by_info3(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *user, const char *pass, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *info3) { return winbindd_store_creds(domain, mem_ctx, user, pass, info3, NULL); } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ad87fd2c67..79b4c764c3 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -29,83 +29,75 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *info3) { char *ex; size_t size; uint32_t i; state->response.data.auth.info3.logon_time = - nt_time_to_unix(info3->logon_time); + nt_time_to_unix(info3->base.last_logon); state->response.data.auth.info3.logoff_time = - nt_time_to_unix(info3->logoff_time); + nt_time_to_unix(info3->base.last_logoff); state->response.data.auth.info3.kickoff_time = - nt_time_to_unix(info3->kickoff_time); + nt_time_to_unix(info3->base.acct_expiry); state->response.data.auth.info3.pass_last_set_time = - nt_time_to_unix(info3->pass_last_set_time); + nt_time_to_unix(info3->base.last_password_change); state->response.data.auth.info3.pass_can_change_time = - nt_time_to_unix(info3->pass_can_change_time); + nt_time_to_unix(info3->base.allow_password_change); state->response.data.auth.info3.pass_must_change_time = - nt_time_to_unix(info3->pass_must_change_time); - - state->response.data.auth.info3.logon_count = info3->logon_count; - state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count; - - state->response.data.auth.info3.user_rid = info3->user_rid; - state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid)); - - state->response.data.auth.info3.num_groups = info3->num_groups; - state->response.data.auth.info3.user_flgs = info3->user_flgs; - - state->response.data.auth.info3.acct_flags = info3->acct_flags; - state->response.data.auth.info3.num_other_sids = info3->num_other_sids; - - unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, - sizeof(state->response.data.auth.info3.user_name)); - unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, - sizeof(state->response.data.auth.info3.full_name)); - unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, - sizeof(state->response.data.auth.info3.logon_script)); - unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, - sizeof(state->response.data.auth.info3.profile_path)); - unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, - sizeof(state->response.data.auth.info3.home_dir)); - unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, - sizeof(state->response.data.auth.info3.dir_drive)); - - unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, - sizeof(state->response.data.auth.info3.logon_srv)); - unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, - sizeof(state->response.data.auth.info3.logon_dom)); + nt_time_to_unix(info3->base.force_password_change); + + state->response.data.auth.info3.logon_count = info3->base.logon_count; + state->response.data.auth.info3.bad_pw_count = info3->base.bad_password_count; + + state->response.data.auth.info3.user_rid = info3->base.rid; + state->response.data.auth.info3.group_rid = info3->base.primary_gid; + sid_to_fstring(state->response.data.auth.info3.dom_sid, info3->base.domain_sid); + + state->response.data.auth.info3.num_groups = info3->base.groups.count; + state->response.data.auth.info3.user_flgs = info3->base.user_flags; + + state->response.data.auth.info3.acct_flags = info3->base.acct_flags; + state->response.data.auth.info3.num_other_sids = info3->sidcount; + + fstrcpy(state->response.data.auth.info3.user_name, + info3->base.account_name.string); + fstrcpy(state->response.data.auth.info3.full_name, + info3->base.full_name.string); + fstrcpy(state->response.data.auth.info3.logon_script, + info3->base.logon_script.string); + fstrcpy(state->response.data.auth.info3.profile_path, + info3->base.profile_path.string); + fstrcpy(state->response.data.auth.info3.home_dir, + info3->base.home_directory.string); + fstrcpy(state->response.data.auth.info3.dir_drive, + info3->base.home_drive.string); + + fstrcpy(state->response.data.auth.info3.logon_srv, + info3->base.logon_server.string); + fstrcpy(state->response.data.auth.info3.logon_dom, + info3->base.domain.string); ex = talloc_strdup(mem_ctx, ""); NT_STATUS_HAVE_NO_MEMORY(ex); - for (i=0; i < info3->num_groups; i++) { + for (i=0; i < info3->base.groups.count; i++) { ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n", - info3->gids[i].g_rid, - info3->gids[i].attr); + info3->base.groups.rids[i].rid, + info3->base.groups.rids[i].attributes); NT_STATUS_HAVE_NO_MEMORY(ex); } - for (i=0; i < info3->num_other_sids; i++) { + for (i=0; i < info3->sidcount; i++) { char *sid; - sid = dom_sid_string(mem_ctx, &info3->other_sids[i].sid); + sid = dom_sid_string(mem_ctx, info3->sids[i].sid); NT_STATUS_HAVE_NO_MEMORY(sid); ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n", sid, - info3->other_sids_attrib[i]); + info3->sids[i].attributes); NT_STATUS_HAVE_NO_MEMORY(ex); talloc_free(sid); @@ -158,7 +150,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - const NET_USER_INFO_3 *info3, + const struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -168,15 +160,15 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, fstring username_out; const char *nt_username, *nt_domain; - if (!(nt_domain = unistr2_to_ascii_talloc(mem_ctx, - &info3->uni_logon_dom))) { + nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string); + if (!nt_domain) { /* If the server didn't give us one, just use the one * we sent them */ nt_domain = name_domain; } - if (!(nt_username = unistr2_to_ascii_talloc(mem_ctx, - &info3->uni_user_name))) { + nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string); + if (!nt_username) { /* If the server didn't give us one, just use the one * we sent them */ nt_username = name_user; @@ -200,7 +192,7 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - const NET_USER_INFO_3 *info3, + const struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -224,8 +216,8 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, DOM_SID user_sid; fstring sidstr; - sid_copy(&user_sid, &info3->dom_sid.sid); - sid_append_rid(&user_sid, info3->user_rid); + sid_copy(&user_sid, info3->base.domain_sid); + sid_append_rid(&user_sid, info3->base.rid); sid_to_fstring(sidstr, &user_sid); afsname = talloc_string_sub(mem_ctx, afsname, "%s", sidstr); @@ -262,7 +254,7 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, } static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, - NET_USER_INFO_3 *info3, + struct netr_SamInfo3 *info3, const char *group_sid) /** * Check whether a user belongs to a group or list of groups. @@ -576,7 +568,7 @@ static uid_t get_uid_from_state(struct winbindd_cli_state *state) static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { #ifdef HAVE_KRB5 NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -765,7 +757,7 @@ static bool check_request_flags(uint32_t flags) ****************************************************************/ static NTSTATUS append_data(struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3, + struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -774,14 +766,14 @@ static NTSTATUS append_data(struct winbindd_cli_state *state, if (flags & WBFLAG_PAM_USER_SESSION_KEY) { memcpy(state->response.data.auth.user_session_key, - info3->user_sess_key, + info3->base.key.key, sizeof(state->response.data.auth.user_session_key) /* 16 */); } if (flags & WBFLAG_PAM_LMKEY) { memcpy(state->response.data.auth.first_8_lm_hash, - info3->lm_sess_key, + info3->base.LMSessKey.key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } @@ -882,7 +874,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; uint16 max_allowed_bad_attempts; @@ -892,7 +884,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, uchar new_nt_pass[NT_HASH_LEN]; const uint8 *cached_nt_pass; const uint8 *cached_salt; - NET_USER_INFO_3 *my_info3; + struct netr_SamInfo3 *my_info3; time_t kickoff_time, must_change_time; bool password_good = False; #ifdef HAVE_KRB5 @@ -964,43 +956,43 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - my_info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; + my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; - if (my_info3->acct_flags & ACB_AUTOLOCK) { + if (my_info3->base.acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; } - if (my_info3->acct_flags & ACB_DISABLED) { + if (my_info3->base.acct_flags & ACB_DISABLED) { return NT_STATUS_ACCOUNT_DISABLED; } - if (my_info3->acct_flags & ACB_WSTRUST) { + if (my_info3->base.acct_flags & ACB_WSTRUST) { return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } - if (my_info3->acct_flags & ACB_SVRTRUST) { + if (my_info3->base.acct_flags & ACB_SVRTRUST) { return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } - if (my_info3->acct_flags & ACB_DOMTRUST) { + if (my_info3->base.acct_flags & ACB_DOMTRUST) { return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } - if (!(my_info3->acct_flags & ACB_NORMAL)) { + if (!(my_info3->base.acct_flags & ACB_NORMAL)) { DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", - my_info3->acct_flags)); + my_info3->base.acct_flags)); return NT_STATUS_LOGON_FAILURE; } - kickoff_time = nt_time_to_unix(my_info3->kickoff_time); + kickoff_time = nt_time_to_unix(my_info3->base.acct_expiry); if (kickoff_time != 0 && time(NULL) > kickoff_time) { return NT_STATUS_ACCOUNT_EXPIRED; } - must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); + must_change_time = nt_time_to_unix(my_info3->base.force_password_change); if (must_change_time != 0 && must_change_time < time(NULL)) { /* we allow grace logons when the password has expired */ - my_info3->user_flgs |= NETLOGON_GRACE_LOGON; + my_info3->base.user_flags |= NETLOGON_GRACE_LOGON; /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } @@ -1071,8 +1063,8 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* FIXME: we possibly should handle logon hours as well (does xp when * offline?) see auth/auth_sam.c:sam_account_ok for details */ - unix_to_nt_time(&my_info3->logon_time, time(NULL)); - my_info3->bad_pw_count = 0; + unix_to_nt_time(&my_info3->base.last_logon, time(NULL)); + my_info3->base.bad_password_count = 0; result = winbindd_update_creds_by_info3(domain, state->mem_ctx, @@ -1099,14 +1091,14 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, } /* increase counter */ - my_info3->bad_pw_count++; + my_info3->base.bad_password_count++; if (max_allowed_bad_attempts == 0) { goto failed; } /* lockout user */ - if (my_info3->bad_pw_count >= max_allowed_bad_attempts) { + if (my_info3->base.bad_password_count >= max_allowed_bad_attempts) { uint32 password_properties; @@ -1115,9 +1107,9 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n")); } - if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || + if ((my_info3->base.rid != DOMAIN_USER_RID_ADMIN) || (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) { - my_info3->acct_flags |= ACB_AUTOLOCK; + my_info3->base.acct_flags |= ACB_AUTOLOCK; } } @@ -1138,7 +1130,7 @@ failed: NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { struct winbindd_domain *contact_domain; fstring name_domain, name_user; @@ -1197,7 +1189,7 @@ done: NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { struct rpc_pipe_client *netlogon_pipe; @@ -1211,18 +1203,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, fstring name_domain, name_user; bool retry; NTSTATUS result; - NET_USER_INFO_3 *my_info3; - - ZERO_STRUCTP(info3); + struct netr_SamInfo3 *my_info3 = NULL; *info3 = NULL; - my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3); - if (my_info3 == NULL) { - return NT_STATUS_NO_MEMORY; - } - - DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); /* Parse domain and username */ @@ -1330,7 +1314,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, chal, lm_resp, nt_resp, - my_info3); + &my_info3); attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -1364,7 +1348,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * caller, we look up the account flags ourselve - gd */ if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && - (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) { + (my_info3->base.acct_flags == 0) && NT_STATUS_IS_OK(result)) { struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; @@ -1384,7 +1368,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx, &samr_domain_handle, MAXIMUM_ALLOWED_ACCESS, - my_info3->user_rid, + my_info3->base.rid, &user_pol); if (!NT_STATUS_IS_OK(status_tmp)) { @@ -1412,7 +1396,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - my_info3->acct_flags = acct_flags; + my_info3->base.acct_flags = acct_flags; DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); @@ -1430,8 +1414,8 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, NTSTATUS result = NT_STATUS_LOGON_FAILURE; NTSTATUS krb5_result = NT_STATUS_OK; fstring name_domain, name_user; - NET_USER_INFO_3 *info3 = NULL; - + struct netr_SamInfo3 *info3 = NULL; + /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; @@ -1526,7 +1510,7 @@ sam_logon: DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n")); /* add the Krb5 err if we have one */ if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) { - info3->user_flgs |= LOGON_KRB5_FAIL_CLOCK_SKEW; + info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW; } goto process_result; } @@ -1586,8 +1570,8 @@ process_result: the cache entry by storing the seq_num for the wrong domain). */ if ( domain->primary ) { - sid_compose(&user_sid, &info3->dom_sid.sid, - info3->user_rid); + sid_compose(&user_sid, info3->base.domain_sid, + info3->base.rid); cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid); } @@ -1752,7 +1736,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; - NET_USER_INFO_3 info3; + struct netr_SamInfo3 *info3 = NULL; struct rpc_pipe_client *netlogon_pipe; const char *name_user = NULL; const char *name_domain = NULL; @@ -1830,7 +1814,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - ZERO_STRUCT(info3); retry = False; netlogon_pipe = NULL; @@ -1884,12 +1867,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { - netsamlogon_cache_store(name_user, &info3); - wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + netsamlogon_cache_store(name_user, info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); /* Check if the user is in the right group */ - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so " "crap authentication is rejected\n", @@ -1898,7 +1881,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = append_data(state, &info3, name_domain, name_user); + result = append_data(state, info3, name_domain, name_user); if (!NT_STATUS_IS_OK(result)) { goto done; } diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 585923410f..f818772ce7 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -429,7 +429,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, POLICY_HND dom_pol, user_pol; union samr_UserInfo *info = NULL; uint32 user_rid; - NET_USER_INFO_3 *user; + struct netr_SamInfo3 *user; struct rpc_pipe_client *cli; DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid))); @@ -449,14 +449,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain, DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_dbg(user_sid))); - sid_compose(&user_info->user_sid, &domain->sid, user->user_rid); + sid_compose(&user_info->user_sid, &domain->sid, user->base.rid); sid_compose(&user_info->group_sid, &domain->sid, - user->group_rid); + user->base.primary_gid); - user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, - &user->uni_user_name); - user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, - &user->uni_full_name); + user_info->acct_name = talloc_strdup(mem_ctx, + user->base.account_name.string); + user_info->full_name = talloc_strdup(mem_ctx, + user->base.full_name.string); TALLOC_FREE(user); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 7933ecf63e..038bafbe4e 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1272,7 +1272,7 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, const DOM_SID *user_sid, uint32 *p_num_groups, DOM_SID **user_sids) { - NET_USER_INFO_3 *info3 = NULL; + struct netr_SamInfo3 *info3 = NULL; NTSTATUS status = NT_STATUS_NO_MEMORY; int i; size_t num_groups = 0; @@ -1290,13 +1290,13 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (info3->num_groups == 0) { + if (info3->base.groups.count == 0) { TALLOC_FREE(info3); return NT_STATUS_UNSUCCESSFUL; } /* always add the primary group to the sid array */ - sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid); + sid_compose(&primary_group, info3->base.domain_sid, info3->base.rid); status = add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups); @@ -1305,9 +1305,9 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, return status; } - for (i=0; inum_groups; i++) { - sid_copy(&group_sid, &info3->dom_sid.sid); - sid_append_rid(&group_sid, info3->gids[i].g_rid); + for (i=0; i < info3->base.groups.count; i++) { + sid_copy(&group_sid, info3->base.domain_sid); + sid_append_rid(&group_sid, info3->base.groups.rids[i].rid); status = add_sid_to_array(mem_ctx, &group_sid, user_sids, &num_groups); @@ -1319,13 +1319,13 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, /* Add any Universal groups in the other_sids list */ - for (i=0; inum_other_sids; i++) { + for (i=0; i < info3->sidcount; i++) { /* Skip Domain local groups outside our domain. We'll get these from the getsidaliases() RPC call. */ - if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE) + if (info3->sids[i].attributes & SE_GROUP_RESOURCE) continue; - status = add_sid_to_array(mem_ctx, &info3->other_sids[i].sid, + status = add_sid_to_array(mem_ctx, info3->sids[i].sid, user_sids, &num_groups); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); -- cgit From 7269a504fdd06fbbe24c2df8e084b41382d71269 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 27 Feb 2008 19:38:48 +0100 Subject: Add my copyright. Guenther (This used to be commit d078a8757182d84dfd3307a2e1b751cf173aaa97) --- source3/winbindd/winbindd_rpc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index f818772ce7..2a7704c8a5 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2000-2001,2003 Copyright (C) Andrew Tridgell 2001 Copyright (C) Volker Lendecke 2005 + Copyright (C) Guenther Deschner 2008 (pidl conversion) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit From 0d8985f2da43d35d8f940af112ad74a199778dd8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 28 Feb 2008 12:30:18 +0100 Subject: Let dsgetdcname() return a struct netr_DsRGetDCNameInfo. Guenther (This used to be commit b1a4b21f8c35dc23e5c986ebe44d3806055eb39b) --- source3/winbindd/winbindd_locator.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 6b1cff99e0..10a6c5afeb 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -58,7 +58,7 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + struct netr_DsRGetDCNameInfo *info = NULL; const char *dc = NULL; state->request.domain_name @@ -74,15 +74,15 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, return WINBINDD_ERROR; } - if (info->domain_controller_address) { - dc = info->domain_controller_address; + if (info->dc_address) { + dc = info->dc_address; if ((dc[0] == '\\') && (dc[1] == '\\')) { dc += 2; } } - if ((!dc || !is_ipaddress_v4(dc)) && info->domain_controller_name) { - dc = info->domain_controller_name; + if ((!dc || !is_ipaddress_v4(dc)) && info->dc_unc) { + dc = info->dc_unc; } if (!dc || !*dc) { -- cgit From 76de025c724d68bef1b81c8ec6081db5e0f19c4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 Feb 2008 13:29:47 +0100 Subject: winbind: use a struct element for WBFLAG_PAM_UNIX_NAME To not conflict with WBFLAG_PAM_INFO3_TEXT. This should fix pam_winbind. metze (This used to be commit 1b8ed6c0ffb2548442bb7e9d848117ce9b1c65c0) --- source3/winbindd/winbindd_pam.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 79b4c764c3..ef5a312eea 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -157,7 +157,6 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, /* We've been asked to return the unix username, per 'winbind use default domain' settings and the like */ - fstring username_out; const char *nt_username, *nt_domain; nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string); @@ -174,18 +173,11 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, nt_username = name_user; } - fill_domain_username(username_out, nt_domain, nt_username, - True); + fill_domain_username(state->response.data.auth.unix_username, + nt_domain, nt_username, True); - DEBUG(5,("Setting unix username to [%s]\n", username_out)); - - SAFE_FREE(state->response.extra_data.data); - state->response.extra_data.data = SMB_STRDUP(username_out); - if (!state->response.extra_data.data) { - return NT_STATUS_NO_MEMORY; - } - state->response.length += - strlen((const char *)state->response.extra_data.data)+1; + DEBUG(5,("Setting unix username to [%s]\n", + state->response.data.auth.unix_username)); return NT_STATUS_OK; } @@ -736,14 +728,12 @@ failed: static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | - WBFLAG_PAM_UNIX_NAME | WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_INFO3_NDR; if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| - ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || !(flags & flags_edata) ) { return True; } -- cgit From 1ebfc66b2c145289d1e1314e8415d9e3c6f405ae Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Mar 2008 21:08:29 +0100 Subject: Use a separate tdb for mutexes Another preparation to convert secrets.c to dbwrap: The dbwrap API does not provide a sane tdb_lock_with_timeout abstraction. In the clustered case the DC mutex is needed per-node anyway, so it is perfectly fine to use a local mutex only. (This used to be commit f94a63cd8f94490780ad9331da229c0bcb2ca5d6) --- source3/winbindd/winbindd_cm.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0f536cdfb8..072b4ee98f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -747,7 +747,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, char *ipc_domain = NULL; char *ipc_password = NULL; - bool got_mutex; + struct named_mutex *mutex; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -761,10 +761,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, *retry = True; - got_mutex = secrets_named_mutex(controller, - WINBIND_SERVER_MUTEX_WAIT_TIME); - - if (!got_mutex) { + mutex = grab_named_mutex(talloc_tos(), controller, + WINBIND_SERVER_MUTEX_WAIT_TIME); + if (mutex == NULL) { DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n", controller)); result = NT_STATUS_POSSIBLE_DEADLOCK; @@ -952,8 +951,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - secrets_named_mutex_release(controller); - got_mutex = False; + TALLOC_FREE(mutex); *retry = False; /* set the domain if empty; needed for schannel connections */ @@ -964,10 +962,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = NT_STATUS_OK; done: - if (got_mutex) { - secrets_named_mutex_release(controller); - } - + TALLOC_FREE(mutex); SAFE_FREE(machine_account); SAFE_FREE(machine_password); SAFE_FREE(machine_krb5_principal); -- cgit From bf10e7f93960f18739a9110d59d0ca09bfaf6c03 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Mar 2008 16:08:24 +0100 Subject: Fix some "nexted extern" warnins (This used to be commit 32fc759d942abb36d7dd351eff82925b6788dd28) --- source3/winbindd/winbindd_ndr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c index 842c915c5f..9d1502afa7 100644 --- a/source3/winbindd/winbindd_ndr.c +++ b/source3/winbindd/winbindd_ndr.c @@ -70,18 +70,18 @@ void ndr_print_winbindd_cm_conn(struct ndr_print *ndr, /**************************************************************** ****************************************************************/ +#ifdef HAVE_ADS +extern struct winbindd_methods ads_methods; +#endif +extern struct winbindd_methods msrpc_methods; +extern struct winbindd_methods passdb_methods; +extern struct winbindd_methods reconnect_methods; +extern struct winbindd_methods cache_methods; + void ndr_print_winbindd_methods(struct ndr_print *ndr, const char *name, const struct winbindd_methods *r) { -#ifdef HAVE_ADS - extern struct winbindd_methods ads_methods; -#endif - extern struct winbindd_methods msrpc_methods; - extern struct winbindd_methods passdb_methods; - extern struct winbindd_methods reconnect_methods; - extern struct winbindd_methods cache_methods; - ndr_print_struct(ndr, name, "winbindd_methods"); ndr->depth++; -- cgit From ca63c6e0796454c18a1d580df99cbd6d05f60672 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Mar 2008 16:09:37 +0100 Subject: Merge dd9e0bea31751 from 3-0-ctdb -- use NetSamLogonEx when possible NetSamLogonEx has the advantage that it does not use the credential chain (This used to be commit cfceb063f559f8549b8f24ce347be213c89303b0) --- source3/winbindd/winbindd.h | 8 ++++ source3/winbindd/winbindd_cm.c | 10 +++++ source3/winbindd/winbindd_pam.c | 95 +++++++++++++++++++++++++++++++---------- 3 files changed, 90 insertions(+), 23 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index b812d69aeb..0840e581fe 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -176,6 +176,14 @@ struct winbindd_domain { time_t startup_time; /* When we set "startup" true. */ bool startup; /* are we in the first 30 seconds after startup_time ? */ + bool can_do_samlogon_ex; /* Due to the lack of finer control what type + * of DC we have, let us try to do a + * credential-chain less samlogon_ex call + * with AD and schannel. If this fails with + * DCERPC_FAULT_OP_RNG_ERROR, then set this + * to False. This variable is around so that + * we don't have to try _ex every time. */ + /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 072b4ee98f..c715ac08d8 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2403,6 +2403,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + /* + * NetSamLogonEx only works for schannel + */ + domain->can_do_samlogon_ex = False; + /* We're done - just keep the existing connection to NETLOGON * open */ conn->netlogon_pipe = netlogon_pipe; @@ -2434,6 +2439,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; } + /* + * Try NetSamLogonEx for AD domains + */ + domain->can_do_samlogon_ex = domain->active_directory; + *cli = conn->netlogon_pipe; return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ef5a312eea..c56eb1b3f8 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1283,6 +1283,17 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); ZERO_STRUCTP(my_info3); retry = False; @@ -1294,19 +1305,32 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - 0, - contact_domain->dcname, /* server name */ - name_user, /* user name */ - name_domain, /* target domain */ - global_myname(), /* workstation */ - chal, - lm_resp, - nt_resp, - &my_info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + 0, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + &my_info3); attempts += 1; + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + /* We have to try a second time as cm_connect_netlogon might not yet have noticed that the DC has killed our connection. */ @@ -1804,6 +1828,18 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + retry = False; netlogon_pipe = NULL; @@ -1815,18 +1851,31 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - state->request.data.auth_crap.logon_parameters, - contact_domain->dcname, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, - &info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } attempts += 1; -- cgit From 04cd5c6bd8bb0b18e631ba3a42d004ac959bf106 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Mar 2008 21:35:41 +0100 Subject: Fix typo (This used to be commit 38683a73013865695e1b04f5f6a974bd0c5c1cac) --- source3/winbindd/winbindd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 615f4a918e..25ceeeb321 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1238,7 +1238,7 @@ int main(int argc, char **argv, char **envp) wcache_tdc_clear(); if (!init_domain_list()) { - DEBUG(0,("unable to initalize domain list\n")); + DEBUG(0,("unable to initialize domain list\n")); exit(1); } -- cgit From 689cd9e1012bba0a4e9a7da4bbf8b2833e0f1684 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Mar 2008 22:21:50 +0100 Subject: Fix a segfault When we get a NT_STATUS_WRONG_PASSWORD for example, my_info3 is not initialized at all. So first check that we have NT_STATUS_IS_OK(status) before we dereference my_info3. (This used to be commit 559cd9e5a7fac3ce3769d457132cdcb28569b93d) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c56eb1b3f8..5712f08603 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1362,7 +1362,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * caller, we look up the account flags ourselve - gd */ if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && - (my_info3->base.acct_flags == 0) && NT_STATUS_IS_OK(result)) { + NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) { struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; -- cgit From 06772e7f6561d32e9cc7b15811815e3368b2beae Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 26 Mar 2008 21:08:53 +0100 Subject: Fix winbind NETLOGON cred chain on a samba dc for w2k8 trusts. Guenther (This used to be commit 2586dc34e0f72204749f5bf10c8135cd3a753a42) --- source3/winbindd/winbindd_cm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index c715ac08d8..d4241a0c78 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2335,7 +2335,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; @@ -2348,6 +2348,10 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return result; } + if (domain->active_directory) { + neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + } + conn = &domain->conn; if (conn->netlogon_pipe != NULL) { -- cgit From cba8dcf759a2a0ed10060a19e9676bd1872ded67 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 27 Mar 2008 12:02:18 +0100 Subject: Move LOGON_KRB5_FAIL_CLOCK_SKEW to winbindd_pam. Guenther (This used to be commit fa64c76ac8e54f385f277b5b39be70075b2eeee0) --- source3/winbindd/winbindd_pam.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 5712f08603..63127cbfcd 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -27,6 +27,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +#define LOGON_KRB5_FAIL_CLOCK_SKEW 0x02000000 + static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, struct netr_SamInfo3 *info3) -- cgit From 2198058624d456e7434f5fbbb998cd232ea3e9e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Mar 2008 13:00:23 +0100 Subject: Fix wbinfo -a trusted\\user%password on a Samba DC with trusts Winbind can't be allowed to connect to the local smbd. (This used to be commit 0d617f639a3c9c52e4327aed4bd02d9e8e7312a2) --- source3/winbindd/winbindd_cache.c | 5 +++++ source3/winbindd/winbindd_dual.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 4d81ee3960..a8a98e5bc8 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -37,6 +37,7 @@ extern bool opt_nocache; #ifdef HAVE_ADS extern struct winbindd_methods ads_methods; #endif +extern struct winbindd_methods passdb_methods; /* * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES. @@ -135,6 +136,10 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) /* We have to know what type of domain we are dealing with first. */ + if (domain->internal) { + domain->backend = &passdb_methods; + domain->initialized = True; + } if ( !domain->initialized ) { init_dc_connection( domain ); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 2b756b24d1..3c342e54a4 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1089,7 +1089,6 @@ static bool fork_domain_child(struct winbindd_child *child) * but not the main daemon */ if (child->domain && child->domain->internal && IS_DC) { - child->domain->internal = False; child->domain->methods = &cache_methods; child->domain->online = False; } -- cgit From 9c169e9e42b58e7b6c4b37f57d4649daea7593e5 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Thu, 27 Mar 2008 11:56:29 -0500 Subject: Don't fill password policy structure for any domain other than our own. The samr connects will fail. This is not independent of the CONTACT_TRUSTDOM flag neede by krb5 logins. (This used to be commit 4de4949e3bfcfb2169c329f19cb76936d9043d50) --- source3/winbindd/winbindd_pam.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 63127cbfcd..3b13a9269a 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1638,12 +1638,24 @@ process_result: if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { - result = fillup_password_policy(domain, state); - + struct winbindd_domain *our_domain = find_our_domain(); + + /* This is not entiurely correct I believe, but it is + consistent. Only apply the password policy settings + too warn users for our own domain. Cannot obtain these + from trusted DCs all the time so don't do it at all. + -- jerry */ + + result = NT_STATUS_NOT_SUPPORTED; + if (our_domain == domain ) { +a result = fillup_password_policy(our_domain, state); + } + if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) { - DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); + DEBUG(10,("Failed to get password policies for domain %s: %s\n", + domain->name, nt_errstr(result))); goto done; } } -- cgit From 1b9c4763eec7770008d85796dc5a05c3f5739042 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 27 Mar 2008 18:05:02 +0100 Subject: Fix typo. Guenther (This used to be commit fed644372916a5e565e4f5352aab61b39a3a42a0) --- source3/winbindd/winbindd_pam.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 3b13a9269a..972a3bf3b9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1639,18 +1639,18 @@ process_result: if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { struct winbindd_domain *our_domain = find_our_domain(); - - /* This is not entiurely correct I believe, but it is + + /* This is not entirely correct I believe, but it is consistent. Only apply the password policy settings too warn users for our own domain. Cannot obtain these from trusted DCs all the time so don't do it at all. -- jerry */ - result = NT_STATUS_NOT_SUPPORTED; + result = NT_STATUS_NOT_SUPPORTED; if (our_domain == domain ) { -a result = fillup_password_policy(our_domain, state); + result = fillup_password_policy(our_domain, state); } - + if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) { -- cgit From 26fead2c6ee5e26f9a0360222c8231f0409f68a8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Mar 2008 18:39:11 +0100 Subject: Make some fns static (This used to be commit e04fc36f223d8d905a930c077a6cf6c48ee57af7) --- source3/winbindd/idmap_cache.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index cf46196ebe..f7e1d4e6d1 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -70,12 +70,8 @@ struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) return cache; } -void idmap_cache_shutdown(struct idmap_cache_ctx *cache) -{ - talloc_free(cache); -} - -NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct id_map *id) +static NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, + const struct id_map *id) { fstring sidstr; @@ -89,7 +85,8 @@ NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct i return NT_STATUS_OK; } -NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, const struct id_map *id) +static NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, + const struct id_map *id) { *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu", (id->xid.type==ID_TYPE_UID)?"UID":"GID", @@ -256,7 +253,7 @@ done: return ret; } -NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) +static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) { char *rem; @@ -304,14 +301,6 @@ failed: return NT_STATUS_INTERNAL_DB_CORRUPTION; } -bool idmap_cache_is_negative(const char *val) -{ - if ( ! strcmp("IDMAP/NEGATIVE", val)) { - return True; - } - return False; -} - /* search the cahce for the SID an return a mapping if found * * * 4 cases are possible -- cgit From 4ce88f719e38ade76f7bcfd2e5b9932d864e4b20 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 29 Mar 2008 00:47:42 +0100 Subject: Don't let winbind getgroups crash when we have no gids in the token. Guenther (This used to be commit 6a576cfe9b87e69af6acbe9abc04124b8b743fd3) --- source3/winbindd/winbindd_group.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 6a704cf290..5dbd8c55a5 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1595,9 +1595,11 @@ static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid) } s->state->response.data.num_entries = s->num_token_gids; - /* s->token_gids are talloced */ - s->state->response.extra_data.data = smb_xmemdup(s->token_gids, s->num_token_gids * sizeof(gid_t)); - s->state->response.length += s->num_token_gids * sizeof(gid_t); + if (s->num_token_gids) { + /* s->token_gids are talloced */ + s->state->response.extra_data.data = smb_xmemdup(s->token_gids, s->num_token_gids * sizeof(gid_t)); + s->state->response.length += s->num_token_gids * sizeof(gid_t); + } request_ok(s->state); } -- cgit From 2487f0c88c0ecf04921e5484ed1fc983762a86c9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 29 Mar 2008 01:05:17 +0100 Subject: winbindd_cache: add missing validation function for pwinfo cache entry Michael (This used to be commit 6d3fc63bfab06346fa57719e8747397873a3c46d) --- source3/winbindd/winbindd_cache.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index a8a98e5bc8..0f8bd49d06 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -3209,6 +3209,29 @@ static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, return 0; } +static int validate_pwinfo(TALLOC_CTX *mem_ctx, const char *keystr, + TDB_DATA dbuf, struct tdb_validation_status *state) +{ + struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + + if (!centry) { + return 1; + } + + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_string(centry, mem_ctx); + (void)centry_uint32(centry); + + centry_free(centry); + + if (!(state->success)) { + return 1; + } + DEBUG(10,("validate_pwinfo: %s ok\n", keystr)); + return 0; +} + static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct tdb_validation_status *state) { @@ -3307,6 +3330,7 @@ struct key_val_struct { {"GM/", validate_gm}, {"DR/", validate_dr}, {"DE/", validate_de}, + {"NSS/PWINFO/", validate_pwinfo}, {"TRUSTDOMS/", validate_trustdoms}, {"TRUSTDOMCACHE/", validate_trustdomcache}, {"WINBINDD_OFFLINE", validate_offline}, -- cgit From 223071f01de8d85b594bab7c1f8514386da11281 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Tue, 25 Mar 2008 16:50:58 -0700 Subject: Forest root trust flags won't overwrite child trust flags * changed the behavior of winbind_ads.c:trusted_domains() to not overwrite existing trust information if we're joined to a child domain, and querying the forest root domain. Previously if we were joined to a child domain, we'd request all known trust information from this child domain (our primary domain) and store it in the tdc. We'd then request all trust information from our tree root (to get the forests we transitively trust) and overwrite the existing trust information we already had from the perspective of the tree root. * updated several comments and fixed typos (This used to be commit 6aac972d790ad5ca65096cb2e85e6819b60a5413) --- source3/winbindd/winbindd_ads.c | 81 +++++++++++++++++++++++++--------------- source3/winbindd/winbindd_util.c | 6 +-- 2 files changed, 54 insertions(+), 33 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 0900d56987..ae8ad9dd1a 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1249,32 +1249,55 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, fstrcpy( d.alt_name, trusts.array[i].dns_name); sid_copy( &d.sid, trusts.array[i].sid); - /* This gets a little tricky. If we are - following a transitive forest trust, then - innerit the flags, type, and attrins from - the domain we queried to make sure we don't - record the view of the trust from the wrong - side. Always view it from the side of our - primary domain. --jerry */ - if ( domain->primary || - ((domain->domain_flags&fr_flags) == fr_flags) ) - { - DEBUG(10,("trusted_domains(ads): Storing trust " - "flags for domain %s\n", d.alt_name)); - - /* Look this up in cache to make sure - we have the current trust flags and - attributes */ + if ( domain->primary ) { + DEBUG(10,("trusted_domains(ads): Searching " + "trusted domain list of %s and storing " + "trust flags for domain %s\n", + domain->name, d.alt_name)); d.domain_flags = trusts.array[i].trust_flags; d.domain_type = trusts.array[i].trust_type; d.domain_trust_attribs = trusts.array[i].trust_attributes; - } else { - /* Look up the record in the cache */ - struct winbindd_tdc_domain *parent; - DEBUG(10,("trusted_domains(ads): Inheriting trust " - "flags for domain %s\n", d.alt_name)); + wcache_tdc_add_domain( &d ); + ret_count++; + } else if ( (domain->domain_flags&fr_flags) == fr_flags ) { + /* Check if we already have this record. If + * we are following our forest root that is not + * our primary domain, we want to keep trust + * flags from the perspective of our primary + * domain not our forest root. */ + struct winbindd_tdc_domain *exist = NULL; + + exist = + wcache_tdc_fetch_domain(NULL, trusts.array[i].netbios_name); + if (!exist) { + DEBUG(10,("trusted_domains(ads): Searching " + "trusted domain list of %s and storing " + "trust flags for domain %s\n", + domain->name, d.alt_name)); + d.domain_flags = trusts.array[i].trust_flags; + d.domain_type = trusts.array[i].trust_type; + d.domain_trust_attribs = trusts.array[i].trust_attributes; + + wcache_tdc_add_domain( &d ); + ret_count++; + } + TALLOC_FREE(exist); + } else { + /* This gets a little tricky. If we are + following a transitive forest trust, then + innerit the flags, type, and attribs from + the domain we queried to make sure we don't + record the view of the trust from the wrong + side. Always view it from the side of our + primary domain. --jerry */ + struct winbindd_tdc_domain *parent = NULL; + + DEBUG(10,("trusted_domains(ads): Searching " + "trusted domain list of %s and inheriting " + "trust flags for domain %s\n", + domain->name, d.alt_name)); parent = wcache_tdc_fetch_domain(NULL, domain->name); if (parent) { @@ -1282,17 +1305,15 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, d.domain_type = parent->trust_type; d.domain_trust_attribs = parent->trust_attribs; } else { - d.domain_flags = domain->domain_flags; - d.domain_type = domain->domain_type; - d.domain_trust_attribs = domain->domain_trust_attribs; - } + d.domain_flags = domain->domain_flags; + d.domain_type = domain->domain_type; + d.domain_trust_attribs = domain->domain_trust_attribs; + } TALLOC_FREE(parent); + + wcache_tdc_add_domain( &d ); + ret_count++; } - - wcache_tdc_add_domain( &d ); - - ret_count++; - } *num_domains = ret_count; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 038bafbe4e..641fd5a9f5 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -339,7 +339,7 @@ static void trustdom_recv(void *private_data, bool success) */ if ( state->primary ) { - /* If this is our primary domain and we are not the in the + /* If this is our primary domain and we are not in the forest root, we have to scan the root trusts first */ if ( !state->forest_root ) @@ -349,7 +349,7 @@ static void trustdom_recv(void *private_data, bool success) } else if ( state->forest_root ) { /* Once we have done root forest trust search, we can - go on to search thing trusted forests */ + go on to search the trusted forests */ rescan_forest_trusts(); } @@ -419,7 +419,7 @@ static void rescan_forest_root_trusts( void ) } /******************************************************************** - scan the transitive forest trists (not our own) + scan the transitive forest trusts (not our own) ********************************************************************/ -- cgit From 2b70174e1bcef3b34acb406c9f8d79b0ec0cacfa Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Tue, 25 Mar 2008 16:58:40 -0700 Subject: Augmented "wbinfo -m" to list additional information about the type, direction, and transitivty of trusts. * added several helper functions to convert the trust_flags field in the winbindd_tdc_domain to more useful administrator ideas of trust type, trust direction, and trust transitivity. * converted winbindd_list_trusted_domains() to enumerate the trusted domain cache, instead of the domain list, and return additional trust information to the calling process * modified wbinfo to pretty print this additional trust information when a new --verbose switch is given with -m. Thus "wbinfo -m" and "wbinfo -all-domains" output as before, but "wbinfo --verbose -m" prints extra trust info. * updated some comments and fixed typos (This used to be commit e7827bb6afa264c12ecdc0858f49707ca3d6104f) --- source3/winbindd/winbindd_misc.c | 104 ++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index c22da3e8ef..93986d174e 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -97,27 +97,104 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } +/* Constants and helper functions for determining domain trust types */ + +enum trust_type { + EXTERNAL = 0, + FOREST, + IN_FOREST, + NONE, +}; + +const char *trust_type_strings[] = {"External", + "Forest", + "In Forest", + "None"}; + +static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain) +{ + if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) + return EXTERNAL; + else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) + return FOREST; + else if (((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == NETR_TRUST_FLAG_IN_FOREST) && + ((domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) == 0x0)) + return IN_FOREST; + return NONE; +} + +static const char *get_trust_type_string(struct winbindd_tdc_domain *domain) +{ + return trust_type_strings[get_trust_type(domain)]; +} + +static bool trust_is_inbound(struct winbindd_tdc_domain *domain) +{ + return (domain->trust_flags == 0x0) || + ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == + NETR_TRUST_FLAG_IN_FOREST) || + ((domain->trust_flags & NETR_TRUST_FLAG_INBOUND) == + NETR_TRUST_FLAG_INBOUND); +} + +static bool trust_is_outbound(struct winbindd_tdc_domain *domain) +{ + return (domain->trust_flags == 0x0) || + ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == + NETR_TRUST_FLAG_IN_FOREST) || + ((domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) == + NETR_TRUST_FLAG_OUTBOUND); +} + +static bool trust_is_transitive(struct winbindd_tdc_domain *domain) +{ + if ((domain->trust_attribs == NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE) || + (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) || + (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL)) + return False; + return True; +} + void winbindd_list_trusted_domains(struct winbindd_cli_state *state) { - struct winbindd_domain *d = NULL; + struct winbindd_tdc_domain *dom_list = NULL; + struct winbindd_tdc_domain *d = NULL; + size_t num_domains = 0; int extra_data_len = 0; char *extra_data = NULL; + int i = 0; DEBUG(3, ("[%5lu]: list trusted domains\n", (unsigned long)state->pid)); - for ( d=domain_list(); d; d=d->next ) { + if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) { + request_error(state); + goto done; + } + + for ( i = 0; i < num_domains; i++ ) { + d = &dom_list[i]; if ( !extra_data ) { - extra_data = talloc_asprintf( - state->mem_ctx, "%s\\%s\\%s", - d->name, d->alt_name ? d->alt_name : d->name, - sid_string_talloc(state->mem_ctx, &d->sid)); + extra_data = talloc_asprintf(state->mem_ctx, + "%s\\%s\\%s\\%s\\%s\\%s\\%s", + d->domain_name, + d->dns_name ? d->dns_name : d->domain_name, + sid_string_talloc(state->mem_ctx, &d->sid), + get_trust_type_string(d), + trust_is_transitive(d) ? "Yes" : "No", + trust_is_inbound(d) ? "Yes" : "No", + trust_is_outbound(d) ? "Yes" : "No"); } else { - extra_data = talloc_asprintf( - state->mem_ctx, "%s\n%s\\%s\\%s", - extra_data, d->name, - d->alt_name ? d->alt_name : d->name, - sid_string_talloc(state->mem_ctx, &d->sid)); + extra_data = talloc_asprintf(state->mem_ctx, + "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s", + extra_data, + d->domain_name, + d->dns_name ? d->dns_name : d->domain_name, + sid_string_talloc(state->mem_ctx, &d->sid), + get_trust_type_string(d), + trust_is_transitive(d) ? "Yes" : "No", + trust_is_inbound(d) ? "Yes" : "No", + trust_is_outbound(d) ? "Yes" : "No"); } } @@ -131,9 +208,10 @@ void winbindd_list_trusted_domains(struct winbindd_cli_state *state) state->response.length += extra_data_len+1; } - TALLOC_FREE( extra_data ); - request_ok(state); +done: + TALLOC_FREE( dom_list ); + TALLOC_FREE( extra_data ); } enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain, -- cgit From 5414a21ba39f9ad5a7d65f46033d4fa5eed21225 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Mon, 31 Mar 2008 13:39:54 -0500 Subject: Fix enumeration of forest trusts from our root domain. Do not overwrite the domain->domain_flags when setting infomation in set_dc_type_and_flags_connect(). (This used to be commit 3414eac439b731ad7204b821ddc4fec54fe4435d) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d4241a0c78..39d8def7ea 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1938,7 +1938,7 @@ no_dssetup: lsa_info->dns.dns_forest.string); if (strequal(domain->forest_name, domain->alt_name)) { - domain->domain_flags = NETR_TRUST_FLAG_TREEROOT; + domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT; } } -- cgit From 99d35904552b01ef9f2adc40e16887da9eb4de69 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 2 Apr 2008 02:29:48 +0200 Subject: Fix NETLOGON credential chain with Windows 2008 all over the place. In order to avoid receiving NT_STATUS_DOWNGRADE_DETECTED from a w2k8 netr_ServerAuthenticate2 reply, we need to start with the AD netlogon negotiate flags everywhere (not only when running in security=ads). Only for NT4 we need to do a downgrade to the returned negotiate flags. Tested with w2k8, w2ksp4, w2k3r2 and nt4sp6. Guenther (This used to be commit 0970369ca0cb9ae465cff40e5c75739824daf1d0) --- source3/winbindd/winbindd_cm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 39d8def7ea..b792de0aab 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2335,7 +2335,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; @@ -2348,10 +2348,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return result; } - if (domain->active_directory) { - neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - } - conn = &domain->conn; if (conn->netlogon_pipe != NULL) { -- cgit From a123abdb912e9fefed501d2621b719f3584c2a2b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 1 Apr 2008 18:25:47 -0400 Subject: Fix trusted users on a DC that uses the old idmap syntax. There was no default backend therefore on IDs were mapped by default. (This used to be commit f6069126e5e6d239b1ae00e897a420227f923e3f) --- source3/winbindd/idmap.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index c1b4e10adf..10807e6640 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -522,6 +522,76 @@ NTSTATUS idmap_init(void) talloc_free(config_option); } + /* on DCs we need to add idmap_tdb as the default backend if compat is + * defined (when the old implicit configuration is used) + * This is not done in the previous loop a on member server we exclude + * the local domain. But on a DC the local domain is the only domain + * available therefore we are left with no default domain */ + if (((lp_server_role() == ROLE_DOMAIN_PDC) || + (lp_server_role() == ROLE_DOMAIN_BDC)) && + ((num_domains == 0) && (compat == 1))) { + + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); + + dom->name = talloc_strdup(dom, "__default__"); + IDMAP_CHECK_ALLOC(dom->name); + + dom->default_domain = True; + dom->readonly = False; + + /* get the backend methods for this domain */ + dom->methods = get_methods(backends, compat_backend); + + if ( ! dom->methods) { + ret = smb_probe_module("idmap", compat_backend); + if (NT_STATUS_IS_OK(ret)) { + dom->methods = get_methods(backends, + compat_backend); + } + } + if ( ! dom->methods) { + DEBUG(0, ("ERROR: Could not get methods for " + "backend %s\n", compat_backend)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* now that we have methods, + * set the destructor for this domain */ + talloc_set_destructor(dom, close_domain_destructor); + + dom->params = talloc_strdup(dom, compat_params); + IDMAP_CHECK_ALLOC(dom->params); + + /* Finally instance a backend copy for this domain */ + ret = dom->methods->init(dom); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Initialization failed for backend " + "%s (domain %s), deferred!\n", + compat_backend, dom->name)); + } + idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, + struct idmap_domain *, 2); + if ( ! idmap_domains) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + idmap_domains[num_domains] = dom; + + def_dom_num = num_domains; + + /* Bump counter to next available slot */ + + num_domains++; + + DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", + dom->name, compat_backend, + dom->default_domain?"":"not ", + dom->readonly?"":"not ")); + } + /* automatically add idmap_nss backend if needed */ if ((lp_server_role() == ROLE_DOMAIN_MEMBER) && ( ! pri_dom_is_in_list) && -- cgit From bea4541e11f0664aaa8b62d525e0a02b14fc3afa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 4 Apr 2008 02:53:40 +0200 Subject: Use sid_array_from_info3 in lookup_usergroups_cached(). Guenther (This used to be commit 65b4cb20ea3fb806cfd50281e08f32bea70fafce) --- source3/winbindd/winbindd_pam.c | 2 +- source3/winbindd/winbindd_util.c | 50 ++++++++-------------------------------- 2 files changed, 11 insertions(+), 41 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 972a3bf3b9..bc27f3db20 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -313,7 +313,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, status = sid_array_from_info3(mem_ctx, info3, &token->user_sids, &token->num_sids, - True); + true, false); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 641fd5a9f5..ec97b49428 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1274,14 +1274,11 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, { struct netr_SamInfo3 *info3 = NULL; NTSTATUS status = NT_STATUS_NO_MEMORY; - int i; size_t num_groups = 0; - DOM_SID group_sid, primary_group; - + DEBUG(3,(": lookup_usergroups_cached\n")); - + *user_sids = NULL; - num_groups = 0; *p_num_groups = 0; info3 = netsamlogon_cache_get(mem_ctx, user_sid); @@ -1294,46 +1291,19 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, TALLOC_FREE(info3); return NT_STATUS_UNSUCCESSFUL; } - - /* always add the primary group to the sid array */ - sid_compose(&primary_group, info3->base.domain_sid, info3->base.rid); - - status = add_sid_to_array(mem_ctx, &primary_group, user_sids, - &num_groups); + + /* Skip Domain local groups outside our domain. + We'll get these from the getsidaliases() RPC call. */ + status = sid_array_from_info3(mem_ctx, info3, + user_sids, + &num_groups, + true, true); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } - for (i=0; i < info3->base.groups.count; i++) { - sid_copy(&group_sid, info3->base.domain_sid); - sid_append_rid(&group_sid, info3->base.groups.rids[i].rid); - - status = add_sid_to_array(mem_ctx, &group_sid, user_sids, - &num_groups); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(info3); - return status; - } - } - - /* Add any Universal groups in the other_sids list */ - - for (i=0; i < info3->sidcount; i++) { - /* Skip Domain local groups outside our domain. - We'll get these from the getsidaliases() RPC call. */ - if (info3->sids[i].attributes & SE_GROUP_RESOURCE) - continue; - - status = add_sid_to_array(mem_ctx, info3->sids[i].sid, - user_sids, &num_groups); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(info3); - return status; - } - } - - TALLOC_FREE(info3); *p_num_groups = num_groups; status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; -- cgit From 66dad54c723d971aeb9c2dc11f2e3fa9734597fb Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 7 Apr 2008 09:51:42 -0400 Subject: Only cache password policy results that worked, otherwise we cannot login until the cache expires even if a connection to a DC has been restored. (This used to be commit 8671f9767d7d93a86712741303d6046937c3aae8) --- source3/winbindd/winbindd_cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 0f8bd49d06..e4b0a53d5d 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2232,7 +2232,9 @@ do_query: /* and save it */ refresh_sequence_number(domain, false); - wcache_save_password_policy(domain, status, policy); + if (NT_STATUS_IS_OK(status)) { + wcache_save_password_policy(domain, status, policy); + } return status; } -- cgit From bc5f19cb28e26206e216396d6561f05d77cf9ffa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Apr 2008 16:38:14 +0200 Subject: winbindd: fix break out early condition in fill_grent_mem(). if (!&new_glist) would always be skipped, if (new_glist == NULL) is what must have been meant... Michael (This used to be commit c1b60cdecff2a53f0a75a432a1ad7730eb734908) --- source3/winbindd/winbindd_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 5dbd8c55a5..d5d3accec1 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -567,7 +567,7 @@ static bool fill_grent_mem(struct winbindd_domain *domain, /* If we have no more groups to expand, break out early */ - if ( !&new_glist ) + if (new_glist == NULL) break; /* One more round */ -- cgit From 9fa04934e081fc87d9a40c9bf8c371726f7be6ad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 9 Apr 2008 09:48:59 +0200 Subject: Try anonymous session setup ... if there's no trust password Attempt to fix bug 5350 (This used to be commit 99f6b63f3c637457fdda7ed930c6666171b25b61) --- source3/winbindd/winbindd_cm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index b792de0aab..80261862b1 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -825,7 +825,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, &machine_account, &machine_krb5_principal); if (!NT_STATUS_IS_OK(result)) { - goto done; + goto anon_fallback; } if (lp_security() == SEC_ADS) { @@ -910,6 +910,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, } } + anon_fallback: + /* Fall back to anonymous connection, this might fail later */ if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0, -- cgit From 0f37cd0c8e62e5bffcbf587c1c826b35802e1e8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 10 Apr 2008 11:52:44 +0200 Subject: Also accept 0x15 getdc replies My NT4SP6 which my DC here trusts sends 0x15 instead of 0x13, from looking at the sniff at least the DC name is at the same place. (This used to be commit 79bc6796b81395d591fc6ef389f153dd981fe68b) --- source3/winbindd/winbindd_cm.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 80261862b1..8e275b2269 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1145,28 +1145,31 @@ static bool receive_getdc_response(struct sockaddr_storage *dc_ss, /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */ p = buf+SVAL(buf, smb_vwv10); - if (CVAL(p,0) != SAMLOGON_R) { - DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0))); - return False; - } + switch (CVAL(p, 0)) { + case SAMLOGON_R: + case SAMLOGON_UNK_R: + p+=2; + pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + pull_ucs2(buf, user, p, sizeof(user), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + pull_ucs2(buf, domain, p, sizeof(domain), PTR_DIFF(buf+len, p), + STR_TERMINATE|STR_NOALIGN); + p = skip_unibuf(p, PTR_DIFF(buf+len, p)); + + if (!strequal(domain, domain_name)) { + DEBUG(3, ("GetDC: Expected domain %s, got %s\n", + domain_name, domain)); + return False; + } + break; - p+=2; - pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - - if (!strequal(domain, domain_name)) { - DEBUG(3, ("GetDC: Expected domain %s, got %s\n", - domain_name, domain)); + default: + DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0))); return False; } - p = dcname; if (*p == '\\') p += 1; if (*p == '\\') p += 1; -- cgit From b884db5c47a958188d9570f78093b9443b48b9cc Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 10 Apr 2008 11:53:53 +0200 Subject: winbindd: only call winbindd_validate_cache when not in offline logon mode. originally, the cache was cleared before calling validate, but this way, we skipt the validation of the database when not in offline logon mode. This is put into a new wrapper function winbindd_cache_validate_and_initialize() which is now called in winbindd.c instead calling validate and initialize functions separately. Michael (This used to be commit 641b5e3fecfce9581536de8daf6d7e6ecbefaf34) --- source3/winbindd/winbindd.c | 23 +++-------------------- source3/winbindd/winbindd_cache.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 25ceeeb321..dbfd397f8b 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -123,19 +123,7 @@ static void flush_caches(void) if (!wcache_invalidate_cache()) { DEBUG(0, ("invalidating the cache failed; revalidate the cache\n")); - /* Close the cache to be able to valdite the cache */ - close_winbindd_cache(); - /* - * Ensure all cache and idmap caches are consistent - * before we initialize the cache again. - */ - if (winbindd_validate_cache() < 0) { - DEBUG(0, ("winbindd cache tdb corrupt and no backup " - "could be restore.\n")); - } - - /* Initialize cache again. */ - if (!initialize_winbindd_cache()) { + if (!winbindd_cache_validate_and_initialize()) { exit(1); } } @@ -1194,14 +1182,9 @@ int main(int argc, char **argv, char **envp) /* * Ensure all cache and idmap caches are consistent - * before we startup. + * and initialized before we startup. */ - if (winbindd_validate_cache() < 0) { - DEBUG(0, ("corrupted tdb found, trying to restore backup\n")); - } - - /* Initialize cache (ensure version is correct). */ - if (!initialize_winbindd_cache()) { + if (!winbindd_cache_validate_and_initialize()) { exit(1); } diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index e4b0a53d5d..ddb0ab317e 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -3476,6 +3476,20 @@ int winbindd_validate_cache_nobackup(void) return ret; } +bool winbindd_cache_validate_and_initialize(void) +{ + close_winbindd_cache(); + + if (lp_winbind_offline_logon()) { + if (winbindd_validate_cache() < 0) { + DEBUG(0, ("winbindd cache tdb corrupt and no backup " + "could be restored.\n")); + } + } + + return initialize_winbindd_cache(); +} + /********************************************************************* ********************************************************************/ -- cgit From e21b283d6713794fb0a415a9313943867812884d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 14:01:28 +0200 Subject: dbwrap: wait for tdb2 change notifies in smbd, nmbd and winbindd metze (This used to be commit 64450cc1e441355aa8925b7183e90872eeab20b1) --- source3/winbindd/winbindd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index dbfd397f8b..ff9bbf1c24 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1102,6 +1102,8 @@ int main(int argc, char **argv, char **envp) DEBUG(0,("winbindd version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); + db_tdb2_setup_messaging(NULL, false); + if (!reload_services_file()) { DEBUG(0, ("error opening config file\n")); exit(1); @@ -1188,6 +1190,9 @@ int main(int argc, char **argv, char **envp) exit(1); } + /* get broadcast messages */ + claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP); + /* React on 'smbcontrol winbindd reload-config' in the same way as to SIGHUP signal */ messaging_register(winbind_messaging_context(), NULL, @@ -1214,6 +1219,8 @@ int main(int argc, char **argv, char **envp) MSG_WINBIND_DUMP_DOMAIN_LIST, winbind_msg_dump_domain_list); + db_tdb2_setup_messaging(winbind_messaging_context(), true); + netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ -- cgit From bbded540b689d3f0c6ed3ddb61eae3b8a5569372 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 16 Apr 2008 23:52:34 +0200 Subject: Move GETDC mailslot out of winbindd. Guenther (This used to be commit b003ba65e34bb92bf71a7943957715cd7acbcce0) --- source3/winbindd/winbindd_cm.c | 164 +---------------------------------------- 1 file changed, 2 insertions(+), 162 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 8e275b2269..adb631b57b 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1021,167 +1021,6 @@ static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, return True; } -static void mailslot_name(struct in_addr dc_ip, fstring name) -{ - fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr); -} - -static bool send_getdc_request(struct sockaddr_storage *dc_ss, - const char *domain_name, - const DOM_SID *sid) -{ - char outbuf[1024]; - struct in_addr dc_ip; - char *p; - fstring my_acct_name; - fstring my_mailslot; - size_t sid_size; - - if (dc_ss->ss_family != AF_INET) { - return false; - } - - dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; - mailslot_name(dc_ip, my_mailslot); - - memset(outbuf, '\0', sizeof(outbuf)); - - p = outbuf; - - SCVAL(p, 0, SAMLOGON); - p++; - - SCVAL(p, 0, 0); /* Count pointer ... */ - p++; - - SIVAL(p, 0, 0); /* The sender's token ... */ - p += 2; - - p += dos_PutUniCode(p, global_myname(), - sizeof(outbuf) - PTR_DIFF(p, outbuf), True); - fstr_sprintf(my_acct_name, "%s$", global_myname()); - p += dos_PutUniCode(p, my_acct_name, - sizeof(outbuf) - PTR_DIFF(p, outbuf), True); - - if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { - return false; - } - - memcpy(p, my_mailslot, strlen(my_mailslot)+1); - p += strlen(my_mailslot)+1; - - if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) { - return false; - } - - SIVAL(p, 0, 0x80); - p+=4; - - sid_size = ndr_size_dom_sid(sid, 0); - - SIVAL(p, 0, sid_size); - p+=4; - - p = ALIGN4(p, outbuf); - if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) { - return false; - } - - if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { - return false; - } - sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid); - - p += sid_size; - - SIVAL(p, 0, 1); - SSVAL(p, 4, 0xffff); - SSVAL(p, 6, 0xffff); - p+=8; - - return cli_send_mailslot(winbind_messaging_context(), - False, "\\MAILSLOT\\NET\\NTLOGON", 0, - outbuf, PTR_DIFF(p, outbuf), - global_myname(), 0, domain_name, 0x1c, - dc_ss); -} - -static bool receive_getdc_response(struct sockaddr_storage *dc_ss, - const char *domain_name, - fstring dc_name) -{ - struct packet_struct *packet; - fstring my_mailslot; - char *buf, *p; - fstring dcname, user, domain; - int len; - struct in_addr dc_ip; - - if (dc_ss->ss_family != AF_INET) { - return false; - } - dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; - mailslot_name(dc_ip, my_mailslot); - - packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot); - - if (packet == NULL) { - DEBUG(5, ("Did not receive packet for %s\n", my_mailslot)); - return False; - } - - DEBUG(5, ("Received packet for %s\n", my_mailslot)); - - buf = packet->packet.dgram.data; - len = packet->packet.dgram.datasize; - - if (len < 70) { - /* 70 is a completely arbitrary value to make sure - the SVAL below does not read uninitialized memory */ - DEBUG(3, ("GetDC got short response\n")); - return False; - } - - /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */ - p = buf+SVAL(buf, smb_vwv10); - - switch (CVAL(p, 0)) { - case SAMLOGON_R: - case SAMLOGON_UNK_R: - p+=2; - pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - pull_ucs2(buf, user, p, sizeof(user), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - pull_ucs2(buf, domain, p, sizeof(domain), PTR_DIFF(buf+len, p), - STR_TERMINATE|STR_NOALIGN); - p = skip_unibuf(p, PTR_DIFF(buf+len, p)); - - if (!strequal(domain, domain_name)) { - DEBUG(3, ("GetDC: Expected domain %s, got %s\n", - domain_name, domain)); - return False; - } - break; - - default: - DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0))); - return False; - } - p = dcname; - if (*p == '\\') p += 1; - if (*p == '\\') p += 1; - - fstrcpy(dc_name, p); - - DEBUG(10, ("GetDC gave name %s for domain %s\n", - dc_name, domain)); - - return True; -} - /******************************************************************* convert an ip to a name *******************************************************************/ @@ -1253,7 +1092,8 @@ static bool dcip_to_name(const struct winbindd_domain *domain, /* try GETDC requests next */ - if (send_getdc_request(pss, domain->name, &domain->sid)) { + if (send_getdc_request(winbind_messaging_context(), + pss, domain->name, &domain->sid)) { int i; smb_msleep(100); for (i=0; i<5; i++) { -- cgit From 94b603648fdb074eec1f208d423ed1349e3d3841 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 01:02:42 +0200 Subject: winbindd: call reinit_after_fork() in the child processes metze (This used to be commit 8e9fdef792e612e414444e7714a2fd4513892248) --- source3/winbindd/winbindd_cm.c | 5 ++--- source3/winbindd/winbindd_dual.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index adb631b57b..fc1a9cae93 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -199,9 +199,8 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) /* Leave messages blocked - we will never process one. */ - /* tdb needs special fork handling */ - if (tdb_reopen_all(1) == -1) { - DEBUG(0,("tdb_reopen_all failed.\n")); + if (!reinit_after_fork(winbind_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); _exit(0); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 3c342e54a4..77fbe3c0ed 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1005,9 +1005,8 @@ static bool fork_domain_child(struct winbindd_child *child) state.sock = fdpair[0]; close(fdpair[1]); - /* tdb needs special fork handling */ - if (tdb_reopen_all(1) == -1) { - DEBUG(0,("tdb_reopen_all failed.\n")); + if (!reinit_after_fork(winbind_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); _exit(0); } -- cgit From 913cd26b2b2afc30a4295ede31c7f5f4ea4a71bc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 10:57:16 +0200 Subject: winbindd: create the messaging conntext earlier metze (This used to be commit 2e1b9130635235efdbf49d0b92a43b342114246c) --- source3/winbindd/winbindd.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index ff9bbf1c24..64674b8ace 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1023,6 +1023,8 @@ int main(int argc, char **argv, char **envp) load_case_tables(); + db_tdb2_setup_messaging(NULL, false); + /* Initialise for running in non-root mode */ sec_init(); @@ -1102,7 +1104,19 @@ int main(int argc, char **argv, char **envp) DEBUG(0,("winbindd version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); - db_tdb2_setup_messaging(NULL, false); + if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { + DEBUG(0, ("error opening config file\n")); + exit(1); + } + + /* Initialise messaging system */ + + if (winbind_messaging_context() == NULL) { + DEBUG(0, ("unable to initialize messaging system\n")); + exit(1); + } + + db_tdb2_setup_messaging(winbind_messaging_context(), true); if (!reload_services_file()) { DEBUG(0, ("error opening config file\n")); @@ -1175,10 +1189,8 @@ int main(int argc, char **argv, char **envp) TimeInit(); - /* Initialise messaging system */ - - if (winbind_messaging_context() == NULL) { - DEBUG(0, ("unable to initialize messaging system\n")); + if (!reinit_after_fork(winbind_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } @@ -1219,8 +1231,6 @@ int main(int argc, char **argv, char **envp) MSG_WINBIND_DUMP_DOMAIN_LIST, winbind_msg_dump_domain_list); - db_tdb2_setup_messaging(winbind_messaging_context(), true); - netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ -- cgit From 2a2188591b5ed922d09dc723adcf10f8b8f5e5a0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 21:56:43 +0200 Subject: Add "desthost" to rpc_pipe_client This reduces the dependency on cli_state (This used to be commit 783afab9c891dd7bcb78895b2a639b6f3a0edf5b) --- source3/winbindd/winbindd_ads.c | 2 +- source3/winbindd/winbindd_cm.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index ae8ad9dd1a..8be6a47998 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1195,7 +1195,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, } result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, - cli->cli->desthost, + cli->desthost, flags, &trusts, NULL); diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index fc1a9cae93..71d2c029ee 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1609,7 +1609,7 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) } result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, - cli->cli->desthost, + cli->desthost, flags, &trusts, NULL); @@ -1962,7 +1962,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, domain_name, machine_account)); result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, - conn->samr_pipe->cli->desthost, + conn->samr_pipe->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { @@ -1997,7 +1997,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "schannel.\n", domain->name )); result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, - conn->samr_pipe->cli->desthost, + conn->samr_pipe->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { @@ -2020,7 +2020,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, - conn->samr_pipe->cli->desthost, + conn->samr_pipe->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (!NT_STATUS_IS_OK(result)) { -- cgit From e1102b8f48aeebe7d4e730d2b432a1503b425210 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 23:27:35 +0200 Subject: Introduce rpccli_set_timeout() Reduce dependency on "cli" member of rpc_pipe_client struct (This used to be commit 2e4c1ba38963cffe4c3f25ab24bc28975f2fc291) --- source3/winbindd/winbindd_cm.c | 4 ++-- source3/winbindd/winbindd_misc.c | 4 ++-- source3/winbindd/winbindd_rpc.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 71d2c029ee..8fcbae77ff 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -598,7 +598,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, /* This call can take a long time - allow the server to time out. 35 seconds should do it. */ - orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); + orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000); if (our_domain->active_directory) { struct netr_DsRGetDCNameInfo *domain_info = NULL; @@ -638,7 +638,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, } /* And restore our original timeout. */ - cli_set_timeout(netlogon_pipe->cli, orig_timeout); + rpccli_set_timeout(netlogon_pipe, orig_timeout); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n", diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 93986d174e..bde2eafb53 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -333,7 +333,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, /* This call can take a long time - allow the server to time out. 35 seconds should do it. */ - orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); + orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000); req_domain = find_domain_from_name_noinit(state->request.domain_name); if (req_domain == domain) { @@ -352,7 +352,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, &werr); } /* And restore our original timeout. */ - cli_set_timeout(netlogon_pipe->cli, orig_timeout); + rpccli_set_timeout(netlogon_pipe, orig_timeout); if (!NT_STATUS_IS_OK(result)) { DEBUG(5,("Error requesting DCname for domain %s: %s\n", diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 2a7704c8a5..bb79d7ec12 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -750,14 +750,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, /* This call can take a long time - allow the server to time out. 35 seconds should do it. */ - orig_timeout = cli_set_timeout(cli->cli, 35000); + orig_timeout = rpccli_set_timeout(cli, 35000); result = rpccli_samr_QueryGroupMember(cli, mem_ctx, &group_pol, &rids); /* And restore our original timeout. */ - cli_set_timeout(cli->cli, orig_timeout); + rpccli_set_timeout(cli, orig_timeout); rpccli_samr_Close(cli, mem_ctx, &group_pol); -- cgit From e73e8297f5484b6c7f525917679414c09a145cf0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Apr 2008 13:51:46 +0200 Subject: Replace cli_rpc_pipe_close by a talloc destructor on rpc_pipe_struct (This used to be commit 99fc3283c4ecc791f5a242bd1983b4352ce3e6cf) --- source3/winbindd/winbindd_cm.c | 52 +++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 29 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 8fcbae77ff..73f74ca8ec 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1432,33 +1432,27 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) } if (conn->samr_pipe != NULL) { - if (!cli_rpc_pipe_close(conn->samr_pipe)) { - /* Ok, it must be dead. Drop timeout to 0.5 sec. */ - if (conn->cli) { - cli_set_timeout(conn->cli, 500); - } + TALLOC_FREE(conn->samr_pipe); + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); } - conn->samr_pipe = NULL; } if (conn->lsa_pipe != NULL) { - if (!cli_rpc_pipe_close(conn->lsa_pipe)) { - /* Ok, it must be dead. Drop timeout to 0.5 sec. */ - if (conn->cli) { - cli_set_timeout(conn->cli, 500); - } + TALLOC_FREE(conn->lsa_pipe); + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); } - conn->lsa_pipe = NULL; } if (conn->netlogon_pipe != NULL) { - if (!cli_rpc_pipe_close(conn->netlogon_pipe)) { - /* Ok, it must be dead. Drop timeout to 0.5 sec. */ - if (conn->cli) { - cli_set_timeout(conn->cli, 500); - } + TALLOC_FREE(conn->netlogon_pipe); + /* Ok, it must be dead. Drop timeout to 0.5 sec. */ + if (conn->cli) { + cli_set_timeout(conn->cli, 500); } - conn->netlogon_pipe = NULL; } if (conn->cli) { @@ -1711,7 +1705,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DS_ROLE_BASIC_INFORMATION, &info, &werr); - cli_rpc_pipe_close(cli); + TALLOC_FREE(cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo " @@ -1745,7 +1739,7 @@ no_dssetup: DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " "PI_LSARPC on domain %s: (%s)\n", domain->name, nt_errstr(result))); - cli_rpc_pipe_close(cli); + TALLOC_FREE(cli); TALLOC_FREE(mem_ctx); return; } @@ -1825,7 +1819,7 @@ done: DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n", domain->name, domain->active_directory ? "" : "NOT ")); - cli_rpc_pipe_close(cli); + TALLOC_FREE(cli); TALLOC_FREE(mem_ctx); @@ -1971,7 +1965,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 " "failed for domain %s, error was %s. Trying schannel\n", domain->name, nt_errstr(result) )); - cli_rpc_pipe_close(conn->samr_pipe); + TALLOC_FREE(conn->samr_pipe); schannel: @@ -2006,7 +2000,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed " "for domain %s, error was %s. Trying anonymous\n", domain->name, nt_errstr(result) )); - cli_rpc_pipe_close(conn->samr_pipe); + TALLOC_FREE(conn->samr_pipe); anonymous: @@ -2108,7 +2102,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying " "schannel\n")); - cli_rpc_pipe_close(conn->lsa_pipe); + TALLOC_FREE(conn->lsa_pipe); schannel: @@ -2143,7 +2137,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying " "anonymous\n")); - cli_rpc_pipe_close(conn->lsa_pipe); + TALLOC_FREE(conn->lsa_pipe); anonymous: @@ -2218,7 +2212,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, &sec_chan_type)) { - cli_rpc_pipe_close(netlogon_pipe); + TALLOC_FREE(netlogon_pipe); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -2233,14 +2227,14 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, &neg_flags); if (!NT_STATUS_IS_OK(result)) { - cli_rpc_pipe_close(netlogon_pipe); + TALLOC_FREE(netlogon_pipe); return result; } if ((lp_client_schannel() == True) && ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { DEBUG(3, ("Server did not offer schannel\n")); - cli_rpc_pipe_close(netlogon_pipe); + TALLOC_FREE(netlogon_pipe); return NT_STATUS_ACCESS_DENIED; } @@ -2273,7 +2267,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, &result); /* We can now close the initial netlogon pipe. */ - cli_rpc_pipe_close(netlogon_pipe); + TALLOC_FREE(netlogon_pipe); if (conn->netlogon_pipe == NULL) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " -- cgit From 937091161b82782d3578c80a6e56123c86050752 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 21 Apr 2008 10:55:23 +0200 Subject: winbind: Use libnbt for NTLOGON SAMLOGON mailslot request and reply. Guenther (This used to be commit 2d6a1c5da64195784b0b102edb268356a24d84b5) --- source3/winbindd/winbindd_cm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 73f74ca8ec..97b2259985 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1093,10 +1093,12 @@ static bool dcip_to_name(const struct winbindd_domain *domain, if (send_getdc_request(winbind_messaging_context(), pss, domain->name, &domain->sid)) { + const char *dc_name = NULL; int i; smb_msleep(100); for (i=0; i<5; i++) { - if (receive_getdc_response(pss, domain->name, name)) { + if (receive_getdc_response(pss, domain->name, &dc_name)) { + fstrcpy(name, dc_name); namecache_store(name, 0x20, 1, &ip_list); return True; } -- cgit From 154f4837b3169ddf6c61f87b9d28c257f69d35bf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Apr 2008 17:48:31 +0200 Subject: Add in a nice big comment explaining why SamLogonEx matters. Andrew Bartlett (This used to be commit 87232351b5e66728f8d602259961909e8c1dfcb6) --- source3/winbindd/winbindd_pam.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index bc27f3db20..2de10a9f10 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1307,6 +1307,27 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } + /* It is really important to try SamLogonEx here, + * because in a clustered environment, we want to use + * one machine account from multiple physical + * computers. + * + * With a normal SamLogon call, we must keep the + * credentials chain updated and intact between all + * users of the machine account (which would imply + * cross-node communication for every NTLM logon). + * + * (The credentials chain is not per NETLOGON pipe + * connection, but globally on the server/client pair + * by machine name). + * + * When using SamLogonEx, the credentials are not + * supplied, but the session key is implied by the + * wrapping SamLogon context. + * + * -- abartlet 21 April 2008 + */ + logon_fn = contact_domain->can_do_samlogon_ex ? rpccli_netlogon_sam_network_logon_ex : rpccli_netlogon_sam_network_logon; -- cgit From 1eca3f138c9368116a405f3871d39884375af0dd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 21 Apr 2008 17:51:36 +0200 Subject: winbind: pass down existing talloc context. Guenther (This used to be commit 675bf42cfff89b05f21d77ca74eba20c4a24d44c) --- source3/winbindd/winbindd_cm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 97b2259985..5cff052114 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1024,7 +1024,8 @@ static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, convert an ip to a name *******************************************************************/ -static bool dcip_to_name(const struct winbindd_domain *domain, +static bool dcip_to_name(TALLOC_CTX *mem_ctx, + const struct winbindd_domain *domain, struct sockaddr_storage *pss, fstring name ) { @@ -1091,13 +1092,13 @@ static bool dcip_to_name(const struct winbindd_domain *domain, /* try GETDC requests next */ - if (send_getdc_request(winbind_messaging_context(), + if (send_getdc_request(mem_ctx, winbind_messaging_context(), pss, domain->name, &domain->sid)) { const char *dc_name = NULL; int i; smb_msleep(100); for (i=0; i<5; i++) { - if (receive_getdc_response(pss, domain->name, &dc_name)) { + if (receive_getdc_response(mem_ctx, pss, domain->name, &dc_name)) { fstrcpy(name, dc_name); namecache_store(name, 0x20, 1, &ip_list); return True; @@ -1291,7 +1292,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, } /* Try to figure out the name */ - if (dcip_to_name(domain, pss, dcname)) { + if (dcip_to_name(mem_ctx, domain, pss, dcname)) { return True; } @@ -1336,7 +1337,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, AI_NUMERICHOST)) { return NT_STATUS_UNSUCCESSFUL; } - if (dcip_to_name( domain, &ss, saf_name )) { + if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) { fstrcpy( domain->dcname, saf_name ); } else { winbind_add_failed_connection_entry( -- cgit From bcbac69d1a38e128ffe8b763ac027d6eab33dcec Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 21 Apr 2008 19:59:27 +0200 Subject: cldap: avoid duplicate definitions so remove ads_cldap.h. Guenther (This used to be commit 538eefe22ad69540b9f73ffaa613d6be045de199) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 5cff052114..c62476e5eb 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1054,7 +1054,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags)); - if (domain->primary && (ads->config.flags & ADS_KDC)) { + if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) { if (ads_closest_dc(ads)) { char *sitename = sitename_fetch(ads->config.realm); -- cgit From 9ffcc7966f5bb5fb6f502580a0f5514568d18463 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Apr 2008 15:41:25 +0200 Subject: Fix wbinfo --group-info if the winbind separator set to non \ In getgrsid_lookupsid_recv() we use parse_domain_user which itself looks at lp_winbind_separator(). Thus when building up that group name we should better use it as well. (This used to be commit 5df75578ef1da41164936cd11b14114889201d47) --- source3/winbindd/winbindd_group.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index d5d3accec1..63fde9f495 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -806,8 +806,10 @@ static void getgrsid_lookupsid_recv( void *private_data, bool success, } if ( (s->group_name = talloc_asprintf( s->state->mem_ctx, - "%s\\%s", - dom_name, name )) == NULL ) + "%s%c%s", + dom_name, + *lp_winbind_separator(), + name)) == NULL ) { DEBUG(1, ("getgrsid_lookupsid_recv: talloc_asprintf() Failed!\n")); request_error(s->state); -- cgit From 7a407d5927455c4f9147dd00333dda585fab6559 Mon Sep 17 00:00:00 2001 From: Holger Hetterich Date: Fri, 11 Apr 2008 14:02:19 +0200 Subject: winbindd_cache: recognize and allow longer UA keys UA keys consist of a potientally large number of concatenated SID strings which can grow much larger than 1024 bytes in complex environments. We catch those keys and allow them exclusivly to be larger. (This used to be commit fcd35232e111f9b046ae35d939d08c29d0d43438) --- source3/winbindd/winbindd_cache.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index ddb0ab317e..5abd207e79 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -3352,9 +3352,19 @@ static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_D /* Paranoia check. */ if (kbuf.dsize > 1024) { - DEBUG(0,("cache_traverse_validate_fn: key length too large (%u) > 1024\n\n", - (unsigned int)kbuf.dsize )); - return 1; + if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0) { + unsigned int max_key_len = 1024*1024; + if (kbuf.dsize > max_key_len) { + DEBUG(0,("cache_traverse_validate_fn: UA key to large (%u) > (%u)\n\n", + (unsigned int)kbuf.dsize, (unsigned int)max_key_len )); + return 1; + } + } else { + + DEBUG(0,("cache_traverse_validate_fn: key length too large (%u) > 1024\n\n", + (unsigned int)kbuf.dsize )); + return 1; + } } for (i = 0; key_val[i].keyname; i++) { -- cgit From 65c0fd59203a3d9c4cb685e3a739f29f6f0c4fd6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Apr 2008 14:55:51 +0200 Subject: winbindd_cache: simplify logic in new key length check for UA keys. This reduces indentation by combining common code paths, and wraps long lines. Holger: sorry, I could not resist. I think it is much easier to understand what is going on when we only have one check and determine the max allowed key length in advance. Michael (This used to be commit e489f3d988feafe35b486b31a9e60c2399e6a6e7) --- source3/winbindd/winbindd_cache.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 5abd207e79..020338165b 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -3348,23 +3348,18 @@ struct key_val_struct { static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { int i; + unsigned int max_key_len = 1024; struct tdb_validation_status *v_state = (struct tdb_validation_status *)state; /* Paranoia check. */ - if (kbuf.dsize > 1024) { - if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0) { - unsigned int max_key_len = 1024*1024; - if (kbuf.dsize > max_key_len) { - DEBUG(0,("cache_traverse_validate_fn: UA key to large (%u) > (%u)\n\n", - (unsigned int)kbuf.dsize, (unsigned int)max_key_len )); - return 1; - } - } else { - - DEBUG(0,("cache_traverse_validate_fn: key length too large (%u) > 1024\n\n", - (unsigned int)kbuf.dsize )); - return 1; - } + if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0) { + max_key_len = 1024 * 1024; + } + if (kbuf.dsize > max_key_len) { + DEBUG(0, ("cache_traverse_validate_fn: key length too large: " + "(%u) > (%u)\n\n", + (unsigned int)kbuf.dsize, (unsigned int)max_key_len)); + return 1; } for (i = 0; key_val[i].keyname; i++) { -- cgit From de154dcf92ebaed23a33b6849af8aa14dc767a7d Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Tue, 22 Apr 2008 15:29:53 -0500 Subject: Mark a domain offline in the wbcDomainInfo structure using the domain_flags. Use the existing domain_flags fiueld in wbcDomainInfo to set a bit if the domain is marked as offline by Winbind. (This used to be commit 59cfba2c3d6d4594f08cbe3b7295ab36a7cfb044) --- source3/winbindd/winbindd_misc.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index bde2eafb53..8933cf2794 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -173,20 +173,29 @@ void winbindd_list_trusted_domains(struct winbindd_cli_state *state) } for ( i = 0; i < num_domains; i++ ) { + struct winbindd_domain *domain; + bool is_online = true; + d = &dom_list[i]; + domain = find_domain_from_name_noinit(d->domain_name); + if (domain) { + is_online = domain->online; + } + if ( !extra_data ) { extra_data = talloc_asprintf(state->mem_ctx, - "%s\\%s\\%s\\%s\\%s\\%s\\%s", + "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s", d->domain_name, d->dns_name ? d->dns_name : d->domain_name, sid_string_talloc(state->mem_ctx, &d->sid), get_trust_type_string(d), trust_is_transitive(d) ? "Yes" : "No", trust_is_inbound(d) ? "Yes" : "No", - trust_is_outbound(d) ? "Yes" : "No"); + trust_is_outbound(d) ? "Yes" : "No", + is_online ? "Online" : "Offline" ); } else { extra_data = talloc_asprintf(state->mem_ctx, - "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s", + "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s", extra_data, d->domain_name, d->dns_name ? d->dns_name : d->domain_name, @@ -194,7 +203,8 @@ void winbindd_list_trusted_domains(struct winbindd_cli_state *state) get_trust_type_string(d), trust_is_transitive(d) ? "Yes" : "No", trust_is_inbound(d) ? "Yes" : "No", - trust_is_outbound(d) ? "Yes" : "No"); + trust_is_outbound(d) ? "Yes" : "No", + is_online ? "Online" : "Offline" ); } } -- cgit From 0c4093a234dfaca6d363a6e1358f2fbf421dcd3c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Apr 2008 17:13:50 +0200 Subject: Fix CLEAR_IF_FIRST handling of messages.tdb We now open messages.tdb even before we do the become_daemon. become_daemon() involves a fork and an immediate exit of the parent, thus the parent_is_longlived argument must be set to false in this case. The parent is not really long lived :-) (This used to be commit 4f4781c6d17fe2db34dd5945fec52a7685448aec) --- source3/winbindd/winbindd.c | 2 +- source3/winbindd/winbindd_cm.c | 2 +- source3/winbindd/winbindd_dual.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 64674b8ace..1072f8e762 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1189,7 +1189,7 @@ int main(int argc, char **argv, char **envp) TimeInit(); - if (!reinit_after_fork(winbind_messaging_context())) { + if (!reinit_after_fork(winbind_messaging_context(), false)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index c62476e5eb..822f946e1a 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -199,7 +199,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) /* Leave messages blocked - we will never process one. */ - if (!reinit_after_fork(winbind_messaging_context())) { + if (!reinit_after_fork(winbind_messaging_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); _exit(0); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 77fbe3c0ed..14ba38cef3 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1005,7 +1005,7 @@ static bool fork_domain_child(struct winbindd_child *child) state.sock = fdpair[0]; close(fdpair[1]); - if (!reinit_after_fork(winbind_messaging_context())) { + if (!reinit_after_fork(winbind_messaging_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); _exit(0); } -- cgit From e66d452466514a16c15acf64cbb9494b46ea92c1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Apr 2008 21:28:03 +0200 Subject: mailslot: allow to define nt_version in send_getdc_request(). Guenther (This used to be commit ce3728191b23badfd5eb92701e4cebf84273b61e) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 822f946e1a..863df6ec11 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1093,7 +1093,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, /* try GETDC requests next */ if (send_getdc_request(mem_ctx, winbind_messaging_context(), - pss, domain->name, &domain->sid)) { + pss, domain->name, &domain->sid, 1)) { const char *dc_name = NULL; int i; smb_msleep(100); -- cgit From b77601a4b7c9d0f472eb51dad1d491d54a6dcbdc Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Apr 2008 21:37:42 +0200 Subject: mailslot: allow to give back struct nbt_ntlogon_packet. Guenther (This used to be commit 2b178dcae608ecc05f62593a7a0c2a127b8b7ca2) --- source3/winbindd/winbindd_cm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 863df6ec11..d27f3e47f5 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1098,7 +1098,8 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, int i; smb_msleep(100); for (i=0; i<5; i++) { - if (receive_getdc_response(mem_ctx, pss, domain->name, &dc_name)) { + if (receive_getdc_response(mem_ctx, pss, domain->name, + &dc_name, NULL)) { fstrcpy(name, dc_name); namecache_store(name, 0x20, 1, &ip_list); return True; -- cgit From c413c97ff4b646a260bc4665069f4e99d50ecd1c Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Wed, 30 Apr 2008 10:09:43 -0500 Subject: Winbind: Prevent cycle in children list when reaping dead child processes. Thanks to Glenn Curtis and Kyle Stemen @ Likewise. Their explanation is: In winbindd_dual.c, there is a list of children processes that is maintained using macros DTLIST_ADD and DTLIST_REMOVE. In the case when a scheduled_async_request fails, the particular child was located in the list, and its attributes were cleared out and it was reused for a subsequent async request. The bug was that the new request would queue the same node into the doubly-linked list and would result in list->next pointing to the same node as list itself. This would set up an infinite loop in the processing of the for loop when the list of children was referenced. Solution was to fully remove the child node from the list, such that it could be inserted without risk of being inserted twice. Note that the child is re-added to the list in fork_domain_child() again. (This used to be commit b379b5b5d8a6daccc69aaf2be6d9a6e276e7dd78) --- source3/winbindd/winbindd_dual.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 14ba38cef3..f71eec56f6 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -478,6 +478,10 @@ void winbind_child_died(pid_t pid) return; } + /* This will be re-added in fork_domain_child() */ + + DLIST_REMOVE(children, child); + remove_fd_event(&child->event); close(child->event.fd); child->event.fd = 0; -- cgit From 1f6065765c148251488acd068fdea98717f7233f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 May 2008 18:04:41 +0200 Subject: mailslot/cldap: use nt_version bits in queries. Guenther (This used to be commit b261f063125f8454d8f4e8f6b6f8aa5bc393ea34) --- source3/winbindd/winbindd_cm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d27f3e47f5..80f6bfaab3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1030,6 +1030,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, fstring name ) { struct ip_service ip_list; + uint32_t nt_version = NETLOGON_VERSION_1; ip_list.ss = *pss; ip_list.port = 0; @@ -1093,7 +1094,8 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, /* try GETDC requests next */ if (send_getdc_request(mem_ctx, winbind_messaging_context(), - pss, domain->name, &domain->sid, 1)) { + pss, domain->name, &domain->sid, + nt_version)) { const char *dc_name = NULL; int i; smb_msleep(100); -- cgit From 9be17e2187a93633b23761fc2f6f0b40c94db809 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 7 May 2008 18:57:43 +0200 Subject: dsgetdcname: mailslot replies are identical to the cldap ones, use cldap everywhere. Guenther (This used to be commit fe904ee77a7fec1674e9db660978c40c17897f77) --- source3/winbindd/winbindd_cm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 80f6bfaab3..0b0de5ad4f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1101,6 +1101,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, smb_msleep(100); for (i=0; i<5; i++) { if (receive_getdc_response(mem_ctx, pss, domain->name, + &nt_version, &dc_name, NULL)) { fstrcpy(name, dc_name); namecache_store(name, 0x20, 1, &ip_list); -- cgit From f11acf358225ecf10a8af2a12e304019adc6ee4f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 8 May 2008 14:23:20 +0200 Subject: Use strip_hostname after dsgetdcname/getdcname calls. Guenther (This used to be commit 82cbb3269b2e764c9c2a2fbcbe9c29feae07fb62) --- source3/winbindd/winbindd_cm.c | 8 +------- source3/winbindd/winbindd_locator.c | 7 ++----- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0b0de5ad4f..377b1b2d21 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -655,13 +655,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, } /* rpccli_netr_GetAnyDCName gives us a name with \\ */ - p = tmp; - if (*p == '\\') { - p+=1; - } - if (*p == '\\') { - p+=1; - } + p = strip_hostname(tmp); fstrcpy(dcname, p); diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 10a6c5afeb..f154f36c85 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -75,14 +75,11 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, } if (info->dc_address) { - dc = info->dc_address; - if ((dc[0] == '\\') && (dc[1] == '\\')) { - dc += 2; - } + dc = strip_hostname(info->dc_address); } if ((!dc || !is_ipaddress_v4(dc)) && info->dc_unc) { - dc = info->dc_unc; + dc = strip_hostname(info->dc_unc); } if (!dc || !*dc) { -- cgit From 67c644aa591c051cfe1e3f3536186ecf0b4449f2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 8 May 2008 18:32:22 +0200 Subject: dsgetdcname: use existing messaging_context if possible. Guenther (This used to be commit 7889516a384c155a9045aad4409c041fddd0d98d) --- source3/winbindd/winbindd_locator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index f154f36c85..709fbcc5d1 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -67,7 +67,8 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid, state->request.domain_name)); - result = dsgetdcname(state->mem_ctx, state->request.domain_name, + result = dsgetdcname(state->mem_ctx, winbind_messaging_context(), + state->request.domain_name, NULL, NULL, state->request.flags, &info); if (!NT_STATUS_IS_OK(result)) { -- cgit From 34933a5c236ee489e4c11172820cdc0496b9e334 Mon Sep 17 00:00:00 2001 From: coffeedude Date: Tue, 13 May 2008 12:58:52 -0500 Subject: libwbclient: Abstract the DS_XXX flags for DsGetDcName(). The wbcLookupDomainController() call supports a set of flags defined in wbclient.h. Add a mapping function between these flags and the original DS_XXX flags in order to prevent having to include the generated RPC headers in wbclient.h. (This used to be commit 31614cd5e08dd6389c66e6ddf9f2d5429c6ab033) --- source3/winbindd/winbindd.h | 1 + source3/winbindd/winbindd_locator.c | 46 ++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 0840e581fe..301d877e61 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -24,6 +24,7 @@ #define _WINBINDD_H #include "nsswitch/winbind_struct_protocol.h" +#include "nsswitch/libwbclient/wbclient.h" #ifdef HAVE_LIBNSCD #include diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c index 709fbcc5d1..b2a8bd7e30 100644 --- a/source3/winbindd/winbindd_locator.c +++ b/source3/winbindd/winbindd_locator.c @@ -54,12 +54,54 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state) sendto_child(state, locator_child()); } +struct wbc_flag_map { + uint32_t wbc_dc_flag; + uint32_t ds_dc_flags; +}; + +static uint32_t get_dsgetdc_flags(uint32_t wbc_flags) +{ + struct wbc_flag_map lookup_dc_flags[] = { + { WBC_LOOKUP_DC_FORCE_REDISCOVERY, DS_FORCE_REDISCOVERY }, + { WBC_LOOKUP_DC_DS_REQUIRED, DS_DIRECTORY_SERVICE_REQUIRED }, + { WBC_LOOKUP_DC_DS_PREFERRED, DS_DIRECTORY_SERVICE_PREFERRED}, + { WBC_LOOKUP_DC_GC_SERVER_REQUIRED, DS_GC_SERVER_REQUIRED }, + { WBC_LOOKUP_DC_PDC_REQUIRED, DS_PDC_REQUIRED}, + { WBC_LOOKUP_DC_BACKGROUND_ONLY, DS_BACKGROUND_ONLY }, + { WBC_LOOKUP_DC_IP_REQUIRED, DS_IP_REQUIRED }, + { WBC_LOOKUP_DC_KDC_REQUIRED, DS_KDC_REQUIRED }, + { WBC_LOOKUP_DC_TIMESERV_REQUIRED, DS_TIMESERV_REQUIRED }, + { WBC_LOOKUP_DC_WRITABLE_REQUIRED, DS_WRITABLE_REQUIRED }, + { WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED, DS_GOOD_TIMESERV_PREFERRED }, + { WBC_LOOKUP_DC_AVOID_SELF, DS_AVOID_SELF }, + { WBC_LOOKUP_DC_ONLY_LDAP_NEEDED, DS_ONLY_LDAP_NEEDED }, + { WBC_LOOKUP_DC_IS_FLAT_NAME, DS_IS_FLAT_NAME }, + { WBC_LOOKUP_DC_IS_DNS_NAME, DS_IS_DNS_NAME }, + { WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE, DS_TRY_NEXTCLOSEST_SITE }, + { WBC_LOOKUP_DC_DS_6_REQUIRED, DS_DIRECTORY_SERVICE_6_REQUIRED }, + { WBC_LOOKUP_DC_RETURN_DNS_NAME, DS_RETURN_DNS_NAME }, + { WBC_LOOKUP_DC_RETURN_FLAT_NAME, DS_RETURN_FLAT_NAME } + }; + uint32_t ds_flags = 0; + int i = 0 ; + int num_entries = sizeof(lookup_dc_flags) / sizeof(struct wbc_flag_map); + + for (i=0; irequest.domain_name [sizeof(state->request.domain_name)-1] = '\0'; @@ -67,9 +109,11 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid, state->request.domain_name)); + ds_flags = get_dsgetdc_flags(state->request.flags); + result = dsgetdcname(state->mem_ctx, winbind_messaging_context(), state->request.domain_name, - NULL, NULL, state->request.flags, &info); + NULL, NULL, ds_flags, &info); if (!NT_STATUS_IS_OK(result)) { return WINBINDD_ERROR; -- cgit From a6b0ea8ee341fde28e568f8e1a4f16d9a89425c8 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 13 May 2008 16:57:01 -0400 Subject: Enable winbind child processes to do something with signals, in particular closing and reopening logs on SIGHUP. Conflicts: source/winbindd/winbindd.c (This used to be commit 0f7b11accec7df1c0e9a9dc0828a5e0c5ddec4cb) --- source3/winbindd/winbindd.c | 35 +++++++++++++++++++++++------------ source3/winbindd/winbindd_dual.c | 4 ++++ 2 files changed, 27 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 1072f8e762..57eee20f49 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -795,6 +795,27 @@ static bool remove_idle_client(void) return False; } +/* check if HUP has been received and reload files */ +void winbind_check_sighup(void) +{ + if (do_sighup) { + + DEBUG(3, ("got SIGHUP\n")); + + flush_caches(); + reload_services_file(); + + do_sighup = False; + } +} + +/* check if TERM has been received */ +void winbind_check_sigterm(void) +{ + if (do_sigterm) + terminate(); +} + /* Process incoming clients on listen_sock. We use a tricky non-blocking, non-forking, non-threaded model which allows us to handle many simultaneous connections while remaining impervious to many denial of @@ -954,18 +975,8 @@ static void process_loop(void) /* Check signal handling things */ - if (do_sigterm) - terminate(); - - if (do_sighup) { - - DEBUG(3, ("got SIGHUP\n")); - - flush_caches(); - reload_services_file(); - - do_sighup = False; - } + winbind_check_sigterm(); + winbind_check_sighup(); if (do_sigusr2) { print_winbindd_status(); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index f71eec56f6..1d741be79e 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1105,6 +1105,10 @@ static bool fork_domain_child(struct winbindd_child *child) struct timeval now; TALLOC_CTX *frame = talloc_stackframe(); + /* check for signals */ + winbind_check_sigterm(); + winbind_check_sighup(); + run_events(winbind_event_context(), 0, NULL, NULL); GetTimeOfDay(&now); -- cgit From 5e70a25116f4b7355e3995a74e586da7832dff39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 May 2008 14:10:39 -0700 Subject: Fix bug #5464. Pointed out by Herb @ Connectathon. In fork_domain_child() we call : CatchChild(); *before* we fork the domain child. This call establishes a signal handler that eats SIGCLD signals and doesn't call sys_select_signal() as the main daemon SIGCLD handler should do. This causes the parent to ignore dead children and time out, instead of calling winbind_child_died() on receipt of the signal. The correct fix is to move the CatchChild call into the child code after the fork. Jeremy. (This used to be commit 8d701a142be2b75dc30ad215bc178af902eb4af9) --- source3/winbindd/winbindd_dual.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 1d741be79e..d46580155c 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -982,9 +982,6 @@ static bool fork_domain_child(struct winbindd_child *child) ZERO_STRUCT(state); state.pid = sys_getpid(); - /* Stop zombies */ - CatchChild(); - child->pid = sys_fork(); if (child->pid == -1) { @@ -1006,6 +1003,9 @@ static bool fork_domain_child(struct winbindd_child *child) /* Child */ + /* Stop zombies in children */ + CatchChild(); + state.sock = fdpair[0]; close(fdpair[1]); -- cgit From 03dcad0b271ab348149431340317d053308614bd Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 18 May 2008 23:09:34 +0200 Subject: winbindd: freeze winbindd_proto.h Michael (This used to be commit 467b8f0f4d58fc00d07264c651016087bd00b233) --- source3/winbindd/winbindd_proto.h | 583 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 583 insertions(+) create mode 100644 source3/winbindd/winbindd_proto.h (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h new file mode 100644 index 0000000000..8ec6f7e108 --- /dev/null +++ b/source3/winbindd/winbindd_proto.h @@ -0,0 +1,583 @@ +/* + * Unix SMB/CIFS implementation. + * collected prototypes header + * + * frozen from "make proto" in May 2008 + * + * Copyright (C) Michael Adam 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _WINBINDD_PROTO_H_ +#define _WINBINDD_PROTO_H_ + + +/* The following definitions come from auth/token_util.c */ + +bool nt_token_check_sid ( const DOM_SID *sid, const NT_USER_TOKEN *token ); +bool nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid ); +NT_USER_TOKEN *get_root_nt_token( void ); +NTSTATUS add_aliases(const DOM_SID *domain_sid, + struct nt_user_token *token); +struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + bool is_guest, + int num_groupsids, + const DOM_SID *groupsids); +void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token); +void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, + int n_groups, gid_t *groups); + +/* The following definitions come from smbd/connection.c */ + +bool yield_connection(connection_struct *conn, const char *name); +int count_current_connections( const char *sharename, bool clear ); +int count_all_current_connections(void); +bool claim_connection(connection_struct *conn, const char *name, + uint32 msg_flags); +bool register_message_flags(bool doreg, uint32 msg_flags); +bool store_pipe_opendb( smb_np_struct *p ); +bool delete_pipe_opendb( smb_np_struct *p ); + +/* The following definitions come from winbindd/winbindd.c */ + +struct event_context *winbind_event_context(void); +struct messaging_context *winbind_messaging_context(void); +void add_fd_event(struct fd_event *ev); +void remove_fd_event(struct fd_event *ev); +void setup_async_read(struct fd_event *event, void *data, size_t length, + void (*finished)(void *private_data, bool success), + void *private_data); +void setup_async_write(struct fd_event *event, void *data, size_t length, + void (*finished)(void *private_data, bool success), + void *private_data); +void request_error(struct winbindd_cli_state *state); +void request_ok(struct winbindd_cli_state *state); +void request_finished_cont(void *private_data, bool success); +void winbind_check_sighup(void); +void winbind_check_sigterm(void); +int main(int argc, char **argv, char **envp); + +/* The following definitions come from winbindd/winbindd_ads.c */ + + +/* The following definitions come from winbindd/winbindd_async.c */ + +void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data); +void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data); +void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, bool success, + const char *dom_name, + const char *name, + enum lsa_SidType type), + void *private_data); +enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, + const char *dom_name, const char *name, + void (*cont)(void *private_data, bool success, + const DOM_SID *sid, + enum lsa_SidType type), + enum winbindd_cmd orig_cmd, + void *private_data); +enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, + size_t num_sids, char **result, ssize_t *len); +enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_getsidaliases_async(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sids, size_t num_sids, + void (*cont)(void *private_data, + bool success, + const DOM_SID *aliases, + size_t num_aliases), + void *private_data); +enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, + void (*cont)(void *private_data, bool success, + DOM_SID *sids, size_t num_sids), + void *private_data); +void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const DOM_SID *sid, + void (*cont)(void *private_data, bool success, + const char *acct_name, + const char *full_name, + const char *homedir, + const char *shell, + gid_t gid, + uint32 group_rid), + void *private_data); + +/* The following definitions come from winbindd/winbindd_cache.c */ + +void winbindd_check_cache_size(time_t t); +struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status); +NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid); +NTSTATUS wcache_get_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const uint8 **cached_nt_pass, + const uint8 **cached_salt); +NTSTATUS wcache_save_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const uint8 nt_pass[NT_HASH_LEN]); +void wcache_invalidate_samlogon(struct winbindd_domain *domain, + struct netr_SamInfo3 *info3); +bool wcache_invalidate_cache(void); +bool init_wcache(void); +bool initialize_winbindd_cache(void); +void close_winbindd_cache(void); +void cache_store_response(pid_t pid, struct winbindd_response *response); +bool cache_retrieve_response(pid_t pid, struct winbindd_response * response); +void cache_cleanup_response(pid_t pid); +bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain_name, char **name, + enum lsa_SidType *type); +bool lookup_cached_name(TALLOC_CTX *mem_ctx, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type); +void cache_name2sid(struct winbindd_domain *domain, + const char *domain_name, const char *name, + enum lsa_SidType type, const DOM_SID *sid); +void wcache_flush_cache(void); +NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count); +NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) ; +bool set_global_winbindd_state_offline(void); +void set_global_winbindd_state_online(void); +bool get_global_winbindd_state_offline(void); +int winbindd_validate_cache(void); +int winbindd_validate_cache_nobackup(void); +bool winbindd_cache_validate_and_initialize(void); +bool wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_domains ); +bool wcache_tdc_add_domain( struct winbindd_domain *domain ); +struct winbindd_tdc_domain * wcache_tdc_fetch_domain( TALLOC_CTX *ctx, const char *name ); +void wcache_tdc_clear( void ); +NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, + const DOM_SID *user_sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, LDAPMessage *msg, + char **homedir, char **shell, char **gecos, + gid_t *p_gid); + +/* The following definitions come from winbindd/winbindd_ccache_access.c */ + +void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_cm.c */ + +void set_domain_offline(struct winbindd_domain *domain); +void set_domain_online_request(struct winbindd_domain *domain); +void winbind_add_failed_connection_entry(const struct winbindd_domain *domain, + const char *server, + NTSTATUS result); +void invalidate_cm_connection(struct winbindd_cm_conn *conn); +void close_conns_after_fork(void); +NTSTATUS init_dc_connection(struct winbindd_domain *domain); +NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **cli, POLICY_HND *sam_handle); +NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **cli, POLICY_HND *lsa_policy); +NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + struct rpc_pipe_client **cli); + +/* The following definitions come from winbindd/winbindd_cred_cache.c */ + +bool ccache_entry_exists(const char *username); +bool ccache_entry_identical(const char *username, + uid_t uid, + const char *ccname); +NTSTATUS add_ccache_to_list(const char *princ_name, + const char *ccname, + const char *service, + const char *username, + const char *realm, + uid_t uid, + time_t create_time, + time_t ticket_end, + time_t renew_until, + bool postponed_request); +NTSTATUS remove_ccache(const char *username); +struct WINBINDD_MEMORY_CREDS *find_memory_creds_by_name(const char *username); +NTSTATUS winbindd_add_memory_creds(const char *username, + uid_t uid, + const char *pass); +NTSTATUS winbindd_delete_memory_creds(const char *username); +NTSTATUS winbindd_replace_memory_creds(const char *username, + const char *pass); + +/* The following definitions come from winbindd/winbindd_creds.c */ + +NTSTATUS winbindd_get_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + struct netr_SamInfo3 **info3, + const uint8 *cached_nt_pass[NT_HASH_LEN], + const uint8 *cred_salt[NT_HASH_LEN]); +NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass, + struct netr_SamInfo3 *info3, + const DOM_SID *user_sid); +NTSTATUS winbindd_update_creds_by_info3(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass, + struct netr_SamInfo3 *info3); +NTSTATUS winbindd_update_creds_by_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + const char *pass); +NTSTATUS winbindd_update_creds_by_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const char *user, + const char *pass); + +/* The following definitions come from winbindd/winbindd_domain.c */ + +void setup_domain_child(struct winbindd_domain *domain, + struct winbindd_child *child); + +/* The following definitions come from winbindd/winbindd_dual.c */ + +void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, + struct winbindd_request *request, + struct winbindd_response *response, + void (*continuation)(void *private_data, bool success), + void *private_data); +void async_domain_request(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + struct winbindd_request *request, + struct winbindd_response *response, + void (*continuation)(void *private_data_data, bool success), + void *private_data_data); +void sendto_child(struct winbindd_cli_state *state, + struct winbindd_child *child); +void sendto_domain(struct winbindd_cli_state *state, + struct winbindd_domain *domain); +void setup_child(struct winbindd_child *child, + const struct winbindd_child_dispatch_table *table, + const char *logprefix, + const char *logname); +void winbind_child_died(pid_t pid); +void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain); +void winbind_msg_offline(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); +void winbind_msg_online(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); +void winbind_msg_onlinestatus(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); +void winbind_msg_dump_event_list(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); +void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); + +/* The following definitions come from winbindd/winbindd_group.c */ + +void winbindd_getgrnam(struct winbindd_cli_state *state); +void winbindd_getgrgid(struct winbindd_cli_state *state); +void winbindd_setgrent(struct winbindd_cli_state *state); +void winbindd_endgrent(struct winbindd_cli_state *state); +void winbindd_getgrent(struct winbindd_cli_state *state); +void winbindd_list_groups(struct winbindd_cli_state *state); +void winbindd_getgroups(struct winbindd_cli_state *state); +void winbindd_getusersids(struct winbindd_cli_state *state); +void winbindd_getuserdomgroups(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_idmap.c */ + +void init_idmap_child(void); +struct winbindd_child *idmap_child(void); +void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map, + void (*cont)(void *private_data, bool success), + void *private_data); +enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid, + void (*cont)(void *private_data, bool success), + void *private_data); +enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, + void (*cont)(void *private_data, bool success, void *data, int len), + void *private_data); +enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, bool success, uid_t uid), + void *private_data); +enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + void (*cont)(void *private_data, bool success, gid_t gid), + void *private_data); +enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, + void (*cont)(void *private_data, bool success, const char *sid), + void *private_data); +enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, + void (*cont)(void *private_data, bool success, const char *sid), + void *private_data); +enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_locator.c */ + +void init_locator_child(void); +struct winbindd_child *locator_child(void); +void winbindd_dsgetdcname(struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_misc.c */ + +void winbindd_check_machine_acct(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_list_trusted_domains(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_getdcname(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_show_sequence(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_domain_info(struct winbindd_cli_state *state); +void winbindd_ping(struct winbindd_cli_state *state); +void winbindd_info(struct winbindd_cli_state *state); +void winbindd_interface_version(struct winbindd_cli_state *state); +void winbindd_domain_name(struct winbindd_cli_state *state); +void winbindd_netbios_name(struct winbindd_cli_state *state); +void winbindd_priv_pipe_dir(struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_ndr.c */ + +void ndr_print_winbindd_child(struct ndr_print *ndr, + const char *name, + const struct winbindd_child *r); +void ndr_print_winbindd_cm_conn(struct ndr_print *ndr, + const char *name, + const struct winbindd_cm_conn *r); +void ndr_print_winbindd_methods(struct ndr_print *ndr, + const char *name, + const struct winbindd_methods *r); +void ndr_print_winbindd_domain(struct ndr_print *ndr, + const char *name, + const struct winbindd_domain *r); + +/* The following definitions come from winbindd/winbindd_pam.c */ + +struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, + const char *domain_name); +void winbindd_pam_auth(struct winbindd_cli_state *state); +NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3); +NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3); +NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3); +enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, + struct winbindd_cli_state *state) ; +void winbindd_pam_auth_crap(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + struct winbindd_cli_state *state) ; +void winbindd_pam_chauthtok(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, + struct winbindd_cli_state *state); +void winbindd_pam_logoff(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, + struct winbindd_cli_state *state) ; +void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_passdb.c */ + + +/* The following definitions come from winbindd/winbindd_reconnect.c */ + + +/* The following definitions come from winbindd/winbindd_rpc.c */ + +NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + enum winbindd_cmd original_cmd, + const char *domain_name, + const char *name, + DOM_SID *sid, + enum lsa_SidType *type); +NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + char **domain_name, + char **name, + enum lsa_SidType *type); +NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum lsa_SidType **types); +NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID *sids, + uint32 *num_aliases, uint32 **alias_rids); +NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + struct samr_DomInfo12 *lockout_policy); +NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + struct samr_DomInfo1 *password_policy); + +/* The following definitions come from winbindd/winbindd_sid.c */ + +void winbindd_lookupsid(struct winbindd_cli_state *state); +void winbindd_lookupname(struct winbindd_cli_state *state); +void winbindd_lookuprids(struct winbindd_cli_state *state); +void winbindd_sid_to_uid(struct winbindd_cli_state *state); +void winbindd_sid_to_gid(struct winbindd_cli_state *state); +void winbindd_sids_to_unixids(struct winbindd_cli_state *state); +void winbindd_set_mapping(struct winbindd_cli_state *state); +void winbindd_set_hwm(struct winbindd_cli_state *state); +void winbindd_uid_to_sid(struct winbindd_cli_state *state); +void winbindd_gid_to_sid(struct winbindd_cli_state *state); +void winbindd_allocate_uid(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_allocate_gid(struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_user.c */ + +enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +void winbindd_getpwnam(struct winbindd_cli_state *state); +void winbindd_getpwuid(struct winbindd_cli_state *state); +void winbindd_setpwent(struct winbindd_cli_state *state); +void winbindd_endpwent(struct winbindd_cli_state *state); +void winbindd_getpwent(struct winbindd_cli_state *state); +void winbindd_list_users(struct winbindd_cli_state *state); + +/* The following definitions come from winbindd/winbindd_util.c */ + +struct winbindd_domain *domain_list(void); +void free_domain_list(void); +void rescan_trusted_domains( void ); +enum winbindd_result init_child_connection(struct winbindd_domain *domain, + void (*continuation)(void *private_data, + bool success), + void *private_data); +enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +bool init_domain_list(void); +void check_domain_trusted( const char *name, const DOM_SID *user_sid ); +struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name); +struct winbindd_domain *find_domain_from_name(const char *domain_name); +struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid); +struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid); +struct winbindd_domain *find_our_domain(void); +struct winbindd_domain *find_root_domain(void); +struct winbindd_domain *find_builtin_domain(void); +struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid); +struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name); +bool winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx, + enum winbindd_cmd orig_cmd, + struct winbindd_domain *domain, + const char *domain_name, + const char *name, DOM_SID *sid, + enum lsa_SidType *type); +bool winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + DOM_SID *sid, + char **dom_name, + char **name, + enum lsa_SidType *type); +void free_getent_state(struct getent_state *state); +bool parse_domain_user(const char *domuser, fstring domain, fstring user); +bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, + char **domain, char **user); +bool canonicalize_username(fstring username_inout, fstring domain, fstring user); +void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume); +const char *get_winbind_pipe_dir(void) ; +char *get_winbind_priv_pipe_dir(void) ; +int open_winbindd_socket(void); +int open_winbindd_priv_socket(void); +void close_winbindd_socket(void); +struct winbindd_cli_state *winbindd_client_list(void); +void winbindd_add_client(struct winbindd_cli_state *cli); +void winbindd_remove_client(struct winbindd_cli_state *cli); +void winbindd_kill_all_clients(void); +int winbindd_num_clients(void); +NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + uint32 *p_num_groups, DOM_SID **user_sids); +void ws_name_replace( char *name, char replace ); +void ws_name_return( char *name, char replace ); +bool winbindd_can_contact_domain(struct winbindd_domain *domain); +bool winbindd_internal_child(struct winbindd_child *child); +void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain); +void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain); +void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain); +void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain); + +/* The following definitions come from winbindd/winbindd_wins.c */ + +void winbindd_wins_byip(struct winbindd_cli_state *state); +void winbindd_wins_byname(struct winbindd_cli_state *state); + +#endif /* _WINBINDD_PROTO_H_ */ -- cgit From 96653e1ff7551dd9214dc14eed4029e2214598f8 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Wed, 21 May 2008 20:16:33 -0700 Subject: Make WINBINDD_LIST_GROUPS handler asynchronous. Previously WINBINDD_LIST_GROUPS requests (ex: wbinfo -g) were handled by the winbindd parent process in a sequential fashion. This patch, delegates the work to the winbindd children so that the request is handled much faster in large domain topologies, and doesn't block the parent from receiving new requests. The core group enumeration and conversion that was handled in winbindd_list_groups() has been moved into winbindd_dual_list_groups() to be done by the child. The parent winbindd_list_groups() simply calls each of the children asynchronously. listgroups_recv() aggregates the final group list that will be returned to the client and tracks how many of the children have returned their lists. The domain name of the child is passed back through the callbacks to be used in debugging messages. There are also several fixes to typos in various comments. (This used to be commit 037b9689d9042a398cb91e4628a82fcdfa913c21) --- source3/winbindd/winbindd_ads.c | 2 +- source3/winbindd/winbindd_async.c | 91 +++++++++++++++++++++++++ source3/winbindd/winbindd_cache.c | 2 +- source3/winbindd/winbindd_domain.c | 4 ++ source3/winbindd/winbindd_group.c | 136 +++++++++++++++++++++---------------- source3/winbindd/winbindd_proto.h | 12 ++++ 6 files changed, 187 insertions(+), 60 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 8be6a47998..5e3d5d2aec 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -393,7 +393,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, * using LDAP. * * if we ever need to enumerate domain local groups separately, - * then this the optimization in enum_dom_groups() will need + * then this optimization in enum_dom_groups() will need * to be split out */ *num_entries = 0; diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 2ff5ef230d..635bc6b244 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -453,6 +453,97 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } +/* This is the first callback after enumerating groups from a domain */ +static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, + struct winbindd_response *response, + void *c, void *private_data) +{ + void (*cont)(void *priv, bool succ, fstring dom_name, char *data) = + (void (*)(void *, bool, fstring, char*))c; + + if (!success || response->result != WINBINDD_OK) { + DEBUG(5, ("list_groups() failed!\n")); + cont(private_data, False, response->data.name.dom_name, NULL); + return; + } + + cont(private_data, True, response->data.name.dom_name, + response->extra_data.data); + + SAFE_FREE(response->extra_data.data); +} + +/* Request the name of all groups in a single domain */ +void winbindd_listgroups_async(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + void (*cont)(void *private_data, bool success, + fstring dom_name, char* extra_data), + void *private_data) +{ + struct winbindd_request request; + + ZERO_STRUCT(request); + request.cmd = WINBINDD_LIST_GROUPS; + + do_async_domain(mem_ctx, domain, &request, listgroups_recv, + (void *)cont, private_data); +} + +enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct getent_state groups = {}; + char *extra_data = NULL; + unsigned int extra_data_len = 0, i; + + /* Must copy domain into response first for bookeeping in parent */ + fstrcpy(state->response.data.name.dom_name, domain->name); + fstrcpy(groups.domain_name, domain->name); + + /* Get list of sam groups */ + if (!get_sam_group_entries(&groups)) { + /* this domain is empty or in an error state */ + return WINBINDD_ERROR; + } + + /* Allocate some memory for extra data. Note that we limit + account names to sizeof(fstring) = 256 characters. + +1 for the ',' between group names */ + extra_data = (char *)SMB_REALLOC(extra_data, + (sizeof(fstring) + 1) * groups.num_sam_entries); + + if (!extra_data) { + DEBUG(0,("failed to enlarge buffer!\n")); + SAFE_FREE(groups.sam_entries); + return WINBINDD_ERROR; + } + + /* Pack group list into extra data fields */ + for (i = 0; i < groups.num_sam_entries; i++) { + char *group_name = ((struct acct_info *) + groups.sam_entries)[i].acct_name; + fstring name; + + fill_domain_username(name, domain->name, group_name, True); + /* Append to extra data */ + memcpy(&extra_data[extra_data_len], name, strlen(name)); + extra_data_len += strlen(name); + extra_data[extra_data_len++] = ','; + } + + SAFE_FREE(groups.sam_entries); + + /* Assign extra_data fields in response structure */ + if (extra_data) { + /* remove trailing ',' */ + extra_data[extra_data_len - 1] = '\0'; + state->response.extra_data.data = extra_data; + state->response.length += extra_data_len; + } + + return WINBINDD_OK; +} + bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, size_t num_sids, char **result, ssize_t *len) { diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 020338165b..f0ff0294f3 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -524,7 +524,7 @@ static void refresh_sequence_number(struct winbindd_domain *domain, bool force) domain->last_status = status; domain->last_seq_check = time(NULL); - /* save the new sequence number ni the cache */ + /* save the new sequence number in the cache */ store_cache_seqnum( domain ); done: diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c index 1b758cdf40..4d10f49ca2 100644 --- a/source3/winbindd/winbindd_domain.c +++ b/source3/winbindd/winbindd_domain.c @@ -49,6 +49,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { .name = "LOOKUPRIDS", .struct_cmd = WINBINDD_LOOKUPRIDS, .struct_fn = winbindd_dual_lookuprids, + },{ + .name = "LIST_GROUPS", + .struct_cmd = WINBINDD_LIST_GROUPS, + .struct_fn = winbindd_dual_list_groups, },{ .name = "LIST_TRUSTDOM", .struct_cmd = WINBINDD_LIST_TRUSTDOM, diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 63fde9f495..dd2fc6f6b5 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -971,10 +971,9 @@ void winbindd_endgrent(struct winbindd_cli_state *state) /* Get the list of domain groups and domain aliases for a domain. We fill in the sam_entries and num_sam_entries fields with domain group information. - The dispinfo_ndx field is incremented to the index of the next group to - fetch. Return True if some groups were returned, False otherwise. */ + Return True if some groups were returned, False otherwise. */ -static bool get_sam_group_entries(struct getent_state *ent) +bool get_sam_group_entries(struct getent_state *ent) { NTSTATUS status; uint32 num_entries; @@ -1340,15 +1339,23 @@ void winbindd_getgrent(struct winbindd_cli_state *state) request_error(state); } -/* List domain groups without mapping to unix ids */ +struct listgroups_state { + TALLOC_CTX *mem_ctx; + struct winbindd_cli_state *cli_state; + unsigned int domain_count; + char *extra_data; + unsigned int extra_data_len; +}; +static void listgroups_recv(void *private_data, bool success, fstring dom_name, + char *extra_data); + +/* List domain groups without mapping to unix ids */ void winbindd_list_groups(struct winbindd_cli_state *state) { - uint32 total_entries = 0; struct winbindd_domain *domain; const char *which_domain; - char *extra_data = NULL; - unsigned int extra_data_len = 0, i; + struct listgroups_state *groups_state; DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid)); @@ -1356,74 +1363,87 @@ void winbindd_list_groups(struct winbindd_cli_state *state) state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; which_domain = state->request.domain_name; - /* Enumerate over trusted domains */ + /* Initialize listgroups_state */ + groups_state = TALLOC_P(state->mem_ctx, struct listgroups_state); + if (groups_state == NULL) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } - for (domain = domain_list(); domain; domain = domain->next) { - struct getent_state groups; + groups_state->mem_ctx = state->mem_ctx; + groups_state->cli_state = state; + groups_state->domain_count = 0; + groups_state->extra_data = NULL; + groups_state->extra_data_len = 0; + /* Must count the full list of expected domains before we request data + * from any of them. Otherwise it's possible for a connection to the + * first domain to fail, call listgroups_recv(), and return to the + * client without checking any other domains. */ + for (domain = domain_list(); domain; domain = domain->next) { /* if we have a domain name restricting the request and this one in the list doesn't match, then just bypass the remainder of the loop */ - if ( *which_domain && !strequal(which_domain, domain->name) ) continue; - - ZERO_STRUCT(groups); - /* Get list of sam groups */ - - fstrcpy(groups.domain_name, domain->name); - - get_sam_group_entries(&groups); - - if (groups.num_sam_entries == 0) { - /* this domain is empty or in an error state */ - continue; - } + groups_state->domain_count++; + } - /* keep track the of the total number of groups seen so - far over all domains */ - total_entries += groups.num_sam_entries; - - /* Allocate some memory for extra data. Note that we limit - account names to sizeof(fstring) = 128 characters. */ - extra_data = (char *)SMB_REALLOC( - extra_data, sizeof(fstring) * total_entries); - - if (!extra_data) { - DEBUG(0,("failed to enlarge buffer!\n")); - request_error(state); - return; - } + /* Make sure we're enumerating at least one domain */ + if (!groups_state->domain_count) { + request_ok(state); + return; + } - /* Pack group list into extra data fields */ - for (i = 0; i < groups.num_sam_entries; i++) { - char *group_name = ((struct acct_info *) - groups.sam_entries)[i].acct_name; - fstring name; - - fill_domain_username(name, domain->name, group_name, True); - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } + /* Enumerate list of trusted domains and request group list from each */ + for (domain = domain_list(); domain; domain = domain->next) { + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; - SAFE_FREE(groups.sam_entries); + winbindd_listgroups_async(state->mem_ctx, domain, + listgroups_recv, groups_state); } +} + +static void listgroups_recv(void *private_data, bool success, fstring dom_name, + char *extra_data) +{ + /* extra_data comes to us as a '\0' terminated string of comma + separated groups */ + struct listgroups_state *state = private_data; - /* Assign extra_data fields in response structure */ + /* Append groups from one domain onto the whole list */ if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data.data = extra_data; - state->response.length += extra_data_len; + DEBUG(5, ("listgroups_recv: %s returned groups.\n", dom_name)); + if (!state->extra_data) + state->extra_data = talloc_asprintf(state->mem_ctx, + "%s", extra_data); + else + state->extra_data = talloc_asprintf_append_buffer( + state->extra_data, + ",%s", extra_data); + /* Add one for the '\0' and each additional ',' */ + state->extra_data_len += strlen(extra_data) + 1; + } + else { + DEBUG(5, ("listgroups_recv: %s returned no groups.\n", + dom_name)); } - /* No domains may have responded but that's still OK so don't - return an error. */ + if (--state->domain_count) + /* Still waiting for some child domains to return */ + return; - request_ok(state); + /* Return list of all groups to the client */ + if (state->extra_data) { + state->cli_state->response.extra_data.data = + SMB_STRDUP(state->extra_data); + state->cli_state->response.length += state->extra_data_len; + } + + request_ok(state->cli_state); } /* Get user supplementary groups. This is much quicker than trying to diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 8ec6f7e108..f6a0da8fff 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -133,6 +133,16 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, uint32 group_rid), void *private_data); +void winbindd_listgroups_async(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + void (*cont)(void *private_data, bool success, + fstring dom_name, char* extra_data), + void *private_data); + +enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, + struct winbindd_cli_state *state); + + /* The following definitions come from winbindd/winbindd_cache.c */ void winbindd_check_cache_size(time_t t); @@ -330,6 +340,8 @@ void winbindd_getusersids(struct winbindd_cli_state *state); void winbindd_getuserdomgroups(struct winbindd_cli_state *state); enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain, struct winbindd_cli_state *state); +bool get_sam_group_entries(struct getent_state *ent); + /* The following definitions come from winbindd/winbindd_idmap.c */ -- cgit From cfde5c8d478ced2b02e1711aeee6f609c5e97e4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2008 14:19:14 -0700 Subject: Get rid of "shadowed local var" warnings with gcc. Jeremy. (This used to be commit 0bc18967aa7cb6f4debeaa48be81d0e48a7d9503) --- source3/winbindd/winbindd_pam.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 2de10a9f10..f548a04d35 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1290,12 +1290,12 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, uint32 logon_parameters, const char *server, const char *username, - const char *domain, + const char *ldomain, const char *workstation, - const uint8 chal[8], + const uint8 lchal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); + struct netr_SamInfo3 **linfo3); ZERO_STRUCTP(my_info3); retry = False; @@ -1868,12 +1868,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, uint32 logon_parameters, const char *server, const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], + const char *ldomain, + const char *lworkstation, + const uint8 lchal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); + struct netr_SamInfo3 **linfo3); retry = False; -- cgit From b72fc49f441c969a44b3325677cde55670416b24 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Fri, 23 May 2008 15:19:58 -0500 Subject: Manually port Steven Dannenman fix for using the correct machine domain when looking up trust credentials in our tdb. commit fd0ae47046d37ec8297396a2733209c4d999ea91 Author: Steven Danneman Date: Thu May 8 13:34:49 2008 -0700 Use machine account and machine password from our domain when contacting trusted domains. (This used to be commit 69b37ae60757075a0712149c5f97f17ee22c2e41) --- source3/winbindd/winbindd_cm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 377b1b2d21..9bab80377a 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -706,12 +706,12 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - /* this is at least correct when domain is our domain, - * which is the only case, when this is currently used: */ + /* For now assume our machine account only exists in our domain */ + if (machine_krb5_principal != NULL) { if (asprintf(machine_krb5_principal, "%s$@%s", - account_name, domain->alt_name) == -1) + account_name, lp_realm()) == -1) { return NT_STATUS_NO_MEMORY; } -- cgit From 4d2f71e53f5a6cdc5b84a0eeab5822a7f8ca48b9 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Fri, 23 May 2008 16:01:45 -0500 Subject: Manually merge Steven Danneman's patch for SPNEGO auth to a trusted Win2008 domain (merged from v3-0-test). commit 8dc4e979776aae0ecaa74b51dc1eac78a7631405 Author: Steven Danneman Date: Wed May 7 13:34:26 2008 -0700 spnego SPN fix when contacting trusted domains cli_session_setup_spnego() was not taking into consideration the situation where we're connecting to a trusted domain, specifically one (like W2K8) which doesn't return a SPN in the NegTokenInit. This caused two problems: 1) When guessing the SPN using kerberos_get_default_realm_from_ccache() we were always using our default realm, not the realm of the domain we're connecting to. 2) When falling back on NTLMSSP for authentication we were passing the name of the domain we're connecting to for use in our credentials when we should be passing our own workgroup name. The fix for both was to split the single "domain" parameter into "user_domain" and "dest_realm" parameters. We use the "user_domain" parameter to pass into the NTLM call, and we used "dest_realm" to create an SPN if none was returned in the NegTokenInit2 packet. If no "dest_realm" is provided we assume we're connecting to our own domain and use the credentials cache to build the SPN. Since we have a reasonable guess at the SPN, I removed the check that defaults us directly to NTLM when negHint is empty. (This used to be commit b78b14c88e8354aadf9ba7644bdb1c29245fe419) --- source3/winbindd/winbindd_cm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 9bab80377a..2ee0fae6db 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -827,14 +827,15 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, (*cli)->use_kerberos = True; DEBUG(5, ("connecting to %s from %s with kerberos principal " - "[%s]\n", controller, global_myname(), - machine_krb5_principal)); + "[%s] and realm [%s]\n", controller, global_myname(), + machine_krb5_principal, domain->alt_name)); winbindd_set_locator_kdc_envs(domain); ads_status = cli_session_setup_spnego(*cli, machine_krb5_principal, - machine_password, + machine_password, + lp_workgroup(), domain->name); if (!ADS_ERR_OK(ads_status)) { @@ -855,12 +856,13 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(5, ("connecting to %s from %s with username " "[%s]\\[%s]\n", controller, global_myname(), - domain->name, machine_account)); + lp_workgroup(), machine_account)); ads_status = cli_session_setup_spnego(*cli, machine_account, machine_password, - domain->name); + lp_workgroup(), + NULL); if (!ADS_ERR_OK(ads_status)) { DEBUG(4, ("authenticated session setup failed with %s\n", ads_errstr(ads_status))); -- cgit From 1a1fc2f8146ebc6cda852b236c9589e282e4bd8c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 25 May 2008 13:51:14 +0200 Subject: Fix two c++ warnings (This used to be commit 3b1dae7c31b881834ca4494c4434ae97a56ce6c7) --- source3/winbindd/winbindd_async.c | 2 +- source3/winbindd/winbindd_group.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 635bc6b244..bc0f9d836b 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -468,7 +468,7 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, } cont(private_data, True, response->data.name.dom_name, - response->extra_data.data); + (char *)response->extra_data.data); SAFE_FREE(response->extra_data.data); } diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index dd2fc6f6b5..d10609a83f 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1412,7 +1412,8 @@ static void listgroups_recv(void *private_data, bool success, fstring dom_name, { /* extra_data comes to us as a '\0' terminated string of comma separated groups */ - struct listgroups_state *state = private_data; + struct listgroups_state *state = talloc_get_type_abort( + private_data, struct listgroups_state); /* Append groups from one domain onto the whole list */ if (extra_data) { -- cgit From c5a030a38a520e2cd89dc061f4d2bfee57ce9d84 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 26 May 2008 12:38:48 +0200 Subject: winbind: correctly omit check for trusted domain support in cm_prepare_connection when checking for a trusted domain situation. This is how it was meant to be: Otherwise, with a dc-trusted-domain situation but trusted domains disabled, we would attempt to do a session setup and fail (wouldn't even get a trust password). Michael (This used to be commit a5a51ca8e5971992d9b060d66201b808bd2b7a53) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 2ee0fae6db..a1027cec97 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -808,7 +808,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - if (!is_trusted_domain_situation(domain->name) && + if (!is_dc_trusted_domain_situation(domain->name) && (*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { -- cgit From 433a05c1abfa4f67bbbb4633db69ba7e01921800 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 May 2008 10:37:52 -0700 Subject: Fix winbindd on a PDC by reverting : 83b04c60fac76ccd2d5aecb14f8896a07d488b1f..6e66512d5beb256a44c6703cdb8c7fa7e0fd8537. We still need to address https://bugzilla.redhat.com/show_bug.cgi?id=429024, but this will come later. Jeremy. (This used to be commit 41e20becf3b976656f60aaec9175df329803b012) --- source3/winbindd/winbindd_dual.c | 9 --------- source3/winbindd/winbindd_util.c | 6 ++++++ 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index d46580155c..ae042563ed 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1087,15 +1087,6 @@ static bool fork_domain_child(struct winbindd_child *child) child); } - /* Special case for Winbindd on a Samba DC, - * We want to make sure the child can connect to smbd - * but not the main daemon */ - - if (child->domain && child->domain->internal && IS_DC) { - child->domain->methods = &cache_methods; - child->domain->online = False; - } - while (1) { int ret; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index ec97b49428..9008cf8122 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -82,6 +82,9 @@ static bool is_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; + if ( IS_DC ) + return sid_check_is_builtin(sid); + return (sid_check_is_domain(sid) || sid_check_is_builtin(sid)); } @@ -90,6 +93,9 @@ static bool is_in_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; + if ( IS_DC ) + return sid_check_is_in_builtin(sid); + return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid)); } -- cgit From 908812e98d84bd3eded612cd6f40637997a966ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 May 2008 17:52:54 -0700 Subject: Fix bug #5504. winbindd children and parent were handing SIGTERM in the same way - deleting the socket! Jeremy. (This used to be commit 3ab5a3883e33eba159152aa02544d71f047c7e45) --- source3/winbindd/winbindd.c | 25 +++++++++++++++---------- source3/winbindd/winbindd_dual.c | 2 +- source3/winbindd/winbindd_proto.h | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 57eee20f49..c017916f09 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -131,15 +131,20 @@ static void flush_caches(void) /* Handle the signal by unlinking socket and exiting */ -static void terminate(void) +static void terminate(bool is_parent) { - char *path = NULL; - - /* Remove socket file */ - if (asprintf(&path, "%s/%s", + if (is_parent) { + /* When parent goes away we should + * remove the socket file. Not so + * when children terminate. + */ + char *path = NULL; + + if (asprintf(&path, "%s/%s", get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) { - unlink(path); - SAFE_FREE(path); + unlink(path); + SAFE_FREE(path); + } } idmap_close(); @@ -810,10 +815,10 @@ void winbind_check_sighup(void) } /* check if TERM has been received */ -void winbind_check_sigterm(void) +void winbind_check_sigterm(bool is_parent) { if (do_sigterm) - terminate(); + terminate(is_parent); } /* Process incoming clients on listen_sock. We use a tricky non-blocking, @@ -975,7 +980,7 @@ static void process_loop(void) /* Check signal handling things */ - winbind_check_sigterm(); + winbind_check_sigterm(true); winbind_check_sighup(); if (do_sigusr2) { diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index ae042563ed..b8c0ab9113 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1097,7 +1097,7 @@ static bool fork_domain_child(struct winbindd_child *child) TALLOC_CTX *frame = talloc_stackframe(); /* check for signals */ - winbind_check_sigterm(); + winbind_check_sigterm(false); winbind_check_sighup(); run_events(winbind_event_context(), 0, NULL, NULL); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f6a0da8fff..356d4aaf79 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -67,7 +67,7 @@ void request_error(struct winbindd_cli_state *state); void request_ok(struct winbindd_cli_state *state); void request_finished_cont(void *private_data, bool success); void winbind_check_sighup(void); -void winbind_check_sigterm(void); +void winbind_check_sigterm(bool in_parent); int main(int argc, char **argv, char **envp); /* The following definitions come from winbindd/winbindd_ads.c */ -- cgit From 4408fdaf29c2e3ddb240aca2f70316d875f68c35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 May 2008 17:53:16 -0700 Subject: Fix valgrind bug in debug statement. Don't reference uninitialized memory. Jeremy. (This used to be commit 25e76a19f22cdf726928d6c4b165745de9e455d6) --- source3/winbindd/idmap_util.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index bf06cd8472..0d24070dd6 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -157,11 +157,10 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) } if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) { - DEBUG(10, ("sid [%s] not mapped to a gid [%u,%u,%u]\n", + DEBUG(10, ("sid [%s] not mapped to a gid [%u,%u]\n", sid_string_dbg(sid), map.status, - map.xid.type, - map.xid.id)); + map.xid.type)); return NT_STATUS_NONE_MAPPED; } -- cgit From 346dbc62b826dd126d147107396154c31919da1b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 May 2008 23:49:36 -0700 Subject: Split the winbindd_passdb backend into a 'builtin' and a 'sam' backend. This allows winbindd when running on a Samba PDC to correctly answer wbinfo -u lists and other queries. Jeremy. (This used to be commit e61ad0c1586733ae1d3518ce56d95094d1ac5ef9) --- source3/winbindd/winbindd_cache.c | 6 +- source3/winbindd/winbindd_ndr.c | 9 +- source3/winbindd/winbindd_passdb.c | 441 ++++++++++++++++++++++++++++--------- source3/winbindd/winbindd_util.c | 8 +- 4 files changed, 349 insertions(+), 115 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index f0ff0294f3..60403717c1 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -8,7 +8,7 @@ Copyright (C) Volker Lendecke 2005 Copyright (C) Guenther Deschner 2005 Copyright (C) Michael Adam 2007 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or @@ -37,7 +37,7 @@ extern bool opt_nocache; #ifdef HAVE_ADS extern struct winbindd_methods ads_methods; #endif -extern struct winbindd_methods passdb_methods; +extern struct winbindd_methods builtin_passdb_methods; /* * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES. @@ -137,7 +137,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) /* We have to know what type of domain we are dealing with first. */ if (domain->internal) { - domain->backend = &passdb_methods; + domain->backend = &builtin_passdb_methods; domain->initialized = True; } if ( !domain->initialized ) { diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c index 9d1502afa7..3e3ca3225c 100644 --- a/source3/winbindd/winbindd_ndr.c +++ b/source3/winbindd/winbindd_ndr.c @@ -74,7 +74,8 @@ void ndr_print_winbindd_cm_conn(struct ndr_print *ndr, extern struct winbindd_methods ads_methods; #endif extern struct winbindd_methods msrpc_methods; -extern struct winbindd_methods passdb_methods; +extern struct winbindd_methods builtin_passdb_methods; +extern struct winbindd_methods sam_passdb_methods; extern struct winbindd_methods reconnect_methods; extern struct winbindd_methods cache_methods; @@ -97,8 +98,10 @@ void ndr_print_winbindd_methods(struct ndr_print *ndr, } else if (r == &ads_methods) { ndr_print_string(ndr, name, "ads_methods"); #endif - } else if (r == &passdb_methods) { - ndr_print_string(ndr, name, "passdb_methods"); + } else if (r == &builtin_passdb_methods) { + ndr_print_string(ndr, name, "builtin_passdb_methods"); + } else if (r == &sam_passdb_methods) { + ndr_print_string(ndr, name, "sam_passdb_methods"); } else if (r == &reconnect_methods) { ndr_print_string(ndr, name, "reconnect_methods"); } else if (r == &cache_methods) { diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 7c1d7bd71b..8b2016c031 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2000-2001,2003 Copyright (C) Simo Sorce 2003 Copyright (C) Volker Lendecke 2004 + Copyright (C) Jeremy Allison 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,20 +28,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -/* Query display info for a domain. This returns enough information plus a - bit extra to give an overview of domain users for the User Manager - application. */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - /* We don't have users */ - *num_entries = 0; - *info = NULL; - return NT_STATUS_OK; -} - /* list all domain groups */ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -167,16 +154,75 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, char ***names, enum lsa_SidType **types) { - return NT_STATUS_UNSUCCESSFUL; -} + size_t i; + bool have_mapped; + bool have_unmapped; -/* Lookup user information from a rid or username. */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const DOM_SID *user_sid, - WINBIND_USERINFO *user_info) -{ - return NT_STATUS_NO_SUCH_USER; + *domain_name = NULL; + *names = NULL; + *types = NULL; + + if (!num_rids) { + return NT_STATUS_OK; + } + + /* Paranoia check */ + if (!sid_check_is_in_builtin(sid) && + !sid_check_is_in_our_domain(sid) && + !sid_check_is_in_unix_users(sid) && + !sid_check_is_unix_users(sid) && + !sid_check_is_in_unix_groups(sid) && + !sid_check_is_unix_groups(sid) && + !sid_check_is_in_wellknown_domain(sid)) + { + DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with " + "passdb backend\n", sid_string_dbg(sid))); + return NT_STATUS_NONE_MAPPED; + } + + *names = TALLOC_ARRAY(mem_ctx, char *, num_rids); + *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); + + if ((*names == NULL) || (*types == NULL)) { + return NT_STATUS_NO_MEMORY; + } + + have_mapped = have_unmapped = false; + + for (i=0; iaccount_name ); + (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname ); + (*info)[i].homedir = NULL; + (*info)[i].shell = NULL; + sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid); + + /* For the moment we set the primary group for + every user to be the Domain Users group. + There are serious problems with determining + the actual primary group for large domains. + This should really be made into a 'winbind + force group' smb.conf parameter or + something like that. */ + + sid_compose(&(*info)[i].group_sid, &domain->sid, + DOMAIN_GROUP_RID_USERS); + } + + pdb_search_destroy(ps); + return NT_STATUS_OK; +} + +/* Lookup user information from a rid or username. */ +static NTSTATUS sam_query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *user_sid, + WINBIND_USERINFO *user_info) +{ + struct samu *sampass = NULL; + + ZERO_STRUCTP(user_info); + + if (!sid_check_is_in_our_domain(user_sid)) { + return NT_STATUS_NO_SUCH_USER; + } + + DEBUG(10,("sam_query_user: getting samu info for sid %s\n", + sid_string_dbg(user_sid) )); + + if (!(sampass = samu_new(mem_ctx))) { + return NT_STATUS_NO_MEMORY; + } + + if (!pdb_getsampwsid(sampass, user_sid)) { + TALLOC_FREE(sampass); + return NT_STATUS_NO_SUCH_USER; + } + + if (pdb_get_group_sid(sampass) == NULL) { + TALLOC_FREE(sampass); + return NT_STATUS_NO_SUCH_GROUP; + } + + DEBUG(10,("sam_query_user: group sid %s\n", + sid_string_dbg(sampass->group_sid) )); + + sid_copy(&user_info->user_sid, user_sid); + sid_copy(&user_info->group_sid, sampass->group_sid); + + user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ? + sampass->username : ""); + user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ? + sampass->full_name : ""); + user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ? + sampass->home_dir : ""); + if (sampass->unix_pw && sampass->unix_pw->pw_shell) { + user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell); + } else { + user_info->shell = talloc_strdup(mem_ctx, ""); + } + user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1; + + TALLOC_FREE(sampass); + return NT_STATUS_OK; +} + /* Lookup group membership given a rid. */ -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, +static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, uint32 *num_names, DOM_SID **sid_mem, char ***names, @@ -320,83 +605,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, return NT_STATUS_OK; } -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - bool result; - time_t seq_num; - - result = pdb_get_seq_num(&seq_num); - if (!result) { - *seq = 1; - } - - *seq = (int) seq_num; - /* *seq = 1; */ - return NT_STATUS_OK; -} - -static NTSTATUS lockout_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct samr_DomInfo12 *policy) -{ - /* actually we have that */ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS password_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct samr_DomInfo1 *policy) -{ - uint32 min_pass_len,pass_hist,password_properties; - time_t u_expire, u_min_age; - NTTIME nt_expire, nt_min_age; - uint32 account_policy_temp; - - if ((policy = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) { - return NT_STATUS_NO_MEMORY; - } - - if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) { - return NT_STATUS_ACCESS_DENIED; - } - min_pass_len = account_policy_temp; - - if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) { - return NT_STATUS_ACCESS_DENIED; - } - pass_hist = account_policy_temp; - - if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) { - return NT_STATUS_ACCESS_DENIED; - } - password_properties = account_policy_temp; - - if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) { - return NT_STATUS_ACCESS_DENIED; - } - u_expire = account_policy_temp; - - if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) { - return NT_STATUS_ACCESS_DENIED; - } - u_min_age = account_policy_temp; - - unix_to_nt_time_abs(&nt_expire, u_expire); - unix_to_nt_time_abs(&nt_min_age, u_min_age); - - init_samr_DomInfo1(policy, - (uint16)min_pass_len, - (uint16)pass_hist, - password_properties, - nt_expire, - nt_min_age); - - return NT_STATUS_OK; -} - /* get a list of trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, +static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_domains, char ***names, @@ -453,20 +663,39 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, } /* the rpc backend methods are exposed via this structure */ -struct winbindd_methods passdb_methods = { - False, - query_user_list, +struct winbindd_methods builtin_passdb_methods = { + false, + builtin_query_user_list, + enum_dom_groups, + enum_local_groups, + name_to_sid, + sid_to_name, + rids_to_names, + builtin_query_user, + lookup_usergroups, + lookup_useraliases, + builtin_lookup_groupmem, + sequence_number, + lockout_policy, + password_policy, + builtin_trusted_domains, +}; + +/* the rpc backend methods are exposed via this structure */ +struct winbindd_methods sam_passdb_methods = { + false, + sam_query_user_list, enum_dom_groups, enum_local_groups, name_to_sid, sid_to_name, rids_to_names, - query_user, + sam_query_user, lookup_usergroups, lookup_useraliases, - lookup_groupmem, + sam_lookup_groupmem, sequence_number, lockout_policy, password_policy, - trusted_domains, + sam_trusted_domains, }; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 9008cf8122..6a96070f42 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -27,7 +27,9 @@ #define DBGC_CLASS DBGC_WINBIND extern struct winbindd_methods cache_methods; -extern struct winbindd_methods passdb_methods; +extern struct winbindd_methods builtin_passdb_methods; +extern struct winbindd_methods sam_passdb_methods; + /** * @file winbindd_util.c @@ -695,7 +697,7 @@ bool init_domain_list(void) /* BUILTIN domain */ - domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, + domain = add_trusted_domain("BUILTIN", NULL, &builtin_passdb_methods, &global_sid_Builtin); if (domain) { setup_domain_child(domain, @@ -705,7 +707,7 @@ bool init_domain_list(void) /* Local SAM */ domain = add_trusted_domain(get_global_sam_name(), NULL, - &passdb_methods, get_global_sam_sid()); + &sam_passdb_methods, get_global_sam_sid()); if (domain) { if ( role != ROLE_DOMAIN_MEMBER ) { domain->primary = True; -- cgit From 11ef7d202a2f9f438c379ee5e2696be63c750758 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Jun 2008 15:26:37 -0700 Subject: Fix by Bo Yang for bug with winbindd trusted domain child not keeping primary domain online status up to date. Jeremy. (This used to be commit 0621c7c8161b7b94cc9249ab3e71855d3030b6fb) --- source3/winbindd/winbindd_dual.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index b8c0ab9113..29849e9e78 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -965,6 +965,7 @@ static bool fork_domain_child(struct winbindd_child *child) int fdpair[2]; struct winbindd_cli_state state; struct winbindd_domain *domain; + struct winbindd_domain *primary_domain = NULL; if (child->domain) { DEBUG(10, ("fork_domain_child called for domain '%s'\n", @@ -1060,10 +1061,13 @@ static bool fork_domain_child(struct winbindd_child *child) } /* Ensure we have no pending check_online events other - than one for this domain. */ + than one for this domain or the primary domain. */ for (domain = domain_list(); domain; domain = domain->next) { - if (domain != child->domain) { + if (domain->primary) { + primary_domain = domain; + } + if ((domain != child->domain) && !domain->primary) { TALLOC_FREE(domain->check_online_event); } } @@ -1080,6 +1084,18 @@ static bool fork_domain_child(struct winbindd_child *child) set_domain_online_request(child->domain); + if (primary_domain != child->domain) { + /* We need to talk to the primary + * domain as well as the trusted + * domain inside a trusted domain + * child. + * See the code in : + * set_dc_type_and_flags_trustinfo() + * for details. + */ + set_domain_online_request(primary_domain); + } + child->lockout_policy_event = event_add_timed( winbind_event_context(), NULL, timeval_zero(), "account_lockout_policy_handler", -- cgit From dd7cf3464d36e1e6d622371ff3f05b1eac3f381d Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Tue, 3 Jun 2008 11:18:44 -0500 Subject: winbindd_cm: Replace the use of lp_realm() with our_domain->alt_name. Reduce the use of config parameters with run time information after discussion with Guenther. (This used to be commit 57d596395db287301eefd34e62c9aaf857c34c69) --- source3/winbindd/winbindd_cm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a1027cec97..312d30371f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -710,8 +710,14 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, if (machine_krb5_principal != NULL) { + struct winbindd_domain *our_domain = find_our_domain(); + + if (!our_domain) { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + if (asprintf(machine_krb5_principal, "%s$@%s", - account_name, lp_realm()) == -1) + account_name, our_domain->alt_name) == -1) { return NT_STATUS_NO_MEMORY; } -- cgit From bde7cbf4a7f734b1f092825f52de618cfd563e1e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jun 2008 10:38:58 +0200 Subject: Fix a memleak caused by a crappy get_sorted_dc_list() API (This used to be commit 2ea03a1e95a30e321e390bef9408a1215711de07) --- source3/winbindd/winbindd_cm.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 312d30371f..ae51c268bd 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1167,9 +1167,20 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, sitename = sitename_fetch(domain->alt_name); if (sitename) { + NTSTATUS status; /* Do the site-specific AD dns lookup first. */ - get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True); + status = get_sorted_dc_list(domain->alt_name, + sitename, &ip_list, + &iplist_size, True); + if (!NT_STATUS_IS_OK(status)) { + /* + * Work around a crappy about-to-be-replaced + * get_sorted_dc_list error handling :-) + */ + SAFE_FREE(ip_list); + iplist_size = 0; + } for ( i=0; i Date: Sun, 8 Jun 2008 14:19:44 -0700 Subject: Bugfix noticed by Herb. On using the again: tag as a goto target we were not reinitializing the array counts. From Herb: This is in the file nsswitch/winbindd_cm.c (samba-3.0.30) line 1236 We have a label again: where we keep trying to find the name of the DC from the list of IPs returned by get_dcs. If we fail to figure out the name we do a goto again at the end of the function. The problem is we don't reset the num_dcs, num_addrs, etc and free the memory in the various arrays. This seems wrong to me. I have a winbindd core where I have 9 IPs returned for the DCs but at the time of the crash num_dcs is 87 and if I look through the array dcs it keeps repeating entries from the same group of 9 Jerry, Volker and Guenther please check. Jeremy. (This used to be commit 15f464321a7c71a86b747918343746050d286655) --- source3/winbindd/winbindd_cm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ae51c268bd..860fabbf72 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1257,6 +1257,8 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, int i, fd_index; + *fd = -1; + again: if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0)) return False; @@ -1318,6 +1320,19 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, /* We can not continue without the DC's name */ winbind_add_failed_connection_entry(domain, dcs[fd_index].name, NT_STATUS_UNSUCCESSFUL); + + /* Throw away all arrays as we're doing this again. */ + TALLOC_FREE(dcs); + num_dcs = 0; + + TALLOC_FREE(dcnames); + num_dcnames = 0; + + TALLOC_FREE(addrs); + num_addrs = 0; + + *fd = -1; + goto again; } -- cgit From 13eab02679a012b332beed28b0a4fc05cb9fd258 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Mon, 16 Jun 2008 15:21:28 +0200 Subject: winbind cache: Don't create SN cache entries during name-to-sid queries. Clients can request name-to-sid queries for different combinations of upper and lower case names. We don't want to create the reverse caching entries for each combination used. This avoids inconsistent answers on sid-to-name queries. Please review! Karolin (This used to be commit b58e4f6b3d73294d8448c0dff4341183c52e5b7c) --- source3/winbindd/winbindd_cache.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 60403717c1..03512b9745 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -1451,13 +1451,13 @@ do_query: if (domain->online && (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) { wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); + + /* Don't add SN cache entries for sid-to-name queries during this operation. + * It leads to inconsistent answers during sid-to-name queries as the + * client can ask for different combinations of lower case and upper case + * names in these name-to-sid queries. + */ - /* Only save the reverse mapping if this was not a UPN */ - if (!strchr(name, '@')) { - strupper_m(CONST_DISCARD(char *,domain_name)); - strlower_m(CONST_DISCARD(char *,name)); - wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type); - } } return status; -- cgit From 98ed31a107ee6c02d12253d175834359deaa2a64 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 17 Jun 2008 09:44:21 +0200 Subject: Fix typo. arguements -> arguments Karolin (This used to be commit 16b5b772d216d10613d433884634b1215efbd6e6) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 10807e6640..d710dd2ce3 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -345,7 +345,7 @@ NTSTATUS idmap_init(void) goto done; } - /* separate the backend and module arguements */ + /* separate the backend and module arguments */ if ((p = strchr(compat_backend, ':')) != NULL) { *p = '\0'; compat_params = p + 1; -- cgit From a7cf0bd32aa3b5a26d361e300247638d1e0e159e Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 17 Jun 2008 10:30:19 +0200 Subject: idmap: Fix typos in comments. Karolin (This used to be commit 94a4d7fa3209eb668161b8110af6f877b4833fa7) --- source3/winbindd/idmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index d710dd2ce3..8b16f27f7d 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -798,7 +798,7 @@ NTSTATUS idmap_init(void) } } - /* cleanpu temporary strings */ + /* cleanup temporary strings */ TALLOC_FREE( compat_backend ); idmap_init_status = NT_STATUS_OK; @@ -1359,7 +1359,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) } } - /* let's see if there is any id mapping to be retieved + /* let's see if there is any id mapping to be retrieved * from the backends */ if (bi) { /* Only do query if we are online */ @@ -1477,7 +1477,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) } } - /* let's see if there is any id mapping to be retieved + /* let's see if there is any id mapping to be retrieved * from the backends */ if (bids) { /* Only do query if we are online */ -- cgit From ee281b747906bab75b766243dac6b0442f81517d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 17 Jun 2008 12:21:03 +0200 Subject: Revert "Fix a memleak caused by a crappy get_sorted_dc_list() API" This reverts commit 2ea03a1e95a30e321e390bef9408a1215711de07. (This used to be commit 80c2e8295a00c3d88372b55b81d03b455feb69b2) --- source3/winbindd/winbindd_cm.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 860fabbf72..1f1544ea0d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1167,20 +1167,9 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, sitename = sitename_fetch(domain->alt_name); if (sitename) { - NTSTATUS status; /* Do the site-specific AD dns lookup first. */ - status = get_sorted_dc_list(domain->alt_name, - sitename, &ip_list, - &iplist_size, True); - if (!NT_STATUS_IS_OK(status)) { - /* - * Work around a crappy about-to-be-replaced - * get_sorted_dc_list error handling :-) - */ - SAFE_FREE(ip_list); - iplist_size = 0; - } + get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True); for ( i=0; i Date: Fri, 20 Jun 2008 12:49:14 -0700 Subject: Fix bug #5533. Winbindd fails to cope correctly with a workgroup name containing a '.'. Jeremy. (This used to be commit 96325ff44dc404a68d4ebd423cf78210ec3ff902) --- source3/winbindd/winbindd_util.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 6a96070f42..a35ba7bc06 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -165,15 +165,9 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const ZERO_STRUCTP(domain); - /* prioritise the short name */ - if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) { - fstrcpy(domain->name, alternative_name); - fstrcpy(domain->alt_name, domain_name); - } else { - fstrcpy(domain->name, domain_name); - if (alternative_name) { - fstrcpy(domain->alt_name, alternative_name); - } + fstrcpy(domain->name, domain_name); + if (alternative_name) { + fstrcpy(domain->alt_name, alternative_name); } domain->methods = methods; -- cgit From 7687a225104bbec47a672da60125af6ff580c817 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Jun 2008 12:44:18 -0700 Subject: Final (hopefully :-) part of fix for bug #5551. Allow passdb backend to enumerate domain groups. Jeremy (This used to be commit 2181770e4589d475b95b4103a8f95a58787f1f86) --- source3/winbindd/winbindd_passdb.c | 68 +++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 23 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 8b2016c031..ffcf0719be 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -28,35 +28,31 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, +static NTSTATUS enum_groups_internal(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, - struct acct_info **info) -{ - /* We don't have domain groups */ - *num_entries = 0; - *info = NULL; - return NT_STATUS_OK; -} - -/* List all domain groups */ - -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) + struct acct_info **info, + enum lsa_SidType sidtype) { struct pdb_search *search; - struct samr_displayentry *aliases; + struct samr_displayentry *entries; int i; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - search = pdb_search_aliases(&domain->sid); + if (sidtype == SID_NAME_ALIAS) { + search = pdb_search_aliases(&domain->sid); + } else { + search = pdb_search_groups(); + } + if (search == NULL) goto done; - *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases); - if (*num_entries == 0) goto done; + *num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries); + if (*num_entries == 0) { + /* Zero entries isn't an error */ + result = NT_STATUS_OK; + goto done; + } *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); if (*info == NULL) { @@ -65,9 +61,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, } for (i=0; i<*num_entries; i++) { - fstrcpy((*info)[i].acct_name, aliases[i].account_name); - fstrcpy((*info)[i].acct_desc, aliases[i].description); - (*info)[i].rid = aliases[i].rid; + fstrcpy((*info)[i].acct_name, entries[i].account_name); + fstrcpy((*info)[i].acct_desc, entries[i].description); + (*info)[i].rid = entries[i].rid; } result = NT_STATUS_OK; @@ -76,6 +72,32 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, return result; } +/* list all domain groups */ +static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + return enum_groups_internal(domain, + mem_ctx, + num_entries, + info, + SID_NAME_DOM_GRP); +} + +/* List all local groups (aliases) */ +static NTSTATUS enum_local_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + return enum_groups_internal(domain, + mem_ctx, + num_entries, + info, + SID_NAME_ALIAS); +} + /* convert a single name to a sid in a domain */ static NTSTATUS name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, -- cgit From 059293cbf4553a3b4dbfe78dcadb362ec344ef3b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 25 Jun 2008 10:35:59 +0200 Subject: rename rpccli_samr_chgpasswd_user to rpccli_samr_chgpasswd_user2. Guenther (This used to be commit 5b4650d56c04be0c498413f17afb2cf6d0e7d548) --- source3/winbindd/winbindd_pam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f548a04d35..40bd869433 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2093,15 +2093,15 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact got_info = True; } - /* only fallback when the chgpasswd3 call is not supported */ + /* only fallback when the chgpasswd_user3 call is not supported */ if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { - DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", + DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); - result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass); + result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. Map to the same status code as Windows 2003. */ -- cgit From 14d500c0e7e4261fa8d9dbc12e14d79a424059c3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 25 Jun 2008 21:49:57 +0200 Subject: rename rpccli_samr_chgpasswd3 to rpccli_samr_chgpasswd_user3. Guenther (This used to be commit b1209a039b45985e0b28777e04cba5bcc3de061e) --- source3/winbindd/winbindd_pam.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 40bd869433..f7001f7716 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2066,12 +2066,12 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, - user, - newpass, - oldpass, - &info, - &reject); + result = rpccli_samr_chgpasswd_user3(cli, state->mem_ctx, + user, + newpass, + oldpass, + &info, + &reject); /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ @@ -2098,7 +2098,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { - DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user2\n", + DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); -- cgit From ae16606a90291664c7e43ea9316af3167a2d7642 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Jun 2008 15:23:32 -0700 Subject: Part of fix for #5551. Split out the group enumeration functions to a BUILTIN and a Domain specific version. Stops the domain groups appearing twice. Jeremy. (This used to be commit 77b99530e0ce0ab0f335d8b22774548d30690550) --- source3/winbindd/winbindd_passdb.c | 42 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index ffcf0719be..e4cf029225 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -72,19 +72,6 @@ static NTSTATUS enum_groups_internal(struct winbindd_domain *domain, return result; } -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - return enum_groups_internal(domain, - mem_ctx, - num_entries, - info, - SID_NAME_DOM_GRP); -} - /* List all local groups (aliases) */ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -371,6 +358,18 @@ static NTSTATUS password_policy(struct winbindd_domain *domain, BUILTIN specific functions. *********************************************************************/ +/* list all domain groups */ +static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + /* BUILTIN doesn't have domain groups */ + *num_entries = 0; + *info = NULL; + return NT_STATUS_OK; +} + /* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager application. */ @@ -426,6 +425,19 @@ static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain, SAM specific functions. *********************************************************************/ +/* list all domain groups */ +static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *num_entries, + struct acct_info **info) +{ + return enum_groups_internal(domain, + mem_ctx, + num_entries, + info, + SID_NAME_DOM_GRP); +} + static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, @@ -688,7 +700,7 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, struct winbindd_methods builtin_passdb_methods = { false, builtin_query_user_list, - enum_dom_groups, + builtin_enum_dom_groups, enum_local_groups, name_to_sid, sid_to_name, @@ -707,7 +719,7 @@ struct winbindd_methods builtin_passdb_methods = { struct winbindd_methods sam_passdb_methods = { false, sam_query_user_list, - enum_dom_groups, + sam_enum_dom_groups, enum_local_groups, name_to_sid, sid_to_name, -- cgit From 7f8df9c217d9b5771a03067636e822ad4ffc030e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 24 Jun 2008 12:29:05 +0200 Subject: winbindd: don't panic if messaging_init() fails - return NULL instead. Leave appropriate handling to the callers. Michael (This used to be commit 3e0c24323af5f10fa68ae8aad552b7346536c908) --- source3/winbindd/winbindd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index c017916f09..a6c3dd8651 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -49,7 +49,7 @@ struct messaging_context *winbind_messaging_context(void) if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), winbind_event_context()))) { - smb_panic("Could not init winbind messaging context"); + DEBUG(0, ("Could not init winbind messaging context.\n")); } return ctx; } -- cgit From b33d226a61fe8f2ab6e173e5f0182c208bc58b9e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 24 Jun 2008 12:30:38 +0200 Subject: winbind: untangle logic in winbind_messaging_context() slightly. Michael (This used to be commit e710a9b73ea2fd176de7093125bc5f3f3f3a9404) --- source3/winbindd/winbindd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index a6c3dd8651..00951a609e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -47,8 +47,11 @@ struct messaging_context *winbind_messaging_context(void) { static struct messaging_context *ctx; - if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), - winbind_event_context()))) { + if (ctx == NULL) { + ctx = messaging_init(NULL, server_id_self(), + winbind_event_context()); + } + if (ctx == NULL) { DEBUG(0, ("Could not init winbind messaging context.\n")); } return ctx; -- cgit From 89ce05bb1427f6644e2d487bb1c06725550cf493 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 24 Jun 2008 12:34:49 +0200 Subject: winbind: remove duplicate debug message for failing messaging_init(). Leave the message inside winbind_messaging_context() for now. There might be callers, where this debug message could prove useful... Michael (This used to be commit e9177ec56a8fe596d6fcfc4a95df87e39f757818) --- source3/winbindd/winbindd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 00951a609e..ec3bf68e2a 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1131,7 +1131,6 @@ int main(int argc, char **argv, char **envp) /* Initialise messaging system */ if (winbind_messaging_context() == NULL) { - DEBUG(0, ("unable to initialize messaging system\n")); exit(1); } -- cgit From 120c09b125f656d6d03b979560f3ef6652217691 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Jun 2008 14:02:39 -0700 Subject: From Steve Danneman @ Isilon. Attached is the companion patch to (037b9689d9042a398cb91e4628a82fcdfa913c21), which made handling of WINBINDD_LIST_GROUPS asynchronous. Because most all of the list_groups code was reusable, I abstracted it, and implemented both list_groups and list_users on top of it. On my large test domain a "wbinfo -u" call went from 70 seconds to 30 seconds with this patch. Plus, the parent process is no longer blocked from receiving new requests during that time. Steven Danneman | Software Development Engineer Isilon Systems P +1-206-315-7500 F +1-206-315-7501 www.isilon.com (This used to be commit 5188f2861137ff06d5399561d55d7d00c3a08644) --- source3/winbindd/winbindd.h | 7 ++- source3/winbindd/winbindd_async.c | 85 ++++++++++++++++++++++--- source3/winbindd/winbindd_domain.c | 4 ++ source3/winbindd/winbindd_group.c | 104 +------------------------------ source3/winbindd/winbindd_misc.c | 123 +++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 20 +++--- source3/winbindd/winbindd_user.c | 94 +--------------------------- 7 files changed, 220 insertions(+), 217 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 301d877e61..b2fe8b67e7 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -363,7 +363,12 @@ struct winbindd_tdc_domain { uint32 trust_type; }; - +/* Switch for listing users or groups */ +enum ent_type { + LIST_USERS = 0, + LIST_GROUPS, +}; + #include "winbindd/winbindd_proto.h" #define WINBINDD_ESTABLISH_LOOP 30 diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index bc0f9d836b..e47666462e 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -453,8 +453,8 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } -/* This is the first callback after enumerating groups from a domain */ -static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, +/* This is the first callback after enumerating users/groups from a domain */ +static void listent_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { @@ -462,7 +462,7 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, (void (*)(void *, bool, fstring, char*))c; if (!success || response->result != WINBINDD_OK) { - DEBUG(5, ("list_groups() failed!\n")); + DEBUG(5, ("list_ent() failed!\n")); cont(private_data, False, response->data.name.dom_name, NULL); return; } @@ -473,30 +473,95 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, SAFE_FREE(response->extra_data.data); } -/* Request the name of all groups in a single domain */ -void winbindd_listgroups_async(TALLOC_CTX *mem_ctx, +/* Request the name of all users/groups in a single domain */ +void winbindd_listent_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, void (*cont)(void *private_data, bool success, fstring dom_name, char* extra_data), - void *private_data) + void *private_data, enum ent_type type) { struct winbindd_request request; ZERO_STRUCT(request); - request.cmd = WINBINDD_LIST_GROUPS; + if (type == LIST_USERS) + request.cmd = WINBINDD_LIST_USERS; + else if (type == LIST_GROUPS) + request.cmd = WINBINDD_LIST_GROUPS; - do_async_domain(mem_ctx, domain, &request, listgroups_recv, + do_async_domain(mem_ctx, domain, &request, listent_recv, (void *)cont, private_data); } + +enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + WINBIND_USERINFO *info; + NTSTATUS status; + struct winbindd_methods *methods; + uint32 num_entries = 0; + char *extra_data = NULL; + uint32_t extra_data_len = 0, i; + + /* Must copy domain into response first for debugging in parent */ + fstrcpy(state->response.data.name.dom_name, domain->name); + + /* Query user info */ + methods = domain->methods; + status = methods->query_user_list(domain, state->mem_ctx, + &num_entries, &info); + + if (!NT_STATUS_IS_OK(status)) + return WINBINDD_ERROR; + + if (num_entries == 0) + return WINBINDD_OK; + + /* Allocate some memory for extra data. Note that we limit + account names to sizeof(fstring) = 256 characters. + +1 for the ',' between group names */ + extra_data = (char *)SMB_REALLOC(extra_data, + (sizeof(fstring) + 1) * num_entries); + + if (!extra_data) { + DEBUG(0,("failed to enlarge buffer!\n")); + return WINBINDD_ERROR; + } + + /* Pack user list into extra data fields */ + for (i = 0; i < num_entries; i++) { + fstring acct_name, name; + + if (info[i].acct_name == NULL) + fstrcpy(acct_name, ""); + else + fstrcpy(acct_name, info[i].acct_name); + + fill_domain_username(name, domain->name, acct_name, True); + /* Append to extra data */ + memcpy(&extra_data[extra_data_len], name, strlen(name)); + extra_data_len += strlen(name); + extra_data[extra_data_len++] = ','; + } + + /* Assign extra_data fields in response structure */ + if (extra_data) { + /* remove trailing ',' */ + extra_data[extra_data_len - 1] = '\0'; + state->response.extra_data.data = extra_data; + state->response.length += extra_data_len; + } + + return WINBINDD_OK; +} enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, struct winbindd_cli_state *state) { struct getent_state groups = {}; char *extra_data = NULL; - unsigned int extra_data_len = 0, i; + uint32_t extra_data_len = 0, i; - /* Must copy domain into response first for bookeeping in parent */ + /* Must copy domain into response first for debugging in parent */ fstrcpy(state->response.data.name.dom_name, domain->name); fstrcpy(groups.domain_name, domain->name); diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c index 4d10f49ca2..2e8c6175ca 100644 --- a/source3/winbindd/winbindd_domain.c +++ b/source3/winbindd/winbindd_domain.c @@ -49,6 +49,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { .name = "LOOKUPRIDS", .struct_cmd = WINBINDD_LOOKUPRIDS, .struct_fn = winbindd_dual_lookuprids, + },{ + .name = "LIST_USERS", + .struct_cmd = WINBINDD_LIST_USERS, + .struct_fn = winbindd_dual_list_users, },{ .name = "LIST_GROUPS", .struct_cmd = WINBINDD_LIST_GROUPS, diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index d10609a83f..f9f946f3f3 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1339,112 +1339,10 @@ void winbindd_getgrent(struct winbindd_cli_state *state) request_error(state); } -struct listgroups_state { - TALLOC_CTX *mem_ctx; - struct winbindd_cli_state *cli_state; - unsigned int domain_count; - char *extra_data; - unsigned int extra_data_len; -}; - -static void listgroups_recv(void *private_data, bool success, fstring dom_name, - char *extra_data); - /* List domain groups without mapping to unix ids */ void winbindd_list_groups(struct winbindd_cli_state *state) { - struct winbindd_domain *domain; - const char *which_domain; - struct listgroups_state *groups_state; - - DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid)); - - /* Ensure null termination */ - state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; - which_domain = state->request.domain_name; - - /* Initialize listgroups_state */ - groups_state = TALLOC_P(state->mem_ctx, struct listgroups_state); - if (groups_state == NULL) { - DEBUG(0, ("talloc failed\n")); - request_error(state); - return; - } - - groups_state->mem_ctx = state->mem_ctx; - groups_state->cli_state = state; - groups_state->domain_count = 0; - groups_state->extra_data = NULL; - groups_state->extra_data_len = 0; - - /* Must count the full list of expected domains before we request data - * from any of them. Otherwise it's possible for a connection to the - * first domain to fail, call listgroups_recv(), and return to the - * client without checking any other domains. */ - for (domain = domain_list(); domain; domain = domain->next) { - /* if we have a domain name restricting the request and this - one in the list doesn't match, then just bypass the remainder - of the loop */ - if ( *which_domain && !strequal(which_domain, domain->name) ) - continue; - - groups_state->domain_count++; - } - - /* Make sure we're enumerating at least one domain */ - if (!groups_state->domain_count) { - request_ok(state); - return; - } - - /* Enumerate list of trusted domains and request group list from each */ - for (domain = domain_list(); domain; domain = domain->next) { - if ( *which_domain && !strequal(which_domain, domain->name) ) - continue; - - winbindd_listgroups_async(state->mem_ctx, domain, - listgroups_recv, groups_state); - } -} - -static void listgroups_recv(void *private_data, bool success, fstring dom_name, - char *extra_data) -{ - /* extra_data comes to us as a '\0' terminated string of comma - separated groups */ - struct listgroups_state *state = talloc_get_type_abort( - private_data, struct listgroups_state); - - /* Append groups from one domain onto the whole list */ - if (extra_data) { - DEBUG(5, ("listgroups_recv: %s returned groups.\n", dom_name)); - if (!state->extra_data) - state->extra_data = talloc_asprintf(state->mem_ctx, - "%s", extra_data); - else - state->extra_data = talloc_asprintf_append_buffer( - state->extra_data, - ",%s", extra_data); - /* Add one for the '\0' and each additional ',' */ - state->extra_data_len += strlen(extra_data) + 1; - } - else { - DEBUG(5, ("listgroups_recv: %s returned no groups.\n", - dom_name)); - } - - if (--state->domain_count) - /* Still waiting for some child domains to return */ - return; - - /* Return list of all groups to the client */ - if (state->extra_data) { - state->cli_state->response.extra_data.data = - SMB_STRDUP(state->extra_data); - state->cli_state->response.length += state->extra_data_len; - } - - request_ok(state->cli_state); + winbindd_list_ent(state, LIST_GROUPS); } /* Get user supplementary groups. This is much quicker than trying to diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 8933cf2794..01a4054d44 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -97,6 +97,129 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } +/* Helpers for listing user and group names */ + +const char *ent_type_strings[] = {"users", + "groups"}; + +static const char *get_ent_type_string(enum ent_type type) +{ + return ent_type_strings[type]; +} + +struct listent_state { + TALLOC_CTX *mem_ctx; + struct winbindd_cli_state *cli_state; + enum ent_type type; + int domain_count; + char *extra_data; + uint32_t extra_data_len; +}; + +static void listent_recv(void *private_data, bool success, fstring dom_name, + char *extra_data); + +/* List domain users/groups without mapping to unix ids */ +void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type) +{ + struct winbindd_domain *domain; + const char *which_domain; + struct listent_state *ent_state; + + DEBUG(3, ("[%5lu]: list %s\n", (unsigned long)state->pid, + get_ent_type_string(type))); + + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + + /* Initialize listent_state */ + ent_state = TALLOC_P(state->mem_ctx, struct listent_state); + if (ent_state == NULL) { + DEBUG(0, ("talloc failed\n")); + request_error(state); + return; + } + + ent_state->mem_ctx = state->mem_ctx; + ent_state->cli_state = state; + ent_state->type = type; + ent_state->domain_count = 0; + ent_state->extra_data = NULL; + ent_state->extra_data_len = 0; + + /* Must count the full list of expected domains before we request data + * from any of them. Otherwise it's possible for a connection to the + * first domain to fail, call listent_recv(), and return to the + * client without checking any other domains. */ + for (domain = domain_list(); domain; domain = domain->next) { + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + + ent_state->domain_count++; + } + + /* Make sure we're enumerating at least one domain */ + if (!ent_state->domain_count) { + request_ok(state); + return; + } + + /* Enumerate list of trusted domains and request user/group list from + * each */ + for (domain = domain_list(); domain; domain = domain->next) { + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + + winbindd_listent_async(state->mem_ctx, domain, + listent_recv, ent_state, type); + } +} + +static void listent_recv(void *private_data, bool success, fstring dom_name, + char *extra_data) +{ + /* extra_data comes to us as a '\0' terminated string of comma + separated users or groups */ + struct listent_state *state = talloc_get_type_abort( + private_data, struct listent_state); + + /* Append users/groups from one domain onto the whole list */ + if (extra_data) { + DEBUG(5, ("listent_recv: %s returned %s.\n", + dom_name, get_ent_type_string(state->type))); + if (!state->extra_data) + state->extra_data = talloc_asprintf(state->mem_ctx, + "%s", extra_data); + else + state->extra_data = talloc_asprintf_append( + state->extra_data, + ",%s", extra_data); + /* Add one for the '\0' and each additional ',' */ + state->extra_data_len += strlen(extra_data) + 1; + } + else { + DEBUG(5, ("listent_recv: %s returned no %s.\n", + dom_name, get_ent_type_string(state->type))); + } + + if (--state->domain_count) + /* Still waiting for some child domains to return */ + return; + + /* Return list of all users/groups to the client */ + if (state->extra_data) { + state->cli_state->response.extra_data.data = + SMB_STRDUP(state->extra_data); + state->cli_state->response.length += state->extra_data_len; + } + + request_ok(state->cli_state); +} + /* Constants and helper functions for determining domain trust types */ enum trust_type { diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 356d4aaf79..84ea67b9ec 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -104,6 +104,15 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, void *private_data); enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, struct winbindd_cli_state *state); +void winbindd_listent_async(TALLOC_CTX *mem_ctx, + struct winbindd_domain *domain, + void (*cont)(void *private_data, bool success, + fstring dom_name, char* extra_data), + void *private_data, enum ent_type type); +enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, + struct winbindd_cli_state *state); +enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, + struct winbindd_cli_state *state); bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, size_t num_sids, char **result, ssize_t *len); enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain, @@ -133,16 +142,6 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, uint32 group_rid), void *private_data); -void winbindd_listgroups_async(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - void (*cont)(void *private_data, bool success, - fstring dom_name, char* extra_data), - void *private_data); - -enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - - /* The following definitions come from winbindd/winbindd_cache.c */ void winbindd_check_cache_size(time_t t); @@ -394,6 +393,7 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state); void winbindd_check_machine_acct(struct winbindd_cli_state *state); enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain, struct winbindd_cli_state *state); +void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type); void winbindd_list_trusted_domains(struct winbindd_cli_state *state); enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain, struct winbindd_cli_state *state); diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 6241d84fe6..45918383b7 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -778,99 +778,7 @@ void winbindd_getpwent(struct winbindd_cli_state *state) } /* List domain users without mapping to unix ids */ - void winbindd_list_users(struct winbindd_cli_state *state) { - struct winbindd_domain *domain; - WINBIND_USERINFO *info; - const char *which_domain; - uint32 num_entries = 0, total_entries = 0; - char *extra_data = NULL; - int extra_data_len = 0; - enum winbindd_result rv = WINBINDD_ERROR; - - DEBUG(3, ("[%5lu]: list users\n", (unsigned long)state->pid)); - - /* Ensure null termination */ - state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; - which_domain = state->request.domain_name; - - /* Enumerate over trusted domains */ - - for (domain = domain_list(); domain; domain = domain->next) { - NTSTATUS status; - struct winbindd_methods *methods; - unsigned int i; - - /* if we have a domain name restricting the request and this - one in the list doesn't match, then just bypass the remainder - of the loop */ - - if ( *which_domain && !strequal(which_domain, domain->name) ) - continue; - - methods = domain->methods; - - /* Query display info */ - status = methods->query_user_list(domain, state->mem_ctx, - &num_entries, &info); - - if (!NT_STATUS_IS_OK(status)) { - continue; - } - - if (num_entries == 0) - continue; - - /* Allocate some memory for extra data */ - total_entries += num_entries; - - extra_data = (char *)SMB_REALLOC( - extra_data, sizeof(fstring) * total_entries); - - if (!extra_data) { - DEBUG(0,("failed to enlarge buffer!\n")); - goto done; - } - - /* Pack user list into extra data fields */ - - for (i = 0; i < num_entries; i++) { - fstring acct_name, name; - - if (!info[i].acct_name) { - fstrcpy(acct_name, ""); - } else { - fstrcpy(acct_name, info[i].acct_name); - } - - fill_domain_username(name, domain->name, acct_name, True); - - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } - } - - /* Assign extra_data fields in response structure */ - - if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data.data = extra_data; - state->response.length += extra_data_len; - } - - /* No domains responded but that's still OK so don't return an - error. */ - - rv = WINBINDD_OK; - - done: - - if (rv == WINBINDD_OK) - request_ok(state); - else - request_error(state); + winbindd_list_ent(state, LIST_USERS); } -- cgit From 9ff1ffcbee46257c3b2b13b84c2a539322493190 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Fri, 27 Jun 2008 10:22:39 -0400 Subject: libads: Add API call to connect to a global catalog server. Extends ads_connect() to a new call ads_connect_gc() which connects on port 3268 rather than port 389. Also makes ads_try_connect() static and only used internally to ldap.c (This used to be commit f4c37dbe2c986fb7bfe510cdff3b4a9fbc06d079) --- source3/winbindd/winbindd_cm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 1f1544ea0d..51ef14b708 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1043,14 +1043,16 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, if (lp_security() == SEC_ADS) { ADS_STRUCT *ads; + ADS_STATUS ads_status; char addr[INET6_ADDRSTRLEN]; print_sockaddr(addr, sizeof(addr), pss); - ads = ads_init(domain->alt_name, domain->name, NULL); + ads = ads_init(domain->alt_name, domain->name, addr); ads->auth.flags |= ADS_AUTH_NO_BIND; - if (ads_try_connect(ads, addr)) { + ads_status = ads_connect(ads); + if (ADS_ERR_OK(ads_status)) { /* We got a cldap packet. */ fstrcpy(name, ads->config.ldap_server_name); namecache_store(name, 0x20, 1, &ip_list); -- cgit From 4aaa3a0fac09044498a6f725242f12e534e21d18 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Jun 2008 09:20:05 -0700 Subject: Fix from Atte Peltomäki - atte.peltomaki@f-secure.com to correctly check error code in winbindd group expansion. Jeremy. (This used to be commit e321377174f579ba57a70f260f4d4bc234a07439) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/winbindd/winbindd_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index f9f946f3f3..20b90e3283 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -442,7 +442,7 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, &sid_mem[j], &new_groups, &new_groups_size); - if (NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status)) { goto out; } -- cgit From 3b1de7f7f4db16c50a2c6b310d04643c094be695 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 1 Jul 2008 10:34:22 +0200 Subject: Revert "winbind cache: Don't create SN cache entries during name-to-sid queries." This reverts commit b58e4f6b3d73294d8448c0dff4341183c52e5b7c. Details can be found on the samba-technical mailing list. Karolin (This used to be commit 534a445df450c681be7da2c9dd65f7294f942b08) --- source3/winbindd/winbindd_cache.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 03512b9745..60403717c1 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -1451,13 +1451,13 @@ do_query: if (domain->online && (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) { wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); - - /* Don't add SN cache entries for sid-to-name queries during this operation. - * It leads to inconsistent answers during sid-to-name queries as the - * client can ask for different combinations of lower case and upper case - * names in these name-to-sid queries. - */ + /* Only save the reverse mapping if this was not a UPN */ + if (!strchr(name, '@')) { + strupper_m(CONST_DISCARD(char *,domain_name)); + strlower_m(CONST_DISCARD(char *,name)); + wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type); + } } return status; -- cgit From 065760ede0b4d785adf8a5dcdd9237a494b4876a Mon Sep 17 00:00:00 2001 From: Darshan Purandare Date: Tue, 1 Jul 2008 11:37:13 -0700 Subject: MSG_DEBUG now forwarded to all the winbindd children by parent. smbcontrol winbindd debug level would only set the debug level of the parent winbindd process and not the child processes. This patch adds the functionality of broadcasting the debug message to all winbindd children. Now the debug level message is propagated to all the winbindd processes that includes parent and children. (This used to be commit cfbcfc3ffe74f28ec874a6bf1ab93f55f405b6e6) --- source3/winbindd/winbindd.c | 5 +++++ source3/winbindd/winbindd_dual.c | 34 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 5 +++++ 3 files changed, 44 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index ec3bf68e2a..4b7efe81eb 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1249,6 +1249,11 @@ int main(int argc, char **argv, char **envp) MSG_WINBIND_DUMP_DOMAIN_LIST, winbind_msg_dump_domain_list); + /* Register handler for MSG_DEBUG. */ + messaging_register(winbind_messaging_context(), NULL, + MSG_DEBUG, + winbind_msg_debug); + netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 29849e9e78..c3bcb715bb 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -501,6 +501,36 @@ void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain) } } +/* + * Parent winbindd process sets its own debug level first and then + * sends a message to all the winbindd children to adjust their debug + * level to that of parents. + */ + +void winbind_msg_debug(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child; + + DEBUG(10,("winbind_msg_debug: got debug message.\n")); + + debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data); + + for (child = children; child != NULL; child = child->next) { + + DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n", + (unsigned int)child->pid)); + + messaging_send_buf(msg_ctx, pid_to_procid(child->pid), + MSG_DEBUG, + data->data, + strlen((char *) data->data) + 1); + } +} + /* Set our domains as offline and forward the offline message to our children. */ void winbind_msg_offline(struct messaging_context *msg_ctx, @@ -1044,6 +1074,8 @@ static bool fork_domain_child(struct winbindd_child *child) MSG_DUMP_EVENT_LIST, NULL); messaging_deregister(winbind_messaging_context(), MSG_WINBIND_DUMP_DOMAIN_LIST, NULL); + messaging_deregister(winbind_messaging_context(), + MSG_DEBUG, NULL); /* Handle online/offline messages. */ messaging_register(winbind_messaging_context(), NULL, @@ -1054,6 +1086,8 @@ static bool fork_domain_child(struct winbindd_child *child) MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus); messaging_register(winbind_messaging_context(), NULL, MSG_DUMP_EVENT_LIST, child_msg_dump_event_list); + messaging_register(winbind_messaging_context(), NULL, + MSG_DEBUG, debug_message); if ( child->domain ) { child->domain->startup = True; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 84ea67b9ec..7f68cbfbc2 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -300,6 +300,11 @@ void setup_child(struct winbindd_child *child, const char *logname); void winbind_child_died(pid_t pid); void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain); +void winbind_msg_debug(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); void winbind_msg_offline(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, -- cgit From ab57861686e90d1639f9836d964d8a642c644953 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 12:22:15 +0200 Subject: Fix two memory leaks in an error path in idmap.c (This used to be commit 7cec389e19323e99b6b6258e539be9d1fd65810f) --- source3/winbindd/idmap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 8b16f27f7d..c056596470 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -154,6 +154,7 @@ NTSTATUS smb_register_idmap(int version, const char *name, entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); + TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->methods = methods; @@ -207,6 +208,7 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); + TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->methods = methods; -- cgit From 1999791b7cedb6f25d6d638513a5b9aa647bb977 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 13:33:25 +0200 Subject: Make idmap_init() static This is called only from idmap_alloc_init, which feels kindof weird. Digging deeper in the code... (This used to be commit c8d1bbfddce41cd6bf37dd0a622ef3437a24b492) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index c056596470..32fc3dc975 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -279,7 +279,7 @@ NTSTATUS idmap_init_cache(void) /**************************************************************************** ****************************************************************************/ -NTSTATUS idmap_init(void) +static NTSTATUS idmap_init(void) { NTSTATUS ret; static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; -- cgit From dd7691ce68f3b0b44c35749efb03d7b7cb38a4ad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 14:03:25 +0200 Subject: Fix typo (This used to be commit fe58926283b51910d8587e32bb11aa681b9a27d3) --- source3/winbindd/idmap_cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index f7e1d4e6d1..b427db51b0 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -301,7 +301,7 @@ failed: return NT_STATUS_INTERNAL_DB_CORRUPTION; } -/* search the cahce for the SID an return a mapping if found * +/* search the cache for the SID an return a mapping if found * * * 4 cases are possible * @@ -410,7 +410,7 @@ done: return ret; } -/* search the cahce for the ID an return a mapping if found * +/* search the cache for the ID an return a mapping if found * * * 4 cases are possible * -- cgit From d6ab71f06c22739cacd683ae07e87b120c6c749a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 14:04:52 +0200 Subject: Fix a debug msg, this was probably a leftover from gencache (This used to be commit daa171552dc00d9602a05ba199c9a3ff24c802f5) --- source3/winbindd/idmap_cache.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index b427db51b0..ebfae7dc26 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -343,7 +343,8 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) t = strtol((const char *)databuf.dptr, &endptr, 10); if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); /* remove the entry */ tdb_delete_bystring(cache->tdb, sidkey); ret = NT_STATUS_NONE_MAPPED; @@ -452,7 +453,8 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) t = strtol((const char *)databuf.dptr, &endptr, 10); if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); /* remove the entry */ tdb_delete_bystring(cache->tdb, idkey); ret = NT_STATUS_NONE_MAPPED; -- cgit From 69b9cffe6ee441b19e301019f84823173a457a9a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 14:06:09 +0200 Subject: Fix indentation (This used to be commit 954556b527aa652f9a46f0d48834e92befb3c5f9) --- source3/winbindd/idmap_cache.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index ebfae7dc26..a3207663e4 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -396,15 +396,15 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* Check for valid or expired cache hits */ - if (t <= now) { + if (t <= now) { /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped as it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } - + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped as it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } + done: SAFE_FREE(databuf.dptr); talloc_free(sidkey); @@ -508,14 +508,14 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* Process the negative cache hit */ - if (t <= now) { + if (t <= now) { /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { + ret = NT_STATUS_NONE_MAPPED; + } else { /* this is not mapped is it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } done: SAFE_FREE(databuf.dptr); -- cgit From 62dddd04f453956d241c23c6a86d50929f521d56 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 14:06:49 +0200 Subject: Fix nonempty whitespace only lines (This used to be commit 0da9d0d0f9662d8bd2f370f764d5a875e11b3068) --- source3/winbindd/idmap_cache.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index a3207663e4..b724ba0c59 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -119,7 +119,6 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) { return NT_STATUS_OK; } - ret = idmap_cache_build_sidkey(cache, &sidkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -259,11 +258,11 @@ static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) /* see if it is a sid */ if ( ! strncmp("IDMAP/SID/", value, 10)) { - + if ( ! string_to_sid(id->sid, &value[10])) { goto failed; } - + id->status = ID_MAPPED; return NT_STATUS_OK; @@ -271,21 +270,21 @@ static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) /* not a SID see if it is an UID or a GID */ if ( ! strncmp("IDMAP/UID/", value, 10)) { - + /* a uid */ id->xid.type = ID_TYPE_UID; - + } else if ( ! strncmp("IDMAP/GID/", value, 10)) { - + /* a gid */ id->xid.type = ID_TYPE_GID; - + } else { - + /* a completely bogus value bail out */ goto failed; } - + id->xid.id = strtol(&value[10], &rem, 0); if (*rem != '\0') { goto failed; @@ -328,7 +327,7 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as not mapped by default */ id->status = ID_UNKNOWN; - + ret = idmap_cache_build_sidkey(cache, &sidkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -376,7 +375,7 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); goto done; } - + /* We're expired, set an error code for upper layer */ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; @@ -438,7 +437,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as unknown by default */ id->status = ID_UNKNOWN; - + ret = idmap_cache_build_idkey(cache, &idkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -463,7 +462,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* check it is not negative */ if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " "timeout = %s", t > now ? "valid" : "expired", idkey, endptr+1, ctime(&t))); @@ -494,7 +493,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) goto done; } - + /* Was a negative cache hit */ /* Ignore the negative cache when offline */ @@ -502,7 +501,6 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) if ( IS_DOMAIN_OFFLINE(our_domain) ) { DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); ret = NT_STATUS_NONE_MAPPED; - goto done; } -- cgit From ec77a06a5da103482aa1b277d5dd009afa244d95 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 14:53:57 +0200 Subject: fix typos (This used to be commit e0957c6f4b1e81c27fda1de7fb7cbc9c585f5ac9) --- source3/winbindd/idmap_rid.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c index f1cd77853c..fe753c9deb 100644 --- a/source3/winbindd/idmap_rid.c +++ b/source3/winbindd/idmap_rid.c @@ -171,7 +171,8 @@ static NTSTATUS idmap_rid_unixids_to_sids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initilization my have been deferred because of an error, retry or fail */ + /* Initialization may have been deferred because of an error, retry or + * fail */ if ( ! dom->initialized) { ret = idmap_rid_initialize(dom); if ( ! NT_STATUS_IS_OK(ret)) { @@ -213,7 +214,8 @@ static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initilization my have been deferred because of an error, retry or fail */ + /* Initialization may have been deferred because of an error, retry or + * fail */ if ( ! dom->initialized) { ret = idmap_rid_initialize(dom); if ( ! NT_STATUS_IS_OK(ret)) { -- cgit From e467fae948ffa2dd67aa38f51dd79612d508dffb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 15:04:46 +0200 Subject: Fix nonempty whitespace only lines (This used to be commit cc77db2acbc35cea58576f1e28c7a760a5e31609) --- source3/winbindd/idmap_ad.c | 34 +++++++++++++++++----------------- source3/winbindd/idmap_nss.c | 8 ++++---- source3/winbindd/idmap_passdb.c | 8 ++++---- source3/winbindd/idmap_tdb.c | 6 +++--- source3/winbindd/idmap_tdb2.c | 28 ++++++++++++++-------------- source3/winbindd/idmap_util.c | 12 ++++++------ source3/winbindd/nss_info.c | 33 ++++++++++++++++----------------- source3/winbindd/nss_info_template.c | 10 +++++----- 8 files changed, 69 insertions(+), 70 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 0d7c068844..2e79413ffc 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -108,7 +108,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) /* setup server affinity */ get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip ); - + status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(1, ("ad_idmap_init: failed to connect to AD\n")); @@ -129,7 +129,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) static ADS_STRUCT *ad_idmap_cached_connection(void) { ADS_STRUCT *ads = ad_idmap_cached_connection_internal(); - + if ( !ads ) return NULL; @@ -146,14 +146,14 @@ static ADS_STRUCT *ad_idmap_cached_connection(void) (ad_map_type == WB_POSIX_MAP_RFC2307) ) { ADS_STATUS schema_status; - + schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema); if ( !ADS_ERR_OK(schema_status) ) { DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n")); return NULL; } } - + return ads; } @@ -320,7 +320,7 @@ again: (unsigned long)ids[idx]->xid.id); CHECK_ALLOC_DONE(u_filter); break; - + case ID_TYPE_GID: if ( ! g_filter) { g_filter = talloc_asprintf(memctx, "(&(|" @@ -527,7 +527,7 @@ again: ")(|", ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP); - + CHECK_ALLOC_DONE(filter); bidx = idx; @@ -535,7 +535,7 @@ again: sidstr = sid_binstring(ids[idx]->sid); filter = talloc_asprintf_append_buffer(filter, "(objectSid=%s)", sidstr); - + free(sidstr); CHECK_ALLOC_DONE(filter); } @@ -668,7 +668,7 @@ static NTSTATUS idmap_ad_close(struct idmap_domain *dom) } TALLOC_FREE( ad_schema ); - + return NT_STATUS_OK; } @@ -692,7 +692,7 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_SFU; return NT_STATUS_OK; @@ -710,7 +710,7 @@ static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_SFU20; return NT_STATUS_OK; @@ -720,7 +720,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) { /* Sanity check if we have previously been called with a different schema model */ - + if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) && (ad_map_type != WB_POSIX_MAP_RFC2307) ) { @@ -728,7 +728,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_RFC2307; return NT_STATUS_OK; @@ -761,19 +761,19 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, if ( !ads_internal || !ad_schema ) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - + if ( !homedir || !shell || !gecos ) return NT_STATUS_INVALID_PARAMETER; *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr ); *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr ); *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr ); - + if ( gid ) { if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) ) *gid = (uint32)-1; } - + return NT_STATUS_OK; } @@ -800,7 +800,7 @@ static struct idmap_methods ad_methods = { /* The SFU and RFC2307 NSS plugins share everything but the init function which sets the intended schema model to use */ - + static struct nss_info_methods nss_rfc2307_methods = { .init = nss_rfc2307_init, .get_nss_info = nss_ad_get_info, @@ -841,7 +841,7 @@ NTSTATUS idmap_ad_init(void) if ( !NT_STATUS_IS_OK(status_idmap_ad) ) return status_idmap_ad; } - + if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) { status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, "rfc2307", &nss_rfc2307_methods ); diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index e4acd9ce65..c4115b1ee3 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -4,17 +4,17 @@ idmap PASSDB backend Copyright (C) Simo Sorce 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -60,7 +60,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma const char *name; enum lsa_SidType type; bool ret; - + switch (ids[i]->xid.type) { case ID_TYPE_UID: pw = getpwuid((uid_t)ids[i]->xid.id); diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c index 17afd71ab8..6fbb47b979 100644 --- a/source3/winbindd/idmap_passdb.c +++ b/source3/winbindd/idmap_passdb.c @@ -4,17 +4,17 @@ idmap PASSDB backend Copyright (C) Simo Sorce 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -85,7 +85,7 @@ static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma for (i = 0; ids[i]; i++) { enum lsa_SidType type; union unid_t id; - + if (pdb_sid_to_id(ids[i]->sid, &id, &type)) { switch (type) { case SID_NAME_USER: diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index e5f605361b..26dc2fdac7 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -7,17 +7,17 @@ Copyright (C) Jim McDonough 2003 Copyright (C) Jeremy Allison 2006 Copyright (C) Simo Sorce 2003-2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index ab89e615f7..b8049d00e5 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -15,17 +15,17 @@ Copyright (C) Jim McDonough 2003 Copyright (C) Jeremy Allison 2006 Copyright (C) Simo Sorce 2003-2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -88,7 +88,7 @@ static NTSTATUS idmap_tdb2_alloc_load(void); static NTSTATUS idmap_tdb2_open_perm_db(void) { char *db_path; - + if (idmap_tdb2_perm) { /* its already open */ return NT_STATUS_OK; @@ -281,7 +281,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) hwmtype, (unsigned long)high_hwm)); return NT_STATUS_UNSUCCESSFUL; } - + xid->id = hwm; DEBUG(10,("New %s = %d\n", hwmtype, hwm)); @@ -384,7 +384,7 @@ static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr) } return ret; } - + status = idmap_tdb2_open_perm_db(); if (!NT_STATUS_IS_OK(status)) { return ret; @@ -570,7 +570,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m case ID_TYPE_UID: keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); break; - + case ID_TYPE_GID: keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); break; @@ -621,7 +621,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m } goto done; } - + if (!string_to_sid(map->sid, (const char *)data.dptr)) { DEBUG(10,("INVALID SID (%s) in record %s\n", (const char *)data.dptr, keystr)); @@ -667,7 +667,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m ret = NT_STATUS_NONE_MAPPED; goto done; } - + ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr); /* store it on shared storage */ if (!NT_STATUS_IS_OK(ret)) { @@ -702,7 +702,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr)); ret = NT_STATUS_INTERNAL_DB_ERROR; } - + /* apply filters before returning result */ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { @@ -746,7 +746,7 @@ static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_m ids[i]->status = ID_UNMAPPED; continue; } - + /* some fatal error occurred, return immediately */ goto done; } @@ -791,7 +791,7 @@ static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_m ids[i]->status = ID_UNMAPPED; continue; } - + /* some fatal error occurred, return immediately */ goto done; } @@ -835,7 +835,7 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id data.dptr = NULL; /* TODO: should we filter a set_mapping using low/high filters ? */ - + ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); switch (map->xid.type) { @@ -843,7 +843,7 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id case ID_TYPE_UID: kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); break; - + case ID_TYPE_GID: kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); break; diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 0d24070dd6..78f4d13ec1 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -41,7 +41,7 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) maps[0] = ↦ maps[1] = NULL; - + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); @@ -75,7 +75,7 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) maps[0] = ↦ maps[1] = NULL; - + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); @@ -105,10 +105,10 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) map.sid = sid; map.xid.type = ID_TYPE_UID; - + maps[0] = ↦ maps[1] = NULL; - + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", @@ -145,10 +145,10 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) map.sid = sid; map.xid.type = ID_TYPE_GID; - + maps[0] = ↦ maps[1] = NULL; - + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c index daa3dd037d..af73fe2900 100644 --- a/source3/winbindd/nss_info.c +++ b/source3/winbindd/nss_info.c @@ -8,12 +8,12 @@ modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ @@ -89,12 +89,12 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) int len; *backend = *domain = NULL; - + if ( !config ) return False; - + p = strchr( config, ':' ); - + /* if no : then the string must be the backend name only */ if ( !p ) { @@ -107,13 +107,13 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( strlen(p+1) > 0 ) { *domain = SMB_STRDUP( p+1 ); } - + len = PTR_DIFF(p,config)+1; if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) { SAFE_FREE( *backend ); return False; } - + StrnCpy( q, config, len-1); q[len-1] = '\0'; *backend = q; @@ -139,7 +139,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( NT_STATUS_IS_OK(nss_initialized) ) return NT_STATUS_OK; - + /* The "template" backend should alqays be registered as it is a static module */ @@ -166,7 +166,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( !NT_STATUS_IS_OK(status) ) { continue; } - + /* try again */ if ( (nss_backend = nss_get_backend( backend )) == NULL ) { DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n", @@ -184,7 +184,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) DEBUG(0,("nss_init: talloc() failure!\n")); return NT_STATUS_NO_MEMORY; } - + nss_domain->backend = nss_backend; nss_domain->domain = talloc_strdup( nss_domain, domain ); @@ -210,10 +210,9 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) /* we shouild default to use template here */ } - - + nss_initialized = NT_STATUS_OK; - + return NT_STATUS_OK; } @@ -231,19 +230,19 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) nt_errstr(status))); return NULL; } - + for ( p=nss_domain_list; p; p=p->next ) { if ( strequal( p->domain, domain ) ) break; } - + /* If we didn't find a match, then use the default nss info */ if ( !p ) { if ( !nss_domain_list ) { return NULL; } - + p = nss_domain_list; } @@ -271,7 +270,7 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) domain )); return NT_STATUS_NOT_FOUND; } - + m = p->backend->methods; return m->get_nss_info( p, user_sid, ctx, ads, msg, diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c index aaf02e4abe..641bfe9eaf 100644 --- a/source3/winbindd/nss_info_template.c +++ b/source3/winbindd/nss_info_template.c @@ -8,12 +8,12 @@ modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ @@ -44,7 +44,7 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, { if ( !homedir || !shell || !gecos ) return NT_STATUS_INVALID_PARAMETER; - + *homedir = talloc_strdup( ctx, lp_template_homedir() ); *shell = talloc_strdup( ctx, lp_template_shell() ); *gecos = NULL; @@ -52,7 +52,7 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, if ( !*homedir || !*shell ) { return NT_STATUS_NO_MEMORY; } - + return NT_STATUS_OK; } @@ -73,7 +73,7 @@ static struct nss_info_methods nss_template_methods = { .get_nss_info = nss_template_get_info, .close_fn = nss_template_close }; - + NTSTATUS nss_info_template_init( void ) { return smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, -- cgit From 7207b41a5e6a7cbf2b598775d831560e1b70cc93 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 15:13:01 +0200 Subject: Tiny logic simplification: Remove an unnecessary else branch (This used to be commit 6009ae329375b1c40e3d00df977ddccc8b5cc176) --- source3/winbindd/idmap_ad.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 2e79413ffc..b99da57a4a 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -77,15 +77,15 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) if ( ads->config.realm && (expire > time(NULL))) { return ads; - } else { - /* we own this ADS_STRUCT so make sure it goes away */ - DEBUG(7,("Deleting expired krb5 credential cache\n")); - ads->is_mine = True; - ads_destroy( &ads ); - ads_kdestroy(WINBIND_CCACHE_NAME); - ad_idmap_ads = NULL; - TALLOC_FREE( ad_schema ); } + + /* we own this ADS_STRUCT so make sure it goes away */ + DEBUG(7,("Deleting expired krb5 credential cache\n")); + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy(WINBIND_CCACHE_NAME); + ad_idmap_ads = NULL; + TALLOC_FREE( ad_schema ); } if (!local) { -- cgit From ec7aa52a3b6b32cd5e4b2807dc3df13eb734c0a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Jul 2008 15:13:14 +0200 Subject: Fix typo (This used to be commit fe79c8a5b726754703626ca0bff57074274c98c7) --- source3/winbindd/idmap_ad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index b99da57a4a..ca1cf81ca9 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -98,7 +98,8 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) return NULL; } - /* the machine acct password might have change - fetch it every time */ + /* the machine acct password might have changed - fetch it every + * time */ SAFE_FREE(ads->auth.password); ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); -- cgit From 47f1090de77937ad5fece426a04eb7a3406a1284 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 15:14:01 +0200 Subject: Fix indentation (This used to be commit c4e6de9e34e1ff76552ce6d4e72b343fb5f33306) --- source3/winbindd/idmap_ad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index ca1cf81ca9..1a41f4f6ff 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -347,7 +347,7 @@ again: if ( u_filter) { filter = talloc_asprintf_append_buffer(filter, "%s))", u_filter); CHECK_ALLOC_DONE(filter); - TALLOC_FREE(u_filter); + TALLOC_FREE(u_filter); } if ( g_filter) { filter = talloc_asprintf_append_buffer(filter, "%s))", g_filter); -- cgit From 8857affd3cf9466466f1eeb2ccd8085d087bb2f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 04:57:30 +0200 Subject: Simplify idmap_cache_build_[s]idkey a bit (This used to be commit 80932c0266ef73b8d0462c078a053444fff47f32) --- source3/winbindd/idmap_cache.c | 69 ++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 36 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index b724ba0c59..0b3c22eb20 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -70,33 +70,19 @@ struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) return cache; } -static NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, - const struct id_map *id) +static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) { fstring sidstr; - *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", - sid_to_fstring(sidstr, id->sid)); - if ( ! *sidkey) { - DEBUG(1, ("failed to build sidkey, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; + return talloc_asprintf(ctx, "IDMAP/SID/%s", + sid_to_fstring(sidstr, sid)); } -static NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, - const struct id_map *id) +static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct id_map *id) { - *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu", - (id->xid.type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)id->xid.id); - if ( ! *idkey) { - DEBUG(1, ("failed to build idkey, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; + return talloc_asprintf(ctx, "IDMAP/%s/%lu", + (id->xid.type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)id->xid.id); } NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) @@ -120,12 +106,15 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) return NT_STATUS_OK; } - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; + sidkey = idmap_cache_sidkey(cache, id->sid); + if (sidkey == NULL) { + return NT_STATUS_NO_MEMORY; + } /* use sidkey as the local memory ctx */ - ret = idmap_cache_build_idkey(sidkey, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) { + idkey = idmap_cache_idkey(sidkey, id); + if (idkey == NULL) { + ret = NT_STATUS_NO_MEMORY; goto done; } @@ -182,14 +171,16 @@ done: NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) { - NTSTATUS ret; + NTSTATUS ret = NT_STATUS_OK; time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); TDB_DATA databuf; char *sidkey; char *valstr; - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; + sidkey = idmap_cache_sidkey(cache, id->sid); + if (sidkey == NULL) { + return NT_STATUS_NO_MEMORY; + } /* use sidkey as the local memory ctx */ valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); @@ -218,14 +209,16 @@ done: NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) { - NTSTATUS ret; + NTSTATUS ret = NT_STATUS_OK; time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); TDB_DATA databuf; char *idkey; char *valstr; - ret = idmap_cache_build_idkey(cache, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; + idkey = idmap_cache_idkey(cache, id); + if (idkey == NULL) { + return NT_STATUS_NO_MEMORY; + } /* use idkey as the local memory ctx */ valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); @@ -317,7 +310,7 @@ failed: NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) { - NTSTATUS ret; + NTSTATUS ret = NT_STATUS_OK; TDB_DATA databuf; time_t t; char *sidkey; @@ -328,8 +321,10 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as not mapped by default */ id->status = ID_UNKNOWN; - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; + sidkey = idmap_cache_sidkey(cache, id->sid); + if (sidkey == NULL) { + return NT_STATUS_NO_MEMORY; + } databuf = tdb_fetch_bystring(cache->tdb, sidkey); @@ -438,8 +433,10 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as unknown by default */ id->status = ID_UNKNOWN; - ret = idmap_cache_build_idkey(cache, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; + idkey = idmap_cache_idkey(cache, id); + if (idkey == NULL) { + return NT_STATUS_NO_MEMORY; + } databuf = tdb_fetch_bystring(cache->tdb, idkey); -- cgit From 60582d1fb47cb975790915c892b849dce8518d47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 04:59:36 +0200 Subject: Simplify idmap_cache_set() a bit sid_check_is_in_unix_* will only give true if it is of the corresponding type, so the check if the struct idmap actually represents a user or group is unnecessary. (This used to be commit 55b976ba93462c6885e8d89edd13c32fb5529944) --- source3/winbindd/idmap_cache.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 0b3c22eb20..eaff30c4e1 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -95,14 +95,9 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) char *valstr; /* Don't cache lookups in the S-1-22-{1,2} domain */ - if ( (id->xid.type == ID_TYPE_UID) && - sid_check_is_in_unix_users(id->sid) ) - { - return NT_STATUS_OK; - } - if ( (id->xid.type == ID_TYPE_GID) && - sid_check_is_in_unix_groups(id->sid) ) - { + + if (sid_check_is_in_unix_users(id->sid) + || sid_check_is_in_unix_groups(id->sid)) { return NT_STATUS_OK; } -- cgit From 9c7e12d9f7c925402163d568539a753ce60571c3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 20:39:22 +0200 Subject: IDMAP_READ_CACHE_DATA_FMT_TEMPLATE is unused, remove it (This used to be commit 2396d5d5d2f453f097f8ce77b640ad7e1d7e7c4c) --- source3/winbindd/idmap_cache.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index eaff30c4e1..8bf797f952 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -25,7 +25,6 @@ #define TIMEOUT_LEN 12 #define IDMAP_CACHE_DATA_FMT "%12u/%s" -#define IDMAP_READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" struct idmap_cache_ctx { TDB_CONTEXT *tdb; -- cgit From 0234276af848343ba13332de9d3f6dee0a529c0c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 23:12:22 +0200 Subject: Convert idmap_cache to gencache (This used to be commit 0bf0434f22b0ea46fda3ccc4dd612adbc88dd4f2) --- source3/winbindd/idmap.c | 54 +++-- source3/winbindd/idmap_cache.c | 463 ++++++++--------------------------------- source3/winbindd/winbindd.h | 1 + 3 files changed, 125 insertions(+), 393 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 32fc3dc975..db17245b92 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -40,8 +40,6 @@ struct idmap_alloc_backend { struct idmap_alloc_backend *prev, *next; }; -struct idmap_cache_ctx; - struct idmap_alloc_context { const char *params; struct idmap_alloc_methods *methods; @@ -49,7 +47,6 @@ struct idmap_alloc_context { }; static TALLOC_CTX *idmap_ctx = NULL; -static struct idmap_cache_ctx *idmap_cache; static struct idmap_backend *backends = NULL; static struct idmap_domain **idmap_domains = NULL; @@ -246,7 +243,6 @@ NTSTATUS idmap_close(void) /* this talloc_free call will fire the talloc destructors * that will free all active backends resources */ TALLOC_FREE(idmap_ctx); - idmap_cache = NULL; idmap_domains = NULL; backends = NULL; @@ -269,10 +265,6 @@ NTSTATUS idmap_init_cache(void) return NT_STATUS_NO_MEMORY; } - if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { - return NT_STATUS_UNSUCCESSFUL; - } - return NT_STATUS_OK; } @@ -1316,15 +1308,28 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) for (i = 0; ids[i]; i++) { + bool found, mapped, expired; + if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ret = idmap_cache_map_id(idmap_cache, ids[i]); + ids[i]->status = ID_UNKNOWN; - if ( ! NT_STATUS_IS_OK(ret)) { + found = idmap_cache_map_id(&ids[i]->xid, ids[i]->sid, + &mapped, &expired); + + if (found) { + ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; + } + + if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + + /* + * Need to ask the backend + */ if ( ! bids) { /* alloc space for ids to be resolved by @@ -1376,7 +1381,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) /* update the cache */ for (i = 0; i < bi; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(idmap_cache, bids[i]); + ret = idmap_cache_set(bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1391,8 +1396,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_id(idmap_cache, - bids[i]); + ret = idmap_cache_set_negative_id(bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1434,15 +1438,28 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) for (i = 0; ids[i]; i++) { + bool found, mapped, expired; + if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array\n")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ret = idmap_cache_map_sid(idmap_cache, ids[i]); + ids[i]->status = ID_UNKNOWN; - if ( ! NT_STATUS_IS_OK(ret)) { + found = idmap_cache_map_sid(ids[i]->sid, &ids[i]->xid, + &mapped, &expired); + + if (found) { + ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; + } + + if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + + /* + * Need to ask the backends + */ if ( ! bids) { /* alloc space for ids to be resolved @@ -1494,7 +1511,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* update the cache */ for (i = 0; bids[i]; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(idmap_cache, bids[i]); + ret = idmap_cache_set(bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1509,8 +1526,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_sid(idmap_cache, - bids[i]); + ret = idmap_cache_set_negative_sid(bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1550,7 +1566,7 @@ NTSTATUS idmap_set_mapping(const struct id_map *id) IDMAP_CHECK_RET(ret); /* set the mapping in the cache */ - ret = idmap_cache_set(idmap_cache, id); + ret = idmap_cache_set(id); IDMAP_CHECK_RET(ret); done: diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 8bf797f952..191cadb536 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -1,9 +1,8 @@ -/* +/* Unix SMB/CIFS implementation. ID Mapping Cache - based on gencache - + Copyright (C) Volker Lendecke 2008 Copyright (C) Simo Sorce 2006 Copyright (C) Rafal Szczesniak 2002 @@ -23,52 +22,6 @@ #include "includes.h" #include "winbindd.h" -#define TIMEOUT_LEN 12 -#define IDMAP_CACHE_DATA_FMT "%12u/%s" - -struct idmap_cache_ctx { - TDB_CONTEXT *tdb; -}; - -static int idmap_cache_destructor(struct idmap_cache_ctx *cache) -{ - int ret = 0; - - if (cache && cache->tdb) { - ret = tdb_close(cache->tdb); - cache->tdb = NULL; - } - - return ret; -} - -struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) -{ - struct idmap_cache_ctx *cache; - char* cache_fname = NULL; - - cache = talloc(memctx, struct idmap_cache_ctx); - if ( ! cache) { - DEBUG(0, ("Out of memory!\n")); - return NULL; - } - - cache_fname = lock_path("idmap_cache.tdb"); - - DEBUG(10, ("Opening cache file at %s\n", cache_fname)); - - cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - - if (!cache->tdb) { - DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname)); - return NULL; - } - - talloc_set_destructor(cache, idmap_cache_destructor); - - return cache; -} - static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) { fstring sidstr; @@ -77,21 +30,19 @@ static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) sid_to_fstring(sidstr, sid)); } -static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct id_map *id) +static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct unixid *xid) { return talloc_asprintf(ctx, "IDMAP/%s/%lu", - (id->xid.type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)id->xid.id); + (xid->type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)xid->id); } -NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) +NTSTATUS idmap_cache_set(const struct id_map *id) { NTSTATUS ret; time_t timeout = time(NULL) + lp_idmap_cache_time(); - TDB_DATA databuf; char *sidkey; char *idkey; - char *valstr; /* Don't cache lookups in the S-1-22-{1,2} domain */ @@ -100,415 +51,179 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) return NT_STATUS_OK; } - sidkey = idmap_cache_sidkey(cache, id->sid); + sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } /* use sidkey as the local memory ctx */ - idkey = idmap_cache_idkey(sidkey, id); + idkey = idmap_cache_idkey(sidkey, &id->xid); if (idkey == NULL) { ret = NT_STATUS_NO_MEMORY; goto done; } - /* save SID -> ID */ - - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", sidkey, valstr , ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { - DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* save ID -> SID */ - - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { + if (!gencache_set(idkey, sidkey, timeout) + || !gencache_set(sidkey, idkey, timeout)) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_ACCESS_DENIED; goto done; } ret = NT_STATUS_OK; done: - talloc_free(sidkey); + TALLOC_FREE(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) +NTSTATUS idmap_cache_set_negative_sid(const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; - time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); - TDB_DATA databuf; char *sidkey; - char *valstr; - sidkey = idmap_cache_sidkey(cache, id->sid); + sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", sidkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { + if (!gencache_set(sidkey, "IDMAP/NEGATIVE", + time(NULL) + lp_idmap_negative_cache_time())) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_ACCESS_DENIED; goto done; } done: - talloc_free(sidkey); + TALLOC_FREE(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) +NTSTATUS idmap_cache_set_negative_id(const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; - time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); - TDB_DATA databuf; char *idkey; - char *valstr; - idkey = idmap_cache_idkey(cache, id); + idkey = idmap_cache_idkey(talloc_tos(), &id->xid); if (idkey == NULL) { return NT_STATUS_NO_MEMORY; } - /* use idkey as the local memory ctx */ - valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { + if (!gencache_set(idkey, "IDMAP/NEGATIVE", + time(NULL) + lp_idmap_negative_cache_time())) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_ACCESS_DENIED; goto done; } done: - talloc_free(idkey); + TALLOC_FREE(idkey); return ret; } -static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) -{ - char *rem; - - /* see if it is a sid */ - if ( ! strncmp("IDMAP/SID/", value, 10)) { - - if ( ! string_to_sid(id->sid, &value[10])) { - goto failed; - } - - id->status = ID_MAPPED; - - return NT_STATUS_OK; - } - - /* not a SID see if it is an UID or a GID */ - if ( ! strncmp("IDMAP/UID/", value, 10)) { - - /* a uid */ - id->xid.type = ID_TYPE_UID; - - } else if ( ! strncmp("IDMAP/GID/", value, 10)) { - - /* a gid */ - id->xid.type = ID_TYPE_GID; - - } else { - - /* a completely bogus value bail out */ - goto failed; - } - - id->xid.id = strtol(&value[10], &rem, 0); - if (*rem != '\0') { - goto failed; - } - - id->status = ID_MAPPED; - - return NT_STATUS_OK; - -failed: - DEBUG(1, ("invalid value: %s\n", value)); - id->status = ID_UNKNOWN; - return NT_STATUS_INTERNAL_DB_CORRUPTION; -} - -/* search the cache for the SID an return a mapping if found * - * - * 4 cases are possible - * - * 1 map found - * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned - * 2 map not found - * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned - * 3 negative cache found - * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned - * 4 map found but timer expired - * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED - * is returned. In this case revalidation of the cache is needed. +/* + * search the cache for the SID an return a mapping if found */ -NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) +bool idmap_cache_map_sid(const struct dom_sid *sid, struct unixid *xid, + bool *mapped, bool *expired) { - NTSTATUS ret = NT_STATUS_OK; - TDB_DATA databuf; - time_t t; + bool ret = false; + time_t timeout; char *sidkey; - char *endptr; - struct winbindd_domain *our_domain = find_our_domain(); - time_t now = time(NULL); - - /* make sure it is marked as not mapped by default */ - id->status = ID_UNKNOWN; + char *value; + char *rem; - sidkey = idmap_cache_sidkey(cache, id->sid); + sidkey = idmap_cache_sidkey(talloc_tos(), sid); if (sidkey == NULL) { - return NT_STATUS_NO_MEMORY; + DEBUG(0, ("idmap_cache_sidkey failed\n")); + return false; } - databuf = tdb_fetch_bystring(cache->tdb, sidkey); - - if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey)); - ret = NT_STATUS_NONE_MAPPED; - goto done; + if (!gencache_get(sidkey, &value, &timeout)) { + TALLOC_FREE(sidkey); + return false; } - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid idmap cache data format: %s\n", - (const char *)databuf.dptr)); - /* remove the entry */ - tdb_delete_bystring(cache->tdb, sidkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; + if (strcmp(value, "IDMAP/NEGATIVE") == 0) { + *mapped = false; } - - /* check it is not negative */ - if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > now ? "valid" : - "expired", sidkey, endptr+1, ctime(&t))); - - /* this call if successful will also mark the entry as mapped */ - ret = idmap_cache_fill_map(id, endptr+1); - if ( ! NT_STATUS_IS_OK(ret)) { - /* if not valid form delete the entry */ - tdb_delete_bystring(cache->tdb, sidkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; + else if (strncmp(value, "IDMAP/UID/", 10) == 0) { + *mapped = true; + xid->type = ID_TYPE_UID; + xid->id = strtol(&value[10], &rem, 10); + if (*rem != '\0') { + goto fail; } - - /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ - - if (t <= now) { - /* If we've been told to be offline - stay in - that state... */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; - } - - /* We're expired, set an error code - for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + else if (strncmp(value, "IDMAP/GID/", 10) == 0) { + *mapped = true; + xid->type = ID_TYPE_GID; + xid->id = strtol(&value[10], &rem, 10); + if (*rem != '\0') { + goto fail; } - - goto done; } - - /* Was a negative cache hit */ - - /* Ignore the negative cache when offline */ - - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; + else { + goto fail; } + *expired = (timeout <= time(NULL)); - /* Check for valid or expired cache hits */ - if (t <= now) { - /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped as it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } + ret = true; -done: - SAFE_FREE(databuf.dptr); - talloc_free(sidkey); + fail: + if (!ret) { + DEBUG(1, ("Invalid entry %s in cache\n", value)); + } + SAFE_FREE(value); + TALLOC_FREE(sidkey); return ret; } -/* search the cache for the ID an return a mapping if found * - * - * 4 cases are possible - * - * 1 map found - * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned - * 2 map not found - * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned - * 3 negative cache found - * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned - * 4 map found but timer expired - * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED - * is returned. In this case revalidation of the cache is needed. +/* + * search the cache for the ID an return a mapping if found */ -NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) +bool idmap_cache_map_id(const struct unixid *xid, struct dom_sid *psid, + bool *mapped, bool *expired) { - NTSTATUS ret; - TDB_DATA databuf; - time_t t; + bool ret = false; + time_t timeout; char *idkey; - char *endptr; - struct winbindd_domain *our_domain = find_our_domain(); - time_t now = time(NULL); + char *value; - /* make sure it is marked as unknown by default */ - id->status = ID_UNKNOWN; - - idkey = idmap_cache_idkey(cache, id); + idkey = idmap_cache_idkey(talloc_tos(), xid); if (idkey == NULL) { - return NT_STATUS_NO_MEMORY; + return false; } - databuf = tdb_fetch_bystring(cache->tdb, idkey); - - if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey)); - ret = NT_STATUS_NONE_MAPPED; - goto done; + if (!gencache_get(idkey, &value, &timeout)) { + TALLOC_FREE(idkey); + return false; } - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid idmap cache data format: %s\n", - (const char *)databuf.dptr)); - /* remove the entry */ - tdb_delete_bystring(cache->tdb, idkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; + if (strcmp(value, "IDMAP/NEGATIVE") == 0) { + *mapped = false; } - - /* check it is not negative */ - if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > now ? "valid" : - "expired", idkey, endptr+1, ctime(&t))); - - /* this call if successful will also mark the entry as mapped */ - ret = idmap_cache_fill_map(id, endptr+1); - if ( ! NT_STATUS_IS_OK(ret)) { - /* if not valid form delete the entry */ - tdb_delete_bystring(cache->tdb, idkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; + else if (strncmp(value, "IDMAP/SID/", 10) == 0) { + *mapped = true; + if (!string_to_sid(psid, value+10)) { + goto fail; } - - /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */ - - if (t <= now) { - /* If we've been told to be offline - stay in - that state... */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; - } - - /* We're expired, set an error code - for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; - } - - goto done; } - - /* Was a negative cache hit */ - - /* Ignore the negative cache when offline */ - - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - ret = NT_STATUS_NONE_MAPPED; - goto done; + else { + goto fail; } - /* Process the negative cache hit */ + ret = true; - if (t <= now) { - /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped is it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; + fail: + if (!ret) { + DEBUG(1, ("Invalid entry %s in cache\n", value)); } - -done: - SAFE_FREE(databuf.dptr); - talloc_free(idkey); + SAFE_FREE(value); + TALLOC_FREE(idkey); return ret; } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index b2fe8b67e7..8a35fd9e37 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -379,4 +379,5 @@ enum ent_type { #define IS_DOMAIN_OFFLINE(x) ( lp_winbind_offline_logon() && \ ( get_global_winbindd_state_offline() \ || !(x)->online ) ) +#define IS_DOMAIN_ONLINE(x) (!(IS_DOMAIN_OFFLINE(x))) #endif /* _WINBINDD_H */ -- cgit From ca342870639f8720b1becb9b6a5587feafbeec11 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 23:29:49 +0200 Subject: Make use of ADD_TO_ARRAY (This used to be commit 81f334bd6da601a040f754c46705cfa2fd4f8c45) --- source3/winbindd/idmap.c | 94 +++++++++------------------------------ source3/winbindd/idmap_util.c | 34 ++++++-------- source3/winbindd/winbindd_idmap.c | 4 +- 3 files changed, 36 insertions(+), 96 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index db17245b92..504be22292 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1177,7 +1177,8 @@ done: return ret; } -static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) +static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids, int + num_ids) { struct id_map ***dom_ids; struct idmap_domain *dom; @@ -1205,7 +1206,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) /* partition the requests by domain */ - for (i = 0; ids[i]; i++) { + for (i = 0; i < num_ids; i++) { uint32 idx; if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) { @@ -1245,7 +1246,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) /* ok all the backends have been contacted at this point */ /* let's see if we have any unmapped SID left and act accordingly */ - for (i = 0; ids[i]; i++) { + for (i = 0; i < num_ids; i++) { /* NOTE: this will NOT touch ID_EXPIRED entries that the backend * was not able to confirm/deny (offline mode) */ if (ids[i]->status == ID_UNKNOWN || @@ -1278,7 +1279,7 @@ done: idmap interface functions **************************************************************************/ -NTSTATUS idmap_unixids_to_sids(struct id_map **ids) +NTSTATUS idmap_unixids_to_sids(struct id_map **ids, int n_ids) { TALLOC_CTX *ctx; NTSTATUS ret; @@ -1306,7 +1307,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) bids = NULL; bi = 0; - for (i = 0; ids[i]; i++) { + for (i = 0; i < n_ids; i++) { bool found, mapped, expired; @@ -1331,38 +1332,12 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) * Need to ask the backend */ - if ( ! bids) { - /* alloc space for ids to be resolved by - * backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; + ADD_TO_ARRAY(ctx, struct id_map *, ids[i], &bids, &bn); + if (bids == NULL) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; } - - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the rids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, - struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - } - - /* make sure the last element is NULL */ - bids[bi] = NULL; } } @@ -1408,12 +1383,12 @@ done: return ret; } -NTSTATUS idmap_sids_to_unixids(struct id_map **ids) +NTSTATUS idmap_sids_to_unixids(struct id_map **ids, int n_ids) { TALLOC_CTX *ctx; NTSTATUS ret; struct id_map **bids; - int i, bi; + int i; int bn = 0; struct winbindd_domain *our_domain = find_our_domain(); @@ -1434,9 +1409,8 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* no ids to be asked to the backends by default */ bids = NULL; - bi = 0; - for (i = 0; ids[i]; i++) { + for (i = 0; i < n_ids; i++) { bool found, mapped, expired; @@ -1461,38 +1435,12 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) * Need to ask the backends */ - if ( ! bids) { - /* alloc space for ids to be resolved - by backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; - } - - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the ids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, - struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } + ADD_TO_ARRAY(ctx, struct id_map *, ids[i], &bids, &bn); + if (bids == NULL) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; } - - /* make sure the last element is NULL */ - bids[bi] = NULL; } } @@ -1505,11 +1453,11 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) goto done; } - ret = idmap_backends_sids_to_unixids(bids); + ret = idmap_backends_sids_to_unixids(bids, bn); IDMAP_CHECK_RET(ret); /* update the cache */ - for (i = 0; bids[i]; i++) { + for (i = 0; i < bn; i++) { if (bids[i]->status == ID_MAPPED) { ret = idmap_cache_set(bids[i]); } else if (bids[i]->status == ID_EXPIRED) { diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 78f4d13ec1..9819fe15f0 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -31,18 +31,16 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; + struct id_map *maps; DEBUG(10,("uid = [%lu]\n", (unsigned long)uid)); map.sid = sid; map.xid.type = ID_TYPE_UID; map.xid.id = uid; + maps = ↦ - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_unixids_to_sids(maps); + ret = idmap_unixids_to_sids(&maps, 1); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); return ret; @@ -65,18 +63,16 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; + struct id_map *maps; DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); map.sid = sid; map.xid.type = ID_TYPE_GID; map.xid.id = gid; + maps = ↦ - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_unixids_to_sids(maps); + ret = idmap_unixids_to_sids(&maps, 1); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); return ret; @@ -99,17 +95,15 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; + struct id_map *maps; DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; - map.xid.type = ID_TYPE_UID; - - maps[0] = ↦ - maps[1] = NULL; + map.xid.type = ID_TYPE_UID; + maps = ↦ - ret = idmap_sids_to_unixids(maps); + ret = idmap_sids_to_unixids(&maps, 1); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", sid_string_dbg(sid))); @@ -139,17 +133,15 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; + struct id_map *maps; DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_GID; + maps = ↦ - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_sids_to_unixids(maps); + ret = idmap_sids_to_unixids(&maps, 1); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", sid_string_dbg(sid))); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 3c7aa2d0c2..98f8548083 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -224,7 +224,7 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, sids = (DOM_SID *)state->request.extra_data.data; num = state->request.extra_len / sizeof(DOM_SID); - ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); + ids = TALLOC_ARRAY(state->mem_ctx, struct id_map *, num); if ( ! ids) { DEBUG(0, ("Out of memory!\n")); return WINBINDD_ERROR; @@ -239,7 +239,7 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, ids[i]->sid = &sids[i]; } - result = idmap_sids_to_unixids(ids); + result = idmap_sids_to_unixids(ids, num); if (NT_STATUS_IS_OK(result)) { -- cgit From 4dbfa7a211317be2e46657a3bdc040091049a75d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Jul 2008 23:34:28 +0200 Subject: Tiny logic simplification -- remove an else branch (This used to be commit 01c8c7bbf6163d5c7733db0d8ecbccfe7e4fec7d) --- source3/winbindd/winbindd_idmap.c | 42 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 98f8548083..631f5c1ab4 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -241,33 +241,31 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, result = idmap_sids_to_unixids(ids, num); - if (NT_STATUS_IS_OK(result)) { - - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; - } - } - - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; + if (!NT_STATUS_IS_OK(result)) { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", + NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; + } - } else { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); talloc_free(ids); return WINBINDD_ERROR; } + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } + } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; talloc_free(ids); return WINBINDD_OK; } -- cgit From d0a71a00bb0408713eca523807955b6dd087f2bc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Jul 2008 12:03:35 -0400 Subject: Make code more readable, fix indentation and traling spaces. (This used to be commit e19e12d5cbba28ccf682eaf0ff26909bd7e8e6c6) --- source3/winbindd/winbindd_user.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 45918383b7..270a297b7c 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -365,23 +365,27 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) { struct winbindd_domain *domain; fstring domname, username; + char *domuser; + size_t dusize; - /* Ensure null termination */ - state->request.data.username[sizeof(state->request.data.username)-1]='\0'; + domuser = state->request.data.username; + dusize = sizeof(state->request.data.username); - DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid, - state->request.data.username)); + /* Ensure null termination (it's an fstring) */ + domuser[dusize-1] = '\0'; - ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); + DEBUG(3, ("[%5lu]: getpwnam %s\n", + (unsigned long)state->pid, + domuser)); - if (!parse_domain_user(state->request.data.username, domname, - username)) { - DEBUG(5, ("Could not parse domain user: %s\n", - state->request.data.username)); + ws_name_return(domuser, WB_REPLACE_CHAR); + + if (!parse_domain_user(domuser, domname, username)) { + DEBUG(5, ("Could not parse domain user: %s\n", domuser)); request_error(state); return; } - + /* Get info for the domain */ domain = find_domain_from_name(domname); @@ -391,17 +395,19 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) "Using primary domain\n", domname)); if ( (domain = find_our_domain()) == NULL ) { DEBUG(0,("Cannot find my primary domain structure!\n")); - request_error(state); - return; - } + request_error(state); + return; + } } - if ( strequal(domname, lp_workgroup()) && lp_winbind_trusted_domains_only() ) { - DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", - domname, username)); + if (strequal(domname, lp_workgroup()) && + lp_winbind_trusted_domains_only() ) { + DEBUG(7,("winbindd_getpwnam: My domain -- " + "rejecting getpwnam() for %s\\%s.\n", + domname, username)); request_error(state); return; - } + } /* Get rid and name type from name. The following costs 1 packet */ -- cgit From 632e42e16503ba6e34e8bcb3a9449a2c39805426 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Jul 2008 12:17:22 -0400 Subject: More clean up, indentation and trailing space removal (This used to be commit d17d401603c1c26a5fd5eca5ece245790445e6d4) --- source3/winbindd/winbindd_user.c | 79 ++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 40 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 270a297b7c..c75ed4adf1 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -564,7 +564,7 @@ void winbindd_endpwent(struct winbindd_cli_state *state) { DEBUG(3, ("[%5lu]: endpwent\n", (unsigned long)state->pid)); - free_getent_state(state->getpwent_state); + free_getent_state(state->getpwent_state); state->getpwent_initialized = False; state->getpwent_state = NULL; request_ok(state); @@ -600,23 +600,23 @@ static bool get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) SAFE_FREE(ent->sam_entries); ent->num_sam_entries = 0; - + /* Call query_user_list to get a list of usernames and user rids */ num_entries = 0; - status = methods->query_user_list(domain, mem_ctx, &num_entries, - &info); - + status = methods->query_user_list(domain, mem_ctx, &num_entries, &info); + if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("get_sam_user_entries: query_user_list failed with %s\n", - nt_errstr(status) )); + DEBUG(10,("get_sam_user_entries: " + "query_user_list failed with %s\n", + nt_errstr(status))); return False; } if (num_entries) { - name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries); - + name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, + ent->num_sam_entries + num_entries); if (!name_list) { DEBUG(0,("get_sam_user_entries realloc failed.\n")); return False; @@ -628,40 +628,40 @@ static bool get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) if (!info[i].acct_name) { fstrcpy(name_list[ent->num_sam_entries + i].name, ""); } else { - fstrcpy(name_list[ent->num_sam_entries + i].name, - info[i].acct_name); + fstrcpy(name_list[ent->num_sam_entries + i].name, + info[i].acct_name); } if (!info[i].full_name) { fstrcpy(name_list[ent->num_sam_entries + i].gecos, ""); } else { - fstrcpy(name_list[ent->num_sam_entries + i].gecos, - info[i].full_name); + fstrcpy(name_list[ent->num_sam_entries + i].gecos, + info[i].full_name); } if (!info[i].homedir) { - fstrcpy(name_list[ent->num_sam_entries + i].homedir, ""); + fstrcpy(name_list[ent->num_sam_entries + i].homedir,""); } else { - fstrcpy(name_list[ent->num_sam_entries + i].homedir, - info[i].homedir); + fstrcpy(name_list[ent->num_sam_entries + i].homedir, + info[i].homedir); } if (!info[i].shell) { fstrcpy(name_list[ent->num_sam_entries + i].shell, ""); } else { - fstrcpy(name_list[ent->num_sam_entries + i].shell, - info[i].shell); + fstrcpy(name_list[ent->num_sam_entries + i].shell, + info[i].shell); } - - + + /* User and group ids */ sid_copy(&name_list[ent->num_sam_entries+i].user_sid, &info[i].user_sid); sid_copy(&name_list[ent->num_sam_entries+i].group_sid, &info[i].group_sid); } - + ent->num_sam_entries += num_entries; - + /* Fill in remaining fields */ - + ent->sam_entries = name_list; ent->sam_entry_index = 0; return ent->num_sam_entries > 0; @@ -694,20 +694,20 @@ void winbindd_getpwent(struct winbindd_cli_state *state) request_error(state); return; } - - if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) { + + user_list = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users); + if (!user_list) { request_error(state); return; } + /* will be freed by process_request() */ + state->response.extra_data.data = user_list; - memset(state->response.extra_data.data, 0, num_users * - sizeof(struct winbindd_pw)); - - user_list = (struct winbindd_pw *)state->response.extra_data.data; + memset(user_list, 0, num_users * sizeof(struct winbindd_pw)); if (!state->getpwent_initialized) winbindd_setpwent_internal(state); - + if (!(ent = state->getpwent_state)) { request_error(state); return; @@ -737,19 +737,19 @@ void winbindd_getpwent(struct winbindd_cli_state *state) SAFE_FREE(ent); ent = next_ent; } - + /* No more domains */ - if (!ent) + if (!ent) break; } name_list = (struct getpwent_user *)ent->sam_entries; /* Lookup user info */ - + result = winbindd_fill_pwent( - ent->domain_name, + ent->domain_name, name_list[ent->sam_entry_index].name, &name_list[ent->sam_entry_index].user_sid, &name_list[ent->sam_entry_index].group_sid, @@ -757,22 +757,21 @@ void winbindd_getpwent(struct winbindd_cli_state *state) name_list[ent->sam_entry_index].homedir, name_list[ent->sam_entry_index].shell, &user_list[user_list_ndx]); - + /* Add user to return list */ - + if (result) { - + user_list_ndx++; state->response.data.num_entries++; - state->response.length += - sizeof(struct winbindd_pw); + state->response.length += sizeof(struct winbindd_pw); } else DEBUG(1, ("could not lookup domain user %s\n", name_list[ent->sam_entry_index].name)); ent->sam_entry_index++; - + } /* Out of domains */ -- cgit From fae6a4e79b4476dcd77be7011011e25b27a36f22 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Jul 2008 12:27:34 -0400 Subject: Clean up the rest of the file too (This used to be commit f6c92c4759096f839e3854a1e9eea56e6eecad4d) --- source3/winbindd/winbindd_user.c | 160 +++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 84 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index c75ed4adf1..576300555a 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -27,12 +27,12 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -static bool fillup_pw_field(const char *lp_template, - const char *username, +static bool fillup_pw_field(const char *lp_template, + const char *username, const char *domname, uid_t uid, gid_t gid, - const char *in, + const char *in, fstring out) { char *templ; @@ -40,43 +40,43 @@ static bool fillup_pw_field(const char *lp_template, if (out == NULL) return False; - /* The substitution of %U and %D in the 'template + /* The substitution of %U and %D in the 'template homedir' is done by talloc_sub_specified() below. If we have an in string (which means the value has already been set in the nss_info backend), then use that. Otherwise use the template value passed in. */ if ( in && !strequal(in,"") && lp_security() == SEC_ADS ) { - templ = talloc_sub_specified(NULL, in, + templ = talloc_sub_specified(NULL, in, username, domname, uid, gid); } else { - templ = talloc_sub_specified(NULL, lp_template, + templ = talloc_sub_specified(NULL, lp_template, username, domname, - uid, gid); + uid, gid); } - + if (!templ) return False; safe_strcpy(out, templ, sizeof(fstring) - 1); TALLOC_FREE(templ); - + return True; - + } /* Fill a pwent structure with information we have obtained */ -static bool winbindd_fill_pwent(char *dom_name, char *user_name, +static bool winbindd_fill_pwent(char *dom_name, char *user_name, DOM_SID *user_sid, DOM_SID *group_sid, char *full_name, char *homedir, char *shell, struct winbindd_pw *pw) { fstring output_username; - + if (!pw || !dom_name || !user_name) return False; - + /* Resolve the uid number */ if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) { @@ -84,8 +84,8 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, sid_string_dbg(user_sid))); return False; } - - /* Resolve the gid number */ + + /* Resolve the gid number */ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) { DEBUG(1, ("error getting group id for sid %s\n", @@ -97,21 +97,21 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, /* Username */ - fill_domain_username(output_username, dom_name, user_name, True); + fill_domain_username(output_username, dom_name, user_name, True); safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); - + /* Full name (gecos) */ - + safe_strcpy(pw->pw_gecos, full_name, sizeof(pw->pw_gecos) - 1); /* Home directory and shell */ - - if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, + + if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir)) return False; - if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, + if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, pw->pw_uid, pw->pw_gid, shell, pw->pw_shell)) return False; @@ -135,7 +135,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, + DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, state->request.data.sid)); if (!string_to_sid(&sid, state->request.data.sid)) { @@ -155,7 +155,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, fstrcpy(state->response.data.user_info.full_name, user_info.full_name); fstrcpy(state->response.data.user_info.homedir, user_info.homedir); fstrcpy(state->response.data.user_info.shell, user_info.shell); - state->response.data.user_info.primary_gid = user_info.primary_gid; + state->response.data.user_info.primary_gid = user_info.primary_gid; if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid, &state->response.data.user_info.group_rid)) { DEBUG(1, ("Could not extract group rid out of %s\n", @@ -181,7 +181,7 @@ struct getpwsid_state { static void getpwsid_queryuser_recv(void *private_data, bool success, const char *acct_name, - const char *full_name, + const char *full_name, const char *homedir, const char *shell, uint32 gid, @@ -217,10 +217,10 @@ static void winbindd_getpwsid(struct winbindd_cli_state *state, error: request_error(state); } - + static void getpwsid_queryuser_recv(void *private_data, bool success, const char *acct_name, - const char *full_name, + const char *full_name, const char *homedir, const char *shell, uint32 gid, @@ -239,43 +239,43 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, if ( acct_name && *acct_name ) { fstrcpy( username, acct_name ); - } else { + } else { char *domain_name = NULL; enum lsa_SidType type; char *user_name = NULL; struct winbindd_domain *domain = NULL; - + domain = find_lookup_domain_from_sid(&s->user_sid); if (domain == NULL) { DEBUG(5, ("find_lookup_domain_from_sid(%s) failed\n", sid_string_dbg(&s->user_sid))); request_error(s->state); - return; + return; } winbindd_lookup_name_by_sid(s->state->mem_ctx, domain, &s->user_sid, &domain_name, - &user_name, &type ); + &user_name, &type ); /* If this still fails we ar4e done. Just error out */ if ( !user_name ) { DEBUG(5,("Could not obtain a name for SID %s\n", sid_string_dbg(&s->user_sid))); request_error(s->state); - return; + return; } - fstrcpy( username, user_name ); + fstrcpy( username, user_name ); } strlower_m( username ); s->username = talloc_strdup(s->state->mem_ctx, username); ws_name_replace( s->username, WB_REPLACE_CHAR ); - + s->fullname = talloc_strdup(s->state->mem_ctx, full_name); s->homedir = talloc_strdup(s->state->mem_ctx, homedir); s->shell = talloc_strdup(s->state->mem_ctx, shell); - s->gid = gid; + s->gid = gid; sid_copy(&s->group_sid, &s->domain->sid); sid_append_rid(&s->group_sid, group_rid); @@ -328,18 +328,21 @@ static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid) pw = &s->state->response.data.pw; pw->pw_uid = s->uid; pw->pw_gid = s->gid; - fill_domain_username(output_username, s->domain->name, s->username, True); + fill_domain_username(output_username, s->domain->name, + s->username, True); safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1); - if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, - pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) { + if (!fillup_pw_field(lp_template_homedir(), s->username, + s->domain->name, pw->pw_uid, pw->pw_gid, + s->homedir, pw->pw_dir)) { DEBUG(5, ("Could not compose homedir\n")); goto failed; } - if (!fillup_pw_field(lp_template_shell(), s->username, s->domain->name, - pw->pw_uid, pw->pw_gid, s->shell, pw->pw_shell)) { + if (!fillup_pw_field(lp_template_shell(), s->username, + s->domain->name, pw->pw_uid, pw->pw_gid, + s->shell, pw->pw_shell)) { DEBUG(5, ("Could not compose shell\n")); goto failed; } @@ -412,7 +415,7 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) /* Get rid and name type from name. The following costs 1 packet */ winbindd_lookupname_async(state->mem_ctx, domname, username, - getpwnam_name2sid_recv, WINBINDD_GETPWNAM, + getpwnam_name2sid_recv, WINBINDD_GETPWNAM, state); } @@ -421,27 +424,25 @@ static void getpwnam_name2sid_recv(void *private_data, bool success, { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; - fstring domname, username; + fstring domname, username; + char *domuser = state->request.data.username; if (!success) { - DEBUG(5, ("Could not lookup name for user %s\n", - state->request.data.username)); + DEBUG(5, ("Could not lookup name for user %s\n", domuser)); request_error(state); return; } if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) { - DEBUG(5, ("%s is not a user\n", state->request.data.username)); + DEBUG(5, ("%s is not a user\n", domuser)); request_error(state); return; } - if ( parse_domain_user(state->request.data.username, domname, username) ) { - check_domain_trusted( domname, sid ); + if (parse_domain_user(domuser, domname, username)) { + check_domain_trusted(domname, sid); } - - winbindd_getpwsid(state, sid); } @@ -457,7 +458,7 @@ static void getpwuid_recv(void *private_data, bool success, const char *sid) request_error(state); return; } - + DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n", (unsigned long)(state->request.data.uid), sid)); @@ -468,12 +469,16 @@ static void getpwuid_recv(void *private_data, bool success, const char *sid) /* Return a password structure given a uid number */ void winbindd_getpwuid(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5lu]: getpwuid %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.uid)); + uid_t uid = state->request.data.uid; + + DEBUG(3, ("[%5lu]: getpwuid %lu\n", + (unsigned long)state->pid, + (unsigned long)uid)); /* always query idmap via the async interface */ - /* if this turns to be too slow we will add here a direct query to the cache */ - winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, getpwuid_recv, state); + /* if this turns to be too slow we will add here + * a direct query to the cache */ + winbindd_uid2sid_async(state->mem_ctx, uid, getpwuid_recv, state); } /* @@ -485,66 +490,53 @@ void winbindd_getpwuid(struct winbindd_cli_state *state) static bool winbindd_setpwent_internal(struct winbindd_cli_state *state) { struct winbindd_domain *domain; - + DEBUG(3, ("[%5lu]: setpwent\n", (unsigned long)state->pid)); - + /* Check user has enabled this */ - + if (!lp_winbind_enum_users()) { return False; } /* Free old static data if it exists */ - + if (state->getpwent_state != NULL) { free_getent_state(state->getpwent_state); state->getpwent_state = NULL; } -#if 0 /* JERRY */ - /* add any local users we have */ - - if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL ) - return False; - - ZERO_STRUCTP(domain_state); - - /* Add to list of open domains */ - - DLIST_ADD(state->getpwent_state, domain_state); -#endif - /* Create sam pipes for each domain we know about */ - + for(domain = domain_list(); domain != NULL; domain = domain->next) { struct getent_state *domain_state; - - - /* don't add our domaina if we are a PDC or if we + + + /* don't add our domaina if we are a PDC or if we are a member of a Samba domain */ - - if ( (IS_DC || lp_winbind_trusted_domains_only()) - && strequal(domain->name, lp_workgroup()) ) - { + + if ((IS_DC || lp_winbind_trusted_domains_only()) + && strequal(domain->name, lp_workgroup())) { continue; } - + /* Create a state record for this domain */ - - if ((domain_state = SMB_MALLOC_P(struct getent_state)) == NULL) { + + domain_state = SMB_MALLOC_P(struct getent_state); + if (!domain_state) { DEBUG(0, ("malloc failed\n")); return False; } - + ZERO_STRUCTP(domain_state); fstrcpy(domain_state->domain_name, domain->name); /* Add to list of open domains */ - + DLIST_ADD(state->getpwent_state, domain_state); } - + state->getpwent_initialized = True; return True; } -- cgit From 4be7a83a2cc249f4b15de43df30560fe078dacf8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Jul 2008 12:55:07 -0400 Subject: Clean up winbindd_group.c too (This used to be commit 50a347f5503ebed0fcc7b9de60f8368677585bb1) --- source3/winbindd/winbindd_group.c | 465 +++++++++++++++++++++----------------- 1 file changed, 255 insertions(+), 210 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 20b90e3283..69e3a6a555 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -45,7 +45,9 @@ static void add_member(const char *domain, const char *user, Add member users resulting from sid. Expand if it is a domain group. **********************************************************************/ -static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_num_members) +static void add_expanded_sid(const DOM_SID *sid, + char **pp_members, + size_t *p_num_members) { DOM_SID dom_sid; uint32 rid; @@ -143,8 +145,8 @@ static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_nu } static bool fill_passdb_alias_grmem(struct winbindd_domain *domain, - DOM_SID *group_sid, - size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len) + DOM_SID *group_sid, size_t *num_gr_mem, + char **gr_mem, size_t *gr_mem_len) { DOM_SID *members; size_t i, num_members; @@ -177,7 +179,7 @@ static bool fill_passdb_alias_grmem(struct winbindd_domain *domain, /* Fill a grent structure from various other information */ -static bool fill_grent(struct winbindd_gr *gr, const char *dom_name, +static bool fill_grent(struct winbindd_gr *gr, const char *dom_name, const char *gr_name, gid_t unix_gid) { fstring full_group_name; @@ -185,9 +187,9 @@ static bool fill_grent(struct winbindd_gr *gr, const char *dom_name, fill_domain_username( full_group_name, dom_name, gr_name, True ); gr->gr_gid = unix_gid; - + /* Group name and password */ - + safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1); safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1); @@ -208,7 +210,7 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, DOM_SID *group_sid, enum lsa_SidType group_name_type, - size_t *num_gr_mem, char **gr_mem, + size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len) { DOM_SID querying_user_sid; @@ -232,7 +234,8 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, status = idmap_uid_to_sid(&querying_user_sid, ret_uid); if (NT_STATUS_IS_OK(status)) { pquerying_user_sid = &querying_user_sid; - DEBUG(10,("fill_grent_mem_domain_users: querying uid %u -> %s\n", + DEBUG(10,("fill_grent_mem_domain_users: " + "querying uid %u -> %s\n", (unsigned int)ret_uid, sid_string_dbg(pquerying_user_sid))); } @@ -242,22 +245,23 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, /* Only look up if it was a winbindd user in this domain. */ if (pquerying_user_sid && (sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) { - + DEBUG(10,("fill_grent_mem_domain_users: querying user = %s\n", sid_string_dbg(pquerying_user_sid) )); - + status = domain->methods->lookup_usergroups(domain, mem_ctx, pquerying_user_sid, &num_groups, &user_sids); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("fill_grent_mem_domain_users: lookup_usergroups failed " - "for sid %s in domain %s (error: %s)\n", + DEBUG(1, ("fill_grent_mem_domain_users: " + "lookup_usergroups failed " + "for sid %s in domain %s (error: %s)\n", sid_string_dbg(pquerying_user_sid), domain->name, nt_errstr(status))); - return False; + return False; } for (i = 0; i < num_groups; i++) { @@ -269,18 +273,19 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, } } } - + if (u_in_group) { size_t len = 0; char *domainname = NULL; char *username = NULL; fstring name; enum lsa_SidType type; - - DEBUG(10,("fill_grent_mem_domain_users: sid %s in 'Domain Users' in domain %s\n", + + DEBUG(10,("fill_grent_mem_domain_users: " + "sid %s in 'Domain Users' in domain %s\n", sid_string_dbg(pquerying_user_sid), domain->name )); - + status = domain->methods->sid_to_name(domain, mem_ctx, pquerying_user_sid, &domainname, @@ -288,38 +293,39 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, &type); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("could not lookup username for user " - "sid %s in domain %s (error: %s)\n", + "sid %s in domain %s (error: %s)\n", sid_string_dbg(pquerying_user_sid), domain->name, nt_errstr(status))); - return False; + return False; } fill_domain_username(name, domain->name, username, True); len = strlen(name); buf_len = len + 1; if (!(buf = (char *)SMB_MALLOC(buf_len))) { DEBUG(1, ("out of memory\n")); - return False; + return False; } memcpy(buf, name, buf_len); - + DEBUG(10,("fill_grent_mem_domain_users: user %s in " "'Domain Users' in domain %s\n", name, domain->name )); - + /* user is the only member */ *num_gr_mem = 1; } - + *gr_mem = buf; *gr_mem_len = buf_len; - - DEBUG(10, ("fill_grent_mem_domain_users: num_mem = %u, len = %u, mem = %s\n", - (unsigned int)*num_gr_mem, - (unsigned int)buf_len, *num_gr_mem ? buf : "NULL")); + + DEBUG(10, ("fill_grent_mem_domain_users: " + "num_mem = %u, len = %u, mem = %s\n", + (unsigned int)*num_gr_mem, + (unsigned int)buf_len, *num_gr_mem ? buf : "NULL")); return True; -} +} /*********************************************************************** Add names to a list. Assumes a canonical version of the string @@ -328,28 +334,29 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, static int namecmp( const void *a, const void *b ) { - return StrCaseCmp( * (char * const *) a, * (char * const *) b); + return StrCaseCmp( * (char * const *) a, * (char * const *) b); } -static NTSTATUS add_names_to_list( TALLOC_CTX *ctx, - char ***list, uint32 *n_list, +static NTSTATUS add_names_to_list( TALLOC_CTX *ctx, + char ***list, uint32 *n_list, char **names, uint32 n_names ) { - char **new_list = NULL; - uint32 n_new_list = 0; - int i, j; + char **new_list = NULL; + uint32 n_new_list = 0; + int i, j; if ( !names || (n_names == 0) ) return NT_STATUS_OK; - + /* Alloc the maximum size we'll need */ if ( *list == NULL ) { - if ( (new_list = TALLOC_ARRAY( ctx, char *, n_names )) == NULL ) + if ((new_list = TALLOC_ARRAY(ctx, char *, n_names)) == NULL) { return NT_STATUS_NO_MEMORY; - n_new_list = n_names; + } + n_new_list = n_names; } else { - new_list = TALLOC_REALLOC_ARRAY( ctx, *list, char *, + new_list = TALLOC_REALLOC_ARRAY( ctx, *list, char *, (*n_list) + n_names ); if ( !new_list ) return NT_STATUS_NO_MEMORY; @@ -364,33 +371,33 @@ static NTSTATUS add_names_to_list( TALLOC_CTX *ctx, /* search for duplicates for sorting and looking for matching neighbors */ - + qsort( new_list, n_new_list, sizeof(char*), QSORT_CAST namecmp ); - + for ( i=1; imethods->lookup_groupmem(d, tmp_ctx, + status = d->methods->lookup_groupmem(d, tmp_ctx, &glist[i], &num_names, - &sid_mem, &names, + &sid_mem, &names, &name_types); - if ( !NT_STATUS_IS_OK(status) ) + if ( !NT_STATUS_IS_OK(status) ) goto out; - + /* Separate users and groups into two lists */ for ( j=0; jname))) return False; @@ -508,7 +516,7 @@ static bool fill_grent_mem(struct winbindd_domain *domain, if ( !((group_name_type==SID_NAME_DOM_GRP) || ((group_name_type==SID_NAME_ALIAS) && domain->primary)) ) { - DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", + DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", sid_string_dbg(group_sid), domain->name, group_name_type)); goto done; @@ -519,15 +527,15 @@ static bool fill_grent_mem(struct winbindd_domain *domain, sid_peek_rid( group_sid, &group_rid ); if (!lp_winbind_enum_users() && group_rid == DOMAIN_GROUP_RID_USERS) { - result = fill_grent_mem_domusers( mem_ctx, domain, state, + result = fill_grent_mem_domusers( mem_ctx, domain, state, group_sid, group_name_type, num_gr_mem, gr_mem, gr_mem_len ); - goto done; + goto done; } /* Real work goes here. Create a list of group names to - expand startign with the initial one. Pass that to + expand startign with the initial one. Pass that to expand_groups() which returns a list of more group names to expand. Do this up to the max search depth. */ @@ -536,33 +544,33 @@ static bool fill_grent_mem(struct winbindd_domain *domain, DEBUG(0,("fill_grent_mem: talloc failure!\n")); goto done; } - sid_copy( &glist[0], group_sid ); - n_glist = 1; + sid_copy( &glist[0], group_sid ); + n_glist = 1; for ( i=0; irequest.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; @@ -676,14 +686,14 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) state->request.data.groupname)); /* Parse domain and groupname */ - + memset(name_group, 0, sizeof(fstring)); tmp = state->request.data.groupname; name_domain[0] = '\0'; name_group[0] = '\0'; - + parse_domain_user(tmp, name_domain, name_group); /* if no domain or our local domain and no local tdb group, default to @@ -702,7 +712,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) return; } /* should we deal with users for our domain? */ - + if ( lp_winbind_trusted_domains_only() && domain->primary) { DEBUG(7,("winbindd_getgrnam: My domain -- rejecting " "getgrnam() for %s\\%s.\n", name_domain, name_group)); @@ -713,7 +723,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) /* Get rid and name type from name */ ws_name_replace( name_group, WB_REPLACE_CHAR ); - + winbindd_lookupname_async( state->mem_ctx, domain->name, name_group, getgrnam_recv, WINBINDD_GETGRNAM, state ); } @@ -722,7 +732,7 @@ struct getgrsid_state { struct winbindd_cli_state *state; struct winbindd_domain *domain; char *group_name; - enum lsa_SidType group_type; + enum lsa_SidType group_type; uid_t gid; DOM_SID group_sid; }; @@ -735,7 +745,7 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) size_t gr_mem_len; size_t num_gr_mem; char *gr_mem; - fstring dom_name, group_name; + fstring dom_name, group_name; if (!success) { DEBUG(5,("getgrsid_sid2gid_recv: sid2gid failed!\n")); @@ -751,7 +761,7 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) return; } - + /* Fill in group structure */ if ( (domain = find_domain_from_name_noinit(dom_name)) == NULL ) { @@ -762,7 +772,7 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) if (!fill_grent(&s->state->response.data.gr, dom_name, group_name, gid) || !fill_grent_mem(domain, s->state, &s->group_sid, s->group_type, - &num_gr_mem, &gr_mem, &gr_mem_len)) + &num_gr_mem, &gr_mem, &gr_mem_len)) { request_error(s->state); return; @@ -777,7 +787,7 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) s->state->response.length += gr_mem_len; s->state->response.extra_data.data = gr_mem; - request_ok(s->state); + request_ok(s->state); } static void getgrsid_lookupsid_recv( void *private_data, bool success, @@ -796,16 +806,16 @@ static void getgrsid_lookupsid_recv( void *private_data, bool success, local group in an internal domain */ if ( !( (name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && + ((name_type==SID_NAME_ALIAS) && (s->domain->primary || s->domain->internal)) ) ) { - DEBUG(1, ("name '%s\\%s' is not a local or domain group: %d\n", + DEBUG(1, ("name '%s\\%s' is not a local or domain group: %d\n", dom_name, name, name_type)); request_error(s->state); return; } - if ( (s->group_name = talloc_asprintf( s->state->mem_ctx, + if ( (s->group_name = talloc_asprintf( s->state->mem_ctx, "%s%c%s", dom_name, *lp_winbind_separator(), @@ -843,7 +853,7 @@ static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID g sid_copy(&s->group_sid, &group_sid); - winbindd_lookupsid_async( s->state->mem_ctx, &group_sid, + winbindd_lookupsid_async( s->state->mem_ctx, &group_sid, getgrsid_lookupsid_recv, s ); } @@ -874,7 +884,7 @@ static void getgrgid_recv(void *private_data, bool success, const char *sid) return; } - DEBUG(1, ("could not convert gid %lu to sid\n", + DEBUG(1, ("could not convert gid %lu to sid\n", (unsigned long)state->request.data.gid)); request_error(state); } @@ -882,11 +892,14 @@ static void getgrgid_recv(void *private_data, bool success, const char *sid) /* Return a group structure from a gid number */ void winbindd_getgrgid(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, - (unsigned long)state->request.data.gid)); + gid_t gid = state->request.data.gid; + + DEBUG(3, ("[%5lu]: getgrgid %lu\n", + (unsigned long)state->pid, + (unsigned long)gid)); /* always use the async interface */ - winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, getgrgid_recv, state); + winbindd_gid2sid_async(state->mem_ctx, gid, getgrgid_recv, state); } /* @@ -905,45 +918,46 @@ static bool winbindd_setgrent_internal(struct winbindd_cli_state *state) if (!lp_winbind_enum_groups()) { return False; - } + } /* Free old static data if it exists */ - + if (state->getgrent_state != NULL) { free_getent_state(state->getgrent_state); state->getgrent_state = NULL; } - + /* Create sam pipes for each domain we know about */ - + for (domain = domain_list(); domain != NULL; domain = domain->next) { struct getent_state *domain_state; - + /* Create a state record for this domain */ - /* don't add our domaina if we are a PDC or if we + /* don't add our domaina if we are a PDC or if we are a member of a Samba domain */ - + if ( lp_winbind_trusted_domains_only() && domain->primary ) { continue; } - - - if ((domain_state = SMB_MALLOC_P(struct getent_state)) == NULL) { - DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n")); + + domain_state = SMB_MALLOC_P(struct getent_state); + if (!domain_state) { + DEBUG(1, ("winbindd_setgrent: " + "malloc failed for domain_state!\n")); return False; } - + ZERO_STRUCTP(domain_state); - + fstrcpy(domain_state->domain_name, domain->name); /* Add to list of open domains */ - + DLIST_ADD(state->getgrent_state, domain_state); } - + state->getgrent_initialized = True; return True; } @@ -970,7 +984,7 @@ void winbindd_endgrent(struct winbindd_cli_state *state) } /* Get the list of domain groups and domain aliases for a domain. We fill in - the sam_entries and num_sam_entries fields with domain group information. + the sam_entries and num_sam_entries fields with domain group information. Return True if some groups were returned, False otherwise. */ bool get_sam_group_entries(struct getent_state *ent) @@ -982,16 +996,17 @@ bool get_sam_group_entries(struct getent_state *ent) bool result = False; struct acct_info *sam_grp_entries = NULL; struct winbindd_domain *domain; - + if (ent->got_sam_entries) return False; if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)", ent->domain_name))) { - DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n")); + DEBUG(1, ("get_sam_group_entries: " + "could not create talloc context!\n")); return False; } - + /* Free any existing group info */ SAFE_FREE(ent->sam_entries); @@ -1003,16 +1018,20 @@ bool get_sam_group_entries(struct getent_state *ent) num_entries = 0; if (!(domain = find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name)); + DEBUG(3, ("no such domain %s in get_sam_group_entries\n", + ent->domain_name)); goto done; } /* always get the domain global groups */ - status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - + status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, + &sam_grp_entries); + if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s\n", nt_errstr(status))); + DEBUG(3, ("get_sam_group_entries: " + "could not enumerate domain groups! Error: %s\n", + nt_errstr(status))); result = False; goto done; } @@ -1020,29 +1039,36 @@ bool get_sam_group_entries(struct getent_state *ent) /* Copy entries into return buffer */ if (num_entries) { - if ( !(name_list = SMB_MALLOC_ARRAY(struct acct_info, num_entries)) ) { - DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n", - num_entries)); + name_list = SMB_MALLOC_ARRAY(struct acct_info, num_entries); + if (!name_list) { + DEBUG(0,("get_sam_group_entries: Failed to malloc " + "memory for %d domain groups!\n", + num_entries)); result = False; goto done; } - memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) ); + memcpy(name_list, sam_grp_entries, + num_entries * sizeof(struct acct_info)); } - + ent->num_sam_entries = num_entries; - - /* get the domain local groups if we are a member of a native win2k domain - and are not using LDAP to get the groups */ - - if ( ( lp_security() != SEC_ADS && domain->native_mode + + /* get the domain local groups if we are a member of a native win2k + * domain and are not using LDAP to get the groups */ + + if ( ( lp_security() != SEC_ADS && domain->native_mode && domain->primary) || domain->internal ) { - DEBUG(4,("get_sam_group_entries: %s domain; enumerating local groups as well\n", - domain->native_mode ? "Native Mode 2k":"BUILTIN or local")); - - status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - - if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(4,("get_sam_group_entries: %s domain; " + "enumerating local groups as well\n", + domain->native_mode ? "Native Mode 2k": + "BUILTIN or local")); + + status = domain->methods->enum_local_groups(domain, mem_ctx, + &num_entries, + &sam_grp_entries); + + if ( !NT_STATUS_IS_OK(status) ) { DEBUG(3,("get_sam_group_entries: " "Failed to enumerate " "domain local groups with error %s!\n", @@ -1050,27 +1076,35 @@ bool get_sam_group_entries(struct getent_state *ent) num_entries = 0; } else - DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries)); - + DEBUG(4,("get_sam_group_entries: " + "Returned %d local groups\n", + num_entries)); + /* Copy entries into return buffer */ if ( num_entries ) { - if ( !(name_list = SMB_REALLOC_ARRAY( name_list, struct acct_info, ent->num_sam_entries+num_entries)) ) - { - DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n", - num_entries)); + name_list = SMB_REALLOC_ARRAY(name_list, + struct acct_info, + ent->num_sam_entries+ + num_entries); + if (!name_list) { + DEBUG(0,("get_sam_group_entries: " + "Failed to realloc more memory " + "for %d local groups!\n", + num_entries)); result = False; goto done; } - - memcpy( &name_list[ent->num_sam_entries], sam_grp_entries, - num_entries * sizeof(struct acct_info) ); + + memcpy(&name_list[ent->num_sam_entries], + sam_grp_entries, + num_entries * sizeof(struct acct_info)); } - + ent->num_sam_entries += num_entries; } - - + + /* Fill in remaining fields */ ent->sam_entries = name_list; @@ -1111,18 +1145,19 @@ void winbindd_getgrent(struct winbindd_cli_state *state) return; } - if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) { + group_list = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups); + if (!group_list) { request_error(state); return; } + /* will be freed by process_request() */ + state->response.extra_data.data = group_list; memset(state->response.extra_data.data, '\0', num_groups * sizeof(struct winbindd_gr) ); state->response.data.num_entries = 0; - group_list = (struct winbindd_gr *)state->response.extra_data.data; - if (!state->getgrent_initialized) winbindd_setgrent_internal(state); @@ -1142,7 +1177,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state) char *gr_mem; DOM_SID group_sid; struct winbindd_domain *domain; - + /* Do we need to fetch another chunk of groups? */ tryagain: @@ -1155,7 +1190,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state) while(ent && !get_sam_group_entries(ent)) { struct getent_state *next_ent; - DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name)); + DEBUG(10, ("freeing state info for domain %s\n", + ent->domain_name)); /* Free state information for this domain */ @@ -1163,28 +1199,28 @@ void winbindd_getgrent(struct winbindd_cli_state *state) next_ent = ent->next; DLIST_REMOVE(state->getgrent_state, ent); - + SAFE_FREE(ent); ent = next_ent; } /* No more domains */ - if (!ent) + if (!ent) break; } - + name_list = (struct acct_info *)ent->sam_entries; - - if (!(domain = - find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); + + if (!(domain = find_domain_from_name(ent->domain_name))) { + DEBUG(3, ("No such domain %s in winbindd_getgrent\n", + ent->domain_name)); result = False; goto done; } /* Lookup group info */ - + sid_copy(&group_sid, &domain->sid); sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); @@ -1196,9 +1232,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state) sid_string_dbg(&group_sid))); if (!pdb_sid_to_id(&group_sid, &id, &type)) { - DEBUG(1, ("could not look up gid for group " - "%s\n", - name_list[ent->sam_entry_index].acct_name)); + DEBUG(1,("could not look up gid for group %s\n", + name_list[ent->sam_entry_index].acct_name)); ent->sam_entry_index++; goto tryagain; } @@ -1215,15 +1250,16 @@ void winbindd_getgrent(struct winbindd_cli_state *state) group_gid = id.gid; } - DEBUG(10, ("got gid %lu for group %lu\n", (unsigned long)group_gid, + DEBUG(10, ("got gid %lu for group %lu\n", + (unsigned long)group_gid, (unsigned long)name_list[ent->sam_entry_index].rid)); - + /* Fill in group entry */ - fill_domain_username(domain_group_name, ent->domain_name, + fill_domain_username(domain_group_name, ent->domain_name, name_list[ent->sam_entry_index].acct_name, True); - result = fill_grent(&group_list[group_list_ndx], + result = fill_grent(&group_list[group_list_ndx], ent->domain_name, name_list[ent->sam_entry_index].acct_name, group_gid); @@ -1236,8 +1272,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state) group_list[group_list_ndx].num_gr_mem = 0; gr_mem = NULL; gr_mem_len = 0; - - /* Get group membership */ + + /* Get group membership */ if (state->request.cmd == WINBINDD_GETGRLST) { result = True; } else { @@ -1260,7 +1296,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state) gr_mem_list = (char *)SMB_REALLOC( gr_mem_list, gr_mem_list_len + gr_mem_len); - if (!gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) { + if (!gr_mem_list && + (group_list[group_list_ndx].num_gr_mem != 0)) { DEBUG(0, ("out of memory\n")); gr_mem_list_len = 0; break; @@ -1274,16 +1311,16 @@ void winbindd_getgrent(struct winbindd_cli_state *state) SAFE_FREE(gr_mem); - group_list[group_list_ndx].gr_mem_ofs = + group_list[group_list_ndx].gr_mem_ofs = gr_mem_list_len; gr_mem_list_len += gr_mem_len; } ent->sam_entry_index++; - + /* Add group to return list */ - + if (result) { DEBUG(10, ("adding group num_entries = %d\n", @@ -1291,12 +1328,12 @@ void winbindd_getgrent(struct winbindd_cli_state *state) group_list_ndx++; state->response.data.num_entries++; - + state->response.length += sizeof(struct winbindd_gr); - + } else { - DEBUG(0, ("could not lookup domain group %s\n", + DEBUG(0, ("could not lookup domain group %s\n", domain_group_name)); } } @@ -1319,7 +1356,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state) } memcpy(&((char *)state->response.extra_data.data) - [group_list_ndx * sizeof(struct winbindd_gr)], + [group_list_ndx * sizeof(struct winbindd_gr)], gr_mem_list, gr_mem_list_len); state->response.length += gr_mem_list_len; @@ -1408,25 +1445,27 @@ void winbindd_getgroups(struct winbindd_cli_state *state) return; } - s->domname = talloc_strdup( state->mem_ctx, get_global_sam_name() ); - s->username = talloc_strdup( state->mem_ctx, state->request.data.username ); + s->domname = talloc_strdup(state->mem_ctx, + get_global_sam_name()); + s->username = talloc_strdup(state->mem_ctx, + state->request.data.username); } - - /* Get info for the domain (either by short domain name or + + /* Get info for the domain (either by short domain name or DNS name in the case of a UPN) */ s->domain = find_domain_from_name_noinit(s->domname); if (!s->domain) { char *p = strchr(s->username, '@'); - + if (p) { - s->domain = find_domain_from_name_noinit(p+1); + s->domain = find_domain_from_name_noinit(p+1); } - + } if (s->domain == NULL) { - DEBUG(7, ("could not find domain entry for domain %s\n", + DEBUG(7, ("could not find domain entry for domain %s\n", s->domname)); request_error(state); return; @@ -1438,12 +1477,14 @@ void winbindd_getgroups(struct winbindd_cli_state *state) s->username)); request_error(state); return; - } + } /* Get rid and name type from name. The following costs 1 packet */ - winbindd_lookupname_async(state->mem_ctx, s->domname, s->username, - getgroups_usersid_recv, WINBINDD_GETGROUPS, s); + winbindd_lookupname_async(state->mem_ctx, + s->domname, s->username, + getgroups_usersid_recv, + WINBINDD_GETGROUPS, s); } static void getgroups_usersid_recv(void *private_data, bool success, @@ -1518,7 +1559,9 @@ static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid) s->state->response.data.num_entries = s->num_token_gids; if (s->num_token_gids) { /* s->token_gids are talloced */ - s->state->response.extra_data.data = smb_xmemdup(s->token_gids, s->num_token_gids * sizeof(gid_t)); + s->state->response.extra_data.data = + smb_xmemdup(s->token_gids, + s->num_token_gids * sizeof(gid_t)); s->state->response.length += s->num_token_gids * sizeof(gid_t); } request_ok(s->state); @@ -1529,7 +1572,7 @@ static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid) rather than a NAME->SID->SIDS->GIDS mapping, which means we avoid idmap. This call is designed to be used with applications that need to do ACL evaluation themselves. Note that the cached info3 data is - not used + not used this function assumes that the SID that comes in is a user SID. If you pass in another type of SID then you may get unpredictable @@ -1622,9 +1665,9 @@ void winbindd_getuserdomgroups(struct winbindd_cli_state *state) return; } - /* Get info for the domain */ + /* Get info for the domain */ if ((domain = find_domain_from_sid_noinit(&user_sid)) == NULL) { - DEBUG(0,("could not find domain entry for sid %s\n", + DEBUG(0,("could not find domain entry for sid %s\n", sid_string_dbg(&user_sid))); request_error(state); return; @@ -1665,7 +1708,9 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma return WINBINDD_OK; } - if (!print_sidlist(state->mem_ctx, groups, num_groups, &sidstring, &len)) { + if (!print_sidlist(state->mem_ctx, + groups, num_groups, + &sidstring, &len)) { DEBUG(0, ("talloc failed\n")); return WINBINDD_ERROR; } -- cgit From 06b3a79d1fb2b66c39e0d8667c5904bfaff26b03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2008 11:26:16 -0700 Subject: Allow authentication and memory credential refresh after password change from gdm/xdm. Patch from boyang . Jeremy. (This used to be commit 8cfc6afc7b4a6af9aea5f5a7cb5af7e3218c2d75) --- source3/winbindd/winbindd_pam.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f7001f7716..c26f552d31 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2114,11 +2114,21 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact done: if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { - + /* Update the single sign-on memory creds. */ result = winbindd_replace_memory_creds(state->request.data.chauthtok.user, newpass); + /* When we login from gdm or xdm and password expires, + * we change password, but there are no memory crendentials + * So, winbindd_replace_memory_creds() returns + * NT_STATUS_OBJECT_NAME_NOT_FOUND. This is not a failure. + * --- BoYang + * */ + if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + result = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result))); goto process_result; @@ -2128,12 +2138,23 @@ done: result = winbindd_update_creds_by_name(contact_domain, state->mem_ctx, user, newpass); + /* Again, this happens when we login from gdm or xdm + * and the password expires, *BUT* cached crendentials + * doesn't exist. winbindd_update_creds_by_name() + * returns NT_STATUS_NO_SUCH_USER. + * This is not a failure. + * --- BoYang + * */ + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) { + result = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); goto process_result; } } - } + } if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { -- cgit From 6c3c068716c9b7a3a7fe041fc605bcd00b376ec9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:42:40 +0200 Subject: Revert "Tiny logic simplification -- remove an else branch" This reverts commit 01c8c7bbf6163d5c7733db0d8ecbccfe7e4fec7d. (This used to be commit b0fe0c7ac18d4f47ad4a218114de7bab7a3f19de) --- source3/winbindd/winbindd_idmap.c | 42 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 631f5c1ab4..98f8548083 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -241,31 +241,33 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, result = idmap_sids_to_unixids(ids, num); - if (!NT_STATUS_IS_OK(result)) { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", - NT_STATUS_V(result))); - talloc_free(ids); - return WINBINDD_ERROR; - } + if (NT_STATUS_IS_OK(result)) { - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } + xids = SMB_MALLOC_ARRAY(struct unixid, num); + if ( ! xids) { + DEBUG(0, ("Out of memory!\n")); + talloc_free(ids); + return WINBINDD_ERROR; + } - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; + for (i = 0; i < num; i++) { + if (ids[i]->status == ID_MAPPED) { + xids[i].type = ids[i]->xid.type; + xids[i].id = ids[i]->xid.id; + } else { + xids[i].type = -1; + } } + + state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); + state->response.extra_data.data = xids; + + } else { + DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); + talloc_free(ids); + return WINBINDD_ERROR; } - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; talloc_free(ids); return WINBINDD_OK; } -- cgit From ebb2d70a607cf33f3d2084d715c2d9d4329f2e7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:42:48 +0200 Subject: Revert "Make use of ADD_TO_ARRAY" This reverts commit 81f334bd6da601a040f754c46705cfa2fd4f8c45. (This used to be commit d4d106776af3f475d46a4dd78794b7b48a3572af) --- source3/winbindd/idmap.c | 94 ++++++++++++++++++++++++++++++--------- source3/winbindd/idmap_util.c | 34 ++++++++------ source3/winbindd/winbindd_idmap.c | 4 +- 3 files changed, 96 insertions(+), 36 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 504be22292..db17245b92 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1177,8 +1177,7 @@ done: return ret; } -static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids, int - num_ids) +static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) { struct id_map ***dom_ids; struct idmap_domain *dom; @@ -1206,7 +1205,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids, int /* partition the requests by domain */ - for (i = 0; i < num_ids; i++) { + for (i = 0; ids[i]; i++) { uint32 idx; if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) { @@ -1246,7 +1245,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids, int /* ok all the backends have been contacted at this point */ /* let's see if we have any unmapped SID left and act accordingly */ - for (i = 0; i < num_ids; i++) { + for (i = 0; ids[i]; i++) { /* NOTE: this will NOT touch ID_EXPIRED entries that the backend * was not able to confirm/deny (offline mode) */ if (ids[i]->status == ID_UNKNOWN || @@ -1279,7 +1278,7 @@ done: idmap interface functions **************************************************************************/ -NTSTATUS idmap_unixids_to_sids(struct id_map **ids, int n_ids) +NTSTATUS idmap_unixids_to_sids(struct id_map **ids) { TALLOC_CTX *ctx; NTSTATUS ret; @@ -1307,7 +1306,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids, int n_ids) bids = NULL; bi = 0; - for (i = 0; i < n_ids; i++) { + for (i = 0; ids[i]; i++) { bool found, mapped, expired; @@ -1332,12 +1331,38 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids, int n_ids) * Need to ask the backend */ - ADD_TO_ARRAY(ctx, struct id_map *, ids[i], &bids, &bn); - if (bids == NULL) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; + if ( ! bids) { + /* alloc space for ids to be resolved by + * backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + bn = 10; } + + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; + + /* check if we need to allocate new space + * on the rids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, + struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + } + + /* make sure the last element is NULL */ + bids[bi] = NULL; } } @@ -1383,12 +1408,12 @@ done: return ret; } -NTSTATUS idmap_sids_to_unixids(struct id_map **ids, int n_ids) +NTSTATUS idmap_sids_to_unixids(struct id_map **ids) { TALLOC_CTX *ctx; NTSTATUS ret; struct id_map **bids; - int i; + int i, bi; int bn = 0; struct winbindd_domain *our_domain = find_our_domain(); @@ -1409,8 +1434,9 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids, int n_ids) /* no ids to be asked to the backends by default */ bids = NULL; + bi = 0; - for (i = 0; i < n_ids; i++) { + for (i = 0; ids[i]; i++) { bool found, mapped, expired; @@ -1435,12 +1461,38 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids, int n_ids) * Need to ask the backends */ - ADD_TO_ARRAY(ctx, struct id_map *, ids[i], &bids, &bn); - if (bids == NULL) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; + if ( ! bids) { + /* alloc space for ids to be resolved + by backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } + bn = 10; + } + + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; + + /* check if we need to allocate new space + * on the ids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, + struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } } + + /* make sure the last element is NULL */ + bids[bi] = NULL; } } @@ -1453,11 +1505,11 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids, int n_ids) goto done; } - ret = idmap_backends_sids_to_unixids(bids, bn); + ret = idmap_backends_sids_to_unixids(bids); IDMAP_CHECK_RET(ret); /* update the cache */ - for (i = 0; i < bn; i++) { + for (i = 0; bids[i]; i++) { if (bids[i]->status == ID_MAPPED) { ret = idmap_cache_set(bids[i]); } else if (bids[i]->status == ID_EXPIRED) { diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 9819fe15f0..78f4d13ec1 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -31,16 +31,18 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps; + struct id_map *maps[2]; DEBUG(10,("uid = [%lu]\n", (unsigned long)uid)); map.sid = sid; map.xid.type = ID_TYPE_UID; map.xid.id = uid; - maps = ↦ - ret = idmap_unixids_to_sids(&maps, 1); + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); return ret; @@ -63,16 +65,18 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps; + struct id_map *maps[2]; DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); map.sid = sid; map.xid.type = ID_TYPE_GID; map.xid.id = gid; - maps = ↦ - ret = idmap_unixids_to_sids(&maps, 1); + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); return ret; @@ -95,15 +99,17 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps; + struct id_map *maps[2]; DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; - map.xid.type = ID_TYPE_UID; - maps = ↦ + map.xid.type = ID_TYPE_UID; - ret = idmap_sids_to_unixids(&maps, 1); + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", sid_string_dbg(sid))); @@ -133,15 +139,17 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps; + struct id_map *maps[2]; DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_GID; - maps = ↦ - ret = idmap_sids_to_unixids(&maps, 1); + maps[0] = ↦ + maps[1] = NULL; + + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", sid_string_dbg(sid))); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 98f8548083..3c7aa2d0c2 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -224,7 +224,7 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, sids = (DOM_SID *)state->request.extra_data.data; num = state->request.extra_len / sizeof(DOM_SID); - ids = TALLOC_ARRAY(state->mem_ctx, struct id_map *, num); + ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); if ( ! ids) { DEBUG(0, ("Out of memory!\n")); return WINBINDD_ERROR; @@ -239,7 +239,7 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, ids[i]->sid = &sids[i]; } - result = idmap_sids_to_unixids(ids, num); + result = idmap_sids_to_unixids(ids); if (NT_STATUS_IS_OK(result)) { -- cgit From b6dcc24987c5c8790502c70687cb0c302333d12c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:42:58 +0200 Subject: Revert "Convert idmap_cache to gencache" This reverts commit 0bf0434f22b0ea46fda3ccc4dd612adbc88dd4f2. (This used to be commit cc536677735ecc318cbd2176ce53b124f44d85a0) --- source3/winbindd/idmap.c | 54 ++--- source3/winbindd/idmap_cache.c | 463 +++++++++++++++++++++++++++++++++-------- source3/winbindd/winbindd.h | 1 - 3 files changed, 393 insertions(+), 125 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index db17245b92..32fc3dc975 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -40,6 +40,8 @@ struct idmap_alloc_backend { struct idmap_alloc_backend *prev, *next; }; +struct idmap_cache_ctx; + struct idmap_alloc_context { const char *params; struct idmap_alloc_methods *methods; @@ -47,6 +49,7 @@ struct idmap_alloc_context { }; static TALLOC_CTX *idmap_ctx = NULL; +static struct idmap_cache_ctx *idmap_cache; static struct idmap_backend *backends = NULL; static struct idmap_domain **idmap_domains = NULL; @@ -243,6 +246,7 @@ NTSTATUS idmap_close(void) /* this talloc_free call will fire the talloc destructors * that will free all active backends resources */ TALLOC_FREE(idmap_ctx); + idmap_cache = NULL; idmap_domains = NULL; backends = NULL; @@ -265,6 +269,10 @@ NTSTATUS idmap_init_cache(void) return NT_STATUS_NO_MEMORY; } + if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { + return NT_STATUS_UNSUCCESSFUL; + } + return NT_STATUS_OK; } @@ -1308,28 +1316,15 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) for (i = 0; ids[i]; i++) { - bool found, mapped, expired; - if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ids[i]->status = ID_UNKNOWN; - - found = idmap_cache_map_id(&ids[i]->xid, ids[i]->sid, - &mapped, &expired); - - if (found) { - ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; - } - - if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + ret = idmap_cache_map_id(idmap_cache, ids[i]); - /* - * Need to ask the backend - */ + if ( ! NT_STATUS_IS_OK(ret)) { if ( ! bids) { /* alloc space for ids to be resolved by @@ -1381,7 +1376,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) /* update the cache */ for (i = 0; i < bi; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(bids[i]); + ret = idmap_cache_set(idmap_cache, bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1396,7 +1391,8 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_id(bids[i]); + ret = idmap_cache_set_negative_id(idmap_cache, + bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1438,28 +1434,15 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) for (i = 0; ids[i]; i++) { - bool found, mapped, expired; - if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array\n")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ids[i]->status = ID_UNKNOWN; - - found = idmap_cache_map_sid(ids[i]->sid, &ids[i]->xid, - &mapped, &expired); - - if (found) { - ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; - } - - if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + ret = idmap_cache_map_sid(idmap_cache, ids[i]); - /* - * Need to ask the backends - */ + if ( ! NT_STATUS_IS_OK(ret)) { if ( ! bids) { /* alloc space for ids to be resolved @@ -1511,7 +1494,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* update the cache */ for (i = 0; bids[i]; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(bids[i]); + ret = idmap_cache_set(idmap_cache, bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1526,7 +1509,8 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_sid(bids[i]); + ret = idmap_cache_set_negative_sid(idmap_cache, + bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1566,7 +1550,7 @@ NTSTATUS idmap_set_mapping(const struct id_map *id) IDMAP_CHECK_RET(ret); /* set the mapping in the cache */ - ret = idmap_cache_set(id); + ret = idmap_cache_set(idmap_cache, id); IDMAP_CHECK_RET(ret); done: diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 191cadb536..8bf797f952 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -1,8 +1,9 @@ -/* +/* Unix SMB/CIFS implementation. ID Mapping Cache - Copyright (C) Volker Lendecke 2008 + based on gencache + Copyright (C) Simo Sorce 2006 Copyright (C) Rafal Szczesniak 2002 @@ -22,6 +23,52 @@ #include "includes.h" #include "winbindd.h" +#define TIMEOUT_LEN 12 +#define IDMAP_CACHE_DATA_FMT "%12u/%s" + +struct idmap_cache_ctx { + TDB_CONTEXT *tdb; +}; + +static int idmap_cache_destructor(struct idmap_cache_ctx *cache) +{ + int ret = 0; + + if (cache && cache->tdb) { + ret = tdb_close(cache->tdb); + cache->tdb = NULL; + } + + return ret; +} + +struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) +{ + struct idmap_cache_ctx *cache; + char* cache_fname = NULL; + + cache = talloc(memctx, struct idmap_cache_ctx); + if ( ! cache) { + DEBUG(0, ("Out of memory!\n")); + return NULL; + } + + cache_fname = lock_path("idmap_cache.tdb"); + + DEBUG(10, ("Opening cache file at %s\n", cache_fname)); + + cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + + if (!cache->tdb) { + DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname)); + return NULL; + } + + talloc_set_destructor(cache, idmap_cache_destructor); + + return cache; +} + static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) { fstring sidstr; @@ -30,19 +77,21 @@ static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) sid_to_fstring(sidstr, sid)); } -static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct unixid *xid) +static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct id_map *id) { return talloc_asprintf(ctx, "IDMAP/%s/%lu", - (xid->type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)xid->id); + (id->xid.type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)id->xid.id); } -NTSTATUS idmap_cache_set(const struct id_map *id) +NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret; time_t timeout = time(NULL) + lp_idmap_cache_time(); + TDB_DATA databuf; char *sidkey; char *idkey; + char *valstr; /* Don't cache lookups in the S-1-22-{1,2} domain */ @@ -51,179 +100,415 @@ NTSTATUS idmap_cache_set(const struct id_map *id) return NT_STATUS_OK; } - sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } /* use sidkey as the local memory ctx */ - idkey = idmap_cache_idkey(sidkey, &id->xid); + idkey = idmap_cache_idkey(sidkey, id); if (idkey == NULL) { ret = NT_STATUS_NO_MEMORY; goto done; } - if (!gencache_set(idkey, sidkey, timeout) - || !gencache_set(sidkey, idkey, timeout)) { + /* save SID -> ID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr , ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* save ID -> SID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } ret = NT_STATUS_OK; done: - TALLOC_FREE(sidkey); + talloc_free(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_sid(const struct id_map *id) +NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; char *sidkey; + char *valstr; - sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } - if (!gencache_set(sidkey, "IDMAP/NEGATIVE", - time(NULL) + lp_idmap_negative_cache_time())) { + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } done: - TALLOC_FREE(sidkey); + talloc_free(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_id(const struct id_map *id) +NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; char *idkey; + char *valstr; - idkey = idmap_cache_idkey(talloc_tos(), &id->xid); + idkey = idmap_cache_idkey(cache, id); if (idkey == NULL) { return NT_STATUS_NO_MEMORY; } - if (!gencache_set(idkey, "IDMAP/NEGATIVE", - time(NULL) + lp_idmap_negative_cache_time())) { + /* use idkey as the local memory ctx */ + valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } done: - TALLOC_FREE(idkey); + talloc_free(idkey); return ret; } -/* - * search the cache for the SID an return a mapping if found +static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) +{ + char *rem; + + /* see if it is a sid */ + if ( ! strncmp("IDMAP/SID/", value, 10)) { + + if ( ! string_to_sid(id->sid, &value[10])) { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + } + + /* not a SID see if it is an UID or a GID */ + if ( ! strncmp("IDMAP/UID/", value, 10)) { + + /* a uid */ + id->xid.type = ID_TYPE_UID; + + } else if ( ! strncmp("IDMAP/GID/", value, 10)) { + + /* a gid */ + id->xid.type = ID_TYPE_GID; + + } else { + + /* a completely bogus value bail out */ + goto failed; + } + + id->xid.id = strtol(&value[10], &rem, 0); + if (*rem != '\0') { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + +failed: + DEBUG(1, ("invalid value: %s\n", value)); + id->status = ID_UNKNOWN; + return NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +/* search the cache for the SID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. */ -bool idmap_cache_map_sid(const struct dom_sid *sid, struct unixid *xid, - bool *mapped, bool *expired) +NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) { - bool ret = false; - time_t timeout; + NTSTATUS ret = NT_STATUS_OK; + TDB_DATA databuf; + time_t t; char *sidkey; - char *value; - char *rem; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); + + /* make sure it is marked as not mapped by default */ + id->status = ID_UNKNOWN; - sidkey = idmap_cache_sidkey(talloc_tos(), sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { - DEBUG(0, ("idmap_cache_sidkey failed\n")); - return false; + return NT_STATUS_NO_MEMORY; } - if (!gencache_get(sidkey, &value, &timeout)) { - TALLOC_FREE(sidkey); - return false; + databuf = tdb_fetch_bystring(cache->tdb, sidkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - if (strcmp(value, "IDMAP/NEGATIVE") == 0) { - *mapped = false; + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - else if (strncmp(value, "IDMAP/UID/", 10) == 0) { - *mapped = true; - xid->type = ID_TYPE_UID; - xid->id = strtol(&value[10], &rem, 10); - if (*rem != '\0') { - goto fail; + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", sidkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - } - else if (strncmp(value, "IDMAP/GID/", 10) == 0) { - *mapped = true; - xid->type = ID_TYPE_GID; - xid->id = strtol(&value[10], &rem, 10); - if (*rem != '\0') { - goto fail; + + /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; } + + goto done; } - else { - goto fail; - } - *expired = (timeout <= time(NULL)); + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } - ret = true; - fail: - if (!ret) { - DEBUG(1, ("Invalid entry %s in cache\n", value)); + /* Check for valid or expired cache hits */ + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped as it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; } - SAFE_FREE(value); - TALLOC_FREE(sidkey); + +done: + SAFE_FREE(databuf.dptr); + talloc_free(sidkey); return ret; } -/* - * search the cache for the ID an return a mapping if found +/* search the cache for the ID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. */ -bool idmap_cache_map_id(const struct unixid *xid, struct dom_sid *psid, - bool *mapped, bool *expired) +NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) { - bool ret = false; - time_t timeout; + NTSTATUS ret; + TDB_DATA databuf; + time_t t; char *idkey; - char *value; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); - idkey = idmap_cache_idkey(talloc_tos(), xid); + /* make sure it is marked as unknown by default */ + id->status = ID_UNKNOWN; + + idkey = idmap_cache_idkey(cache, id); if (idkey == NULL) { - return false; + return NT_STATUS_NO_MEMORY; } - if (!gencache_get(idkey, &value, &timeout)) { - TALLOC_FREE(idkey); - return false; + databuf = tdb_fetch_bystring(cache->tdb, idkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - if (strcmp(value, "IDMAP/NEGATIVE") == 0) { - *mapped = false; + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - else if (strncmp(value, "IDMAP/SID/", 10) == 0) { - *mapped = true; - if (!string_to_sid(psid, value+10)) { - goto fail; + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", idkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } + + /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + goto done; } - else { - goto fail; + + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - ret = true; + /* Process the negative cache hit */ - fail: - if (!ret) { - DEBUG(1, ("Invalid entry %s in cache\n", value)); + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped is it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; } - SAFE_FREE(value); - TALLOC_FREE(idkey); + +done: + SAFE_FREE(databuf.dptr); + talloc_free(idkey); return ret; } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 8a35fd9e37..b2fe8b67e7 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -379,5 +379,4 @@ enum ent_type { #define IS_DOMAIN_OFFLINE(x) ( lp_winbind_offline_logon() && \ ( get_global_winbindd_state_offline() \ || !(x)->online ) ) -#define IS_DOMAIN_ONLINE(x) (!(IS_DOMAIN_OFFLINE(x))) #endif /* _WINBINDD_H */ -- cgit From 50a84acc40cf83accdcdb03bc34836dddb4e0c1a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:43:17 +0200 Subject: Revert "IDMAP_READ_CACHE_DATA_FMT_TEMPLATE is unused, remove it" This reverts commit 2396d5d5d2f453f097f8ce77b640ad7e1d7e7c4c. (This used to be commit 447d77949f99fdc5fc2bea6ddc27176d3a0871a9) --- source3/winbindd/idmap_cache.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 8bf797f952..eaff30c4e1 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -25,6 +25,7 @@ #define TIMEOUT_LEN 12 #define IDMAP_CACHE_DATA_FMT "%12u/%s" +#define IDMAP_READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" struct idmap_cache_ctx { TDB_CONTEXT *tdb; -- cgit From ebb9437f4f1bc91da53919ddc6f4c33ecac09b8e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:43:25 +0200 Subject: Revert "Simplify idmap_cache_set() a bit" This reverts commit 55b976ba93462c6885e8d89edd13c32fb5529944. (This used to be commit 23edc4ec0ab1de60a864de01c0ff90ea1378231d) --- source3/winbindd/idmap_cache.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index eaff30c4e1..0b3c22eb20 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -95,9 +95,14 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) char *valstr; /* Don't cache lookups in the S-1-22-{1,2} domain */ - - if (sid_check_is_in_unix_users(id->sid) - || sid_check_is_in_unix_groups(id->sid)) { + if ( (id->xid.type == ID_TYPE_UID) && + sid_check_is_in_unix_users(id->sid) ) + { + return NT_STATUS_OK; + } + if ( (id->xid.type == ID_TYPE_GID) && + sid_check_is_in_unix_groups(id->sid) ) + { return NT_STATUS_OK; } -- cgit From d1edba537fb262b019414c326f2823e5406072f6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:43:42 +0200 Subject: Revert "Simplify idmap_cache_build_[s]idkey a bit" This reverts commit 80932c0266ef73b8d0462c078a053444fff47f32. (This used to be commit 847609a148b653b9e3a24b2bc9e1636c6ef0db84) --- source3/winbindd/idmap_cache.c | 69 ++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 33 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 0b3c22eb20..b724ba0c59 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -70,19 +70,33 @@ struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) return cache; } -static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) +static NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, + const struct id_map *id) { fstring sidstr; - return talloc_asprintf(ctx, "IDMAP/SID/%s", - sid_to_fstring(sidstr, sid)); + *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", + sid_to_fstring(sidstr, id->sid)); + if ( ! *sidkey) { + DEBUG(1, ("failed to build sidkey, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; } -static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct id_map *id) +static NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, + const struct id_map *id) { - return talloc_asprintf(ctx, "IDMAP/%s/%lu", - (id->xid.type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)id->xid.id); + *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu", + (id->xid.type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)id->xid.id); + if ( ! *idkey) { + DEBUG(1, ("failed to build idkey, OOM?\n")); + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; } NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) @@ -106,15 +120,12 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) return NT_STATUS_OK; } - sidkey = idmap_cache_sidkey(cache, id->sid); - if (sidkey == NULL) { - return NT_STATUS_NO_MEMORY; - } + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; /* use sidkey as the local memory ctx */ - idkey = idmap_cache_idkey(sidkey, id); - if (idkey == NULL) { - ret = NT_STATUS_NO_MEMORY; + ret = idmap_cache_build_idkey(sidkey, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) { goto done; } @@ -171,16 +182,14 @@ done: NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) { - NTSTATUS ret = NT_STATUS_OK; + NTSTATUS ret; time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); TDB_DATA databuf; char *sidkey; char *valstr; - sidkey = idmap_cache_sidkey(cache, id->sid); - if (sidkey == NULL) { - return NT_STATUS_NO_MEMORY; - } + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; /* use sidkey as the local memory ctx */ valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); @@ -209,16 +218,14 @@ done: NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) { - NTSTATUS ret = NT_STATUS_OK; + NTSTATUS ret; time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); TDB_DATA databuf; char *idkey; char *valstr; - idkey = idmap_cache_idkey(cache, id); - if (idkey == NULL) { - return NT_STATUS_NO_MEMORY; - } + ret = idmap_cache_build_idkey(cache, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; /* use idkey as the local memory ctx */ valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); @@ -310,7 +317,7 @@ failed: NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) { - NTSTATUS ret = NT_STATUS_OK; + NTSTATUS ret; TDB_DATA databuf; time_t t; char *sidkey; @@ -321,10 +328,8 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as not mapped by default */ id->status = ID_UNKNOWN; - sidkey = idmap_cache_sidkey(cache, id->sid); - if (sidkey == NULL) { - return NT_STATUS_NO_MEMORY; - } + ret = idmap_cache_build_sidkey(cache, &sidkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; databuf = tdb_fetch_bystring(cache->tdb, sidkey); @@ -433,10 +438,8 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as unknown by default */ id->status = ID_UNKNOWN; - idkey = idmap_cache_idkey(cache, id); - if (idkey == NULL) { - return NT_STATUS_NO_MEMORY; - } + ret = idmap_cache_build_idkey(cache, &idkey, id); + if (!NT_STATUS_IS_OK(ret)) return ret; databuf = tdb_fetch_bystring(cache->tdb, idkey); -- cgit From f70c8ecde2a1041adf4a8ef1cc2a70f823997e38 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:44:35 +0200 Subject: Revert "Fix indentation" This reverts commit c4e6de9e34e1ff76552ce6d4e72b343fb5f33306. (This used to be commit fa9b128e93cca45b9516917f73f586197e7637f3) --- source3/winbindd/idmap_ad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 1a41f4f6ff..ca1cf81ca9 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -347,7 +347,7 @@ again: if ( u_filter) { filter = talloc_asprintf_append_buffer(filter, "%s))", u_filter); CHECK_ALLOC_DONE(filter); - TALLOC_FREE(u_filter); + TALLOC_FREE(u_filter); } if ( g_filter) { filter = talloc_asprintf_append_buffer(filter, "%s))", g_filter); -- cgit From 0948a5cda8756cca1edbe0f430175b31111d2497 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:03 +0200 Subject: Revert "Fix typo" This reverts commit fe79c8a5b726754703626ca0bff57074274c98c7. (This used to be commit 62835f8d7e824a5d469ec5f79e4db739e6602f4f) --- source3/winbindd/idmap_ad.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index ca1cf81ca9..b99da57a4a 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -98,8 +98,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) return NULL; } - /* the machine acct password might have changed - fetch it every - * time */ + /* the machine acct password might have change - fetch it every time */ SAFE_FREE(ads->auth.password); ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); -- cgit From f7ee7d2fe96658aa102e94a7606ca8c1c52cae25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:09 +0200 Subject: Revert "Tiny logic simplification: Remove an unnecessary else branch" This reverts commit 6009ae329375b1c40e3d00df977ddccc8b5cc176. (This used to be commit b71ce00796efdd27b593bbbc36f5cbba23fe9240) --- source3/winbindd/idmap_ad.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index b99da57a4a..2e79413ffc 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -77,15 +77,15 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) if ( ads->config.realm && (expire > time(NULL))) { return ads; + } else { + /* we own this ADS_STRUCT so make sure it goes away */ + DEBUG(7,("Deleting expired krb5 credential cache\n")); + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy(WINBIND_CCACHE_NAME); + ad_idmap_ads = NULL; + TALLOC_FREE( ad_schema ); } - - /* we own this ADS_STRUCT so make sure it goes away */ - DEBUG(7,("Deleting expired krb5 credential cache\n")); - ads->is_mine = True; - ads_destroy( &ads ); - ads_kdestroy(WINBIND_CCACHE_NAME); - ad_idmap_ads = NULL; - TALLOC_FREE( ad_schema ); } if (!local) { -- cgit From 0439d4ba61e1d9380e160a16f3c301fdb0354523 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:16 +0200 Subject: Revert "Fix nonempty whitespace only lines" This reverts commit cc77db2acbc35cea58576f1e28c7a760a5e31609. (This used to be commit ed5b516c2027d78011cdaa7cbbc01bb01e766381) --- source3/winbindd/idmap_ad.c | 34 +++++++++++++++++----------------- source3/winbindd/idmap_nss.c | 8 ++++---- source3/winbindd/idmap_passdb.c | 8 ++++---- source3/winbindd/idmap_tdb.c | 6 +++--- source3/winbindd/idmap_tdb2.c | 28 ++++++++++++++-------------- source3/winbindd/idmap_util.c | 12 ++++++------ source3/winbindd/nss_info.c | 33 +++++++++++++++++---------------- source3/winbindd/nss_info_template.c | 10 +++++----- 8 files changed, 70 insertions(+), 69 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 2e79413ffc..0d7c068844 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -108,7 +108,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) /* setup server affinity */ get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip ); - + status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(1, ("ad_idmap_init: failed to connect to AD\n")); @@ -129,7 +129,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void) static ADS_STRUCT *ad_idmap_cached_connection(void) { ADS_STRUCT *ads = ad_idmap_cached_connection_internal(); - + if ( !ads ) return NULL; @@ -146,14 +146,14 @@ static ADS_STRUCT *ad_idmap_cached_connection(void) (ad_map_type == WB_POSIX_MAP_RFC2307) ) { ADS_STATUS schema_status; - + schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema); if ( !ADS_ERR_OK(schema_status) ) { DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n")); return NULL; } } - + return ads; } @@ -320,7 +320,7 @@ again: (unsigned long)ids[idx]->xid.id); CHECK_ALLOC_DONE(u_filter); break; - + case ID_TYPE_GID: if ( ! g_filter) { g_filter = talloc_asprintf(memctx, "(&(|" @@ -527,7 +527,7 @@ again: ")(|", ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP); - + CHECK_ALLOC_DONE(filter); bidx = idx; @@ -535,7 +535,7 @@ again: sidstr = sid_binstring(ids[idx]->sid); filter = talloc_asprintf_append_buffer(filter, "(objectSid=%s)", sidstr); - + free(sidstr); CHECK_ALLOC_DONE(filter); } @@ -668,7 +668,7 @@ static NTSTATUS idmap_ad_close(struct idmap_domain *dom) } TALLOC_FREE( ad_schema ); - + return NT_STATUS_OK; } @@ -692,7 +692,7 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_SFU; return NT_STATUS_OK; @@ -710,7 +710,7 @@ static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_SFU20; return NT_STATUS_OK; @@ -720,7 +720,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) { /* Sanity check if we have previously been called with a different schema model */ - + if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) && (ad_map_type != WB_POSIX_MAP_RFC2307) ) { @@ -728,7 +728,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) "Mixed schema models not supported!\n")); return NT_STATUS_NOT_SUPPORTED; } - + ad_map_type = WB_POSIX_MAP_RFC2307; return NT_STATUS_OK; @@ -761,19 +761,19 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, if ( !ads_internal || !ad_schema ) return NT_STATUS_OBJECT_NAME_NOT_FOUND; - + if ( !homedir || !shell || !gecos ) return NT_STATUS_INVALID_PARAMETER; *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr ); *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr ); *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr ); - + if ( gid ) { if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) ) *gid = (uint32)-1; } - + return NT_STATUS_OK; } @@ -800,7 +800,7 @@ static struct idmap_methods ad_methods = { /* The SFU and RFC2307 NSS plugins share everything but the init function which sets the intended schema model to use */ - + static struct nss_info_methods nss_rfc2307_methods = { .init = nss_rfc2307_init, .get_nss_info = nss_ad_get_info, @@ -841,7 +841,7 @@ NTSTATUS idmap_ad_init(void) if ( !NT_STATUS_IS_OK(status_idmap_ad) ) return status_idmap_ad; } - + if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) { status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, "rfc2307", &nss_rfc2307_methods ); diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index c4115b1ee3..e4acd9ce65 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -4,17 +4,17 @@ idmap PASSDB backend Copyright (C) Simo Sorce 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -60,7 +60,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma const char *name; enum lsa_SidType type; bool ret; - + switch (ids[i]->xid.type) { case ID_TYPE_UID: pw = getpwuid((uid_t)ids[i]->xid.id); diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c index 6fbb47b979..17afd71ab8 100644 --- a/source3/winbindd/idmap_passdb.c +++ b/source3/winbindd/idmap_passdb.c @@ -4,17 +4,17 @@ idmap PASSDB backend Copyright (C) Simo Sorce 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -85,7 +85,7 @@ static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma for (i = 0; ids[i]; i++) { enum lsa_SidType type; union unid_t id; - + if (pdb_sid_to_id(ids[i]->sid, &id, &type)) { switch (type) { case SID_NAME_USER: diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 26dc2fdac7..e5f605361b 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -7,17 +7,17 @@ Copyright (C) Jim McDonough 2003 Copyright (C) Jeremy Allison 2006 Copyright (C) Simo Sorce 2003-2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index b8049d00e5..ab89e615f7 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -15,17 +15,17 @@ Copyright (C) Jim McDonough 2003 Copyright (C) Jeremy Allison 2006 Copyright (C) Simo Sorce 2003-2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -88,7 +88,7 @@ static NTSTATUS idmap_tdb2_alloc_load(void); static NTSTATUS idmap_tdb2_open_perm_db(void) { char *db_path; - + if (idmap_tdb2_perm) { /* its already open */ return NT_STATUS_OK; @@ -281,7 +281,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) hwmtype, (unsigned long)high_hwm)); return NT_STATUS_UNSUCCESSFUL; } - + xid->id = hwm; DEBUG(10,("New %s = %d\n", hwmtype, hwm)); @@ -384,7 +384,7 @@ static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr) } return ret; } - + status = idmap_tdb2_open_perm_db(); if (!NT_STATUS_IS_OK(status)) { return ret; @@ -570,7 +570,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m case ID_TYPE_UID: keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); break; - + case ID_TYPE_GID: keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); break; @@ -621,7 +621,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m } goto done; } - + if (!string_to_sid(map->sid, (const char *)data.dptr)) { DEBUG(10,("INVALID SID (%s) in record %s\n", (const char *)data.dptr, keystr)); @@ -667,7 +667,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m ret = NT_STATUS_NONE_MAPPED; goto done; } - + ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr); /* store it on shared storage */ if (!NT_STATUS_IS_OK(ret)) { @@ -702,7 +702,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr)); ret = NT_STATUS_INTERNAL_DB_ERROR; } - + /* apply filters before returning result */ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) { @@ -746,7 +746,7 @@ static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_m ids[i]->status = ID_UNMAPPED; continue; } - + /* some fatal error occurred, return immediately */ goto done; } @@ -791,7 +791,7 @@ static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_m ids[i]->status = ID_UNMAPPED; continue; } - + /* some fatal error occurred, return immediately */ goto done; } @@ -835,7 +835,7 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id data.dptr = NULL; /* TODO: should we filter a set_mapping using low/high filters ? */ - + ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); switch (map->xid.type) { @@ -843,7 +843,7 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id case ID_TYPE_UID: kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id); break; - + case ID_TYPE_GID: kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id); break; diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 78f4d13ec1..0d24070dd6 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -41,7 +41,7 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) maps[0] = ↦ maps[1] = NULL; - + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); @@ -75,7 +75,7 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) maps[0] = ↦ maps[1] = NULL; - + ret = idmap_unixids_to_sids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); @@ -105,10 +105,10 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) map.sid = sid; map.xid.type = ID_TYPE_UID; - + maps[0] = ↦ maps[1] = NULL; - + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", @@ -145,10 +145,10 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) map.sid = sid; map.xid.type = ID_TYPE_GID; - + maps[0] = ↦ maps[1] = NULL; - + ret = idmap_sids_to_unixids(maps); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c index af73fe2900..daa3dd037d 100644 --- a/source3/winbindd/nss_info.c +++ b/source3/winbindd/nss_info.c @@ -8,12 +8,12 @@ modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ @@ -89,12 +89,12 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) int len; *backend = *domain = NULL; - + if ( !config ) return False; - + p = strchr( config, ':' ); - + /* if no : then the string must be the backend name only */ if ( !p ) { @@ -107,13 +107,13 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( strlen(p+1) > 0 ) { *domain = SMB_STRDUP( p+1 ); } - + len = PTR_DIFF(p,config)+1; if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) { SAFE_FREE( *backend ); return False; } - + StrnCpy( q, config, len-1); q[len-1] = '\0'; *backend = q; @@ -139,7 +139,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( NT_STATUS_IS_OK(nss_initialized) ) return NT_STATUS_OK; - + /* The "template" backend should alqays be registered as it is a static module */ @@ -166,7 +166,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) if ( !NT_STATUS_IS_OK(status) ) { continue; } - + /* try again */ if ( (nss_backend = nss_get_backend( backend )) == NULL ) { DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n", @@ -184,7 +184,7 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) DEBUG(0,("nss_init: talloc() failure!\n")); return NT_STATUS_NO_MEMORY; } - + nss_domain->backend = nss_backend; nss_domain->domain = talloc_strdup( nss_domain, domain ); @@ -210,9 +210,10 @@ static bool parse_nss_parm( const char *config, char **backend, char **domain ) /* we shouild default to use template here */ } - + + nss_initialized = NT_STATUS_OK; - + return NT_STATUS_OK; } @@ -230,19 +231,19 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) nt_errstr(status))); return NULL; } - + for ( p=nss_domain_list; p; p=p->next ) { if ( strequal( p->domain, domain ) ) break; } - + /* If we didn't find a match, then use the default nss info */ if ( !p ) { if ( !nss_domain_list ) { return NULL; } - + p = nss_domain_list; } @@ -270,7 +271,7 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) domain )); return NT_STATUS_NOT_FOUND; } - + m = p->backend->methods; return m->get_nss_info( p, user_sid, ctx, ads, msg, diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c index 641bfe9eaf..aaf02e4abe 100644 --- a/source3/winbindd/nss_info_template.c +++ b/source3/winbindd/nss_info_template.c @@ -8,12 +8,12 @@ modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ @@ -44,7 +44,7 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, { if ( !homedir || !shell || !gecos ) return NT_STATUS_INVALID_PARAMETER; - + *homedir = talloc_strdup( ctx, lp_template_homedir() ); *shell = talloc_strdup( ctx, lp_template_shell() ); *gecos = NULL; @@ -52,7 +52,7 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, if ( !*homedir || !*shell ) { return NT_STATUS_NO_MEMORY; } - + return NT_STATUS_OK; } @@ -73,7 +73,7 @@ static struct nss_info_methods nss_template_methods = { .get_nss_info = nss_template_get_info, .close_fn = nss_template_close }; - + NTSTATUS nss_info_template_init( void ) { return smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, -- cgit From 979496d5c1186140b6e0aafa5f51713f9110b064 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:23 +0200 Subject: Revert "fix typos" This reverts commit e0957c6f4b1e81c27fda1de7fb7cbc9c585f5ac9. (This used to be commit 0d2fc3c394d300d906cdcd14f1abf8e6f84beff7) --- source3/winbindd/idmap_rid.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c index fe753c9deb..f1cd77853c 100644 --- a/source3/winbindd/idmap_rid.c +++ b/source3/winbindd/idmap_rid.c @@ -171,8 +171,7 @@ static NTSTATUS idmap_rid_unixids_to_sids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initialization may have been deferred because of an error, retry or - * fail */ + /* Initilization my have been deferred because of an error, retry or fail */ if ( ! dom->initialized) { ret = idmap_rid_initialize(dom); if ( ! NT_STATUS_IS_OK(ret)) { @@ -214,8 +213,7 @@ static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initialization may have been deferred because of an error, retry or - * fail */ + /* Initilization my have been deferred because of an error, retry or fail */ if ( ! dom->initialized) { ret = idmap_rid_initialize(dom); if ( ! NT_STATUS_IS_OK(ret)) { -- cgit From be187b787ffa0db5207bf158dd7af55b86f0c253 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:31 +0200 Subject: Revert "Fix nonempty whitespace only lines" This reverts commit 0da9d0d0f9662d8bd2f370f764d5a875e11b3068. (This used to be commit b2f7bd6a05afcbba076f78d0caeaf154854db7de) --- source3/winbindd/idmap_cache.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index b724ba0c59..a3207663e4 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -119,6 +119,7 @@ NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) { return NT_STATUS_OK; } + ret = idmap_cache_build_sidkey(cache, &sidkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -258,11 +259,11 @@ static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) /* see if it is a sid */ if ( ! strncmp("IDMAP/SID/", value, 10)) { - + if ( ! string_to_sid(id->sid, &value[10])) { goto failed; } - + id->status = ID_MAPPED; return NT_STATUS_OK; @@ -270,21 +271,21 @@ static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) /* not a SID see if it is an UID or a GID */ if ( ! strncmp("IDMAP/UID/", value, 10)) { - + /* a uid */ id->xid.type = ID_TYPE_UID; - + } else if ( ! strncmp("IDMAP/GID/", value, 10)) { - + /* a gid */ id->xid.type = ID_TYPE_GID; - + } else { - + /* a completely bogus value bail out */ goto failed; } - + id->xid.id = strtol(&value[10], &rem, 0); if (*rem != '\0') { goto failed; @@ -327,7 +328,7 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as not mapped by default */ id->status = ID_UNKNOWN; - + ret = idmap_cache_build_sidkey(cache, &sidkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -375,7 +376,7 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); goto done; } - + /* We're expired, set an error code for upper layer */ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; @@ -437,7 +438,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* make sure it is marked as unknown by default */ id->status = ID_UNKNOWN; - + ret = idmap_cache_build_idkey(cache, &idkey, id); if (!NT_STATUS_IS_OK(ret)) return ret; @@ -462,7 +463,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* check it is not negative */ if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " "timeout = %s", t > now ? "valid" : "expired", idkey, endptr+1, ctime(&t))); @@ -493,7 +494,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) goto done; } - + /* Was a negative cache hit */ /* Ignore the negative cache when offline */ @@ -501,6 +502,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) if ( IS_DOMAIN_OFFLINE(our_domain) ) { DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); ret = NT_STATUS_NONE_MAPPED; + goto done; } -- cgit From a25278a522414ef265871ed1108db72ac31e4550 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:40 +0200 Subject: Revert "Fix indentation" This reverts commit 954556b527aa652f9a46f0d48834e92befb3c5f9. (This used to be commit 1b1124bcb9043deb495897467e4cd3ae8a07784b) --- source3/winbindd/idmap_cache.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index a3207663e4..ebfae7dc26 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -396,15 +396,15 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* Check for valid or expired cache hits */ - if (t <= now) { + if (t <= now) { /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped as it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } - + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped as it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } + done: SAFE_FREE(databuf.dptr); talloc_free(sidkey); @@ -508,14 +508,14 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* Process the negative cache hit */ - if (t <= now) { + if (t <= now) { /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { + ret = NT_STATUS_NONE_MAPPED; + } else { /* this is not mapped is it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; + } done: SAFE_FREE(databuf.dptr); -- cgit From b76fb9ac739afb2007adfb652c5d8c14a07e0991 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:46 +0200 Subject: Revert "Fix a debug msg, this was probably a leftover from gencache" This reverts commit daa171552dc00d9602a05ba199c9a3ff24c802f5. (This used to be commit b826420c3adfd24a01080d25f8a61d33d05722c8) --- source3/winbindd/idmap_cache.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index ebfae7dc26..b427db51b0 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -343,8 +343,7 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) t = strtol((const char *)databuf.dptr, &endptr, 10); if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid idmap cache data format: %s\n", - (const char *)databuf.dptr)); + DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); /* remove the entry */ tdb_delete_bystring(cache->tdb, sidkey); ret = NT_STATUS_NONE_MAPPED; @@ -453,8 +452,7 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) t = strtol((const char *)databuf.dptr, &endptr, 10); if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid idmap cache data format: %s\n", - (const char *)databuf.dptr)); + DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); /* remove the entry */ tdb_delete_bystring(cache->tdb, idkey); ret = NT_STATUS_NONE_MAPPED; -- cgit From 025689ad18a03a531b559759598d4f310c73d18d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:45:54 +0200 Subject: Revert "Fix typo" This reverts commit fe58926283b51910d8587e32bb11aa681b9a27d3. (This used to be commit fe216bff1d7d805403cbfb3eaf381c2a57a254d7) --- source3/winbindd/idmap_cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index b427db51b0..f7e1d4e6d1 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -301,7 +301,7 @@ failed: return NT_STATUS_INTERNAL_DB_CORRUPTION; } -/* search the cache for the SID an return a mapping if found * +/* search the cahce for the SID an return a mapping if found * * * 4 cases are possible * @@ -410,7 +410,7 @@ done: return ret; } -/* search the cache for the ID an return a mapping if found * +/* search the cahce for the ID an return a mapping if found * * * 4 cases are possible * -- cgit From 622d36aa41683e122892cd6674279bf52f496e9d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:46:00 +0200 Subject: Revert "Make idmap_init() static" This reverts commit c8d1bbfddce41cd6bf37dd0a622ef3437a24b492. (This used to be commit 5cded3da00c0af40a98d86011507553f97fe6a22) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 32fc3dc975..c056596470 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -279,7 +279,7 @@ NTSTATUS idmap_init_cache(void) /**************************************************************************** ****************************************************************************/ -static NTSTATUS idmap_init(void) +NTSTATUS idmap_init(void) { NTSTATUS ret; static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; -- cgit From 343c7ff3d2f2125a873692c635f1fddedaecf242 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 17:46:09 +0200 Subject: Revert "Fix two memory leaks in an error path in idmap.c" This reverts commit 7cec389e19323e99b6b6258e539be9d1fd65810f. (This used to be commit d0b34cbb4eba2b6543402af2c9f95407546cefad) --- source3/winbindd/idmap.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index c056596470..8b16f27f7d 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -154,7 +154,6 @@ NTSTATUS smb_register_idmap(int version, const char *name, entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); - TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->methods = methods; @@ -208,7 +207,6 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); - TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->methods = methods; -- cgit From 02e592486fc3130ebd365fe337d8597ebf9071ad Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Jul 2008 21:13:05 -0400 Subject: Make again idmap_init static (This used to be commit e113b7c13f2457676fdec9e52f09046286e25b60) --- source3/winbindd/idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 8b16f27f7d..b793c47969 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -277,7 +277,7 @@ NTSTATUS idmap_init_cache(void) /**************************************************************************** ****************************************************************************/ -NTSTATUS idmap_init(void) +static NTSTATUS idmap_init(void) { NTSTATUS ret; static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; -- cgit From eda1a267e1a70506107100a853884c49978acc01 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Jul 2008 21:13:44 -0400 Subject: Add back mem leak fixes (This used to be commit 2adea093c5709e128bdde1e37c6a897db7cbc3b1) --- source3/winbindd/idmap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index b793c47969..1f28c50930 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -149,11 +149,13 @@ NTSTATUS smb_register_idmap(int version, const char *name, entry = talloc(idmap_ctx, struct idmap_backend); if ( ! entry) { DEBUG(0,("Out of memory!\n")); + TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); + TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } entry->methods = methods; -- cgit From 8812606c43baa796f6164484fb7cac3d9b0dc9c8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Jul 2008 21:23:16 -0400 Subject: Remove one nested level by reversing if condition (This used to be commit 657a2f20dd4d422d45d7e054f463641cdff16816) --- source3/winbindd/idmap.c | 112 +++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 58 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 1f28c50930..7a9462b7fd 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1324,41 +1324,39 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) ret = idmap_cache_map_id(idmap_cache, ids[i]); - if ( ! NT_STATUS_IS_OK(ret)) { + if (NT_STATUS_IS_OK(ret)) continue; + if ( ! bids) { + /* alloc space for ids to be resolved by + * backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); if ( ! bids) { - /* alloc space for ids to be resolved by - * backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; } + bn = 10; + } - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the rids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, - struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - } + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; - /* make sure the last element is NULL */ - bids[bi] = NULL; + /* check if we need to allocate new space + * on the rids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } } + + /* make sure the last element is NULL */ + bids[bi] = NULL; } /* let's see if there is any id mapping to be retrieved @@ -1442,41 +1440,39 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) ret = idmap_cache_map_sid(idmap_cache, ids[i]); - if ( ! NT_STATUS_IS_OK(ret)) { + if (NT_STATUS_IS_OK(ret)) continue; + if ( ! bids) { + /* alloc space for ids to be resolved + by backends (realloc ten by ten) */ + bids = TALLOC_ARRAY(ctx, struct id_map *, 10); if ( ! bids) { - /* alloc space for ids to be resolved - by backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; } + bn = 10; + } - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the ids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, - struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - } + /* add this id to the ones to be retrieved + * from the backends */ + bids[bi] = ids[i]; + bi++; - /* make sure the last element is NULL */ - bids[bi] = NULL; + /* check if we need to allocate new space + * on the ids array */ + if (bi == bn) { + bn += 10; + bids = talloc_realloc(ctx, bids, struct id_map *, bn); + if ( ! bids) { + DEBUG(1, ("Out of memory!\n")); + talloc_free(ctx); + return NT_STATUS_NO_MEMORY; + } } + + /* make sure the last element is NULL */ + bids[bi] = NULL; } /* let's see if there is any id mapping to be retrieved -- cgit From 9669411d1ea30ca6d2c2bc6bfa4bca8231901b58 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Jul 2008 21:28:18 -0400 Subject: Fix regression introduced with 4086ef15b395f1a536fb669af2103a33ecc14de4 We must not return an error here just because we are offline. We must instead fix the mappings to the best of our knowledge (ie mark as mapped, expired ones, and as unmapped, unknown ones) (This used to be commit 4436272dd4d6cdd223b1dc3d217a97cbe3bc887b) --- source3/winbindd/idmap.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 7a9462b7fd..95ff923d0f 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1361,16 +1361,16 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) /* let's see if there is any id mapping to be retrieved * from the backends */ - if (bi) { + if (bids) { + bool online; + /* Only do query if we are online */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - ret = NT_STATUS_FILE_IS_OFFLINE; - goto done; + online = !IS_DOMAIN_OFFLINE(our_domain); + if (online) { + ret = idmap_backends_unixids_to_sids(bids); + IDMAP_CHECK_RET(ret); } - ret = idmap_backends_unixids_to_sids(bids); - IDMAP_CHECK_RET(ret); - /* update the cache */ for (i = 0; i < bi; i++) { if (bids[i]->status == ID_MAPPED) { @@ -1388,7 +1388,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) * unmapped and hope next time things will * settle down. */ bids[i]->status = ID_UNMAPPED; - } else { /* unmapped */ + } else if (online) { /* unmapped */ ret = idmap_cache_set_negative_id(idmap_cache, bids[i]); } @@ -1478,15 +1478,15 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* let's see if there is any id mapping to be retrieved * from the backends */ if (bids) { + bool online; + /* Only do query if we are online */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - ret = NT_STATUS_FILE_IS_OFFLINE; - goto done; + online = !IS_DOMAIN_OFFLINE(our_domain); + if (online) { + ret = idmap_backends_sids_to_unixids(bids); + IDMAP_CHECK_RET(ret); } - ret = idmap_backends_sids_to_unixids(bids); - IDMAP_CHECK_RET(ret); - /* update the cache */ for (i = 0; bids[i]; i++) { if (bids[i]->status == ID_MAPPED) { @@ -1504,7 +1504,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) * unmapped and hope next time things will * settle down. */ bids[i]->status = ID_UNMAPPED; - } else { /* unmapped */ + } else if (online) { /* unmapped */ ret = idmap_cache_set_negative_sid(idmap_cache, bids[i]); } -- cgit From 1484b7f3b540a9a9ec77199cea034f6368f6d2ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Jul 2008 20:10:18 -0700 Subject: From Jim McDonough In reloading the smb.conf, if a "log file" is specified in smb.conf, winbind children will overwrite the logfile name to be the same as the parent. Jeremy. (This used to be commit 62d319cc1a2ef891866b2ddbd22f3ed0944356af) --- source3/winbindd/winbindd.c | 18 ++++++++++++------ source3/winbindd/winbindd_dual.c | 3 ++- source3/winbindd/winbindd_proto.h | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 4b7efe81eb..55ab58f7eb 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -59,7 +59,7 @@ struct messaging_context *winbind_messaging_context(void) /* Reload configuration */ -static bool reload_services_file(void) +static bool reload_services_file(const char *logfile) { bool ret; @@ -71,6 +71,12 @@ static bool reload_services_file(void) } } + /* if this is a child, restore the logfile to the special + name - , idmap, etc. */ + if (logfile && *logfile) { + lp_set_logfile(logfile); + } + reopen_logs(); ret = lp_load(get_dyn_CONFIGFILE(),False,False,True,True); @@ -208,7 +214,7 @@ static void msg_reload_services(struct messaging_context *msg, { /* Flush various caches */ flush_caches(); - reload_services_file(); + reload_services_file((const char *) private_data); } /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ @@ -804,14 +810,14 @@ static bool remove_idle_client(void) } /* check if HUP has been received and reload files */ -void winbind_check_sighup(void) +void winbind_check_sighup(const char *logfile) { if (do_sighup) { DEBUG(3, ("got SIGHUP\n")); flush_caches(); - reload_services_file(); + reload_services_file(logfile); do_sighup = False; } @@ -984,7 +990,7 @@ static void process_loop(void) /* Check signal handling things */ winbind_check_sigterm(true); - winbind_check_sighup(); + winbind_check_sighup(NULL); if (do_sigusr2) { print_winbindd_status(); @@ -1136,7 +1142,7 @@ int main(int argc, char **argv, char **envp) db_tdb2_setup_messaging(winbind_messaging_context(), true); - if (!reload_services_file()) { + if (!reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index c3bcb715bb..57ab627a5b 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1148,7 +1148,8 @@ static bool fork_domain_child(struct winbindd_child *child) /* check for signals */ winbind_check_sigterm(false); - winbind_check_sighup(); + winbind_check_sighup(override_logfile ? NULL : + child->logfilename); run_events(winbind_event_context(), 0, NULL, NULL); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 7f68cbfbc2..9fafd57cea 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -66,7 +66,7 @@ void setup_async_write(struct fd_event *event, void *data, size_t length, void request_error(struct winbindd_cli_state *state); void request_ok(struct winbindd_cli_state *state); void request_finished_cont(void *private_data, bool success); -void winbind_check_sighup(void); +void winbind_check_sighup(const char *logfile); void winbind_check_sigterm(bool in_parent); int main(int argc, char **argv, char **envp); -- cgit From 1335da2a7cc639310e5d389e8e8dbe67c4e7ca25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_noauth Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit 9abc9dc4dc13bd3e42f98eff64eacf24b51f5779) --- source3/winbindd/winbindd_cm.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 51ef14b708..b7e2f086fc 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1712,10 +1712,11 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); - cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP, - &result); + result = cli_rpc_pipe_open_noauth(domain->conn.cli, + &ndr_table_dssetup.syntax_id, + &cli); - if (cli == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " "PI_DSSETUP on domain %s: (%s)\n", domain->name, nt_errstr(result))); @@ -1759,9 +1760,10 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) } no_dssetup: - cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); + result = cli_rpc_pipe_open_noauth(domain->conn.cli, + &ndr_table_lsarpc.syntax_id, &cli); - if (cli == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " "PI_LSARPC on domain %s: (%s)\n", domain->name, nt_errstr(result))); @@ -2031,11 +2033,10 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: /* Finally fall back to anonymous. */ - conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, - &result); + result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id, + &conn->samr_pipe); - if (conn->samr_pipe == NULL) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; + if (!NT_STATUS_IS_OK(result)) { goto done; } @@ -2167,9 +2168,10 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: - conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC, - &result); - if (conn->lsa_pipe == NULL) { + result = cli_rpc_pipe_open_noauth(conn->cli, + &ndr_table_lsarpc.syntax_id, + &conn->lsa_pipe); + if (!NT_STATUS_IS_OK(result)) { result = NT_STATUS_PIPE_NOT_AVAILABLE; goto done; } @@ -2219,9 +2221,10 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, - &result); - if (netlogon_pipe == NULL) { + result = cli_rpc_pipe_open_noauth(conn->cli, + &ndr_table_netlogon.syntax_id, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { return result; } -- cgit From e0be03d8d5006f92ed479b84cd30ebfe510fa68a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_ntlmssp Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit a13f0599551609394904b99e4014d580ec65c506) --- source3/winbindd/winbindd_cm.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index b7e2f086fc..340dc2381d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1962,14 +1962,15 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ - conn->samr_pipe = - cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, - PIPE_AUTH_LEVEL_PRIVACY, - domain_name, - machine_account, - machine_password, &result); + result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, + &ndr_table_samr.syntax_id, + PIPE_AUTH_LEVEL_PRIVACY, + domain_name, + machine_account, + machine_password, + &conn->samr_pipe); - if (conn->samr_pipe == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " "pipe for domain %s using NTLMSSP " "authenticated pipe: user %s\\%s. Error was " @@ -2102,11 +2103,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* We have an authenticated connection. Use a NTLMSSP SPNEGO * authenticated LSA pipe with sign & seal. */ - conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp - (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY, - conn->cli->domain, conn->cli->user_name, conn_pwd, &result); + result = cli_rpc_pipe_open_spnego_ntlmssp + (conn->cli, &ndr_table_lsarpc.syntax_id, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, conn->cli->user_name, conn_pwd, + &conn->lsa_pipe); - if (conn->lsa_pipe == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " "domain %s using NTLMSSP authenticated pipe: user " "%s\\%s. Error was %s. Trying schannel.\n", -- cgit From ba2cb35ca5b335a8f33e012255b43b9cf9a04ecf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_schannel_with_key Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit 78e9c937ff2d2e1b70cfed4121e17feb6efafda1) --- source3/winbindd/winbindd_cm.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 340dc2381d..b3f8950691 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2006,11 +2006,11 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "for domain %s, trying anon\n", domain->name)); goto anonymous; } - conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key - (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, - domain->name, p_dcinfo, &result); + result = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &conn->samr_pipe); - if (conn->samr_pipe == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " "domain %s using schannel. Error was %s\n", domain->name, nt_errstr(result) )); @@ -2144,11 +2144,12 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "for domain %s, trying anon\n", domain->name)); goto anonymous; } - conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key - (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY, - domain->name, p_dcinfo, &result); + result = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_lsarpc.syntax_id, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &conn->lsa_pipe); - if (conn->lsa_pipe == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " "domain %s using schannel. Error was %s\n", domain->name, nt_errstr(result) )); @@ -2290,18 +2291,15 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, part of the new pipe auth struct. */ - conn->netlogon_pipe = - cli_rpc_pipe_open_schannel_with_key(conn->cli, - PI_NETLOGON, - PIPE_AUTH_LEVEL_PRIVACY, - domain->name, - netlogon_pipe->dc, - &result); + result = cli_rpc_pipe_open_schannel_with_key( + conn->cli, &ndr_table_netlogon.syntax_id, + PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc, + &conn->netlogon_pipe); /* We can now close the initial netlogon pipe. */ TALLOC_FREE(netlogon_pipe); - if (conn->netlogon_pipe == NULL) { + if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); -- cgit From 06d0790c0799112b89534a646e78d0cb38b06e20 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 3 Jul 2008 22:53:42 -0700 Subject: Fix various build warnings This fixes various build warnings on our platform. I'm sure I haven't caught them all, but it's a start. (This used to be commit 6b73f259cb67d9dda9127907d706f9244a871fa3) --- source3/winbindd/winbindd_pam.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c26f552d31..0f9f1e1621 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1179,6 +1179,18 @@ done: return result; } +typedef NTSTATUS (*netlogon_fn_t)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct winbindd_cli_state *state, struct netr_SamInfo3 **info3) @@ -1285,17 +1297,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *ldomain, - const char *workstation, - const uint8 lchal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **linfo3); + netlogon_fn_t logon_fn; ZERO_STRUCTP(my_info3); retry = False; @@ -1863,17 +1865,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *ldomain, - const char *lworkstation, - const uint8 lchal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **linfo3); + netlogon_fn_t logon_fn; retry = False; -- cgit From d7b87cdce289030a9d274e51404ad1a0580b36bd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Jul 2008 14:46:43 +0200 Subject: Make use of TALLOC_FREE when freeing the per-winbindrequest memory context (This used to be commit 9e49d390f79c6afc8b0efd9664e60602aebaa4f2) --- source3/winbindd/winbindd.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 55ab58f7eb..cb16c765a1 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -546,10 +546,7 @@ static void response_extra_sent(void *private_data, bool success) struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); - if (state->mem_ctx != NULL) { - talloc_destroy(state->mem_ctx); - state->mem_ctx = NULL; - } + TALLOC_FREE(state->mem_ctx); if (!success) { state->finished = True; @@ -574,10 +571,7 @@ static void response_main_sent(void *private_data, bool success) } if (state->response.length == sizeof(state->response)) { - if (state->mem_ctx != NULL) { - talloc_destroy(state->mem_ctx); - state->mem_ctx = NULL; - } + TALLOC_FREE(state->mem_ctx); setup_async_read(&state->fd_event, &state->request, sizeof(uint32), request_len_recv, state); @@ -767,10 +761,7 @@ static void remove_client(struct winbindd_cli_state *state) SAFE_FREE(state->response.extra_data.data); - if (state->mem_ctx != NULL) { - talloc_destroy(state->mem_ctx); - state->mem_ctx = NULL; - } + TALLOC_FREE(state->mem_ctx); remove_fd_event(&state->fd_event); -- cgit From 8ea3ce5342f7ddcc0e36ff0b17d75ed74bdb6ce4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Jul 2008 14:58:21 +0200 Subject: Remove unused request_finished_cont() (This used to be commit 865ea6fcbc089a03e453709fa54ff2a39c0c168e) --- source3/winbindd/winbindd.c | 12 ------------ source3/winbindd/winbindd_proto.h | 1 - 2 files changed, 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index cb16c765a1..13c510d4f9 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -537,7 +537,6 @@ static void request_len_recv(void *private_data, bool success); static void request_recv(void *private_data, bool success); static void request_main_recv(void *private_data, bool success); static void request_finished(struct winbindd_cli_state *state); -void request_finished_cont(void *private_data, bool success); static void response_main_sent(void *private_data, bool success); static void response_extra_sent(void *private_data, bool success); @@ -603,17 +602,6 @@ void request_ok(struct winbindd_cli_state *state) request_finished(state); } -void request_finished_cont(void *private_data, bool success) -{ - struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); - - if (success) - request_ok(state); - else - request_error(state); -} - static void request_len_recv(void *private_data, bool success) { struct winbindd_cli_state *state = diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 9fafd57cea..0e0db3e859 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -65,7 +65,6 @@ void setup_async_write(struct fd_event *event, void *data, size_t length, void *private_data); void request_error(struct winbindd_cli_state *state); void request_ok(struct winbindd_cli_state *state); -void request_finished_cont(void *private_data, bool success); void winbind_check_sighup(const char *logfile); void winbind_check_sigterm(bool in_parent); int main(int argc, char **argv, char **envp); -- cgit From 0f9c30c11421d045cace1f2c909fdb583ea830ba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jul 2008 12:08:03 +0200 Subject: Fix a race condition in winbind leading to a crash When SIGCHLD handling is delayed for some reason, sending a request to a child can fail early because the child has died already. In this case async_main_request_sent() directly called the continuation function without properly removing the malfunctioning child process and the requests in the queue. The next request would then crash in the DLIST_ADD_END() in async_request() because the request pending for the child had been talloc_free()'ed and yet still was referenced in the list. This one is *old*... Volker (cherry picked from commit 8691709626b0d461de91b8fc9d10c730d1f183dd) (This used to be commit c70e2b6476d2d99c79624e15a4a3cfcdc850fc7c) --- source3/winbindd/winbindd_dual.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 57ab627a5b..f2be6d692c 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -104,6 +104,7 @@ struct winbindd_async_request { void *private_data; }; +static void async_request_fail(struct winbindd_async_request *state); static void async_main_request_sent(void *private_data, bool success); static void async_request_sent(void *private_data, bool success); static void async_reply_recv(void *private_data, bool success); @@ -129,6 +130,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, state->mem_ctx = mem_ctx; state->child = child; + state->reply_timeout_event = NULL; state->request = request; state->response = response; state->continuation = continuation; @@ -148,10 +150,7 @@ static void async_main_request_sent(void *private_data, bool success) if (!success) { DEBUG(5, ("Could not send async request\n")); - - state->response->length = sizeof(struct winbindd_response); - state->response->result = WINBINDD_ERROR; - state->continuation(state->private_data, False); + async_request_fail(state); return; } -- cgit From 0fdffbc9595ac32969fbb30bc403b426af7a82d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jul 2008 23:30:53 +0200 Subject: Fix an incompatible pointer warning (cherry picked from commit 3282f7289b7b33beeaa1ca649651cca6537a69af) (This used to be commit fc8641443951dc852dc9cf1e73626df452b815f7) --- source3/winbindd/winbindd_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 576300555a..00e53eff74 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -184,7 +184,7 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, const char *full_name, const char *homedir, const char *shell, - uint32 gid, + gid_t gid, uint32 group_rid); static void getpwsid_sid2uid_recv(void *private_data, bool success, uid_t uid); static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid); @@ -223,7 +223,7 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, const char *full_name, const char *homedir, const char *shell, - uint32 gid, + gid_t gid, uint32 group_rid) { fstring username; -- cgit From 3bdfcbac5c1a6c571a4299467a7993da46a921a5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 29 Jul 2008 12:08:47 +0200 Subject: winbindd: handle trusted domains without sid. Guenther (This used to be commit 0c1efc6c89b1a51a94d10971bf0fc515416709b3) --- source3/winbindd/winbindd_ads.c | 12 ++++++++++-- source3/winbindd/winbindd_cache.c | 9 +++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 5e3d5d2aec..097fa3907d 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1241,13 +1241,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name); (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name); - sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid); + if (trusts.array[i].sid) { + sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid); + } else { + sid_copy(&(*dom_sids)[ret_count], &global_sid_NULL); + } /* add to the trusted domain cache */ fstrcpy( d.name, trusts.array[i].netbios_name); fstrcpy( d.alt_name, trusts.array[i].dns_name); - sid_copy( &d.sid, trusts.array[i].sid); + if (trusts.array[i].sid) { + sid_copy( &d.sid, trusts.array[i].sid); + } else { + sid_copy(&(*dom_sids)[ret_count], &global_sid_NULL); + } if ( domain->primary ) { DEBUG(10,("trusted_domains(ads): Searching " diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 60403717c1..c9d857c2ec 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2072,7 +2072,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, for (i=0; i<(*num_domains); i++) { (*names)[i] = centry_string(centry, mem_ctx); (*alt_names)[i] = centry_string(centry, mem_ctx); - centry_sid(centry, mem_ctx, &(*dom_sids)[i]); + if (!centry_sid(centry, mem_ctx, &(*dom_sids)[i])) { + sid_copy(&(*dom_sids)[i], &global_sid_NULL); + } } status = centry->status; @@ -3543,8 +3545,11 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom, list[idx].domain_name = talloc_strdup( list, new_dom->name ); list[idx].dns_name = talloc_strdup( list, new_dom->alt_name ); - if ( !is_null_sid( &new_dom->sid ) ) + if ( !is_null_sid( &new_dom->sid ) ) { sid_copy( &list[idx].sid, &new_dom->sid ); + } else { + sid_copy(&list[idx].sid, &global_sid_NULL); + } if ( new_dom->domain_flags != 0x0 ) list[idx].trust_flags = new_dom->domain_flags; -- cgit From 8fed76b73e3576ef2279c0ff6c8bc393010443e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 6 Aug 2008 14:02:45 +1000 Subject: fixed a fd leak when trying to regain contact to a domain controller in winbind When a w2k3 DC is rebooted the 139/445 ports come up before the udp/389 cldap port. During this brief period, winbind manages to connect to 139/445 but not to udp 389. It then enters a tight loop where it leaks one fd each time. In a couple of seconds it runs out of file descriptors, and leaves winbind crippled after the DC does finally come up (This used to be commit 57187cafbcc053e75bb54750494df9feabe3a738) --- source3/winbindd/winbindd_cm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index b3f8950691..47df4e4058 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1320,6 +1320,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, TALLOC_FREE(addrs); num_addrs = 0; + close(*fd); *fd = -1; goto again; -- cgit From 08f7c2d0fc69f58cbe4dc077f609818d3afe07cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 Jul 2008 22:09:39 +0200 Subject: Move the uid2sid cache to the parent winbind process (This used to be commit 6e885aeabba2265a06b726f567cb14dde12c8ccb) --- source3/winbindd/idmap_cache.c | 80 +++++++++++++++++++++++++++++++++ source3/winbindd/winbindd.h | 2 + source3/winbindd/winbindd_sid.c | 97 +++++++++++++++++++++++++++++++++-------- 3 files changed, 160 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index f7e1d4e6d1..027ce3b619 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -521,3 +521,83 @@ done: return ret; } +bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid, + bool *expired) +{ + fstring sidstr; + char *key; + char *value; + char *endptr; + time_t timeout; + uid_t uid; + bool ret; + + key = talloc_asprintf(talloc_tos(), "IDMAP/SID2UID/%s", + sid_to_fstring(sidstr, sid)); + if (key == NULL) { + return false; + } + ret = gencache_get(key, &value, &timeout); + TALLOC_FREE(key); + if (!ret) { + return false; + } + uid = strtol(value, &endptr, 10); + ret = (*endptr == '\0'); + SAFE_FREE(value); + if (ret) { + *puid = uid; + *expired = (timeout <= time(NULL)); + } + return ret; +} + +bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) +{ + char *key; + char *value; + time_t timeout; + bool ret; + + key = talloc_asprintf(talloc_tos(), "IDMAP/UID2SID/%d", (int)uid); + if (key == NULL) { + return false; + } + ret = gencache_get(key, &value, &timeout); + TALLOC_FREE(key); + if (!ret) { + return false; + } + ZERO_STRUCTP(sid); + ret = string_to_sid(sid, value); + SAFE_FREE(value); + if (ret) { + *expired = (timeout <= time(NULL)); + } + return ret; +} + +void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) +{ + time_t now = time(NULL); + time_t timeout; + fstring sidstr, key, value; + + if (!is_null_sid(sid)) { + fstr_sprintf(key, "IDMAP/SID2UID/%s", + sid_to_fstring(sidstr, sid)); + fstr_sprintf(value, "%d", (int)uid); + timeout = (uid == -1) + ? lp_idmap_negative_cache_time() + : lp_idmap_cache_time(); + gencache_set(key, value, now + timeout); + } + if (uid != -1) { + fstr_sprintf(key, "IDMAP/UID2SID/%d", (int)uid); + sid_to_fstring(value, sid); + timeout = is_null_sid(sid) + ? lp_idmap_negative_cache_time() + : lp_idmap_cache_time(); + gencache_set(key, value, now + timeout); + } +} diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index b2fe8b67e7..f6f269ee6d 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -379,4 +379,6 @@ enum ent_type { #define IS_DOMAIN_OFFLINE(x) ( lp_winbind_offline_logon() && \ ( get_global_winbindd_state_offline() \ || !(x)->online ) ) +#define IS_DOMAIN_ONLINE(x) (!IS_DOMAIN_OFFLINE(x)) + #endif /* _WINBINDD_H */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 0e8e6ca00b..ce34dadf4c 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -159,14 +159,19 @@ static void sid2uid_recv(void *private_data, bool success, uid_t uid) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); + struct dom_sid sid; + + string_to_sid(&sid, state->request.data.sid); if (!success) { DEBUG(5, ("Could not convert sid %s\n", state->request.data.sid)); + idmap_cache_set_sid2uid(&sid, -1); request_error(state); return; } + idmap_cache_set_sid2uid(&sid, uid); state->response.data.uid = uid; request_ok(state); } @@ -180,34 +185,40 @@ static void sid2uid_lookupsid_recv( void *private_data, bool success, talloc_get_type_abort(private_data, struct winbindd_cli_state); DOM_SID sid; + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid " + "%s from string\n", state->request.data.sid)); + request_error(state); + return; + } + if (!success) { DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n", state->request.data.sid)); - request_error(state); - return; + goto fail; } if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) { DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n", state->request.data.sid)); - request_error(state); - return; + goto fail; } - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n", - state->request.data.sid)); - request_error(state); - return; - } - /* always use the async interface (may block) */ winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state); + return; + + fail: + idmap_cache_set_sid2uid(&sid, -1); + request_error(state); + return; } void winbindd_sid_to_uid(struct winbindd_cli_state *state) { DOM_SID sid; + uid_t uid; + bool expired; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -222,10 +233,29 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state) return; } + if (idmap_cache_find_sid2uid(&sid, &uid, &expired)) { + DEBUG(10, ("idmap_cache_find_sid2uid found %d%s\n", + (int)uid, expired ? " (expired)": "")); + if (expired && IS_DOMAIN_ONLINE(find_our_domain())) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (uid == -1) { + DEBUG(10, ("Returning negative cache entry\n")); + request_error(state); + return; + } + DEBUG(10, ("Returning positive cache entry\n")); + state->response.data.uid = uid; + request_ok(state); + return; + } + /* Validate the SID as a user. Hopefully this will hit cache. Needed to prevent DoS by exhausting the uid allocation range from random SIDs. */ + backend: winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state ); } @@ -411,30 +441,59 @@ void winbindd_set_hwm(struct winbindd_cli_state *state) /* Convert a uid to a sid */ -static void uid2sid_recv(void *private_data, bool success, const char *sid) +static void uid2sid_recv(void *private_data, bool success, const char *sidstr) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; + struct dom_sid sid; - if (success) { - DEBUG(10,("uid2sid: uid %lu has sid %s\n", - (unsigned long)(state->request.data.uid), sid)); - fstrcpy(state->response.data.sid.sid, sid); - state->response.data.sid.type = SID_NAME_USER; - request_ok(state); + if (!success || !string_to_sid(&sid, sidstr)) { + ZERO_STRUCT(sid); + idmap_cache_set_sid2uid(&sid, state->request.data.uid); + request_error(state); return; } - request_error(state); + DEBUG(10,("uid2sid: uid %lu has sid %s\n", + (unsigned long)(state->request.data.uid), sidstr)); + + idmap_cache_set_sid2uid(&sid, state->request.data.uid); + fstrcpy(state->response.data.sid.sid, sidstr); + state->response.data.sid.type = SID_NAME_USER; + request_ok(state); return; } void winbindd_uid_to_sid(struct winbindd_cli_state *state) { + struct dom_sid sid; + bool expired; + DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, (unsigned long)state->request.data.uid)); + if (idmap_cache_find_uid2sid(state->request.data.uid, &sid, + &expired)) { + DEBUG(10, ("idmap_cache_find_uid2sid found %d%s\n", + (int)state->request.data.uid, + expired ? " (expired)": "")); + if (expired && IS_DOMAIN_ONLINE(find_our_domain())) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (is_null_sid(&sid)) { + DEBUG(10, ("Returning negative cache entry\n")); + request_error(state); + return; + } + DEBUG(10, ("Returning positive cache entry\n")); + sid_to_fstring(state->response.data.sid.sid, &sid); + request_ok(state); + return; + } + /* always go via the async interface (may block) */ + backend: winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state); } -- cgit From 1bdbe772ada5aeb1eeb98e78759ae7235d098085 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 13:58:31 +0200 Subject: Move the gid2sid cache to the parent winbind process (This used to be commit a86a6835e2737fdbdf1f36bcd594d4b01a60acb9) --- source3/winbindd/idmap_cache.c | 81 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_sid.c | 96 +++++++++++++++++++++++++++++++++-------- 2 files changed, 158 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 027ce3b619..e54d02784f 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -601,3 +601,84 @@ void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) gencache_set(key, value, now + timeout); } } + +bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid, + bool *expired) +{ + fstring sidstr; + char *key; + char *value; + char *endptr; + time_t timeout; + gid_t gid; + bool ret; + + key = talloc_asprintf(talloc_tos(), "IDMAP/SID2GID/%s", + sid_to_fstring(sidstr, sid)); + if (key == NULL) { + return false; + } + ret = gencache_get(key, &value, &timeout); + TALLOC_FREE(key); + if (!ret) { + return false; + } + gid = strtol(value, &endptr, 10); + ret = (*endptr == '\0'); + SAFE_FREE(value); + if (ret) { + *pgid = gid; + *expired = (timeout <= time(NULL)); + } + return ret; +} + +bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) +{ + char *key; + char *value; + time_t timeout; + bool ret; + + key = talloc_asprintf(talloc_tos(), "IDMAP/GID2SID/%d", (int)gid); + if (key == NULL) { + return false; + } + ret = gencache_get(key, &value, &timeout); + TALLOC_FREE(key); + if (!ret) { + return false; + } + ZERO_STRUCTP(sid); + ret = string_to_sid(sid, value); + SAFE_FREE(value); + if (ret) { + *expired = (timeout <= time(NULL)); + } + return ret; +} + +void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid) +{ + time_t now = time(NULL); + time_t timeout; + fstring sidstr, key, value; + + if (!is_null_sid(sid)) { + fstr_sprintf(key, "IDMAP/SID2GID/%s", + sid_to_fstring(sidstr, sid)); + fstr_sprintf(value, "%d", (int)gid); + timeout = (gid == -1) + ? lp_idmap_negative_cache_time() + : lp_idmap_cache_time(); + gencache_set(key, value, now + timeout); + } + if (gid != -1) { + fstr_sprintf(key, "IDMAP/GID2SID/%d", (int)gid); + sid_to_fstring(value, sid); + timeout = is_null_sid(sid) + ? lp_idmap_negative_cache_time() + : lp_idmap_cache_time(); + gencache_set(key, value, now + timeout); + } +} diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index ce34dadf4c..2869c7c8e1 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -266,14 +266,19 @@ static void sid2gid_recv(void *private_data, bool success, gid_t gid) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); + struct dom_sid sid; + + string_to_sid(&sid, state->request.data.sid); if (!success) { DEBUG(5, ("Could not convert sid %s\n", state->request.data.sid)); + idmap_cache_set_sid2gid(&sid, -1); request_error(state); return; } + idmap_cache_set_sid2gid(&sid, gid); state->response.data.gid = gid; request_ok(state); } @@ -287,11 +292,17 @@ static void sid2gid_lookupsid_recv( void *private_data, bool success, talloc_get_type_abort(private_data, struct winbindd_cli_state); DOM_SID sid; + if (!string_to_sid(&sid, state->request.data.sid)) { + DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid " + "%s from string\n", state->request.data.sid)); + request_error(state); + return; + } + if (!success) { DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n", state->request.data.sid)); - request_error(state); - return; + goto fail; } if ( (type!=SID_NAME_DOM_GRP) && @@ -300,24 +311,24 @@ static void sid2gid_lookupsid_recv( void *private_data, bool success, { DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n", state->request.data.sid)); - request_error(state); - return; + goto fail; } - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n", - state->request.data.sid)); - request_error(state); - return; - } - /* always use the async interface (may block) */ winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state); + return; + + fail: + idmap_cache_set_sid2gid(&sid, -1); + request_error(state); + return; } void winbindd_sid_to_gid(struct winbindd_cli_state *state) { DOM_SID sid; + gid_t gid; + bool expired; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -332,10 +343,29 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state) return; } + if (idmap_cache_find_sid2gid(&sid, &gid, &expired)) { + DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n", + (int)gid, expired ? " (expired)": "")); + if (expired && IS_DOMAIN_ONLINE(find_our_domain())) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (gid == -1) { + DEBUG(10, ("Returning negative cache entry\n")); + request_error(state); + return; + } + DEBUG(10, ("Returning positive cache entry\n")); + state->response.data.gid = gid; + request_ok(state); + return; + } + /* Validate the SID as a group. Hopefully this will hit cache. Needed to prevent DoS by exhausting the uid allocation range from random SIDs. */ + backend: winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state ); } @@ -499,31 +529,59 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state) /* Convert a gid to a sid */ -static void gid2sid_recv(void *private_data, bool success, const char *sid) +static void gid2sid_recv(void *private_data, bool success, const char *sidstr) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; + struct dom_sid sid; - if (success) { - DEBUG(10,("gid2sid: gid %lu has sid %s\n", - (unsigned long)(state->request.data.gid), sid)); - fstrcpy(state->response.data.sid.sid, sid); - state->response.data.sid.type = SID_NAME_DOM_GRP; - request_ok(state); + if (!success || !string_to_sid(&sid, sidstr)) { + ZERO_STRUCT(sid); + idmap_cache_set_sid2gid(&sid, state->request.data.gid); + request_error(state); return; } + DEBUG(10,("gid2sid: gid %lu has sid %s\n", + (unsigned long)(state->request.data.gid), sid)); - request_error(state); + idmap_cache_set_sid2gid(&sid, state->request.data.gid); + fstrcpy(state->response.data.sid.sid, sidstr); + state->response.data.sid.type = SID_NAME_DOM_GRP; + request_ok(state); return; } void winbindd_gid_to_sid(struct winbindd_cli_state *state) { + struct dom_sid sid; + bool expired; + DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, (unsigned long)state->request.data.gid)); + if (idmap_cache_find_gid2sid(state->request.data.gid, &sid, + &expired)) { + DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n", + (int)state->request.data.gid, + expired ? " (expired)": "")); + if (expired && IS_DOMAIN_ONLINE(find_our_domain())) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (is_null_sid(&sid)) { + DEBUG(10, ("Returning negative cache entry\n")); + request_error(state); + return; + } + DEBUG(10, ("Returning positive cache entry\n")); + sid_to_fstring(state->response.data.sid.sid, &sid); + request_ok(state); + return; + } + /* always use async calls (may block) */ + backend: winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state); } -- cgit From 0c1e27abf69855abef396e4c93989964b70fcf1f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 Jul 2008 12:32:18 +0200 Subject: Directly call backends from idmap_[ugs]_to_[ugs]id (This used to be commit f955407042e6d2384acccc399d72ff65ba0e721c) --- source3/winbindd/idmap.c | 39 +++++++++++++++++++++++++++++++++++++++ source3/winbindd/idmap_util.c | 28 ++++++---------------------- 2 files changed, 45 insertions(+), 22 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 95ff923d0f..f0d2c03e0b 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -1282,6 +1282,45 @@ done: return ret; } +NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id) +{ + struct id_map *maps[2]; + int i; + + maps[0] = id; + maps[1] = NULL; + + for (i = num_domains-1; i>=0; i--) { + struct idmap_domain *dom = idmap_domains[i]; + NTSTATUS status; + + DEBUG(10, ("Query sids from domain %s\n", dom->name)); + + status = dom->methods->unixids_to_sids(dom, maps); + if (NT_STATUS_IS_OK(status)) { + return NT_STATUS_OK; + } + } + + return NT_STATUS_NONE_MAPPED; +} + +NTSTATUS idmap_backends_sid_to_unixid(struct id_map *id) +{ + struct idmap_domain *dom; + struct id_map *maps[2]; + + dom = find_idmap_domain_from_sid(id->sid); + if (dom == NULL) { + return NT_STATUS_NONE_MAPPED; + } + + maps[0] = id; + maps[1] = NULL; + + return dom->methods->sids_to_unixids(dom, maps); +} + /************************************************************************** idmap interface functions **************************************************************************/ diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 0d24070dd6..31b9895224 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -31,7 +31,6 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; DEBUG(10,("uid = [%lu]\n", (unsigned long)uid)); @@ -39,10 +38,7 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) map.xid.type = ID_TYPE_UID; map.xid.id = uid; - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_unixids_to_sids(maps); + ret = idmap_backends_unixid_to_sid(&map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); return ret; @@ -65,7 +61,6 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); @@ -73,10 +68,7 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) map.xid.type = ID_TYPE_GID; map.xid.id = gid; - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_unixids_to_sids(maps); + ret = idmap_backends_unixid_to_sid(&map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); return ret; @@ -99,17 +91,13 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_UID; - - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_sids_to_unixids(maps); + + ret = idmap_backends_sid_to_unixid(&map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to uid\n", sid_string_dbg(sid))); @@ -139,17 +127,13 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) { NTSTATUS ret; struct id_map map; - struct id_map *maps[2]; DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid))); map.sid = sid; map.xid.type = ID_TYPE_GID; - - maps[0] = ↦ - maps[1] = NULL; - - ret = idmap_sids_to_unixids(maps); + + ret = idmap_backends_sid_to_unixid(&map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping sid [%s] to gid\n", sid_string_dbg(sid))); -- cgit From 8d4bd2d960ebf11bc85891210c6f72a371e08417 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 13 Jul 2008 09:59:57 +0200 Subject: Remove the multi-ID lookup code and the 3.2.0 version of idmap_cache (This used to be commit 1bd98521dc3f16ad77ccccd3979288c58e03ebe8) --- source3/winbindd/idmap.c | 434 --------------------------------- source3/winbindd/idmap_cache.c | 498 -------------------------------------- source3/winbindd/winbindd.c | 3 - source3/winbindd/winbindd_idmap.c | 108 --------- source3/winbindd/winbindd_sid.c | 26 -- 5 files changed, 1069 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index f0d2c03e0b..2c18164f8c 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -269,10 +269,6 @@ NTSTATUS idmap_init_cache(void) return NT_STATUS_NO_MEMORY; } - if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { - return NT_STATUS_UNSUCCESSFUL; - } - return NT_STATUS_OK; } @@ -1092,196 +1088,6 @@ static NTSTATUS idmap_backends_set_mapping(const struct id_map *map) return dom->methods->set_mapping(dom, map); } -static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids) -{ - struct idmap_domain *dom; - struct id_map **unmapped; - struct id_map **_ids; - TALLOC_CTX *ctx; - NTSTATUS ret; - int i, u, n; - - if (!ids || !*ids) { - DEBUG(1, ("Invalid list of maps\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - ctx = talloc_named_const(NULL, 0, "idmap_backends_unixids_to_sids ctx"); - if ( ! ctx) { - DEBUG(0, ("Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - DEBUG(10, ("Query backends to map ids->sids\n")); - - /* start from the default (the last one) and then if there are still - * unmapped entries cycle through the others */ - - _ids = ids; - - unmapped = NULL; - for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */ - - dom = idmap_domains[n]; - - DEBUG(10, ("Query sids from domain %s\n", dom->name)); - - ret = dom->methods->unixids_to_sids(dom, _ids); - IDMAP_REPORT_RET(ret); - - unmapped = NULL; - - for (i = 0, u = 0; _ids[i]; i++) { - if (_ids[i]->status != ID_MAPPED) { - unmapped = talloc_realloc(ctx, unmapped, - struct id_map *, u + 2); - IDMAP_CHECK_ALLOC(unmapped); - unmapped[u] = _ids[i]; - u++; - } - } - if (unmapped) { - /* terminate the unmapped list */ - unmapped[u] = NULL; - } else { /* no more entries, get out */ - break; - } - - _ids = unmapped; - - } - - if (unmapped) { - /* there are still unmapped ids, - * map them to the unix users/groups domains */ - /* except for expired entries, - * these will be returned as valid (offline mode) */ - for (i = 0; unmapped[i]; i++) { - if (unmapped[i]->status == ID_EXPIRED) continue; - switch (unmapped[i]->xid.type) { - case ID_TYPE_UID: - uid_to_unix_users_sid( - (uid_t)unmapped[i]->xid.id, - unmapped[i]->sid); - unmapped[i]->status = ID_MAPPED; - break; - case ID_TYPE_GID: - gid_to_unix_groups_sid( - (gid_t)unmapped[i]->xid.id, - unmapped[i]->sid); - unmapped[i]->status = ID_MAPPED; - break; - default: /* what?! */ - unmapped[i]->status = ID_UNKNOWN; - break; - } - } - } - - ret = NT_STATUS_OK; - -done: - talloc_free(ctx); - return ret; -} - -static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) -{ - struct id_map ***dom_ids; - struct idmap_domain *dom; - TALLOC_CTX *ctx; - NTSTATUS ret; - int i, *counters; - - if ( (ctx = talloc_named_const(NULL, 0, "be_sids_to_ids")) == NULL ) { - DEBUG(1, ("failed to allocate talloc context, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - DEBUG(10, ("Query backends to map sids->ids\n")); - - /* split list per domain */ - if (num_domains == 0) { - DEBUG(1, ("No domains available?\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - dom_ids = TALLOC_ZERO_ARRAY(ctx, struct id_map **, num_domains); - IDMAP_CHECK_ALLOC(dom_ids); - counters = TALLOC_ZERO_ARRAY(ctx, int, num_domains); - IDMAP_CHECK_ALLOC(counters); - - /* partition the requests by domain */ - - for (i = 0; ids[i]; i++) { - uint32 idx; - - if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) { - /* no available idmap_domain. Move on */ - continue; - } - - DEBUG(10,("SID %s is being handled by %s\n", - sid_string_dbg(ids[i]->sid), - dom ? dom->name : "none" )); - - idx = find_idmap_domain_index( dom ); - SMB_ASSERT( idx != -1 ); - - dom_ids[idx] = talloc_realloc(ctx, dom_ids[idx], - struct id_map *, - counters[idx] + 2); - IDMAP_CHECK_ALLOC(dom_ids[idx]); - - dom_ids[idx][counters[idx]] = ids[i]; - counters[idx]++; - dom_ids[idx][counters[idx]] = NULL; - } - - /* All the ids have been dispatched in the right queues. - Let's cycle through the filled ones */ - - for (i = 0; i < num_domains; i++) { - if (dom_ids[i]) { - dom = idmap_domains[i]; - DEBUG(10, ("Query ids from domain %s\n", dom->name)); - ret = dom->methods->sids_to_unixids(dom, dom_ids[i]); - IDMAP_REPORT_RET(ret); - } - } - - /* ok all the backends have been contacted at this point */ - /* let's see if we have any unmapped SID left and act accordingly */ - - for (i = 0; ids[i]; i++) { - /* NOTE: this will NOT touch ID_EXPIRED entries that the backend - * was not able to confirm/deny (offline mode) */ - if (ids[i]->status == ID_UNKNOWN || - ids[i]->status == ID_UNMAPPED) { - /* ok this is an unmapped one, see if we can map it */ - ret = idmap_new_mapping(ctx, ids[i]); - if (NT_STATUS_IS_OK(ret)) { - /* successfully mapped */ - ids[i]->status = ID_MAPPED; - } else - if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) { - /* could not map it */ - ids[i]->status = ID_UNMAPPED; - } else { - /* Something very bad happened down there - * OR we are offline */ - ids[i]->status = ID_UNKNOWN; - } - } - } - - ret = NT_STATUS_OK; - -done: - talloc_free(ctx); - return ret; -} - NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id) { struct id_map *maps[2]; @@ -1321,242 +1127,6 @@ NTSTATUS idmap_backends_sid_to_unixid(struct id_map *id) return dom->methods->sids_to_unixids(dom, maps); } -/************************************************************************** - idmap interface functions -**************************************************************************/ - -NTSTATUS idmap_unixids_to_sids(struct id_map **ids) -{ - TALLOC_CTX *ctx; - NTSTATUS ret; - struct id_map **bids; - int i, bi; - int bn = 0; - struct winbindd_domain *our_domain = find_our_domain(); - - if (! NT_STATUS_IS_OK(ret = idmap_init())) { - return ret; - } - - if (!ids || !*ids) { - DEBUG(1, ("Invalid list of maps\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - ctx = talloc_named_const(NULL, 0, "idmap_unixids_to_sids ctx"); - if ( ! ctx) { - DEBUG(1, ("failed to allocate talloc context, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - /* no ids to be asked to the backends by default */ - bids = NULL; - bi = 0; - - for (i = 0; ids[i]; i++) { - - if ( ! ids[i]->sid) { - DEBUG(1, ("invalid null SID in id_map array")); - talloc_free(ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - ret = idmap_cache_map_id(idmap_cache, ids[i]); - - if (NT_STATUS_IS_OK(ret)) continue; - - if ( ! bids) { - /* alloc space for ids to be resolved by - * backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; - } - - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the rids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - } - - /* make sure the last element is NULL */ - bids[bi] = NULL; - } - - /* let's see if there is any id mapping to be retrieved - * from the backends */ - if (bids) { - bool online; - - /* Only do query if we are online */ - online = !IS_DOMAIN_OFFLINE(our_domain); - if (online) { - ret = idmap_backends_unixids_to_sids(bids); - IDMAP_CHECK_RET(ret); - } - - /* update the cache */ - for (i = 0; i < bi; i++) { - if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(idmap_cache, bids[i]); - } else if (bids[i]->status == ID_EXPIRED) { - /* the cache returned an expired entry and the - * backend was not able to clear the situation - * (offline). This handles a previous - * NT_STATUS_SYNCHRONIZATION_REQUIRED - * for disconnected mode, */ - bids[i]->status = ID_MAPPED; - } else if (bids[i]->status == ID_UNKNOWN) { - /* something bad here. We were not able to - * handle this for some reason, mark it as - * unmapped and hope next time things will - * settle down. */ - bids[i]->status = ID_UNMAPPED; - } else if (online) { /* unmapped */ - ret = idmap_cache_set_negative_id(idmap_cache, - bids[i]); - } - IDMAP_CHECK_RET(ret); - } - } - - ret = NT_STATUS_OK; -done: - talloc_free(ctx); - return ret; -} - -NTSTATUS idmap_sids_to_unixids(struct id_map **ids) -{ - TALLOC_CTX *ctx; - NTSTATUS ret; - struct id_map **bids; - int i, bi; - int bn = 0; - struct winbindd_domain *our_domain = find_our_domain(); - - if (! NT_STATUS_IS_OK(ret = idmap_init())) { - return ret; - } - - if (!ids || !*ids) { - DEBUG(1, ("Invalid list of maps\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - ctx = talloc_named_const(NULL, 0, "idmap_sids_to_unixids ctx"); - if ( ! ctx) { - DEBUG(1, ("failed to allocate talloc context, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - /* no ids to be asked to the backends by default */ - bids = NULL; - bi = 0; - - for (i = 0; ids[i]; i++) { - - if ( ! ids[i]->sid) { - DEBUG(1, ("invalid null SID in id_map array\n")); - talloc_free(ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - ret = idmap_cache_map_sid(idmap_cache, ids[i]); - - if (NT_STATUS_IS_OK(ret)) continue; - - if ( ! bids) { - /* alloc space for ids to be resolved - by backends (realloc ten by ten) */ - bids = TALLOC_ARRAY(ctx, struct id_map *, 10); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - bn = 10; - } - - /* add this id to the ones to be retrieved - * from the backends */ - bids[bi] = ids[i]; - bi++; - - /* check if we need to allocate new space - * on the ids array */ - if (bi == bn) { - bn += 10; - bids = talloc_realloc(ctx, bids, struct id_map *, bn); - if ( ! bids) { - DEBUG(1, ("Out of memory!\n")); - talloc_free(ctx); - return NT_STATUS_NO_MEMORY; - } - } - - /* make sure the last element is NULL */ - bids[bi] = NULL; - } - - /* let's see if there is any id mapping to be retrieved - * from the backends */ - if (bids) { - bool online; - - /* Only do query if we are online */ - online = !IS_DOMAIN_OFFLINE(our_domain); - if (online) { - ret = idmap_backends_sids_to_unixids(bids); - IDMAP_CHECK_RET(ret); - } - - /* update the cache */ - for (i = 0; bids[i]; i++) { - if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(idmap_cache, bids[i]); - } else if (bids[i]->status == ID_EXPIRED) { - /* the cache returned an expired entry and the - * backend was not able to clear the situation - * (offline). This handles a previous - * NT_STATUS_SYNCHRONIZATION_REQUIRED - * for disconnected mode, */ - bids[i]->status = ID_MAPPED; - } else if (bids[i]->status == ID_UNKNOWN) { - /* something bad here. We were not able to - * handle this for some reason, mark it as - * unmapped and hope next time things will - * settle down. */ - bids[i]->status = ID_UNMAPPED; - } else if (online) { /* unmapped */ - ret = idmap_cache_set_negative_sid(idmap_cache, - bids[i]); - } - IDMAP_CHECK_RET(ret); - } - } - - ret = NT_STATUS_OK; -done: - talloc_free(ctx); - return ret; -} - NTSTATUS idmap_set_mapping(const struct id_map *id) { TALLOC_CTX *ctx; @@ -1584,10 +1154,6 @@ NTSTATUS idmap_set_mapping(const struct id_map *id) ret = idmap_backends_set_mapping(id); IDMAP_CHECK_RET(ret); - /* set the mapping in the cache */ - ret = idmap_cache_set(idmap_cache, id); - IDMAP_CHECK_RET(ret); - done: talloc_free(ctx); return ret; diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index e54d02784f..1e82314440 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -23,504 +23,6 @@ #include "includes.h" #include "winbindd.h" -#define TIMEOUT_LEN 12 -#define IDMAP_CACHE_DATA_FMT "%12u/%s" -#define IDMAP_READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" - -struct idmap_cache_ctx { - TDB_CONTEXT *tdb; -}; - -static int idmap_cache_destructor(struct idmap_cache_ctx *cache) -{ - int ret = 0; - - if (cache && cache->tdb) { - ret = tdb_close(cache->tdb); - cache->tdb = NULL; - } - - return ret; -} - -struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) -{ - struct idmap_cache_ctx *cache; - char* cache_fname = NULL; - - cache = talloc(memctx, struct idmap_cache_ctx); - if ( ! cache) { - DEBUG(0, ("Out of memory!\n")); - return NULL; - } - - cache_fname = lock_path("idmap_cache.tdb"); - - DEBUG(10, ("Opening cache file at %s\n", cache_fname)); - - cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - - if (!cache->tdb) { - DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname)); - return NULL; - } - - talloc_set_destructor(cache, idmap_cache_destructor); - - return cache; -} - -static NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, - const struct id_map *id) -{ - fstring sidstr; - - *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", - sid_to_fstring(sidstr, id->sid)); - if ( ! *sidkey) { - DEBUG(1, ("failed to build sidkey, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -static NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, - const struct id_map *id) -{ - *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu", - (id->xid.type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)id->xid.id); - if ( ! *idkey) { - DEBUG(1, ("failed to build idkey, OOM?\n")); - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) -{ - NTSTATUS ret; - time_t timeout = time(NULL) + lp_idmap_cache_time(); - TDB_DATA databuf; - char *sidkey; - char *idkey; - char *valstr; - - /* Don't cache lookups in the S-1-22-{1,2} domain */ - if ( (id->xid.type == ID_TYPE_UID) && - sid_check_is_in_unix_users(id->sid) ) - { - return NT_STATUS_OK; - } - if ( (id->xid.type == ID_TYPE_GID) && - sid_check_is_in_unix_groups(id->sid) ) - { - return NT_STATUS_OK; - } - - - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; - - /* use sidkey as the local memory ctx */ - ret = idmap_cache_build_idkey(sidkey, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) { - goto done; - } - - /* save SID -> ID */ - - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", sidkey, valstr , ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { - DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* save ID -> SID */ - - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { - DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - ret = NT_STATUS_OK; - -done: - talloc_free(sidkey); - return ret; -} - -NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) -{ - NTSTATUS ret; - time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); - TDB_DATA databuf; - char *sidkey; - char *valstr; - - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; - - /* use sidkey as the local memory ctx */ - valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", sidkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { - DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - -done: - talloc_free(sidkey); - return ret; -} - -NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) -{ - NTSTATUS ret; - time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); - TDB_DATA databuf; - char *idkey; - char *valstr; - - ret = idmap_cache_build_idkey(cache, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; - - /* use idkey as the local memory ctx */ - valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); - if (!valstr) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), - (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { - DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - -done: - talloc_free(idkey); - return ret; -} - -static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) -{ - char *rem; - - /* see if it is a sid */ - if ( ! strncmp("IDMAP/SID/", value, 10)) { - - if ( ! string_to_sid(id->sid, &value[10])) { - goto failed; - } - - id->status = ID_MAPPED; - - return NT_STATUS_OK; - } - - /* not a SID see if it is an UID or a GID */ - if ( ! strncmp("IDMAP/UID/", value, 10)) { - - /* a uid */ - id->xid.type = ID_TYPE_UID; - - } else if ( ! strncmp("IDMAP/GID/", value, 10)) { - - /* a gid */ - id->xid.type = ID_TYPE_GID; - - } else { - - /* a completely bogus value bail out */ - goto failed; - } - - id->xid.id = strtol(&value[10], &rem, 0); - if (*rem != '\0') { - goto failed; - } - - id->status = ID_MAPPED; - - return NT_STATUS_OK; - -failed: - DEBUG(1, ("invalid value: %s\n", value)); - id->status = ID_UNKNOWN; - return NT_STATUS_INTERNAL_DB_CORRUPTION; -} - -/* search the cahce for the SID an return a mapping if found * - * - * 4 cases are possible - * - * 1 map found - * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned - * 2 map not found - * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned - * 3 negative cache found - * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned - * 4 map found but timer expired - * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED - * is returned. In this case revalidation of the cache is needed. - */ - -NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) -{ - NTSTATUS ret; - TDB_DATA databuf; - time_t t; - char *sidkey; - char *endptr; - struct winbindd_domain *our_domain = find_our_domain(); - time_t now = time(NULL); - - /* make sure it is marked as not mapped by default */ - id->status = ID_UNKNOWN; - - ret = idmap_cache_build_sidkey(cache, &sidkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; - - databuf = tdb_fetch_bystring(cache->tdb, sidkey); - - if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey)); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); - /* remove the entry */ - tdb_delete_bystring(cache->tdb, sidkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - /* check it is not negative */ - if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > now ? "valid" : - "expired", sidkey, endptr+1, ctime(&t))); - - /* this call if successful will also mark the entry as mapped */ - ret = idmap_cache_fill_map(id, endptr+1); - if ( ! NT_STATUS_IS_OK(ret)) { - /* if not valid form delete the entry */ - tdb_delete_bystring(cache->tdb, sidkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ - - if (t <= now) { - /* If we've been told to be offline - stay in - that state... */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; - } - - /* We're expired, set an error code - for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; - } - - goto done; - } - - /* Was a negative cache hit */ - - /* Ignore the negative cache when offline */ - - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; - } - - - /* Check for valid or expired cache hits */ - if (t <= now) { - /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped as it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } - -done: - SAFE_FREE(databuf.dptr); - talloc_free(sidkey); - return ret; -} - -/* search the cahce for the ID an return a mapping if found * - * - * 4 cases are possible - * - * 1 map found - * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned - * 2 map not found - * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned - * 3 negative cache found - * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned - * 4 map found but timer expired - * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED - * is returned. In this case revalidation of the cache is needed. - */ - -NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) -{ - NTSTATUS ret; - TDB_DATA databuf; - time_t t; - char *idkey; - char *endptr; - struct winbindd_domain *our_domain = find_our_domain(); - time_t now = time(NULL); - - /* make sure it is marked as unknown by default */ - id->status = ID_UNKNOWN; - - ret = idmap_cache_build_idkey(cache, &idkey, id); - if (!NT_STATUS_IS_OK(ret)) return ret; - - databuf = tdb_fetch_bystring(cache->tdb, idkey); - - if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey)); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", (const char *)databuf.dptr)); - /* remove the entry */ - tdb_delete_bystring(cache->tdb, idkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - /* check it is not negative */ - if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { - - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > now ? "valid" : - "expired", idkey, endptr+1, ctime(&t))); - - /* this call if successful will also mark the entry as mapped */ - ret = idmap_cache_fill_map(id, endptr+1); - if ( ! NT_STATUS_IS_OK(ret)) { - /* if not valid form delete the entry */ - tdb_delete_bystring(cache->tdb, idkey); - ret = NT_STATUS_NONE_MAPPED; - goto done; - } - - /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */ - - if (t <= now) { - /* If we've been told to be offline - stay in - that state... */ - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - goto done; - } - - /* We're expired, set an error code - for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; - } - - goto done; - } - - /* Was a negative cache hit */ - - /* Ignore the negative cache when offline */ - - if ( IS_DOMAIN_OFFLINE(our_domain) ) { - DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); - ret = NT_STATUS_NONE_MAPPED; - - goto done; - } - - /* Process the negative cache hit */ - - if (t <= now) { - /* We're expired. Return not mapped */ - ret = NT_STATUS_NONE_MAPPED; - } else { - /* this is not mapped is it was a negative cache hit */ - id->status = ID_UNMAPPED; - ret = NT_STATUS_OK; - } - -done: - SAFE_FREE(databuf.dptr); - talloc_free(idkey); - return ret; -} - bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid, bool *expired) { diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 13c510d4f9..08cf8ba00a 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -340,9 +340,6 @@ static struct winbindd_dispatch_table { { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" }, { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" }, { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_SIDS_TO_XIDS, winbindd_sids_to_unixids, "SIDS_TO_XIDS" }, -#endif /* end DISABLED */ { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" }, { WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" }, { WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" }, diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 3c7aa2d0c2..41782ff0d1 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -170,108 +170,6 @@ enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain, return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, bool success, - struct winbindd_response *response, - void *c, void *private_data) -{ - void (*cont)(void *priv, bool succ, void *, int) = - (void (*)(void *, bool, void *, int))c; - - if (!success) { - DEBUG(5, ("Could not trigger sids2xids\n")); - cont(private_data, False, NULL, 0); - return; - } - - if (response->result != WINBINDD_OK) { - DEBUG(5, ("sids2xids returned an error\n")); - cont(private_data, False, NULL, 0); - return; - } - - cont(private_data, True, response->extra_data.data, response->length - sizeof(response)); -} - -void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size, - void (*cont)(void *private_data, bool success, void *data, int len), - void *private_data) -{ - struct winbindd_request request; - ZERO_STRUCT(request); - request.cmd = WINBINDD_DUAL_SIDS2XIDS; - request.extra_data.data = (char *)sids; - request.extra_len = size; - do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv, - (void *)cont, private_data); -} - -enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - DOM_SID *sids; - struct unixid *xids; - struct id_map **ids; - NTSTATUS result; - int num, i; - - DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid)); - - if (state->request.extra_len == 0) { - DEBUG(0, ("Invalid buffer size!\n")); - return WINBINDD_ERROR; - } - - sids = (DOM_SID *)state->request.extra_data.data; - num = state->request.extra_len / sizeof(DOM_SID); - - ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1); - if ( ! ids) { - DEBUG(0, ("Out of memory!\n")); - return WINBINDD_ERROR; - } - for (i = 0; i < num; i++) { - ids[i] = TALLOC_P(ids, struct id_map); - if ( ! ids[i]) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - ids[i]->sid = &sids[i]; - } - - result = idmap_sids_to_unixids(ids); - - if (NT_STATUS_IS_OK(result)) { - - xids = SMB_MALLOC_ARRAY(struct unixid, num); - if ( ! xids) { - DEBUG(0, ("Out of memory!\n")); - talloc_free(ids); - return WINBINDD_ERROR; - } - - for (i = 0; i < num; i++) { - if (ids[i]->status == ID_MAPPED) { - xids[i].type = ids[i]->xid.type; - xids[i].id = ids[i]->xid.id; - } else { - xids[i].type = -1; - } - } - - state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num); - state->response.extra_data.data = xids; - - } else { - DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result))); - talloc_free(ids); - return WINBINDD_ERROR; - } - - talloc_free(ids); - return WINBINDD_OK; -} - static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) @@ -521,12 +419,6 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { .name = "DUAL_SID2GID", .struct_cmd = WINBINDD_DUAL_SID2GID, .struct_fn = winbindd_dual_sid2gid, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - },{ - .name = "DUAL_SIDS2XIDS", - .struct_cmd = WINBINDD_DUAL_SIDS2XIDS, - .struct_fn = winbindd_dual_sids2xids, -#endif /* end DISABLED */ },{ .name = "DUAL_UID2SID", .struct_cmd = WINBINDD_DUAL_UID2SID, diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 2869c7c8e1..5f5972fb05 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -369,32 +369,6 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state) winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state ); } -static void sids2xids_recv(void *private_data, bool success, void *data, int len) -{ - struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); - - if (!success) { - DEBUG(5, ("Could not convert sids to xids\n")); - request_error(state); - return; - } - - state->response.extra_data.data = data; - state->response.length = sizeof(state->response) + len; - request_ok(state); -} - -void winbindd_sids_to_unixids(struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid)); - - winbindd_sids2xids_async(state->mem_ctx, - state->request.extra_data.data, - state->request.extra_len, - sids2xids_recv, state); -} - static void set_mapping_recv(void *private_data, bool success) { struct winbindd_cli_state *state = -- cgit From 340ab6a256802a22c11b7f707748397249075b65 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 13 Jul 2008 12:07:40 +0200 Subject: idmap rewrite (This used to be commit 30a180f2fce8cf6a3e5548f6bba453272ba70b33) --- source3/winbindd/idmap.c | 1151 +++++++++++-------------------------- source3/winbindd/idmap_ad.c | 20 +- source3/winbindd/idmap_cache.c | 38 +- source3/winbindd/idmap_ldap.c | 55 +- source3/winbindd/idmap_nss.c | 12 +- source3/winbindd/idmap_passdb.c | 11 +- source3/winbindd/idmap_rid.c | 20 +- source3/winbindd/idmap_tdb.c | 45 +- source3/winbindd/idmap_tdb2.c | 28 +- source3/winbindd/idmap_util.c | 162 ++++-- source3/winbindd/winbindd.c | 6 - source3/winbindd/winbindd.h | 7 + source3/winbindd/winbindd_dual.c | 2 + source3/winbindd/winbindd_group.c | 6 +- source3/winbindd/winbindd_idmap.c | 64 ++- source3/winbindd/winbindd_sid.c | 14 +- source3/winbindd/winbindd_user.c | 6 +- source3/winbindd/winbindd_util.c | 34 ++ 18 files changed, 650 insertions(+), 1031 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 2c18164f8c..bace38876b 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -40,41 +40,25 @@ struct idmap_alloc_backend { struct idmap_alloc_backend *prev, *next; }; -struct idmap_cache_ctx; - struct idmap_alloc_context { - const char *params; struct idmap_alloc_methods *methods; - bool initialized; }; -static TALLOC_CTX *idmap_ctx = NULL; -static struct idmap_cache_ctx *idmap_cache; - +/* + * Lists for the module initializations + */ static struct idmap_backend *backends = NULL; +static struct idmap_alloc_backend *alloc_backends = NULL; + + +static struct idmap_domain *default_idmap_domain; +static struct idmap_domain *passdb_idmap_domain; + static struct idmap_domain **idmap_domains = NULL; static int num_domains = 0; -static int pdb_dom_num = -1; -static int def_dom_num = -1; -static struct idmap_alloc_backend *alloc_backends = NULL; static struct idmap_alloc_context *idmap_alloc_ctx = NULL; -#define IDMAP_CHECK_RET(ret) do { \ - if ( ! NT_STATUS_IS_OK(ret)) { \ - DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \ - goto done; \ - } } while(0) -#define IDMAP_REPORT_RET(ret) do { \ - if ( ! NT_STATUS_IS_OK(ret)) { \ - DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \ - } } while(0) -#define IDMAP_CHECK_ALLOC(mem) do { \ - if (!mem) { \ - DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; \ - goto done; \ - } } while(0) - static struct idmap_methods *get_methods(struct idmap_backend *be, const char *name) { @@ -110,6 +94,11 @@ bool idmap_is_offline(void) get_global_winbindd_state_offline() ); } +bool idmap_is_online(void) +{ + return !idmap_is_offline(); +} + /********************************************************************** Allow a module to register itself as a method. **********************************************************************/ @@ -117,13 +106,8 @@ bool idmap_is_offline(void) NTSTATUS smb_register_idmap(int version, const char *name, struct idmap_methods *methods) { - struct idmap_methods *test; struct idmap_backend *entry; - if (!idmap_ctx) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - if ((version != SMB_IDMAP_INTERFACE_VERSION)) { DEBUG(0, ("Failed to register idmap module.\n" "The module was compiled against " @@ -140,19 +124,20 @@ NTSTATUS smb_register_idmap(int version, const char *name, return NT_STATUS_INVALID_PARAMETER; } - test = get_methods(backends, name); - if (test) { - DEBUG(0,("Idmap module %s already registered!\n", name)); - return NT_STATUS_OBJECT_NAME_COLLISION; + for (entry = backends; entry != NULL; entry = entry->next) { + if (strequal(entry->name, name)) { + DEBUG(0,("Idmap module %s already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } } - entry = talloc(idmap_ctx, struct idmap_backend); + entry = talloc(NULL, struct idmap_backend); if ( ! entry) { DEBUG(0,("Out of memory!\n")); TALLOC_FREE(entry); return NT_STATUS_NO_MEMORY; } - entry->name = talloc_strdup(idmap_ctx, name); + entry->name = talloc_strdup(entry, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); TALLOC_FREE(entry); @@ -175,10 +160,6 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, struct idmap_alloc_methods *test; struct idmap_alloc_backend *entry; - if (!idmap_ctx) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - if ((version != SMB_IDMAP_INTERFACE_VERSION)) { DEBUG(0, ("Failed to register idmap alloc module.\n" "The module was compiled against " @@ -201,12 +182,12 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = talloc(idmap_ctx, struct idmap_alloc_backend); + entry = talloc(NULL, struct idmap_alloc_backend); if ( ! entry) { DEBUG(0,("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } - entry->name = talloc_strdup(idmap_ctx, name); + entry->name = talloc_strdup(entry, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -230,610 +211,313 @@ static int close_domain_destructor(struct idmap_domain *dom) return 0; } -/************************************************************************** - Shutdown. -**************************************************************************/ - -NTSTATUS idmap_close(void) +static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param, + char **pmodulename, char **pargs) { - /* close the alloc backend first before freeing idmap_ctx */ - if (idmap_alloc_ctx) { - idmap_alloc_ctx->methods->close_fn(); - idmap_alloc_ctx->methods = NULL; - } - alloc_backends = NULL; - - /* this talloc_free call will fire the talloc destructors - * that will free all active backends resources */ - TALLOC_FREE(idmap_ctx); - idmap_cache = NULL; - idmap_domains = NULL; - backends = NULL; - - return NT_STATUS_OK; -} + char *modulename; + char *args; -/**************************************************************************** - ****************************************************************************/ + if (strncmp(param, "idmap_", 6) == 0) { + param += 6; + DEBUG(1, ("idmap_init: idmap backend uses deprecated " + "'idmap_' prefix. Please replace 'idmap_%s' by " + "'%s'\n", param, param)); + } -NTSTATUS idmap_init_cache(void) -{ - /* Always initialize the cache. We'll have to delay initialization - of backends if we are offline */ + modulename = talloc_strdup(mem_ctx, param); + if (modulename == NULL) { + return false; + } - if ( idmap_ctx ) { - return NT_STATUS_OK; + args = strchr(modulename, ':'); + if (args == NULL) { + *pmodulename = modulename; + *pargs = NULL; + return true; } - if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) { - return NT_STATUS_NO_MEMORY; + *args = '\0'; + + args = talloc_strdup(mem_ctx, args+1); + if (args == NULL) { + TALLOC_FREE(modulename); + return false; } - return NT_STATUS_OK; + *pmodulename = modulename; + *pargs = args; + return true; } -/**************************************************************************** - ****************************************************************************/ - -static NTSTATUS idmap_init(void) +static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx, + const char *domainname, + const char *modulename, + const char *params) { - NTSTATUS ret; - static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL; - struct idmap_domain *dom; - char *compat_backend = NULL; - char *compat_params = NULL; - const char **dom_list = NULL; - const char *default_domain = NULL; - char *alloc_backend = NULL; - bool default_already_defined = False; - bool pri_dom_is_in_list = False; - int compat = 0; - int i; + struct idmap_domain *result; + NTSTATUS status; - ret = idmap_init_cache(); - if (!NT_STATUS_IS_OK(ret)) - return ret; - - if (NT_STATUS_IS_OK(idmap_init_status)) { - return NT_STATUS_OK; + result = talloc_zero(mem_ctx, struct idmap_domain); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - /* We can't reliably call intialization code here unless - we are online. But return NT_STATUS_OK so the upper - level code doesn't abort idmap lookups. */ - - if ( get_global_winbindd_state_offline() ) { - idmap_init_status = NT_STATUS_FILE_IS_OFFLINE; - return NT_STATUS_OK; + result->name = talloc_strdup(result, domainname); + if (result->name == NULL) { + DEBUG(0, ("talloc failed\n")); + goto fail; } - static_init_idmap; + result->methods = get_methods(backends, modulename); + if (result->methods == NULL) { + DEBUG(3, ("idmap backend %s not found\n", modulename)); - dom_list = lp_idmap_domains(); - - if ( lp_idmap_backend() ) { - const char **compat_list = lp_idmap_backend(); - char *p = NULL; - const char *q = NULL; - - if ( dom_list ) { - DEBUG(0, ("WARNING: idmap backend and idmap domains are" - " mutually exclusive!\n")); - DEBUGADD(0,("idmap backend option will be IGNORED!\n")); - } else { - compat = 1; - - compat_backend = talloc_strdup(idmap_ctx, *compat_list); - - /* strip any leading idmap_ prefix of */ - if (strncmp(*compat_list, "idmap_", 6) == 0 ) { - q = *compat_list += 6; - DEBUG(0, ("WARNING: idmap backend uses obsolete" - " and deprecated 'idmap_' prefix.\n" - "Please replace 'idmap_%s' by '%s' in" - " %s\n", q, q, get_dyn_CONFIGFILE())); - compat_backend = talloc_strdup(idmap_ctx, q); - } else { - compat_backend = talloc_strdup(idmap_ctx, - *compat_list); - } - - if (compat_backend == NULL ) { - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - /* separate the backend and module arguments */ - if ((p = strchr(compat_backend, ':')) != NULL) { - *p = '\0'; - compat_params = p + 1; - } + status = smb_probe_module("idmap", modulename); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not probe idmap module %s\n", + modulename)); + goto fail; } - } else if ( !dom_list ) { - /* Back compatible: without idmap domains and explicit - idmap backend. Taking default idmap backend: tdb */ - compat = 1; - compat_backend = talloc_strdup( idmap_ctx, "tdb"); - compat_params = compat_backend; + result->methods = get_methods(backends, modulename); } - - if ( ! dom_list) { - /* generate a list with our main domain */ - const char ** dl; - - dl = talloc_array(idmap_ctx, const char *, 2); - if (dl == NULL) { - ret = NT_STATUS_NO_MEMORY; - goto done; - } - dl[0] = talloc_strdup(dl, lp_workgroup()); - if (dl[0] == NULL) { - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - /* terminate */ - dl[1] = NULL; - - dom_list = dl; - default_domain = dl[0]; + if (result->methods == NULL) { + DEBUG(1, ("idmap backend %s not found\n", modulename)); + goto fail; } - /*************************** - * initialize idmap domains - */ - DEBUG(1, ("Initializing idmap domains\n")); - - for (i=0, num_domains=0; dom_list[i]; i++) { - const char *parm_backend; - char *config_option; - - /* ignore BUILTIN and local MACHINE domains */ - if (strequal(dom_list[i], "BUILTIN") - || strequal(dom_list[i], get_global_sam_name())) - { - DEBUG(0,("idmap_init: Ignoring domain %s\n", - dom_list[i])); - continue; - } - - if ((dom_list[i] != default_domain) && - strequal(dom_list[i], lp_workgroup())) { - pri_dom_is_in_list = True; - } - /* init domain */ - - dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); - IDMAP_CHECK_ALLOC(dom); - - dom->name = talloc_strdup(dom, dom_list[i]); - IDMAP_CHECK_ALLOC(dom->name); - - config_option = talloc_asprintf(dom, "idmap config %s", - dom->name); - IDMAP_CHECK_ALLOC(config_option); - - /* default or specific ? */ - - dom->default_domain = lp_parm_bool(-1, config_option, - "default", False); - - if (dom->default_domain || - (default_domain && strequal(dom_list[i], default_domain))) { - - /* make sure this is set even when we match - * default_domain */ - dom->default_domain = True; - - if (default_already_defined) { - DEBUG(1, ("ERROR: Multiple domains defined as" - " default!\n")); - ret = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - default_already_defined = True; - - } - - dom->readonly = lp_parm_bool(-1, config_option, - "readonly", False); - - /* find associated backend (default: tdb) */ - if (compat) { - parm_backend = talloc_strdup(idmap_ctx, compat_backend); - } else { - parm_backend = talloc_strdup(idmap_ctx, - lp_parm_const_string( - -1, config_option, - "backend", "tdb")); - } - IDMAP_CHECK_ALLOC(parm_backend); - - /* get the backend methods for this domain */ - dom->methods = get_methods(backends, parm_backend); - - if ( ! dom->methods) { - ret = smb_probe_module("idmap", parm_backend); - if (NT_STATUS_IS_OK(ret)) { - dom->methods = get_methods(backends, - parm_backend); - } - } - if ( ! dom->methods) { - DEBUG(0, ("ERROR: Could not get methods for " - "backend %s\n", parm_backend)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* check the set_mapping function exists otherwise mark the - * module as readonly */ - if ( ! dom->methods->set_mapping) { - DEBUG(5, ("Forcing to readonly, as this module can't" - " store arbitrary mappings.\n")); - dom->readonly = True; - } - - /* now that we have methods, - * set the destructor for this domain */ - talloc_set_destructor(dom, close_domain_destructor); + status = result->methods->init(result, params); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("idmap initialization returned %s\n", + nt_errstr(status))); + goto fail; + } - if (compat_params) { - dom->params = talloc_strdup(dom, compat_params); - IDMAP_CHECK_ALLOC(dom->params); - } else { - dom->params = NULL; - } + talloc_set_destructor(result, close_domain_destructor); - /* Finally instance a backend copy for this domain */ - ret = dom->methods->init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for backend " - "%s (domain %s), deferred!\n", - parm_backend, dom->name)); - } - idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, - struct idmap_domain *, i+1); - if ( ! idmap_domains) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - idmap_domains[num_domains] = dom; + return result; - /* save default domain position for future uses */ - if (dom->default_domain) { - def_dom_num = num_domains; - } +fail: + TALLOC_FREE(result); + return NULL; +} - /* Bump counter to next available slot */ +static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx) +{ + struct idmap_domain *result; + char *modulename; + char *params; - num_domains++; + DEBUG(10, ("idmap_init_default_domain: calling static_init_idmap\n")); - DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", - dom->name, parm_backend, - dom->default_domain?"":"not ", - dom->readonly?"":"not ")); + static_init_idmap; - talloc_free(config_option); + if (!parse_idmap_module(talloc_tos(), lp_idmap_backend(), &modulename, + ¶ms)) { + DEBUG(1, ("parse_idmap_module failed\n")); + return NULL; } - /* on DCs we need to add idmap_tdb as the default backend if compat is - * defined (when the old implicit configuration is used) - * This is not done in the previous loop a on member server we exclude - * the local domain. But on a DC the local domain is the only domain - * available therefore we are left with no default domain */ - if (((lp_server_role() == ROLE_DOMAIN_PDC) || - (lp_server_role() == ROLE_DOMAIN_BDC)) && - ((num_domains == 0) && (compat == 1))) { - - dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); - IDMAP_CHECK_ALLOC(dom); - - dom->name = talloc_strdup(dom, "__default__"); - IDMAP_CHECK_ALLOC(dom->name); - - dom->default_domain = True; - dom->readonly = False; - - /* get the backend methods for this domain */ - dom->methods = get_methods(backends, compat_backend); - - if ( ! dom->methods) { - ret = smb_probe_module("idmap", compat_backend); - if (NT_STATUS_IS_OK(ret)) { - dom->methods = get_methods(backends, - compat_backend); - } - } - if ( ! dom->methods) { - DEBUG(0, ("ERROR: Could not get methods for " - "backend %s\n", compat_backend)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* now that we have methods, - * set the destructor for this domain */ - talloc_set_destructor(dom, close_domain_destructor); + DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename)); - dom->params = talloc_strdup(dom, compat_params); - IDMAP_CHECK_ALLOC(dom->params); + result = idmap_init_domain(mem_ctx, "*", modulename, params); + if (result == NULL) { + goto fail; + } - /* Finally instance a backend copy for this domain */ - ret = dom->methods->init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for backend " - "%s (domain %s), deferred!\n", - compat_backend, dom->name)); - } - idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, - struct idmap_domain *, 2); - if ( ! idmap_domains) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - idmap_domains[num_domains] = dom; + TALLOC_FREE(modulename); + TALLOC_FREE(params); + return result; - def_dom_num = num_domains; +fail: + TALLOC_FREE(modulename); + TALLOC_FREE(params); + TALLOC_FREE(result); + return NULL; +} - /* Bump counter to next available slot */ +static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx, + const char *domname) +{ + struct idmap_domain *result = NULL; + char *config_option; + const char *backend; - num_domains++; + config_option = talloc_asprintf(talloc_tos(), "idmap config %s", + domname); + if (config_option == NULL) { + DEBUG(0, ("talloc failed\n")); + goto fail; + } - DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", - dom->name, compat_backend, - dom->default_domain?"":"not ", - dom->readonly?"":"not ")); + backend = lp_parm_const_string(-1, config_option, "backend", NULL); + if (backend == NULL) { + DEBUG(1, ("no backend defined for %s\n", config_option)); + goto fail; } - /* automatically add idmap_nss backend if needed */ - if ((lp_server_role() == ROLE_DOMAIN_MEMBER) && - ( ! pri_dom_is_in_list) && - lp_winbind_trusted_domains_only()) { + result = idmap_init_domain(mem_ctx, domname, backend, NULL); + if (result == NULL) { + goto fail; + } - dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); - IDMAP_CHECK_ALLOC(dom); + TALLOC_FREE(config_option); + return result; - dom->name = talloc_strdup(dom, lp_workgroup()); - IDMAP_CHECK_ALLOC(dom->name); +fail: + TALLOC_FREE(config_option); + TALLOC_FREE(result); + return NULL; +} - dom->default_domain = False; - dom->readonly = True; +static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx) +{ + if (passdb_idmap_domain != NULL) { + return passdb_idmap_domain; + } - /* get the backend methods for passdb */ - dom->methods = get_methods(backends, "nss"); + passdb_idmap_domain = idmap_init_domain(NULL, get_global_sam_name(), + "passdb", NULL); + if (passdb_idmap_domain == NULL) { + DEBUG(1, ("Could not init passdb idmap domain\n")); + } - /* (the nss module is always statically linked) */ - if ( ! dom->methods) { - DEBUG(0, ("ERROR: No methods for idmap_nss ?!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } + return passdb_idmap_domain; +} - /* now that we have methods, - * set the destructor for this domain */ - talloc_set_destructor(dom, close_domain_destructor); +static struct idmap_domain *idmap_find_domain(const char *domname) +{ + struct idmap_domain *result; + int i; - if (compat_params) { - dom->params = talloc_strdup(dom, compat_params); - IDMAP_CHECK_ALLOC(dom->params); - } else { - dom->params = NULL; - } + /* + * Always init the default domain, we can't go without one + */ + if (default_idmap_domain == NULL) { + default_idmap_domain = idmap_init_default_domain(NULL); + } + if (default_idmap_domain == NULL) { + return NULL; + } - /* Finally instance a backend copy for this domain */ - ret = dom->methods->init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Init. failed for idmap_nss ?!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } + if ((domname == NULL) || (domname[0] == '\0')) { + return default_idmap_domain; + } - idmap_domains = talloc_realloc(idmap_ctx, - idmap_domains, - struct idmap_domain *, - num_domains+1); - if ( ! idmap_domains) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; + for (i=0; iname, domname)) { + return idmap_domains[i]; } - idmap_domains[num_domains] = dom; + } - DEBUG(10, ("Domain %s - Backend nss - not default - readonly\n", - dom->name )); + if (idmap_domains == NULL) { + /* + * talloc context for all idmap domains + */ + idmap_domains = TALLOC_ARRAY(NULL, struct idmap_domain *, 1); + } - num_domains++; + if (idmap_domains == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - /**** automatically add idmap_passdb backend ****/ - dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); - IDMAP_CHECK_ALLOC(dom); + result = idmap_init_named_domain(idmap_domains, domname); + if (result == NULL) { + /* + * Could not init that domain -- try the default one + */ + return default_idmap_domain; + } - dom->name = talloc_strdup(dom, get_global_sam_name()); - IDMAP_CHECK_ALLOC(dom->name); + ADD_TO_ARRAY(idmap_domains, struct idmap_domain *, result, + &idmap_domains, &num_domains); + return result; +} - dom->default_domain = False; - dom->readonly = True; +void idmap_close(void) +{ + if (idmap_alloc_ctx) { + idmap_alloc_ctx->methods->close_fn(); + idmap_alloc_ctx->methods = NULL; + } + alloc_backends = NULL; + TALLOC_FREE(default_idmap_domain); + TALLOC_FREE(passdb_idmap_domain); + TALLOC_FREE(idmap_domains); + num_domains = 0; +} - /* get the backend methods for passdb */ - dom->methods = get_methods(backends, "passdb"); +static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx) +{ + const char *backend; + char *modulename, *params; + NTSTATUS ret = NT_STATUS_NO_MEMORY;; - /* (the passdb module is always statically linked) */ - if ( ! dom->methods) { - DEBUG(0, ("ERROR: No methods for idmap_passdb ?!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; + if (idmap_alloc_ctx != NULL) { + *ctx = idmap_alloc_ctx; + return NT_STATUS_OK; } - /* now that we have methods, set the destructor for this domain */ - talloc_set_destructor(dom, close_domain_destructor); - - if (compat_params) { - dom->params = talloc_strdup(dom, compat_params); - IDMAP_CHECK_ALLOC(dom->params); - } else { - dom->params = NULL; + idmap_alloc_ctx = talloc(NULL, struct idmap_alloc_context); + if (idmap_alloc_ctx == NULL) { + DEBUG(0, ("talloc failed\n")); + goto fail; } - /* Finally instance a backend copy for this domain */ - ret = dom->methods->init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Init. failed for idmap_passdb ?!\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; + backend = lp_idmap_alloc_backend(); + if ((backend == NULL) || (backend[0] == '\0')) { + backend = lp_idmap_backend(); } - idmap_domains = talloc_realloc(idmap_ctx, - idmap_domains, - struct idmap_domain *, - num_domains+1); - if ( ! idmap_domains) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; + if (backend == NULL) { + DEBUG(3, ("no idmap alloc backend defined\n")); + ret = NT_STATUS_INVALID_PARAMETER; + goto fail; } - idmap_domains[num_domains] = dom; - - /* needed to handle special BUILTIN and wellknown SIDs cases */ - pdb_dom_num = num_domains; - - DEBUG(10, ("Domain %s - Backend passdb - not default - readonly\n", - dom->name)); - - num_domains++; - /**** finished adding idmap_passdb backend ****/ - - /* sort domains so that the default is the last one */ - /* don't sort if no default domain defined */ - if (def_dom_num != -1 && def_dom_num != num_domains-1) { - /* default is not last, move it */ - struct idmap_domain *tmp; - - if (pdb_dom_num > def_dom_num) { - pdb_dom_num --; - - } else if (pdb_dom_num == def_dom_num) { /* ?? */ - pdb_dom_num = num_domains - 1; - } - - tmp = idmap_domains[def_dom_num]; - for (i = def_dom_num; i < num_domains-1; i++) { - idmap_domains[i] = idmap_domains[i+1]; - } - idmap_domains[i] = tmp; - def_dom_num = i; + if (!parse_idmap_module(idmap_alloc_ctx, backend, &modulename, + ¶ms)) { + DEBUG(1, ("parse_idmap_module %s failed\n", backend)); + goto fail; } + idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, + modulename); - /* Initialize alloc module */ - - DEBUG(3, ("Initializing idmap alloc module\n")); - - alloc_backend = NULL; - if (compat) { - alloc_backend = talloc_strdup(idmap_ctx, compat_backend); - } else { - char *ab = lp_idmap_alloc_backend(); - - if (ab && (ab[0] != '\0')) { - alloc_backend = talloc_strdup(idmap_ctx, - lp_idmap_alloc_backend()); + if (idmap_alloc_ctx->methods == NULL) { + ret = smb_probe_module("idmap", modulename); + if (NT_STATUS_IS_OK(ret)) { + idmap_alloc_ctx->methods = + get_alloc_methods(alloc_backends, + modulename); } } - if ( alloc_backend ) { - - idmap_alloc_ctx = TALLOC_ZERO_P(idmap_ctx, - struct idmap_alloc_context); - IDMAP_CHECK_ALLOC(idmap_alloc_ctx); - - idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, - alloc_backend); - if ( ! idmap_alloc_ctx->methods) { - ret = smb_probe_module("idmap", alloc_backend); - if (NT_STATUS_IS_OK(ret)) { - idmap_alloc_ctx->methods = - get_alloc_methods(alloc_backends, - alloc_backend); - } - } - if (idmap_alloc_ctx->methods) { - - if (compat_params) { - idmap_alloc_ctx->params = - talloc_strdup(idmap_alloc_ctx, - compat_params); - IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params); - } else { - idmap_alloc_ctx->params = NULL; - } - - ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for " - "alloc backend %s, deferred!\n", - alloc_backend)); - } else { - idmap_alloc_ctx->initialized = True; - } - } else { - DEBUG(2, ("idmap_init: Unable to get methods for " - "alloc backend %s\n", - alloc_backend)); - /* certain compat backends are just readonly */ - if ( compat ) { - TALLOC_FREE(idmap_alloc_ctx); - ret = NT_STATUS_OK; - } else { - ret = NT_STATUS_UNSUCCESSFUL; - } - } + if (idmap_alloc_ctx->methods == NULL) { + DEBUG(1, ("could not find idmap alloc module %s\n", backend)); + ret = NT_STATUS_INVALID_PARAMETER; + goto fail; } - /* cleanup temporary strings */ - TALLOC_FREE( compat_backend ); - - idmap_init_status = NT_STATUS_OK; - - return ret; + ret = idmap_alloc_ctx->methods->init(params); -done: - DEBUG(0, ("Aborting IDMAP Initialization ...\n")); - idmap_close(); - - return ret; -} - -static NTSTATUS idmap_alloc_init(void) -{ - NTSTATUS ret; - - if (! NT_STATUS_IS_OK(ret = idmap_init())) { - return ret; - } - - if ( ! idmap_alloc_ctx) { - return NT_STATUS_NOT_SUPPORTED; + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("ERROR: Initialization failed for alloc " + "backend, deferred!\n")); + goto fail; } - if ( ! idmap_alloc_ctx->initialized) { - ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for alloc " - "backend, deferred!\n")); - return ret; - } else { - idmap_alloc_ctx->initialized = True; - } - } + TALLOC_FREE(modulename); + TALLOC_FREE(params); + *ctx = idmap_alloc_ctx; return NT_STATUS_OK; + +fail: + TALLOC_FREE(idmap_alloc_ctx); + return ret; } /************************************************************************** @@ -842,343 +526,180 @@ static NTSTATUS idmap_alloc_init(void) NTSTATUS idmap_allocate_uid(struct unixid *id) { + struct idmap_alloc_context *ctx; NTSTATUS ret; - if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) { return ret; } id->type = ID_TYPE_UID; - return idmap_alloc_ctx->methods->allocate_id(id); + return ctx->methods->allocate_id(id); } NTSTATUS idmap_allocate_gid(struct unixid *id) { + struct idmap_alloc_context *ctx; NTSTATUS ret; - if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) { return ret; } id->type = ID_TYPE_GID; - return idmap_alloc_ctx->methods->allocate_id(id); + return ctx->methods->allocate_id(id); } NTSTATUS idmap_set_uid_hwm(struct unixid *id) { + struct idmap_alloc_context *ctx; NTSTATUS ret; - if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) { return ret; } id->type = ID_TYPE_UID; - return idmap_alloc_ctx->methods->set_id_hwm(id); + return ctx->methods->set_id_hwm(id); } NTSTATUS idmap_set_gid_hwm(struct unixid *id) { + struct idmap_alloc_context *ctx; NTSTATUS ret; - if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { + if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) { return ret; } id->type = ID_TYPE_GID; - return idmap_alloc_ctx->methods->set_id_hwm(id); -} - -/****************************************************************************** - Lookup an idmap_domain give a full user or group SID - ******************************************************************************/ - -static struct idmap_domain* find_idmap_domain_from_sid( DOM_SID *account_sid ) -{ - DOM_SID domain_sid; - uint32 rid; - struct winbindd_domain *domain = NULL; - int i; - - /* 1. Handle BUILTIN or Special SIDs and prevent them from - falling into the default domain space (if we have a - configured passdb backend. */ - - if ( (pdb_dom_num != -1) && - (sid_check_is_in_builtin(account_sid) || - sid_check_is_in_wellknown_domain(account_sid) || - sid_check_is_in_unix_groups(account_sid) || - sid_check_is_in_unix_users(account_sid)) ) - { - return idmap_domains[pdb_dom_num]; - } - - /* 2. Lookup the winbindd_domain from the account_sid */ - - sid_copy( &domain_sid, account_sid ); - sid_split_rid( &domain_sid, &rid ); - domain = find_domain_from_sid_noinit( &domain_sid ); - - for (i = 0; domain && i < num_domains; i++) { - if ( strequal( idmap_domains[i]->name, domain->name ) ) { - return idmap_domains[i]; - } - } - - /* 3. Fall back to the default domain */ - - if ( def_dom_num != -1 ) { - return idmap_domains[def_dom_num]; - } - - return NULL; + return ctx->methods->set_id_hwm(id); } -/****************************************************************************** - Lookup an index given an idmap_domain pointer - ******************************************************************************/ - -static uint32 find_idmap_domain_index( struct idmap_domain *id_domain) -{ - int i; - - for (i = 0; i < num_domains; i++) { - if ( idmap_domains[i] == id_domain ) - return i; - } - - return -1; -} - - -/********************************************************* - Check if creating a mapping is permitted for the domain -*********************************************************/ - -static NTSTATUS idmap_can_map(const struct id_map *map, - struct idmap_domain **ret_dom) +NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type, + struct unixid *pxid) { + struct dom_sid sid; struct idmap_domain *dom; + struct id_map map; + NTSTATUS status; - /* Check we do not create mappings for our own local domain, - * or BUILTIN or special SIDs */ - if ((sid_compare_domain(map->sid, get_global_sam_sid()) == 0) || - sid_check_is_in_builtin(map->sid) || - sid_check_is_in_wellknown_domain(map->sid) || - sid_check_is_in_unix_users(map->sid) || - sid_check_is_in_unix_groups(map->sid) ) - { - DEBUG(10, ("We are not supposed to create mappings for our own " - "domains (local, builtin, specials)\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - /* Special check for trusted domain only = Yes */ - if (lp_winbind_trusted_domains_only()) { - struct winbindd_domain *wdom = find_our_domain(); - if (wdom && (sid_compare_domain(map->sid, &wdom->sid) == 0)) { - DEBUG(10, ("We are not supposed to create mappings for " - "our primary domain when is True\n")); - DEBUGADD(10, ("Leave [%s] unmapped\n", - sid_string_dbg(map->sid))); - return NT_STATUS_UNSUCCESSFUL; - } - } - - if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) { - /* huh, couldn't find a suitable domain, - * let's just leave it unmapped */ - DEBUG(10, ("Could not find idmap backend for SID %s\n", - sid_string_dbg(map->sid))); - return NT_STATUS_NO_SUCH_DOMAIN; + dom = idmap_find_domain(NULL); + if (dom == NULL) { + DEBUG(3, ("no default domain, no place to write\n")); + return NT_STATUS_ACCESS_DENIED; } - - if (dom->readonly) { - /* ouch the domain is read only, - * let's just leave it unmapped */ - DEBUG(10, ("idmap backend for SID %s is READONLY!\n", - sid_string_dbg(map->sid))); - return NT_STATUS_UNSUCCESSFUL; + if (dom->methods->set_mapping == NULL) { + DEBUG(3, ("default domain not writable\n")); + return NT_STATUS_MEDIA_WRITE_PROTECTED; } - *ret_dom = dom; - return NT_STATUS_OK; -} - -static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map) -{ - NTSTATUS ret; - struct idmap_domain *dom; + sid_copy(&sid, psid); + map.sid = &sid; + map.xid.type = type; - /* If we are offline we cannot lookup SIDs, deny mapping */ - if (idmap_is_offline()) { - return NT_STATUS_FILE_IS_OFFLINE; - } - - ret = idmap_can_map(map, &dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return NT_STATUS_NONE_MAPPED; - } - - /* check if this is a valid SID and then map it */ - switch (map->xid.type) { + switch (type) { case ID_TYPE_UID: - ret = idmap_allocate_uid(&map->xid); - if ( ! NT_STATUS_IS_OK(ret)) { - /* can't allocate id, let's just leave it unmapped */ - DEBUG(2, ("uid allocation failed! " - "Can't create mapping\n")); - return NT_STATUS_NONE_MAPPED; - } + status = idmap_allocate_uid(&map.xid); break; case ID_TYPE_GID: - ret = idmap_allocate_gid(&map->xid); - if ( ! NT_STATUS_IS_OK(ret)) { - /* can't allocate id, let's just leave it unmapped */ - DEBUG(2, ("gid allocation failed! " - "Can't create mapping\n")); - return NT_STATUS_NONE_MAPPED; - } + status = idmap_allocate_gid(&map.xid); break; default: - /* invalid sid, let's just leave it unmapped */ - DEBUG(3,("idmap_new_mapping: Refusing to create a " - "mapping for an unspecified ID type.\n")); - return NT_STATUS_NONE_MAPPED; + status = NT_STATUS_INVALID_PARAMETER; + break; } - /* ok, got a new id, let's set a mapping */ - map->status = ID_MAPPED; - - DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", - sid_string_dbg(map->sid), - (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", - (unsigned long)map->xid.id)); - ret = dom->methods->set_mapping(dom, map); - - if ( ! NT_STATUS_IS_OK(ret)) { - /* something wrong here :-( */ - DEBUG(2, ("Failed to commit mapping\n!")); - - /* TODO: would it make sense to have an "unalloc_id function?" */ - - return NT_STATUS_NONE_MAPPED; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(status))); + return status; } - return NT_STATUS_OK; -} + map.status = ID_MAPPED; -static NTSTATUS idmap_backends_set_mapping(const struct id_map *map) -{ - struct idmap_domain *dom; - NTSTATUS ret; + DEBUG(10, ("Setting mapping: %s <-> %s %lu\n", + sid_string_dbg(map.sid), + (map.xid.type == ID_TYPE_UID) ? "UID" : "GID", + (unsigned long)map.xid.id)); - DEBUG(10, ("Setting mapping %s <-> %s %lu\n", - sid_string_dbg(map->sid), - (map->xid.type == ID_TYPE_UID) ? "UID" : "GID", - (unsigned long)map->xid.id)); + status = dom->methods->set_mapping(dom, &map); - ret = idmap_can_map(map, &dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not store the new mapping: %s\n", + nt_errstr(status))); + return status; } - DEBUG(10,("set_mapping for domain %s\n", dom->name )); + *pxid = map.xid; - return dom->methods->set_mapping(dom, map); + return NT_STATUS_OK; } -NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id) +NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) { + struct idmap_domain *dom; struct id_map *maps[2]; - int i; maps[0] = id; maps[1] = NULL; - for (i = num_domains-1; i>=0; i--) { - struct idmap_domain *dom = idmap_domains[i]; - NTSTATUS status; + /* + * Always give passdb a chance first + */ - DEBUG(10, ("Query sids from domain %s\n", dom->name)); + dom = idmap_init_passdb_domain(NULL); + if ((dom != NULL) + && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))) { + return NT_STATUS_OK; + } - status = dom->methods->unixids_to_sids(dom, maps); - if (NT_STATUS_IS_OK(status)) { - return NT_STATUS_OK; - } + dom = idmap_find_domain(domname); + if (dom == NULL) { + return NT_STATUS_NONE_MAPPED; } - return NT_STATUS_NONE_MAPPED; + return dom->methods->unixids_to_sids(dom, maps); } -NTSTATUS idmap_backends_sid_to_unixid(struct id_map *id) +NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id) { struct idmap_domain *dom; struct id_map *maps[2]; - dom = find_idmap_domain_from_sid(id->sid); - if (dom == NULL) { - return NT_STATUS_NONE_MAPPED; - } - maps[0] = id; maps[1] = NULL; - return dom->methods->sids_to_unixids(dom, maps); -} - -NTSTATUS idmap_set_mapping(const struct id_map *id) -{ - TALLOC_CTX *ctx; - NTSTATUS ret; - - if (! NT_STATUS_IS_OK(ret = idmap_init())) { - return ret; - } + if (sid_check_is_in_builtin(id->sid) + || (sid_check_is_in_our_domain(id->sid))) { - /* sanity checks */ - if ((id->sid == NULL) || (id->status != ID_MAPPED)) { - DEBUG(1, ("NULL SID or unmapped entry\n")); - return NT_STATUS_INVALID_PARAMETER; + dom = idmap_init_passdb_domain(NULL); + if (dom == NULL) { + return NT_STATUS_NONE_MAPPED; + } + return dom->methods->sids_to_unixids(dom, maps); } - /* TODO: check uid/gid range ? */ - - ctx = talloc_named_const(NULL, 0, "idmap_set_mapping ctx"); - if ( ! ctx) { - DEBUG(1, ("failed to allocate talloc context, OOM?\n")); - return NT_STATUS_NO_MEMORY; + dom = idmap_find_domain(domain); + if (dom == NULL) { + return NT_STATUS_NONE_MAPPED; } - /* set the new mapping */ - ret = idmap_backends_set_mapping(id); - IDMAP_CHECK_RET(ret); - -done: - talloc_free(ctx); - return ret; + return dom->methods->sids_to_unixids(dom, maps); } -char *idmap_fetch_secret(const char *backend, bool alloc, - const char *domain, const char *identity) +NTSTATUS idmap_set_mapping(const struct id_map *map) { - char *tmp, *ret; - int r; + struct idmap_domain *dom; - if (alloc) { - r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend); - } else { - r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain); + dom = idmap_find_domain(NULL); + if (dom == NULL) { + DEBUG(3, ("no default domain, no place to write\n")); + return NT_STATUS_ACCESS_DENIED; + } + if (dom->methods->set_mapping == NULL) { + DEBUG(3, ("default domain not writable\n")); + return NT_STATUS_MEDIA_WRITE_PROTECTED; } - if (r < 0) - return NULL; - - strupper_m(tmp); /* make sure the key is case insensitive */ - ret = secrets_fetch_generic(tmp, identity); - - SAFE_FREE(tmp); - - return ret; + return dom->methods->set_mapping(dom, map); } - diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 0d7c068844..9fefb1bba7 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -160,7 +160,8 @@ static ADS_STRUCT *ad_idmap_cached_connection(void) /************************************************************************ ***********************************************************************/ -static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom) +static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, + const char *params) { struct idmap_ad_context *ctx; char *config_option; @@ -206,7 +207,6 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom) } dom->private_data = ctx; - dom->initialized = True; talloc_free(config_option); @@ -277,14 +277,6 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map return NT_STATUS_FILE_IS_OFFLINE; } - /* Initilization my have been deferred because we were offline */ - if ( ! dom->initialized) { - ret = idmap_ad_initialize(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); if ( (memctx = talloc_new(ctx)) == NULL ) { @@ -496,14 +488,6 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map return NT_STATUS_FILE_IS_OFFLINE; } - /* Initilization my have been deferred because we were offline */ - if ( ! dom->initialized) { - ret = idmap_ad_initialize(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); if ( (memctx = talloc_new(ctx)) == NULL ) { diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 1e82314440..b818d0dafb 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -59,7 +59,7 @@ bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) char *key; char *value; time_t timeout; - bool ret; + bool ret = true; key = talloc_asprintf(talloc_tos(), "IDMAP/UID2SID/%d", (int)uid); if (key == NULL) { @@ -71,7 +71,9 @@ bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) return false; } ZERO_STRUCTP(sid); - ret = string_to_sid(sid, value); + if (value[0] != '-') { + ret = string_to_sid(sid, value); + } SAFE_FREE(value); if (ret) { *expired = (timeout <= time(NULL)); @@ -96,10 +98,15 @@ void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) } if (uid != -1) { fstr_sprintf(key, "IDMAP/UID2SID/%d", (int)uid); - sid_to_fstring(value, sid); - timeout = is_null_sid(sid) - ? lp_idmap_negative_cache_time() - : lp_idmap_cache_time(); + if (is_null_sid(sid)) { + /* negative uid mapping */ + fstrcpy(value, "-"); + timeout = lp_idmap_negative_cache_time(); + } + else { + sid_to_fstring(value, sid); + timeout = lp_idmap_cache_time(); + } gencache_set(key, value, now + timeout); } } @@ -140,7 +147,7 @@ bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) char *key; char *value; time_t timeout; - bool ret; + bool ret = true; key = talloc_asprintf(talloc_tos(), "IDMAP/GID2SID/%d", (int)gid); if (key == NULL) { @@ -152,7 +159,9 @@ bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) return false; } ZERO_STRUCTP(sid); - ret = string_to_sid(sid, value); + if (value[0] != '-') { + ret = string_to_sid(sid, value); + } SAFE_FREE(value); if (ret) { *expired = (timeout <= time(NULL)); @@ -177,10 +186,15 @@ void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid) } if (gid != -1) { fstr_sprintf(key, "IDMAP/GID2SID/%d", (int)gid); - sid_to_fstring(value, sid); - timeout = is_null_sid(sid) - ? lp_idmap_negative_cache_time() - : lp_idmap_cache_time(); + if (is_null_sid(sid)) { + /* negative gid mapping */ + fstrcpy(value, "-"); + timeout = lp_idmap_negative_cache_time(); + } + else { + sid_to_fstring(value, sid); + timeout = lp_idmap_cache_time(); + } gencache_set(key, value, now + timeout); } } diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index fa80fae5d8..64b176389e 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -33,6 +33,29 @@ #include "smbldap.h" +static char *idmap_fetch_secret(const char *backend, bool alloc, + const char *domain, const char *identity) +{ + char *tmp, *ret; + int r; + + if (alloc) { + r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend); + } else { + r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain); + } + + if (r < 0) + return NULL; + + strupper_m(tmp); /* make sure the key is case insensitive */ + ret = secrets_fetch_generic(tmp, identity); + + SAFE_FREE(tmp); + + return ret; +} + struct idmap_ldap_context { struct smbldap_state *smbldap_state; char *url; @@ -760,7 +783,8 @@ static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx) Initialise idmap database. ********************************/ -static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) +static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, + const char *params) { NTSTATUS ret; struct idmap_ldap_context *ctx = NULL; @@ -798,9 +822,9 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) } } - if (dom->params && *(dom->params)) { + if (params != NULL) { /* assume location is the only parameter */ - ctx->url = talloc_strdup(ctx, dom->params); + ctx->url = talloc_strdup(ctx, params); } else { tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL); @@ -848,7 +872,6 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) talloc_set_destructor(ctx, idmap_ldap_close_destructor); dom->private_data = ctx; - dom->initialized = True; talloc_free(config_option); return NT_STATUS_OK; @@ -909,14 +932,6 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, return NT_STATUS_FILE_IS_OFFLINE; } - /* Initilization my have been deferred because we were offline */ - if ( ! dom->initialized) { - ret = idmap_ldap_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); memctx = talloc_new(ctx); @@ -1138,14 +1153,6 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, return NT_STATUS_FILE_IS_OFFLINE; } - /* Initilization my have been deferred because we were offline */ - if ( ! dom->initialized) { - ret = idmap_ldap_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); memctx = talloc_new(ctx); @@ -1350,14 +1357,6 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, return NT_STATUS_FILE_IS_OFFLINE; } - /* Initilization my have been deferred because we were offline */ - if ( ! dom->initialized) { - ret = idmap_ldap_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); switch(map->xid.type) { diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index e4acd9ce65..156fdc7cc9 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -29,9 +29,9 @@ Initialise idmap database. *****************************/ -static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom) +static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom, + const char *params) { - dom->initialized = True; return NT_STATUS_OK; } @@ -44,10 +44,6 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma TALLOC_CTX *ctx; int i; - if (! dom->initialized) { - return NT_STATUS_UNSUCCESSFUL; - } - ctx = talloc_new(dom); if ( ! ctx) { DEBUG(0, ("Out of memory!\n")); @@ -134,10 +130,6 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma TALLOC_CTX *ctx; int i; - if (! dom->initialized) { - return NT_STATUS_UNSUCCESSFUL; - } - ctx = talloc_new(dom); if ( ! ctx) { DEBUG(0, ("Out of memory!\n")); diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c index 17afd71ab8..4dcf74416c 100644 --- a/source3/winbindd/idmap_passdb.c +++ b/source3/winbindd/idmap_passdb.c @@ -28,9 +28,8 @@ Initialise idmap database. *****************************/ -static NTSTATUS idmap_pdb_init(struct idmap_domain *dom) +static NTSTATUS idmap_pdb_init(struct idmap_domain *dom, const char *params) { - dom->initialized = True; return NT_STATUS_OK; } @@ -42,10 +41,6 @@ static NTSTATUS idmap_pdb_unixids_to_sids(struct idmap_domain *dom, struct id_ma { int i; - if (! dom->initialized) { - return NT_STATUS_UNSUCCESSFUL; - } - for (i = 0; ids[i]; i++) { /* unmapped by default */ @@ -78,10 +73,6 @@ static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma { int i; - if (! dom->initialized) { - return NT_STATUS_UNSUCCESSFUL; - } - for (i = 0; ids[i]; i++) { enum lsa_SidType type; union unid_t id; diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c index f1cd77853c..9d1898708c 100644 --- a/source3/winbindd/idmap_rid.c +++ b/source3/winbindd/idmap_rid.c @@ -36,7 +36,8 @@ struct idmap_rid_context { we support multiple domains in the new idmap *****************************************************************************/ -static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom) +static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom, + const char *params) { NTSTATUS ret; struct idmap_rid_context *ctx; @@ -95,7 +96,6 @@ static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom) ctx->domain_name = talloc_strdup( ctx, dom->name ); dom->private_data = ctx; - dom->initialized = True; talloc_free(config_option); return NT_STATUS_OK; @@ -171,14 +171,6 @@ static NTSTATUS idmap_rid_unixids_to_sids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initilization my have been deferred because of an error, retry or fail */ - if ( ! dom->initialized) { - ret = idmap_rid_initialize(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context); ctx = talloc_new(dom); @@ -213,14 +205,6 @@ static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* Initilization my have been deferred because of an error, retry or fail */ - if ( ! dom->initialized) { - ret = idmap_rid_initialize(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context); ctx = talloc_new(dom); diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index e5f605361b..3f6cccd35a 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -585,7 +585,7 @@ struct idmap_tdb_context { Initialise idmap database. *****************************/ -static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom) +static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) { NTSTATUS ret; struct idmap_tdb_context *ctx; @@ -619,7 +619,6 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom) } dom->private_data = ctx; - dom->initialized = True; talloc_free(config_option); return NT_STATUS_OK; @@ -774,14 +773,6 @@ static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); for (i = 0; ids[i]; i++) { @@ -820,14 +811,6 @@ static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma NTSTATUS ret; int i; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); for (i = 0; ids[i]; i++) { @@ -868,14 +851,6 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_ char *ksidstr, *kidstr; fstring tmp; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - if (!map || !map->sid) { return NT_STATUS_INVALID_PARAMETER; } @@ -983,14 +958,6 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct char *ksidstr, *kidstr; fstring tmp; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - if (!map || !map->sid) { return NT_STATUS_INVALID_PARAMETER; } @@ -1171,14 +1138,6 @@ static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **ma struct dump_data *data; NTSTATUS ret = NT_STATUS_OK; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); data = TALLOC_ZERO_P(ctx, struct dump_data); @@ -1229,6 +1188,8 @@ NTSTATUS idmap_tdb_init(void) { NTSTATUS ret; + DEBUG(10, ("calling idmap_tdb_init\n")); + /* FIXME: bad hack to actually register also the alloc_tdb module without changining configure.in */ ret = idmap_alloc_tdb_init(); if (! NT_STATUS_IS_OK(ret)) { diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index ab89e615f7..d30b6459fb 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -431,7 +431,8 @@ static NTSTATUS tdb2_delete_bystring(const char *keystr) /* Initialise idmap database. */ -static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom) +static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, + const char *params) { NTSTATUS ret; struct idmap_tdb2_context *ctx; @@ -464,7 +465,6 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom) } dom->private_data = ctx; - dom->initialized = True; talloc_free(config_option); return NT_STATUS_OK; @@ -725,14 +725,6 @@ static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_m NTSTATUS ret; int i; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb2_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); for (i = 0; ids[i]; i++) { @@ -770,14 +762,6 @@ static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_m NTSTATUS ret; int i; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb2_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context); for (i = 0; ids[i]; i++) { @@ -819,14 +803,6 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id struct db_record *update_lock = NULL; struct db_record *rec = NULL; - /* make sure we initialized */ - if ( ! dom->initialized) { - ret = idmap_tdb2_db_init(dom); - if ( ! NT_STATUS_IS_OK(ret)) { - return ret; - } - } - if (!map || !map->sid) { return NT_STATUS_INVALID_PARAMETER; } diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 31b9895224..04d12944e2 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -27,28 +27,50 @@ If mapping is not possible returns an error. *****************************************************************/ -NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) +NTSTATUS idmap_uid_to_sid(const char *domname, DOM_SID *sid, uid_t uid) { NTSTATUS ret; struct id_map map; + bool expired; DEBUG(10,("uid = [%lu]\n", (unsigned long)uid)); + if (idmap_cache_find_uid2sid(uid, sid, &expired)) { + DEBUG(10, ("idmap_cache_find_uid2sid found %d%s\n", uid, + expired ? " (expired)": "")); + if (expired && idmap_is_online()) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (is_null_sid(sid)) { + DEBUG(10, ("Returning negative cache entry\n")); + return NT_STATUS_NONE_MAPPED; + } + DEBUG(10, ("Returning positive cache entry\n")); + return NT_STATUS_OK; + } + +backend: map.sid = sid; map.xid.type = ID_TYPE_UID; map.xid.id = uid; - ret = idmap_backends_unixid_to_sid(&map); + ret = idmap_backends_unixid_to_sid(domname, &map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid)); return ret; } if (map.status != ID_MAPPED) { + struct dom_sid null_sid; + ZERO_STRUCT(null_sid); + idmap_cache_set_sid2uid(&null_sid, uid); DEBUG(10, ("uid [%lu] not mapped\n", (unsigned long)uid)); return NT_STATUS_NONE_MAPPED; } + idmap_cache_set_sid2uid(sid, uid); + return NT_STATUS_OK; } @@ -57,28 +79,50 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) If mapping is not possible returns an error. *****************************************************************/ -NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) +NTSTATUS idmap_gid_to_sid(const char *domname, DOM_SID *sid, gid_t gid) { NTSTATUS ret; struct id_map map; + bool expired; DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); + if (idmap_cache_find_uid2sid(gid, sid, &expired)) { + DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n", gid, + expired ? " (expired)": "")); + if (expired && idmap_is_online()) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if (is_null_sid(sid)) { + DEBUG(10, ("Returning negative cache entry\n")); + return NT_STATUS_NONE_MAPPED; + } + DEBUG(10, ("Returning positive cache entry\n")); + return NT_STATUS_OK; + } + +backend: map.sid = sid; map.xid.type = ID_TYPE_GID; map.xid.id = gid; - ret = idmap_backends_unixid_to_sid(&map); + ret = idmap_backends_unixid_to_sid(domname, &map); if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid)); return ret; } if (map.status != ID_MAPPED) { + struct dom_sid null_sid; + ZERO_STRUCT(null_sid); + idmap_cache_set_sid2uid(&null_sid, gid); DEBUG(10, ("gid [%lu] not mapped\n", (unsigned long)gid)); return NT_STATUS_NONE_MAPPED; } + idmap_cache_set_sid2uid(sid, gid); + return NT_STATUS_OK; } @@ -87,34 +131,61 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) If mapping is not possible or SID maps to a GID returns an error. *****************************************************************/ -NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) +NTSTATUS idmap_sid_to_uid(const char *dom_name, DOM_SID *sid, uid_t *uid) { NTSTATUS ret; struct id_map map; + bool expired; DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid))); + if (idmap_cache_find_sid2uid(sid, uid, &expired)) { + DEBUG(10, ("idmap_cache_find_sid2uid found %d%s\n", + (int)(*uid), expired ? " (expired)": "")); + if (expired && idmap_is_online()) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if ((*uid) == -1) { + DEBUG(10, ("Returning negative cache entry\n")); + return NT_STATUS_NONE_MAPPED; + } + DEBUG(10, ("Returning positive cache entry\n")); + return NT_STATUS_OK; + } + +backend: map.sid = sid; map.xid.type = ID_TYPE_UID; - ret = idmap_backends_sid_to_unixid(&map); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(10, ("error mapping sid [%s] to uid\n", - sid_string_dbg(sid))); - return ret; + ret = idmap_backends_sid_to_unixid(dom_name, &map); + + if (NT_STATUS_IS_OK(ret) && (map.status == ID_MAPPED)) { + if (map.xid.type != ID_TYPE_UID) { + DEBUG(10, ("sid [%s] not mapped to a uid " + "[%u,%u,%u]\n", + sid_string_dbg(sid), + map.status, + map.xid.type, + map.xid.id)); + idmap_cache_set_sid2uid(sid, -1); + return NT_STATUS_NONE_MAPPED; + } + goto done; } - if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_UID)) { - DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n", - sid_string_dbg(sid), - map.status, - map.xid.type, - map.xid.id)); - return NT_STATUS_NONE_MAPPED; - } + ret = idmap_new_mapping(sid, ID_TYPE_UID, &map.xid); - *uid = map.xid.id; + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("idmap_new_mapping failed: %s\n", + nt_errstr(ret))); + idmap_cache_set_sid2uid(sid, -1); + return ret; + } +done: + *uid = (uid_t)map.xid.id; + idmap_cache_set_sid2uid(sid, *uid); return NT_STATUS_OK; } @@ -123,32 +194,59 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) If mapping is not possible or SID maps to a UID returns an error. *****************************************************************/ -NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) +NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid) { NTSTATUS ret; struct id_map map; + bool expired; DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid))); + if (idmap_cache_find_sid2gid(sid, gid, &expired)) { + DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n", + (int)(*gid), expired ? " (expired)": "")); + if (expired && idmap_is_online()) { + DEBUG(10, ("revalidating expired entry\n")); + goto backend; + } + if ((*gid) == -1) { + DEBUG(10, ("Returning negative cache entry\n")); + return NT_STATUS_NONE_MAPPED; + } + DEBUG(10, ("Returning positive cache entry\n")); + return NT_STATUS_OK; + } + +backend: map.sid = sid; map.xid.type = ID_TYPE_GID; - ret = idmap_backends_sid_to_unixid(&map); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(10, ("error mapping sid [%s] to gid\n", - sid_string_dbg(sid))); - return ret; + ret = idmap_backends_sid_to_unixid(domname, &map); + if (NT_STATUS_IS_OK(ret) && (map.status == ID_MAPPED)) { + if (map.xid.type != ID_TYPE_GID) { + DEBUG(10, ("sid [%s] not mapped to a gid " + "[%u,%u,%u]\n", + sid_string_dbg(sid), + map.status, + map.xid.type, + map.xid.id)); + idmap_cache_set_sid2gid(sid, -1); + return NT_STATUS_NONE_MAPPED; + } + goto done; } - if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) { - DEBUG(10, ("sid [%s] not mapped to a gid [%u,%u]\n", - sid_string_dbg(sid), - map.status, - map.xid.type)); - return NT_STATUS_NONE_MAPPED; + ret = idmap_new_mapping(sid, ID_TYPE_GID, &map.xid); + + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(10, ("idmap_new_mapping failed: %s\n", + nt_errstr(ret))); + idmap_cache_set_sid2gid(sid, -1); + return ret; } +done: *gid = map.xid.id; - + idmap_cache_set_sid2gid(sid, *gid); return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 08cf8ba00a..ec20d8c195 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1144,12 +1144,6 @@ int main(int argc, char **argv, char **envp) namecache_enable(); - /* Winbind daemon initialisation */ - - if ( ! NT_STATUS_IS_OK(idmap_init_cache()) ) { - DEBUG(1, ("Could not init idmap cache!\n")); - } - /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index f6f269ee6d..fe0c076209 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -196,6 +196,13 @@ struct winbindd_domain { void *private_data; + /* + * idmap config settings, used to tell the idmap child which + * special domain config to use for a mapping + */ + bool have_idmap_config; + uint32_t id_range_low, id_range_high; + /* A working DC */ fstring dcname; struct sockaddr_storage dcaddr; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index f2be6d692c..1e8325f983 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1033,6 +1033,8 @@ static bool fork_domain_child(struct winbindd_child *child) /* Child */ + DEBUG(10, ("Child process %d\n", (int)sys_getpid())); + /* Stop zombies in children */ CatchChild(); diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 69e3a6a555..21ee8951b5 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -231,7 +231,8 @@ static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx, if (sys_getpeereid(state->sock, &ret_uid)==0) { /* We know who's asking - look up their SID if it's one we've mapped before. */ - status = idmap_uid_to_sid(&querying_user_sid, ret_uid); + status = idmap_uid_to_sid(domain->name, + &querying_user_sid, ret_uid); if (NT_STATUS_IS_OK(status)) { pquerying_user_sid = &querying_user_sid; DEBUG(10,("fill_grent_mem_domain_users: " @@ -1224,7 +1225,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state) sid_copy(&group_sid, &domain->sid); sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->name, &group_sid, + &group_gid))) { union unid_t id; enum lsa_SidType type; diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 41782ff0d1..d8c67dc21c 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -197,8 +197,28 @@ void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, void *private_data) { struct winbindd_request request; + struct winbindd_domain *domain; + ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_SID2UID; + + domain = find_domain_from_sid(sid); + + if (domain != NULL) { + DEBUG(10, ("winbindd_sid2uid_async found domain %s, " + "have_idmap_config = %d\n", domain->name, + (int)domain->have_idmap_config)); + + } + else { + DEBUG(10, ("winbindd_sid2uid_async did not find a domain for " + "%s\n", sid_string_dbg(sid))); + } + + if ((domain != NULL) && (domain->have_idmap_config)) { + fstrcpy(request.domain_name, domain->name); + } + sid_to_fstring(request.data.dual_sid2id.sid, sid); do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv, (void *)cont, private_data); @@ -219,9 +239,12 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, return WINBINDD_ERROR; } - /* Find uid for this sid and return it, possibly ask the slow remote idmap */ + result = idmap_sid_to_uid(state->request.domain_name, &sid, + &state->response.data.uid); - result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); + DEBUG(10, ("winbindd_dual_sid2uid: 0x%08x - %s - %u\n", + NT_STATUS_V(result), sid_string_dbg(&sid), + state->response.data.uid)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -253,8 +276,16 @@ void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, void *private_data) { struct winbindd_request request; + struct winbindd_domain *domain; + ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_SID2GID; + + domain = find_domain_from_sid(sid); + if ((domain != NULL) && (domain->have_idmap_config)) { + fstrcpy(request.domain_name, domain->name); + } + sid_to_fstring(request.data.dual_sid2id.sid, sid); DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", @@ -281,7 +312,8 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, /* Find gid for this sid and return it, possibly ask the slow remote idmap */ - result = idmap_sid_to_gid(&sid, &state->response.data.gid); + result = idmap_sid_to_gid(state->request.domain_name, &sid, + &state->response.data.gid); DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_dbg(&sid), @@ -319,11 +351,21 @@ void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid, void (*cont)(void *private_data, bool success, const char *sid), void *private_data) { + struct winbindd_domain *domain; struct winbindd_request request; ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_UID2SID; request.data.uid = uid; + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + if (domain->have_idmap_config + && (uid >= domain->id_range_low) + && (uid <= domain->id_range_high)) { + fstrcpy(request.domain_name, domain->name); + } + } + do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, (void *)cont, private_data); } @@ -339,7 +381,8 @@ enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain, (unsigned long) state->request.data.uid)); /* Find sid for this uid and return it, possibly ask the slow remote idmap */ - result = idmap_uid_to_sid(&sid, state->request.data.uid); + result = idmap_uid_to_sid(state->request.domain_name, &sid, + state->request.data.uid); if (NT_STATUS_IS_OK(result)) { sid_to_fstring(state->response.data.sid.sid, &sid); @@ -376,11 +419,21 @@ void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid, void (*cont)(void *private_data, bool success, const char *sid), void *private_data) { + struct winbindd_domain *domain; struct winbindd_request request; ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_GID2SID; request.data.gid = gid; + + for (domain = domain_list(); domain != NULL; domain = domain->next) { + if (domain->have_idmap_config + && (gid >= domain->id_range_low) + && (gid <= domain->id_range_high)) { + fstrcpy(request.domain_name, domain->name); + } + } + do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, (void *)cont, private_data); } @@ -396,7 +449,8 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain, (unsigned long) state->request.data.gid)); /* Find sid for this gid and return it, possibly ask the slow remote idmap */ - result = idmap_gid_to_sid(&sid, state->request.data.gid); + result = idmap_gid_to_sid(state->request.domain_name, &sid, + state->request.data.gid); if (NT_STATUS_IS_OK(result)) { sid_to_fstring(state->response.data.sid.sid, &sid); diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 5f5972fb05..274786fa63 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -166,12 +166,10 @@ static void sid2uid_recv(void *private_data, bool success, uid_t uid) if (!success) { DEBUG(5, ("Could not convert sid %s\n", state->request.data.sid)); - idmap_cache_set_sid2uid(&sid, -1); request_error(state); return; } - idmap_cache_set_sid2uid(&sid, uid); state->response.data.uid = uid; request_ok(state); } @@ -209,6 +207,10 @@ static void sid2uid_lookupsid_recv( void *private_data, bool success, return; fail: + /* + * We have to set the cache ourselves here, the child which is + * normally responsible was not queried yet. + */ idmap_cache_set_sid2uid(&sid, -1); request_error(state); return; @@ -273,12 +275,10 @@ static void sid2gid_recv(void *private_data, bool success, gid_t gid) if (!success) { DEBUG(5, ("Could not convert sid %s\n", state->request.data.sid)); - idmap_cache_set_sid2gid(&sid, -1); request_error(state); return; } - idmap_cache_set_sid2gid(&sid, gid); state->response.data.gid = gid; request_ok(state); } @@ -319,6 +319,10 @@ static void sid2gid_lookupsid_recv( void *private_data, bool success, return; fail: + /* + * We have to set the cache ourselves here, the child which is + * normally responsible was not queried yet. + */ idmap_cache_set_sid2gid(&sid, -1); request_error(state); return; @@ -516,7 +520,7 @@ static void gid2sid_recv(void *private_data, bool success, const char *sidstr) return; } DEBUG(10,("gid2sid: gid %lu has sid %s\n", - (unsigned long)(state->request.data.gid), sid)); + (unsigned long)(state->request.data.gid), sidstr)); idmap_cache_set_sid2gid(&sid, state->request.data.gid); fstrcpy(state->response.data.sid.sid, sidstr); diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 00e53eff74..3b6dfdda1c 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -79,7 +79,8 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, /* Resolve the uid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_uid(dom_name, user_sid, + &pw->pw_uid))) { DEBUG(1, ("error getting user id for sid %s\n", sid_string_dbg(user_sid))); return False; @@ -87,7 +88,8 @@ static bool winbindd_fill_pwent(char *dom_name, char *user_name, /* Resolve the gid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(dom_name, group_sid, + &pw->pw_gid))) { DEBUG(1, ("error getting group id for sid %s\n", sid_string_dbg(group_sid))); return False; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index a35ba7bc06..f1da5780aa 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -109,6 +109,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const { struct winbindd_domain *domain; const char *alternative_name = NULL; + char *idmap_config_option; + const char *param; /* ignore alt_name if we are not in an AD domain */ @@ -181,12 +183,44 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const if (sid) { sid_copy(&domain->sid, sid); } + /* Link to domain list */ DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *); wcache_tdc_add_domain( domain ); + idmap_config_option = talloc_asprintf(talloc_tos(), "idmap config %s", + domain->name); + if (idmap_config_option == NULL) { + DEBUG(0, ("talloc failed, not looking for idmap config\n")); + goto done; + } + + param = lp_parm_const_string(-1, idmap_config_option, "range", NULL); + + DEBUG(10, ("%s : range = %s\n", idmap_config_option, + param ? param : "not defined")); + + if (param != NULL) { + unsigned low_id, high_id; + if (sscanf(param, "%u - %u", &low_id, &high_id) != 2) { + DEBUG(1, ("invalid range syntax in %s: %s\n", + idmap_config_option, param)); + goto done; + } + if (low_id > high_id) { + DEBUG(1, ("invalid range in %s: %s\n", + idmap_config_option, param)); + goto done; + } + domain->have_idmap_config = true; + domain->id_range_low = low_id; + domain->id_range_high = high_id; + } + +done: + DEBUG(2,("Added domain %s %s %s\n", domain->name, domain->alt_name, &domain->sid?sid_string_dbg(&domain->sid):"")); -- cgit From 2a3698e5c05b5eb98d4ff47437d5afd191bd4ebd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 Jul 2008 16:51:46 +0200 Subject: Remove "idmap alloc config : range" parameter This was overwritten by "idmap uid/gid" anyway. These are now the range parameters for the alloc backend. (This used to be commit d563a7b80dc3e759069db2cd54d596a1b8c55191) --- source3/winbindd/idmap_ldap.c | 45 ++++++--------------- source3/winbindd/idmap_tdb.c | 75 +++++++++++++---------------------- source3/winbindd/idmap_tdb2.c | 91 ++++++++++++++++++------------------------- 3 files changed, 76 insertions(+), 135 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 64b176389e..5657cb591e 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -263,50 +263,27 @@ static NTSTATUS idmap_ldap_alloc_init(const char *params) /* load ranges */ - idmap_alloc_ldap->low_uid = 0; - idmap_alloc_ldap->high_uid = 0; - idmap_alloc_ldap->low_gid = 0; - idmap_alloc_ldap->high_gid = 0; - - range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); - if (range && range[0]) { - unsigned low_id, high_id; - - if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { - if (low_id < high_id) { - idmap_alloc_ldap->low_gid = low_id; - idmap_alloc_ldap->low_uid = low_id; - idmap_alloc_ldap->high_gid = high_id; - idmap_alloc_ldap->high_uid = high_id; - } else { - DEBUG(1, ("ERROR: invalid idmap alloc range " - "[%s]", range)); - } - } else { - DEBUG(1, ("ERROR: invalid syntax for idmap alloc " - "config:range [%s]", range)); - } - } - - if (lp_idmap_uid(&low_uid, &high_uid)) { - idmap_alloc_ldap->low_uid = low_uid; - idmap_alloc_ldap->high_uid = high_uid; + if (!lp_idmap_uid(&low_uid, &high_uid) + || !lp_idmap_gid(&low_gid, &high_gid)) { + DEBUG(1, ("idmap uid or idmap gid missing\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; } - if (lp_idmap_gid(&low_gid, &high_gid)) { - idmap_alloc_ldap->low_gid = low_gid; - idmap_alloc_ldap->high_gid= high_gid; - } + idmap_alloc_ldap->low_uid = low_uid; + idmap_alloc_ldap->high_uid = high_uid; + idmap_alloc_ldap->low_gid = low_gid; + idmap_alloc_ldap->high_gid= high_gid; if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) { - DEBUG(1, ("idmap uid range missing or invalid\n")); + DEBUG(1, ("idmap uid range invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; } if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) { - DEBUG(1, ("idmap gid range missing or invalid\n")); + DEBUG(1, ("idmap gid range invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 3f6cccd35a..2b9520d54d 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -318,6 +318,7 @@ static NTSTATUS idmap_tdb_alloc_init( const char *params ) uid_t high_uid = 0; gid_t low_gid = 0; gid_t high_gid = 0; + uint32_t low_id, high_id; /* use our own context here */ ctx = talloc_new(NULL); @@ -335,67 +336,47 @@ static NTSTATUS idmap_tdb_alloc_init( const char *params ) talloc_free(ctx); /* load ranges */ - idmap_tdb_state.low_uid = 0; - idmap_tdb_state.high_uid = 0; - idmap_tdb_state.low_gid = 0; - idmap_tdb_state.high_gid = 0; - - range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); - if (range && range[0]) { - unsigned low_id, high_id; - - if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { - if (low_id < high_id) { - idmap_tdb_state.low_gid = idmap_tdb_state.low_uid = low_id; - idmap_tdb_state.high_gid = idmap_tdb_state.high_uid = high_id; - } else { - DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range)); - } - } else { - DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range)); - } - } - /* Create high water marks for group and user id */ - if (lp_idmap_uid(&low_uid, &high_uid)) { - idmap_tdb_state.low_uid = low_uid; - idmap_tdb_state.high_uid = high_uid; + if (!lp_idmap_uid(&low_uid, &high_uid) + || !lp_idmap_gid(&low_gid, &high_gid)) { + DEBUG(1, ("idmap uid or idmap gid missing\n")); + return NT_STATUS_UNSUCCESSFUL; } - if (lp_idmap_gid(&low_gid, &high_gid)) { - idmap_tdb_state.low_gid = low_gid; - idmap_tdb_state.high_gid = high_gid; - } + idmap_tdb_state.low_uid = low_uid; + idmap_tdb_state.high_uid = high_uid; + idmap_tdb_state.low_gid = low_gid; + idmap_tdb_state.high_gid = high_gid; if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) { DEBUG(1, ("idmap uid range missing or invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); return NT_STATUS_UNSUCCESSFUL; - } else { - uint32 low_id; - - if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) || - (low_id < idmap_tdb_state.low_uid)) { - if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, idmap_tdb_state.low_uid) == -1) { - DEBUG(0, ("Unable to initialise user hwm in idmap database\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } - } } if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) { DEBUG(1, ("idmap gid range missing or invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); return NT_STATUS_UNSUCCESSFUL; - } else { - uint32 low_id; - - if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) || - (low_id < idmap_tdb_state.low_gid)) { - if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, idmap_tdb_state.low_gid) == -1) { - DEBUG(0, ("Unable to initialise group hwm in idmap database\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } + } + + if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) || + (low_id < idmap_tdb_state.low_uid)) { + if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, + idmap_tdb_state.low_uid) == -1) { + DEBUG(0, ("Unable to initialise user hwm in idmap " + "database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + } + + if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) || + (low_id < idmap_tdb_state.low_gid)) { + if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, + idmap_tdb_state.low_gid) == -1) { + DEBUG(0, ("Unable to initialise group hwm in idmap " + "database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; } } diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index d30b6459fb..cb5e9ec6d4 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -128,62 +128,46 @@ static NTSTATUS idmap_tdb2_alloc_load(void) uid_t high_uid = 0; gid_t low_gid = 0; gid_t high_gid = 0; - - /* load ranges */ - idmap_tdb2_state.low_uid = 0; - idmap_tdb2_state.high_uid = 0; - idmap_tdb2_state.low_gid = 0; - idmap_tdb2_state.high_gid = 0; + uint32 low_id, high_id; /* see if a idmap script is configured */ - idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL); + idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", + "script", NULL); if (idmap_tdb2_state.idmap_script) { - DEBUG(1, ("using idmap script '%s'\n", idmap_tdb2_state.idmap_script)); - } - - range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL); - if (range && range[0]) { - unsigned low_id, high_id; - if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) { - if (low_id < high_id) { - idmap_tdb2_state.low_gid = idmap_tdb2_state.low_uid = low_id; - idmap_tdb2_state.high_gid = idmap_tdb2_state.high_uid = high_id; - } else { - DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range)); - } - } else { - DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range)); - } + DEBUG(1, ("using idmap script '%s'\n", + idmap_tdb2_state.idmap_script)); } + /* load ranges */ + /* Create high water marks for group and user id */ - if (lp_idmap_uid(&low_uid, &high_uid)) { - idmap_tdb2_state.low_uid = low_uid; - idmap_tdb2_state.high_uid = high_uid; + if (!lp_idmap_uid(&low_uid, &high_uid) + || !lp_idmap_gid(&low_gid, &high_gid)) { + DEBUG(1, ("idmap uid or idmap gid missing\n")); + return NT_STATUS_UNSUCCESSFUL; } - if (lp_idmap_gid(&low_gid, &high_gid)) { - idmap_tdb2_state.low_gid = low_gid; - idmap_tdb2_state.high_gid = high_gid; - } + idmap_tdb2_state.low_uid = low_uid; + idmap_tdb2_state.high_uid = high_uid; + idmap_tdb2_state.low_gid = low_gid; + idmap_tdb2_state.high_gid = high_gid; if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) { DEBUG(1, ("idmap uid range missing or invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); return NT_STATUS_UNSUCCESSFUL; - } else { - uint32 low_id; - - if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, - HWM_USER)) == -1) || - (low_id < idmap_tdb2_state.low_uid)) { - if (dbwrap_store_int32( - idmap_tdb2_perm, HWM_USER, - idmap_tdb2_state.low_uid) == -1) { - DEBUG(0, ("Unable to initialise user hwm in idmap database\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } + } + + if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + HWM_USER)) == -1) || + (low_id < idmap_tdb2_state.low_uid)) { + if (dbwrap_store_int32( + idmap_tdb2_perm, HWM_USER, + idmap_tdb2_state.low_uid) == -1) { + DEBUG(0, ("Unable to initialise user hwm in idmap " + "database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; } } @@ -191,18 +175,17 @@ static NTSTATUS idmap_tdb2_alloc_load(void) DEBUG(1, ("idmap gid range missing or invalid\n")); DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); return NT_STATUS_UNSUCCESSFUL; - } else { - uint32 low_id; - - if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, - HWM_GROUP)) == -1) || - (low_id < idmap_tdb2_state.low_gid)) { - if (dbwrap_store_int32( - idmap_tdb2_perm, HWM_GROUP, - idmap_tdb2_state.low_gid) == -1) { - DEBUG(0, ("Unable to initialise group hwm in idmap database\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } + } + + if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + HWM_GROUP)) == -1) || + (low_id < idmap_tdb2_state.low_gid)) { + if (dbwrap_store_int32( + idmap_tdb2_perm, HWM_GROUP, + idmap_tdb2_state.low_gid) == -1) { + DEBUG(0, ("Unable to initialise group hwm in idmap " + "database\n")); + return NT_STATUS_INTERNAL_DB_ERROR; } } -- cgit From 8d25729705170733b565ccc1751302dc9962eea5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 Jul 2008 18:14:33 +0200 Subject: Fix prototypes (This used to be commit 8b9d12714679745b98755e6805e71b75828ce227) --- source3/winbindd/idmap_ldap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 5657cb591e..c86a5023d0 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -246,7 +246,6 @@ done: static NTSTATUS idmap_ldap_alloc_init(const char *params) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - const char *range; const char *tmp; uid_t low_uid = 0; uid_t high_uid = 0; @@ -1458,12 +1457,13 @@ static struct idmap_alloc_methods idmap_ldap_alloc_methods = { /* .dump_data = TODO */ }; -NTSTATUS idmap_alloc_ldap_init(void) +static NTSTATUS idmap_alloc_ldap_init(void) { return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_alloc_methods); } +NTSTATUS idmap_ldap_init(void); NTSTATUS idmap_ldap_init(void) { NTSTATUS ret; -- cgit From 18bc97287cbaffb03a54c0b1e635d443a3d54d8d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 17 Jul 2008 13:32:28 +0200 Subject: Some doxygen comments for idmap (This used to be commit adecc6d91338e7e34afd0672aada5d0e47247a33) --- source3/winbindd/idmap.c | 101 +++++++++++++++++++++++++++++++++++++---- source3/winbindd/idmap_cache.c | 71 +++++++++++++++++++++++++++-- 2 files changed, 157 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index bace38876b..c23919fb18 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -28,37 +28,59 @@ static_decl_idmap; +/** + * Pointer to the backend methods. Modules register themselves here via + * smb_register_idmap. + */ + struct idmap_backend { const char *name; struct idmap_methods *methods; struct idmap_backend *prev, *next; }; +static struct idmap_backend *backends = NULL; +/** + * Pointer to the alloc backend methods. Modules register themselves here via + * smb_register_idmap_alloc. + */ struct idmap_alloc_backend { const char *name; struct idmap_alloc_methods *methods; struct idmap_alloc_backend *prev, *next; }; +static struct idmap_alloc_backend *alloc_backends = NULL; +/** + * The idmap alloc context that is configured via "idmap alloc + * backend". Defaults to "idmap backend" in case the module (tdb, ldap) also + * provides alloc methods. + */ struct idmap_alloc_context { struct idmap_alloc_methods *methods; }; +static struct idmap_alloc_context *idmap_alloc_ctx = NULL; -/* - * Lists for the module initializations +/** + * Default idmap domain configured via "idmap backend". */ -static struct idmap_backend *backends = NULL; -static struct idmap_alloc_backend *alloc_backends = NULL; - - static struct idmap_domain *default_idmap_domain; + +/** + * Passdb idmap domain, not configurable. winbind must always give passdb a + * chance to map ids. + */ static struct idmap_domain *passdb_idmap_domain; +/** + * List of specially configured idmap domains. This list is filled on demand + * in the winbind idmap child when the parent winbind figures out via the + * special range parameter or via the domain SID that a special "idmap config + * domain" configuration is present. + */ static struct idmap_domain **idmap_domains = NULL; static int num_domains = 0; -static struct idmap_alloc_context *idmap_alloc_ctx = NULL; - static struct idmap_methods *get_methods(struct idmap_backend *be, const char *name) { @@ -126,7 +148,8 @@ NTSTATUS smb_register_idmap(int version, const char *name, for (entry = backends; entry != NULL; entry = entry->next) { if (strequal(entry->name, name)) { - DEBUG(0,("Idmap module %s already registered!\n", name)); + DEBUG(0,("Idmap module %s already registered!\n", + name)); return NT_STATUS_OBJECT_NAME_COLLISION; } } @@ -151,7 +174,7 @@ NTSTATUS smb_register_idmap(int version, const char *name, } /********************************************************************** - Allow a module to register itself as a method. + Allow a module to register itself as an alloc method. **********************************************************************/ NTSTATUS smb_register_idmap_alloc(int version, const char *name, @@ -249,6 +272,14 @@ static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param, return true; } +/** + * Initialize a domain structure + * @param[in] mem_ctx memory context for the result + * @param[in] domainname which domain is this for + * @param[in] modulename which backend module + * @param[in] params parameter to pass to the init function + * @result The initialized structure + */ static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx, const char *domainname, const char *modulename, @@ -303,6 +334,15 @@ fail: return NULL; } +/** + * Initialize the default domain structure + * @param[in] mem_ctx memory context for the result + * @result The default domain structure + * + * This routine takes the module name from the "idmap backend" parameter, + * passing a possible parameter like ldap:ldap://ldap-url/ to the module. + */ + static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx) { struct idmap_domain *result; @@ -337,6 +377,16 @@ fail: return NULL; } +/** + * Initialize a named domain structure + * @param[in] mem_ctx memory context for the result + * @param[in] domname the domain name + * @result The default domain structure + * + * This routine looks at the "idmap config " parameters to figure out + * the configuration. + */ + static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx, const char *domname) { @@ -371,6 +421,14 @@ fail: return NULL; } +/** + * Initialize the passdb domain structure + * @param[in] mem_ctx memory context for the result + * @result The default domain structure + * + * No config, passdb has its own configuration. + */ + static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx) { if (passdb_idmap_domain != NULL) { @@ -386,6 +444,21 @@ static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx) return passdb_idmap_domain; } +/** + * Find a domain struct according to a domain name + * @param[in] domname Domain name to get the config for + * @result The default domain structure that fits + * + * This is the central routine in the winbindd-idmap child to pick the correct + * domain for looking up IDs. If domname is NULL or empty, we use the default + * domain. If it contains something, we try to use idmap_init_named_domain() + * to fetch the correct backend. + * + * The choice about "domname" is being made by the winbind parent, look at the + * "have_idmap_config" of "struct winbindd_domain" which is set in + * add_trusted_domain. + */ + static struct idmap_domain *idmap_find_domain(const char *domname) { struct idmap_domain *result; @@ -449,6 +522,14 @@ void idmap_close(void) num_domains = 0; } +/** + * Initialize the idmap alloc backend + * @param[out] ctx Where to put the alloc_ctx? + * @result Did it work fine? + * + * This routine first looks at "idmap alloc backend" and if that is not + * defined, it uses "idmap backend" for the module name. + */ static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx) { const char *backend; diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index b818d0dafb..496f70ab45 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -1,11 +1,8 @@ -/* +/* Unix SMB/CIFS implementation. ID Mapping Cache - based on gencache - - Copyright (C) Simo Sorce 2006 - Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Volker Lendecke 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +20,16 @@ #include "includes.h" #include "winbindd.h" +/** + * Find a sid2uid mapping + * @param[in] sid the sid to map + * @param[out] puid where to put the result + * @param[out] expired is the cache entry expired? + * @retval Was anything in the cache at all? + * + * If *puid == -1 this was a negative mapping. + */ + bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid, bool *expired) { @@ -54,6 +61,16 @@ bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid, return ret; } +/** + * Find a uid2sid mapping + * @param[in] uid the uid to map + * @param[out] sid where to put the result + * @param[out] expired is the cache entry expired? + * @retval Was anything in the cache at all? + * + * If "is_null_sid(sid)", this was a negative mapping. + */ + bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) { char *key; @@ -81,6 +98,18 @@ bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) return ret; } +/** + * Store a mapping in the idmap cache + * @param[in] sid the sid to map + * @param[in] uid the uid to map + * + * If both parameters are valid values, then a positive mapping in both + * directions is stored. If "is_null_sid(sid)" is true, then this will be a + * negative mapping of uid, we want to cache that for this uid we could not + * find anything. Likewise if "uid==-1", then we want to cache that we did not + * find a mapping for the sid passed here. + */ + void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) { time_t now = time(NULL); @@ -111,6 +140,16 @@ void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) } } +/** + * Find a sid2gid mapping + * @param[in] sid the sid to map + * @param[out] pgid where to put the result + * @param[out] expired is the cache entry expired? + * @retval Was anything in the cache at all? + * + * If *pgid == -1 this was a negative mapping. + */ + bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid, bool *expired) { @@ -142,6 +181,16 @@ bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid, return ret; } +/** + * Find a gid2sid mapping + * @param[in] gid the gid to map + * @param[out] sid where to put the result + * @param[out] expired is the cache entry expired? + * @retval Was anything in the cache at all? + * + * If "is_null_sid(sid)", this was a negative mapping. + */ + bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) { char *key; @@ -169,6 +218,18 @@ bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) return ret; } +/** + * Store a mapping in the idmap cache + * @param[in] sid the sid to map + * @param[in] gid the gid to map + * + * If both parameters are valid values, then a positive mapping in both + * directions is stored. If "is_null_sid(sid)" is true, then this will be a + * negative mapping of gid, we want to cache that for this gid we could not + * find anything. Likewise if "gid==-1", then we want to cache that we did not + * find a mapping for the sid passed here. + */ + void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid) { time_t now = time(NULL); -- cgit From a93d0f6f4e40c0130f8e14eaa555cdbbccce825e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Jul 2008 09:04:17 +0200 Subject: Do not create a new mapping if a domain with an explicit config fails (This used to be commit 2c27de44269198e22c323191dd4762d1aab81b22) --- source3/winbindd/idmap_util.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 04d12944e2..2a6beca5a2 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -174,6 +174,15 @@ backend: goto done; } + if (dom_name[0] != '\0') { + /* + * We had the task to go to a specific domain which + * could not answer our request. Fail. + */ + idmap_cache_set_sid2uid(sid, -1); + return NT_STATUS_NONE_MAPPED; + } + ret = idmap_new_mapping(sid, ID_TYPE_UID, &map.xid); if (!NT_STATUS_IS_OK(ret)) { @@ -236,6 +245,15 @@ backend: goto done; } + if (domname[0] != '\0') { + /* + * We had the task to go to a specific domain which + * could not answer our request. Fail. + */ + idmap_cache_set_sid2uid(sid, -1); + return NT_STATUS_NONE_MAPPED; + } + ret = idmap_new_mapping(sid, ID_TYPE_GID, &map.xid); if (!NT_STATUS_IS_OK(ret)) { -- cgit From 68fe1a1d86dddc387753220790bb9ac5c096edf1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 12 Aug 2008 11:59:13 +0200 Subject: Remove two unused variables (This used to be commit 257b0401ee675b6b7eddf2b46a0f8115940e6640) --- source3/winbindd/idmap_tdb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 2b9520d54d..9e66eed0c8 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -313,12 +313,11 @@ static NTSTATUS idmap_tdb_alloc_init( const char *params ) { NTSTATUS ret; TALLOC_CTX *ctx; - const char *range; uid_t low_uid = 0; uid_t high_uid = 0; gid_t low_gid = 0; gid_t high_gid = 0; - uint32_t low_id, high_id; + uint32_t low_id; /* use our own context here */ ctx = talloc_new(NULL); -- cgit From e3ec81c519716fe50fd4d1b5941195baebe5be46 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 1 Jul 2008 14:24:47 +0200 Subject: Attempt to fix the build on Irix CC (cherry picked from commit 666bf8456ac44cbbbd5524af2bf4fd89e18ddf62) (This used to be commit 8819c51809cabe6ad0843f3838de53e785a10b47) --- source3/winbindd/winbindd_async.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index e47666462e..1481aed8e1 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -557,10 +557,12 @@ enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, struct winbindd_cli_state *state) { - struct getent_state groups = {}; + struct getent_state groups; char *extra_data = NULL; uint32_t extra_data_len = 0, i; + ZERO_STRUCT(groups); + /* Must copy domain into response first for debugging in parent */ fstrcpy(state->response.data.name.dom_name, domain->name); fstrcpy(groups.domain_name, domain->name); -- cgit From 5a3642d5aa725b0a54e6e303e1afdbfefdb81de7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 19 May 2008 18:15:06 +0200 Subject: Add winbind:online check timeout parameter This is a band-aid for the rather convoluted offline/online mess in winbind right now. Winbind re-uses the offline functionality that is targeted at domain client installations on laptops to not overload disfunctional DCs. It uses the winbind cache timeout as the retry timeout after a DC reboot. I am using a parametric options because when this mess is cleaned up, that parameter needs to go away again. I'd recommend to use something like winbind:online check timeout = 30 in typical LAN environments. This means a reconnect is attempted every 30 seconds. Volker (This used to be commit 9920473cc165e75ee9aa5cbb9e568eb5fb67e9e6) --- source3/winbindd/winbindd_cm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 47df4e4058..c6dab6f2e6 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -292,6 +292,22 @@ static void check_domain_online_handler(struct event_context *ctx, static void calc_new_online_timeout_check(struct winbindd_domain *domain) { int wbc = lp_winbind_cache_time(); + int domain_online_check; + + /* + * If "winbind:online check timeout" is set explicitly, + * override the default of "winbind cache timeout" + * + * Add this as a parametric option and don't document it. The + * whole offline abuse for non-reachable DCs needs + * fixing. Till then, use this hackish parameter. + */ + + domain_online_check = lp_parm_int(-1, "winbind", + "online check timeout", 0); + if (domain_online_check != 0) { + wbc = domain_online_check; + } if (domain->startup) { domain->check_online_timeout = 10; -- cgit From 6afa8e573e1afe93fb126f851aaf6b0c0cd8d75a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 6 Aug 2008 22:33:58 +0200 Subject: idmap tdb2: fix broken logic in tdb2_store_bystring(). 1. use the return value that idmap_tdb2_open_perm_db() gives us 2. don't write to the local db if writing to the perm db failed. 3. fix wrong interpretation of return value of the local store Michael (This used to be commit be8c6b4f2f40014313899b5cbc1da9d390d94fee) --- source3/winbindd/idmap_tdb2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index cb5e9ec6d4..172922b85f 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -383,15 +383,18 @@ static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr) static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags) { NTSTATUS ret; - NTSTATUS status = idmap_tdb2_open_perm_db(); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_UNSUCCESSFUL; + + ret = idmap_tdb2_open_perm_db(); + if (!NT_STATUS_IS_OK(ret)) { + return ret; } ret = dbwrap_store_bystring(idmap_tdb2_perm, keystr, data, flags); if (!NT_STATUS_IS_OK(ret)) { - ret = tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + return ret; } - return ret; + return (tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) == 0) + ? NT_STATUS_OK + : NT_STATUS_UNSUCCESSFUL; } /* -- cgit From 134ea912781ba8da276217d6d663ab1967407f3e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 6 Aug 2008 22:43:27 +0200 Subject: idmap tdb2: fix broken logic in tdb2_delete_bystring(). 1. use the return value that idmap_tdb2_open_perm_db() gives us 2. don't delete frep the local db if deleting from the perm db failed. 3. fix wrong interpretation of return value of the local delete Michael (This used to be commit 147573d7f6faab0ad90258b6a28c4b9575ccb6ea) --- source3/winbindd/idmap_tdb2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index 172922b85f..81553dc9c6 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -403,15 +403,18 @@ static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags static NTSTATUS tdb2_delete_bystring(const char *keystr) { NTSTATUS ret; - NTSTATUS status = idmap_tdb2_open_perm_db(); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_UNSUCCESSFUL; + + ret = idmap_tdb2_open_perm_db(); + if (!NT_STATUS_IS_OK(ret)) { + return ret; } ret = dbwrap_delete_bystring(idmap_tdb2_perm, keystr); if (!NT_STATUS_IS_OK(ret)) { - ret = tdb_delete_bystring(idmap_tdb2_tmp, keystr) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + return ret; } - return ret; + return (tdb_delete_bystring(idmap_tdb2_tmp, keystr) == 0) + ? NT_STATUS_OK + : NT_STATUS_UNSUCCESSFUL; } /* -- cgit From 620d87318381a417e3f0843e8cb5f0257ebf9873 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 7 Aug 2008 02:03:22 +0200 Subject: idmap tdb2: fix inconsistent mappings by checking for race and retrying to fetch mapping. Michael (This used to be commit cb4c74c9c206e5a445ca636fa6562ce721ea5839) --- source3/winbindd/idmap.c | 9 ++++++ source3/winbindd/idmap_tdb2.c | 70 ++++++++----------------------------------- 2 files changed, 22 insertions(+), 57 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index c23919fb18..2962fe6c1c 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -705,6 +705,15 @@ NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type, status = dom->methods->set_mapping(dom, &map); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + struct id_map *ids[2]; + DEBUG(5, ("Mapping for %s exists - retrying to map sid\n", + sid_string_dbg(map.sid))); + ids[0] = ↦ + ids[1] = NULL; + status = dom->methods->sids_to_unixids(dom, ids); + } + if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not store the new mapping: %s\n", nt_errstr(status))); diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index 81553dc9c6..a3c867f5bb 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -790,14 +790,12 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id TDB_DATA data; char *ksidstr, *kidstr; struct db_record *update_lock = NULL; - struct db_record *rec = NULL; if (!map || !map->sid) { return NT_STATUS_INVALID_PARAMETER; } ksidstr = kidstr = NULL; - data.dptr = NULL; /* TODO: should we filter a set_mapping using low/high filters ? */ @@ -845,66 +843,25 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id goto done; } - /* - * *DELETE* previous mappings if any. * - */ - - /* First delete indexed on SID */ - - if (((rec = idmap_tdb2_perm->fetch_locked( - idmap_tdb2_perm, update_lock, - string_term_tdb_data(ksidstr))) != NULL) - && (rec->value.dsize != 0)) { - struct db_record *rec2; - - if ((rec2 = idmap_tdb2_perm->fetch_locked( - idmap_tdb2_perm, update_lock, rec->value)) - != NULL) { - rec2->delete_rec(rec2); - TALLOC_FREE(rec2); - } - - rec->delete_rec(rec); - - tdb_delete(idmap_tdb2_tmp, rec->key); - tdb_delete(idmap_tdb2_tmp, rec->value); - } - TALLOC_FREE(rec); - - /* Now delete indexed on unix ID */ - - if (((rec = idmap_tdb2_perm->fetch_locked( - idmap_tdb2_perm, update_lock, - string_term_tdb_data(kidstr))) != NULL) - && (rec->value.dsize != 0)) { - struct db_record *rec2; - - if ((rec2 = idmap_tdb2_perm->fetch_locked( - idmap_tdb2_perm, update_lock, rec->value)) - != NULL) { - rec2->delete_rec(rec2); - TALLOC_FREE(rec2); - } - - rec->delete_rec(rec); - - tdb_delete(idmap_tdb2_tmp, rec->key); - tdb_delete(idmap_tdb2_tmp, rec->value); + /* check wheter sid mapping is already present in db */ + data = tdb2_fetch_bystring(ksidstr, ksidstr); + if (data.dptr) { + ret = NT_STATUS_OBJECT_NAME_COLLISION; + goto done; } - TALLOC_FREE(rec); - if (!NT_STATUS_IS_OK(tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr), - TDB_INSERT))) { - DEBUG(0, ("Error storing SID -> ID\n")); - ret = NT_STATUS_UNSUCCESSFUL; + ret = tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr), + TDB_INSERT); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("Error storing SID -> ID: %s\n", nt_errstr(ret))); goto done; } - if (!NT_STATUS_IS_OK(tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr), - TDB_INSERT))) { - DEBUG(0, ("Error storing ID -> SID\n")); + ret = tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr), + TDB_INSERT); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("Error storing ID -> SID: %s\n", nt_errstr(ret))); /* try to remove the previous stored SID -> ID map */ tdb2_delete_bystring(ksidstr); - ret = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -914,7 +871,6 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id done: talloc_free(ksidstr); talloc_free(kidstr); - SAFE_FREE(data.dptr); TALLOC_FREE(update_lock); return ret; } -- cgit From 9c79d1c23e607947b582278b181af8f5ef37806b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Aug 2008 11:59:39 +1000 Subject: got rid of the redundent cache database (This used to be commit 126f4ac8e85458ee4693b89a184b99420f1b6bee) --- source3/winbindd/idmap_tdb2.c | 162 ++++++++---------------------------------- 1 file changed, 28 insertions(+), 134 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index a3c867f5bb..8ab55030db 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -3,9 +3,8 @@ idmap TDB2 backend, used for clustered Samba setups. - This uses 2 tdb files. One is permanent, and is in shared storage - on the cluster (using "tdb:idmap2.tdb =" in smb.conf). The other is a - temporary cache tdb on local storage. + This uses dbwrap to access tdb files. The location can be set + using tdb:idmap2.tdb =" in smb.conf Copyright (C) Andrew Tridgell 2007 @@ -50,46 +49,19 @@ static struct idmap_tdb2_state { -/* tdb context for the local cache tdb */ -static TDB_CONTEXT *idmap_tdb2_tmp; - /* handle to the permanent tdb */ -static struct db_context *idmap_tdb2_perm; - -/* - open the cache tdb - */ -static NTSTATUS idmap_tdb2_open_cache_db(void) -{ - const char *db_path; - - if (idmap_tdb2_tmp) { - /* its already open */ - return NT_STATUS_OK; - } - - db_path = lock_path("idmap2_cache.tdb"); - - /* Open idmap repository */ - if (!(idmap_tdb2_tmp = tdb_open_log(db_path, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644))) { - DEBUG(0, ("Unable to open cache idmap database '%s'\n", db_path)); - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; -} - +static struct db_context *idmap_tdb2; static NTSTATUS idmap_tdb2_alloc_load(void); /* open the permanent tdb */ -static NTSTATUS idmap_tdb2_open_perm_db(void) +static NTSTATUS idmap_tdb2_open_db(void) { char *db_path; - if (idmap_tdb2_perm) { + if (idmap_tdb2) { /* its already open */ return NT_STATUS_OK; } @@ -103,12 +75,11 @@ static NTSTATUS idmap_tdb2_open_perm_db(void) NT_STATUS_HAVE_NO_MEMORY(db_path); /* Open idmap repository */ - idmap_tdb2_perm = db_open(NULL, db_path, 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0644); + idmap_tdb2 = db_open(NULL, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644); TALLOC_FREE(db_path); - if (idmap_tdb2_perm == NULL) { - DEBUG(0, ("Unable to open permanent idmap database '%s'\n", + if (idmap_tdb2 == NULL) { + DEBUG(0, ("Unable to open idmap_tdb2 database '%s'\n", db_path)); return NT_STATUS_UNSUCCESSFUL; } @@ -159,11 +130,11 @@ static NTSTATUS idmap_tdb2_alloc_load(void) return NT_STATUS_UNSUCCESSFUL; } - if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + if (((low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_USER)) == -1) || (low_id < idmap_tdb2_state.low_uid)) { if (dbwrap_store_int32( - idmap_tdb2_perm, HWM_USER, + idmap_tdb2, HWM_USER, idmap_tdb2_state.low_uid) == -1) { DEBUG(0, ("Unable to initialise user hwm in idmap " "database\n")); @@ -177,11 +148,11 @@ static NTSTATUS idmap_tdb2_alloc_load(void) return NT_STATUS_UNSUCCESSFUL; } - if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm, + if (((low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_GROUP)) == -1) || (low_id < idmap_tdb2_state.low_gid)) { if (dbwrap_store_int32( - idmap_tdb2_perm, HWM_GROUP, + idmap_tdb2, HWM_GROUP, idmap_tdb2_state.low_gid) == -1) { DEBUG(0, ("Unable to initialise group hwm in idmap " "database\n")); @@ -217,9 +188,6 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) uint32_t hwm; NTSTATUS status; - status = idmap_tdb2_open_perm_db(); - NT_STATUS_NOT_OK_RETURN(status); - /* Get current high water mark */ switch (xid->type) { @@ -240,7 +208,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } - if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { + if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -252,7 +220,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) } /* fetch a new id and increment it */ - ret = dbwrap_change_uint32_atomic(idmap_tdb2_perm, hwmkey, &hwm, 1); + ret = dbwrap_change_uint32_atomic(idmap_tdb2, hwmkey, &hwm, 1); if (ret == -1) { DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype)); return NT_STATUS_UNSUCCESSFUL; @@ -300,7 +268,7 @@ static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } - if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { + if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -343,80 +311,6 @@ struct idmap_tdb2_context { uint32_t filter_high_id; }; -/* - try fetching from the cache tdb, and if that fails then - fetch from the permanent tdb - */ -static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr) -{ - TDB_DATA ret; - NTSTATUS status; - - ret = tdb_fetch_bystring(idmap_tdb2_tmp, keystr); - if (ret.dptr != NULL) { - /* got it from cache */ - unsigned char *tmp; - - tmp = (unsigned char *)talloc_memdup(mem_ctx, ret.dptr, - ret.dsize); - SAFE_FREE(ret.dptr); - ret.dptr = tmp; - - if (ret.dptr == NULL) { - return make_tdb_data(NULL, 0); - } - return ret; - } - - status = idmap_tdb2_open_perm_db(); - if (!NT_STATUS_IS_OK(status)) { - return ret; - } - - /* fetch from the permanent tdb */ - return dbwrap_fetch_bystring(idmap_tdb2_perm, mem_ctx, keystr); -} - -/* - store into both databases - */ -static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags) -{ - NTSTATUS ret; - - ret = idmap_tdb2_open_perm_db(); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - ret = dbwrap_store_bystring(idmap_tdb2_perm, keystr, data, flags); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - return (tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) == 0) - ? NT_STATUS_OK - : NT_STATUS_UNSUCCESSFUL; -} - -/* - delete from both databases - */ -static NTSTATUS tdb2_delete_bystring(const char *keystr) -{ - NTSTATUS ret; - - ret = idmap_tdb2_open_perm_db(); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - ret = dbwrap_delete_bystring(idmap_tdb2_perm, keystr); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - return (tdb_delete_bystring(idmap_tdb2_tmp, keystr) == 0) - ? NT_STATUS_OK - : NT_STATUS_UNSUCCESSFUL; -} - /* Initialise idmap database. */ @@ -429,7 +323,7 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, const char *range; NTSTATUS status; - status = idmap_tdb2_open_cache_db(); + status = idmap_tdb2_open_db(); NT_STATUS_NOT_OK_RETURN(status); ctx = talloc(dom, struct idmap_tdb2_context); @@ -581,7 +475,7 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m DEBUG(10,("Fetching record %s\n", keystr)); /* Check if the mapping exists */ - data = tdb2_fetch_bystring(keystr, keystr); + data = dbwrap_fetch_bystring(idmap_tdb2, keystr, keystr); if (!data.dptr) { fstring sidstr; @@ -601,10 +495,10 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m if (sid_to_fstring(sidstr, map->sid)) { /* both forward and reverse mappings */ - tdb2_store_bystring(keystr, + dbwrap_store_bystring(idmap_tdb2, keystr, string_term_tdb_data(sidstr), TDB_REPLACE); - tdb2_store_bystring(sidstr, + dbwrap_store_bystring(idmap_tdb2, sidstr, string_term_tdb_data(keystr), TDB_REPLACE); } @@ -646,7 +540,7 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m DEBUG(10,("Fetching record %s\n", keystr)); /* Check if sid is present in database */ - data = tdb2_fetch_bystring(keystr, keystr); + data = dbwrap_fetch_bystring(idmap_tdb2, keystr, keystr); if (!data.dptr) { fstring idstr; @@ -667,9 +561,9 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m map->xid.type == ID_TYPE_UID?'U':'G', (unsigned long)map->xid.id); /* store both forward and reverse mappings */ - tdb2_store_bystring(keystr, string_term_tdb_data(idstr), + dbwrap_store_bystring(idmap_tdb2, keystr, string_term_tdb_data(idstr), TDB_REPLACE); - tdb2_store_bystring(idstr, string_term_tdb_data(keystr), + dbwrap_store_bystring(idmap_tdb2, idstr, string_term_tdb_data(keystr), TDB_REPLACE); goto done; } @@ -835,8 +729,8 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id * right, we need to deal with two records under a lock. */ - if (!(update_lock = idmap_tdb2_perm->fetch_locked( - idmap_tdb2_perm, ctx, + if (!(update_lock = idmap_tdb2->fetch_locked( + idmap_tdb2, ctx, string_term_tdb_data("UPDATELOCK")))) { DEBUG(10,("Failed to lock record %s\n", ksidstr)); ret = NT_STATUS_UNSUCCESSFUL; @@ -844,24 +738,24 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id } /* check wheter sid mapping is already present in db */ - data = tdb2_fetch_bystring(ksidstr, ksidstr); + data = dbwrap_fetch_bystring(idmap_tdb2, ksidstr, ksidstr); if (data.dptr) { ret = NT_STATUS_OBJECT_NAME_COLLISION; goto done; } - ret = tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr), + ret = dbwrap_store_bystring(idmap_tdb2, ksidstr, string_term_tdb_data(kidstr), TDB_INSERT); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0, ("Error storing SID -> ID: %s\n", nt_errstr(ret))); goto done; } - ret = tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr), + ret = dbwrap_store_bystring(idmap_tdb2, kidstr, string_term_tdb_data(ksidstr), TDB_INSERT); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0, ("Error storing ID -> SID: %s\n", nt_errstr(ret))); /* try to remove the previous stored SID -> ID map */ - tdb2_delete_bystring(ksidstr); + dbwrap_delete_bystring(idmap_tdb2, ksidstr); goto done; } -- cgit From 0f41961e4ffaa602a5b19a1e0899bffa491c886f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Aug 2008 16:20:05 +1000 Subject: first cut at adding full transactions for ctdb to samba3 (This used to be commit f91a3e0f7b7737c1d0667cd961ea950e2b93e592) --- source3/winbindd/winbindd.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index ec20d8c195..f75af64f8f 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1024,8 +1024,6 @@ int main(int argc, char **argv, char **envp) load_case_tables(); - db_tdb2_setup_messaging(NULL, false); - /* Initialise for running in non-root mode */ sec_init(); @@ -1116,8 +1114,6 @@ int main(int argc, char **argv, char **envp) exit(1); } - db_tdb2_setup_messaging(winbind_messaging_context(), true); - if (!reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); -- cgit From 4d76ed4f383fcb0f22347582de0c19f63919d6c8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Aug 2008 18:35:19 +1000 Subject: use transactions in idmap_tdb2 (This used to be commit 32b8db27652a66a2ade547a6d27f34d0816f7296) --- source3/winbindd/idmap_tdb2.c | 60 ++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index 8ab55030db..3066db6f3b 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -133,9 +133,9 @@ static NTSTATUS idmap_tdb2_alloc_load(void) if (((low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_USER)) == -1) || (low_id < idmap_tdb2_state.low_uid)) { - if (dbwrap_store_int32( - idmap_tdb2, HWM_USER, - idmap_tdb2_state.low_uid) == -1) { + if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32( + idmap_tdb2, HWM_USER, + idmap_tdb2_state.low_uid))) { DEBUG(0, ("Unable to initialise user hwm in idmap " "database\n")); return NT_STATUS_INTERNAL_DB_ERROR; @@ -151,9 +151,9 @@ static NTSTATUS idmap_tdb2_alloc_load(void) if (((low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_GROUP)) == -1) || (low_id < idmap_tdb2_state.low_gid)) { - if (dbwrap_store_int32( - idmap_tdb2, HWM_GROUP, - idmap_tdb2_state.low_gid) == -1) { + if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32( + idmap_tdb2, HWM_GROUP, + idmap_tdb2_state.low_gid))) { DEBUG(0, ("Unable to initialise group hwm in idmap " "database\n")); return NT_STATUS_INTERNAL_DB_ERROR; @@ -186,7 +186,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) const char *hwmtype; uint32_t high_hwm; uint32_t hwm; - NTSTATUS status; + int res; /* Get current high water mark */ switch (xid->type) { @@ -208,7 +208,14 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } + res = idmap_tdb2->transaction_start(idmap_tdb2); + if (res != 0) { + DEBUG(1,(__location__ " Failed to start transaction\n")); + return NT_STATUS_UNSUCCESSFUL; + } + if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) { + idmap_tdb2->transaction_cancel(idmap_tdb2); return NT_STATUS_INTERNAL_DB_ERROR; } @@ -216,6 +223,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) if (hwm > high_hwm) { DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", hwmtype, (unsigned long)high_hwm)); + idmap_tdb2->transaction_cancel(idmap_tdb2); return NT_STATUS_UNSUCCESSFUL; } @@ -223,6 +231,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) ret = dbwrap_change_uint32_atomic(idmap_tdb2, hwmkey, &hwm, 1); if (ret == -1) { DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype)); + idmap_tdb2->transaction_cancel(idmap_tdb2); return NT_STATUS_UNSUCCESSFUL; } @@ -230,6 +239,13 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) if (hwm > high_hwm) { DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n", hwmtype, (unsigned long)high_hwm)); + idmap_tdb2->transaction_cancel(idmap_tdb2); + return NT_STATUS_UNSUCCESSFUL; + } + + res = idmap_tdb2->transaction_commit(idmap_tdb2); + if (res != 0) { + DEBUG(1,(__location__ " Failed to commit transaction\n")); return NT_STATUS_UNSUCCESSFUL; } @@ -683,7 +699,8 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id NTSTATUS ret; TDB_DATA data; char *ksidstr, *kidstr; - struct db_record *update_lock = NULL; + int res; + bool started_transaction = false; if (!map || !map->sid) { return NT_STATUS_INVALID_PARAMETER; @@ -724,19 +741,15 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr)); - /* - * Get us the update lock. This is necessary to get the lock orders - * right, we need to deal with two records under a lock. - */ - - if (!(update_lock = idmap_tdb2->fetch_locked( - idmap_tdb2, ctx, - string_term_tdb_data("UPDATELOCK")))) { - DEBUG(10,("Failed to lock record %s\n", ksidstr)); + res = idmap_tdb2->transaction_start(idmap_tdb2); + if (res != 0) { + DEBUG(1,(__location__ " Failed to start transaction\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; } + started_transaction = true; + /* check wheter sid mapping is already present in db */ data = dbwrap_fetch_bystring(idmap_tdb2, ksidstr, ksidstr); if (data.dptr) { @@ -759,13 +772,24 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id goto done; } + started_transaction = false; + + res = idmap_tdb2->transaction_commit(idmap_tdb2); + if (res != 0) { + DEBUG(1,(__location__ " Failed to commit transaction\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr)); ret = NT_STATUS_OK; done: + if (started_transaction) { + idmap_tdb2->transaction_cancel(idmap_tdb2); + } talloc_free(ksidstr); talloc_free(kidstr); - TALLOC_FREE(update_lock); return ret; } -- cgit From e90dc23ff5d9853501df21331ce57ccb29601fa8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Aug 2008 11:09:37 +0200 Subject: Revert "Add winbind:online check timeout parameter" This reverts commit 9920473cc165e75ee9aa5cbb9e568eb5fb67e9e6. (This used to be commit 34a32db9060e7b60455774f923f61b7367ee3fcf) --- source3/winbindd/winbindd_cm.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index c6dab6f2e6..47df4e4058 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -292,22 +292,6 @@ static void check_domain_online_handler(struct event_context *ctx, static void calc_new_online_timeout_check(struct winbindd_domain *domain) { int wbc = lp_winbind_cache_time(); - int domain_online_check; - - /* - * If "winbind:online check timeout" is set explicitly, - * override the default of "winbind cache timeout" - * - * Add this as a parametric option and don't document it. The - * whole offline abuse for non-reachable DCs needs - * fixing. Till then, use this hackish parameter. - */ - - domain_online_check = lp_parm_int(-1, "winbind", - "online check timeout", 0); - if (domain_online_check != 0) { - wbc = domain_online_check; - } if (domain->startup) { domain->check_online_timeout = 10; -- cgit From 63ff9e008147b105316dcb0ea2df9b4304a8851e Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 15 Aug 2008 15:28:23 -0700 Subject: I think the problem with these functions is that lookup_usergroups should never include the user SID. The comment for the function in winbindd/winbindd_ads.c says /* Lookup groups a user is a member of. */ The following patch makes the wbinfo calls return the correct data before and after a login. wbinfo --user-domgroups and --user-sids (This used to be commit 7849938906a9c859805cbaeca66fae9d3c515aad) --- source3/winbindd/winbindd_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index f1da5780aa..77b17787c9 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1333,7 +1333,7 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, status = sid_array_from_info3(mem_ctx, info3, user_sids, &num_groups, - true, true); + false, true); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); -- cgit From 165f5c0c0a99d7da598a3c27355abaed1161cc7f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Aug 2008 11:12:35 +0200 Subject: Attempt to fix Coverity ID 596 Jeremy, please check & push if it's ok. (This used to be commit f06070c188d6d2efed3205bbc9c3c290718397b1) --- source3/winbindd/winbindd_passdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index e4cf029225..8387565a74 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -217,7 +217,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, (*names)[i] = CONST_DISCARD(char *, nam); } - if (domain_name == NULL) { + if (*domain_name == NULL) { *domain_name = CONST_DISCARD(char *, dom); } else { char *dname = CONST_DISCARD(char *, dom); -- cgit From ee6c02f7c8bc92190b9f5474057f5885f29c2f8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Aug 2008 19:23:38 -0700 Subject: Fix bug 5696. The problem was when smbd was asking for a winbindd name to SID lookup of "Unix Group\name" where "name" was also a valid username, the winbindd passdb lookup of that name was losing the domain string info before calling lookup name (ie. lookup_name() was being called with just the string "name", not the full string "Unix Group\name"). The passdb backend of winbindd has to cope with not only names from it's own global SAM domain, but it does lookups for BUILTIN and "Unix User" and "Unix Group" also, so making it guess by losing the domain string is "A Bad Idea" (tm) :-). Note that as winbind globally calls winbind_off() at startup, it's safe for winbind to call sys_getgrnam() to do the "Unix Group" lookup from inside lookup_name(). Jeremy. (This used to be commit 5293af6c3cbfdde340e6add47b914b6ee6fd7b6f) --- source3/winbindd/winbindd_passdb.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 8387565a74..5677c01be1 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -94,6 +94,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DOM_SID *sid, enum lsa_SidType *type) { + const char *fullname; uint32 flags = LOOKUP_NAME_ALL; switch ( original_cmd ) { @@ -107,12 +108,27 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, break; } - DEBUG(10, ("Finding name %s\n", name)); + if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) { + fullname = talloc_asprintf(mem_ctx, "%s\\%s", + domain_name, name); + if (fullname == NULL) { + return NT_STATUS_NO_MEMORY; + } + } else { + fullname = name; + } + + DEBUG(10, ("Finding fullname %s\n", fullname)); - if ( !lookup_name( mem_ctx, name, flags, NULL, NULL, sid, type ) ) { + if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) { return NT_STATUS_NONE_MAPPED; } + DEBUG(10, ("name_to_sid for %s returned %s (%s)\n", + fullname, + sid_string_dbg(sid), + sid_type_lookup((uint32)*type))); + return NT_STATUS_OK; } -- cgit From 5e7655fa27f7b2c9c54edfc25f86974dbdb23ea4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 17 Aug 2008 19:54:41 -0400 Subject: Split lookup_name() and create a new functiong called lookup_domain_name(). This new function accept separated strings for domain and name. (This used to be commit 8594edf666c29fd4ddf1780da842683dd81483b6) --- source3/winbindd/winbindd_passdb.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index 5677c01be1..fbe4a27abf 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -94,8 +94,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DOM_SID *sid, enum lsa_SidType *type) { - const char *fullname; uint32 flags = LOOKUP_NAME_ALL; + bool res; switch ( original_cmd ) { case WINBINDD_LOOKUPNAME: @@ -107,28 +107,26 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n")); break; } - - if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) { - fullname = talloc_asprintf(mem_ctx, "%s\\%s", - domain_name, name); - if (fullname == NULL) { - return NT_STATUS_NO_MEMORY; - } + + DEBUG(10, ("looking up name [%s\\%s] (domain\\name) \n", + domain_name?domain_name:"(NULL)", name)); + + if (strchr_m(name, '\\')) { + res = lookup_name(mem_ctx, name, flags, NULL, NULL, sid, type); } else { - fullname = name; + res = lookup_domain_name(mem_ctx, domain_name, name, flags, + NULL, NULL, sid, type); } - DEBUG(10, ("Finding fullname %s\n", fullname)); - - if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) { + if (!res) { return NT_STATUS_NONE_MAPPED; } - DEBUG(10, ("name_to_sid for %s returned %s (%s)\n", - fullname, + DEBUG(10, ("name_to_sid for [%s\\%s] returned %s (%s)\n", + domain_name?domain_name:"(NULL)", name, sid_string_dbg(sid), sid_type_lookup((uint32)*type))); - + return NT_STATUS_OK; } -- cgit From 9f28b99ba8c3fa36abc775880a2571dad1c01c10 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 01:18:24 +0200 Subject: winbindd: kill some trailing/leading whitespace. Guenther (This used to be commit b5bb7844952a87b123551b478b60bfe232afc308) --- source3/winbindd/winbindd_pam.c | 318 ++++++++++++++++++++-------------------- 1 file changed, 159 insertions(+), 159 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 0f9f1e1621..01cdc4d2e9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -310,8 +310,8 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, TALLOC_FREE(frame); - status = sid_array_from_info3(mem_ctx, info3, - &token->user_sids, + status = sid_array_from_info3(mem_ctx, info3, + &token->user_sids, &token->num_sids, true, false); if (!NT_STATUS_IS_OK(status)) { @@ -338,13 +338,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } } - + /* Do not distinguish this error from a wrong username/pw */ return NT_STATUS_LOGON_FAILURE; } -struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, +struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, const char *domain_name) { struct winbindd_domain *domain; @@ -353,7 +353,7 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { DEBUG(3, ("Authentication for domain [%s] refused " - "as it is not a trusted domain\n", + "as it is not a trusted domain\n", domain_name)); } return domain; @@ -370,12 +370,12 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, if (state->request.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) { domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { - DEBUG(3, ("Authentication for domain [%s] skipped " - "as it is not a trusted domain\n", + DEBUG(3, ("Authentication for domain [%s] skipped " + "as it is not a trusted domain\n", domain_name)); } else { return domain; - } + } } return find_our_domain(); @@ -387,7 +387,7 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); /* we might have given a more useful error above */ - if (*resp->data.auth.error_string == '\0') + if (*resp->data.auth.error_string == '\0') fstrcpy(resp->data.auth.error_string, get_friendly_nt_error_msg(result)); resp->data.auth.pam_error = nt_status_to_pam(result); @@ -402,9 +402,9 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(5,("fillup_password_policy: No inbound trust to " - "contact domain %s\n", domain->name)); + "contact domain %s\n", domain->name)); return NT_STATUS_NOT_SUPPORTED; - } + } methods = domain->methods; @@ -427,8 +427,8 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, return NT_STATUS_OK; } -static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, +static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, uint16 *lockout_threshold) { struct winbindd_methods *methods; @@ -449,8 +449,8 @@ static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain return NT_STATUS_OK; } -static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, +static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, uint32 *password_properties) { struct winbindd_methods *methods; @@ -473,7 +473,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, #ifdef HAVE_KRB5 -static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, +static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *type, uid_t uid, bool *internal_ccache) @@ -532,11 +532,11 @@ static void setup_return_cc_name(struct winbindd_cli_state *state, const char *c if (!strequal(type, "FILE") && !strequal(type, "WRFILE")) { - DEBUG(10,("won't return krbccname for a %s type ccache\n", + DEBUG(10,("won't return krbccname for a %s type ccache\n", type)); return; } - + fstrcpy(state->response.data.auth.krb5ccname, cc); } @@ -582,8 +582,8 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, ZERO_STRUCTP(info3); *info3 = NULL; - - /* 1st step: + + /* 1st step: * prepare a krb5_cc_cache string for the user */ uid = get_uid_from_state(state); @@ -593,31 +593,31 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, cc = generate_krb5_ccache(state->mem_ctx, state->request.data.auth.krb5_cc_type, - state->request.data.auth.uid, + state->request.data.auth.uid, &internal_ccache); if (cc == NULL) { return NT_STATUS_NO_MEMORY; } - /* 2nd step: + /* 2nd step: * get kerberos properties */ - + if (domain->private_data) { ads = (ADS_STRUCT *)domain->private_data; - time_offset = ads->auth.time_offset; + time_offset = ads->auth.time_offset; } - /* 3rd step: + /* 3rd step: * do kerberos auth and setup ccache as the user */ parse_domain_user(state->request.data.auth.user, name_domain, name_user); realm = domain->alt_name; strupper_m(realm); - - principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); if (principal_s == NULL) { return NT_STATUS_NO_MEMORY; } @@ -665,7 +665,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, * environment */ if (!internal_ccache) { - + setup_return_cc_name(state, cc); result = add_ccache_to_list(principal_s, @@ -676,11 +676,11 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid, time(NULL), ticket_lifetime, - renewal_until, + renewal_until, False); if (!NT_STATUS_IS_OK(result)) { - DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", + DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", nt_errstr(result))); } } else { @@ -836,7 +836,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) } /* Parse domain and username */ - + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); if (!canonicalize_username(state->request.data.auth.user, @@ -869,7 +869,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; - uint16 max_allowed_bad_attempts; + uint16 max_allowed_bad_attempts; fstring name_domain, name_user; DOM_SID sid; enum lsa_SidType type; @@ -890,7 +890,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, DEBUG(10,("winbindd_dual_pam_auth_cached\n")); /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); @@ -908,10 +908,10 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, return NT_STATUS_LOGON_FAILURE; } - result = winbindd_get_creds(domain, - state->mem_ctx, - &sid, - &my_info3, + result = winbindd_get_creds(domain, + state->mem_ctx, + &sid, + &my_info3, &cached_nt_pass, &cached_salt); if (!NT_STATUS_IS_OK(result)) { @@ -947,31 +947,31 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - + my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; - + if (my_info3->base.acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; } - + if (my_info3->base.acct_flags & ACB_DISABLED) { return NT_STATUS_ACCOUNT_DISABLED; } - + if (my_info3->base.acct_flags & ACB_WSTRUST) { return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } - + if (my_info3->base.acct_flags & ACB_SVRTRUST) { return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } - + if (my_info3->base.acct_flags & ACB_DOMTRUST) { return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (!(my_info3->base.acct_flags & ACB_NORMAL)) { - DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", + DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", my_info3->base.acct_flags)); return NT_STATUS_LOGON_FAILURE; } @@ -988,7 +988,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } - + #ifdef HAVE_KRB5 if ((state->request.flags & WBFLAG_PAM_KRB5) && ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && @@ -1113,7 +1113,7 @@ failed: my_info3); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", + DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", nt_errstr(result))); } @@ -1121,7 +1121,7 @@ failed: } NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, - struct winbindd_cli_state *state, + struct winbindd_cli_state *state, struct netr_SamInfo3 **info3) { struct winbindd_domain *contact_domain; @@ -1129,38 +1129,38 @@ NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, NTSTATUS result; DEBUG(10,("winbindd_dual_pam_auth_kerberos\n")); - + /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); /* what domain should we contact? */ - + if ( IS_DC ) { if (!(contact_domain = find_domain_from_name(name_domain))) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request.data.auth.user, name_domain, name_user, name_domain)); + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } - + } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } - + contact_domain = find_domain_from_name(name_domain); if (contact_domain == NULL) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request.data.auth.user, name_domain, name_user, name_domain)); + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); contact_domain = find_our_domain(); } } - if (contact_domain->initialized && + if (contact_domain->initialized && contact_domain->active_directory) { goto try_login; } @@ -1212,13 +1212,13 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, *info3 = NULL; DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); - + /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); /* do password magic */ - + generate_random_buffer(chal, 8); if (lp_client_ntlmv2_auth()) { @@ -1226,17 +1226,17 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, DATA_BLOB names_blob; DATA_BLOB nt_response; DATA_BLOB lm_response; - server_chal = data_blob_talloc(state->mem_ctx, chal, 8); - + server_chal = data_blob_talloc(state->mem_ctx, chal, 8); + /* note that the 'workgroup' here is a best guess - we don't know the server's domain at this point. The 'server name' is also - dodgy... + dodgy... */ names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); - - if (!SMBNTLMv2encrypt(name_user, name_domain, - state->request.data.auth.pass, - &server_chal, + + if (!SMBNTLMv2encrypt(name_user, name_domain, + state->request.data.auth.pass, + &server_chal, &names_blob, &lm_response, &nt_response, NULL)) { data_blob_free(&names_blob); @@ -1255,35 +1255,35 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, data_blob_free(&nt_response); } else { - if (lp_client_lanman_auth() - && SMBencrypt(state->request.data.auth.pass, - chal, + if (lp_client_lanman_auth() + && SMBencrypt(state->request.data.auth.pass, + chal, local_lm_response)) { - lm_resp = data_blob_talloc(state->mem_ctx, - local_lm_response, + lm_resp = data_blob_talloc(state->mem_ctx, + local_lm_response, sizeof(local_lm_response)); } else { lm_resp = data_blob_null; } - SMBNTencrypt(state->request.data.auth.pass, + SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); - nt_resp = data_blob_talloc(state->mem_ctx, - local_nt_response, + nt_resp = data_blob_talloc(state->mem_ctx, + local_nt_response, sizeof(local_nt_response)); } - + /* what domain should we contact? */ - + if ( IS_DC ) { if (!(contact_domain = find_domain_from_name(name_domain))) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request.data.auth.user, name_domain, name_user, name_domain)); + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth.user, name_domain, name_user, name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } - + } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); @@ -1312,7 +1312,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* It is really important to try SamLogonEx here, * because in a clustered environment, we want to use * one machine account from multiple physical - * computers. + * computers. * * With a normal SamLogon call, we must keep the * credentials chain updated and intact between all @@ -1326,7 +1326,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * When using SamLogonEx, the credentials are not * supplied, but the session key is implied by the * wrapping SamLogon context. - * + * * -- abartlet 21 April 2008 */ @@ -1364,12 +1364,12 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, retry = True; continue; } - + /* if we get access denied, a possible cause was that we had and open connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ - + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("winbindd_pam_auth: sam_logon returned " "ACCESS_DENIED. Maybe the trust account " @@ -1378,15 +1378,15 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, name_domain)); invalidate_cm_connection(&contact_domain->conn); retry = True; - } - + } + } while ( (attempts < 2) && retry ); /* handle the case where a NT4 DC does not fill in the acct_flags in * the samlogon reply info3. When accurate info3 is required by the * caller, we look up the account flags ourselve - gd */ - if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && + if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) { struct rpc_pipe_client *samr_pipe; @@ -1395,11 +1395,11 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, NTSTATUS status_tmp; uint32 acct_flags; - status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, + status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, &samr_pipe, &samr_domain_handle); if (!NT_STATUS_IS_OK(status_tmp)) { - DEBUG(3, ("could not open handle to SAMR pipe: %s\n", + DEBUG(3, ("could not open handle to SAMR pipe: %s\n", nt_errstr(status_tmp))); goto done; } @@ -1448,10 +1448,10 @@ done: } enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; - NTSTATUS krb5_result = NT_STATUS_OK; + NTSTATUS krb5_result = NT_STATUS_OK; fstring name_domain, name_user; struct netr_SamInfo3 *info3 = NULL; @@ -1470,7 +1470,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } /* Parse domain and username */ - + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); parse_domain_user(state->request.data.auth.user, name_domain, name_user); @@ -1494,11 +1494,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, /* Check for Kerberos authentication */ if (domain->online && (state->request.flags & WBFLAG_PAM_KRB5)) { - + result = winbindd_dual_pam_auth_kerberos(domain, state, &info3); /* save for later */ krb5_result = result; - + if (NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n")); @@ -1512,7 +1512,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n")); set_domain_offline( domain ); - goto cached_logon; + goto cached_logon; } /* there are quite some NT_STATUS errors where there is no @@ -1531,7 +1531,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { goto process_result; } - + if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) { DEBUG(3,("falling back to samlogon\n")); goto sam_logon; @@ -1544,7 +1544,7 @@ sam_logon: /* Check for Samlogon authentication */ if (domain->online) { result = winbindd_dual_pam_auth_samlogon(domain, state, &info3); - + if (NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n")); /* add the Krb5 err if we have one */ @@ -1552,18 +1552,18 @@ sam_logon: info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW; } goto process_result; - } + } - DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", + DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", nt_errstr(result))); if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) || NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) || - NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) + NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n")); set_domain_offline( domain ); - goto cached_logon; + goto cached_logon; } if (domain->online) { @@ -1574,9 +1574,9 @@ sam_logon: cached_logon: /* Check for Cached logons */ - if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && + if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && lp_winbind_offline_logon()) { - + result = winbindd_dual_pam_auth_cached(domain, state, &info3); if (NT_STATUS_IS_OK(result)) { @@ -1591,7 +1591,7 @@ cached_logon: process_result: if (NT_STATUS_IS_OK(result)) { - + DOM_SID user_sid; /* In all codepaths where result == NT_STATUS_OK info3 must have @@ -1608,19 +1608,19 @@ process_result: this is our primary domain so we don't invalidate the cache entry by storing the seq_num for the wrong domain). */ - if ( domain->primary ) { + if ( domain->primary ) { sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); - cache_name2sid(domain, name_domain, name_user, + cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid); } - + /* Check if the user is in the right group */ if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, state->request.data.auth.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", - state->request.data.auth.user, + state->request.data.auth.user, state->request.data.auth.require_membership_of_sid)); goto done; } @@ -1665,8 +1665,8 @@ process_result: /* This is not entirely correct I believe, but it is consistent. Only apply the password policy settings - too warn users for our own domain. Cannot obtain these - from trusted DCs all the time so don't do it at all. + too warn users for our own domain. Cannot obtain these + from trusted DCs all the time so don't do it at all. -- jerry */ result = NT_STATUS_NOT_SUPPORTED; @@ -1674,16 +1674,16 @@ process_result: result = fillup_password_policy(our_domain, state); } - if (!NT_STATUS_IS_OK(result) - && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) + if (!NT_STATUS_IS_OK(result) + && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) { - DEBUG(10,("Failed to get password policies for domain %s: %s\n", + DEBUG(10,("Failed to get password policies for domain %s: %s\n", domain->name, nt_errstr(result))); goto done; } } - result = NT_STATUS_OK; + result = NT_STATUS_OK; } done: @@ -1692,26 +1692,26 @@ done: (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } - + state->response.data.auth.nt_status = NT_STATUS_V(result); fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); /* we might have given a more useful error above */ - if (!*state->response.data.auth.error_string) + if (!*state->response.data.auth.error_string) fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", - state->request.data.auth.user, + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", + state->request.data.auth.user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } /********************************************************************** - Challenge Response Authentication Protocol + Challenge Response Authentication Protocol **********************************************************************/ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) @@ -1775,7 +1775,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) set_auth_errors(&state->response, result); DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n", state->request.data.auth_crap.domain, - state->request.data.auth_crap.user, + state->request.data.auth_crap.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -1784,7 +1784,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result; struct netr_SamInfo3 *info3 = NULL; @@ -1817,7 +1817,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } else if (lp_winbind_use_default_domain()) { name_domain = lp_workgroup(); } else { - DEBUG(5,("no domain specified with username (%s) - failing auth\n", + DEBUG(5,("no domain specified with username (%s) - failing auth\n", name_user)); result = NT_STATUS_NO_SUCH_USER; goto done; @@ -1825,7 +1825,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, name_domain, name_user)); - + if (*state->request.data.auth_crap.workstation) { workstation = state->request.data.auth_crap.workstation; } else { @@ -1834,8 +1834,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { - DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", - state->request.data.auth_crap.lm_resp_len, + DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", + state->request.data.auth_crap.lm_resp_len, state->request.data.auth_crap.nt_resp_len)); result = NT_STATUS_INVALID_PARAMETER; goto done; @@ -1847,11 +1847,11 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.nt_resp_len); /* what domain should we contact? */ - + if ( IS_DC ) { if (!(contact_domain = find_domain_from_name(name_domain))) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request.data.auth_crap.user, name_domain, name_user, name_domain)); + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth_crap.user, name_domain, name_user, name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } @@ -1887,7 +1887,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.logon_parameters, contact_domain->dcname, name_user, - name_domain, + name_domain, /* Bug #3248 - found by Stefan Burkei. */ workstation, /* We carefully set this above so use it... */ state->request.data.auth_crap.chal, @@ -1918,7 +1918,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, /* if we get access denied, a possible cause was that we had and open connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ - + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("winbindd_pam_auth: sam_logon returned " "ACCESS_DENIED. Maybe the trust account " @@ -1927,7 +1927,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, name_domain)); invalidate_cm_connection(&contact_domain->conn); retry = True; - } + } } while ( (attempts < 2) && retry ); @@ -1942,7 +1942,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so " "crap authentication is rejected\n", - state->request.data.auth_crap.user, + state->request.data.auth_crap.user, state->request.data.auth_crap.require_membership_of_sid)); goto done; } @@ -1974,12 +1974,12 @@ done: } state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", name_domain, name_user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2002,7 +2002,7 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s" "(PAM: %d)\n", - state->request.data.auth.user, + state->request.data.auth.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -2012,8 +2012,8 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) contact_domain = find_domain_from_name(domain); if (!contact_domain) { set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); - DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", - state->request.data.chauthtok.user, domain, user, domain)); + DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", + state->request.data.chauthtok.user, domain, user, domain)); request_error(state); return; } @@ -2092,18 +2092,18 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); - + result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. Map to the same status code as Windows 2003. */ if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) { - result = NT_STATUS_PASSWORD_RESTRICTION; + result = NT_STATUS_PASSWORD_RESTRICTION; } } -done: +done: if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { @@ -2151,7 +2151,7 @@ done: if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { NTSTATUS policy_ret; - + policy_ret = fillup_password_policy(contact_domain, state); /* failure of this is non critical, it will just provide no @@ -2171,12 +2171,12 @@ process_result: fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", domain, user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2211,7 +2211,7 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) } if ((sys_getpeereid(state->sock, &caller_uid)) != 0) { - DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", + DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", strerror(errno))); goto failed; } @@ -2247,7 +2247,7 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) } enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result = NT_STATUS_NOT_SUPPORTED; @@ -2265,7 +2265,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, } #ifdef HAVE_KRB5 - + if (state->request.data.logoff.uid < 0) { DEBUG(0,("winbindd_pam_logoff: invalid uid\n")); goto process_result; @@ -2280,7 +2280,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, goto process_result; } - if (!ccache_entry_identical(state->request.data.logoff.user, + if (!ccache_entry_identical(state->request.data.logoff.user, state->request.data.logoff.uid, state->request.data.logoff.krb5ccname)) { DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n")); @@ -2322,12 +2322,12 @@ void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; state->request.data.chng_pswd_auth_crap.domain[ sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; - + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", (unsigned long)state->pid, state->request.data.chng_pswd_auth_crap.domain, state->request.data.chng_pswd_auth_crap.user)); - + if (*state->request.data.chng_pswd_auth_crap.domain != '\0') { domain_name = state->request.data.chng_pswd_auth_crap.domain; } else if (lp_winbind_use_default_domain()) { @@ -2347,7 +2347,7 @@ void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n", state->request.data.chng_pswd_auth_crap.domain, - state->request.data.chng_pswd_auth_crap.user, + state->request.data.chng_pswd_auth_crap.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -2373,7 +2373,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; *domain = 0; *user = 0; - + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", (unsigned long)state->pid, state->request.data.chng_pswd_auth_crap.domain, @@ -2411,7 +2411,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, domain, user)); - + /* Change password */ new_nt_password = data_blob_talloc( state->mem_ctx, @@ -2450,18 +2450,18 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, new_lm_password, old_lm_hash_enc); - done: + done: state->response.data.auth.nt_status = NT_STATUS_V(result); fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", domain, user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -- cgit From 4289e4b87805b95c4147cfd4cce4abbf19cd7f05 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:31:10 +0200 Subject: winbindd: fill_in_password_policy (to avoid redundant code). Guenther (This used to be commit dbfa7ba14c9f1a4d7a1e7205dd0b3ea2fc2e6131) --- source3/winbindd/winbindd_pam.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 01cdc4d2e9..a808b37791 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -393,6 +393,21 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) resp->data.auth.pam_error = nt_status_to_pam(result); } +static void fill_in_password_policy(struct winbindd_response *r, + const struct samr_DomInfo1 *p) +{ + r->data.auth.policy.min_length_password = + p->min_password_length; + r->data.auth.policy.password_history = + p->password_history_length; + r->data.auth.policy.password_properties = + p->password_properties; + r->data.auth.policy.expire = + nt_time_to_unix_abs((NTTIME *)&(p->max_password_age)); + r->data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&(p->min_password_age)); +} + static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, struct winbindd_cli_state *state) { @@ -413,16 +428,7 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, return status; } - state->response.data.auth.policy.min_length_password = - password_policy.min_password_length; - state->response.data.auth.policy.password_history = - password_policy.password_history_length; - state->response.data.auth.policy.password_properties = - password_policy.password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs((NTTIME *)&(password_policy.max_password_age)); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs((NTTIME *)&(password_policy.min_password_age)); + fill_in_password_policy(&state->response, &password_policy); return NT_STATUS_OK; } @@ -2068,16 +2074,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { - state->response.data.auth.policy.min_length_password = - info->min_password_length; - state->response.data.auth.policy.password_history = - info->password_history_length; - state->response.data.auth.policy.password_properties = - info->password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs((NTTIME *)&info->max_password_age); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs((NTTIME *)&info->min_password_age); + + fill_in_password_policy(&state->response, info); state->response.data.auth.reject_reason = reject->reason; -- cgit From d9484d43318e5456ed9d177a399850bd6f949fcd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:31:35 +0200 Subject: winbindd: use set_auth_errors (avoid code duplication). Guenther (This used to be commit ae35a5110ea03d8ff27f320cdc685e5623715a2a) --- source3/winbindd/winbindd_pam.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index a808b37791..1cddfe391f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1699,13 +1699,7 @@ done: result = NT_STATUS_NO_LOGON_SERVERS; } - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - - /* we might have given a more useful error above */ - if (!*state->response.data.auth.error_string) - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", state->request.data.auth.user, @@ -1971,14 +1965,7 @@ done: result = nt_status_squash(result); } - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - - /* we might have given a more useful error above */ - if (!*state->response.data.auth.error_string) { - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - } - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", @@ -2164,10 +2151,7 @@ done: process_result: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", @@ -2300,10 +2284,7 @@ process_result: winbindd_delete_memory_creds(state->request.data.logoff.user); - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2449,11 +2430,8 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai new_lm_password, old_lm_hash_enc); done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, - get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", -- cgit From 477e6bb40d83dc53829cd8bdbb15ca9759872ca5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:03:13 +0200 Subject: winbindd: consistently use false/true. Guenther (This used to be commit e8619121d16d086f1ab186051d0ecdc83c02e5b5) --- source3/winbindd/winbindd_pam.c | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 1cddfe391f..4beef852e9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -176,7 +176,7 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, } fill_domain_username(state->response.data.auth.unix_username, - nt_domain, nt_username, True); + nt_domain, nt_username, true); DEBUG(5,("Setting unix username to [%s]\n", state->response.data.auth.unix_username)); @@ -490,7 +490,7 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *gen_cc = NULL; - *internal_ccache = True; + *internal_ccache = true; if (uid == -1) { goto memory_ccache; @@ -509,7 +509,7 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, goto memory_ccache; } - *internal_ccache = False; + *internal_ccache = false; goto done; memory_ccache: @@ -583,7 +583,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid_t uid = -1; ADS_STRUCT *ads; time_t time_offset = 0; - bool internal_ccache = True; + bool internal_ccache = true; ZERO_STRUCTP(info3); @@ -650,8 +650,8 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, &ticket_lifetime, &renewal_until, cc, - True, - True, + true, + true, WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, info3); if (!internal_ccache) { @@ -683,7 +683,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, time(NULL), ticket_lifetime, renewal_until, - False); + false); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", @@ -743,12 +743,12 @@ static bool check_request_flags(uint32_t flags) ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| !(flags & flags_edata) ) { - return True; + return true; } DEBUG(1,("check_request_flags: invalid request flags[0x%08X]\n",flags)); - return False; + return false; } /**************************************************************** @@ -884,7 +884,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, const uint8 *cached_salt; struct netr_SamInfo3 *my_info3; time_t kickoff_time, must_change_time; - bool password_good = False; + bool password_good = false; #ifdef HAVE_KRB5 struct winbindd_tdc_domain *tdc_domain = NULL; #endif @@ -942,11 +942,11 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, E_md5hash(cached_salt, new_nt_pass, salted_hash); password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ? - True : False; + true : false; } else { /* Old cached cred - direct store of nt_hash (bad bad bad !). */ password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ? - True : False; + true : false; } if (password_good) { @@ -1005,7 +1005,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, char *realm = NULL; const char *principal_s = NULL; const char *service = NULL; - bool internal_ccache = False; + bool internal_ccache = false; uid = get_uid_from_state(state); if (uid == -1) { @@ -1047,7 +1047,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, time(NULL), time(NULL) + lp_winbind_cache_time(), time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, - True); + true); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_dual_pam_auth_cached: failed " @@ -1306,7 +1306,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, netlogon_fn_t logon_fn; ZERO_STRUCTP(my_info3); - retry = False; + retry = false; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1357,8 +1357,8 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, && contact_domain->can_do_samlogon_ex) { DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; + contact_domain->can_do_samlogon_ex = false; + retry = true; continue; } @@ -1367,7 +1367,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, our connection. */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { - retry = True; + retry = true; continue; } @@ -1383,7 +1383,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, "Killing connections to domain %s\n", name_domain)); invalidate_cm_connection(&contact_domain->conn); - retry = True; + retry = true; } } while ( (attempts < 2) && retry ); @@ -1481,7 +1481,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, parse_domain_user(state->request.data.auth.user, name_domain, name_user); - if (domain->online == False) { + if (domain->online == false) { result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; if (domain->startup) { /* Logons are very important to users. If we're offline and @@ -1867,7 +1867,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, do { netlogon_fn_t logon_fn; - retry = False; + retry = false; netlogon_pipe = NULL; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1899,8 +1899,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, && contact_domain->can_do_samlogon_ex) { DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; + contact_domain->can_do_samlogon_ex = false; + retry = true; continue; } @@ -1911,7 +1911,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, our connection. */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { - retry = True; + retry = true; continue; } @@ -1926,7 +1926,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, "Killing connections to domain %s\n", name_domain)); invalidate_cm_connection(&contact_domain->conn); - retry = True; + retry = true; } } while ( (attempts < 2) && retry ); @@ -2021,7 +2021,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact char *newpass = NULL; POLICY_HND dom_pol; struct rpc_pipe_client *cli; - bool got_info = False; + bool got_info = false; struct samr_DomInfo1 *info = NULL; struct samr_ChangeReject *reject = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -2067,7 +2067,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact state->response.data.auth.reject_reason = reject->reason; - got_info = True; + got_info = true; } /* only fallback when the chgpasswd_user3 call is not supported */ -- cgit From 79150da70bbfddea3dc4013212fc7314b1004534 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Aug 2008 16:24:22 -0700 Subject: Here is a re-working of the winbindd reconnect code to cope with rebooting a DC. This replaces the code I asked Volker to revert. The logic is pretty simple. It adds a new parameter, "winbind reconnect delay", set to 30 seconds by default, which determines how long to wait between connection attempts. To avoid overwhelming the box with DC-probe forked children, the code now keeps track of the DC probe child per winbindd_domain struct and only starts a new one if the existing one has died. I also added a little logic to make sure the dc probe child always sends a message whatever the reason for exit so we will always reschedule another connect attempt. Also added documentation. Jeremy. (This used to be commit 8027197635b988b3dcf9d3d00126a024e768fa62) --- source3/winbindd/winbindd.h | 1 + source3/winbindd/winbindd_cm.c | 39 +++++++++++++++++++++++++++++++-------- source3/winbindd/winbindd_util.c | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index fe0c076209..1b8cd9163f 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -204,6 +204,7 @@ struct winbindd_domain { uint32_t id_range_low, id_range_high; /* A working DC */ + pid_t dc_probe_pid; /* Child we're using to detect the DC. */ fstring dcname; struct sockaddr_storage dcaddr; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 47df4e4058..69e95b1c05 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -171,20 +171,33 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) struct dc_name_ip *dcs = NULL; int num_dcs = 0; TALLOC_CTX *mem_ctx = NULL; - pid_t child_pid; pid_t parent_pid = sys_getpid(); /* Stop zombies */ CatchChild(); - child_pid = sys_fork(); + if (domain->dc_probe_pid != (pid_t)-1) { + /* + * We might already have a DC probe + * child working, check. + */ + if (process_exists_by_pid(domain->dc_probe_pid)) { + DEBUG(10,("fork_child_dc_connect: pid %u already " + "checking for DC's.\n", + (unsigned int)domain->dc_probe_pid)); + return true; + } + domain->dc_probe_pid = (pid_t)-1; + } - if (child_pid == -1) { + domain->dc_probe_pid = sys_fork(); + + if (domain->dc_probe_pid == (pid_t)-1) { DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno))); return False; } - if (child_pid != 0) { + if (domain->dc_probe_pid != (pid_t)0) { /* Parent */ messaging_register(winbind_messaging_context(), NULL, MSG_WINBIND_TRY_TO_GO_ONLINE, @@ -201,6 +214,11 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) if (!reinit_after_fork(winbind_messaging_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_FAILED_TO_GO_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); _exit(0); } @@ -218,6 +236,11 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) mem_ctx = talloc_init("fork_child_dc_connect"); if (!mem_ctx) { DEBUG(0,("talloc_init failed.\n")); + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_FAILED_TO_GO_ONLINE, + (uint8 *)domain->name, + strlen(domain->name)+1); _exit(0); } @@ -291,12 +314,12 @@ static void check_domain_online_handler(struct event_context *ctx, static void calc_new_online_timeout_check(struct winbindd_domain *domain) { - int wbc = lp_winbind_cache_time(); + int wbr = lp_winbind_reconnect_delay(); if (domain->startup) { domain->check_online_timeout = 10; - } else if (domain->check_online_timeout < wbc) { - domain->check_online_timeout = wbc; + } else if (domain->check_online_timeout < wbr) { + domain->check_online_timeout = wbr; } } @@ -336,7 +359,7 @@ void set_domain_offline(struct winbindd_domain *domain) } /* If we're in statup mode, check again in 10 seconds, not in - lp_winbind_cache_time() seconds (which is 5 mins by default). */ + lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */ calc_new_online_timeout_check(domain); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 77b17787c9..4668d3725d 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -180,11 +180,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const domain->initialized = False; domain->online = is_internal_domain(sid); domain->check_online_timeout = 0; + domain->dc_probe_pid = (pid_t)-1; if (sid) { sid_copy(&domain->sid, sid); } - /* Link to domain list */ DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *); -- cgit From 7e0314f6a29dd36e3911a21972aedb76270f1313 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 22 Aug 2008 10:17:04 -0500 Subject: winbindd: Fix crash in cm_connect_sam() Fix segv when talking to parent DC (joined to child domain). The root cause was (a) storing the parent domain in the cli_state struct caused the NTLMSSP pipe bind to fail which made us fallover to the schannel code path (b) the dcinfo pointer in cm_get_schannel_dcinfo() was returning NULL even though the function indicated success. (This used to be commit 5ce4a2ae6697970ea37d0078a506615b4b7a9a9c) --- source3/winbindd/winbindd_cm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 69e95b1c05..6db45f72c3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -875,7 +875,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, domain->name, machine_password); + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); goto session_setup_done; } } @@ -900,7 +900,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, domain->name, machine_password); + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); goto session_setup_done; } } @@ -1927,6 +1927,10 @@ static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain, /* Return a pointer to the struct dcinfo from the netlogon pipe. */ + if (!domain->conn.netlogon_pipe->dc) { + return false; + } + *ppdc = domain->conn.netlogon_pipe->dc; return True; } @@ -1953,6 +1957,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto done; } + /* * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated * sign and sealed pipe using the machine account password by -- cgit From 5571bd29131ae8b27c25b478e2dd831aef99580c Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 22 Aug 2008 14:54:50 -0500 Subject: idmap_gid_to_sid: Fix a cut-a-npaste error. The call was looking up a uid and not gid in the cache. (This used to be commit 25293ba1507f8f8fa7e33c302200184e980bb123) --- source3/winbindd/idmap_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c index 2a6beca5a2..b10a1a4ba9 100644 --- a/source3/winbindd/idmap_util.c +++ b/source3/winbindd/idmap_util.c @@ -87,7 +87,7 @@ NTSTATUS idmap_gid_to_sid(const char *domname, DOM_SID *sid, gid_t gid) DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); - if (idmap_cache_find_uid2sid(gid, sid, &expired)) { + if (idmap_cache_find_gid2sid(gid, sid, &expired)) { DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n", gid, expired ? " (expired)": "")); if (expired && idmap_is_online()) { -- cgit From 4a5ccfb91f8d427fe9fa83cab992587fe6ce70c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Aug 2008 13:49:46 -0700 Subject: Don't re-initialize a token when we already have one. This fixes the build farm failures when winbindd connects as guest. This one took a *lot* of tracking down :-). Jeremy. (This used to be commit dca827791276906436452c650062164eb819dfe0) --- source3/winbindd/winbindd_cm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 6db45f72c3..a8c0166d27 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -937,6 +937,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, anon_fallback: /* Fall back to anonymous connection, this might fail later */ + DEBUG(10,("cm_prepare_connection: falling back to anonymous " + "connection for DC %s\n", + controller )); if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0, NULL, 0, ""))) { -- cgit From 6e89443ebacaa082c50935e4359f70686e1cc184 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 21 Aug 2008 01:20:22 +0200 Subject: winbindd: add event based machine password change. Guenther (This used to be commit 15b72d44cbde0b8a375d8ed3d045c40ae97ec05a) --- source3/winbindd/winbindd.h | 1 + source3/winbindd/winbindd_dual.c | 119 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 1b8cd9163f..04b0b39f81 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -153,6 +153,7 @@ struct winbindd_child { struct fd_event event; struct timed_event *lockout_policy_event; + struct timed_event *machine_password_change_event; struct winbindd_async_request *requests; const struct winbindd_child_dispatch_table *table; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 1e8325f983..aa6da545d3 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -840,6 +840,110 @@ static void account_lockout_policy_handler(struct event_context *ctx, child); } +static time_t get_machine_password_timeout(void) +{ + /* until we have gpo support use lp setting */ + return lp_machine_password_timeout(); +} + +static bool calculate_next_machine_pwd_change(const char *domain, + struct timeval *t) +{ + time_t pass_last_set_time; + time_t timeout; + time_t next_change; + + if (!secrets_fetch_machine_password(domain, + &pass_last_set_time, + NULL)) { + DEBUG(0,("cannot fetch own machine password ????")); + return false; + } + + timeout = get_machine_password_timeout(); + if (timeout == 0) { + DEBUG(10,("machine password never expires\n")); + return false; + } + + if (time(NULL) < (pass_last_set_time + timeout)) { + next_change = pass_last_set_time + timeout; + DEBUG(10,("machine password still valid until: %s\n", + http_timestring(next_change))); + *t = timeval_set(next_change, 0); + return true; + } + + DEBUG(10,("machine password expired, needs immediate change\n")); + + *t = timeval_zero(); + + return true; +} + +static void machine_password_change_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct winbindd_child *child = + (struct winbindd_child *)private_data; + struct rpc_pipe_client *netlogon_pipe = NULL; + TALLOC_CTX *mem_ctx = NULL; + NTSTATUS result; + struct timeval next_change; + + DEBUG(10,("machine_password_change_handler called\n")); + + TALLOC_FREE(child->machine_password_change_event); + + if (!calculate_next_machine_pwd_change(child->domain->name, + &next_change)) { + return; + } + + if (!winbindd_can_contact_domain(child->domain)) { + DEBUG(10,("machine_password_change_handler: Removing myself since I " + "do not have an incoming trust to domain %s\n", + child->domain->name)); + return; + } + + mem_ctx = talloc_init("machine_password_change_handler "); + if (!mem_ctx) { + return; + } + + result = cm_connect_netlogon(child->domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("machine_password_change_handler: " + "failed to connect netlogon pipe: %s\n", + nt_errstr(result))); + TALLOC_FREE(mem_ctx); + return; + } + + result = trust_pw_find_change_and_store_it(netlogon_pipe, + mem_ctx, + child->domain->name); + TALLOC_FREE(mem_ctx); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("machine_password_change_handler: " + "failed to change machine password: %s\n", + nt_errstr(result))); + } else { + DEBUG(10,("machine_password_change_handler: " + "successfully changed machine password\n")); + } + + child->machine_password_change_event = event_add_timed(winbind_event_context(), NULL, + next_change, + "machine_password_change_handler", + machine_password_change_handler, + child); +} + /* Deal with a request to go offline. */ static void child_msg_offline(struct messaging_context *msg, @@ -1138,6 +1242,21 @@ static bool fork_domain_child(struct winbindd_child *child) child); } + if (child->domain && !(child->domain->internal) && + lp_server_role() == ROLE_DOMAIN_MEMBER) { + + struct timeval next_change; + + if (calculate_next_machine_pwd_change(child->domain->name, + &next_change)) { + child->machine_password_change_event = event_add_timed( + winbind_event_context(), NULL, next_change, + "machine_password_change_handler", + machine_password_change_handler, + child); + } + } + while (1) { int ret; -- cgit From 03dfaf37fd34a696dd6c586ec10b3134c5af0341 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Aug 2008 13:12:05 +0200 Subject: Fix a memleak in calculate_next_machine_pwd_change (This used to be commit 5314f06dcdf14ce5e038a03a3e4dfded227bd00c) --- source3/winbindd/winbindd_dual.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index aa6da545d3..4d879c6fc4 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -852,14 +852,19 @@ static bool calculate_next_machine_pwd_change(const char *domain, time_t pass_last_set_time; time_t timeout; time_t next_change; + char *pw; - if (!secrets_fetch_machine_password(domain, + pw = secrets_fetch_machine_password(domain, &pass_last_set_time, - NULL)) { + NULL); + + if (pw == NULL) { DEBUG(0,("cannot fetch own machine password ????")); return false; } + SAFE_FREE(pw); + timeout = get_machine_password_timeout(); if (timeout == 0) { DEBUG(10,("machine password never expires\n")); -- cgit From c33e648fa5275c596d8047da8219531171245959 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Aug 2008 13:12:36 +0200 Subject: Use talloc_stackframe() in machine_password_change_handler (This used to be commit 79103000b13c95325534db749a0da638a3eb1807) --- source3/winbindd/winbindd_dual.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 4d879c6fc4..d958ed0110 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -894,7 +894,7 @@ static void machine_password_change_handler(struct event_context *ctx, struct winbindd_child *child = (struct winbindd_child *)private_data; struct rpc_pipe_client *netlogon_pipe = NULL; - TALLOC_CTX *mem_ctx = NULL; + TALLOC_CTX *frame; NTSTATUS result; struct timeval next_change; @@ -914,24 +914,20 @@ static void machine_password_change_handler(struct event_context *ctx, return; } - mem_ctx = talloc_init("machine_password_change_handler "); - if (!mem_ctx) { - return; - } - result = cm_connect_netlogon(child->domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("machine_password_change_handler: " "failed to connect netlogon pipe: %s\n", nt_errstr(result))); - TALLOC_FREE(mem_ctx); return; } + frame = talloc_stackframe(); + result = trust_pw_find_change_and_store_it(netlogon_pipe, - mem_ctx, + frame, child->domain->name); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("machine_password_change_handler: " -- cgit From d7d3b37d566785234f383c2f0538b92798f49e9e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Aug 2008 10:14:59 +0200 Subject: Fix some nonempty blank lines (This used to be commit 541e088656773d2b3b56a5a8bdc8dea6c9edec86) --- source3/winbindd/winbindd_cm.c | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a8c0166d27..71f1a56519 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -8,17 +8,17 @@ Copyright (C) Gerald (Jerry) Carter 2003-2005. Copyright (C) Volker Lendecke 2004-2005 Copyright (C) Jeremy Allison 2006 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -27,14 +27,14 @@ We need to manage connections to domain controllers without having to mess up the main winbindd code with other issues. The aim of the connection manager is to: - + - make connections to domain controllers and cache them - re-establish connections when networks or servers go down - centralise the policy on connection timeouts, domain controller selection etc - manage re-entrancy for when winbindd becomes able to handle multiple outstanding rpc requests - + Why not have connection management as part of the rpc layer like tng? Good question. This code may morph into libsmb/rpc_cache.c or something like that but at the moment it's simply staying as part of winbind. I @@ -383,7 +383,7 @@ void set_domain_offline(struct winbindd_domain *domain) if ( domain->primary ) { struct winbindd_child *idmap = idmap_child(); - + if ( idmap->pid != 0 ) { messaging_send_buf(winbind_messaging_context(), pid_to_procid(idmap->pid), @@ -462,7 +462,7 @@ static void set_domain_online(struct winbindd_domain *domain) if ( domain->primary ) { struct winbindd_child *idmap = idmap_child(); - + if ( idmap->pid != 0 ) { messaging_send_buf(winbind_messaging_context(), pid_to_procid(idmap->pid), @@ -553,7 +553,7 @@ void winbind_add_failed_connection_entry(const struct winbindd_domain *domain, an authenticated connection if DCs have the RestrictAnonymous registry entry set > 0, or the "Additional restrictions for anonymous connections" set in the win2k Local Security Policy. - + Caller to free() result in domain, username, password */ @@ -562,12 +562,12 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL); *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - + if (*username && **username) { if (!*domain || !**domain) *domain = smb_xstrdup(lp_workgroup()); - + if (!*password || !**password) *password = smb_xstrdup(""); @@ -703,7 +703,7 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, { const char *account_name; const char *name = NULL; - + /* If we are a DC and this is not our own domain */ if (IS_DC) { @@ -713,10 +713,10 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, if (!our_domain) return NT_STATUS_INVALID_SERVER_STATE; - + name = our_domain->name; } - + if (!get_trust_pw_clear(name, machine_password, &account_name, NULL)) { @@ -738,7 +738,7 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, if (!our_domain) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - + if (asprintf(machine_krb5_principal, "%s$@%s", account_name, our_domain->alt_name) == -1) { @@ -1342,7 +1342,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, TALLOC_FREE(dcnames); num_dcnames = 0; - + TALLOC_FREE(addrs); num_addrs = 0; @@ -1368,7 +1368,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, /* we have to check the server affinity cache here since later we selecte a DC based on response time and not preference */ - + /* Check the negative connection cache before talking to it. It going down may have triggered the reconnection. */ @@ -1618,26 +1618,26 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) TALLOC_CTX *mem_ctx = NULL; DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name )); - + /* Our primary domain doesn't need to worry about trust flags. Force it to go through the network setup */ if ( domain->primary ) { return False; } - + our_domain = find_our_domain(); - + if ( !connection_ok(our_domain) ) { DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n")); return False; } /* This won't work unless our domain is AD */ - + if ( !our_domain->active_directory ) { return False; } - + /* Use DsEnumerateDomainTrusts to get us the trust direction and type */ @@ -1698,13 +1698,13 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) if ( !winbindd_can_contact_domain( domain) ) domain->internal = True; - + break; } } - + talloc_destroy( mem_ctx ); - + return domain->initialized; } @@ -1801,7 +1801,7 @@ no_dssetup: result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); - + if (NT_STATUS_IS_OK(result)) { /* This particular query is exactly what Win2k clients use to determine that the DC is active directory */ @@ -2334,7 +2334,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); - + /* make sure we return something besides OK */ return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; } -- cgit From fd5b2f42068b461052687b96b6032eb02db065d5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 25 Aug 2008 11:37:57 +0200 Subject: winbindd: only create machine pwd change event when in primary domain child. Guenther (This used to be commit 543dfdc1cf6baf60bffc23c6aebc542fd58d2d2e) --- source3/winbindd/winbindd_dual.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index d958ed0110..916e8c07c7 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1243,7 +1243,7 @@ static bool fork_domain_child(struct winbindd_child *child) child); } - if (child->domain && !(child->domain->internal) && + if (child->domain && child->domain->primary && lp_server_role() == ROLE_DOMAIN_MEMBER) { struct timeval next_change; -- cgit From 66fa77ba9ed50b114131b0c071dbe1fcb658b755 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 25 Aug 2008 13:15:41 +0200 Subject: winbindd: move set_auth_errors to util functions. Guenther (This used to be commit ae3fa60c4546c7420722d8f422c22bbfd623ff5b) --- source3/winbindd/winbindd_pam.c | 12 ------------ source3/winbindd/winbindd_proto.h | 1 + source3/winbindd/winbindd_util.c | 12 ++++++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4beef852e9..a7911f60aa 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -381,18 +381,6 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, return find_our_domain(); } -static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) -{ - resp->data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); - - /* we might have given a more useful error above */ - if (*resp->data.auth.error_string == '\0') - fstrcpy(resp->data.auth.error_string, - get_friendly_nt_error_msg(result)); - resp->data.auth.pam_error = nt_status_to_pam(result); -} - static void fill_in_password_policy(struct winbindd_response *r, const struct samr_DomInfo1 *p) { diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 0e0db3e859..c5b7b07931 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -590,6 +590,7 @@ void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain); void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain); void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain); void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain); +void set_auth_errors(struct winbindd_response *resp, NTSTATUS result); /* The following definitions come from winbindd/winbindd_wins.c */ diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 4668d3725d..83c5053f78 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1544,3 +1544,15 @@ void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) } #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */ + +void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) +{ + resp->data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); + + /* we might have given a more useful error above */ + if (*resp->data.auth.error_string == '\0') + fstrcpy(resp->data.auth.error_string, + get_friendly_nt_error_msg(result)); + resp->data.auth.pam_error = nt_status_to_pam(result); +} -- cgit From e682f09da5dccd531dd908b62f1902a555bfc772 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 25 Aug 2008 13:03:15 +0200 Subject: winbindd: use set_auth_errors() in winbindd_dual_check_machine_acct as well. Guenther (This used to be commit bb9c59e892cc9d3047bde89a15cc341e2bd21bc5) --- source3/winbindd/winbindd_misc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 01a4054d44..50936c01a3 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -86,10 +86,7 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do "good" : "bad")); done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", state->response.data.auth.nt_status_string)); -- cgit From 13c66c8eb18629801da479a65dcf5bbd62f09bb9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Aug 2008 19:08:27 +0200 Subject: Move idmap_cache.c from winbindd/ to lib/ (This used to be commit fe70dcc1b63b1969c13f7fb03ec374b6e5a376a1) --- source3/winbindd/idmap_cache.c | 261 ----------------------------------------- 1 file changed, 261 deletions(-) delete mode 100644 source3/winbindd/idmap_cache.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c deleted file mode 100644 index 496f70ab45..0000000000 --- a/source3/winbindd/idmap_cache.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - Unix SMB/CIFS implementation. - ID Mapping Cache - - Copyright (C) Volker Lendecke 2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see .*/ - -#include "includes.h" -#include "winbindd.h" - -/** - * Find a sid2uid mapping - * @param[in] sid the sid to map - * @param[out] puid where to put the result - * @param[out] expired is the cache entry expired? - * @retval Was anything in the cache at all? - * - * If *puid == -1 this was a negative mapping. - */ - -bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid, - bool *expired) -{ - fstring sidstr; - char *key; - char *value; - char *endptr; - time_t timeout; - uid_t uid; - bool ret; - - key = talloc_asprintf(talloc_tos(), "IDMAP/SID2UID/%s", - sid_to_fstring(sidstr, sid)); - if (key == NULL) { - return false; - } - ret = gencache_get(key, &value, &timeout); - TALLOC_FREE(key); - if (!ret) { - return false; - } - uid = strtol(value, &endptr, 10); - ret = (*endptr == '\0'); - SAFE_FREE(value); - if (ret) { - *puid = uid; - *expired = (timeout <= time(NULL)); - } - return ret; -} - -/** - * Find a uid2sid mapping - * @param[in] uid the uid to map - * @param[out] sid where to put the result - * @param[out] expired is the cache entry expired? - * @retval Was anything in the cache at all? - * - * If "is_null_sid(sid)", this was a negative mapping. - */ - -bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired) -{ - char *key; - char *value; - time_t timeout; - bool ret = true; - - key = talloc_asprintf(talloc_tos(), "IDMAP/UID2SID/%d", (int)uid); - if (key == NULL) { - return false; - } - ret = gencache_get(key, &value, &timeout); - TALLOC_FREE(key); - if (!ret) { - return false; - } - ZERO_STRUCTP(sid); - if (value[0] != '-') { - ret = string_to_sid(sid, value); - } - SAFE_FREE(value); - if (ret) { - *expired = (timeout <= time(NULL)); - } - return ret; -} - -/** - * Store a mapping in the idmap cache - * @param[in] sid the sid to map - * @param[in] uid the uid to map - * - * If both parameters are valid values, then a positive mapping in both - * directions is stored. If "is_null_sid(sid)" is true, then this will be a - * negative mapping of uid, we want to cache that for this uid we could not - * find anything. Likewise if "uid==-1", then we want to cache that we did not - * find a mapping for the sid passed here. - */ - -void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid) -{ - time_t now = time(NULL); - time_t timeout; - fstring sidstr, key, value; - - if (!is_null_sid(sid)) { - fstr_sprintf(key, "IDMAP/SID2UID/%s", - sid_to_fstring(sidstr, sid)); - fstr_sprintf(value, "%d", (int)uid); - timeout = (uid == -1) - ? lp_idmap_negative_cache_time() - : lp_idmap_cache_time(); - gencache_set(key, value, now + timeout); - } - if (uid != -1) { - fstr_sprintf(key, "IDMAP/UID2SID/%d", (int)uid); - if (is_null_sid(sid)) { - /* negative uid mapping */ - fstrcpy(value, "-"); - timeout = lp_idmap_negative_cache_time(); - } - else { - sid_to_fstring(value, sid); - timeout = lp_idmap_cache_time(); - } - gencache_set(key, value, now + timeout); - } -} - -/** - * Find a sid2gid mapping - * @param[in] sid the sid to map - * @param[out] pgid where to put the result - * @param[out] expired is the cache entry expired? - * @retval Was anything in the cache at all? - * - * If *pgid == -1 this was a negative mapping. - */ - -bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid, - bool *expired) -{ - fstring sidstr; - char *key; - char *value; - char *endptr; - time_t timeout; - gid_t gid; - bool ret; - - key = talloc_asprintf(talloc_tos(), "IDMAP/SID2GID/%s", - sid_to_fstring(sidstr, sid)); - if (key == NULL) { - return false; - } - ret = gencache_get(key, &value, &timeout); - TALLOC_FREE(key); - if (!ret) { - return false; - } - gid = strtol(value, &endptr, 10); - ret = (*endptr == '\0'); - SAFE_FREE(value); - if (ret) { - *pgid = gid; - *expired = (timeout <= time(NULL)); - } - return ret; -} - -/** - * Find a gid2sid mapping - * @param[in] gid the gid to map - * @param[out] sid where to put the result - * @param[out] expired is the cache entry expired? - * @retval Was anything in the cache at all? - * - * If "is_null_sid(sid)", this was a negative mapping. - */ - -bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired) -{ - char *key; - char *value; - time_t timeout; - bool ret = true; - - key = talloc_asprintf(talloc_tos(), "IDMAP/GID2SID/%d", (int)gid); - if (key == NULL) { - return false; - } - ret = gencache_get(key, &value, &timeout); - TALLOC_FREE(key); - if (!ret) { - return false; - } - ZERO_STRUCTP(sid); - if (value[0] != '-') { - ret = string_to_sid(sid, value); - } - SAFE_FREE(value); - if (ret) { - *expired = (timeout <= time(NULL)); - } - return ret; -} - -/** - * Store a mapping in the idmap cache - * @param[in] sid the sid to map - * @param[in] gid the gid to map - * - * If both parameters are valid values, then a positive mapping in both - * directions is stored. If "is_null_sid(sid)" is true, then this will be a - * negative mapping of gid, we want to cache that for this gid we could not - * find anything. Likewise if "gid==-1", then we want to cache that we did not - * find a mapping for the sid passed here. - */ - -void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid) -{ - time_t now = time(NULL); - time_t timeout; - fstring sidstr, key, value; - - if (!is_null_sid(sid)) { - fstr_sprintf(key, "IDMAP/SID2GID/%s", - sid_to_fstring(sidstr, sid)); - fstr_sprintf(value, "%d", (int)gid); - timeout = (gid == -1) - ? lp_idmap_negative_cache_time() - : lp_idmap_cache_time(); - gencache_set(key, value, now + timeout); - } - if (gid != -1) { - fstr_sprintf(key, "IDMAP/GID2SID/%d", (int)gid); - if (is_null_sid(sid)) { - /* negative gid mapping */ - fstrcpy(value, "-"); - timeout = lp_idmap_negative_cache_time(); - } - else { - sid_to_fstring(value, sid); - timeout = lp_idmap_cache_time(); - } - gencache_set(key, value, now + timeout); - } -} -- cgit From 29af730964e567a8391ee381aae3b9aaa7e5e7e1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2008 17:29:10 -0700 Subject: Fix the wcache_invalidate_samlogon calls. Jeremy. (This used to be commit 7c820899ed1364fdaeb7b49e8ddd839e67397ec0) --- source3/winbindd/winbindd_cache.c | 23 ++++++++++++++++++++++- source3/winbindd/winbindd_pam.c | 4 ++-- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index c9d857c2ec..2fbb01b623 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2259,6 +2259,8 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void wcache_invalidate_samlogon(struct winbindd_domain *domain, struct netr_SamInfo3 *info3) { + DOM_SID sid; + fstring key_str, sid_string; struct winbind_cache *cache; /* dont clear cached U/SID and UG/SID entries when we want to logon @@ -2272,7 +2274,26 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain, return; cache = get_cache(domain); - netsamlogon_clear_cached_user(cache->tdb, info3); + + if (!cache->tdb) { + return; + } + + sid_copy(&sid, info3->base.domain_sid); + sid_append_rid(&sid, info3->base.rid); + + /* Clear U/SID cache entry */ + fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid)); + DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str)); + tdb_delete(cache->tdb, string_tdb_data(key_str)); + + /* Clear UG/SID cache entry */ + fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid)); + DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str)); + tdb_delete(cache->tdb, string_tdb_data(key_str)); + + /* Samba/winbindd never needs this. */ + netsamlogon_clear_cached_user(info3); } bool wcache_invalidate_cache(void) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index a7911f60aa..d4a2e3ed79 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1595,8 +1595,8 @@ process_result: goto done; } - netsamlogon_cache_store(name_user, info3); wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + netsamlogon_cache_store(name_user, info3); /* save name_to_sid info as early as possible (only if this is our primary domain so we don't invalidate @@ -1921,8 +1921,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { - netsamlogon_cache_store(name_user, info3); wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + netsamlogon_cache_store(name_user, info3); /* Check if the user is in the right group */ -- cgit From 52e23fe460ed662e10137503abd08f4bd6596651 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 28 Aug 2008 12:29:24 +0200 Subject: winbindd: fix invalid sid copy (hit when enumerating sibling domains). Guenther (This used to be commit 5eee7423351ffd05486e33ff8eb905babcbc9422) --- source3/winbindd/winbindd_ads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 097fa3907d..53ea3e148c 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1254,7 +1254,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, if (trusts.array[i].sid) { sid_copy( &d.sid, trusts.array[i].sid); } else { - sid_copy(&(*dom_sids)[ret_count], &global_sid_NULL); + sid_copy(&d.sid, &global_sid_NULL); } if ( domain->primary ) { -- cgit From ec4015d34fed1f0a53ae495d9d9b2744f0c29df0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Aug 2008 11:34:01 +0200 Subject: Fix Coverity ID 592 The scanner did not figure out that we always have a primary domain, so it complained about us potentially passing a NULL pointer down to set_domain_online_request() where it is dereferenced. Make the code a bit clearer. (This used to be commit e6e8d108f95ed974f98f3f57adcfbbde4e00fad9) --- source3/winbindd/winbindd_dual.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 916e8c07c7..63ce0e8d7f 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1212,6 +1212,10 @@ static bool fork_domain_child(struct winbindd_child *child) } } + if (primary_domain == NULL) { + smb_panic("no primary domain found"); + } + /* Ensure we're not handling an event inherited from our parent. */ -- cgit From aac60fead2d3a07756c320ee09a0960252510c19 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 2 Sep 2008 21:51:30 +0200 Subject: winbindd: the ad trusted_domains call should return talloced strings. Guenther (This used to be commit b57cbf62e8180c8fdb8f541c43358d36d8dbbdfa) --- source3/winbindd/winbindd_ads.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 53ea3e148c..94e3bad7b2 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1239,8 +1239,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, continue; } - (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name); - (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name); + (*names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].netbios_name); + (*alt_names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].dns_name); + if ((*names)[ret_count] == NULL) { + return NT_STATUS_NO_MEMORY; + } if (trusts.array[i].sid) { sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid); } else { -- cgit From 3fa16da8c70af9c54e03ea2a497d18009d2126e9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 3 Sep 2008 14:36:43 -0400 Subject: Revert "Split lookup_name() and create a new functiong called" This reverts commit 8594edf666c29fd4ddf1780da842683dd81483b6. (This used to be commit ad462e2e2d025a7fc23e7dea32b2b442b528970b) --- source3/winbindd/winbindd_passdb.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index fbe4a27abf..5677c01be1 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -94,8 +94,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DOM_SID *sid, enum lsa_SidType *type) { + const char *fullname; uint32 flags = LOOKUP_NAME_ALL; - bool res; switch ( original_cmd ) { case WINBINDD_LOOKUPNAME: @@ -107,26 +107,28 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n")); break; } - - DEBUG(10, ("looking up name [%s\\%s] (domain\\name) \n", - domain_name?domain_name:"(NULL)", name)); - - if (strchr_m(name, '\\')) { - res = lookup_name(mem_ctx, name, flags, NULL, NULL, sid, type); + + if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) { + fullname = talloc_asprintf(mem_ctx, "%s\\%s", + domain_name, name); + if (fullname == NULL) { + return NT_STATUS_NO_MEMORY; + } } else { - res = lookup_domain_name(mem_ctx, domain_name, name, flags, - NULL, NULL, sid, type); + fullname = name; } - if (!res) { + DEBUG(10, ("Finding fullname %s\n", fullname)); + + if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) { return NT_STATUS_NONE_MAPPED; } - DEBUG(10, ("name_to_sid for [%s\\%s] returned %s (%s)\n", - domain_name?domain_name:"(NULL)", name, + DEBUG(10, ("name_to_sid for %s returned %s (%s)\n", + fullname, sid_string_dbg(sid), sid_type_lookup((uint32)*type))); - + return NT_STATUS_OK; } -- cgit From 304554115a2f2dc316386a9ea5bec237d67f595f Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Wed, 3 Sep 2008 15:31:39 -0700 Subject: Cleanup of DC enumeration in get_dcs() This is a fix for a few small inefficiencies/bugs in the get_dcs() path. * because the third add_one_dc_unique() loop was outside the ADS check all DCs returned from the non-sitename lookup were being tacked onto the dc_name_ip list twice. * add_one_dc_unique() now checks if the given IP address already exists before adding it to the list, making the returned list actually unique * added more thorough doxygen comment headers (This used to be commit cb2d488e1dbd90953c496c5e25d648977884f7e3) --- source3/winbindd/winbindd_cm.c | 98 +++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 24 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 71f1a56519..ce851649ba 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1010,15 +1010,37 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, return result; } +/******************************************************************* + Add a dcname and sockaddr_storage pair to the end of a dc_name_ip + array. + + Keeps the list unique by not adding duplicate entries. + + @param[in] mem_ctx talloc memory context to allocate from + @param[in] domain_name domain of the DC + @param[in] dcname name of the DC to add to the list + @param[in] pss Internet address and port pair to add to the list + @param[in,out] dcs array of dc_name_ip structures to add to + @param[in,out] num_dcs number of dcs returned in the dcs array + @return true if the list was added to, false otherwise +*******************************************************************/ + static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, const char *dcname, struct sockaddr_storage *pss, struct dc_name_ip **dcs, int *num) { + int i = 0; + if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) { DEBUG(10, ("DC %s was in the negative conn cache\n", dcname)); return False; } + /* Make sure there's no duplicates in the list */ + for (i=0; i<*num; i++) + if (addr_equal(&(*dcs)[i].ss, pss)) + return False; + *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1); if (*dcs == NULL) @@ -1151,8 +1173,15 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, } /******************************************************************* - Retreive a list of IP address for domain controllers. Fill in - the dcs[] with results. + Retrieve a list of IP addresses for domain controllers. + + The array is sorted in the preferred connection order. + + @param[in] mem_ctx talloc memory context to allocate from + @param[in] domain domain to retrieve DCs for + @param[out] dcs array of dcs that will be returned + @param[out] num_dcs number of dcs returned in the dcs array + @return always true *******************************************************************/ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, @@ -1168,9 +1197,11 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, is_our_domain = strequal(domain->name, lp_workgroup()); + /* If not our domain, get the preferred DC, by asking our primary DC */ if ( !is_our_domain && get_dc_name_via_netlogon(domain, dcname, &ss) - && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, num_dcs) ) + && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs, + num_dcs) ) { char addr[INET6_ADDRSTRLEN]; print_sockaddr(addr, sizeof(addr), &ss); @@ -1197,8 +1228,13 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, if (sitename) { /* Do the site-specific AD dns lookup first. */ - get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True); + get_sorted_dc_list(domain->alt_name, sitename, &ip_list, + &iplist_size, True); + /* Add ips to the DC array. We don't look up the name + of the DC in this function, but we fill in the char* + of the ip now to make the failed connection cache + work */ for ( i=0; ialt_name, NULL, &ip_list, &iplist_size, True); + /* Now we add DCs from the main AD DNS lookup. */ + get_sorted_dc_list(domain->alt_name, NULL, &ip_list, + &iplist_size, True); for ( i=0; iname, NULL, &ip_list, &iplist_size, False); - } + SAFE_FREE(ip_list); + iplist_size = 0; + } - /* FIXME!! this is where we should re-insert the GETDC requests --jerry */ + /* Try standard netbios queries if no ADS */ + if (*num_dcs == 0) { + get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, + False); - /* now add to the dc array. We'll wait until the last minute - to look up the name of the DC. But we fill in the char* for - the ip now in to make the failed connection cache work */ + for ( i=0; iname, + addr, + &ip_list[i].ss, + dcs, + num_dcs); + } - for ( i=0; iname, addr, - &ip_list[i].ss, dcs, num_dcs); + SAFE_FREE(ip_list); + iplist_size = 0; } - SAFE_FREE( ip_list ); - return True; } +/******************************************************************* + Find and make a connection to a DC in the given domain. + + @param[in] mem_ctx talloc memory context to allocate from + @param[in] domain domain to find a dc in + @param[out] dcname NetBIOS or FQDN of DC that's connected to + @param[out] pss DC Internet address and port + @param[out] fd fd of the open socket connected to the newly found dc + @return true when a DC connection is made, false otherwise +*******************************************************************/ + static bool find_new_dc(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, fstring dcname, struct sockaddr_storage *pss, int *fd) -- cgit From 24992010cb57556ee2b65776f26e586ea0e3895d Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 4 Sep 2008 14:35:27 -0700 Subject: get rid of unneeded argument in get_methods and get_alloc_methods (This used to be commit 07b0323472b78d49cff06b78924c3015bea52a30) --- source3/winbindd/idmap.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 2962fe6c1c..cfc5597f42 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -81,12 +81,11 @@ static struct idmap_domain *passdb_idmap_domain; static struct idmap_domain **idmap_domains = NULL; static int num_domains = 0; -static struct idmap_methods *get_methods(struct idmap_backend *be, - const char *name) +static struct idmap_methods *get_methods(const char *name) { struct idmap_backend *b; - for (b = be; b; b = b->next) { + for (b = backends; b; b = b->next) { if (strequal(b->name, name)) { return b->methods; } @@ -95,13 +94,11 @@ static struct idmap_methods *get_methods(struct idmap_backend *be, return NULL; } -static struct idmap_alloc_methods *get_alloc_methods( - struct idmap_alloc_backend *be, - const char *name) +static struct idmap_alloc_methods *get_alloc_methods(const char *name) { struct idmap_alloc_backend *b; - for (b = be; b; b = b->next) { + for (b = alloc_backends; b; b = b->next) { if (strequal(b->name, name)) { return b->methods; } @@ -199,7 +196,7 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, return NT_STATUS_INVALID_PARAMETER; } - test = get_alloc_methods(alloc_backends, name); + test = get_alloc_methods(name); if (test) { DEBUG(0,("idmap_alloc module %s already registered!\n", name)); return NT_STATUS_OBJECT_NAME_COLLISION; @@ -300,7 +297,7 @@ static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx, goto fail; } - result->methods = get_methods(backends, modulename); + result->methods = get_methods(modulename); if (result->methods == NULL) { DEBUG(3, ("idmap backend %s not found\n", modulename)); @@ -311,7 +308,7 @@ static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx, goto fail; } - result->methods = get_methods(backends, modulename); + result->methods = get_methods(modulename); } if (result->methods == NULL) { DEBUG(1, ("idmap backend %s not found\n", modulename)); @@ -564,15 +561,13 @@ static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx) goto fail; } - idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, - modulename); + idmap_alloc_ctx->methods = get_alloc_methods(modulename); if (idmap_alloc_ctx->methods == NULL) { ret = smb_probe_module("idmap", modulename); if (NT_STATUS_IS_OK(ret)) { idmap_alloc_ctx->methods = - get_alloc_methods(alloc_backends, - modulename); + get_alloc_methods(modulename); } } -- cgit From 72df99975966ddccc87f80f3f6b735713f882a18 Mon Sep 17 00:00:00 2001 From: James Ding Date: Thu, 4 Sep 2008 15:13:12 -0700 Subject: Fix winbindd crash bug with trusted domains. Bug #5736 (This used to be commit d4f5caa3d38b5afc1e8b3d0e0c6d7d68a152fe0a) --- source3/winbindd/winbindd_ads.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 94e3bad7b2..c7f730e397 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1225,6 +1225,8 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, for (i = 0; i < trusts.count; i++) { struct winbindd_domain d; + ZERO_STRUCT(d); + /* drop external trusts if this is not our primary domain. This means that the returned number of domains may be less that the ones actually trusted -- cgit From 38c287740f9b6a9cb8f093de864f8fd5e98eff9c Mon Sep 17 00:00:00 2001 From: Qiao Yang Date: Fri, 5 Sep 2008 14:08:09 +0200 Subject: Fix a memleak request.extra_data is not freed if there is no extra_data in response or when there is some error happens in processing. This patch will free the buffer right after processing a request before sending back a response. (This used to be commit be6f12273f171a3eb1967d2299064e57d737f6a4) --- source3/winbindd/winbindd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index f75af64f8f..44b5415726 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -549,7 +549,6 @@ static void response_extra_sent(void *private_data, bool success) return; } - SAFE_FREE(state->request.extra_data.data); SAFE_FREE(state->response.extra_data.data); setup_async_read(&state->fd_event, &state->request, sizeof(uint32), @@ -581,6 +580,8 @@ static void response_main_sent(void *private_data, bool success) static void request_finished(struct winbindd_cli_state *state) { + /* Make sure request.extra_data is freed when finish processing a request */ + SAFE_FREE(state->request.extra_data.data); setup_async_write(&state->fd_event, &state->response, sizeof(state->response), response_main_sent, state); } -- cgit From ce9d89678111d95b6f94576dba934b10601e6e13 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 5 Sep 2008 23:22:10 +0200 Subject: Revert "winbindd: the ad trusted_domains call should return talloced strings." This reverts commit b57cbf62e8180c8fdb8f541c43358d36d8dbbdfa. (This used to be commit b2a3f13e5b3b81df2ed7460e54c11a7f56b3c4f6) --- source3/winbindd/winbindd_ads.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index c7f730e397..894e7866b3 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1241,11 +1241,8 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, continue; } - (*names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].netbios_name); - (*alt_names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].dns_name); - if ((*names)[ret_count] == NULL) { - return NT_STATUS_NO_MEMORY; - } + (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name); + (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name); if (trusts.array[i].sid) { sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid); } else { -- cgit From f25863e04cf3264575545701cb257bac8f0aee82 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 11 Sep 2008 09:51:39 -0400 Subject: Fix for bug 5571 Make sure that usernames are parsed using the correct separator. Otherwise group memeberships in winbind may be result broken. (This used to be commit 20b9c0aa7b4e6d6be5bb6e4e96bd8a1cbb6edd37) --- source3/winbindd/winbindd_group.c | 2 +- source3/winbindd/winbindd_proto.h | 1 + source3/winbindd/winbindd_util.c | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 21ee8951b5..4d5026d158 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -607,7 +607,7 @@ static bool fill_grent_mem(struct winbindd_domain *domain, } else { DEBUG(10, ("appending %s at ndx %d\n", names[i], buf_ndx)); - safe_strcpy(&buf[buf_ndx], names[i], len); + parse_add_domuser(&buf[buf_ndx], names[i], &len); buf_ndx += len; buf[buf_ndx] = ','; buf_ndx++; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index c5b7b07931..e0fc073a0a 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -566,6 +566,7 @@ void free_getent_state(struct getent_state *state); bool parse_domain_user(const char *domuser, fstring domain, fstring user); bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, char **domain, char **user); +void parse_add_domuser(void *buf, char *domuser, int *len); bool canonicalize_username(fstring username_inout, fstring domain, fstring user); void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume); const char *get_winbind_pipe_dir(void) ; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 83c5053f78..132c96f1ee 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1138,6 +1138,31 @@ bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, return ((*domain != NULL) && (*user != NULL)); } +/* add a domain user name to a buffer */ +void parse_add_domuser(void *buf, char *domuser, int *len) +{ + fstring domain; + char *p, *user; + + user = domuser; + p = strchr(domuser, *lp_winbind_separator()); + + if (p) { + + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + p++; + + if (assume_domain(domain)) { + + user = p; + *len -= (PTR_DIFF(p, domuser)); + } + } + + safe_strcpy(buf, user, *len); +} + /* Ensure an incoming username from NSS is fully qualified. Replace the incoming fstring with DOMAIN user. Returns the same values as parse_domain_user() but also replaces the incoming username. -- cgit