diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/common/util.c | 93 | ||||
-rw-r--r-- | source4/dsdb/pydsdb.c | 27 | ||||
-rw-r--r-- | source4/dsdb/repl/drepl_fsmo.c | 62 | ||||
-rw-r--r-- | source4/dsdb/repl/replicated_objects.c | 27 | ||||
-rw-r--r-- | source4/dsdb/samdb/cracknames.c | 102 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 37 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_info_attr.c | 75 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 15 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_prefixmap.c | 13 |
9 files changed, 357 insertions, 94 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 0e371082be..a5d7caeefe 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -43,6 +43,7 @@ #include "dsdb/common/util.h" #include "lib/socket/socket.h" #include "dsdb/samdb/ldb_modules/util.h" +#include "librpc/gen_ndr/irpc.h" /* search the sam for the specified attributes in a specific domain, filter on @@ -3982,3 +3983,95 @@ bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa) /* other attributes are denied */ return false; } + +/* return fsmo role dn and role owner dn for a particular role*/ +WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx, + struct ldb_context *ldb, + uint32_t role, + struct ldb_dn **fsmo_role_dn, + struct ldb_dn **role_owner_dn) +{ + int ret; + switch (role) { + case DREPL_NAMING_MASTER: + *fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx); + ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_INFRASTRUCTURE_MASTER: + *fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx); + ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_RID_MASTER: + ret = samdb_rid_manager_dn(ldb, tmp_ctx, fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_SCHEMA_MASTER: + *fsmo_role_dn = ldb_get_schema_basedn(ldb); + ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_PDC_MASTER: + *fsmo_role_dn = ldb_get_default_basedn(ldb); + ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + default: + return WERR_DS_DRA_INTERNAL_ERROR; + } + return WERR_OK; +} + +const char *samdb_dn_to_dnshostname(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *server_dn) +{ + int ldb_ret; + struct ldb_result *res = NULL; + const char * const attrs[] = { "dNSHostName", NULL}; + + ldb_ret = ldb_search(ldb, mem_ctx, &res, + server_dn, + LDB_SCOPE_BASE, + attrs, NULL); + if (ldb_ret != LDB_SUCCESS) { + DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s", + ldb_dn_get_linearized(server_dn), ldb_errstring(ldb))); + return NULL; + } + + return samdb_result_string(res->msgs[0], "dNSHostName", NULL); +} diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index 5ba69d7388..7f2e71550c 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -534,6 +534,30 @@ static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args) } +/* + call into samdb_rodc() + */ +static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + struct ldb_context *ldb; + int ret; + bool am_rodc; + + if (!PyArg_ParseTuple(args, "O", &py_ldb)) + return NULL; + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + ret = samdb_rodc(ldb, &am_rodc); + if (samdb_rodc(ldb, &am_rodc) != LDB_SUCCESS) { + PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb)); + return NULL; + } + + return PyBool_FromLong(am_rodc); +} + static PyMethodDef py_dsdb_methods[] = { { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name, @@ -573,6 +597,9 @@ static PyMethodDef py_dsdb_methods[] = { { "_dsdb_set_am_rodc", (PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS, NULL }, + { "_am_rodc", + (PyCFunction)py_dsdb_am_rodc, METH_VARARGS, + NULL }, { "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS, NULL }, { "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS, diff --git a/source4/dsdb/repl/drepl_fsmo.c b/source4/dsdb/repl/drepl_fsmo.c index 375e37b517..ad655f77b9 100644 --- a/source4/dsdb/repl/drepl_fsmo.c +++ b/source4/dsdb/repl/drepl_fsmo.c @@ -6,6 +6,7 @@ Copyright (C) Nadezhda Ivanova 2010 Copyright (C) Andrew Tridgell 2010 Copyright (C) Andrew Bartlett 2010 + Copyright (C) Anatoliy Atanasov 2010 based on drepl_ridalloc.c @@ -62,76 +63,31 @@ WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service, { struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn; TALLOC_CTX *tmp_ctx = talloc_new(service); - struct ldb_context *ldb = service->samdb; - int ret; uint64_t fsmo_info = 0; enum drsuapi_DsExtendedOperation extended_op = DRSUAPI_EXOP_NONE; WERROR werr; - ntds_dn = samdb_ntds_settings_dn(ldb); + ntds_dn = samdb_ntds_settings_dn(service->samdb); if (!ntds_dn) { return WERR_DS_DRA_INTERNAL_ERROR; } + werr = dsdb_get_fsmo_role_info(tmp_ctx, service->samdb, role, + &fsmo_role_dn, &role_owner_dn); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + switch (role) { case DREPL_NAMING_MASTER: - fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx), - ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s", - ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } - break; case DREPL_INFRASTRUCTURE_MASTER: - fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx); - ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", - ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } + case DREPL_SCHEMA_MASTER: extended_op = DRSUAPI_EXOP_FSMO_REQ_ROLE; break; case DREPL_RID_MASTER: - ret = samdb_rid_manager_dn(ldb, tmp_ctx, &fsmo_role_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } - - ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s", - ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } extended_op = DRSUAPI_EXOP_FSMO_RID_REQ_ROLE; break; - case DREPL_SCHEMA_MASTER: - fsmo_role_dn = ldb_get_schema_basedn(ldb); - ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", - ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } - extended_op = DRSUAPI_EXOP_FSMO_REQ_ROLE; - break; case DREPL_PDC_MASTER: - fsmo_role_dn = ldb_get_default_basedn(ldb); - ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s", - ldb_errstring(ldb))); - talloc_free(tmp_ctx); - return WERR_DS_DRA_INTERNAL_ERROR; - } extended_op = DRSUAPI_EXOP_FSMO_REQ_PDC; break; default: diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c index 838dc84655..0beb53c2f3 100644 --- a/source4/dsdb/repl/replicated_objects.c +++ b/source4/dsdb/repl/replicated_objects.c @@ -197,7 +197,7 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb, } WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb, - const char *partition_dn, + const char *partition_dn_str, const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, uint32_t object_count, const struct drsuapi_DsReplicaObjectListItemEx *first_object, @@ -210,6 +210,7 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb, struct dsdb_extended_replicated_objects **objects) { WERROR status; + struct ldb_dn *partition_dn; const struct dsdb_schema *schema; struct dsdb_extended_replicated_objects *out; const struct drsuapi_DsReplicaObjectListItemEx *cur; @@ -226,14 +227,24 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb, return WERR_DS_SCHEMA_NOT_LOADED; } - status = dsdb_schema_pfm_contains_drsuapi_pfm(schema->prefixmap, mapping_ctr); - if (!W_ERROR_IS_OK(status)) { - talloc_free(out); - return status; + partition_dn = ldb_dn_new(out, ldb, partition_dn_str); + W_ERROR_HAVE_NO_MEMORY_AND_FREE(partition_dn, out); + + if (ldb_dn_compare(partition_dn, ldb_get_schema_basedn(ldb)) != 0) { + /* + * check for schema changes in case + * we are not replicating Schema NC + */ + status = dsdb_schema_info_cmp(schema, mapping_ctr); + if (!W_ERROR_IS_OK(status)) { + DEBUG(1,("Remote schema has changed while replicating %s\n", + partition_dn_str)); + talloc_free(out); + return status; + } } - out->partition_dn = ldb_dn_new(out, ldb, partition_dn); - W_ERROR_HAVE_NO_MEMORY(out->partition_dn); + out->partition_dn = partition_dn; out->source_dsa = source_dsa; out->uptodateness_vector= uptodateness_vector; @@ -242,7 +253,7 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb, out->objects = talloc_array(out, struct dsdb_extended_replicated_object, out->num_objects); - W_ERROR_HAVE_NO_MEMORY(out->objects); + W_ERROR_HAVE_NO_MEMORY_AND_FREE(out->objects, out); /* pass the linked attributes down to the repl_meta_data module */ diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index 63fe34552d..e642984171 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -39,12 +39,14 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, - uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, + uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, struct ldb_dn *name_dn, const char *name, const char *domain_filter, const char *result_filter, struct drsuapi_DsNameInfo1 *info1); static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, - uint32_t format_offered, uint32_t format_desired, + enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, struct ldb_dn *name_dn, const char *name, struct drsuapi_DsNameInfo1 *info1); @@ -177,7 +179,8 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, - uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, + uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, const char *name, struct drsuapi_DsNameInfo1 *info1) { WERROR wret; @@ -262,7 +265,8 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, - uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, + uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, const char *name, struct drsuapi_DsNameInfo1 *info1) { int ldb_ret; @@ -348,7 +352,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, /* Crack a single 'name', from format_offered into format_desired, returning the result in info1 */ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, - uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, + uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, const char *name, struct drsuapi_DsNameInfo1 *info1) { krb5_error_code ret; @@ -678,7 +683,8 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, * database */ static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, - uint32_t format_offered, uint32_t format_desired, + enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, struct ldb_dn *name_dn, const char *name, struct drsuapi_DsNameInfo1 *info1) { @@ -717,7 +723,8 @@ static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, - uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, + uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, + enum drsuapi_DsNameFormat format_desired, struct ldb_dn *name_dn, const char *name, const char *domain_filter, const char *result_filter, struct drsuapi_DsNameInfo1 *info1) @@ -872,6 +879,8 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ return DsCrackNameUPN(sam_ctx, mem_ctx, smb_krb5_context, format_flags, format_offered, format_desired, name, info1); + default: + break; } info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; @@ -894,6 +903,8 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn); break; + default: + break; } if (strcasecmp_m(canonical_name, name) == 0) { result = result_res[i]; @@ -1208,7 +1219,7 @@ NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx, NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx, - uint32_t format_offered, + enum drsuapi_DsNameFormat format_offered, const char *name, const char **nt4_domain, const char **nt4_account) { @@ -1275,7 +1286,7 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx, const char **nt4_domain, const char **nt4_account) { - uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN; + enum drsuapi_DsNameFormat format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN; /* Handle anonymous bind */ if (!name || !*name) { @@ -1298,3 +1309,76 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx, return crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, format_offered, name, nt4_domain, nt4_account); } + + +WERROR dcesrv_drsuapi_ListRoles(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, + const struct drsuapi_DsNameRequest1 *req1, + struct drsuapi_DsNameCtr1 **ctr1) +{ + struct drsuapi_DsNameInfo1 *names; + uint32_t i; + uint32_t count = 5;/*number of fsmo role owners we are going to return*/ + + *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1); + W_ERROR_HAVE_NO_MEMORY(*ctr1); + names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count); + W_ERROR_HAVE_NO_MEMORY(names); + + for (i = 0; i < count; i++) { + WERROR werr; + struct ldb_dn *role_owner_dn, *fsmo_role_dn, *server_dn; + werr = dsdb_get_fsmo_role_info(mem_ctx, sam_ctx, i, + &fsmo_role_dn, &role_owner_dn); + if(!W_ERROR_IS_OK(werr)) { + return werr; + } + server_dn = ldb_dn_copy(mem_ctx, role_owner_dn); + ldb_dn_remove_child_components(server_dn, 1); + names[i].status = DRSUAPI_DS_NAME_STATUS_OK; + names[i].dns_domain_name = samdb_dn_to_dnshostname(sam_ctx, mem_ctx, + server_dn); + if(!names[i].dns_domain_name) { + DEBUG(4, ("list_roles: Failed to find dNSHostName for server %s", + ldb_dn_get_linearized(server_dn))); + } + names[i].result_name = talloc_strdup(mem_ctx, ldb_dn_get_linearized(role_owner_dn)); + } + + (*ctr1)->count = count; + (*ctr1)->array = names; + + return WERR_OK; +} + +WERROR dcesrv_drsuapi_CrackNamesByNameFormat(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, + const struct drsuapi_DsNameRequest1 *req1, + struct drsuapi_DsNameCtr1 **ctr1) +{ + struct drsuapi_DsNameInfo1 *names; + uint32_t i, count; + WERROR status; + + *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1); + W_ERROR_HAVE_NO_MEMORY(*ctr1); + + count = req1->count; + names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count); + W_ERROR_HAVE_NO_MEMORY(names); + + for (i=0; i < count; i++) { + status = DsCrackNameOneName(sam_ctx, mem_ctx, + req1->format_flags, + req1->format_offered, + req1->format_desired, + req1->names[i].str, + &names[i]); + if (!W_ERROR_IS_OK(status)) { + return status; + } + } + + (*ctr1)->count = count; + (*ctr1)->array = names; + + return WERR_OK; +} diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 2e7c97af38..b84621f9ee 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -492,6 +492,35 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares) return LDB_SUCCESS; } +/* + mark our registered controls as non-critical in the request + + This is needed as clients may mark controls as critical even if they + are not needed at all in a request. For example, the centrify client + sets the SD_FLAGS control as critical on ldap modify requests which + are setting the dNSHostName attribute on the machine account. That + request doesn't need SD_FLAGS at all, but centrify adds it on all + ldap requests. + */ +static void rootdse_mark_noncritical(struct ldb_module *module, struct ldb_control **controls) +{ + int i, j; + struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data); + + if (!controls) return; + + for (i=0; controls[i]; i++) { + if (controls[i]->critical == 0) { + continue; + } + for (j=0; j<priv->num_controls; j++) { + if (strcasecmp(priv->controls[j], controls[i]->oid) == 0) { + controls[i]->critical = 0; + } + } + } +} + static int rootdse_search(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb; @@ -499,6 +528,8 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req) struct ldb_request *down_req; int ret; + rootdse_mark_noncritical(module, req->controls); + ldb = ldb_module_get_ctx(module); /* see if its for the rootDSE - only a base search on the "" DN qualifies */ @@ -963,6 +994,8 @@ static int rootdse_add(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); + rootdse_mark_noncritical(module, req->controls); + /* If dn is not "" we should let it pass through */ @@ -1013,6 +1046,8 @@ static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); + rootdse_mark_noncritical(module, req->controls); + /* If dn is not "" we should let it pass through */ @@ -1054,6 +1089,8 @@ static int rootdse_delete(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); + rootdse_mark_noncritical(module, req->controls); + /* If dn is not "" we should let it pass through */ diff --git a/source4/dsdb/schema/schema_info_attr.c b/source4/dsdb/schema/schema_info_attr.c index a9c5e932a1..0b5d50b529 100644 --- a/source4/dsdb/schema/schema_info_attr.c +++ b/source4/dsdb/schema/schema_info_attr.c @@ -70,6 +70,28 @@ WERROR dsdb_schema_info_blob_new(TALLOC_CTX *mem_ctx, DATA_BLOB *_schema_info_bl /** + * Verify the 'blob' is a valid schemaInfo blob + */ +bool dsdb_schema_info_blob_is_valid(const DATA_BLOB *blob) +{ + if (!blob || !blob->data) { + return false; + } + + /* schemaInfo blob must be 21 bytes long */ + if (blob->length != 21) { + return false; + } + + /* schemaInfo blob should start with 0xFF */ + if (blob->data[0] != 0xFF) { + return false; + } + + return true; +} + +/** * Parse schemaInfo structure from a data_blob * (DATA_BLOB or ldb_val). * Suitable for parsing blobs that comes from @@ -83,16 +105,8 @@ WERROR dsdb_schema_info_from_blob(const DATA_BLOB *blob, struct dsdb_schema_info *schema_info; struct schemaInfoBlob schema_info_blob; - if (!blob || !blob->data) { - return WERR_INVALID_PARAMETER; - } - - if (blob->length != 21) { - return WERR_INVALID_PARAMETER; - } - - /* schemaInfo blob should start with 0xFF */ - if (blob->data[0] != 0xFF) { + /* verify schemaInfo blob is valid */ + if (!dsdb_schema_info_blob_is_valid(blob)) { return WERR_INVALID_PARAMETER; } @@ -150,6 +164,47 @@ WERROR dsdb_blob_from_schema_info(const struct dsdb_schema_info *schema_info, return WERR_OK; } +/** + * Compares schemaInfo signatures in dsdb_schema and prefixMap. + * NOTE: At present function compares schemaInfo values + * as string without taking into account schemVersion field + * + * @return WERR_OK if schemaInfos are equal + * WERR_DS_DRA_SCHEMA_MISMATCH if schemaInfos are different + */ +WERROR dsdb_schema_info_cmp(const struct dsdb_schema *schema, + const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr) +{ + bool bres; + DATA_BLOB blob; + char *schema_info_str; + struct drsuapi_DsReplicaOIDMapping *mapping; + + /* we should have at least schemaInfo element */ + if (ctr->num_mappings < 1) { + return WERR_INVALID_PARAMETER; + } + + /* verify schemaInfo element is valid */ + mapping = &ctr->mappings[ctr->num_mappings - 1]; + if (mapping->id_prefix != 0) { + return WERR_INVALID_PARAMETER; + } + + blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length); + if (!dsdb_schema_info_blob_is_valid(&blob)) { + return WERR_INVALID_PARAMETER; + } + + schema_info_str = hex_encode_talloc(NULL, blob.data, blob.length); + W_ERROR_HAVE_NO_MEMORY(schema_info_str); + + bres = strequal(schema->schema_info, schema_info_str); + talloc_free(schema_info_str); + + return bres ? WERR_OK : WERR_DS_DRA_SCHEMA_MISMATCH; +} + /** * Reads schema_info structure from schemaInfo diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index a95e7ec2af..ba12f523e8 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -113,20 +113,17 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema, WERROR werr; const char *schema_info; struct dsdb_schema_prefixmap *pfm; - struct dsdb_schema_info *schi; TALLOC_CTX *mem_ctx; + /* verify schemaInfo blob is valid one */ + if (!dsdb_schema_info_blob_is_valid(schemaInfo)) { + DEBUG(0,(__location__": dsdb_schema_info_blob_is_valid() failed.\n")); + return WERR_INVALID_PARAMETER; + } + mem_ctx = talloc_new(schema); W_ERROR_HAVE_NO_MEMORY(mem_ctx); - /* parse schemaInfo blob to verify it is valid */ - werr = dsdb_schema_info_from_blob(schemaInfo, mem_ctx, &schi); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " dsdb_schema_info_from_blob failed: %s\n", win_errstr(werr))); - talloc_free(mem_ctx); - return werr; - } - /* fetch prefixMap */ werr = _dsdb_prefixmap_from_ldb_val(prefixMap, mem_ctx, &pfm); diff --git a/source4/dsdb/schema/schema_prefixmap.c b/source4/dsdb/schema/schema_prefixmap.c index 50f74b7161..79894fe272 100644 --- a/source4/dsdb/schema/schema_prefixmap.c +++ b/source4/dsdb/schema/schema_prefixmap.c @@ -188,6 +188,7 @@ static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ct /* encode oid in BER format */ if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) { + DEBUG(0,("ber_write_OID_String() failed for %s\n", full_oid)); return WERR_INTERNAL_ERROR; } @@ -341,7 +342,9 @@ WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_ } if (!pfm_entry) { - return WERR_INTERNAL_ERROR; + DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n", + attid, attid)); + return WERR_DS_NO_ATTRIBUTE_OR_VALUE; } /* copy oid prefix making enough room */ @@ -363,6 +366,8 @@ WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_ } if (!ber_read_OID_String(mem_ctx, bin_oid, _oid)) { + DEBUG(0,("ber_read_OID_String() failed for %s\n", + hex_encode_talloc(bin_oid.data, bin_oid.data, bin_oid.length))); werr = WERR_INTERNAL_ERROR; } @@ -394,7 +399,6 @@ static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_ if (have_schema_info) { DATA_BLOB blob; - struct dsdb_schema_info *schi = NULL; if (ctr->num_mappings < 2) { return WERR_INVALID_PARAMETER; @@ -406,10 +410,9 @@ static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_ return WERR_INVALID_PARAMETER; } - /* parse schemaInfo blob to verify it is valid */ + /* verify schemaInfo blob is valid one */ blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length); - if (!W_ERROR_IS_OK(dsdb_schema_info_from_blob(&blob, talloc_autofree_context(), &schi))) { - talloc_free(schi); + if (!dsdb_schema_info_blob_is_valid(&blob)) { return WERR_INVALID_PARAMETER; } |