diff options
Diffstat (limited to 'source/winbindd')
39 files changed, 3291 insertions, 7752 deletions
diff --git a/source/winbindd/idmap.c b/source/winbindd/idmap.c index cfc5597f42..d601210ecf 100644 --- a/source/winbindd/idmap.c +++ b/source/winbindd/idmap.c @@ -28,58 +28,52 @@ 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_cache_ctx; + struct idmap_alloc_context { + const char *params; struct idmap_alloc_methods *methods; + bool initialized; }; -static struct idmap_alloc_context *idmap_alloc_ctx = NULL; -/** - * Default idmap domain configured via "idmap backend". - */ -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 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(const char *name) { @@ -113,11 +107,6 @@ 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. **********************************************************************/ @@ -125,8 +114,13 @@ bool idmap_is_online(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 " @@ -143,24 +137,20 @@ NTSTATUS smb_register_idmap(int version, const char *name, return NT_STATUS_INVALID_PARAMETER; } - 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; - } + test = get_methods(name); + if (test) { + DEBUG(0,("Idmap module %s already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = talloc(NULL, struct idmap_backend); + 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(entry, 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; @@ -171,7 +161,7 @@ NTSTATUS smb_register_idmap(int version, const char *name, } /********************************************************************** - Allow a module to register itself as an alloc method. + Allow a module to register itself as a method. **********************************************************************/ NTSTATUS smb_register_idmap_alloc(int version, const char *name, @@ -180,6 +170,10 @@ 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 " @@ -202,12 +196,12 @@ NTSTATUS smb_register_idmap_alloc(int version, const char *name, return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = talloc(NULL, struct idmap_alloc_backend); + 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(entry, name); + entry->name = talloc_strdup(idmap_ctx, name); if ( ! entry->name) { DEBUG(0,("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -231,560 +225,1349 @@ static int close_domain_destructor(struct idmap_domain *dom) return 0; } -static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param, - char **pmodulename, char **pargs) -{ - char *modulename; - char *args; +/************************************************************************** + Shutdown. +**************************************************************************/ - 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_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; - modulename = talloc_strdup(mem_ctx, param); - if (modulename == NULL) { - return false; - } + /* 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; +} + +/**************************************************************************** + ****************************************************************************/ + +NTSTATUS idmap_init_cache(void) +{ + /* Always initialize the cache. We'll have to delay initialization + of backends if we are offline */ - args = strchr(modulename, ':'); - if (args == NULL) { - *pmodulename = modulename; - *pargs = NULL; - return true; + if ( idmap_ctx ) { + return NT_STATUS_OK; } - *args = '\0'; + if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) { + return NT_STATUS_NO_MEMORY; + } - args = talloc_strdup(mem_ctx, args+1); - if (args == NULL) { - TALLOC_FREE(modulename); - return false; + if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { + return NT_STATUS_UNSUCCESSFUL; } - *pmodulename = modulename; - *pargs = args; - return true; + return NT_STATUS_OK; } -/** - * 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, - const char *params) +/**************************************************************************** + ****************************************************************************/ + +NTSTATUS idmap_init(void) { - struct idmap_domain *result; - NTSTATUS status; + 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; - result = talloc_zero(mem_ctx, struct idmap_domain); - if (result == NULL) { - DEBUG(0, ("talloc failed\n")); - return NULL; + 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->name = talloc_strdup(result, domainname); - if (result->name == NULL) { - DEBUG(0, ("talloc failed\n")); - goto fail; + /* 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->methods = get_methods(modulename); - if (result->methods == NULL) { - DEBUG(3, ("idmap backend %s not found\n", modulename)); + static_init_idmap; - status = smb_probe_module("idmap", modulename); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not probe idmap module %s\n", - modulename)); - goto fail; + 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 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 */ - result->methods = get_methods(modulename); - } - if (result->methods == NULL) { - DEBUG(1, ("idmap backend %s not found\n", modulename)); - goto fail; + compat = 1; + compat_backend = talloc_strdup( idmap_ctx, "tdb"); + compat_params = compat_backend; } - 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 ( ! 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]; } - talloc_set_destructor(result, close_domain_destructor); + /*************************** + * 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; + } - return result; + if ((dom_list[i] != default_domain) && + strequal(dom_list[i], lp_workgroup())) { + pri_dom_is_in_list = True; + } + /* init domain */ -fail: - TALLOC_FREE(result); - return NULL; -} + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); -/** - * 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. - */ + dom->name = talloc_strdup(dom, dom_list[i]); + IDMAP_CHECK_ALLOC(dom->name); -static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx) -{ - struct idmap_domain *result; - char *modulename; - char *params; + config_option = talloc_asprintf(dom, "idmap config %s", + dom->name); + IDMAP_CHECK_ALLOC(config_option); - DEBUG(10, ("idmap_init_default_domain: calling static_init_idmap\n")); + /* default or specific ? */ - static_init_idmap; + dom->default_domain = lp_parm_bool(-1, config_option, + "default", False); - if (!parse_idmap_module(talloc_tos(), lp_idmap_backend(), &modulename, - ¶ms)) { - DEBUG(1, ("parse_idmap_module failed\n")); - return NULL; - } + if (dom->default_domain || + (default_domain && strequal(dom_list[i], default_domain))) { - DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename)); + /* make sure this is set even when we match + * default_domain */ + dom->default_domain = True; - result = idmap_init_domain(mem_ctx, "*", modulename, params); - if (result == NULL) { - goto fail; - } + if (default_already_defined) { + DEBUG(1, ("ERROR: Multiple domains defined as" + " default!\n")); + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } - TALLOC_FREE(modulename); - TALLOC_FREE(params); - return result; + default_already_defined = True; -fail: - TALLOC_FREE(modulename); - TALLOC_FREE(params); - TALLOC_FREE(result); - 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 <domname>" parameters to figure out - * the configuration. - */ - -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; + 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); - config_option = talloc_asprintf(talloc_tos(), "idmap config %s", - domname); - if (config_option == NULL) { - DEBUG(0, ("talloc failed\n")); - goto fail; - } + /* get the backend methods for this domain */ + dom->methods = get_methods(parm_backend); - 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; - } + if ( ! dom->methods) { + ret = smb_probe_module("idmap", parm_backend); + if (NT_STATUS_IS_OK(ret)) { + dom->methods = get_methods(parm_backend); + } + } + if ( ! dom->methods) { + DEBUG(0, ("ERROR: Could not get methods for " + "backend %s\n", parm_backend)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } - result = idmap_init_domain(mem_ctx, domname, backend, NULL); - if (result == NULL) { - goto fail; - } + /* 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; + } - TALLOC_FREE(config_option); - return result; + /* now that we have methods, + * set the destructor for this domain */ + talloc_set_destructor(dom, close_domain_destructor); -fail: - TALLOC_FREE(config_option); - TALLOC_FREE(result); - return NULL; -} + if (compat_params) { + dom->params = talloc_strdup(dom, compat_params); + IDMAP_CHECK_ALLOC(dom->params); + } else { + dom->params = 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. - */ + /* 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; -static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx) -{ - if (passdb_idmap_domain != NULL) { - return passdb_idmap_domain; - } + /* save default domain position for future uses */ + if (dom->default_domain) { + def_dom_num = num_domains; + } - 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")); - } + /* Bump counter to next available slot */ - return passdb_idmap_domain; -} + num_domains++; -/** - * 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; - int i; + DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", + dom->name, parm_backend, + dom->default_domain?"":"not ", + dom->readonly?"":"not ")); - /* - * 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; + talloc_free(config_option); } - if ((domname == NULL) || (domname[0] == '\0')) { - return default_idmap_domain; - } + /* 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(compat_backend); + if ( ! dom->methods) { + ret = smb_probe_module("idmap", compat_backend); + if (NT_STATUS_IS_OK(ret)) { + dom->methods = get_methods(compat_backend); + } + } + if ( ! dom->methods) { + DEBUG(0, ("ERROR: Could not get methods for " + "backend %s\n", compat_backend)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } - for (i=0; i<num_domains; i++) { - if (strequal(idmap_domains[i]->name, domname)) { - return idmap_domains[i]; + /* 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; - if (idmap_domains == NULL) { - /* - * talloc context for all idmap domains - */ - idmap_domains = TALLOC_ARRAY(NULL, struct idmap_domain *, 1); - } + def_dom_num = num_domains; - if (idmap_domains == NULL) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } + /* Bump counter to next available slot */ + + num_domains++; - result = idmap_init_named_domain(idmap_domains, domname); - if (result == NULL) { - /* - * Could not init that domain -- try the default one - */ - return default_idmap_domain; + DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n", + dom->name, compat_backend, + dom->default_domain?"":"not ", + dom->readonly?"":"not ")); } - ADD_TO_ARRAY(idmap_domains, struct idmap_domain *, result, - &idmap_domains, &num_domains); - return result; -} + /* automatically add idmap_nss backend if needed */ + if ((lp_server_role() == ROLE_DOMAIN_MEMBER) && + ( ! pri_dom_is_in_list) && + lp_winbind_trusted_domains_only()) { -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; -} + dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain); + IDMAP_CHECK_ALLOC(dom); -/** - * 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; - char *modulename, *params; - NTSTATUS ret = NT_STATUS_NO_MEMORY;; + dom->name = talloc_strdup(dom, lp_workgroup()); + IDMAP_CHECK_ALLOC(dom->name); - if (idmap_alloc_ctx != NULL) { - *ctx = idmap_alloc_ctx; - return NT_STATUS_OK; + dom->default_domain = False; + dom->readonly = True; + + /* get the backend methods for nss */ + dom->methods = get_methods("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++; } - idmap_alloc_ctx = talloc(NULL, struct idmap_alloc_context); - if (idmap_alloc_ctx == NULL) { - DEBUG(0, ("talloc failed\n")); - goto fail; + /**** 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("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; } - backend = lp_idmap_alloc_backend(); - if ((backend == NULL) || (backend[0] == '\0')) { - backend = lp_idmap_backend(); + /* 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; } - if (backend == NULL) { - DEBUG(3, ("no idmap alloc backend defined\n")); - ret = NT_STATUS_INVALID_PARAMETER; - 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; } - if (!parse_idmap_module(idmap_alloc_ctx, backend, &modulename, - ¶ms)) { - DEBUG(1, ("parse_idmap_module %s failed\n", backend)); - goto fail; + 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 ****/ - idmap_alloc_ctx->methods = get_alloc_methods(modulename); + /* 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 (idmap_alloc_ctx->methods == NULL) { - ret = smb_probe_module("idmap", modulename); - if (NT_STATUS_IS_OK(ret)) { - idmap_alloc_ctx->methods = - get_alloc_methods(modulename); + 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 (idmap_alloc_ctx->methods == NULL) { - DEBUG(1, ("could not find idmap alloc module %s\n", backend)); - ret = NT_STATUS_INVALID_PARAMETER; - goto fail; + + /* 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()); + } } - ret = idmap_alloc_ctx->methods->init(params); + if ( alloc_backend ) { - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for alloc " - "backend, deferred!\n")); - goto fail; + 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_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_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; + } + } } - TALLOC_FREE(modulename); - TALLOC_FREE(params); + /* cleanup temporary strings */ + TALLOC_FREE( compat_backend ); - *ctx = idmap_alloc_ctx; - return NT_STATUS_OK; + idmap_init_status = NT_STATUS_OK; + + return ret; + +done: + DEBUG(0, ("Aborting IDMAP Initialization ...\n")); + idmap_close(); -fail: - TALLOC_FREE(idmap_alloc_ctx); 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) { - struct idmap_alloc_context *ctx; NTSTATUS ret; - if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) { + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { return ret; } id->type = ID_TYPE_UID; - return ctx->methods->allocate_id(id); + return idmap_alloc_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(&ctx))) { + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { return ret; } id->type = ID_TYPE_GID; - return ctx->methods->allocate_id(id); + return idmap_alloc_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(&ctx))) { + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { return ret; } id->type = ID_TYPE_UID; - return ctx->methods->set_id_hwm(id); + return idmap_alloc_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(&ctx))) { + if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) { return ret; } id->type = ID_TYPE_GID; - return ctx->methods->set_id_hwm(id); + 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_t 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; } -NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type, - struct unixid *pxid) +/****************************************************************************** + Lookup an index given an idmap_domain pointer + ******************************************************************************/ + +static uint32_t 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 dom_sid sid; struct idmap_domain *dom; - struct id_map map; - NTSTATUS status; - dom = idmap_find_domain(NULL); - if (dom == NULL) { - DEBUG(3, ("no default domain, no place to write\n")); - return NT_STATUS_ACCESS_DENIED; + /* 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 <trusted domain " + "only> 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; + } + + 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; + + /* If we are offline we cannot lookup SIDs, deny mapping */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; } - sid_copy(&sid, psid); - map.sid = &sid; - map.xid.type = type; + ret = idmap_can_map(map, &dom); + if ( ! NT_STATUS_IS_OK(ret)) { + return NT_STATUS_NONE_MAPPED; + } - switch (type) { + /* check if this is a valid SID and then map it */ + switch (map->xid.type) { case ID_TYPE_UID: - status = idmap_allocate_uid(&map.xid); + 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: - status = idmap_allocate_gid(&map.xid); + 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: - status = NT_STATUS_INVALID_PARAMETER; - break; - } - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(status))); - return status; + /* 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; } - map.status = ID_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_dbg(map.sid), - (map.xid.type == ID_TYPE_UID) ? "UID" : "GID", - (unsigned long)map.xid.id)); + 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!")); - status = dom->methods->set_mapping(dom, &map); + /* TODO: would it make sense to have an "unalloc_id function?" */ - 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); + return NT_STATUS_NONE_MAPPED; } - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not store the new mapping: %s\n", - nt_errstr(status))); - return status; + 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_dbg(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; } - *pxid = map.xid; + DEBUG(10,("set_mapping for domain %s\n", dom->name )); - return NT_STATUS_OK; + return dom->methods->set_mapping(dom, map); } -NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) +static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids) { struct idmap_domain *dom; - struct id_map *maps[2]; + struct id_map **unmapped; + struct id_map **_ids; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i, u, n; - maps[0] = id; - maps[1] = NULL; + if (!ids || !*ids) { + DEBUG(1, ("Invalid list of maps\n")); + return NT_STATUS_INVALID_PARAMETER; + } - /* - * Always give passdb a chance first - */ + 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; - dom = idmap_init_passdb_domain(NULL); - if ((dom != NULL) - && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))) { - return NT_STATUS_OK; } - dom = idmap_find_domain(domname); - if (dom == NULL) { - return NT_STATUS_NONE_MAPPED; + 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; + } + } } - return dom->methods->unixids_to_sids(dom, maps); + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; } -NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id) +static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids) { + struct id_map ***dom_ids; struct idmap_domain *dom; - struct id_map *maps[2]; + TALLOC_CTX *ctx; + NTSTATUS ret; + int i, *counters; - maps[0] = id; - maps[1] = NULL; + 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; + } - if (sid_check_is_in_builtin(id->sid) - || (sid_check_is_in_our_domain(id->sid))) { + DEBUG(10, ("Query backends to map sids->ids\n")); - dom = idmap_init_passdb_domain(NULL); - if (dom == NULL) { - return NT_STATUS_NONE_MAPPED; + /* 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_t idx; + + if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) { + /* no available idmap_domain. Move on */ + continue; } - return dom->methods->sids_to_unixids(dom, maps); + + 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; } - dom = idmap_find_domain(domain); - if (dom == NULL) { - return NT_STATUS_NONE_MAPPED; + /* 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; + } + } } - return dom->methods->sids_to_unixids(dom, maps); + ret = NT_STATUS_OK; + +done: + talloc_free(ctx); + return ret; } -NTSTATUS idmap_set_mapping(const struct id_map *map) +/************************************************************************** + idmap interface functions +**************************************************************************/ + +NTSTATUS idmap_unixids_to_sids(struct id_map **ids) { - struct idmap_domain *dom; + 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; + } - dom = idmap_find_domain(NULL); - if (dom == NULL) { - DEBUG(3, ("no default domain, no place to write\n")); - return NT_STATUS_ACCESS_DENIED; + if (!ids || !*ids) { + DEBUG(1, ("Invalid list of maps\n")); + return NT_STATUS_INVALID_PARAMETER; } - if (dom->methods->set_mapping == NULL) { - DEBUG(3, ("default domain not writable\n")); - return NT_STATUS_MEDIA_WRITE_PROTECTED; + + 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; } - return dom->methods->set_mapping(dom, map); + /* 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 (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)) { + + 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) { + 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; + 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; +} + +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/source/winbindd/idmap_ad.c b/source/winbindd/idmap_ad.c index 8144d876d4..a2c0dac9cd 100644 --- a/source/winbindd/idmap_ad.c +++ b/source/winbindd/idmap_ad.c @@ -160,8 +160,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void) /************************************************************************ ***********************************************************************/ -static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, - const char *params) +static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom) { struct idmap_ad_context *ctx; char *config_option; @@ -207,6 +206,7 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, } dom->private_data = ctx; + dom->initialized = True; talloc_free(config_option); @@ -277,6 +277,14 @@ 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 ) { @@ -488,6 +496,14 @@ 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 ) { @@ -818,159 +834,6 @@ done: return nt_status; } -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx, - const char *domain, - const char *name, - char **alias) -{ - ADS_STRUCT *ads_internal = NULL; - const char *attrs[] = {NULL, /* attr_uid */ - NULL }; - char *filter = NULL; - LDAPMessage *msg = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - /* Check incoming parameters */ - - if ( !domain || !name || !*alias) { - nt_status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Only do query if we are online */ - - if (idmap_is_offline()) { - nt_status = NT_STATUS_FILE_IS_OFFLINE; - goto done; - } - - ads_internal = ad_idmap_cached_connection(); - - if (!ads_internal || !ad_schema) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - goto done; - } - - attrs[0] = ad_schema->posix_uid_attr; - - filter = talloc_asprintf(mem_ctx, - "(sAMAccountName=%s)", - name); - if (!filter) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - ads_status = ads_search_retry(ads_internal, &msg, filter, attrs); - if (!ADS_ERR_OK(ads_status)) { - nt_status = ads_ntstatus(ads_status); - goto done; - } - - *alias = ads_pull_string(ads_internal, mem_ctx, msg, ad_schema->posix_uid_attr ); - - if (!*alias) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - nt_status = NT_STATUS_OK; - -done: - if (filter) { - talloc_destroy(filter); - } - if (msg) { - ads_msgfree(ads_internal, msg); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx, - const char *domain, - const char *alias, - char **name ) -{ - ADS_STRUCT *ads_internal = NULL; - const char *attrs[] = {"sAMAccountName", - NULL }; - char *filter = NULL; - LDAPMessage *msg = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *username; - - /* Check incoming parameters */ - - if ( !alias || !name) { - nt_status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Only do query if we are online */ - - if (idmap_is_offline()) { - nt_status = NT_STATUS_FILE_IS_OFFLINE; - goto done; - } - - ads_internal = ad_idmap_cached_connection(); - - if (!ads_internal || !ad_schema) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - goto done; - } - - filter = talloc_asprintf(mem_ctx, - "(%s=%s)", - ad_schema->posix_uid_attr, - alias); - if (!filter) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - ads_status = ads_search_retry(ads_internal, &msg, filter, attrs); - if (!ADS_ERR_OK(ads_status)) { - nt_status = ads_ntstatus(ads_status); - goto done; - } - - username = ads_pull_string(ads_internal, mem_ctx, msg, - "sAMAccountName"); - if (!username) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - *name = talloc_asprintf(mem_ctx, "%s\\%s", - lp_workgroup(), - username); - if (!*name) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - nt_status = NT_STATUS_OK; - -done: - if (filter) { - talloc_destroy(filter); - } - if (msg) { - ads_msgfree(ads_internal, msg); - } - - return nt_status; -} - - /************************************************************************ ***********************************************************************/ @@ -996,27 +859,21 @@ static struct idmap_methods ad_methods = { 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, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, - .close_fn = nss_ad_close + .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, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, - .close_fn = nss_ad_close + .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, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, - .close_fn = nss_ad_close + .init = nss_sfu20_init, + .get_nss_info = nss_ad_get_info, + .close_fn = nss_ad_close }; diff --git a/source/winbindd/idmap_adex/cell_util.c b/source/winbindd/idmap_adex/cell_util.c deleted file mode 100644 index f5c08a0454..0000000000 --- a/source/winbindd/idmap_adex/cell_util.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * idmap_adex: Support for AD Forests - * - * Copyright (C) Gerald (Jerry) Carter 2006-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -/********************************************************************** -**********************************************************************/ - - char *find_attr_string(char **list, size_t num_lines, const char *substr) -{ - int i; - int cmplen = strlen(substr); - - for (i = 0; i < num_lines; i++) { - /* make sure to avoid substring matches like uid - and uidNumber */ - if ((StrnCaseCmp(list[i], substr, cmplen) == 0) && - (list[i][cmplen] == '=')) { - /* Don't return an empty string */ - if (list[i][cmplen + 1] != '\0') - return &(list[i][cmplen + 1]); - - return NULL; - } - } - - return NULL; -} - -/********************************************************************** -**********************************************************************/ - - bool is_object_class(char **list, size_t num_lines, const char *substr) -{ - int i; - - for (i = 0; i < num_lines; i++) { - if (strequal(list[i], substr)) { - return true; - } - } - - return false; -} - -/********************************************************************** - Find out about the cell (e.g. use2307Attrs, etc...) -**********************************************************************/ - - NTSTATUS cell_lookup_settings(struct likewise_cell * cell) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - /* Parameter check */ - - if (!cell) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Only supporting Forest-wide, schema based searches */ - - cell_set_flags(cell, LWCELL_FLAG_USE_RFC2307_ATTRS); - cell_set_flags(cell, LWCELL_FLAG_SEARCH_FOREST); - - cell->provider = &ccp_unified; - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(1,("LWI: Failed to obtain cell settings (%s)\n", - nt_errstr(nt_status))); - } - - return nt_status; -} - - -static NTSTATUS cell_lookup_forest(struct likewise_cell *c) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct gc_info *gc = NULL; - - if (!c) { - return NT_STATUS_INVALID_PARAMETER; - } - - if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) { - nt_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Query the rootDSE for the forest root naming conect first. - Check that the a GC server for the forest has not already - been added */ - - nt_status = gc_find_forest_root(gc, cell_dns_domain(c)); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - c->forest_name = talloc_strdup(c, gc->forest_name); - BAIL_ON_PTR_ERROR(c->forest_name, nt_status); - -done: - if (gc) { - talloc_free(gc); - } - - return nt_status; -} - -/********************************************************************** -**********************************************************************/ - - NTSTATUS cell_locate_membership(ADS_STRUCT * ads) -{ - ADS_STATUS status; - char *domain_dn = ads_build_dn(lp_realm()); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - DOM_SID sid; - struct likewise_cell *cell = NULL; - - /* In the Likewise plugin, I had to support the concept of cells - based on the machine's membership in an OU. However, now I'll - just assume our membership in the forest cell */ - - DEBUG(2, ("locate_cell_membership: Located membership " - "in cell \"%s\"\n", domain_dn)); - - if ((cell = cell_new()) == NULL) { - nt_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - status = ads_domain_sid(ads, &sid); - if (!ADS_ERR_OK(status)) { - DEBUG(3,("locate_cell_membership: Failed to find " - "domain SID for %s\n", domain_dn)); - } - - /* save the SID and search base for our domain */ - - cell_set_dns_domain(cell, lp_realm()); - cell_set_connection(cell, ads); - cell_set_dn(cell, domain_dn); - cell_set_domain_sid(cell, &sid); - - /* Now save our forest root */ - - cell_lookup_forest(cell); - - /* Add the cell to the list */ - - if (!cell_list_add(cell)) { - nt_status = NT_STATUS_INSUFFICIENT_RESOURCES; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Done! */ - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0,("LWI: Failed to locate cell membership (%s)\n", - nt_errstr(nt_status))); - } - - SAFE_FREE(domain_dn); - - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - - int min_id_value(void) -{ - int id_val; - - id_val = lp_parm_int(-1, "lwidentity", "min_id_value", MIN_ID_VALUE); - - /* Still don't let it go below 50 */ - - return MAX(50, id_val); -} - -/******************************************************************** - *******************************************************************/ - - char *cell_dn_to_dns(const char *dn) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *domain = NULL; - char *dns_name = NULL; - const char *tmp_dn; - char *buffer = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!dn || !*dn) { - goto done; - } - - tmp_dn = talloc_strdup(frame, dn); - BAIL_ON_PTR_ERROR(tmp_dn, nt_status); - - while (next_token_talloc(frame, &tmp_dn, &buffer, ",")) { - - /* skip everything up the where DC=... begins */ - if (StrnCaseCmp(buffer, "DC=", 3) != 0) - continue; - - if (!domain) { - domain = talloc_strdup(frame, &buffer[3]); - } else { - domain = talloc_asprintf_append(domain, ".%s", - &buffer[3]); - } - BAIL_ON_PTR_ERROR(domain, nt_status); - } - - dns_name = SMB_STRDUP(domain); - BAIL_ON_PTR_ERROR(dns_name, nt_status); - - nt_status = NT_STATUS_OK; - -done: - PRINT_NTSTATUS_ERROR(nt_status, "cell_dn_to_dns", 1); - - talloc_destroy(frame); - - return dns_name; -} - -/********************************************************************* - ********************************************************************/ - - NTSTATUS get_sid_type(ADS_STRUCT *ads, - LDAPMessage *msg, - enum lsa_SidType *type) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - uint32_t atype; - - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { - nt_status = NT_STATUS_INVALID_USER_BUFFER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - switch (atype &0xF0000000) { - case ATYPE_SECURITY_GLOBAL_GROUP: - *type = SID_NAME_DOM_GRP; - break; - case ATYPE_SECURITY_LOCAL_GROUP: - *type = SID_NAME_ALIAS; - break; - case ATYPE_NORMAL_ACCOUNT: - case ATYPE_WORKSTATION_TRUST: - case ATYPE_INTERDOMAIN_TRUST: - *type = SID_NAME_USER; - break; - default: - *type = SID_NAME_USE_NONE; - nt_status = NT_STATUS_INVALID_ACCOUNT_NAME; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - return nt_status; -} diff --git a/source/winbindd/idmap_adex/domain_util.c b/source/winbindd/idmap_adex/domain_util.c deleted file mode 100644 index ab31ccef7a..0000000000 --- a/source/winbindd/idmap_adex/domain_util.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * idmap_adex: Domain search interface - * - * Copyright (C) Gerald (Jerry) Carter 2007-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -struct dc_info { - struct dc_info *prev, *next; - char *dns_name; - struct likewise_cell *domain_cell; -}; - -static struct dc_info *_dc_server_list = NULL; - - -/********************************************************************** - *********************************************************************/ - -static struct dc_info *dc_list_head(void) -{ - return _dc_server_list; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS dc_add_domain(const char *domain) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct dc_info *dc = NULL; - - /* Check for duplicates */ - - dc = dc_list_head(); - while (dc) { - if (strequal (dc->dns_name, domain)) - break; - dc = dc->next; - } - - if (dc) { - DEBUG(10,("dc_add_domain: %s already in list\n", domain)); - return NT_STATUS_OK; - } - - dc = TALLOC_ZERO_P(NULL, struct dc_info); - BAIL_ON_PTR_ERROR(dc, nt_status); - - dc->dns_name = talloc_strdup(dc, domain); - BAIL_ON_PTR_ERROR(dc->dns_name, nt_status); - - DLIST_ADD_END(_dc_server_list, dc, struct dc_info*); - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_destroy(dc); - DEBUG(0,("LWI: Failed to add new DC connection for %s (%s)\n", - domain, nt_errstr(nt_status))); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static void dc_server_list_destroy(void) -{ - struct dc_info *dc = dc_list_head(); - - while (dc) { - struct dc_info *p = dc->next; - - cell_destroy(dc->domain_cell); - talloc_destroy(dc); - - dc = p; - } - - return; -} - - -/********************************************************************** - *********************************************************************/ - - NTSTATUS domain_init_list(void) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct winbindd_tdc_domain *domains = NULL; - size_t num_domains = 0; - int i; - - if (_dc_server_list != NULL) { - dc_server_list_destroy(); - } - - /* Add our domain */ - - nt_status = dc_add_domain(lp_realm()); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (!wcache_tdc_fetch_list(&domains, &num_domains)) { - nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Add all domains with an incoming trust path */ - - for (i=0; i<num_domains; i++) { - uint32_t flags = (NETR_TRUST_FLAG_INBOUND|NETR_TRUST_FLAG_IN_FOREST); - - /* We just require one of the flags to be set here */ - - if (domains[i].trust_flags & flags) { - nt_status = dc_add_domain(domains[i].dns_name); - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - } - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2,("LWI: Failed to initialize DC list (%s)\n", - nt_errstr(nt_status))); - } - - TALLOC_FREE(domains); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS dc_do_search(struct dc_info *dc, - const char *search_base, - int scope, - const char *expr, - const char **attrs, - LDAPMessage ** msg) -{ - ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - status = cell_do_search(dc->domain_cell, search_base, - scope, expr, attrs, msg); - nt_status = ads_ntstatus(status); - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static struct dc_info *dc_find_domain(const char *dns_domain) -{ - struct dc_info *dc = dc_list_head(); - - if (!dc) - return NULL; - - while (dc) { - if (strequal(dc->dns_name, dns_domain)) { - return dc; - } - - dc = dc->next; - } - - return NULL; -} - -/********************************************************************** - *********************************************************************/ - - NTSTATUS dc_search_domains(struct likewise_cell **cell, - LDAPMessage **msg, - const char *dn, - const DOM_SID *sid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *frame = talloc_stackframe(); - char *dns_domain; - const char *attrs[] = { "*", NULL }; - struct dc_info *dc = NULL; - const char *base = NULL; - - if (!dn || !*dn) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - dns_domain = cell_dn_to_dns(dn); - BAIL_ON_PTR_ERROR(dns_domain, nt_status); - - if ((dc = dc_find_domain(dns_domain)) == NULL) { - nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Reparse the cell settings for the domain if necessary */ - - if (!dc->domain_cell) { - char *base_dn; - - base_dn = ads_build_dn(dc->dns_name); - BAIL_ON_PTR_ERROR(base_dn, nt_status); - - nt_status = cell_connect_dn(&dc->domain_cell, base_dn); - SAFE_FREE(base_dn); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = cell_lookup_settings(dc->domain_cell); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* By definition this is already part of a larger - forest-wide search scope */ - - cell_set_flags(dc->domain_cell, LWCELL_FLAG_SEARCH_FOREST); - } - - /* Check whether we are operating in non-schema or RFC2307 - mode */ - - if (cell_flags(dc->domain_cell) & LWCELL_FLAG_USE_RFC2307_ATTRS) { - nt_status = dc_do_search(dc, dn, LDAP_SCOPE_BASE, - "(objectclass=*)", attrs, msg); - } else { - const char *sid_str = NULL; - char *filter = NULL; - - sid_str = sid_string_talloc(frame, sid); - BAIL_ON_PTR_ERROR(sid_str, nt_status); - - filter = talloc_asprintf(frame, "(keywords=backLink=%s)", - sid_str); - BAIL_ON_PTR_ERROR(filter, nt_status); - - base = cell_search_base(dc->domain_cell); - BAIL_ON_PTR_ERROR(base, nt_status); - - nt_status = dc_do_search(dc, base, LDAP_SCOPE_SUBTREE, - filter, attrs, msg); - } - BAIL_ON_NTSTATUS_ERROR(nt_status); - - *cell = dc->domain_cell; - -done: - talloc_destroy(CONST_DISCARD(char*, base)); - talloc_destroy(frame); - - return nt_status; -} diff --git a/source/winbindd/idmap_adex/gc_util.c b/source/winbindd/idmap_adex/gc_util.c deleted file mode 100644 index 87dd3c058d..0000000000 --- a/source/winbindd/idmap_adex/gc_util.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * idmap_adex: Global Catalog search interface - * - * Copyright (C) Gerald (Jerry) Carter 2007-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -static struct gc_info *_gc_server_list = NULL; - - -/********************************************************************** - *********************************************************************/ - -static struct gc_info *gc_list_head(void) -{ - return _gc_server_list; -} - -/********************************************************************** - Checks if either of the domains is a subdomain of the other - *********************************************************************/ - -static bool is_subdomain(const char* a, const char *b) -{ - char *s; - TALLOC_CTX *frame = talloc_stackframe(); - char *x, *y; - bool ret = false; - - /* Trivial cases */ - - if (!a && !b) - return true; - - if (!a || !b) - return false; - - /* Normalize the case */ - - x = talloc_strdup(frame, a); - y = talloc_strdup(frame, b); - if (!x || !y) { - ret = false; - goto done; - } - - strupper_m(x); - strupper_m(y); - - /* Exact match */ - - if (strcmp(x, y) == 0) { - ret = true; - goto done; - } - - /* Check for trailing substrings */ - - s = strstr_m(x, y); - if (s && (strlen(s) == strlen(y))) { - ret = true; - goto done; - } - - s = strstr_m(y, x); - if (s && (strlen(s) == strlen(x))) { - ret = true; - goto done; - } - -done: - talloc_destroy(frame); - - return ret; -} - -/********************************************************************** - *********************************************************************/ - - NTSTATUS gc_find_forest_root(struct gc_info *gc, const char *domain) -{ - ADS_STRUCT *ads = NULL; - ADS_STATUS ads_status; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct nbt_cldap_netlogon_5 cldap_reply; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!gc || !domain) { - return NT_STATUS_INVALID_PARAMETER; - } - - ZERO_STRUCT(cldap_reply); - - ads = ads_init(domain, NULL, NULL); - BAIL_ON_PTR_ERROR(ads, nt_status); - - ads->auth.flags = ADS_AUTH_NO_BIND; - ads_status = ads_connect(ads); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4, ("find_forest_root: ads_connect(%s) failed! (%s)\n", - domain, ads_errstr(ads_status))); - } - nt_status = ads_ntstatus(ads_status); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (!ads_cldap_netlogon_5(frame, - ads->config.ldap_server_name, - ads->config.realm, - &cldap_reply)) - { - DEBUG(4,("find_forest_root: Failed to get a CLDAP reply from %s!\n", - ads->server.ldap_server)); - nt_status = NT_STATUS_IO_TIMEOUT; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - gc->forest_name = talloc_strdup(gc, cldap_reply.forest); - BAIL_ON_PTR_ERROR(gc->forest_name, nt_status); - -done: - if (ads) { - ads_destroy(&ads); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS gc_add_forest(const char *domain) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct gc_info *gc = NULL; - struct gc_info *find_gc = NULL; - char *dn; - ADS_STRUCT *ads = NULL; - struct likewise_cell *primary_cell = NULL; - - primary_cell = cell_list_head(); - if (!primary_cell) { - nt_status = NT_STATUS_INVALID_SERVER_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Check for duplicates based on domain name first as this - requires no connection */ - - find_gc = gc_list_head(); - while (find_gc) { - if (strequal (find_gc->forest_name, domain)) - break; - find_gc = find_gc->next; - } - - if (find_gc) { - DEBUG(10,("gc_add_forest: %s already in list\n", find_gc->forest_name)); - return NT_STATUS_OK; - } - - if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) { - nt_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Query the rootDSE for the forest root naming conect first. - Check that the a GC server for the forest has not already - been added */ - - nt_status = gc_find_forest_root(gc, domain); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - find_gc = gc_list_head(); - while (find_gc) { - if (strequal (find_gc->forest_name, gc->forest_name)) - break; - find_gc = find_gc->next; - } - - if (find_gc) { - DEBUG(10,("gc_add_forest: Forest %s already in list\n", - find_gc->forest_name)); - return NT_STATUS_OK; - } - - /* Not found, so add it here. Make sure we connect to - a DC in _this_ domain and not the forest root. */ - - dn = ads_build_dn(gc->forest_name); - BAIL_ON_PTR_ERROR(dn, nt_status); - - gc->search_base = talloc_strdup(gc, dn); - SAFE_FREE(dn); - BAIL_ON_PTR_ERROR(gc->search_base, nt_status); - -#if 0 - /* Can't use cell_connect_dn() here as there is no way to - specifiy the LWCELL_FLAG_GC_CELL flag setting for cell_connect() */ - - nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base); - BAIL_ON_NTSTATUS_ERROR(nt_status); -#else - - gc->forest_cell = cell_new(); - BAIL_ON_PTR_ERROR(gc->forest_cell, nt_status); - - /* Set the DNS domain, dn, etc ... and add it to the list */ - - cell_set_dns_domain(gc->forest_cell, gc->forest_name); - cell_set_dn(gc->forest_cell, gc->search_base); - cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL); -#endif - - /* It is possible to belong to a non-forest cell and a - non-provisioned forest (at our domain levele). In that - case, we should just inherit the flags from our primary - cell since the GC searches will match our own schema - model. */ - - if (strequal(primary_cell->forest_name, gc->forest_name) - || is_subdomain(primary_cell->dns_domain, gc->forest_name)) - { - cell_set_flags(gc->forest_cell, cell_flags(primary_cell)); - } else { - /* outside of our domain */ - - nt_status = cell_connect(gc->forest_cell); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = cell_lookup_settings(gc->forest_cell); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Drop the connection now that we have the settings */ - - ads = cell_connection(gc->forest_cell); - ads_destroy(&ads); - cell_set_connection(gc->forest_cell, NULL); - } - - DLIST_ADD_END(_gc_server_list, gc, struct gc_info*); - - DEBUG(10,("gc_add_forest: Added %s to Global Catalog list of servers\n", - gc->forest_name)); - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_destroy(gc); - DEBUG(3,("LWI: Failed to add new GC connection for %s (%s)\n", - domain, nt_errstr(nt_status))); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static void gc_server_list_destroy(void) -{ - struct gc_info *gc = gc_list_head(); - - while (gc) { - struct gc_info *p = gc->next; - - cell_destroy(gc->forest_cell); - talloc_destroy(gc); - - gc = p; - } - - _gc_server_list = NULL; - - return; -} - -/********************************************************************** - Setup the initial list of forests and initial the forest cell - settings for each. FIXME!!! - *********************************************************************/ - - NTSTATUS gc_init_list(void) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct winbindd_tdc_domain *domains = NULL; - size_t num_domains = 0; - int i; - - if (_gc_server_list != NULL) { - gc_server_list_destroy(); - } - - if (!wcache_tdc_fetch_list(&domains, &num_domains)) { - nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Find our forest first. Have to try all domains here starting - with our own. gc_add_forest() filters duplicates */ - - nt_status = gc_add_forest(lp_realm()); - WARN_ON_NTSTATUS_ERROR(nt_status); - - for (i=0; i<num_domains; i++) { - uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST); - - /* I think we should be able to break out of loop once - we add a GC for our forest and not have to test every one. - In fact, this entire loop is probably irrelevant since - the GC location code should always find a GC given lp_realm(). - Will have to spend time testing before making the change. - --jerry */ - - if ((domains[i].trust_flags & flags) == flags) { - nt_status = gc_add_forest(domains[i].dns_name); - WARN_ON_NTSTATUS_ERROR(nt_status); - /* Don't BAIL here since not every domain may - have a GC server */ - } - } - - /* Now add trusted forests. gc_add_forest() will filter out - duplicates. Check everything with an incoming trust path - that is not in our own forest. */ - - for (i=0; i<num_domains; i++) { - uint32_t flags = domains[i].trust_flags; - uint32_t attribs = domains[i].trust_attribs; - - /* Skip non_AD domains */ - - if (strlen(domains[i].dns_name) == 0) { - continue; - } - - /* Only add a GC for a forest outside of our own. - Ignore QUARANTINED/EXTERNAL trusts */ - - if ((flags & NETR_TRUST_FLAG_INBOUND) - && !(flags & NETR_TRUST_FLAG_IN_FOREST) - && (attribs & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) - { - nt_status = gc_add_forest(domains[i].dns_name); - WARN_ON_NTSTATUS_ERROR(nt_status); - } - } - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2,("LWI: Failed to initialized GC list (%s)\n", - nt_errstr(nt_status))); - } - - TALLOC_FREE(domains); - - return nt_status; -} - - -/********************************************************************** - *********************************************************************/ - - struct gc_info *gc_search_start(void) -{ - NTSTATUS nt_status = NT_STATUS_OK; - struct gc_info *gc = gc_list_head(); - - if (!gc) { - nt_status = gc_init_list(); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - gc = gc_list_head(); - } - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2,("LWI: Failed to initialize GC list (%s)\n", - nt_errstr(nt_status))); - } - - return gc; -} - -/********************************************************************** - Search Global Catalog. Always search our own forest. The flags set - controls whether or not we search cross forest. Assume that the - resulting set is always returned from one GC so that we don't have to - both combining the LDAPMessage * results - *********************************************************************/ - - NTSTATUS gc_search_forest(struct gc_info *gc, - LDAPMessage **msg, - const char *filter) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - const char *attrs[] = {"*", NULL}; - LDAPMessage *m = NULL; - - if (!gc || !msg || !filter) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* When you have multiple domain trees in a forest, the - GC will search all naming contexts when you send it - and empty ("") base search suffix. Tested against - Windows 2003. */ - - ads_status = cell_do_search(gc->forest_cell, "", - LDAP_SCOPE_SUBTREE, filter, attrs, &m); - nt_status = ads_ntstatus(ads_status); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - *msg = m; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2,("LWI: Forest wide search %s failed (%s)\n", - filter, nt_errstr(nt_status))); - } - - return nt_status; -} - -/********************************************************************** - Search all forests via GC and return the results in an array of - ADS_STRUCT/LDAPMessage pairs. - *********************************************************************/ - - NTSTATUS gc_search_all_forests(const char *filter, - ADS_STRUCT ***ads_list, - LDAPMessage ***msg_list, - int *num_resp, uint32_t flags) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct gc_info *gc = NULL; - uint32_t test_flags = ADEX_GC_SEARCH_CHECK_UNIQUE; - - *ads_list = NULL; - *msg_list = NULL; - *num_resp = 0; - - if ((gc = gc_search_start()) == NULL) { - nt_status = NT_STATUS_INVALID_DOMAIN_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - while (gc) { - LDAPMessage *m = NULL; - - nt_status = gc_search_forest(gc, &m, filter); - if (!NT_STATUS_IS_OK(nt_status)) { - gc = gc->next; - continue; - } - - nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell), - m, ads_list, msg_list, - num_resp); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* If there can only be one match, then we are done */ - - if ((*num_resp > 0) && ((flags & test_flags) == test_flags)) { - break; - } - - gc = gc->next; - } - - if (*num_resp == 0) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - return nt_status; -} - -/********************************************************************** - Search all forests via GC and return the results in an array of - ADS_STRUCT/LDAPMessage pairs. - *********************************************************************/ - - NTSTATUS gc_search_all_forests_unique(const char *filter, - ADS_STRUCT **ads, - LDAPMessage **msg) -{ - ADS_STRUCT **ads_list = NULL; - LDAPMessage **msg_list = NULL; - int num_resp; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - nt_status = gc_search_all_forests(filter, &ads_list, - &msg_list, &num_resp, - ADEX_GC_SEARCH_CHECK_UNIQUE); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = check_result_unique(ads_list[0], msg_list[0]); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - *ads = ads_list[0]; - *msg = msg_list[0]; - -done: - /* Be care that we don't free the msg result being returned */ - - if (!NT_STATUS_IS_OK(nt_status)) { - free_result_array(ads_list, msg_list, num_resp); - } else { - talloc_destroy(ads_list); - talloc_destroy(msg_list); - } - - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - - NTSTATUS gc_name_to_sid(const char *domain, - const char *name, - DOM_SID *sid, - enum lsa_SidType *sid_type) -{ - TALLOC_CTX *frame = talloc_stackframe(); - char *p, *name_user; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *name_filter; - ADS_STRUCT *ads = NULL; - LDAPMessage *msg = NULL; - LDAPMessage *e = NULL; - char *dn = NULL; - char *dns_domain = NULL; - ADS_STRUCT **ads_list = NULL; - LDAPMessage **msg_list = NULL; - int num_resp = 0; - int i; - - /* Strip the "DOMAIN\" prefix if necessary and search for - a matching sAMAccountName in the forest */ - - if ((p = strchr_m( name, '\\' )) == NULL) - name_user = talloc_strdup( frame, name ); - else - name_user = talloc_strdup( frame, p+1 ); - BAIL_ON_PTR_ERROR(name_user, nt_status); - - name_filter = talloc_asprintf(frame, "(sAMAccountName=%s)", name_user); - BAIL_ON_PTR_ERROR(name_filter, nt_status); - - nt_status = gc_search_all_forests(name_filter, &ads_list, - &msg_list, &num_resp, 0); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Assume failure until we know otherwise*/ - - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - - /* Match the domain name from the DN */ - - for (i=0; i<num_resp; i++) { - ads = ads_list[i]; - msg = msg_list[i]; - - e = ads_first_entry(ads, msg); - while (e) { - struct winbindd_tdc_domain *domain_rec; - - dn = ads_get_dn(ads, e); - BAIL_ON_PTR_ERROR(dn, nt_status); - - dns_domain = cell_dn_to_dns(dn); - SAFE_FREE(dn); - BAIL_ON_PTR_ERROR(dns_domain, nt_status); - - domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); - SAFE_FREE(dns_domain); - - /* Ignore failures and continue the search */ - - if (!domain_rec) { - e = ads_next_entry(ads, e); - continue; - } - - /* Check for a match on the domain name */ - - if (strequal(domain, domain_rec->domain_name)) { - if (!ads_pull_sid(ads, e, "objectSid", sid)) { - nt_status = NT_STATUS_INVALID_SID; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - talloc_destroy(domain_rec); - - nt_status = get_sid_type(ads, msg, sid_type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* We're done! */ - nt_status = NT_STATUS_OK; - break; - } - - /* once more around thew merry-go-round */ - - talloc_destroy(domain_rec); - e = ads_next_entry(ads, e); - } - } - -done: - free_result_array(ads_list, msg_list, num_resp); - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - Pull an attribute string value - *******************************************************************/ - -static NTSTATUS get_object_account_name(ADS_STRUCT *ads, - LDAPMessage *msg, - char **name) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *sam_name = NULL; - struct winbindd_tdc_domain *domain_rec = NULL; - char *dns_domain = NULL; - char *dn = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - int len; - - /* Check parameters */ - - if (!ads || !msg || !name) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* get the name and domain */ - - dn = ads_get_dn(ads, msg); - BAIL_ON_PTR_ERROR(dn, nt_status); - - DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn)); - - dns_domain = cell_dn_to_dns(dn); - SAFE_FREE(dn); - BAIL_ON_PTR_ERROR(dns_domain, nt_status); - - domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); - SAFE_FREE(dns_domain); - - if (!domain_rec) { - nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - sam_name = ads_pull_string(ads, frame, msg, "sAMAccountName"); - BAIL_ON_PTR_ERROR(sam_name, nt_status); - - len = asprintf(name, "%s\\%s", domain_rec->domain_name, sam_name); - if (len == -1) { - *name = NULL; - BAIL_ON_PTR_ERROR((*name), nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(frame); - - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - - NTSTATUS gc_sid_to_name(const DOM_SID *sid, - char **name, - enum lsa_SidType *sid_type) -{ - TALLOC_CTX *frame = talloc_stackframe(); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *filter; - ADS_STRUCT *ads = NULL; - LDAPMessage *msg = NULL; - char *sid_string; - - *name = NULL; - - sid_string = sid_binstring(sid); - BAIL_ON_PTR_ERROR(sid_string, nt_status); - - filter = talloc_asprintf(frame, "(objectSid=%s)", sid_string); - SAFE_FREE(sid_string); - BAIL_ON_PTR_ERROR(filter, nt_status); - - nt_status = gc_search_all_forests_unique(filter, &ads, &msg); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_object_account_name(ads, msg, name); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_sid_type(ads, msg, sid_type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - ads_msgfree(ads, msg); - talloc_destroy(frame); - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - - NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads, - LDAPMessage *msg, - ADS_STRUCT ***ads_list, - LDAPMessage ***msg_list, - int *size) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - ADS_STRUCT **ads_tmp = NULL; - LDAPMessage **msg_tmp = NULL; - int count = *size; - - if (!ads || !msg) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - -#if 0 - /* Don't add a response with no entries */ - - if (ads_count_replies(ads, msg) == 0) { - return NT_STATUS_OK; - } -#endif - - if (count == 0) { - ads_tmp = TALLOC_ARRAY(NULL, ADS_STRUCT*, 1); - BAIL_ON_PTR_ERROR(ads_tmp, nt_status); - - msg_tmp = TALLOC_ARRAY(NULL, LDAPMessage*, 1); - BAIL_ON_PTR_ERROR(msg_tmp, nt_status); - } else { - ads_tmp = TALLOC_REALLOC_ARRAY(*ads_list, *ads_list, ADS_STRUCT*, - count+1); - BAIL_ON_PTR_ERROR(ads_tmp, nt_status); - - msg_tmp = TALLOC_REALLOC_ARRAY(*msg_list, *msg_list, LDAPMessage*, - count+1); - BAIL_ON_PTR_ERROR(msg_tmp, nt_status); - } - - ads_tmp[count] = ads; - msg_tmp[count] = msg; - count++; - - *ads_list = ads_tmp; - *msg_list = msg_tmp; - *size = count; - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_destroy(ads_tmp); - talloc_destroy(msg_tmp); - } - - return nt_status; -} - -/********************************************************************** - Frees search results. Do not free the ads_list as these are - references back to the GC search structures. - *********************************************************************/ - - void free_result_array(ADS_STRUCT **ads_list, - LDAPMessage **msg_list, - int num_resp) -{ - int i; - - for (i=0; i<num_resp; i++) { - ads_msgfree(ads_list[i], msg_list[i]); - } - - talloc_destroy(ads_list); - talloc_destroy(msg_list); -} - -/********************************************************************** - Check that we have exactly one entry from the search - *********************************************************************/ - - NTSTATUS check_result_unique(ADS_STRUCT *ads, LDAPMessage *msg) -{ - NTSTATUS nt_status; - int count; - - count = ads_count_replies(ads, msg); - - if (count <= 0) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if (count > 1) { - nt_status = NT_STATUS_DUPLICATE_NAME; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - return nt_status; -} diff --git a/source/winbindd/idmap_adex/idmap_adex.c b/source/winbindd/idmap_adex/idmap_adex.c deleted file mode 100644 index 23ab843e95..0000000000 --- a/source/winbindd/idmap_adex/idmap_adex.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * idmap_adex: Support for D Forests - * - * Copyright (C) Gerald (Jerry) Carter 2006-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache" - -NTSTATUS init_module(void); - -/* - * IdMap backend - */ - -/******************************************************************** - Basic init function responsible for determining our current mode - (standalone or using Centeris Cells). This must return success or - it will be dropped from the idmap backend list. - *******************************************************************/ - -static NTSTATUS _idmap_adex_init(struct idmap_domain *dom, - const char *params) -{ - ADS_STRUCT *ads = NULL; - ADS_STATUS status; - static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - DOM_SID domain_sid; - fstring dcname; - struct sockaddr_storage ip; - struct likewise_cell *lwcell; - - if (NT_STATUS_IS_OK(init_status)) - return NT_STATUS_OK; - - /* Silently fail if we are not a member server in security = ads */ - - if ((lp_server_role() != ROLE_DOMAIN_MEMBER) || - (lp_security() != SEC_ADS)) { - init_status = NT_STATUS_INVALID_SERVER_STATE; - BAIL_ON_NTSTATUS_ERROR(init_status); - } - - /* fetch our domain SID first */ - - if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { - init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - BAIL_ON_NTSTATUS_ERROR(init_status); - } - - /* reuse the same ticket cache as winbindd */ - - setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); - - /* Establish a connection to a DC */ - - if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) { - init_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(init_status); - } - - ads->auth.password = - secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - ads->auth.realm = SMB_STRDUP(lp_realm()); - - /* get the DC name here to setup the server affinity cache and - local krb5.conf */ - - get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip); - - status = ads_connect(ads); - if (!ADS_ERR_OK(status)) { - DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n", - ads_errstr(status))); - } - init_status = ads_ntstatus(status); - BAIL_ON_NTSTATUS_ERROR(init_status); - - - /* Find out cell membership */ - - init_status = cell_locate_membership(ads); - if (!NT_STATUS_IS_OK(init_status)) { - DEBUG(0,("LWI: Fail to locate cell membership (%s).", - nt_errstr(init_status))); - goto done; - } - - /* Fill in the cell information */ - - lwcell = cell_list_head(); - - init_status = cell_lookup_settings(lwcell); - BAIL_ON_NTSTATUS_ERROR(init_status); - - /* Miscellaneous setup. E.g. set up the list of GC - servers and domain list for our forest (does not actually - connect). */ - - init_status = gc_init_list(); - BAIL_ON_NTSTATUS_ERROR(init_status); - - init_status = domain_init_list(); - BAIL_ON_NTSTATUS_ERROR(init_status); - -done: - if (!NT_STATUS_IS_OK(init_status)) { - DEBUG(1,("Likewise initialization failed (%s)\n", - nt_errstr(init_status))); - } - - /* cleanup */ - - if (!NT_STATUS_IS_OK(init_status)) { - cell_list_destroy(); - - /* init_status stores the failure reason but we need to - return success or else idmap_init() will drop us from the - backend list */ - return NT_STATUS_OK; - } - - init_status = NT_STATUS_OK; - - return init_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_get_sid_from_id(struct - idmap_domain - *dom, struct - id_map - **ids) -{ - int i; - bool one_mapped = false; - bool all_mapped = true; - NTSTATUS nt_status; - struct likewise_cell *cell; - - nt_status = _idmap_adex_init(dom, NULL); - if (!NT_STATUS_IS_OK(nt_status)) - return nt_status; - - if ((cell = cell_list_head()) == NULL) { - return NT_STATUS_INVALID_SERVER_STATE; - } - - /* have to work through these one by one */ - for (i = 0; ids[i]; i++) { - NTSTATUS status; - status = cell->provider->get_sid_from_id(ids[i]->sid, - ids[i]->xid.id, - ids[i]->xid.type); - /* Fail if we cannot find any DC */ - if (NT_STATUS_EQUAL - (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { - return status; - } - - if (!NT_STATUS_IS_OK(status)) { - ids[i]->status = ID_UNMAPPED; - all_mapped = false; - continue; - } - - ids[i]->status = ID_MAPPED; - one_mapped = true; - } - - return NT_STATUS_OK; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_get_id_from_sid(struct - idmap_domain - *dom, struct - id_map - **ids) -{ - int i; - bool one_mapped = false; - bool all_mapped = true; - NTSTATUS nt_status; - struct likewise_cell *cell; - - nt_status = _idmap_adex_init(dom, NULL); - if (!NT_STATUS_IS_OK(nt_status)) - return nt_status; - - if ((cell = cell_list_head()) == NULL) { - return NT_STATUS_INVALID_SERVER_STATE; - } - - /* have to work through these one by one */ - for (i = 0; ids[i]; i++) { - NTSTATUS status; - status = cell->provider->get_id_from_sid(&ids[i]->xid.id, - &ids[i]->xid. - type, ids[i]->sid); - /* Fail if we cannot find any DC */ - if (NT_STATUS_EQUAL - (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { - return status; - } - - if (!NT_STATUS_IS_OK(status)) { - ids[i]->status = ID_UNMAPPED; - all_mapped = false; - continue; - } - - ids[i]->status = ID_MAPPED; - one_mapped = true; - } - - return NT_STATUS_OK; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_set_mapping(struct - idmap_domain - *dom, const struct - id_map *map) -{ - DEBUG(0, ("_idmap_adex_set_mapping: not implemented\n")); - return NT_STATUS_NOT_IMPLEMENTED; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_remove_mapping(struct - idmap_domain - *dom, const - struct - id_map - *map) -{ - DEBUG(0, ("_idmap_adex_remove_mapping: not implemented\n")); - return NT_STATUS_NOT_IMPLEMENTED; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_dump(struct idmap_domain - *dom, struct id_map **maps, int *num_map) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _idmap_adex_close(struct idmap_domain - *dom) -{ - /* FIXME! need to do cleanup here */ - - return NT_STATUS_OK; -} - -/* - * IdMap NSS plugin - */ - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _nss_adex_init(struct nss_domain_entry - *e) -{ - return _idmap_adex_init(NULL, NULL); -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _nss_adex_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 * p_gid) -{ - NTSTATUS nt_status; - struct likewise_cell *cell; - - nt_status = _idmap_adex_init(NULL, NULL); - if (!NT_STATUS_IS_OK(nt_status)) - return nt_status; - - if ((cell = cell_list_head()) == NULL) { - return NT_STATUS_INVALID_SERVER_STATE; - } - - return cell->provider->get_nss_info(sid, ctx, homedir, - shell, gecos, p_gid); -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx, const char - *domain, const char - *name, char **alias) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct likewise_cell *cell = NULL; - - nt_status = _idmap_adex_init(NULL, NULL); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if ((cell = cell_list_head()) == NULL) { - nt_status = NT_STATUS_INVALID_SERVER_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = cell->provider->map_to_alias(mem_ctx, domain, - name, alias); - - /* go ahead and allow the cache mgr to mark this in - negative cache */ - - if (!NT_STATUS_IS_OK(nt_status)) - nt_status = NT_STATUS_NONE_MAPPED; - -done: - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx, const char - *domain, const char - *alias, char **name) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct likewise_cell *cell = NULL; - - nt_status = _idmap_adex_init(NULL, NULL); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if ((cell = cell_list_head()) == NULL) { - nt_status = NT_STATUS_INVALID_SERVER_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - - nt_status = cell->provider->map_from_alias(mem_ctx, domain, - alias, name); - - /* go ahead and allow the cache mgr to mark this in - negative cache */ - - if (!NT_STATUS_IS_OK(nt_status)) - nt_status = NT_STATUS_NONE_MAPPED; - -done: - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _nss_adex_close(void) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/********************************************************************** - *********************************************************************/ - -static struct idmap_methods adex_idmap_methods = { - - .init = _idmap_adex_init, - .unixids_to_sids = _idmap_adex_get_sid_from_id, - .sids_to_unixids = _idmap_adex_get_id_from_sid, - .set_mapping = _idmap_adex_set_mapping, - .remove_mapping = _idmap_adex_remove_mapping, - .dump_data = _idmap_adex_dump, - .close_fn = _idmap_adex_close -}; -static struct nss_info_methods adex_nss_methods = { - .init = _nss_adex_init, - .get_nss_info = _nss_adex_get_info, - .map_to_alias = _nss_adex_map_to_alias, - .map_from_alias = _nss_adex_map_from_alias, - .close_fn = _nss_adex_close -}; - -/********************************************************************** - Register with the idmap and idmap_nss subsystems. We have to protect - against the idmap and nss_info interfaces being in a half-registered - state. - **********************************************************************/ -NTSTATUS idmap_adex_init(void) -{ - static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL; - static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL; - if (!NT_STATUS_IS_OK(idmap_status)) { - idmap_status = - smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, - "adex", &adex_idmap_methods); - if (!NT_STATUS_IS_OK(idmap_status)) { - DEBUG(0, - ("idmap_centeris_init: Failed to register the adex" - "idmap plugin.\n")); - return idmap_status; - } - } - - if (!NT_STATUS_IS_OK(nss_status)) { - nss_status = - smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, - "adex", &adex_nss_methods); - if (!NT_STATUS_IS_OK(nss_status)) { - DEBUG(0, - ("idmap_adex_init: Failed to register the adex" - "nss plugin.\n")); - return nss_status; - } - } - - return NT_STATUS_OK; -} - -NTSTATUS nss_info_adex_init(void) -{ - return idmap_adex_init(); -} diff --git a/source/winbindd/idmap_adex/idmap_adex.h b/source/winbindd/idmap_adex/idmap_adex.h deleted file mode 100644 index f91bba8d07..0000000000 --- a/source/winbindd/idmap_adex/idmap_adex.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * idmap_centeris: Support for Local IDs and Centeris Cell Structure - * - * Copyright (C) Gerald (Jerry) Carter 2006-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 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. - */ - -#ifndef _IDMAP_ADEX_H -#define _IDMAP_ADEX_H - -#include "winbindd/winbindd.h" - -#define ADEX_CELL_RDN "$LikewiseIdentityCell" - -#define ADEX_OC_USER "centerisLikewiseUser" -#define ADEX_OC_GROUP "centerisLikewiseGroup" - -#define AD_USER "User" -#define AD_GROUP "Group" - -#define ADEX_OC_POSIX_USER "posixAccount" -#define ADEX_OC_POSIX_GROUP "posixGroup" - -#define ADEX_ATTR_UIDNUM "uidNumber" -#define ADEX_ATTR_GIDNUM "gidNUmber" -#define ADEX_ATTR_HOMEDIR "unixHomeDirectory" -#define ADEX_ATTR_USERPW "unixUserPassword" -#define ADEX_ATTR_GROUPALIAS "groupAlias" /* Not part of RFC2307 */ -#define ADEX_ATTR_SHELL "loginShell" -#define ADEX_ATTR_GECOS "gecos" -#define ADEX_ATTR_UID "uid" -#define ADEX_ATTR_DISPLAYNAME "displayName" - -#define MIN_ID_VALUE 100 - -#define BAIL_ON_NTSTATUS_ERROR(x) \ - do { \ - if (!NT_STATUS_IS_OK(x)) { \ - DEBUG(10,("Failed! (%s)\n", nt_errstr(x))); \ - goto done; \ - } \ - } \ - while (0); \ - -#define WARN_ON_NTSTATUS_ERROR(x) \ - do { \ - if (!NT_STATUS_IS_OK(x)) { \ - DEBUG(10,("Failure ignored! (%s)\n", nt_errstr(x))); \ - } \ - } \ - while (0); \ - -#define BAIL_ON_ADS_ERROR(x) \ - do { \ - if (!ADS_ERR_OK(x)) { \ - goto done; \ - } \ - } \ - while (0); - -#define BAIL_ON_PTR_ERROR(p, x) \ - do { \ - if ((p) == NULL ) { \ - DEBUG(10,("NULL pointer!\n")); \ - x = NT_STATUS_NO_MEMORY; \ - goto done; \ - } \ - } while (0); - -#define PRINT_NTSTATUS_ERROR(x, hdr, level) \ - do { \ - if (!NT_STATUS_IS_OK(x)) { \ - DEBUG(level,("LWI ("hdr"): %s\n", nt_errstr(x))); \ - } \ - } while(0); -/* - * Cell Provider API - */ - -struct cell_provider_api { - NTSTATUS(*get_sid_from_id) (DOM_SID * sid, - uint32_t id, enum id_type type); - NTSTATUS(*get_id_from_sid) (uint32_t * id, - enum id_type * type, const DOM_SID * sid); - NTSTATUS(*get_nss_info) (const DOM_SID * sid, - TALLOC_CTX * ctx, - char **homedir, - char **shell, char **gecos, gid_t * p_gid); - NTSTATUS(*map_to_alias) (TALLOC_CTX * mem_ctx, - const char *domain, - const char *name, char **alias); - NTSTATUS(*map_from_alias) (TALLOC_CTX * mem_ctx, - const char *domain, - const char *alias, char **name); -}; - -/* registered providers */ - -extern struct cell_provider_api ccp_unified; -extern struct cell_provider_api ccp_local; - -#define LWCELL_FLAG_USE_RFC2307_ATTRS 0x00000001 -#define LWCELL_FLAG_SEARCH_FOREST 0x00000002 -#define LWCELL_FLAG_GC_CELL 0x00000004 -#define LWCELL_FLAG_LOCAL_MODE 0x00000008 - -struct likewise_cell { - struct likewise_cell *prev, *next; - ADS_STRUCT *conn; - struct likewise_cell *gc_search_cell; - DOM_SID domain_sid; - char *dns_domain; - char *forest_name; - char *dn; - struct GUID *links; /* only held by owning cell */ - size_t num_links; - uint32_t flags; - struct cell_provider_api *provider; -}; - -/* Search flags used for Global Catalog API */ - -#define ADEX_GC_SEARCH_CHECK_UNIQUE 0x00000001 - -struct gc_info { - struct gc_info *prev, *next; - char *forest_name; - char *search_base; - struct likewise_cell *forest_cell; -}; - -/* Available functions outside of idmap_lwidentity.c */ - -/* cell_util.c */ - -char *find_attr_string(char **list, size_t num_lines, const char *substr); -bool is_object_class(char **list, size_t num_lines, const char *substr); -int min_id_value(void); -char *cell_dn_to_dns(const char *dn); -NTSTATUS get_sid_type(ADS_STRUCT *ads, - LDAPMessage *msg, - enum lsa_SidType *type); - -NTSTATUS cell_locate_membership(ADS_STRUCT * ads); -NTSTATUS cell_lookup_settings(struct likewise_cell * cell); -NTSTATUS cell_follow_links(struct likewise_cell *cell); -NTSTATUS cell_set_local_provider(void); - -/* likewise_cell.c */ - -struct likewise_cell *cell_new(void); -struct likewise_cell *cell_list_head(void); - -bool cell_list_add(struct likewise_cell *cell); -bool cell_list_remove(struct likewise_cell * cell); - -void cell_list_destroy(); -void cell_destroy(struct likewise_cell *c); -void cell_set_forest_searches(struct likewise_cell *c, - bool search); -void cell_set_dns_domain(struct likewise_cell *c, - const char *dns_domain); -void cell_set_connection(struct likewise_cell *c, - ADS_STRUCT *ads); -void cell_set_dn(struct likewise_cell *c, - const char *dn); -void cell_set_domain_sid(struct likewise_cell *c, - DOM_SID *sid); -void cell_set_flags(struct likewise_cell *c, uint32_t flags); -void cell_clear_flags(struct likewise_cell *c, uint32_t flags); - -const char* cell_search_base(struct likewise_cell *c); -const char *cell_dns_domain(struct likewise_cell *c); -ADS_STRUCT *cell_connection(struct likewise_cell *c); -bool cell_search_forest(struct likewise_cell *c); -ADS_STATUS cell_do_search(struct likewise_cell *c, - const char *search_base, - int scope, - const char *expr, - const char **attrs, - LDAPMessage ** msg); -uint32_t cell_flags(struct likewise_cell *c); - -NTSTATUS cell_connect_dn(struct likewise_cell **c, - const char *dn); -NTSTATUS cell_connect(struct likewise_cell *c); - - -/* gc_util.c */ - -NTSTATUS gc_init_list(void); - -NTSTATUS gc_find_forest_root(struct gc_info *gc, - const char *domain); - -struct gc_info *gc_search_start(void); - -NTSTATUS gc_search_forest(struct gc_info *gc, - LDAPMessage **msg, - const char *filter); - -NTSTATUS gc_search_all_forests(const char *filter, - ADS_STRUCT ***ads_list, - LDAPMessage ***msg_list, - int *num_resp, uint32_t flags); - -NTSTATUS gc_search_all_forests_unique(const char *filter, - ADS_STRUCT **ads, - LDAPMessage **msg); - -NTSTATUS gc_name_to_sid(const char *domain, - const char *name, - DOM_SID *sid, - enum lsa_SidType *sid_type); - -NTSTATUS gc_sid_to_name(const DOM_SID *sid, - char **name, - enum lsa_SidType *sid_type); - -NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads, - LDAPMessage *msg, - ADS_STRUCT ***ads_list, - LDAPMessage ***msg_list, - int *size); - -void free_result_array(ADS_STRUCT **ads_list, - LDAPMessage **msg_list, - int num_resp); - -NTSTATUS check_result_unique(ADS_STRUCT *ads, - LDAPMessage *msg); - - -/* domain_util.c */ - -NTSTATUS domain_init_list(void); - -NTSTATUS dc_search_domains(struct likewise_cell **cell, - LDAPMessage **msg, - const char *dn, - const DOM_SID *user_sid); - - -#endif /* _IDMAP_ADEX_H */ diff --git a/source/winbindd/idmap_adex/likewise_cell.c b/source/winbindd/idmap_adex/likewise_cell.c deleted file mode 100644 index 77eeee406b..0000000000 --- a/source/winbindd/idmap_adex/likewise_cell.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * idmap_adex: Support for AD Forests - * - * Copyright (C) Gerald (Jerry) Carter 2006-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -static struct likewise_cell *_lw_cell_list = NULL; - -/********************************************************************** - Return the current HEAD of the list - *********************************************************************/ - - struct likewise_cell *cell_list_head(void) -{ - return _lw_cell_list; -} - - -/********************************************************************** - *********************************************************************/ - - void cell_destroy(struct likewise_cell *c) -{ - if (!c) - return; - - if (c->conn) - ads_destroy(&c->conn); - - talloc_destroy(c); -} - -/********************************************************************** - Free all cell entries and reset the list head to NULL - *********************************************************************/ - - void cell_list_destroy(void) -{ - struct likewise_cell *p = _lw_cell_list; - - while (p) { - struct likewise_cell *q = p->next; - - cell_destroy(p); - - p = q; - } - - _lw_cell_list = NULL; - - return; -} - -/********************************************************************** - Add a new cell structure to the list - *********************************************************************/ - - struct likewise_cell* cell_new(void) -{ - struct likewise_cell *c; - - /* Each cell struct is a TALLOC_CTX* */ - - c = TALLOC_ZERO_P(NULL, struct likewise_cell); - if (!c) { - DEBUG(0,("cell_new: memory allocation failure!\n")); - return NULL; - } - - return c; -} - -/********************************************************************** - Add a new cell structure to the list - *********************************************************************/ - - bool cell_list_add(struct likewise_cell * cell) -{ - if (!cell) { - return false; - } - - /* Always add to the end */ - - DLIST_ADD_END(_lw_cell_list, cell, struct likewise_cell *); - - return true; -} - -/********************************************************************** - Add a new cell structure to the list - *********************************************************************/ - - bool cell_list_remove(struct likewise_cell * cell) -{ - if (!cell) { - return false; - } - - /* Remove and drop the cell structure */ - - DLIST_REMOVE(_lw_cell_list, cell); - talloc_destroy(cell); - - return true; -} - -/********************************************************************** - Set the containing DNS domain for a cell - *********************************************************************/ - - void cell_set_dns_domain(struct likewise_cell *c, const char *dns_domain) -{ - c->dns_domain = talloc_strdup(c, dns_domain); -} - -/********************************************************************** - Set ADS connection for a cell - *********************************************************************/ - - void cell_set_connection(struct likewise_cell *c, ADS_STRUCT *ads) -{ - c->conn = ads; -} - -/********************************************************************** - *********************************************************************/ - - void cell_set_flags(struct likewise_cell *c, uint32_t flags) -{ - c->flags |= flags; -} - -/********************************************************************** - *********************************************************************/ - - void cell_clear_flags(struct likewise_cell *c, uint32_t flags) -{ - c->flags &= ~flags; -} - -/********************************************************************** - Set the Cell's DN - *********************************************************************/ - - void cell_set_dn(struct likewise_cell *c, const char *dn) -{ - if ( c->dn) { - talloc_free(c->dn); - c->dn = NULL; - } - - c->dn = talloc_strdup(c, dn); -} - -/********************************************************************** - *********************************************************************/ - - void cell_set_domain_sid(struct likewise_cell *c, DOM_SID *sid) -{ - sid_copy(&c->domain_sid, sid); -} - -/* - * Query Routines - */ - -/********************************************************************** - *********************************************************************/ - - const char* cell_search_base(struct likewise_cell *c) -{ - if (!c) - return NULL; - - return talloc_asprintf(c, "cn=%s,%s", ADEX_CELL_RDN, c->dn); -} - -/********************************************************************** - *********************************************************************/ - - bool cell_search_forest(struct likewise_cell *c) -{ - uint32_t test_flags = LWCELL_FLAG_SEARCH_FOREST; - - return ((c->flags & test_flags) == test_flags); -} - -/********************************************************************** - *********************************************************************/ - - uint32_t cell_flags(struct likewise_cell *c) -{ - if (!c) - return 0; - - return c->flags; -} - -/********************************************************************** - *********************************************************************/ - - const char *cell_dns_domain(struct likewise_cell *c) -{ - if (!c) - return NULL; - - return c->dns_domain; -} - -/********************************************************************** - *********************************************************************/ - - ADS_STRUCT *cell_connection(struct likewise_cell *c) -{ - if (!c) - return NULL; - - return c->conn; -} - -/* - * Connection functions - */ - -/******************************************************************** - *******************************************************************/ - - NTSTATUS cell_connect(struct likewise_cell *c) -{ - ADS_STRUCT *ads = NULL; - ADS_STATUS ads_status; - fstring dc_name; - struct sockaddr_storage dcip; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - /* have to at least have the AD domain name */ - - if (!c->dns_domain) { - nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* clear out any old information */ - - if (c->conn) { - ads_destroy(&c->conn); - c->conn = NULL; - } - - /* now setup the new connection */ - - ads = ads_init(c->dns_domain, NULL, NULL); - BAIL_ON_PTR_ERROR(ads, nt_status); - - ads->auth.password = - secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - ads->auth.realm = SMB_STRDUP(lp_realm()); - - /* Make the connection. We should already have an initial - TGT using the machine creds */ - - if (cell_flags(c) & LWCELL_FLAG_GC_CELL) { - ads_status = ads_connect_gc(ads); - } else { - /* Set up server affinity for normal cells and the client - site name cache */ - - if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) { - nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - ads_status = ads_connect(ads); - } - - - c->conn = ads; - - nt_status = ads_ntstatus(ads_status); - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - ads_destroy(&ads); - c->conn = NULL; - } - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - - NTSTATUS cell_connect_dn(struct likewise_cell **c, const char *dn) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct likewise_cell *new_cell = NULL; - char *dns_domain = NULL; - - if (*c || !dn) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if ((new_cell = cell_new()) == NULL) { - nt_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Set the DNS domain, dn, etc ... and add it to the list */ - - dns_domain = cell_dn_to_dns(dn); - cell_set_dns_domain(new_cell, dns_domain); - SAFE_FREE(dns_domain); - - cell_set_dn(new_cell, dn); - - nt_status = cell_connect(new_cell); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - *c = new_cell; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(1,("LWI: Failled to connect to cell \"%s\" (%s)\n", - dn ? dn : "NULL", nt_errstr(nt_status))); - talloc_destroy(new_cell); - } - - return nt_status; -} - - -/******************************************************************** - *******************************************************************/ - -#define MAX_SEARCH_COUNT 2 - - ADS_STATUS cell_do_search(struct likewise_cell *c, - const char *search_base, - int scope, - const char *expr, - const char **attrs, - LDAPMessage ** msg) -{ - int search_count = 0; - ADS_STATUS status; - NTSTATUS nt_status; - - /* check for a NULL connection */ - - if (!c->conn) { - nt_status = cell_connect(c); - if (!NT_STATUS_IS_OK(nt_status)) { - status = ADS_ERROR_NT(nt_status); - return status; - } - } - - DEBUG(10, ("cell_do_search: Base = %s, Filter = %s, Scope = %d, GC = %s\n", - search_base, expr, scope, - c->conn->server.gc ? "yes" : "no")); - - /* we try multiple times in case the ADS_STRUCT is bad - and we need to reconnect */ - - while (search_count < MAX_SEARCH_COUNT) { - *msg = NULL; - status = ads_do_search(c->conn, search_base, - scope, expr, attrs, msg); - if (ADS_ERR_OK(status)) { - return status; - } - - - DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n", - search_count, ads_errstr(status))); - - search_count++; - - /* Houston, we have a problem */ - - if (status.error_type == ENUM_ADS_ERROR_LDAP) { - switch (status.err.rc) { - case LDAP_TIMELIMIT_EXCEEDED: - case LDAP_TIMEOUT: - case -1: /* we get this error if we cannot contact - the LDAP server */ - nt_status = cell_connect(c); - if (!NT_STATUS_IS_OK(nt_status)) { - status = ADS_ERROR_NT(nt_status); - return status; - } - break; - default: - /* we're all done here */ - return status; - } - } - } - - DEBUG(5, ("cell_do_search: exceeded maximum search count!\n")); - - return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); -} diff --git a/source/winbindd/idmap_adex/provider_unified.c b/source/winbindd/idmap_adex/provider_unified.c deleted file mode 100644 index f18534797e..0000000000 --- a/source/winbindd/idmap_adex/provider_unified.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * idmap_adex - * - * Provider for RFC2307 and SFU AD Forests - * - * Copyright (C) Gerald (Jerry) Carter 2006-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 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 "idmap_adex.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -/* Information needed by the LDAP search filters */ - -enum filterType { SidFilter, IdFilter, AliasFilter }; - -struct lwcell_filter -{ - enum filterType ftype; - bool use2307; - union { - DOM_SID sid; - struct { - uint32_t id; - enum id_type type; - } id; - fstring alias; - } filter; -}; - -/******************************************************************** - *******************************************************************/ - -static char* build_id_filter(uint32_t id, - enum id_type type, - uint32_t search_flags) -{ - char *filter = NULL; - char *oc_filter, *attr_filter; - NTSTATUS nt_status; - TALLOC_CTX *frame = talloc_stackframe(); - bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS) - == LWCELL_FLAG_USE_RFC2307_ATTRS); - bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST) - == LWCELL_FLAG_SEARCH_FOREST); - const char *oc; - - /* Construct search filter for objectclass and attributes */ - - switch (type) { - case ID_TYPE_UID: - oc = ADEX_OC_USER; - if (use2307) { - oc = ADEX_OC_POSIX_USER; - if (use_gc) { - oc = AD_USER; - } - } - oc_filter = talloc_asprintf(frame, "objectclass=%s", oc); - attr_filter = talloc_asprintf(frame, "%s=%u", - ADEX_ATTR_UIDNUM, id); - break; - - case ID_TYPE_GID: - oc = ADEX_OC_GROUP; - if (use2307) { - oc = ADEX_OC_POSIX_GROUP; - if (use_gc) { - oc = AD_GROUP; - } - } - oc_filter = talloc_asprintf(frame, "objectclass=%s", oc); - attr_filter = talloc_asprintf(frame, "%s=%u", - ADEX_ATTR_GIDNUM, id); - break; - default: - return NULL; - } - - BAIL_ON_PTR_ERROR(oc_filter, nt_status); - BAIL_ON_PTR_ERROR(attr_filter, nt_status); - - /* Use "keywords=%s" for non-schema cells */ - - if (use2307) { - filter = talloc_asprintf(frame, "(&(%s)(%s))", - oc_filter, attr_filter); - } else { - filter = talloc_asprintf(frame, "(&(keywords=%s)(keywords=%s))", - oc_filter, attr_filter); - } - - talloc_destroy(oc_filter); - talloc_destroy(attr_filter); - -done: - /* Don't destroy the stackframe CTX since we are returning - memory from it */ - - return filter; -} - -/******************************************************************** - *******************************************************************/ - -static char* build_alias_filter(const char *alias, uint32_t search_flags) -{ - char *filter = NULL; - char *user_attr_filter, *group_attr_filter; - NTSTATUS nt_status; - TALLOC_CTX *frame = talloc_stackframe(); - bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS) - == LWCELL_FLAG_USE_RFC2307_ATTRS); - bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST) - == LWCELL_FLAG_SEARCH_FOREST); - - /* Construct search filter for objectclass and attributes */ - - user_attr_filter = talloc_asprintf(frame, "%s=%s", - ADEX_ATTR_UID, alias); - group_attr_filter = talloc_asprintf(frame, "%s=%s", - ADEX_ATTR_DISPLAYNAME, alias); - BAIL_ON_PTR_ERROR(user_attr_filter, nt_status); - BAIL_ON_PTR_ERROR(group_attr_filter, nt_status); - - /* Use "keywords=%s" for non-schema cells */ - - if (use2307) { - filter = talloc_asprintf(frame, - "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))", - user_attr_filter, - search_forest ? AD_USER : ADEX_OC_POSIX_USER, - group_attr_filter, - search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP); - } else { - filter = talloc_asprintf(frame, - "(|(keywords=%s)(keywords=%s))", - user_attr_filter, - group_attr_filter); - } - - talloc_destroy(user_attr_filter); - talloc_destroy(group_attr_filter); - -done: - /* Don't destroy the stackframe CTX since we are returning - memory from it */ - - return filter; -} - - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS search_cell(struct likewise_cell *c, - LDAPMessage **msg, - const struct lwcell_filter *fdata) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX* frame = talloc_stackframe(); - char *filter = NULL; - const char *base = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - const char *attrs[] = { "*", NULL }; - int count; - char *sid_str; - - /* get the filter and other search parameters */ - - switch (fdata->ftype) { - case SidFilter: - sid_str = sid_string_talloc(frame, &fdata->filter.sid); - BAIL_ON_PTR_ERROR(sid_str, nt_status); - - filter = talloc_asprintf(frame, "(keywords=backLink=%s)", - sid_str); - break; - case IdFilter: - filter = build_id_filter(fdata->filter.id.id, - fdata->filter.id.type, - cell_flags(c)); - break; - case AliasFilter: - filter = build_alias_filter(fdata->filter.alias, - cell_flags(c)); - break; - default: - nt_status = NT_STATUS_INVALID_PARAMETER; - break; - } - BAIL_ON_PTR_ERROR(filter, nt_status); - - base = cell_search_base(c); - BAIL_ON_PTR_ERROR(base, nt_status); - - ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE, - filter, attrs, msg); - - nt_status = ads_ntstatus(ads_status); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Now check that we got only one reply */ - - count = ads_count_replies(c->conn, *msg); - if (count < 1) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if ( count > 1) { - nt_status = NT_STATUS_DUPLICATE_NAME; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - -done: - PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4); - - talloc_destroy(CONST_DISCARD(char*, base)); - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS search_domain(struct likewise_cell **cell, - LDAPMessage **msg, - const char *dn, - const DOM_SID *sid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX* frame = talloc_stackframe(); - int count; - - nt_status = dc_search_domains(cell, msg, dn, sid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Now check that we got only one reply */ - - count = ads_count_replies(cell_connection(*cell), *msg); - if (count < 1) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if ( count > 1) { - nt_status = NT_STATUS_DUPLICATE_NAME; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - -done: - PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4); - talloc_destroy(frame); - - return nt_status; -} - - -/******************************************************************** - Check that a DN is within the forest scope. - *******************************************************************/ - -static bool check_forest_scope(const char *dn) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *frame = talloc_stackframe(); - char *p = NULL; - char *q = NULL; - char *dns_domain = NULL; - struct winbindd_tdc_domain *domain; - - /* If the DN does *not* contain "$LikewiseIdentityCell", - assume this is a schema mode forest and it is in the - forest scope by definition. */ - - if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) { - nt_status = NT_STATUS_OK; - goto done; - } - - /* If this is a non-schema forest, then make sure that the DN - is in the form "...,cn=$LikewiseIdentityCell,DC=..." */ - - if ((q = strchr_m(p, ',')) == NULL) { - nt_status = NT_STATUS_OBJECT_NAME_INVALID; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - q++; - if (StrnCaseCmp(q, "dc=", 3) != 0) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - - dns_domain = cell_dn_to_dns(q); - BAIL_ON_PTR_ERROR(dns_domain, nt_status); - - domain = wcache_tdc_fetch_domain(frame, dns_domain); - if (!domain) { - nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(frame); - SAFE_FREE(dns_domain); - - return NT_STATUS_IS_OK(nt_status); -} - - - -/******************************************************************** - Check that only one result was returned within the forest cell - scope. - *******************************************************************/ - -static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list, - LDAPMessage **msg_list, - int num_resp, - char **dn, - DOM_SID *user_sid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - int i; - ADS_STRUCT *ads = NULL; - LDAPMessage *msg = NULL; - int count = 0; - char *entry_dn = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!dn || !user_sid) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - *dn = NULL; - - if (!ads_list || !msg_list || (num_resp == 0)) { - nt_status = NT_STATUS_NO_SUCH_FILE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Loop over all msgs */ - - for (i=0; i<num_resp; i++) { - LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]); - - while (e) { - entry_dn = ads_get_dn(ads_list[i], e); - BAIL_ON_PTR_ERROR(entry_dn, nt_status); - - if (check_forest_scope(entry_dn)) { - count++; - - /* If we've already broken the condition, no - need to continue */ - - if (count > 1) { - nt_status = NT_STATUS_DUPLICATE_NAME; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - ads = ads_list[i]; - msg = e; - *dn = SMB_STRDUP(entry_dn); - BAIL_ON_PTR_ERROR((*dn), nt_status); - } - - e = ads_next_entry(ads_list[i], e); - SAFE_FREE(entry_dn); - } - } - - if (!ads || !msg) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* If we made is through the loop, then grab the user_sid and - run home to base */ - - /* - Try and get the SID from either objectSid or keywords. - We cannot use pull_sid() here since we want to try - both methods and not only one or the other (and we - have no full likewise_cell struct. - - Fail if both are unavailable - */ - - if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) { - char **keywords; - char *s; - size_t num_lines = 0; - - keywords = ads_pull_strings(ads, frame, msg, "keywords", - &num_lines); - BAIL_ON_PTR_ERROR(keywords, nt_status); - - s = find_attr_string(keywords, num_lines, "backLink"); - if (!s) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if (!string_to_sid(user_sid, s)) { - nt_status = NT_STATUS_INVALID_SID; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - } - - nt_status = NT_STATUS_OK; - -done: - if (!NT_STATUS_IS_OK(nt_status)) { - SAFE_FREE(*dn); - } - - talloc_destroy(frame); - SAFE_FREE(entry_dn); - - return nt_status; -} - -/******************************************************************** - Search all forests. Each forest can have it's own forest-cell - settings so we have to generate the filter for each search. - We don't use gc_search_all_forests() since we may have a different - schema model in each forest and need to construct the search - filter for each GC search. - *******************************************************************/ - -static NTSTATUS search_forest(struct likewise_cell *forest_cell, - LDAPMessage **msg, - const struct lwcell_filter *fdata) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *frame = talloc_stackframe(); - char *filter = NULL; - char *dn = NULL; - struct gc_info *gc = NULL; - ADS_STRUCT **ads_list = NULL; - LDAPMessage **msg_list = NULL; - int num_resp = 0; - LDAPMessage *m; - DOM_SID user_sid; - struct likewise_cell *domain_cell = NULL; - - if ((gc = gc_search_start()) == NULL) { - nt_status = NT_STATUS_INVALID_DOMAIN_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - while (gc) { - char *sid_binstr = NULL; - uint32_t flags = LWCELL_FLAG_SEARCH_FOREST; - - m = NULL; - - flags |= cell_flags(gc->forest_cell); - - switch (fdata->ftype) { - case SidFilter: - sid_binstr = sid_binstring(&fdata->filter.sid); - BAIL_ON_PTR_ERROR(sid_binstr, nt_status); - - filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr); - SAFE_FREE(sid_binstr); - break; - case IdFilter: - filter = build_id_filter(fdata->filter.id.id, - fdata->filter.id.type, flags); - break; - case AliasFilter: - filter = build_alias_filter(fdata->filter.alias, flags); - break; - } - - /* First find the sparse object in GC */ - nt_status = gc_search_forest(gc, &m, filter); - if (!NT_STATUS_IS_OK(nt_status)) { - gc = gc->next; - continue; - } - - nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell), - m, &ads_list, &msg_list, - &num_resp); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - gc = gc->next; - } - - /* Uniqueness check across forests */ - - nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp, - &dn, &user_sid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = search_domain(&domain_cell, &m, dn, &user_sid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Save the connection and results in the return parameters */ - - forest_cell->gc_search_cell = domain_cell; - *msg = m; - -done: - PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4); - - SAFE_FREE(dn); - - free_result_array(ads_list, msg_list, num_resp); - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS search_cell_list(struct likewise_cell **c, - LDAPMessage **m, - const struct lwcell_filter *fdata) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct likewise_cell *cell = NULL; - LDAPMessage *msg = NULL; - struct likewise_cell *result_cell = NULL; - - if ((cell = cell_list_head()) == NULL) { - nt_status = NT_STATUS_INVALID_SERVER_STATE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - while (cell) { - /* Clear any previous GC search results */ - - cell->gc_search_cell = NULL; - - if (cell_search_forest(cell)) { - nt_status = search_forest(cell, &msg, fdata); - } else { - nt_status = search_cell(cell, &msg, fdata); - } - - /* Always point to the search result cell. - In forests this might be for another domain - which means the schema model may be different */ - - result_cell = cell->gc_search_cell ? - cell->gc_search_cell : cell; - - /* Check if we are done */ - - if (NT_STATUS_IS_OK(nt_status)) { - break; - } - - /* No luck. Free memory and hit the next cell. - Forest searches always set the gc_search_cell - so give preference to that connection if possible. */ - - ads_msgfree(cell_connection(result_cell), msg); - msg = NULL; - - cell = cell->next; - } - - /* This might be assigning NULL but that is ok as long as we - give back the proper error code */ - - *c = result_cell; - *m = msg; - -done: - PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3); - - return nt_status; -} - -/******************************************************************** - Pull the SID from an object which is always stored in the keywords - attribute as "backLink=S-1-5-21-..." - *******************************************************************/ - -static NTSTATUS pull_sid(struct likewise_cell *c, - LDAPMessage *msg, - DOM_SID *sid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *frame = talloc_stackframe(); - ADS_STRUCT *ads = NULL; - - ads = cell_connection(c); - - /* - We have two ways of getting the sid: - (a) from the objectSID in case of a GC search, - (b) from backLink in the case of a cell search. - Pull the keywords attributes and grab the backLink. - */ - - if (!ads_pull_sid(ads, msg, "objectSid", sid)) { - char **keywords; - char *s; - size_t num_lines = 0; - - keywords = ads_pull_strings(ads, frame, msg, - "keywords", &num_lines); - BAIL_ON_PTR_ERROR(keywords, nt_status); - - s = find_attr_string(keywords, num_lines, "backLink"); - if (!s) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - if (!string_to_sid(sid, s)) { - nt_status = NT_STATUS_INVALID_SID; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS get_object_type(struct likewise_cell *c, - LDAPMessage *msg, - enum id_type *type) -{ - TALLOC_CTX *ctx = talloc_stackframe(); - char **oc_list = NULL; - NTSTATUS nt_status = NT_STATUS_OK; - size_t list_size = 0; - char *s = NULL; - ADS_STRUCT *ads = NULL; - - ads = cell_connection(c); - - /* Deal with RFC 2307 support first */ - - if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { - oc_list = ads_pull_strings(ads, ctx, msg, - "objectClass", &list_size); - if (!oc_list) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto done; - } - - /* Check for posix classes and AD classes */ - - if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER) - || is_object_class(oc_list, list_size, AD_USER)) { - *type = ID_TYPE_UID; - } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP) - || is_object_class(oc_list, list_size, AD_GROUP)) { - *type = ID_TYPE_GID; - } else { - *type = ID_TYPE_NOT_SPECIFIED; - nt_status = NT_STATUS_INVALID_PARAMETER; - } - } else { - /* Default to non-schema mode */ - - oc_list = ads_pull_strings(ads, ctx, msg, - "keywords", &list_size); - if (!oc_list) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto done; - } - - s = find_attr_string(oc_list, list_size, "objectClass"); - if (!s) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto done; - } - - if (strequal(s, ADEX_OC_USER)) { - *type = ID_TYPE_UID; - } else if (strequal(s, ADEX_OC_GROUP)) { - *type = ID_TYPE_GID; - } else { - *type = ID_TYPE_NOT_SPECIFIED; - nt_status = NT_STATUS_INVALID_PARAMETER; - } - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(ctx); - - return nt_status; -} - -/******************************************************************** - Pull an attribute uint32_t value - *******************************************************************/ - -static NTSTATUS get_object_uint32(struct likewise_cell *c, - LDAPMessage *msg, - const char *attrib, - uint32_t *x) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char **keywords = NULL; - size_t list_size = 0; - TALLOC_CTX *frame = talloc_stackframe(); - ADS_STRUCT *ads = NULL; - - ads = cell_connection(c); - - /* Deal with RFC2307 schema */ - - if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { - if (!ads_pull_uint32(ads, msg, attrib, x)) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - } else { - /* Non-schema mode */ - char *s = NULL; - uint32_t num; - - keywords = ads_pull_strings(ads, frame, msg, "keywords", - &list_size); - BAIL_ON_PTR_ERROR(keywords, nt_status); - - s = find_attr_string(keywords, list_size, attrib); - if (!s) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - num = strtoll(s, NULL, 10); - if (errno == ERANGE) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - *x = num; - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS get_object_id(struct likewise_cell *c, - LDAPMessage *msg, - enum id_type type, - uint32_t *id) -{ - NTSTATUS nt_status = NT_STATUS_OK; - const char *id_attr; - - /* Figure out which attribute we need to pull */ - - switch (type) { - case ID_TYPE_UID: - id_attr = ADEX_ATTR_UIDNUM; - break; - case ID_TYPE_GID: - id_attr = ADEX_ATTR_GIDNUM; - break; - default: - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - break; - } - - nt_status = get_object_uint32(c, msg, id_attr, id); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - return nt_status; -} - -/******************************************************************** - Pull the uid/gid and type from an object. This differs depending on - the cell flags. - *******************************************************************/ - -static NTSTATUS pull_id(struct likewise_cell *c, - LDAPMessage *msg, - uint32_t *id, - enum id_type *type) -{ - NTSTATUS nt_status; - - nt_status = get_object_type(c, msg, type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_object_id(c, msg, *type, id); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - return nt_status; -} - -/******************************************************************** - Pull an attribute string value - *******************************************************************/ - -static NTSTATUS get_object_string(struct likewise_cell *c, - LDAPMessage *msg, - TALLOC_CTX *ctx, - const char *attrib, - char **string) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char **keywords = NULL; - size_t list_size = 0; - TALLOC_CTX *frame = talloc_stackframe(); - ADS_STRUCT *ads = NULL; - - *string = NULL; - - ads = cell_connection(c); - - /* Deal with RFC2307 schema */ - - if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { - *string = ads_pull_string(ads, ctx, msg, attrib); - } else { - /* Non-schema mode */ - - char *s = NULL; - - keywords = ads_pull_strings(ads, frame, msg, - "keywords", &list_size); - if (!keywords) { - nt_status = NT_STATUS_NO_MEMORY; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - s = find_attr_string(keywords, list_size, attrib); - if (s) { - *string = talloc_strdup(ctx, s); - } - } - - if (!*string) { - nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = NT_STATUS_OK; - -done: - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - Pull the struct passwd fields for a user - *******************************************************************/ - -static NTSTATUS pull_nss_info(struct likewise_cell *c, - LDAPMessage *msg, - TALLOC_CTX *ctx, - char **homedir, - char **shell, - char **gecos, - gid_t *p_gid) -{ - NTSTATUS nt_status; - - nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos); - /* Gecos is often not set so ignore failures */ - - nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - return nt_status; -} - -/******************************************************************** - Pull the struct passwd fields for a user - *******************************************************************/ - -static NTSTATUS pull_alias(struct likewise_cell *c, - LDAPMessage *msg, - TALLOC_CTX *ctx, - char **alias) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - enum id_type type; - const char *attr = NULL; - - /* Figure out if this is a user or a group */ - - nt_status = get_object_type(c, msg, &type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - switch (type) { - case ID_TYPE_UID: - attr = ADEX_ATTR_UID; - break; - case ID_TYPE_GID: - /* What is the group attr for RFC2307 Forests? */ - attr = ADEX_ATTR_DISPLAYNAME; - break; - default: - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - break; - } - - nt_status = get_object_string(c, msg, ctx, attr, alias); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid, - uint32_t id, enum id_type type) -{ - struct likewise_cell *cell = NULL; - LDAPMessage *msg = NULL; - NTSTATUS nt_status; - struct lwcell_filter filter; - - filter.ftype = IdFilter; - filter.filter.id.id = id; - filter.filter.id.type = type; - - nt_status = search_cell_list(&cell, &msg, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = pull_sid(cell, msg, sid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - ads_msgfree(cell->conn, msg); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS _ccp_get_id_from_sid(uint32_t * id, - enum id_type *type, - const DOM_SID * sid) -{ - struct likewise_cell *cell = NULL; - LDAPMessage *msg = NULL; - NTSTATUS nt_status; - struct lwcell_filter filter; - - filter.ftype = SidFilter; - sid_copy(&filter.filter.sid, sid); - - nt_status = search_cell_list(&cell, &msg, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = pull_id(cell, msg, id, type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (*id < min_id_value()) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - -done: - ads_msgfree(cell->conn, msg); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid, - TALLOC_CTX * ctx, - char **homedir, - char **shell, - char **gecos, gid_t * p_gid) -{ - struct likewise_cell *cell = NULL; - LDAPMessage *msg = NULL; - NTSTATUS nt_status; - struct lwcell_filter filter; - enum id_type type; - - filter.ftype = SidFilter; - sid_copy(&filter.filter.sid, sid); - - nt_status = search_cell_list(&cell, &msg, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = get_object_type(cell, msg, &type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (type != ID_TYPE_UID) { - nt_status = NT_STATUS_NO_SUCH_USER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos, - (uint32_t*) p_gid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - ads_msgfree(cell->conn, msg); - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx, - const char *domain, - const char *name, char **alias) -{ - TALLOC_CTX *frame = talloc_stackframe(); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - DOM_SID sid; - struct likewise_cell *cell = NULL; - LDAPMessage *msg = NULL; - struct lwcell_filter filter; - enum lsa_SidType sid_type; - - /* Convert the name to a SID */ - - nt_status = gc_name_to_sid(domain, name, &sid, &sid_type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Find the user/group */ - - filter.ftype = SidFilter; - sid_copy(&filter.filter.sid, &sid); - - nt_status = search_cell_list(&cell, &msg, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Pull the alias and return */ - - nt_status = pull_alias(cell, msg, ctx, alias); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3); - - talloc_destroy(frame); - ads_msgfree(cell_connection(cell), msg); - - return nt_status; -} - -/********************************************************************** - Map from an alias name to the canonical, qualified name. - Ensure that the alias is only pull from the closest in which - the user or gorup is enabled in - *********************************************************************/ - -static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx, - const char *domain, - const char *alias, char **name) -{ - TALLOC_CTX *frame = talloc_stackframe(); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - DOM_SID sid; - struct likewise_cell *cell_alias = NULL; - LDAPMessage *msg_alias = NULL; - struct likewise_cell *cell_sid = NULL; - LDAPMessage *msg_sid = NULL; - struct lwcell_filter filter; - char *canonical_name = NULL; - enum lsa_SidType type; - - /* Find the user/group */ - - filter.ftype = AliasFilter; - fstrcpy(filter.filter.alias, alias); - - nt_status = search_cell_list(&cell_alias, &msg_alias, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - nt_status = pull_sid(cell_alias, msg_alias, &sid); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - /* Now search again for the SID according to the cell list. - Verify that the cell of both search results is the same - so that we only match an alias from the closest cell - in which a user/group has been instantied. */ - - filter.ftype = SidFilter; - sid_copy(&filter.filter.sid, &sid); - - nt_status = search_cell_list(&cell_sid, &msg_sid, &filter); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (cell_alias != cell_sid) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Finally do the GC sid/name conversion */ - - nt_status = gc_sid_to_name(&sid, &canonical_name, &type); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - *name = talloc_strdup(mem_ctx, canonical_name); - BAIL_ON_PTR_ERROR((*name), nt_status); - - nt_status = NT_STATUS_OK; - -done: - PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3); - - ads_msgfree(cell_connection(cell_alias), msg_alias); - ads_msgfree(cell_connection(cell_sid), msg_sid); - - SAFE_FREE(canonical_name); - - talloc_destroy(frame); - - return nt_status; -} - -/******************************************************************** - *******************************************************************/ - -struct cell_provider_api ccp_unified = { - .get_sid_from_id = _ccp_get_sid_from_id, - .get_id_from_sid = _ccp_get_id_from_sid, - .get_nss_info = _ccp_nss_get_info, - .map_to_alias = _ccp_map_to_alias, - .map_from_alias = _ccp_map_from_alias -}; diff --git a/source/winbindd/idmap_cache.c b/source/winbindd/idmap_cache.c new file mode 100644 index 0000000000..cf46196ebe --- /dev/null +++ b/source/winbindd/idmap_cache.c @@ -0,0 +1,534 @@ +/* + 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 <http://www.gnu.org/licenses/>.*/ + +#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) +{ + 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; +} + +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/source/winbindd/idmap_hash/idmap_hash.c b/source/winbindd/idmap_hash/idmap_hash.c deleted file mode 100644 index a050f99bc8..0000000000 --- a/source/winbindd/idmap_hash/idmap_hash.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * idmap_hash.c - * - * Copyright (C) Gerald Carter <jerry@samba.org> 2007 - 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 <http://www.gnu.org/licenses/>. - * - */ - -#include "includes.h" -#include "winbindd/winbindd.h" -#include "idmap_hash.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_IDMAP - -struct sid_hash_table { - DOM_SID *sid; -}; - -struct sid_hash_table *hashed_domains = NULL; - -/********************************************************************* - Hash a domain SID (S-1-5-12-aaa-bbb-ccc) to a 12bit number - ********************************************************************/ - -static uint32_t hash_domain_sid(const DOM_SID *sid) -{ - uint32_t hash; - - if (sid->num_auths != 4) - return 0; - - /* XOR the last three subauths */ - - hash = ((sid->sub_auths[1] ^ sid->sub_auths[2]) ^ sid->sub_auths[3]); - - /* Take all 32-bits into account when generating the 12-bit - hash value */ - hash = (((hash & 0xFFF00000) >> 20) - + ((hash & 0x000FFF00) >> 8) - + (hash & 0x000000FF)) & 0x0000FFF; - - /* return a 12-bit hash value */ - - return hash; -} - -/********************************************************************* - Hash a Relative ID to a 20 bit number - ********************************************************************/ - -static uint32_t hash_rid(uint32_t rid) -{ - /* 20 bits for the rid which allows us to support - the first 100K users/groups in a domain */ - - return (rid & 0x0007FFFF); -} - -/********************************************************************* - ********************************************************************/ - -static uint32_t combine_hashes(uint32_t h_domain, - uint32_t h_rid) -{ - uint32_t return_id = 0; - - /* shift the hash_domain 19 bits to the left and OR with the - hash_rid */ - - return_id = ((h_domain<<19) | h_rid); - - return return_id; -} - -/********************************************************************* - ********************************************************************/ - -static void separate_hashes(uint32_t id, - uint32_t *h_domain, - uint32_t *h_rid) -{ - *h_rid = id & 0x0007FFFF; - *h_domain = (id & 0x7FF80000) >> 19; - - return; -} - - -/********************************************************************* - ********************************************************************/ - -static NTSTATUS be_init(struct idmap_domain *dom, - const char *params) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct winbindd_tdc_domain *dom_list = NULL; - size_t num_domains = 0; - int i; - - /* If the domain SID hash talbe has been initialized, assume - that we completed this function previously */ - - if ( hashed_domains ) { - nt_status = NT_STATUS_OK; - goto done; - } - - if (!wcache_tdc_fetch_list(&dom_list, &num_domains)) { - nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* Create the hash table of domain SIDs */ - - hashed_domains = TALLOC_ZERO_ARRAY(NULL, struct sid_hash_table, 4096); - BAIL_ON_PTR_NT_ERROR(hashed_domains, nt_status); - - /* create the hash table of domain SIDs */ - - for (i=0; i<num_domains; i++) { - uint32_t hash; - - if (is_null_sid(&dom_list[i].sid)) - continue; - if ((hash = hash_domain_sid(&dom_list[i].sid)) == 0) - continue; - - DEBUG(5,("hash:be_init() Adding %s (%s) -> %d\n", - dom_list[i].domain_name, - sid_string_dbg(&dom_list[i].sid), - hash)); - - hashed_domains[hash].sid = talloc(hashed_domains, DOM_SID); - sid_copy(hashed_domains[hash].sid, &dom_list[i].sid); - } - -done: - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - -static NTSTATUS unixids_to_sids(struct idmap_domain *dom, - struct id_map **ids) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - int i; - - nt_status = be_init(dom, NULL); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - for (i=0; ids[i]; i++) { - uint32_t h_domain, h_rid; - - ids[i]->status = ID_UNMAPPED; - - separate_hashes(ids[i]->xid.id, &h_domain, &h_rid); - - /* Make sure the caller allocated memor for us */ - - if (!ids[i]->sid) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - /* If the domain hash doesn't find a SID in the table, - skip it */ - - if (!hashed_domains[h_domain].sid) - continue; - - sid_copy(ids[i]->sid, hashed_domains[h_domain].sid); - sid_append_rid(ids[i]->sid, h_rid); - ids[i]->status = ID_MAPPED; - } - -done: - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - -static NTSTATUS sids_to_unixids(struct idmap_domain *dom, - struct id_map **ids) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - int i; - - nt_status = be_init(dom, NULL); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - for (i=0; ids[i]; i++) { - DOM_SID sid; - uint32_t rid; - uint32_t h_domain, h_rid; - - ids[i]->status = ID_UNMAPPED; - - sid_copy(&sid, ids[i]->sid); - sid_split_rid(&sid, &rid); - - h_domain = hash_domain_sid(&sid); - h_rid = hash_rid(rid); - - /* Check that both hashes are non-zero*/ - - if (h_domain && h_rid) { - ids[i]->xid.id = combine_hashes(h_domain, h_rid); - ids[i]->status = ID_MAPPED; - } - } - -done: - return nt_status; -} - -/********************************************************************* - ********************************************************************/ - -static NTSTATUS be_close(struct idmap_domain *dom) -{ - if (hashed_domains) - talloc_free(hashed_domains); - - return NT_STATUS_OK; -} - -/********************************************************************* - ********************************************************************/ - -static NTSTATUS nss_hash_init(struct nss_domain_entry *e ) -{ - return be_init(NULL, NULL); -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_hash_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 *p_gid ) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - nt_status = nss_hash_init(e); - BAIL_ON_NTSTATUS_ERROR(nt_status); - - if (!homedir || !shell || !gecos) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - - *homedir = talloc_strdup(ctx, lp_template_homedir()); - BAIL_ON_PTR_NT_ERROR(*homedir, nt_status); - - *shell = talloc_strdup(ctx, lp_template_shell()); - BAIL_ON_PTR_NT_ERROR(*shell, nt_status); - - *gecos = NULL; - - /* Initialize the gid so that the upper layer fills - in the proper Windows primary group */ - - if (*p_gid) { - *p_gid = (gid_t)-1; - } - -done: - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_hash_map_to_alias(TALLOC_CTX *mem_ctx, - const char *domain, - const char *name, - char **alias) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - const char *value; - - value = talloc_asprintf(mem_ctx, "%s\\%s", domain, name); - BAIL_ON_PTR_NT_ERROR(value, nt_status); - - nt_status = mapfile_lookup_key(mem_ctx, value, alias); - BAIL_ON_NTSTATUS_ERROR(nt_status); - -done: - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_hash_map_from_alias(TALLOC_CTX *mem_ctx, - const char *domain, - const char *alias, - char **name) -{ - return mapfile_lookup_value(mem_ctx, alias, name); -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_hash_close(void) -{ - return NT_STATUS_OK; -} - -/********************************************************************* - Dispatch Tables for IDMap and NssInfo Methods -********************************************************************/ - -static struct idmap_methods hash_idmap_methods = { - .init = be_init, - .unixids_to_sids = unixids_to_sids, - .sids_to_unixids = sids_to_unixids, - .close_fn = be_close -}; - -static struct nss_info_methods hash_nss_methods = { - .init = nss_hash_init, - .get_nss_info = nss_hash_get_info, - .map_to_alias = nss_hash_map_to_alias, - .map_from_alias = nss_hash_map_from_alias, - .close_fn = nss_hash_close -}; - -/********************************************************************** - Register with the idmap and idmap_nss subsystems. We have to protect - against the idmap and nss_info interfaces being in a half-registered - state. - **********************************************************************/ - -NTSTATUS idmap_hash_init(void) -{ - static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL; - static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL; - - if ( !NT_STATUS_IS_OK(idmap_status) ) { - idmap_status = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, - "hash", &hash_idmap_methods); - - if ( !NT_STATUS_IS_OK(idmap_status) ) { - DEBUG(0,("Failed to register hash idmap plugin.\n")); - return idmap_status; - } - } - - if ( !NT_STATUS_IS_OK(nss_status) ) { - nss_status = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, - "hash", &hash_nss_methods); - if ( !NT_STATUS_IS_OK(nss_status) ) { - DEBUG(0,("Failed to register hash idmap nss plugin.\n")); - return nss_status; - } - } - - return NT_STATUS_OK; -} diff --git a/source/winbindd/idmap_hash/idmap_hash.h b/source/winbindd/idmap_hash/idmap_hash.h deleted file mode 100644 index 621520e950..0000000000 --- a/source/winbindd/idmap_hash/idmap_hash.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * lwopen.h - * - * Copyright (C) Gerald Carter <jerry@samba.org> - * - * 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 <http://www.gnu.org/licenses/>. - * - */ - -#ifndef _LWOPEN_H -#define _LWOPEN_H - -#define BAIL_ON_NTSTATUS_ERROR(x) \ - do { \ - if (!NT_STATUS_IS_OK(x)) { \ - DEBUG(10,("Failed! (%s)\n", nt_errstr(x))); \ - goto done; \ - } \ - } \ - while (0); \ - -#define BAIL_ON_PTR_NT_ERROR(p, x) \ - do { \ - if ((p) == NULL ) { \ - DEBUG(10,("NULL pointer!\n")); \ - x = NT_STATUS_NO_MEMORY; \ - goto done; \ - } else { \ - x = NT_STATUS_OK; \ - } \ - } while (0); - -#define PRINT_NTSTATUS_ERROR(x, hdr, level) \ - do { \ - if (!NT_STATUS_IS_OK(x)) { \ - DEBUG(level,("Likewise Open ("hdr"): %s\n", nt_errstr(x))); \ - } \ - } while(0); - - -NTSTATUS mapfile_lookup_key(TALLOC_CTX *ctx, - const char *value, - char **key); - -NTSTATUS mapfile_lookup_value(TALLOC_CTX *ctx, - const char *key, - char **value); - -#endif /* _LWOPEN_H */ diff --git a/source/winbindd/idmap_hash/mapfile.c b/source/winbindd/idmap_hash/mapfile.c deleted file mode 100644 index 5ab1142ffe..0000000000 --- a/source/winbindd/idmap_hash/mapfile.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * mapfile.c - * - * Copyright (C) Gerald Carter <jerry@samba.org> - * - * 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 <http://www.gnu.org/licenses/>. - * - */ - -#include "includes.h" -#include "winbindd/winbindd.h" -#include "idmap_hash.h" -#include <stdio.h> - -XFILE *lw_map_file = NULL; - -/********************************************************************* - ********************************************************************/ - -static bool mapfile_open(void) -{ - const char *mapfile_name = NULL; - - /* If we have an open handle, just reset it */ - - if (lw_map_file) { - return (x_tseek(lw_map_file, 0, SEEK_SET) == 0); - } - - mapfile_name = lp_parm_const_string(-1, "idmap_hash", "name_map", NULL); - if (!mapfile_name) { - return false; - } - - lw_map_file = x_fopen(mapfile_name, O_RDONLY, 0); - if (!lw_map_file) { - DEBUG(0,("can't open idmap_hash:name_map (%s). Error %s\n", - mapfile_name, strerror(errno) )); - return false; - } - - return true; -} - -/********************************************************************* - ********************************************************************/ - -static bool mapfile_read_line(fstring key, fstring value) -{ - char buffer[1024]; - char *p; - int len; - - if (!lw_map_file) - return false; - - if ((p = x_fgets(buffer, sizeof(buffer)-1, lw_map_file)) == NULL) { - return false; - } - - /* Strip newlines and carriage returns */ - - len = strlen_m(buffer) - 1; - while ((buffer[len] == '\n') || (buffer[len] == '\r')) { - buffer[len--] = '\0'; - } - - - if ((p = strchr_m(buffer, '=')) == NULL ) { - DEBUG(0,("idmap_hash: Bad line in name_map (%s)\n", buffer)); - return false; - } - - *p = '\0'; - p++; - - fstrcpy(key, buffer); - fstrcpy(value, p); - - /* Eat whitespace */ - - if (!trim_char(key, ' ', ' ')) - return false; - - if (!trim_char(value, ' ', ' ')) - return false; - - return true; -} - -/********************************************************************* - ********************************************************************/ - -static bool mapfile_close(void) -{ - int ret = 0; - if (lw_map_file) { - ret = x_fclose(lw_map_file); - lw_map_file = NULL; - } - - return (ret == 0); -} - - -/********************************************************************* - ********************************************************************/ - -NTSTATUS mapfile_lookup_key(TALLOC_CTX *ctx, const char *value, char **key) -{ - fstring r_key, r_value; - NTSTATUS ret = NT_STATUS_NOT_FOUND; - - if (!mapfile_open()) - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - - while (mapfile_read_line(r_key, r_value)) - { - if (strequal(r_value, value)) { - ret = NT_STATUS_OK; - - /* We're done once finishing this block */ - *key = talloc_strdup(ctx, r_key); - if (!*key) { - ret = NT_STATUS_NO_MEMORY; - } - break; - } - } - - mapfile_close(); - - return ret; -} - -/********************************************************************* - ********************************************************************/ - -NTSTATUS mapfile_lookup_value(TALLOC_CTX *ctx, const char *key, char **value) -{ - fstring r_key, r_value; - NTSTATUS ret = NT_STATUS_NOT_FOUND; - - if (!mapfile_open()) - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - - while (mapfile_read_line(r_key, r_value)) - { - if (strequal(r_key, key)) { - ret = NT_STATUS_OK; - - /* We're done once finishing this block */ - *value = talloc_strdup(ctx, r_value); - if (!*key) { - ret = NT_STATUS_NO_MEMORY; - } - break; - } - } - - mapfile_close(); - - return ret; -} diff --git a/source/winbindd/idmap_ldap.c b/source/winbindd/idmap_ldap.c index c86a5023d0..fa80fae5d8 100644 --- a/source/winbindd/idmap_ldap.c +++ b/source/winbindd/idmap_ldap.c @@ -33,29 +33,6 @@ #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; @@ -246,6 +223,7 @@ 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; @@ -262,27 +240,50 @@ static NTSTATUS idmap_ldap_alloc_init(const char *params) /* load ranges */ - 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; + 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)); + } } - 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 (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 invalid\n")); + 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 invalid\n")); + 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; @@ -759,8 +760,7 @@ static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx) Initialise idmap database. ********************************/ -static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, - const char *params) +static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) { NTSTATUS ret; struct idmap_ldap_context *ctx = NULL; @@ -798,9 +798,9 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, } } - if (params != NULL) { + if (dom->params && *(dom->params)) { /* assume location is the only parameter */ - ctx->url = talloc_strdup(ctx, params); + ctx->url = talloc_strdup(ctx, dom->params); } else { tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL); @@ -848,6 +848,7 @@ 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; @@ -908,6 +909,14 @@ 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); @@ -1129,6 +1138,14 @@ 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); @@ -1333,6 +1350,14 @@ 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) { @@ -1457,13 +1482,12 @@ static struct idmap_alloc_methods idmap_ldap_alloc_methods = { /* .dump_data = TODO */ }; -static NTSTATUS idmap_alloc_ldap_init(void) +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; diff --git a/source/winbindd/idmap_nss.c b/source/winbindd/idmap_nss.c index 156fdc7cc9..e4acd9ce65 100644 --- a/source/winbindd/idmap_nss.c +++ b/source/winbindd/idmap_nss.c @@ -29,9 +29,9 @@ Initialise idmap database. *****************************/ -static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom, - const char *params) +static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom) { + dom->initialized = True; return NT_STATUS_OK; } @@ -44,6 +44,10 @@ 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")); @@ -130,6 +134,10 @@ 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/source/winbindd/idmap_passdb.c b/source/winbindd/idmap_passdb.c index 4dcf74416c..17afd71ab8 100644 --- a/source/winbindd/idmap_passdb.c +++ b/source/winbindd/idmap_passdb.c @@ -28,8 +28,9 @@ Initialise idmap database. *****************************/ -static NTSTATUS idmap_pdb_init(struct idmap_domain *dom, const char *params) +static NTSTATUS idmap_pdb_init(struct idmap_domain *dom) { + dom->initialized = True; return NT_STATUS_OK; } @@ -41,6 +42,10 @@ 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 */ @@ -73,6 +78,10 @@ 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/source/winbindd/idmap_rid.c b/source/winbindd/idmap_rid.c index 9d1898708c..f1cd77853c 100644 --- a/source/winbindd/idmap_rid.c +++ b/source/winbindd/idmap_rid.c @@ -36,8 +36,7 @@ struct idmap_rid_context { we support multiple domains in the new idmap *****************************************************************************/ -static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom, - const char *params) +static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom) { NTSTATUS ret; struct idmap_rid_context *ctx; @@ -96,6 +95,7 @@ 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,6 +171,14 @@ 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); @@ -205,6 +213,14 @@ 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/source/winbindd/idmap_tdb.c b/source/winbindd/idmap_tdb.c index 9e66eed0c8..e5f605361b 100644 --- a/source/winbindd/idmap_tdb.c +++ b/source/winbindd/idmap_tdb.c @@ -313,11 +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; /* use our own context here */ ctx = talloc_new(NULL); @@ -335,47 +335,67 @@ 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)); + } + } - 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; + /* 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; } - 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 (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; - } - - 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; + } 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; + } } } @@ -565,7 +585,7 @@ struct idmap_tdb_context { Initialise idmap database. *****************************/ -static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) +static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom) { NTSTATUS ret; struct idmap_tdb_context *ctx; @@ -599,6 +619,7 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) } dom->private_data = ctx; + dom->initialized = True; talloc_free(config_option); return NT_STATUS_OK; @@ -753,6 +774,14 @@ 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++) { @@ -791,6 +820,14 @@ 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++) { @@ -831,6 +868,14 @@ 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; } @@ -938,6 +983,14 @@ 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; } @@ -1118,6 +1171,14 @@ 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); @@ -1168,8 +1229,6 @@ 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/source/winbindd/idmap_tdb2.c b/source/winbindd/idmap_tdb2.c index 8bde963c60..ab89e615f7 100644 --- a/source/winbindd/idmap_tdb2.c +++ b/source/winbindd/idmap_tdb2.c @@ -3,8 +3,9 @@ idmap TDB2 backend, used for clustered Samba setups. - This uses dbwrap to access tdb files. The location can be set - using tdb:idmap2.tdb =" in smb.conf + 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 @@ -49,19 +50,46 @@ 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; +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_db(void) +static NTSTATUS idmap_tdb2_open_perm_db(void) { char *db_path; - if (idmap_tdb2) { + if (idmap_tdb2_perm) { /* its already open */ return NT_STATUS_OK; } @@ -75,11 +103,12 @@ static NTSTATUS idmap_tdb2_open_db(void) NT_STATUS_HAVE_NO_MEMORY(db_path); /* Open idmap repository */ - idmap_tdb2 = db_open(NULL, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644); + idmap_tdb2_perm = db_open(NULL, db_path, 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0644); TALLOC_FREE(db_path); - if (idmap_tdb2 == NULL) { - DEBUG(0, ("Unable to open idmap_tdb2 database '%s'\n", + if (idmap_tdb2_perm == NULL) { + DEBUG(0, ("Unable to open permanent idmap database '%s'\n", db_path)); return NT_STATUS_UNSUCCESSFUL; } @@ -94,50 +123,67 @@ static NTSTATUS idmap_tdb2_open_db(void) */ 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; - uint32 low_id; + + /* 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); + 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)); + 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)); + } } - /* load ranges */ - /* Create high water marks for group and user id */ - 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_uid(&low_uid, &high_uid)) { + idmap_tdb2_state.low_uid = low_uid; + idmap_tdb2_state.high_uid = high_uid; } - 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 (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; - } - - if (((low_id = dbwrap_fetch_int32(idmap_tdb2, - HWM_USER)) == -1) || - (low_id < idmap_tdb2_state.low_uid)) { - 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; + } 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; + } } } @@ -145,17 +191,18 @@ 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; - } - - if (((low_id = dbwrap_fetch_int32(idmap_tdb2, - HWM_GROUP)) == -1) || - (low_id < idmap_tdb2_state.low_gid)) { - 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; + } 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; + } } } @@ -185,10 +232,9 @@ static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid) const char *hwmtype; uint32_t high_hwm; uint32_t hwm; - int res; NTSTATUS status; - status = idmap_tdb2_open_db(); + status = idmap_tdb2_open_perm_db(); NT_STATUS_NOT_OK_RETURN(status); /* Get current high water mark */ @@ -211,14 +257,7 @@ 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); + if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -226,15 +265,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; } /* fetch a new id and increment it */ - ret = dbwrap_change_uint32_atomic(idmap_tdb2, hwmkey, &hwm, 1); + 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)); - idmap_tdb2->transaction_cancel(idmap_tdb2); return NT_STATUS_UNSUCCESSFUL; } @@ -242,13 +279,6 @@ 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; } @@ -267,10 +297,6 @@ static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid) const char *hwmtype; uint32_t hwm; uint32_t high_hwm; - NTSTATUS status; - - status = idmap_tdb2_open_db(); - NT_STATUS_NOT_OK_RETURN(status); /* Get current high water mark */ switch (xid->type) { @@ -291,7 +317,7 @@ static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } - if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) { + if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -335,10 +361,77 @@ struct idmap_tdb2_context { }; /* + 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, - const char *params) +static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom) { NTSTATUS ret; struct idmap_tdb2_context *ctx; @@ -346,7 +439,7 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, const char *range; NTSTATUS status; - status = idmap_tdb2_open_db(); + status = idmap_tdb2_open_cache_db(); NT_STATUS_NOT_OK_RETURN(status); ctx = talloc(dom, struct idmap_tdb2_context); @@ -371,6 +464,7 @@ 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; @@ -458,10 +552,6 @@ static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_m NTSTATUS ret; TDB_DATA data; char *keystr; - NTSTATUS status; - - status = idmap_tdb2_open_db(); - NT_STATUS_NOT_OK_RETURN(status); if (!ctx || !map) { return NT_STATUS_INVALID_PARAMETER; @@ -502,7 +592,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 = dbwrap_fetch_bystring(idmap_tdb2, keystr, keystr); + data = tdb2_fetch_bystring(keystr, keystr); if (!data.dptr) { fstring sidstr; @@ -522,10 +612,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 */ - dbwrap_store_bystring(idmap_tdb2, keystr, + tdb2_store_bystring(keystr, string_term_tdb_data(sidstr), TDB_REPLACE); - dbwrap_store_bystring(idmap_tdb2, sidstr, + tdb2_store_bystring(sidstr, string_term_tdb_data(keystr), TDB_REPLACE); } @@ -557,10 +647,6 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m TDB_DATA data; char *keystr; unsigned long rec_id = 0; - NTSTATUS status; - - status = idmap_tdb2_open_db(); - NT_STATUS_NOT_OK_RETURN(status); if ((keystr = sid_string_talloc(ctx, map->sid)) == NULL) { DEBUG(0, ("Out of memory!\n")); @@ -571,7 +657,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 = dbwrap_fetch_bystring(idmap_tdb2, keystr, keystr); + data = tdb2_fetch_bystring(keystr, keystr); if (!data.dptr) { fstring idstr; @@ -592,9 +678,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 */ - dbwrap_store_bystring(idmap_tdb2, keystr, string_term_tdb_data(idstr), + tdb2_store_bystring(keystr, string_term_tdb_data(idstr), TDB_REPLACE); - dbwrap_store_bystring(idmap_tdb2, idstr, string_term_tdb_data(keystr), + tdb2_store_bystring(idstr, string_term_tdb_data(keystr), TDB_REPLACE); goto done; } @@ -639,6 +725,14 @@ 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++) { @@ -676,6 +770,14 @@ 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++) { @@ -714,14 +816,23 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id NTSTATUS ret; TDB_DATA data; char *ksidstr, *kidstr; - int res; - bool started_transaction = false; + 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 ? */ @@ -756,42 +867,78 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr)); - res = idmap_tdb2->transaction_start(idmap_tdb2); - if (res != 0) { - DEBUG(1,(__location__ " Failed to start transaction\n")); + /* + * 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; } - started_transaction = true; - - /* check wheter sid mapping is already present in db */ - data = dbwrap_fetch_bystring(idmap_tdb2, ksidstr, ksidstr); - if (data.dptr) { - ret = NT_STATUS_OBJECT_NAME_COLLISION; - 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); - 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; + /* 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); } - 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 */ - dbwrap_delete_bystring(idmap_tdb2, ksidstr); + 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; } - - started_transaction = false; - - res = idmap_tdb2->transaction_commit(idmap_tdb2); - if (res != 0) { - DEBUG(1,(__location__ " Failed to commit transaction\n")); + 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; } @@ -800,11 +947,10 @@ static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id ret = NT_STATUS_OK; done: - if (started_transaction) { - idmap_tdb2->transaction_cancel(idmap_tdb2); - } talloc_free(ksidstr); talloc_free(kidstr); + SAFE_FREE(data.dptr); + TALLOC_FREE(update_lock); return ret; } diff --git a/source/winbindd/idmap_util.c b/source/winbindd/idmap_util.c index 9f876618be..0d24070dd6 100644 --- a/source/winbindd/idmap_util.c +++ b/source/winbindd/idmap_util.c @@ -27,50 +27,32 @@ If mapping is not possible returns an error. *****************************************************************/ -NTSTATUS idmap_uid_to_sid(const char *domname, DOM_SID *sid, uid_t uid) +NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) { NTSTATUS ret; struct id_map map; - bool expired; + struct id_map *maps[2]; 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(domname, &map); + 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) { - 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; } @@ -79,50 +61,32 @@ backend: If mapping is not possible returns an error. *****************************************************************/ -NTSTATUS idmap_gid_to_sid(const char *domname, DOM_SID *sid, gid_t gid) +NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) { NTSTATUS ret; struct id_map map; - bool expired; + struct id_map *maps[2]; DEBUG(10,("gid = [%lu]\n", (unsigned long)gid)); - 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()) { - 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(domname, &map); + 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) { - 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_sid2gid(sid, gid); - return NT_STATUS_OK; } @@ -131,70 +95,38 @@ backend: If mapping is not possible or SID maps to a GID returns an error. *****************************************************************/ -NTSTATUS idmap_sid_to_uid(const char *dom_name, DOM_SID *sid, uid_t *uid) +NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid) { NTSTATUS ret; struct id_map map; - bool expired; + struct id_map *maps[2]; 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(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; + + 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))); + return ret; } - 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); + 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); - - 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; - } + *uid = map.xid.id; -done: - *uid = (uid_t)map.xid.id; - idmap_cache_set_sid2uid(sid, *uid); return NT_STATUS_OK; } @@ -203,68 +135,36 @@ done: If mapping is not possible or SID maps to a UID returns an error. *****************************************************************/ -NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid) +NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid) { NTSTATUS ret; struct id_map map; - bool expired; + struct id_map *maps[2]; 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(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; + + 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))); + return ret; } - 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); + 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/source/winbindd/nss_info.c b/source/winbindd/nss_info.c index 0e8cb60257..daa3dd037d 100644 --- a/source/winbindd/nss_info.c +++ b/source/winbindd/nss_info.c @@ -281,47 +281,6 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) /******************************************************************** *******************************************************************/ - NTSTATUS nss_map_to_alias( TALLOC_CTX *mem_ctx, const char *domain, - const char *name, char **alias ) -{ - struct nss_domain_entry *p; - struct nss_info_methods *m; - - if ( (p = find_nss_domain( domain )) == NULL ) { - DEBUG(4,("nss_map_to_alias: Failed to find nss domain pointer for %s\n", - domain )); - return NT_STATUS_NOT_FOUND; - } - - m = p->backend->methods; - - return m->map_to_alias( mem_ctx, domain, name, alias ); -} - - -/******************************************************************** - *******************************************************************/ - - NTSTATUS nss_map_from_alias( TALLOC_CTX *mem_ctx, const char *domain, - const char *alias, char **name ) -{ - struct nss_domain_entry *p; - struct nss_info_methods *m; - - if ( (p = find_nss_domain( domain )) == NULL ) { - DEBUG(4,("nss_map_from_alias: Failed to find nss domain pointer for %s\n", - domain )); - return NT_STATUS_NOT_FOUND; - } - - m = p->backend->methods; - - return m->map_from_alias( mem_ctx, domain, alias, name ); -} - -/******************************************************************** - *******************************************************************/ - NTSTATUS nss_close( const char *parameters ) { struct nss_domain_entry *p = nss_domain_list; diff --git a/source/winbindd/nss_info_template.c b/source/winbindd/nss_info_template.c index d8f903ddd0..aaf02e4abe 100644 --- a/source/winbindd/nss_info_template.c +++ b/source/winbindd/nss_info_template.c @@ -45,8 +45,6 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, if ( !homedir || !shell || !gecos ) return NT_STATUS_INVALID_PARAMETER; - /* protect against home directories using whitespace in the - username */ *homedir = talloc_strdup( ctx, lp_template_homedir() ); *shell = talloc_strdup( ctx, lp_template_shell() ); *gecos = NULL; @@ -58,28 +56,6 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, return NT_STATUS_OK; } -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_template_map_to_alias( TALLOC_CTX *mem_ctx, - const char *domain, - const char *name, - char **alias ) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_template_map_from_alias( TALLOC_CTX *mem_ctx, - const char *domain, - const char *alias, - char **name ) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - /************************************************************************ ***********************************************************************/ @@ -93,11 +69,9 @@ static NTSTATUS nss_template_close( void ) ***********************************************************************/ static struct nss_info_methods nss_template_methods = { - .init = nss_template_init, - .get_nss_info = nss_template_get_info, - .map_to_alias = nss_template_map_to_alias, - .map_from_alias = nss_template_map_from_alias, - .close_fn = nss_template_close + .init = nss_template_init, + .get_nss_info = nss_template_get_info, + .close_fn = nss_template_close }; NTSTATUS nss_info_template_init( void ) diff --git a/source/winbindd/winbindd.c b/source/winbindd/winbindd.c index 44b5415726..876b2e8390 100644 --- a/source/winbindd/winbindd.c +++ b/source/winbindd/winbindd.c @@ -47,12 +47,9 @@ struct messaging_context *winbind_messaging_context(void) { static struct messaging_context *ctx; - 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")); + if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), + winbind_event_context()))) { + smb_panic("Could not init winbind messaging context"); } return ctx; } @@ -340,6 +337,9 @@ 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" }, @@ -534,6 +534,7 @@ 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); @@ -542,7 +543,10 @@ 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); - TALLOC_FREE(state->mem_ctx); + if (state->mem_ctx != NULL) { + talloc_destroy(state->mem_ctx); + state->mem_ctx = NULL; + } if (!success) { state->finished = True; @@ -566,7 +570,10 @@ static void response_main_sent(void *private_data, bool success) } if (state->response.length == sizeof(state->response)) { - TALLOC_FREE(state->mem_ctx); + 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); @@ -600,6 +607,17 @@ 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 = @@ -747,7 +765,10 @@ static void remove_client(struct winbindd_cli_state *state) SAFE_FREE(state->response.extra_data.data); - TALLOC_FREE(state->mem_ctx); + if (state->mem_ctx != NULL) { + talloc_destroy(state->mem_ctx); + state->mem_ctx = NULL; + } remove_fd_event(&state->fd_event); @@ -1025,6 +1046,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(); @@ -1112,9 +1135,12 @@ 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); } + db_tdb2_setup_messaging(winbind_messaging_context(), true); + if (!reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); @@ -1141,6 +1167,12 @@ 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/source/winbindd/winbindd.h b/source/winbindd/winbindd.h index 1b8cd9163f..42a1100f02 100644 --- a/source/winbindd/winbindd.h +++ b/source/winbindd/winbindd.h @@ -24,7 +24,6 @@ #define _WINBINDD_H #include "nsswitch/winbind_struct_protocol.h" -#include "nsswitch/libwbclient/wbclient.h" #ifdef HAVE_LIBNSCD #include <libnscd.h> @@ -196,15 +195,7 @@ 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 */ - pid_t dc_probe_pid; /* Child we're using to detect the DC. */ fstring dcname; struct sockaddr_storage dcaddr; @@ -387,6 +378,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 */ diff --git a/source/winbindd/winbindd_ads.c b/source/winbindd/winbindd_ads.c index 894e7866b3..c588726e30 100644 --- a/source/winbindd/winbindd_ads.c +++ b/source/winbindd/winbindd_ads.c @@ -1195,7 +1195,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, } result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, - cli->desthost, + cli->cli->desthost, flags, &trusts, NULL); diff --git a/source/winbindd/winbindd_async.c b/source/winbindd/winbindd_async.c index 1481aed8e1..f29953d9bb 100644 --- a/source/winbindd/winbindd_async.c +++ b/source/winbindd/winbindd_async.c @@ -468,7 +468,7 @@ static void listent_recv(TALLOC_CTX *mem_ctx, bool success, } cont(private_data, True, response->data.name.dom_name, - (char *)response->extra_data.data); + response->extra_data.data); SAFE_FREE(response->extra_data.data); } diff --git a/source/winbindd/winbindd_cache.c b/source/winbindd/winbindd_cache.c index 360e915bc4..d3e47d0874 100644 --- a/source/winbindd/winbindd_cache.c +++ b/source/winbindd/winbindd_cache.c @@ -502,8 +502,14 @@ static void refresh_sequence_number(struct winbindd_domain *domain, bool force) mode domain or not. And that we can contact it. */ if ( winbindd_can_contact_domain( domain ) ) { + struct winbindd_methods *orig_backend = domain->backend; status = domain->backend->sequence_number(domain, &domain->sequence_number); + if (domain->backend != orig_backend) { + /* Try again. */ + status = domain->backend->sequence_number(domain, + &domain->sequence_number); + } } else { /* just use the current time */ status = NT_STATUS_OK; @@ -934,8 +940,6 @@ static void wcache_save_lockout_policy(struct winbindd_domain *domain, centry_free(centry); } - - static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, struct samr_DomInfo1 *policy) @@ -959,209 +963,6 @@ static void wcache_save_password_policy(struct winbindd_domain *domain, centry_free(centry); } -/*************************************************************************** - ***************************************************************************/ - -static void wcache_save_username_alias(struct winbindd_domain *domain, - NTSTATUS status, - const char *name, const char *alias) -{ - struct cache_entry *centry; - fstring uname; - - if ( (centry = centry_start(domain, status)) == NULL ) - return; - - centry_put_string( centry, alias ); - - fstrcpy(uname, name); - strupper_m(uname); - centry_end(centry, "NSS/NA/%s", uname); - - DEBUG(10,("wcache_save_username_alias: %s -> %s\n", name, alias )); - - centry_free(centry); -} - -static void wcache_save_alias_username(struct winbindd_domain *domain, - NTSTATUS status, - const char *alias, const char *name) -{ - struct cache_entry *centry; - fstring uname; - - if ( (centry = centry_start(domain, status)) == NULL ) - return; - - centry_put_string( centry, name ); - - fstrcpy(uname, alias); - strupper_m(uname); - centry_end(centry, "NSS/AN/%s", uname); - - DEBUG(10,("wcache_save_alias_username: %s -> %s\n", alias, name )); - - centry_free(centry); -} - -/*************************************************************************** - ***************************************************************************/ - -NTSTATUS resolve_username_to_alias( TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - const char *name, char **alias ) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - char *upper_name; - - if ( domain->internal ) - return NT_STATUS_NOT_SUPPORTED; - - if (!cache->tdb) - goto do_query; - - if ( (upper_name = SMB_STRDUP(name)) == NULL ) - return NT_STATUS_NO_MEMORY; - strupper_m(upper_name); - - centry = wcache_fetch(cache, domain, "NSS/NA/%s", upper_name); - - SAFE_FREE( upper_name ); - - if (!centry) - goto do_query; - - status = centry->status; - - if (!NT_STATUS_IS_OK(status)) { - centry_free(centry); - return status; - } - - *alias = centry_string( centry, mem_ctx ); - - centry_free(centry); - - DEBUG(10,("resolve_username_to_alias: [Cached] - mapped %s to %s\n", - name, *alias ? *alias : "(none)")); - - return (*alias) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND; - -do_query: - - /* If its not in cache and we are offline, then fail */ - - if ( get_global_winbindd_state_offline() || !domain->online ) { - DEBUG(8,("resolve_username_to_alias: rejecting query " - "in offline mode\n")); - return NT_STATUS_NOT_FOUND; - } - - status = nss_map_to_alias( mem_ctx, domain->name, name, alias ); - - if ( NT_STATUS_IS_OK( status ) ) { - wcache_save_username_alias(domain, status, name, *alias); - } - - if ( NT_STATUS_EQUAL( status, NT_STATUS_NONE_MAPPED ) ) { - wcache_save_username_alias(domain, status, name, "(NULL)"); - } - - DEBUG(5,("resolve_username_to_alias: backend query returned %s\n", - nt_errstr(status))); - - if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) { - set_domain_offline( domain ); - } - - return status; -} - -/*************************************************************************** - ***************************************************************************/ - -NTSTATUS resolve_alias_to_username( TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - const char *alias, char **name ) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - char *upper_name; - - if ( domain->internal ) - return NT_STATUS_NOT_SUPPORTED; - - if (!cache->tdb) - goto do_query; - - if ( (upper_name = SMB_STRDUP(alias)) == NULL ) - return NT_STATUS_NO_MEMORY; - strupper_m(upper_name); - - centry = wcache_fetch(cache, domain, "NSS/AN/%s", upper_name); - - SAFE_FREE( upper_name ); - - if (!centry) - goto do_query; - - status = centry->status; - - if (!NT_STATUS_IS_OK(status)) { - centry_free(centry); - return status; - } - - *name = centry_string( centry, mem_ctx ); - - centry_free(centry); - - DEBUG(10,("resolve_alias_to_username: [Cached] - mapped %s to %s\n", - alias, *name ? *name : "(none)")); - - return (*name) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND; - -do_query: - - /* If its not in cache and we are offline, then fail */ - - if ( get_global_winbindd_state_offline() || !domain->online ) { - DEBUG(8,("resolve_alias_to_username: rejecting query " - "in offline mode\n")); - return NT_STATUS_NOT_FOUND; - } - - /* an alias cannot contain a domain prefix or '@' */ - - if (strchr(alias, '\\') || strchr(alias, '@')) { - DEBUG(10,("resolve_alias_to_username: skipping fully " - "qualified name %s\n", alias)); - return NT_STATUS_OBJECT_NAME_INVALID; - } - - status = nss_map_from_alias( mem_ctx, domain->name, alias, name ); - - if ( NT_STATUS_IS_OK( status ) ) { - wcache_save_alias_username( domain, status, alias, *name ); - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { - wcache_save_alias_username(domain, status, alias, "(NULL)"); - } - - DEBUG(5,("resolve_alias_to_username: backend query returned %s\n", - nt_errstr(status))); - - if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) { - set_domain_offline( domain ); - } - - return status; -} - NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid) { struct winbind_cache *cache = get_cache(domain); @@ -3462,48 +3263,6 @@ static int validate_pwinfo(TALLOC_CTX *mem_ctx, const char *keystr, return 0; } -static int validate_nss_an(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 ); - - centry_free(centry); - - if (!(state->success)) { - return 1; - } - DEBUG(10,("validate_pwinfo: %s ok\n", keystr)); - return 0; -} - -static int validate_nss_na(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 ); - - 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) { @@ -3605,8 +3364,6 @@ struct key_val_struct { {"NSS/PWINFO/", validate_pwinfo}, {"TRUSTDOMS/", validate_trustdoms}, {"TRUSTDOMCACHE/", validate_trustdomcache}, - {"NSS/NA/", validate_nss_na}, - {"NSS/AN/", validate_nss_an}, {"WINBINDD_OFFLINE", validate_offline}, {WINBINDD_CACHE_VERSION_KEYSTR, validate_cache_version}, {NULL, NULL} diff --git a/source/winbindd/winbindd_cm.c b/source/winbindd/winbindd_cm.c index b9ba486f8a..511d839ae9 100644 --- a/source/winbindd/winbindd_cm.c +++ b/source/winbindd/winbindd_cm.c @@ -171,33 +171,20 @@ 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(); - 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; - } - - domain->dc_probe_pid = sys_fork(); + child_pid = sys_fork(); - if (domain->dc_probe_pid == (pid_t)-1) { + if (child_pid == -1) { DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno))); return False; } - if (domain->dc_probe_pid != (pid_t)0) { + if (child_pid != 0) { /* Parent */ messaging_register(winbind_messaging_context(), NULL, MSG_WINBIND_TRY_TO_GO_ONLINE, @@ -214,11 +201,6 @@ 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); } @@ -236,11 +218,6 @@ 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); } @@ -314,12 +291,12 @@ static void check_domain_online_handler(struct event_context *ctx, static void calc_new_online_timeout_check(struct winbindd_domain *domain) { - int wbr = lp_winbind_reconnect_delay(); + int wbc = lp_winbind_cache_time(); if (domain->startup) { domain->check_online_timeout = 10; - } else if (domain->check_online_timeout < wbr) { - domain->check_online_timeout = wbr; + } else if (domain->check_online_timeout < wbc) { + domain->check_online_timeout = wbc; } } @@ -359,7 +336,7 @@ void set_domain_offline(struct winbindd_domain *domain) } /* If we're in statup mode, check again in 10 seconds, not in - lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */ + lp_winbind_cache_time() seconds (which is 5 mins by default). */ calc_new_online_timeout_check(domain); @@ -621,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 = rpccli_set_timeout(netlogon_pipe, 35000); + orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); if (our_domain->active_directory) { struct netr_DsRGetDCNameInfo *domain_info = NULL; @@ -661,7 +638,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, } /* And restore our original timeout. */ - rpccli_set_timeout(netlogon_pipe, orig_timeout); + cli_set_timeout(netlogon_pipe->cli, orig_timeout); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n", @@ -733,14 +710,8 @@ 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, our_domain->alt_name) == -1) + account_name, lp_realm()) == -1) { return NT_STATUS_NO_MEMORY; } @@ -837,7 +808,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - if (!is_dc_trusted_domain_situation(domain->name) && + if (!is_trusted_domain_situation(domain->name) && (*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { @@ -1091,16 +1062,14 @@ 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, addr); + ads = ads_init(domain->alt_name, domain->name, NULL); ads->auth.flags |= ADS_AUTH_NO_BIND; - ads_status = ads_connect(ads); - if (ADS_ERR_OK(ads_status)) { + 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); @@ -1535,27 +1504,33 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) } if (conn->samr_pipe != NULL) { - 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); + 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) { - 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); + 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) { - 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); + 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) { @@ -1706,7 +1681,7 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) } result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx, - cli->desthost, + cli->cli->desthost, flags, &trusts, NULL); @@ -1789,11 +1764,10 @@ 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 )); - result = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_dssetup.syntax_id, - &cli); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP, + &result); - if (!NT_STATUS_IS_OK(result)) { + if (cli == NULL) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " "PI_DSSETUP on domain %s: (%s)\n", domain->name, nt_errstr(result))); @@ -1809,7 +1783,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DS_ROLE_BASIC_INFORMATION, &info, &werr); - TALLOC_FREE(cli); + cli_rpc_pipe_close(cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo " @@ -1837,14 +1811,13 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) } no_dssetup: - result = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_lsarpc.syntax_id, &cli); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); - if (!NT_STATUS_IS_OK(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))); - TALLOC_FREE(cli); + cli_rpc_pipe_close(cli); TALLOC_FREE(mem_ctx); return; } @@ -1924,7 +1897,7 @@ done: DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n", domain->name, domain->active_directory ? "" : "NOT ")); - TALLOC_FREE(cli); + cli_rpc_pipe_close(cli); TALLOC_FREE(mem_ctx); @@ -2044,15 +2017,14 @@ 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. */ - 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 (!NT_STATUS_IS_OK(result)) { + conn->samr_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + 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 " @@ -2067,7 +2039,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->desthost, + conn->samr_pipe->cli->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { @@ -2076,7 +2048,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) )); - TALLOC_FREE(conn->samr_pipe); + cli_rpc_pipe_close(conn->samr_pipe); schannel: @@ -2088,11 +2060,11 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "for domain %s, trying anon\n", domain->name)); goto anonymous; } - 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); + conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key + (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &result); - if (!NT_STATUS_IS_OK(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) )); @@ -2102,7 +2074,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->desthost, + conn->samr_pipe->cli->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (NT_STATUS_IS_OK(result)) { @@ -2111,20 +2083,21 @@ 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) )); - TALLOC_FREE(conn->samr_pipe); + cli_rpc_pipe_close(conn->samr_pipe); anonymous: /* Finally fall back to anonymous. */ - result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id, - &conn->samr_pipe); + conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, + &result); - if (!NT_STATUS_IS_OK(result)) { + if (conn->samr_pipe == NULL) { + result = NT_STATUS_PIPE_NOT_AVAILABLE; goto done; } result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx, - conn->samr_pipe->desthost, + conn->samr_pipe->cli->desthost, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); if (!NT_STATUS_IS_OK(result)) { @@ -2185,13 +2158,11 @@ 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. */ - 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); + 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 (!NT_STATUS_IS_OK(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", @@ -2214,7 +2185,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")); - TALLOC_FREE(conn->lsa_pipe); + cli_rpc_pipe_close(conn->lsa_pipe); schannel: @@ -2226,12 +2197,11 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, "for domain %s, trying anon\n", domain->name)); goto anonymous; } - 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); + conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key + (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY, + domain->name, p_dcinfo, &result); - if (!NT_STATUS_IS_OK(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) )); @@ -2250,14 +2220,13 @@ 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")); - TALLOC_FREE(conn->lsa_pipe); + cli_rpc_pipe_close(conn->lsa_pipe); anonymous: - result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_lsarpc.syntax_id, - &conn->lsa_pipe); - if (!NT_STATUS_IS_OK(result)) { + 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; } @@ -2307,10 +2276,9 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_netlogon.syntax_id, - &netlogon_pipe); - if (!NT_STATUS_IS_OK(result)) { + netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, + &result); + if (netlogon_pipe == NULL) { return result; } @@ -2327,7 +2295,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, &sec_chan_type)) { - TALLOC_FREE(netlogon_pipe); + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -2342,14 +2310,14 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, &neg_flags); if (!NT_STATUS_IS_OK(result)) { - TALLOC_FREE(netlogon_pipe); + 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")); - TALLOC_FREE(netlogon_pipe); + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_ACCESS_DENIED; } @@ -2373,15 +2341,18 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, part of the new pipe auth struct. */ - 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); + 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. */ - TALLOC_FREE(netlogon_pipe); + cli_rpc_pipe_close(netlogon_pipe); - if (!NT_STATUS_IS_OK(result)) { + if (conn->netlogon_pipe == NULL) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); diff --git a/source/winbindd/winbindd_dual.c b/source/winbindd/winbindd_dual.c index 9e9a244acf..f2be6d692c 100644 --- a/source/winbindd/winbindd_dual.c +++ b/source/winbindd/winbindd_dual.c @@ -196,12 +196,10 @@ static void async_request_fail(struct winbindd_async_request *state) TALLOC_FREE(state->reply_timeout_event); - /* If child exists and is not already reaped, - send kill signal to child. */ + SMB_ASSERT(state->child_pid != (pid_t)0); - if ((state->child->pid != (pid_t)0) && - (state->child->pid != (pid_t)-1) && - (state->child->pid == state->child_pid)) { + /* If not already reaped, send kill signal to child. */ + if (state->child->pid == state->child_pid) { kill(state->child_pid, SIGTERM); /* @@ -297,14 +295,12 @@ static void schedule_async_request(struct winbindd_child *child) } if ((child->pid == 0) && (!fork_domain_child(child))) { - /* fork_domain_child failed. - Cancel all outstanding requests */ + /* Cancel all outstanding requests */ while (request != NULL) { /* request might be free'd in the continuation */ struct winbindd_async_request *next = request->next; - - async_request_fail(request); + request->continuation(request->private_data, False); request = next; } return; @@ -1037,8 +1033,6 @@ static bool fork_domain_child(struct winbindd_child *child) /* Child */ - DEBUG(10, ("Child process %d\n", (int)sys_getpid())); - /* Stop zombies in children */ CatchChild(); @@ -1111,10 +1105,6 @@ 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. */ diff --git a/source/winbindd/winbindd_group.c b/source/winbindd/winbindd_group.c index 088f946877..f81caa22b6 100644 --- a/source/winbindd/winbindd_group.c +++ b/source/winbindd/winbindd_group.c @@ -45,9 +45,7 @@ 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; @@ -145,8 +143,8 @@ static void add_expanded_sid(const DOM_SID *sid, } 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; @@ -179,37 +177,17 @@ static bool fill_passdb_alias_grmem(struct winbindd_domain *domain, /* Fill a grent structure from various other information */ -static bool fill_grent(TALLOC_CTX *mem_ctx, struct winbindd_gr *gr, - const char *dom_name, - char *gr_name, gid_t unix_gid) +static bool fill_grent(struct winbindd_gr *gr, const char *dom_name, + const char *gr_name, gid_t unix_gid) { fstring full_group_name; - char *mapped_name = NULL; - struct winbindd_domain *domain = find_domain_from_name_noinit(dom_name); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - nt_status = normalize_name_map(mem_ctx, domain, gr_name, - &mapped_name); - - /* Basic whitespace replacement */ - if (NT_STATUS_IS_OK(nt_status)) { - fill_domain_username(full_group_name, dom_name, - mapped_name, true); - } - /* Mapped to an aliase */ - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) { - fstrcpy(full_group_name, mapped_name); - } - /* no change */ - else { - fill_domain_username( full_group_name, dom_name, - gr_name, True ); - } + 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); @@ -230,7 +208,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; @@ -251,12 +229,10 @@ 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(domain->name, - &querying_user_sid, ret_uid); + 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))); } @@ -266,23 +242,22 @@ 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++) { @@ -294,22 +269,18 @@ 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; - char *mapped_name = NULL; enum lsa_SidType type; - struct winbindd_domain *target_domain = NULL; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; - - 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, @@ -317,56 +288,38 @@ 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; - } - - target_domain = find_domain_from_name_noinit(domainname); - name_map_status = normalize_name_map(mem_ctx, target_domain, - username, &mapped_name); - - /* Basic whitespace replacement */ - if (NT_STATUS_IS_OK(name_map_status)) { - fill_domain_username(name, domainname, mapped_name, true); - } - /* Mapped to an alias */ - else if (NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) { - fstrcpy(name, mapped_name); - } - /* no mapping done...use original name */ - else { - fill_domain_username(name, domainname, username, true); + 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 @@ -375,29 +328,28 @@ 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; @@ -412,33 +364,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; i<n_new_list; i++ ) { - if ( strcmp( new_list[i-1], new_list[i] ) == 0 ) { - memmove( &new_list[i-1], &new_list[i], + if ( strcmp( new_list[i-1], new_list[i] ) == 0 ) { + memmove( &new_list[i-1], &new_list[i], sizeof(char*)*(n_new_list-i) ); n_new_list--; } } *list = new_list; - *n_list = n_new_list; + *n_list = n_new_list; - return NT_STATUS_OK; + return NT_STATUS_OK; } /*********************************************************************** ***********************************************************************/ -static NTSTATUS expand_groups( TALLOC_CTX *ctx, +static NTSTATUS expand_groups( TALLOC_CTX *ctx, struct winbindd_domain *d, DOM_SID *glist, uint32 n_glist, DOM_SID **new_glist, uint32 *n_new_glist, char ***members, uint32 *n_members ) { - int i, j; + int i, j; NTSTATUS status = NT_STATUS_OK; uint32 num_names = 0; uint32 *name_types = NULL; @@ -446,25 +398,25 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, DOM_SID *sid_mem = NULL; TALLOC_CTX *tmp_ctx = NULL; DOM_SID *new_groups = NULL; - size_t new_groups_size = 0; - + size_t new_groups_size = 0; + *members = NULL; - *n_members = 0; + *n_members = 0; *new_glist = NULL; - *n_new_glist = 0; - + *n_new_glist = 0; + for ( i=0; i<n_glist; i++ ) { tmp_ctx = talloc_new( ctx ); /* Lookup the group membership */ - status = d->methods->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; j<num_names; j++ ) { @@ -473,14 +425,14 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, if ( name_types[j] == SID_NAME_USER || name_types[j] == SID_NAME_COMPUTER ) { - status = add_names_to_list( ctx, members, + status = add_names_to_list( ctx, members, n_members, names+j, 1 ); if ( !NT_STATUS_IS_OK(status) ) goto out; - continue; - } + continue; + } /* Groups */ if ( name_types[j] == SID_NAME_DOM_GRP || @@ -502,12 +454,12 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, } *new_glist = new_groups; - *n_new_glist = (uint32)new_groups_size; - + *n_new_glist = (uint32)new_groups_size; + out: TALLOC_FREE( tmp_ctx ); - - return status; + + return status; } /*********************************************************************** @@ -516,10 +468,9 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx, static bool fill_grent_mem(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 *group_sid, + enum lsa_SidType group_name_type, + size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len) { uint32 num_names = 0; unsigned int buf_len = 0, buf_ndx = 0, i; @@ -529,8 +480,8 @@ static bool fill_grent_mem(struct winbindd_domain *domain, uint32 group_rid; DOM_SID *glist = NULL; DOM_SID *new_glist = NULL; - uint32 n_glist, n_new_glist; - int max_depth = lp_winbind_expand_groups(); + uint32 n_glist, n_new_glist; + int max_depth = lp_winbind_expand_groups(); if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) return False; @@ -557,7 +508,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; @@ -568,15 +519,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. */ @@ -585,66 +536,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; i<max_depth && glist; i++ ) { uint32 n_members = 0; char **members = NULL; - NTSTATUS nt_status; - int j; + NTSTATUS nt_status; nt_status = expand_groups( mem_ctx, domain, - glist, n_glist, + glist, n_glist, &new_glist, &n_new_glist, &members, &n_members); if ( !NT_STATUS_IS_OK(nt_status) ) { - result = False; + result = False; goto done; - } + } + + /* Add new group members to list */ - /* Add new group members to list. Pass through the - alias mapping function */ - - for (j=0; j<n_members; j++) { - fstring name_domain, name_acct; - fstring qualified_name; - char *mapped_name = NULL; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; - struct winbindd_domain *target_domain = NULL; - - if (parse_domain_user(members[j], name_domain, name_acct)) { - target_domain = find_domain_from_name_noinit(name_domain); - /* NOW WHAT ? */ - } - if (!target_domain) { - target_domain = domain; - } - - name_map_status = normalize_name_map(members, target_domain, - name_acct, &mapped_name); - - /* Basic whitespace replacement */ - if (NT_STATUS_IS_OK(name_map_status)) { - fill_domain_username(qualified_name, name_domain, - mapped_name, true); - mapped_name = qualified_name; - } - /* no mapping at all */ - else if (!NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) { - mapped_name = members[j]; - } - - nt_status = add_names_to_list( mem_ctx, &names, - &num_names, - &mapped_name, 1); - if ( !NT_STATUS_IS_OK(nt_status) ) { - result = False; - goto done; - } + nt_status = add_names_to_list( mem_ctx, &names, &num_names, + members, n_members ); + if ( !NT_STATUS_IS_OK(nt_status) ) { + result = False; + goto done; } - - TALLOC_FREE( members ); + + TALLOC_FREE( members ); /* If we have no more groups to expand, break out early */ @@ -657,8 +575,8 @@ static bool fill_grent_mem(struct winbindd_domain *domain, glist = new_glist; n_glist = n_new_glist; } - TALLOC_FREE( glist ); - + TALLOC_FREE( glist ); + DEBUG(10, ("looked up %d names\n", num_names)); again: @@ -666,11 +584,11 @@ static bool fill_grent_mem(struct winbindd_domain *domain, for (i = 0; i < num_names; i++) { int len; - + DEBUG(10, ("processing name %s\n", names[i])); len = strlen(names[i]); - + /* Add to list or calculate buffer length */ if (!buf) { @@ -708,27 +626,26 @@ static bool fill_grent_mem(struct winbindd_domain *domain, *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")); + 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 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; - + if (!success) { DEBUG(5,("getgrnam_recv: lookupname failed!\n")); request_error(state); @@ -739,12 +656,12 @@ static void getgrnam_recv( void *private_data, bool success, const DOM_SID *sid, 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) @@ -752,32 +669,22 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) struct winbindd_domain *domain; fstring name_domain, name_group; char *tmp; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - + /* 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)); - nt_status = normalize_name_unmap(state->mem_ctx, - state->request.data.groupname, - &tmp); - /* If we didn't map anything in the above call, just reset the - tmp pointer to the original string */ - if (!NT_STATUS_IS_OK(nt_status) && - !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) - { - tmp = state->request.data.groupname; - } - /* Parse domain and groupname */ + + memset(name_group, 0, sizeof(fstring)); - memset(name_group, 0, sizeof(name_group)); + 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 @@ -796,7 +703,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)); @@ -806,8 +713,8 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) /* Get rid and name type from name */ - fstrcpy( name_group, tmp ); - + ws_name_replace( name_group, WB_REPLACE_CHAR ); + winbindd_lookupname_async( state->mem_ctx, domain->name, name_group, getgrnam_recv, WINBINDD_GETGRNAM, state ); } @@ -816,7 +723,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; }; @@ -829,7 +736,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")); @@ -845,7 +752,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 ) { @@ -854,10 +761,9 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) return; } - if (!fill_grent(s->state->mem_ctx, &s->state->response.data.gr, - dom_name, group_name, 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; @@ -872,7 +778,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, @@ -880,9 +786,6 @@ static void getgrsid_lookupsid_recv( void *private_data, bool success, enum lsa_SidType name_type ) { struct getgrsid_state *s = (struct getgrsid_state *)private_data; - char *mapped_name = NULL; - fstring raw_name; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; if (!success) { DEBUG(5,("getgrsid_lookupsid_recv: lookupsid failed!\n")); @@ -894,46 +797,22 @@ 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; - } - - /* normalize the name and ensure that we have the DOM\name - coming out of here */ - - fstrcpy(raw_name, name); - - nt_status = normalize_name_unmap(s->state->mem_ctx, raw_name, - &mapped_name); - - /* basiuc whitespace reversal */ - if (NT_STATUS_IS_OK(nt_status)) { - s->group_name = talloc_asprintf(s->state->mem_ctx, - "%s%c%s", - dom_name, - *lp_winbind_separator(), - mapped_name); - } - /* mapped from alias */ - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) { - s->group_name = mapped_name; - } - /* no mapping at all. use original string */ - else { - s->group_name = talloc_asprintf(s->state->mem_ctx, - "%s%c%s", - dom_name, - *lp_winbind_separator(), - raw_name); - } +} - if (s->group_name == NULL) { - DEBUG(1, ("getgrsid_lookupsid_recv: group_name is NULL!\n")); + if ( (s->group_name = talloc_asprintf( s->state->mem_ctx, + "%s%c%s", + dom_name, + *lp_winbind_separator(), + name)) == NULL ) +{ + DEBUG(1, ("getgrsid_lookupsid_recv: talloc_asprintf() Failed!\n")); request_error(s->state); return; } @@ -942,10 +821,10 @@ static void getgrsid_lookupsid_recv( void *private_data, bool success, 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 ) { @@ -965,7 +844,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 ); } @@ -996,7 +875,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); } @@ -1004,14 +883,11 @@ 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) { - gid_t gid = state->request.data.gid; - - DEBUG(3, ("[%5lu]: getgrgid %lu\n", - (unsigned long)state->pid, - (unsigned long)gid)); + 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, gid, getgrgid_recv, state); + winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, getgrgid_recv, state); } /* @@ -1030,46 +906,45 @@ 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; } - - domain_state = SMB_MALLOC_P(struct getent_state); - if (!domain_state) { - DEBUG(1, ("winbindd_setgrent: " - "malloc failed for domain_state!\n")); + + + 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; } @@ -1096,7 +971,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) @@ -1108,17 +983,16 @@ 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); @@ -1130,20 +1004,16 @@ 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; } @@ -1151,36 +1021,29 @@ bool get_sam_group_entries(struct getent_state *ent) /* Copy entries into return buffer */ if (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)); + 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)); + 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", @@ -1188,35 +1051,27 @@ 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 ) { - 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)); + 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)); + + 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; @@ -1257,19 +1112,18 @@ void winbindd_getgrent(struct winbindd_cli_state *state) return; } - group_list = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups); - if (!group_list) { + if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) { 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); @@ -1289,7 +1143,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: @@ -1302,8 +1156,7 @@ 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 */ @@ -1311,33 +1164,32 @@ 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); - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->name, &group_sid, - &group_gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid))) { union unid_t id; enum lsa_SidType type; @@ -1345,8 +1197,9 @@ 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; } @@ -1363,16 +1216,15 @@ 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(state->mem_ctx, &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); @@ -1385,8 +1237,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 { @@ -1409,8 +1261,7 @@ 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; @@ -1424,16 +1275,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", @@ -1441,12 +1292,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)); } } @@ -1469,7 +1320,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; @@ -1524,8 +1375,6 @@ 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; - char *real_name = NULL; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; /* Ensure null termination */ state->request.data.username @@ -1545,22 +1394,13 @@ void winbindd_getgroups(struct winbindd_cli_state *state) s->state = state; - nt_status = normalize_name_unmap(state->mem_ctx, - state->request.data.username, - &real_name); + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); - /* Reset the real_name pointer if we didn't do anything - productive in the above call */ - if (!NT_STATUS_IS_OK(nt_status) && - !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) - { - real_name = state->request.data.username; - } - - if (!parse_domain_user_talloc(state->mem_ctx, real_name, + 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", - real_name)); + state->request.data.username)); /* error out if we do not have nested group support */ @@ -1569,27 +1409,25 @@ 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; @@ -1601,14 +1439,12 @@ 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, @@ -1683,9 +1519,7 @@ 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); @@ -1696,7 +1530,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 @@ -1789,9 +1623,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; @@ -1832,9 +1666,7 @@ 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; } diff --git a/source/winbindd/winbindd_idmap.c b/source/winbindd/winbindd_idmap.c index d8c67dc21c..3c7aa2d0c2 100644 --- a/source/winbindd/winbindd_idmap.c +++ b/source/winbindd/winbindd_idmap.c @@ -170,6 +170,108 @@ 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) @@ -197,28 +299,8 @@ 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); @@ -239,12 +321,9 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, return WINBINDD_ERROR; } - result = idmap_sid_to_uid(state->request.domain_name, &sid, - &state->response.data.uid); + /* Find uid for this sid and return it, possibly ask the slow remote idmap */ - DEBUG(10, ("winbindd_dual_sid2uid: 0x%08x - %s - %u\n", - NT_STATUS_V(result), sid_string_dbg(&sid), - state->response.data.uid)); + result = idmap_sid_to_uid(&sid, &(state->response.data.uid)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -276,16 +355,8 @@ 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", @@ -312,8 +383,7 @@ 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(state->request.domain_name, &sid, - &state->response.data.gid); + 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_dbg(&sid), @@ -351,21 +421,11 @@ 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); } @@ -381,8 +441,7 @@ 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(state->request.domain_name, &sid, - state->request.data.uid); + result = idmap_uid_to_sid(&sid, state->request.data.uid); if (NT_STATUS_IS_OK(result)) { sid_to_fstring(state->response.data.sid.sid, &sid); @@ -419,21 +478,11 @@ 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); } @@ -449,8 +498,7 @@ 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(state->request.domain_name, &sid, - state->request.data.gid); + result = idmap_gid_to_sid(&sid, state->request.data.gid); if (NT_STATUS_IS_OK(result)) { sid_to_fstring(state->response.data.sid.sid, &sid); @@ -473,6 +521,12 @@ 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/source/winbindd/winbindd_locator.c b/source/winbindd/winbindd_locator.c index b2a8bd7e30..709fbcc5d1 100644 --- a/source/winbindd/winbindd_locator.c +++ b/source/winbindd/winbindd_locator.c @@ -54,54 +54,12 @@ 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; i<num_entries; i++) { - if (wbc_flags & lookup_dc_flags[i].wbc_dc_flag) - ds_flags |= lookup_dc_flags[i].ds_dc_flags; - } - - return ds_flags; -} - - static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; struct netr_DsRGetDCNameInfo *info = NULL; const char *dc = NULL; - uint32_t ds_flags = 0; state->request.domain_name [sizeof(state->request.domain_name)-1] = '\0'; @@ -109,11 +67,9 @@ 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, ds_flags, &info); + NULL, NULL, state->request.flags, &info); if (!NT_STATUS_IS_OK(result)) { return WINBINDD_ERROR; diff --git a/source/winbindd/winbindd_misc.c b/source/winbindd/winbindd_misc.c index 50936c01a3..ddfaa7d7ae 100644 --- a/source/winbindd/winbindd_misc.c +++ b/source/winbindd/winbindd_misc.c @@ -86,7 +86,10 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do "good" : "bad")); done: - set_auth_errors(&state->response, 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, 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)); @@ -463,7 +466,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 = rpccli_set_timeout(netlogon_pipe, 35000); + orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000); req_domain = find_domain_from_name_noinit(state->request.domain_name); if (req_domain == domain) { @@ -482,7 +485,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, &werr); } /* And restore our original timeout. */ - rpccli_set_timeout(netlogon_pipe, orig_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", diff --git a/source/winbindd/winbindd_pam.c b/source/winbindd/winbindd_pam.c index d9104ca600..90849b59c3 100644 --- a/source/winbindd/winbindd_pam.c +++ b/source/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)); @@ -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,30 +370,27 @@ 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(); } -static void fill_in_password_policy(struct winbindd_response *r, - const struct samr_DomInfo1 *p) +static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) { - 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)); + 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, @@ -405,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; @@ -416,13 +413,22 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, return status; } - fill_in_password_policy(&state->response, &password_policy); + 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)); 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; @@ -443,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; @@ -467,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) @@ -478,7 +484,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; @@ -497,7 +503,7 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, goto memory_ccache; } - *internal_ccache = false; + *internal_ccache = False; goto done; memory_ccache: @@ -526,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); } @@ -571,13 +577,13 @@ 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); *info3 = NULL; - - /* 1st step: + + /* 1st step: * prepare a krb5_cc_cache string for the user */ uid = get_uid_from_state(state); @@ -587,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; } @@ -638,8 +644,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) { @@ -659,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, @@ -670,11 +676,11 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid, time(NULL), ticket_lifetime, - renewal_until, - false); + 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 { @@ -731,12 +737,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; } /**************************************************************** @@ -811,9 +817,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) { struct winbindd_domain *domain; fstring name_domain, name_user; - char *mapped_user = NULL; NTSTATUS result; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; /* Ensure null termination */ state->request.data.auth.user @@ -832,21 +836,11 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) } /* Parse domain and username */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); - name_map_status = normalize_name_unmap(state->mem_ctx, - state->request.data.auth.user, - &mapped_user); - - /* If the name normalization didnt' actually do anything, - just use the original name */ - - if (!NT_STATUS_IS_OK(name_map_status) && - !NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) - { - mapped_user = state->request.data.auth.user; - } - - if (!canonicalize_username(mapped_user, name_domain, name_user)) { + if (!canonicalize_username(state->request.data.auth.user, + name_domain, name_user)) { result = NT_STATUS_NO_SUCH_USER; goto done; } @@ -875,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; @@ -884,7 +878,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 @@ -896,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); @@ -914,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)) { @@ -942,42 +936,42 @@ 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) { /* 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; } @@ -994,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) && @@ -1005,7 +999,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 +1041,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 " @@ -1119,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))); } @@ -1127,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; @@ -1135,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; } @@ -1185,18 +1179,6 @@ 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) @@ -1218,13 +1200,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()) { @@ -1232,17 +1214,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); @@ -1261,35 +1243,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)); @@ -1303,10 +1285,20 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { - netlogon_fn_t logon_fn; + 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; + retry = False; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1318,7 +1310,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 @@ -1332,7 +1324,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 */ @@ -1357,8 +1349,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,15 +1359,15 @@ 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; } - + /* 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 " @@ -1383,16 +1375,16 @@ 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 ); /* 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; @@ -1401,11 +1393,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; } @@ -1454,15 +1446,12 @@ 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; - char *mapped_user; - fstring domain_user; struct netr_SamInfo3 *info3 = NULL; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; @@ -1479,29 +1468,12 @@ 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 ); - name_map_status = normalize_name_unmap(state->mem_ctx, - state->request.data.auth.user, - &mapped_user); - - /* If the name normalization didnt' actually do anything, - just use the original name */ - - if (!NT_STATUS_IS_OK(name_map_status) && - !NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) - { - mapped_user = state->request.data.auth.user; - } - - parse_domain_user(mapped_user, name_domain, name_user); - - if ( mapped_user != state->request.data.auth.user ) { - fstr_sprintf( domain_user, "%s\\%s", name_domain, name_user ); - safe_strcpy( state->request.data.auth.user, domain_user, - sizeof(state->request.data.auth.user)-1 ); - } + 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 @@ -1520,11 +1492,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")); @@ -1538,7 +1510,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 @@ -1557,7 +1529,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; @@ -1570,7 +1542,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 */ @@ -1578,18 +1550,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) { @@ -1600,9 +1572,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)) { @@ -1617,7 +1589,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 @@ -1634,19 +1606,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; } @@ -1691,8 +1663,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; @@ -1700,16 +1672,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: @@ -1718,20 +1690,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)); - set_auth_errors(&state->response, 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, + 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) @@ -1795,7 +1773,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); @@ -1804,7 +1782,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; @@ -1837,7 +1815,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; @@ -1845,7 +1823,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 { @@ -1854,8 +1832,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; @@ -1867,11 +1845,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; } @@ -1885,9 +1863,19 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - netlogon_fn_t logon_fn; - - retry = false; + 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; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1907,7 +1895,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, @@ -1919,8 +1907,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; } @@ -1931,14 +1919,14 @@ 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; } /* 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 " @@ -1946,8 +1934,8 @@ 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 ); @@ -1962,7 +1950,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; } @@ -1985,14 +1973,21 @@ done: result = nt_status_squash(result); } - set_auth_errors(&state->response, 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", + 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,36 +1997,20 @@ done: void winbindd_pam_chauthtok(struct winbindd_cli_state *state) { fstring domain, user; - char *mapped_user; struct winbindd_domain *contact_domain; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid, state->request.data.chauthtok.user)); /* Setup crap */ - nt_status = normalize_name_unmap(state->mem_ctx, - state->request.data.chauthtok.user, - &mapped_user); - - /* Update the chauthtok name if we did any mapping */ - - if (NT_STATUS_IS_OK(nt_status) || - NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) - { - fstrcpy(state->request.data.chauthtok.user, mapped_user); - } - - /* Must pass in state->...chauthtok.user because - canonicalize_username() assumes an fstring(). Since - we have already copied it (if necessary), this is ok. */ + 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->request.data.auth.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -2041,8 +2020,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; } @@ -2057,7 +2036,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; @@ -2087,44 +2066,52 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - result = rpccli_samr_chgpasswd_user3(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) ) { - - fill_in_password_policy(&state->response, info); + 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; + got_info = True; } - /* only fallback when the chgpasswd_user3 call is not supported */ + /* 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 chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", + DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", nt_errstr(result))); - - result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); + + 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; + result = NT_STATUS_PASSWORD_RESTRICTION; } } -done: +done: if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { @@ -2172,7 +2159,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 @@ -2187,14 +2174,17 @@ done: process_result: - set_auth_errors(&state->response, 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", + 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; } @@ -2229,7 +2219,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; } @@ -2265,7 +2255,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; @@ -2283,7 +2273,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; @@ -2298,7 +2288,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")); @@ -2320,7 +2310,10 @@ process_result: winbindd_delete_memory_creds(state->request.data.logoff.user); - set_auth_errors(&state->response, 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); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2337,12 +2330,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()) { @@ -2362,7 +2355,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); @@ -2388,7 +2381,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, @@ -2426,7 +2419,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, @@ -2465,15 +2458,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: - - set_auth_errors(&state->response, result); + 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; } diff --git a/source/winbindd/winbindd_proto.h b/source/winbindd/winbindd_proto.h deleted file mode 100644 index 4774bc8106..0000000000 --- a/source/winbindd/winbindd_proto.h +++ /dev/null @@ -1,615 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#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 winbind_check_sighup(const char *logfile); -void winbind_check_sigterm(bool in_parent); -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); -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, - 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_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, - 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); -bool get_sam_group_entries(struct getent_state *ent); - - -/* 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_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); -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); -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) ; -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); - -NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - char *name, - char **normalized); -NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx, - char *name, - char **normalized); - -NTSTATUS resolve_username_to_alias(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - const char *name, char **alias); -NTSTATUS resolve_alias_to_username(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - const char *alias, char **name); - -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); -void set_auth_errors(struct winbindd_response *resp, NTSTATUS result); - -/* 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_ */ diff --git a/source/winbindd/winbindd_rpc.c b/source/winbindd/winbindd_rpc.c index df80ad8029..2a7704c8a5 100644 --- a/source/winbindd/winbindd_rpc.c +++ b/source/winbindd/winbindd_rpc.c @@ -279,8 +279,6 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, char *full_name = NULL; struct rpc_pipe_client *cli; POLICY_HND lsa_policy; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; - char *mapped_name = NULL; if (name == NULL || *name=='\0') { full_name = talloc_asprintf(mem_ctx, "%s", domain_name); @@ -296,19 +294,9 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, DEBUG(3,("rpc: name_to_sid name=%s\n", full_name)); - name_map_status = normalize_name_unmap(mem_ctx, full_name, - &mapped_name); + ws_name_return( full_name, WB_REPLACE_CHAR ); - /* Reset the full_name pointer if we mapped anytthing */ - - if (NT_STATUS_IS_OK(name_map_status) || - NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) - { - full_name = mapped_name; - } - - DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", - full_name?full_name:"", domain_name )); + 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)) @@ -344,8 +332,6 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, NTSTATUS result; struct rpc_pipe_client *cli; POLICY_HND lsa_policy; - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; - char *mapped_name = NULL; DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid), domain->name )); @@ -370,17 +356,9 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, *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)); - - name_map_status = normalize_name_map(mem_ctx, domain, *name, - &mapped_name); - if (NT_STATUS_IS_OK(name_map_status) || - NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) - { - *name = mapped_name; - DEBUG(5,("returning mapped name -- %s\n", *name)); - } - return NT_STATUS_OK; } @@ -433,20 +411,8 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain, ret_names = *names; for (i=0; i<num_rids; i++) { - NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL; - char *mapped_name = NULL; - if ((*types)[i] != SID_NAME_UNKNOWN) { - name_map_status = normalize_name_map(mem_ctx, - domain, - ret_names[i], - &mapped_name); - if (NT_STATUS_IS_OK(name_map_status) || - NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) - { - ret_names[i] = mapped_name; - } - + ws_name_replace( ret_names[i], WB_REPLACE_CHAR ); *domain_name = domains[i]; } } @@ -784,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 = rpccli_set_timeout(cli, 35000); + orig_timeout = cli_set_timeout(cli->cli, 35000); result = rpccli_samr_QueryGroupMember(cli, mem_ctx, &group_pol, &rids); /* And restore our original timeout. */ - rpccli_set_timeout(cli, orig_timeout); + cli_set_timeout(cli->cli, orig_timeout); rpccli_samr_Close(cli, mem_ctx, &group_pol); diff --git a/source/winbindd/winbindd_sid.c b/source/winbindd/winbindd_sid.c index 274786fa63..0e8e6ca00b 100644 --- a/source/winbindd/winbindd_sid.c +++ b/source/winbindd/winbindd_sid.c @@ -159,9 +159,6 @@ 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", @@ -183,44 +180,34 @@ 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)); - goto fail; + 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)); - goto fail; + 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); - 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; } 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'; @@ -235,29 +222,10 @@ 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 ); } @@ -268,9 +236,6 @@ 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", @@ -292,17 +257,11 @@ 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)); - goto fail; + request_error(state); + return; } if ( (type!=SID_NAME_DOM_GRP) && @@ -311,28 +270,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)); - goto fail; + 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); - 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; } 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'; @@ -347,32 +302,39 @@ 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 ); } +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 = @@ -449,117 +411,60 @@ 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 *sidstr) +static void uid2sid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; - struct dom_sid sid; - if (!success || !string_to_sid(&sid, sidstr)) { - ZERO_STRUCT(sid); - idmap_cache_set_sid2uid(&sid, state->request.data.uid); - request_error(state); + 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; } - 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); + request_error(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); } /* Convert a gid to a sid */ -static void gid2sid_recv(void *private_data, bool success, const char *sidstr) +static void gid2sid_recv(void *private_data, bool success, const char *sid) { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; - struct dom_sid sid; - if (!success || !string_to_sid(&sid, sidstr)) { - ZERO_STRUCT(sid); - idmap_cache_set_sid2gid(&sid, state->request.data.gid); - request_error(state); + 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; } - DEBUG(10,("gid2sid: gid %lu has sid %s\n", - (unsigned long)(state->request.data.gid), sidstr)); - 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); + request_error(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); } diff --git a/source/winbindd/winbindd_user.c b/source/winbindd/winbindd_user.c index e5d0a22a73..19feec38db 100644 --- a/source/winbindd/winbindd_user.c +++ b/source/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,59 +40,54 @@ 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(TALLOC_CTX *ctx, 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; - char *mapped_name = NULL; - struct winbindd_domain *domain = NULL; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - + if (!pw || !dom_name || !user_name) return False; - + /* Resolve the uid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_uid(dom_name, user_sid, - &pw->pw_uid))) { + 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_string_dbg(user_sid))); return False; } + + /* Resolve the gid number */ - /* Resolve the gid number */ - - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(dom_name, group_sid, - &pw->pw_gid))) { + 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_string_dbg(group_sid))); return False; @@ -102,42 +97,21 @@ static bool winbindd_fill_pwent(TALLOC_CTX *ctx, char *dom_name, char *user_name /* Username */ - domain = find_domain_from_name_noinit(dom_name); - if (domain) { - nt_status = normalize_name_map(ctx, domain, user_name, - &mapped_name); - } else { - DEBUG(5,("winbindd_fill_pwent: Failed to find domain for %s. " - "Disabling name alias support\n", dom_name)); - nt_status = NT_STATUS_NO_SUCH_DOMAIN; - } - - /* Basic removal of whitespace */ - if (NT_STATUS_IS_OK(nt_status)) { - fill_domain_username(output_username, dom_name, mapped_name, True); - } - /* Complete name replacement */ - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) { - fstrcpy(output_username, mapped_name); - } - /* No change at all */ - else { - 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; @@ -161,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)) { @@ -181,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", @@ -203,12 +177,11 @@ struct getpwsid_state { uid_t uid; DOM_SID group_sid; gid_t gid; - bool username_mapped; }; 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, gid_t gid, @@ -244,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, gid_t gid, @@ -256,8 +229,6 @@ static void getpwsid_queryuser_recv(void *private_data, bool success, fstring username; struct getpwsid_state *s = talloc_get_type_abort(private_data, struct getpwsid_state); - char *mapped_name; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; if (!success) { DEBUG(5, ("Could not query domain %s SID %s\n", @@ -268,59 +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); - nt_status = normalize_name_map(s->state->mem_ctx, s->domain, - s->username, &mapped_name); - - /* Basic removal of whitespace */ - if (NT_STATUS_IS_OK(nt_status)) { - s->username = mapped_name; - s->username_mapped = false; - } - /* Complete name replacement */ - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) { - s->username = mapped_name; - s->username_mapped = true; - } - /* No change at all */ - else { - s->username_mapped = false; - } - + 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); @@ -373,29 +328,18 @@ 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; - - /* allow username to be overridden by the alias mapping */ - - if ( s->username_mapped ) { - fstrcpy( output_username, s->username ); - } else { - 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; } @@ -421,39 +365,23 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) { struct winbindd_domain *domain; fstring domname, username; - char *mapped_user = NULL; - char *domuser; - size_t dusize; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - domuser = state->request.data.username; - dusize = sizeof(state->request.data.username); - - /* Ensure null termination (it's an fstring) */ - domuser[dusize-1] = '\0'; - - DEBUG(3, ("[%5lu]: getpwnam %s\n", - (unsigned long)state->pid, - domuser)); - - nt_status = normalize_name_unmap(state->mem_ctx, domuser, - &mapped_user); + /* Ensure null termination */ + state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - /* If we could not convert from an aliased name or a - normalized name, then just use the original name */ + DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid, + state->request.data.username)); - if (!NT_STATUS_IS_OK(nt_status) && - !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) - { - mapped_user = domuser; - } + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); - if (!parse_domain_user(mapped_user, domname, username)) { - DEBUG(5, ("Could not parse domain user: %s\n", domuser)); + 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); @@ -463,24 +391,22 @@ 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 */ winbindd_lookupname_async(state->mem_ctx, domname, username, - getpwnam_name2sid_recv, WINBINDD_GETPWNAM, + getpwnam_name2sid_recv, WINBINDD_GETPWNAM, state); } @@ -489,25 +415,27 @@ static void getpwnam_name2sid_recv(void *private_data, bool success, { struct winbindd_cli_state *state = (struct winbindd_cli_state *)private_data; - fstring domname, username; - char *domuser = state->request.data.username; + fstring domname, username; if (!success) { - DEBUG(5, ("Could not lookup name for user %s\n", domuser)); + 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", domuser)); + DEBUG(5, ("%s is not a user\n", state->request.data.username)); request_error(state); return; } - if (parse_domain_user(domuser, domname, username)) { - check_domain_trusted(domname, sid); + if ( parse_domain_user(state->request.data.username, domname, username) ) { + check_domain_trusted( domname, sid ); } + + winbindd_getpwsid(state, sid); } @@ -523,7 +451,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)); @@ -534,16 +462,12 @@ 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) { - uid_t uid = state->request.data.uid; - - DEBUG(3, ("[%5lu]: getpwuid %lu\n", - (unsigned long)state->pid, - (unsigned long)uid)); + 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, 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, state->request.data.uid, getpwuid_recv, state); } /* @@ -555,53 +479,66 @@ 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 */ - - domain_state = SMB_MALLOC_P(struct getent_state); - if (!domain_state) { + + 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; } @@ -621,7 +558,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); @@ -657,23 +594,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; @@ -685,40 +622,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; @@ -751,20 +688,20 @@ void winbindd_getpwent(struct winbindd_cli_state *state) request_error(state); return; } - - user_list = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users); - if (!user_list) { + + if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) { request_error(state); return; } - /* will be freed by process_request() */ - state->response.extra_data.data = user_list; - memset(user_list, 0, num_users * sizeof(struct winbindd_pw)); + 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; @@ -794,20 +731,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( - state->mem_ctx, - 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, @@ -815,21 +751,22 @@ 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 */ diff --git a/source/winbindd/winbindd_util.c b/source/winbindd/winbindd_util.c index ebcf625178..cfe91366d5 100644 --- a/source/winbindd/winbindd_util.c +++ b/source/winbindd/winbindd_util.c @@ -109,18 +109,7 @@ 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; - const char **ignored_domains, **dom; - ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); - for (dom=ignored_domains; dom && *dom; dom++) { - if (gen_fnmatch(*dom, domain_name) == 0) { - DEBUG(2,("Ignoring domain '%s'\n", domain_name)); - return NULL; - } - } - /* ignore alt_name if we are not in an AD domain */ if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) { @@ -189,47 +178,15 @@ 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 *); 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):"")); @@ -445,10 +402,6 @@ static void rescan_forest_root_trusts( void ) &dom_list[i].sid ); } - if (d == NULL) { - continue; - } - DEBUG(10,("rescan_forest_root_trusts: Following trust path " "for domain tree root %s (%s)\n", d->name, d->alt_name )); @@ -513,10 +466,6 @@ static void rescan_forest_trusts( void ) &cache_methods, &dom_list[i].sid ); } - - if (d == NULL) { - continue; - } DEBUG(10,("Following trust path for domain %s (%s)\n", d->name, d->alt_name )); @@ -1075,12 +1024,13 @@ void free_getent_state(struct getent_state *state) temp = state; while(temp != NULL) { - struct getent_state *next = temp->next; + 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; @@ -1394,107 +1344,34 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain, We use this to remove spaces from user and group names ********************************************************************/ -NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - char *name, - char **normalized) +void ws_name_replace( char *name, char replace ) { - NTSTATUS nt_status; - - if (!name || !normalized) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!lp_winbind_normalize_names()) { - return NT_STATUS_PROCEDURE_NOT_FOUND; - } - - /* Alias support and whitespace replacement are mutually - exclusive */ - - nt_status = resolve_username_to_alias(mem_ctx, domain, - name, normalized ); - if (NT_STATUS_IS_OK(nt_status)) { - /* special return code to let the caller know we - mapped to an alias */ - return NT_STATUS_FILE_RENAMED; - } - - /* check for an unreachable domain */ - - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { - DEBUG(5,("normalize_name_map: Setting domain %s offline\n", - domain->name)); - set_domain_offline(domain); - return nt_status; - } - - /* deal with whitespace */ - - *normalized = talloc_strdup(mem_ctx, name); - if (!(*normalized)) { - return NT_STATUS_NO_MEMORY; - } + char replace_char[2] = { 0x0, 0x0 }; + + if ( !lp_winbind_normalize_names() || (replace == '\0') ) + return; - all_string_sub( *normalized, " ", "_", 0 ); + replace_char[0] = replace; + all_string_sub( name, " ", replace_char, 0 ); - return NT_STATUS_OK; + return; } /********************************************************************* - We use this to do the inverse of normalize_name_map() + We use this to do the inverse of ws_name_replace() ********************************************************************/ -NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx, - char *name, - char **normalized) +void ws_name_return( char *name, char replace ) { - NTSTATUS nt_status; - struct winbindd_domain *domain = find_our_domain(); - - if (!name || !normalized) { - return NT_STATUS_INVALID_PARAMETER; - } + char replace_char[2] = { 0x0, 0x0 }; + + if ( !lp_winbind_normalize_names() || (replace == '\0') ) + return; - if (!lp_winbind_normalize_names()) { - return NT_STATUS_PROCEDURE_NOT_FOUND; - } - - /* Alias support and whitespace replacement are mutally - exclusive */ - - /* When mapping from an alias to a username, we don't know the - domain. But we only need a domain structure to cache - a successful lookup , so just our own domain structure for - the seqnum. */ + replace_char[0] = replace; + all_string_sub( name, replace_char, " ", 0 ); - nt_status = resolve_alias_to_username(mem_ctx, domain, - name, normalized); - if (NT_STATUS_IS_OK(nt_status)) { - /* Special return code to let the caller know we mapped - from an alias */ - return NT_STATUS_FILE_RENAMED; - } - - /* check for an unreachable domain */ - - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { - DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n", - domain->name)); - set_domain_offline(domain); - return nt_status; - } - - /* deal with whitespace */ - - *normalized = talloc_strdup(mem_ctx, name); - if (!(*normalized)) { - return NT_STATUS_NO_MEMORY; - } - - all_string_sub(*normalized, "_", " ", 0); - - return NT_STATUS_OK; + return; } /********************************************************************* @@ -1658,15 +1535,3 @@ 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); -} |