From fd22e0304782e20b9bbb29464b6c745d409ff4c6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 2 Oct 2009 12:03:05 +1000 Subject: s4-ldb: Add support for binary blobs in DNs AD has the concept of a DN prefixed with B:NN:XXXXXX: that contains a binary blob. We need to support those in order to give correctly formatted binary blobs for things like wellKnownObjects This implementation is not ideal, as it allows for binary blobs on all DNs, whereas it should only allow them on those with a syntax of 2.5.5.7. We should clean this up in the future, but meanwhile this implementation at least gets us a working DC join of w2k8 to s4. This patch also uses a static function for marking DNs as invalid, which is very useful when debugging this code, as you can break on it in gdb. --- source4/dsdb/schema/schema_syntax.c | 136 ++++++++++++++++++++++++++++++------ 1 file changed, 113 insertions(+), 23 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index c564471d4b..cbbd4a8636 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -1204,6 +1204,8 @@ static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, return WERR_OK; } + + static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, @@ -1212,6 +1214,7 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, struct ldb_message_element *out) { uint32_t i; + int ret; out->flags = 0; out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName); @@ -1222,39 +1225,81 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, W_ERROR_HAVE_NO_MEMORY(out->values); for (i=0; i < out->num_values; i++) { - struct drsuapi_DsReplicaObjectIdentifier3Binary id3b; - char *binary; - char *str; + struct drsuapi_DsReplicaObjectIdentifier3Binary id3; enum ndr_err_code ndr_err; + DATA_BLOB guid_blob; + struct ldb_dn *dn; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + W_ERROR_HAVE_NO_MEMORY(tmp_ctx); + } if (in->value_ctr.values[i].blob == NULL) { + talloc_free(tmp_ctx); return WERR_FOOBAR; } if (in->value_ctr.values[i].blob->length == 0) { + talloc_free(tmp_ctx); return WERR_FOOBAR; } - ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob, - out->values, schema->iconv_convenience, &id3b, - (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary); + + /* windows sometimes sends an extra two pad bytes here */ + ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob, + tmp_ctx, schema->iconv_convenience, &id3, + (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); return ntstatus_to_werror(status); } - /* TODO: handle id3.guid and id3.sid */ - binary = data_blob_hex_string(out->values, &id3b.binary); - W_ERROR_HAVE_NO_MEMORY(binary); + dn = ldb_dn_new(tmp_ctx, ldb, id3.dn); + if (!dn) { + talloc_free(tmp_ctx); + /* If this fails, it must be out of memory, as it does not do much parsing */ + W_ERROR_HAVE_NO_MEMORY(dn); + } - str = talloc_asprintf(out->values, "B:%u:%s:%s", - (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */ - binary, - id3b.dn); - W_ERROR_HAVE_NO_MEMORY(str); + ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); + return ntstatus_to_werror(status); + } - /* TODO: handle id3.guid and id3.sid */ - out->values[i] = data_blob_string_const(str); + ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return WERR_FOOBAR; + } + + talloc_free(guid_blob.data); + + if (id3.__ndr_size_sid) { + DATA_BLOB sid_blob; + ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, + (ndr_push_flags_fn_t)ndr_push_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); + return ntstatus_to_werror(status); + } + + ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return WERR_FOOBAR; + } + } + + /* set binary stuff */ + ldb_dn_set_binary(dn, &id3.binary); + + out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1)); + talloc_free(tmp_ctx); } return WERR_OK; @@ -1285,27 +1330,72 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, W_ERROR_HAVE_NO_MEMORY(blobs); for (i=0; i < in->num_values; i++) { - struct drsuapi_DsReplicaObjectIdentifier3Binary id3b; + struct drsuapi_DsReplicaObjectIdentifier3Binary id3; enum ndr_err_code ndr_err; + const DATA_BLOB *guid_blob, *sid_blob; + struct ldb_dn *dn; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + W_ERROR_HAVE_NO_MEMORY(tmp_ctx); out->value_ctr.values[i].blob = &blobs[i]; - /* TODO: handle id3b.guid and id3b.sid, id3.binary */ - ZERO_STRUCT(id3b); - id3b.dn = (const char *)in->values[i].data; - id3b.binary = data_blob(NULL, 0); + dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]); + + W_ERROR_HAVE_NO_MEMORY(dn); + + guid_blob = ldb_dn_get_extended_component(dn, "GUID"); - ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b, - (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary); + ZERO_STRUCT(id3); + + if (guid_blob) { + ndr_err = ndr_pull_struct_blob_all(guid_blob, + tmp_ctx, schema->iconv_convenience, &id3.guid, + (ndr_pull_flags_fn_t)ndr_pull_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); + return ntstatus_to_werror(status); + } + } + + sid_blob = ldb_dn_get_extended_component(dn, "SID"); + if (sid_blob) { + + ndr_err = ndr_pull_struct_blob_all(sid_blob, + tmp_ctx, schema->iconv_convenience, &id3.sid, + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); + return ntstatus_to_werror(status); + } + } + + id3.dn = ldb_dn_get_linearized(dn); + if (strncmp(id3.dn, "B:", 2) == 0) { + id3.dn = strchr(id3.dn, ':'); + id3.dn = strchr(id3.dn+1, ':'); + id3.dn = strchr(id3.dn+1, ':'); + id3.dn++; + } + + /* get binary stuff */ + ldb_dn_get_binary(dn, &id3.binary); + + ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + talloc_free(tmp_ctx); return ntstatus_to_werror(status); } + talloc_free(tmp_ctx); } return WERR_OK; } + + static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, -- cgit From 0e028fcb7d141d68de2baadeb2c0fae262f2bedc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Sep 2009 15:12:49 -0700 Subject: s4:dsdb add systemPossibleInferiors to schema code This allows us to figure out what the system can add, which will not be in possibleInferiors due to the systemOnly flag. Andrew Bartlett --- source4/dsdb/schema/schema.h | 1 + source4/dsdb/schema/schema_inferiors.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 4e7e503931..ddd9b375f6 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -119,6 +119,7 @@ struct dsdb_class { const char **mustContain; const char **mayContain; const char **possibleInferiors; + const char **systemPossibleInferiors; const char *defaultSecurityDescriptor; diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index b02d557c58..264e471298 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -198,6 +198,25 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds schema_class->possibleInferiors = str_list_unique(schema_class->possibleInferiors); } +static void schema_fill_system_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class) +{ + struct dsdb_class *c2; + + for (c2=schema->classes; c2; c2=c2->next) { + char **superiors = schema_posssuperiors(schema, c2); + if (c2->objectClassCategory != 2 + && c2->objectClassCategory != 3 + && str_list_check(superiors, schema_class->lDAPDisplayName)) { + if (schema_class->possibleInferiors == NULL) { + schema_class->systemPossibleInferiors = str_list_make_empty(schema_class); + } + schema_class->systemPossibleInferiors = str_list_add_const(schema_class->systemPossibleInferiors, + c2->lDAPDisplayName); + } + } + schema_class->systemPossibleInferiors = str_list_unique(schema_class->systemPossibleInferiors); +} + /* fill in a string class name from a governs_ID */ @@ -285,6 +304,7 @@ void schema_fill_constructed(struct dsdb_schema *schema) for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { schema_fill_possible_inferiors(schema, schema_class); + schema_fill_system_possible_inferiors(schema, schema_class); } /* free up our internal cache elements */ -- cgit From cb143eafef1dae1e055454fa3a5e90183e6c4f5d Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Sat, 3 Oct 2009 15:08:00 +0200 Subject: s4:schema_inferiors - Fix wrong check --- source4/dsdb/schema/schema_inferiors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index 264e471298..3be97b6b83 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -207,7 +207,7 @@ static void schema_fill_system_possible_inferiors(struct dsdb_schema *schema, st if (c2->objectClassCategory != 2 && c2->objectClassCategory != 3 && str_list_check(superiors, schema_class->lDAPDisplayName)) { - if (schema_class->possibleInferiors == NULL) { + if (schema_class->systemPossibleInferiors == NULL) { schema_class->systemPossibleInferiors = str_list_make_empty(schema_class); } schema_class->systemPossibleInferiors = str_list_add_const(schema_class->systemPossibleInferiors, -- cgit From c9f70fc3c7a6a44696a64ca40eca6e1995db35b9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 10 Oct 2009 09:10:03 +1100 Subject: s4:dsdb Search for the schema with dsdb_module_search(), in schema_fsmo This avoids using an ldb_search(), which would run from the top of the module stack. This will help us load the schema before the partitions are initialised. Andrew Bartlett --- source4/dsdb/schema/schema_init.c | 111 +------------------------------------- 1 file changed, 1 insertion(+), 110 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index b876ab09fc..74cf53d8f1 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -906,7 +906,7 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema, /* Create a DSDB schema from the ldb results provided. This is called directly when the schema is provisioned from an on-disk LDIF file, or - from dsdb_schema_from_schema_dn below + from dsdb_schema_from_schema_dn in schema_fsmo */ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, @@ -1013,115 +1013,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return LDB_SUCCESS; } -/* - Given an LDB, and the DN, return a populated schema -*/ - -int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, - struct smb_iconv_convenience *iconv_convenience, - struct ldb_dn *schema_dn, - struct dsdb_schema **schema, - char **error_string_out) -{ - TALLOC_CTX *tmp_ctx; - char *error_string; - int ret; - - struct ldb_result *schema_res; - struct ldb_result *a_res; - struct ldb_result *c_res; - static const char *schema_attrs[] = { - "prefixMap", - "schemaInfo", - "fSMORoleOwner", - NULL - }; - unsigned flags; - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) { - dsdb_oom(error_string_out, mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* we don't want to trace the schema load */ - flags = ldb_get_flags(ldb); - ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING); - - /* - * setup the prefix mappings and schema info - */ - ret = ldb_search(ldb, tmp_ctx, &schema_res, - schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL); - if (ret == LDB_ERR_NO_SUCH_OBJECT) { - goto failed; - } else if (ret != LDB_SUCCESS) { - *error_string_out = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to search the schema head: %s", - ldb_errstring(ldb)); - goto failed; - } - if (schema_res->count != 1) { - *error_string_out = talloc_asprintf(mem_ctx, - "dsdb_schema: [%u] schema heads found on a base search", - schema_res->count); - goto failed; - } - - /* - * load the attribute definitions - */ - ret = ldb_search(ldb, tmp_ctx, &a_res, - schema_dn, LDB_SCOPE_ONELEVEL, NULL, - "(objectClass=attributeSchema)"); - if (ret != LDB_SUCCESS) { - *error_string_out = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to search attributeSchema objects: %s", - ldb_errstring(ldb)); - goto failed; - } - - /* - * load the objectClass definitions - */ - ret = ldb_search(ldb, tmp_ctx, &c_res, - schema_dn, LDB_SCOPE_ONELEVEL, NULL, - "(objectClass=classSchema)"); - if (ret != LDB_SUCCESS) { - *error_string_out = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to search attributeSchema objects: %s", - ldb_errstring(ldb)); - goto failed; - } - - ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb, - lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), - schema_res, a_res, c_res, schema, &error_string); - if (ret != LDB_SUCCESS) { - *error_string_out = talloc_asprintf(mem_ctx, - "dsdb_schema load failed: %s", - error_string); - goto failed; - } - talloc_steal(mem_ctx, *schema); - talloc_free(tmp_ctx); - - if (flags & LDB_FLG_ENABLE_TRACING) { - flags = ldb_get_flags(ldb); - ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING); - } - - return LDB_SUCCESS; - -failed: - if (flags & LDB_FLG_ENABLE_TRACING) { - flags = ldb_get_flags(ldb); - ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING); - } - talloc_free(tmp_ctx); - return ret; -} - static const struct { const char *name; -- cgit From aee3c190156ed6f644535ab62ffe72b74e611b43 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Oct 2009 13:10:00 +1100 Subject: s4:dsdb Make dsdb_read_prefixes_from_ldb static --- source4/dsdb/schema/schema_init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 74cf53d8f1..9dd3ce0ccc 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -30,6 +30,8 @@ #include "param/param.h" #include "lib/ldb/include/ldb_module.h" +static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes); + struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience) { struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema); @@ -519,7 +521,7 @@ WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_co return WERR_OK; } -WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes) +static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes) { struct prefixMapBlob *blob; enum ndr_err_code ndr_err; -- cgit From d511d889a09dee93338d93fcef22625089ae110c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Oct 2009 13:17:09 +1100 Subject: s4:schema Add some error checking to the schema load --- source4/dsdb/schema/schema_inferiors.c | 27 +++++++++++++++++++++------ source4/dsdb/schema/schema_set.c | 5 ++++- 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index 3be97b6b83..ecac74a954 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -149,19 +149,22 @@ void schema_subclasses_order_recurse(struct dsdb_schema *schema, struct dsdb_cla return; } -static void schema_create_subclasses(struct dsdb_schema *schema) +static int schema_create_subclasses(struct dsdb_schema *schema) { - struct dsdb_class *schema_class; + struct dsdb_class *schema_class, *top; for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf); if (schema_class2 == NULL) { DEBUG(0,("ERROR: no subClassOf for '%s'\n", schema_class->lDAPDisplayName)); - continue; + return LDB_ERR_OPERATIONS_ERROR; } if (schema_class2 && schema_class != schema_class2) { if (schema_class2->subclasses_direct == NULL) { schema_class2->subclasses_direct = str_list_make_empty(schema_class2); + if (!schema_class2->subclasses_direct) { + return LDB_ERR_OPERATIONS_ERROR; + } } schema_class2->subclasses_direct = str_list_add_const(schema_class2->subclasses_direct, schema_class->lDAPDisplayName); @@ -175,7 +178,14 @@ static void schema_create_subclasses(struct dsdb_schema *schema) schema_class->subClass_order = 0; } - schema_subclasses_order_recurse(schema, dsdb_class_by_lDAPDisplayName(schema, "top"), 1); + top = dsdb_class_by_lDAPDisplayName(schema, "top"); + if (!top) { + DEBUG(0,("ERROR: no 'top' class in loaded schema\n")); + return LDB_ERR_OPERATIONS_ERROR; + } + + schema_subclasses_order_recurse(schema, top, 1); + return LDB_SUCCESS; } static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class) @@ -294,13 +304,17 @@ static void schema_fill_from_ids(struct dsdb_schema *schema) } } -void schema_fill_constructed(struct dsdb_schema *schema) +int schema_fill_constructed(struct dsdb_schema *schema) { + int ret; struct dsdb_class *schema_class; schema_fill_from_ids(schema); - schema_create_subclasses(schema); + ret = schema_create_subclasses(schema); + if (ret != LDB_SUCCESS) { + return ret; + } for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { schema_fill_possible_inferiors(schema, schema_class); @@ -318,4 +332,5 @@ void schema_fill_constructed(struct dsdb_schema *schema) schema_class->subclasses = NULL; schema_class->posssuperiors = NULL; } + return LDB_SUCCESS; } diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 6f09f63596..9f22b32334 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -346,7 +346,10 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) return ret; } - schema_fill_constructed(schema); + ret = schema_fill_constructed(schema); + if (ret != LDB_SUCCESS) { + return ret; + } ret = ldb_set_opaque(ldb, "dsdb_schema", schema); if (ret != LDB_SUCCESS) { -- cgit From 40a8a2268454a55103c5c675d6fc07efa3cb6f31 Mon Sep 17 00:00:00 2001 From: Kamen Mazdrashki Date: Sun, 11 Oct 2009 21:00:55 +0300 Subject: s4/drs: Propagate redefinition of drsuapi_DsReplicaOID into code base The biggest change is that 'oid' field is transmited in binary format. Also the field name is changed to 'binary_oid' so that field format to be clear for callers. After those changes, Samba4 should work the way it works before - i.e. no added value here but we should not fail when partial-oid is part of prefixMap transmited from Win server. Also, thre is a bug in this patch - partial-binary-OIDs are not handled correctly. Partial-binary-OIDs received during replication will be encoded, but not handled correctly. --- source4/dsdb/schema/schema_init.c | 166 ++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 61 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 9dd3ce0ccc..f8b7d5dd44 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -29,6 +29,7 @@ #include "librpc/gen_ndr/ndr_drsblobs.h" #include "param/param.h" #include "lib/ldb/include/ldb_module.h" +#include "../lib/util/asn1.h" static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes); @@ -52,11 +53,11 @@ WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct d W_ERROR_HAVE_NO_MEMORY(schema->prefixes); for (i=0, j=0; i < ctr->num_mappings; i++) { - if (ctr->mappings[i].oid.oid == NULL) { + if (ctr->mappings[i].oid.binary_oid == NULL) { return WERR_INVALID_PARAM; } - if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) { + if (ctr->mappings[i].oid.binary_oid[0] == 0xFF) { if (ctr->mappings[i].id_prefix != 0) { return WERR_INVALID_PARAM; } @@ -66,21 +67,33 @@ WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct d return WERR_INVALID_PARAM; } - if (ctr->mappings[i].oid.__ndr_size != 21) { + if (ctr->mappings[i].oid.length != 21) { return WERR_INVALID_PARAM; } - schema->schema_info = talloc_strdup(schema, ctr->mappings[i].oid.oid); + schema->schema_info = hex_encode_talloc(schema, + ctr->mappings[i].oid.binary_oid, + ctr->mappings[i].oid.length); W_ERROR_HAVE_NO_MEMORY(schema->schema_info); } else { + DATA_BLOB oid_blob; + const char *partial_oid = NULL; + /* the last array member should contain the magic value not a oid */ if (i == (ctr->num_mappings - 1)) { return WERR_INVALID_PARAM; } + oid_blob = data_blob_const(ctr->mappings[i].oid.binary_oid, + ctr->mappings[i].oid.length); + if (!ber_read_partial_OID_String(schema->prefixes, oid_blob, &partial_oid)) { + DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X", + ctr->mappings[i].id_prefix)); + return WERR_INVALID_PARAM; + } + schema->prefixes[j].id = ctr->mappings[i].id_prefix<<16; - schema->prefixes[j].oid = talloc_asprintf(schema->prefixes, "%s.", - ctr->mappings[i].oid.oid); + schema->prefixes[j].oid = partial_oid; W_ERROR_HAVE_NO_MEMORY(schema->prefixes[j].oid); schema->prefixes[j].oid_len = strlen(schema->prefixes[j].oid); j++; @@ -98,7 +111,7 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema, WERROR status; enum ndr_err_code ndr_err; struct prefixMapBlob pfm; - char *schema_info; + DATA_BLOB schema_info_blob; TALLOC_CTX *mem_ctx = talloc_new(schema); W_ERROR_HAVE_NO_MEMORY(mem_ctx); @@ -127,12 +140,12 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema, pfm.ctr.dsdb.num_mappings); W_ERROR_HAVE_NO_MEMORY(pfm.ctr.dsdb.mappings); - schema_info = data_blob_hex_string(pfm.ctr.dsdb.mappings, schemaInfo); - W_ERROR_HAVE_NO_MEMORY(schema_info); + schema_info_blob = data_blob_dup_talloc(pfm.ctr.dsdb.mappings, schemaInfo); + W_ERROR_HAVE_NO_MEMORY(schema_info_blob.data); pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].id_prefix = 0; - pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.__ndr_size = schemaInfo->length; - pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.oid = schema_info; + pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.length = schemaInfo->length; + pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.binary_oid = schema_info_blob.data; /* call the drsuapi version */ status = dsdb_load_oid_mappings_drsuapi(schema, &pfm.ctr.dsdb); @@ -148,6 +161,7 @@ WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr) { + DATA_BLOB oid_blob; struct drsuapi_DsReplicaOIDMapping_Ctr *ctr; uint32_t i; @@ -160,18 +174,23 @@ WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema, W_ERROR_HAVE_NO_MEMORY(ctr->mappings); for (i=0; i < schema->num_prefixes; i++) { + if (!ber_write_partial_OID_String(ctr->mappings, &oid_blob, schema->prefixes[i].oid)) { + DEBUG(0, ("write_partial_OID failed for %s", schema->prefixes[i].oid)); + return WERR_INTERNAL_ERROR; + } + ctr->mappings[i].id_prefix = schema->prefixes[i].id>>16; - ctr->mappings[i].oid.oid = talloc_strndup(ctr->mappings, - schema->prefixes[i].oid, - schema->prefixes[i].oid_len - 1); - W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid); + ctr->mappings[i].oid.length = oid_blob.length; + ctr->mappings[i].oid.binary_oid = oid_blob.data; } if (include_schema_info) { + oid_blob = strhex_to_data_blob(ctr->mappings, schema->schema_info); + W_ERROR_HAVE_NO_MEMORY(oid_blob.data); + ctr->mappings[i].id_prefix = 0; - ctr->mappings[i].oid.oid = talloc_strdup(ctr->mappings, - schema->schema_info); - W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid); + ctr->mappings[i].oid.length = oid_blob.length; + ctr->mappings[i].oid.binary_oid = oid_blob.data; } *_ctr = ctr; @@ -211,13 +230,14 @@ WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema, WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr) { uint32_t i,j; + DATA_BLOB oid_blob; for (i=0; i < ctr->num_mappings; i++) { - if (ctr->mappings[i].oid.oid == NULL) { + if (ctr->mappings[i].oid.binary_oid == NULL) { return WERR_INVALID_PARAM; } - if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) { + if (ctr->mappings[i].oid.binary_oid[0] == 0xFF) { if (ctr->mappings[i].id_prefix != 0) { return WERR_INVALID_PARAM; } @@ -227,13 +247,19 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const return WERR_INVALID_PARAM; } - if (ctr->mappings[i].oid.__ndr_size != 21) { + if (ctr->mappings[i].oid.length != 21) { return WERR_INVALID_PARAM; } - if (strcasecmp(schema->schema_info, ctr->mappings[i].oid.oid) != 0) { + oid_blob = strhex_to_data_blob(NULL, schema->schema_info); + W_ERROR_HAVE_NO_MEMORY(oid_blob.data); + + if (memcmp(oid_blob.data, ctr->mappings[i].oid.binary_oid, 21) != 0) { + data_blob_free(&oid_blob); return WERR_DS_DRA_SCHEMA_MISMATCH; } + + data_blob_free(&oid_blob); } else { /* the last array member should contain the magic value not a oid */ if (i == (ctr->num_mappings - 1)) { @@ -241,21 +267,26 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const } for (j=0; j < schema->num_prefixes; j++) { - size_t oid_len; if (schema->prefixes[j].id != (ctr->mappings[i].id_prefix<<16)) { continue; } - oid_len = strlen(ctr->mappings[i].oid.oid); + if (!ber_write_partial_OID_String(NULL, &oid_blob, schema->prefixes[j].oid)) { + return WERR_INTERNAL_ERROR; + } - if (oid_len != (schema->prefixes[j].oid_len - 1)) { + if (oid_blob.length != ctr->mappings[j].oid.length) { + data_blob_free(&oid_blob); return WERR_DS_DRA_SCHEMA_MISMATCH; } - if (strncmp(ctr->mappings[i].oid.oid, schema->prefixes[j].oid, oid_len) != 0) { - return WERR_DS_DRA_SCHEMA_MISMATCH; + if (memcmp(ctr->mappings[i].oid.binary_oid, oid_blob.data, oid_blob.length) != 0) { + data_blob_free(&oid_blob); + return WERR_DS_DRA_SCHEMA_MISMATCH; } + data_blob_free(&oid_blob); + break; } @@ -284,7 +315,7 @@ WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CT continue; } - val = talloc_asprintf(mem_ctx, "%s%u", + val = talloc_asprintf(mem_ctx, "%s.%u", schema->prefixes[i].oid, in & 0xFFFF); W_ERROR_HAVE_NO_MEMORY(val); @@ -391,8 +422,6 @@ WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struc DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n")); return WERR_FOOBAR; } - /* Add one because we need to copy the dot */ - size += 1; /* Create a spot in the prefixMap for one more prefix*/ (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes); @@ -412,37 +441,33 @@ WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struc WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out) { uint32_t i; + char *oid_prefix; + char *pstr; + char *end_str; + unsigned val; - for (i=0; i < num_prefixes; i++) { - const char *val_str; - char *end_str; - unsigned val; - - if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) { - continue; - } + /* make oid prefix, i.e. oid w/o last subidentifier */ + pstr = strrchr(in, '.'); + if (!pstr) return WERR_INVALID_PARAM; + if (pstr < in) return WERR_INVALID_PARAM; + if ((pstr - in) < 4) return WERR_INVALID_PARAM; - val_str = in + prefixes[i].oid_len; - end_str = NULL; - errno = 0; + oid_prefix = talloc_strndup(0, in, pstr - in); - if (val_str[0] == '\0') { - return WERR_INVALID_PARAM; + for (i=0; i < num_prefixes; i++) { + if (strcmp(prefixes[i].oid, oid_prefix) == 0) { + break; } + } - /* two '.' chars are invalid */ - if (val_str[0] == '.') { - return WERR_INVALID_PARAM; - } + talloc_free(oid_prefix); - val = strtoul(val_str, &end_str, 10); - if (end_str[0] == '.' && end_str[1] != '\0') { - /* - * if it's a '.' and not the last char - * then maybe an other mapping apply - */ - continue; - } else if (end_str[0] != '\0') { + if (i < num_prefixes) { + /* move next to '.' char */ + pstr++; + + val = strtoul(pstr, &end_str, 10); + if (end_str[0] != '\0') { return WERR_INVALID_PARAM; } else if (val > 0xFFFF) { return WERR_INVALID_PARAM; @@ -489,8 +514,16 @@ WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_co } for (i=0; i < schema->num_prefixes; i++) { - pm.ctr.dsdb.mappings[i].id_prefix = schema->prefixes[i].id>>16; - pm.ctr.dsdb.mappings[i].oid.oid = talloc_strdup(pm.ctr.dsdb.mappings, schema->prefixes[i].oid); + DATA_BLOB oid_blob; + + if (!ber_write_partial_OID_String(pm.ctr.dsdb.mappings, &oid_blob, schema->prefixes[i].oid)) { + DEBUG(0, ("write_partial_OID failed for %s", schema->prefixes[i].oid)); + return WERR_INTERNAL_ERROR; + } + + pm.ctr.dsdb.mappings[i].id_prefix = schema->prefixes[i].id>>16; + pm.ctr.dsdb.mappings[i].oid.length = oid_blob.length; + pm.ctr.dsdb.mappings[i].oid.binary_oid = oid_blob.data; } ndr_err = ndr_push_struct_blob(&ndr_blob, msg, @@ -528,7 +561,7 @@ static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_contex uint32_t i; const struct ldb_val *prefix_val; struct ldb_dn *schema_dn; - struct ldb_result *schema_res; + struct ldb_result *schema_res = NULL; int ret; static const char *schema_attrs[] = { "prefixMap", @@ -588,10 +621,21 @@ static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_contex return WERR_NOMEM; } for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { - char *oid; + DATA_BLOB oid_blob; + const char *partial_oid; + + oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid, + blob->ctr.dsdb.mappings[i].oid.length); + + if (!ber_read_partial_OID_String(mem_ctx, oid_blob, &partial_oid)) { + DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X", + blob->ctr.dsdb.mappings[i].id_prefix)); + talloc_free(blob); + return WERR_INVALID_PARAM; + } + (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16; - oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid); - (*prefixes)[i].oid = talloc_asprintf_append(oid, "."); + (*prefixes)[i].oid = partial_oid; (*prefixes)[i].oid_len = strlen((*prefixes)[i].oid); } -- cgit From 784e0c199e8b083865ac96930c3b55d709a2bec5 Mon Sep 17 00:00:00 2001 From: Kamen Mazdrashki Date: Thu, 8 Oct 2009 02:55:28 +0300 Subject: s4/drs: prefixMap module initial definition --- source4/dsdb/schema/prefixmap.h | 45 ++++++++++++++++++++++++++++++++++ source4/dsdb/schema/schema_prefixmap.c | 22 +++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 source4/dsdb/schema/prefixmap.h create mode 100644 source4/dsdb/schema/schema_prefixmap.c (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/prefixmap.h b/source4/dsdb/schema/prefixmap.h new file mode 100644 index 0000000000..7b28c88749 --- /dev/null +++ b/source4/dsdb/schema/prefixmap.h @@ -0,0 +1,45 @@ +/* + Unix SMB/CIFS implementation. + + DRS::prefixMap data structures + + Copyright (C) Kamen Mazdrashki 2009 + + 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 . +*/ + +#ifndef _DSDB_PREFIXMAP_H +#define _DSDB_PREFIXMAP_H + +/** + * oid-prefix in prefixmap + */ +struct dsdb_schema_prefixmap_oid { + uint32_t id; + DATA_BLOB *bin_oid; /* partial binary-oid prefix */ +}; + +/** + * DSDB prefixMap internal presentation + */ +struct dsdb_schema_prefixmap { + uint32_t length; + struct dsdb_schema_prefixmap_oid *prefixes; +}; + + +#include "dsdb/schema/proto.h" + + +#endif /* _DSDB_PREFIXMAP_H */ diff --git a/source4/dsdb/schema/schema_prefixmap.c b/source4/dsdb/schema/schema_prefixmap.c new file mode 100644 index 0000000000..d24c5add00 --- /dev/null +++ b/source4/dsdb/schema/schema_prefixmap.c @@ -0,0 +1,22 @@ +/* + Unix SMB/CIFS implementation. + + DRS::prefixMap implementation + + Copyright (C) Kamen Mazdrashki 2009 + + 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 . +*/ + +#include "includes.h" -- cgit