summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2015-08-19 17:00:46 +0200
committerStefan Metzmacher <metze@samba.org>2015-08-31 10:18:16 +0200
commit4fed47622629c18db5374524e6338bbc75314afe (patch)
treeac30d5e55677ed9ea141163815d9f20b74d7df3b
parent56ac018db83bdd507bc32e76fd3404e1e4eb392d (diff)
downloadsamba-4fed47622629c18db5374524e6338bbc75314afe.tar.gz
idmap: Initialize all idmap domains at startup
So far we have initialized idmap domains on demand indexed by name. For sid2xid this works okay, because we could do lookupsids before and thus get the name. For xid2sid this is more problematic. We have to rely on enumtrustdoms to work completely, and we have to look at the list of winbind domains in the parent to get the domain name. Relying on domain->have_idmap_config is not particularly nice. This patch re-works initialization of idmap domains by scanning all parametric parameters, scanning for :backend configuration settings. This way we get a complete list of :range definitions. This means we can rely on the idmap domain array to be complete. This in turn means we can live without the domain name to find a domain, we can do a range search by uid or gid. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org> Bug: https://bugzilla.samba.org/show_bug.cgi?id=11464 (cherry picked from commit ef0c91195533d95ba4fb7947ff5f69c20aa677b8)
-rw-r--r--source3/winbindd/idmap.c199
1 files changed, 109 insertions, 90 deletions
diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c
index 0ba8fdae995..7b4a84d030f 100644
--- a/source3/winbindd/idmap.c
+++ b/source3/winbindd/idmap.c
@@ -64,12 +64,22 @@ static struct idmap_domain *passdb_idmap_domain;
static struct idmap_domain **idmap_domains = NULL;
static int num_domains = 0;
-static void idmap_init(void)
+static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx,
+ const char *domname);
+static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
+ const char *domainname,
+ const char *modulename,
+ bool check_range);
+static bool idmap_found_domain_backend(
+ const char *string, regmatch_t matches[], void *private_data);
+
+static bool idmap_init(void)
{
static bool initialized;
+ int ret;
if (initialized) {
- return;
+ return true;
}
DEBUG(10, ("idmap_init(): calling static_init_idmap\n"));
@@ -77,6 +87,80 @@ static void idmap_init(void)
static_init_idmap;
initialized = true;
+
+ if (!pdb_is_responsible_for_everything_else()) {
+ default_idmap_domain = idmap_init_named_domain(NULL, "*");
+ if (default_idmap_domain == NULL) {
+ return false;
+ }
+ }
+
+ passdb_idmap_domain = idmap_init_domain(
+ NULL, get_global_sam_name(), "passdb", false);
+ if (passdb_idmap_domain == NULL) {
+ TALLOC_FREE(default_idmap_domain);
+ return false;
+ }
+
+ idmap_domains = talloc_array(NULL, struct idmap_domain *, 0);
+ if (idmap_domains == NULL) {
+ TALLOC_FREE(passdb_idmap_domain);
+ TALLOC_FREE(default_idmap_domain);
+ return false;
+ }
+
+ ret = lp_wi_scan_global_parametrics(
+ "idmapconfig\\(.*\\):backend", 2,
+ idmap_found_domain_backend, NULL);
+ if (ret != 0) {
+ DBG_WARNING("wi_scan_global_parametrics returned %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+static bool idmap_found_domain_backend(
+ const char *string, regmatch_t matches[], void *private_data)
+{
+ if (matches[1].rm_so == -1) {
+ DBG_WARNING("Found match, but no name??\n");
+ return false;
+ }
+
+ {
+ struct idmap_domain *dom, **tmp;
+ regoff_t len = matches[1].rm_eo - matches[1].rm_so;
+ char domname[len+1];
+
+ memcpy(domname, string + matches[1].rm_so, len);
+ domname[len] = '\0';
+
+ DBG_DEBUG("Found idmap domain \"%s\"\n", domname);
+
+ if (strcmp(domname, "*") == 0) {
+ return false;
+ }
+
+ dom = idmap_init_named_domain(idmap_domains, domname);
+ if (dom == NULL) {
+ DBG_NOTICE("Could not init idmap domain %s\n",
+ domname);
+ }
+
+ tmp = talloc_realloc(idmap_domains, idmap_domains,
+ struct idmap_domain *, num_domains + 1);
+ if (tmp == NULL) {
+ DBG_WARNING("talloc_realloc failed\n");
+ TALLOC_FREE(dom);
+ return false;
+ }
+ idmap_domains = tmp;
+ idmap_domains[num_domains] = dom;
+ num_domains += 1;
+ }
+
+ return false;
}
static struct idmap_methods *get_methods(const char *name)
@@ -280,8 +364,12 @@ static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx,
struct idmap_domain *result = NULL;
char *config_option;
const char *backend;
+ bool ok;
- idmap_init();
+ ok = idmap_init();
+ if (!ok) {
+ return NULL;
+ }
config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
domname);
@@ -312,57 +400,6 @@ fail:
}
/**
- * Initialize the default domain structure
- * @param[in] mem_ctx memory context for the result
- * @result The default domain structure
- *
- * This routine takes the module name from the "idmap backend" parameter,
- * passing a possible parameter like ldap:ldap://ldap-url/ to the module.
- */
-
-static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
-{
- return idmap_init_named_domain(mem_ctx, "*");
-}
-
-/**
- * Initialize the passdb domain structure
- * @param[in] mem_ctx memory context for the result
- * @result The default domain structure
- *
- * No config, passdb has its own configuration.
- */
-
-static struct idmap_domain *idmap_passdb_domain(TALLOC_CTX *mem_ctx)
-{
- idmap_init();
-
- if (!pdb_is_responsible_for_everything_else()) {
- /*
- * 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;
- }
- }
-
- if (passdb_idmap_domain != NULL) {
- return passdb_idmap_domain;
- }
-
- passdb_idmap_domain = idmap_init_domain(mem_ctx, get_global_sam_name(),
- "passdb", false);
- if (passdb_idmap_domain == NULL) {
- DEBUG(1, ("Could not init passdb idmap domain\n"));
- }
-
- return passdb_idmap_domain;
-}
-
-/**
* Find a domain struct according to a domain name
* @param[in] domname Domain name to get the config for
* @result The default domain structure that fits
@@ -379,21 +416,14 @@ static struct idmap_domain *idmap_passdb_domain(TALLOC_CTX *mem_ctx)
static struct idmap_domain *idmap_find_domain(const char *domname)
{
- struct idmap_domain *result;
+ bool ok;
int i;
DEBUG(10, ("idmap_find_domain called for domain '%s'\n",
domname?domname:"NULL"));
- idmap_init();
-
- /*
- * 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) {
+ ok = idmap_init();
+ if (!ok) {
return NULL;
}
@@ -407,38 +437,21 @@ static struct idmap_domain *idmap_find_domain(const char *domname)
}
}
- if (idmap_domains == NULL) {
- /*
- * talloc context for all idmap domains
- */
- idmap_domains = talloc_array(NULL, struct idmap_domain *, 1);
- }
-
- if (idmap_domains == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
- }
-
- result = idmap_init_named_domain(idmap_domains, domname);
- if (result == NULL) {
- /*
- * Could not init that domain -- try the default one
- */
- return default_idmap_domain;
- }
-
- ADD_TO_ARRAY(idmap_domains, struct idmap_domain *, result,
- &idmap_domains, &num_domains);
- return result;
+ return default_idmap_domain;
}
struct idmap_domain *idmap_find_domain_with_sid(const char *domname,
const struct dom_sid *sid)
{
- idmap_init();
+ bool ok;
+
+ ok = idmap_init();
+ if (!ok) {
+ return NULL;
+ }
if (sid_check_is_for_passdb(sid)) {
- return idmap_passdb_domain(NULL);
+ return passdb_idmap_domain;
}
return idmap_find_domain(domname);
@@ -493,6 +506,12 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id)
{
struct idmap_domain *dom;
struct id_map *maps[2];
+ bool ok;
+
+ ok = idmap_init();
+ if (!ok) {
+ return NT_STATUS_NONE_MAPPED;
+ }
DEBUG(10, ("idmap_backend_unixid_to_sid: domain = '%s', xid = %d "
"(type %d)\n",
@@ -505,7 +524,7 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id)
* Always give passdb a chance first
*/
- dom = idmap_passdb_domain(NULL);
+ dom = passdb_idmap_domain;
if ((dom != NULL)
&& NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))
&& id->status == ID_MAPPED) {