diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 83 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.c | 87 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 16 | ||||
-rw-r--r-- | source4/scripting/libjs/provision.js | 12 | ||||
-rw-r--r-- | source4/setup/provision_templates.ldif | 22 |
5 files changed, 156 insertions, 64 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 128ec13242..e2e914ee82 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -190,24 +190,16 @@ static int samldb_allocate_next_rid(struct ldb_module *module, TALLOC_CTX *mem_c */ static int samldb_get_new_sid(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn, + struct ldb_dn *dom_dn, struct dom_sid **sid) { const char * const attrs[2] = { "objectSid", NULL }; struct ldb_result *res = NULL; - struct ldb_dn *dom_dn; int ret; struct dom_sid *dom_sid; /* get the domain component part of the provided dn */ - dom_dn = samdb_search_for_parent_domain(module->ldb, mem_ctx, obj_dn); - if (dom_dn == NULL) { - ldb_asprintf_errstring(module->ldb, - "Invalid dn (%s) not child of a domain object!\n", - ldb_dn_get_linearized(obj_dn)); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - /* find the domain sid */ ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res); @@ -338,13 +330,14 @@ int samldb_notice_sid(struct ldb_module *module, } static int samldb_handle_sid(struct ldb_module *module, - TALLOC_CTX *mem_ctx, struct ldb_message *msg2) + TALLOC_CTX *mem_ctx, struct ldb_message *msg2, + struct ldb_dn *parent_dn) { int ret; struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg2, "objectSid"); if (sid == NULL) { - ret = samldb_get_new_sid(module, msg2, msg2->dn, &sid); + ret = samldb_get_new_sid(module, msg2, msg2->dn, parent_dn, &sid); if (ret != 0) { return ret; } @@ -361,31 +354,35 @@ static int samldb_handle_sid(struct ldb_module *module, return ret; } -static char *samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx) +static int samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx, + struct ldb_dn *dom_dn, char **name) { - char *name; const char *attrs[] = { NULL }; - struct ldb_message **msgs; + struct ldb_result *res; int ret; /* Format: $000000-000000000000 */ do { - name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random()); + *name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random()); /* TODO: Figure out exactly what this is meant to conflict with */ - ret = gendb_search(module->ldb, - mem_ctx, NULL, &msgs, attrs, - "samAccountName=%s", - ldb_binary_encode_string(mem_ctx, name)); - if (ret == 0) { + ret = ldb_search_exp_fmt(module->ldb, + mem_ctx, &res, dom_dn, LDB_SCOPE_SUBTREE, attrs, + "samAccountName=%s", + ldb_binary_encode_string(mem_ctx, *name)); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, "samldb: Failure searching to determine if samAccountName %s is unique: %s", + *name, ldb_errstring(module->ldb)); + return ret; + } + + if (res->count == 0) { + talloc_free(res); /* Great. There are no conflicting users/groups/etc */ - return name; - } else if (ret == -1) { - /* Bugger, there is a problem, and we don't know what it is until gendb_search improves */ - return NULL; + return LDB_SUCCESS; } else { - talloc_free(name); - /* gah, there are conflicting sids, lets move around the loop again... */ + talloc_free(*name); + /* gah, there is a conflicting name, lets move around the loop again... */ } } while (1); } @@ -394,8 +391,9 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ struct ldb_message **ret_msg) { int ret; - const char *name; + char *name; struct ldb_message *msg2; + struct ldb_dn *dom_dn; const char *rdn_name; TALLOC_CTX *mem_ctx = talloc_new(msg); const char *errstr; @@ -428,12 +426,19 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ return LDB_ERR_CONSTRAINT_VIOLATION; } + ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "samldb_fill_group_object: %s", errstr); + return ret; + } + /* Generate a random name, if no samAccountName was supplied */ if (ldb_msg_find_element(msg2, "samAccountName") == NULL) { - name = samldb_generate_samAccountName(module, mem_ctx); - if (!name) { + ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name); + if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; + return ret; } ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name); if (ret) { @@ -443,7 +448,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ } /* Manage SID allocation, conflicts etc */ - ret = samldb_handle_sid(module, mem_ctx, msg2); + ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); if (ret == LDB_SUCCESS) { talloc_steal(msg, msg2); @@ -459,6 +464,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const int ret; char *name; struct ldb_message *msg2; + struct ldb_dn *dom_dn; const char *rdn_name; TALLOC_CTX *mem_ctx = talloc_new(msg); const char *errstr; @@ -514,11 +520,18 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const return LDB_ERR_CONSTRAINT_VIOLATION; } + ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "samldb_fill_group_object: %s", errstr); + return ret; + } + if (ldb_msg_find_element(msg2, "samAccountName") == NULL) { - name = samldb_generate_samAccountName(module, mem_ctx); - if (!name) { + ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name); + if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; + return ret; } ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name); if (ret) { @@ -532,7 +545,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const */ /* Manage SID allocation, conflicts etc */ - ret = samldb_handle_sid(module, mem_ctx, msg2); + ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); /* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */ diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index 36e12e859e..96e526d319 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -37,6 +37,34 @@ #include "dsdb/common/flags.h" #include "param/param.h" +char *samdb_relative_path(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *name) +{ + const char *base_url = + (const char *)ldb_get_opaque(ldb, "ldb_url"); + char *path, *p, *full_name; + if (name == NULL) { + return NULL; + } + if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) { + return talloc_strdup(mem_ctx, name); + } + path = talloc_strdup(mem_ctx, base_url); + if (path == NULL) { + return NULL; + } + if ( (p = strrchr(path, '/')) != NULL) { + p[0] = '\0'; + full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name); + } else { + full_name = talloc_asprintf(mem_ctx, "./%s", name); + } + talloc_free(path); + return full_name; +} + + /* connect to the SAM database return an opaque context pointer on success, or NULL on failure @@ -682,21 +710,49 @@ int samdb_copy_template(struct ldb_context *ldb, struct ldb_result *res; struct ldb_message *t; int ret, i, j; - struct ldb_dn *basedn = ldb_dn_new(ldb, ldb, "cn=Templates"); + struct ldb_context *templates_ldb; + char *templates_ldb_path; + struct ldb_dn *basedn; + + templates_ldb = talloc_get_type(ldb_get_opaque(ldb, "templates_ldb"), struct ldb_context); + + if (!templates_ldb) { + templates_ldb_path = samdb_relative_path(ldb, + msg, + "templates.ldb"); + if (!templates_ldb_path) { + *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct path for template db"); + return LDB_ERR_OPERATIONS_ERROR; + } + templates_ldb = ldb_wrap_connect(ldb, global_loadparm, + templates_ldb_path, NULL, + NULL, 0, NULL); + talloc_free(templates_ldb_path); + if (!templates_ldb) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_set_opaque(ldb, "templates_ldb", templates_ldb); + if (ret != LDB_SUCCESS) { + return ret; + } + } *errstring = NULL; + basedn = ldb_dn_new(templates_ldb, ldb, "cn=Templates"); if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) { + talloc_free(basedn); *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", name); return LDB_ERR_OPERATIONS_ERROR; } /* pull the template record */ - ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, "cn=*", NULL, &res); + ret = ldb_search(templates_ldb, basedn, LDB_SCOPE_BASE, "(dn=*)", NULL, &res); talloc_free(basedn); if (ret != LDB_SUCCESS) { - *errstring = talloc_steal(msg, ldb_errstring(ldb)); + *errstring = talloc_steal(msg, ldb_errstring(templates_ldb)); return ret; } if (res->count != 1) { @@ -1439,7 +1495,8 @@ failed: /* Find a domain object in the parents of a particular DN. */ -struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, + struct ldb_dn **parent_dn, const char **errstring) { TALLOC_CTX *local_ctx; struct ldb_dn *sdn = dn; @@ -1448,7 +1505,7 @@ struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CT const char *attrs[] = { NULL }; local_ctx = talloc_new(mem_ctx); - if (local_ctx == NULL) return NULL; + if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR; while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) { ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE, @@ -1458,18 +1515,28 @@ struct ldb_dn *samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CT if (res->count == 1) { break; } + } else { + break; } } - if (ret != LDB_SUCCESS || res->count != 1) { + if (ret != LDB_SUCCESS) { + *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s: %s", + ldb_dn_get_linearized(sdn), + ldb_errstring(ldb)); talloc_free(local_ctx); - return NULL; + return ret; + } + if (res->count != 1) { + *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object", + ldb_dn_get_linearized(sdn)); + talloc_free(local_ctx); + return LDB_ERR_CONSTRAINT_VIOLATION; } - talloc_steal(mem_ctx, sdn); + *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn); talloc_free(local_ctx); - - return sdn; + return ret; } /* diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index d8b361ca27..21c4d36e9b 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -570,6 +570,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer"); if (ret == LDB_SUCCESS && res_account->count == 1) { + const char *errstr; ctr1->array[i].dns_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL); ctr1->array[i].netbios_name @@ -578,10 +579,11 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta = ldb_dn_get_linearized(res_account->msgs[0]->dn); /* Determine if this is the PDC */ - domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx, - mem_ctx, res_account->msgs[0]->dn); + ret = samdb_search_for_parent_domain(b_state->sam_ctx, + mem_ctx, res_account->msgs[0]->dn, + &domain_dn, &errstr); - if (domain_dn) { + if (ret == LDB_SUCCESS) { ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s", ldb_dn_get_linearized(ntds_dn)); @@ -664,6 +666,7 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn, LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer"); if (ret == LDB_SUCCESS && res_account->count == 1) { + const char *errstr; ctr2->array[i].dns_name = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL); ctr2->array[i].netbios_name @@ -673,10 +676,11 @@ static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_sta = samdb_result_guid(res_account->msgs[0], "objectGUID"); /* Determine if this is the PDC */ - domain_dn = samdb_search_for_parent_domain(b_state->sam_ctx, - mem_ctx, res_account->msgs[0]->dn); + ret = samdb_search_for_parent_domain(b_state->sam_ctx, + mem_ctx, res_account->msgs[0]->dn, + &domain_dn, &errstr); - if (domain_dn) { + if (ret == LDB_SUCCESS) { ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn, LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s", ldb_dn_get_linearized(ntds_dn)); diff --git a/source4/scripting/libjs/provision.js b/source4/scripting/libjs/provision.js index 3f3b179688..73c7608814 100644 --- a/source4/scripting/libjs/provision.js +++ b/source4/scripting/libjs/provision.js @@ -383,6 +383,7 @@ function provision_default_paths(subobj) paths.shareconf = lp.get("private dir") + "/" + "share.ldb"; paths.samdb = lp.get("sam database"); paths.secrets = lp.get("secrets database"); + paths.templates = lp.get("private dir") + "/" + "templates.ldb"; paths.keytab = "secrets.keytab"; paths.dns_keytab = "dns.keytab"; paths.dns_keytab_abs = lp.get("private dir") + "/" + paths.dns_keytab; @@ -528,6 +529,9 @@ function provision_become_dc(subobj, message, erase, paths, session_info) info.message = message; info.session_info = session_info; + message("Setting up teplates into " + paths.templates + "\n"); + setup_ldb("provision_templates.ldif", info, paths.templates); + /* Also wipes the database */ message("Setting up " + paths.samdb + " partitions\n"); setup_ldb("provision_partitions.ldif", info, paths.samdb); @@ -548,9 +552,6 @@ function provision_become_dc(subobj, message, erase, paths, session_info) message("Setting up " + paths.samdb + " indexes\n"); setup_add_ldif("provision_index.ldif", info, samdb, false); - message("Setting up " + paths.samdb + " templates\n"); - setup_add_ldif("provision_templates.ldif", info, samdb, false); - ok = samdb.transaction_commit(); assert(ok); @@ -623,6 +624,9 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda var reg = reg_open(); reg.apply_patchfile(lp.get("setup directory") + "/provision.reg") + message("Setting up teplates into " + paths.templates + "\n"); + setup_ldb("provision_templates.ldif", info, paths.templates); + message("Setting up sam.ldb partitions\n"); /* Also wipes the database */ setup_ldb("provision_partitions.ldif", info, paths.samdb); @@ -707,8 +711,6 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda message("Setting up display specifiers\n"); setup_add_ldif("display_specifiers.ldif", info, samdb, false); - message("Setting up sam.ldb templates\n"); - setup_add_ldif("provision_templates.ldif", info, samdb, false); message("Adding users container (permitted to fail)\n"); var add_ok = setup_add_ldif("provision_users_add.ldif", info, samdb, true); diff --git a/source4/setup/provision_templates.ldif b/source4/setup/provision_templates.ldif index fa0718a0b7..8797efaf98 100644 --- a/source4/setup/provision_templates.ldif +++ b/source4/setup/provision_templates.ldif @@ -1,15 +1,21 @@ +### +# Templates to be put in templates.ldb. Not part of main samdb any more. +### + +dn: @OPTIONS +checkBaseOnSearch: TRUE + +dn: @INDEXLIST +@IDXATTR: cn + +dn: @ATTRIBUTES +cn: CASE_INSENSITIVE +dn: CASE_INSENSITIVE + dn: CN=Templates objectClass: top objectClass: container description: Container for SAM account templates -showInAdvancedViewOnly: TRUE -systemFlags: 2348810240 -isCriticalSystemObject: TRUE - -### -# note! the template users must not match normal searches. Be careful -# with what classes you put them in -### dn: CN=TemplateUser,CN=Templates userAccountControl: 514 |