summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/common/util.c93
-rw-r--r--source4/dsdb/pydsdb.c27
-rw-r--r--source4/dsdb/repl/drepl_fsmo.c62
-rw-r--r--source4/dsdb/repl/replicated_objects.c27
-rw-r--r--source4/dsdb/samdb/cracknames.c102
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c37
-rw-r--r--source4/dsdb/schema/schema_info_attr.c75
-rw-r--r--source4/dsdb/schema/schema_init.c15
-rw-r--r--source4/dsdb/schema/schema_prefixmap.c13
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;
}