From f0d43e9e562bfd7c254a9b2446fb11f85186b45e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Nov 2009 17:04:10 +1100 Subject: [PATCH] s4:dsdb Use new dsdb_dn code in LDB modules and Samba4 schema This converts the code from using the binary DN code in ldb_dn to using a special Samba-specfic wrapper around ldb_dn. We also use the dsdb_dn code for DN+Binary and DN+String comparisons (changed from treating them as Binary blobs) Andrew Bartlett --- .../dsdb/samdb/ldb_modules/extended_dn_out.c | 36 ++++++--- .../samdb/ldb_modules/extended_dn_store.c | 81 +++++++++++-------- source4/dsdb/schema/schema_syntax.c | 34 ++++---- source4/lib/ldb-samba/ldif_handlers.c | 12 +++ 4 files changed, 99 insertions(+), 64 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c index cbbf8c60781..c4ddf6781f5 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c @@ -2,7 +2,7 @@ ldb database library Copyright (C) Simo Sorce 2005-2008 - Copyright (C) Andrew Bartlett 2007-2008 + Copyright (C) Andrew Bartlett 2007-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 @@ -420,21 +420,30 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, } /* Look to see if this attributeSyntax is a DN */ - if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0 && - strcmp(attribute->attributeSyntax_oid, "2.5.5.7") != 0) { + if (dsdb_dn_oid_to_format(attribute->syntax->ldap_oid) == DSDB_INVALID_DN) { continue; } for (j = 0; j < msg->elements[i].num_values; j++) { const char *dn_str; - struct ldb_dn *dn = ldb_dn_from_ldb_val(ac, ldb_module_get_ctx(ac->module), &msg->elements[i].values[j]); - if (!dn || !ldb_dn_validate(dn)) { + struct ldb_dn *dn; + struct dsdb_dn *dsdb_dn = NULL; + struct ldb_val *plain_dn = &msg->elements[i].values[j]; + dsdb_dn = dsdb_dn_parse(msg, ldb_module_get_ctx(ac->module), plain_dn, attribute->syntax->ldap_oid); + + if (!dsdb_dn || !ldb_dn_validate(dsdb_dn->dn)) { + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "could not parse %.*s as a %s DN", (int)plain_dn->length, plain_dn->data, + attribute->syntax->ldap_oid); + talloc_free(dsdb_dn); return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX); } + dn = dsdb_dn->dn; if (p->normalise) { ret = fix_dn(dn); if (ret != LDB_SUCCESS) { + talloc_free(dsdb_dn); return ldb_module_done(ac->req, NULL, NULL, ret); } } @@ -453,24 +462,26 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, msg->elements[i].name, &msg->elements[i].values[j]); if (ret != LDB_SUCCESS) { + talloc_free(dsdb_dn); return ldb_module_done(ac->req, NULL, NULL, ret); } } if (!ac->inject) { - dn_str = talloc_steal(msg->elements[i].values, - ldb_dn_get_linearized(dn)); + dn_str = dsdb_dn_get_linearized(msg->elements[i].values, + dsdb_dn); } else { - dn_str = talloc_steal(msg->elements[i].values, - ldb_dn_get_extended_linearized(msg->elements[i].values, - dn, ac->extended_type)); + dn_str = dsdb_dn_get_extended_linearized(msg->elements[i].values, + dsdb_dn, ac->extended_type); } + if (!dn_str) { ldb_oom(ldb_module_get_ctx(ac->module)); + talloc_free(dsdb_dn); return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); } msg->elements[i].values[j] = data_blob_string_const(dn_str); - talloc_free(dn); + talloc_free(dsdb_dn); } } return ldb_module_send_entry(ac->req, msg, ares->controls); @@ -717,8 +728,7 @@ static int extended_dn_out_dereference_init(struct ldb_module *module, const cha } for (cur = schema->attributes; cur; cur = cur->next) { - if (strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.1") != 0 && - strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.7") != 0) { + if (dsdb_dn_oid_to_format(cur->syntax->ldap_oid) == DSDB_INVALID_DN) { continue; } dereference_control->dereference diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c index 122a9bb2b7d..ef8532c82ae 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c @@ -2,7 +2,7 @@ ldb database library Copyright (C) Simo Sorce 2005-2008 - Copyright (C) Andrew Bartlett 2007-2008 + Copyright (C) Andrew Bartlett 2007-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 @@ -47,7 +47,7 @@ struct extended_dn_replace_list { struct extended_dn_replace_list *next; - struct ldb_dn *dn; + struct dsdb_dn *dsdb_dn; TALLOC_CTX *mem_ctx; struct ldb_val *replace_dn; struct extended_dn_context *ac; @@ -157,12 +157,20 @@ static int extended_replace_dn(struct ldb_request *req, struct ldb_reply *ares) * search. We can't check, as it could be an extended * DN, so a module below will resolve it */ struct ldb_dn *dn = ares->message->dn; - - /* Replace the DN with the extended version of the DN - * (ie, add SID and GUID) */ - *os->replace_dn = data_blob_string_const( - ldb_dn_get_extended_linearized(os->mem_ctx, - dn, 1)); + + /* Rebuild with the string or binary 'extra part' the + * DN may have had as a prefix */ + struct dsdb_dn *dsdb_dn = dsdb_dn_construct(ares, dn, + os->dsdb_dn->extra_part, + os->dsdb_dn->oid); + if (dsdb_dn) { + /* Replace the DN with the extended version of the DN + * (ie, add SID and GUID) */ + *os->replace_dn = data_blob_string_const( + dsdb_dn_get_extended_linearized(os->mem_ctx, + dsdb_dn, 1)); + talloc_free(dsdb_dn); + } if (os->replace_dn->data == NULL) { return ldb_module_done(os->ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); @@ -209,7 +217,9 @@ static int extended_replace_dn(struct ldb_request *req, struct ldb_reply *ares) static int extended_store_replace(struct extended_dn_context *ac, TALLOC_CTX *callback_mem_ctx, - struct ldb_val *plain_dn) + struct ldb_val *plain_dn, + bool is_delete, + const char *oid) { int ret; struct extended_dn_replace_list *os; @@ -228,14 +238,25 @@ static int extended_store_replace(struct extended_dn_context *ac, os->mem_ctx = callback_mem_ctx; - os->dn = ldb_dn_from_ldb_val(os, ldb_module_get_ctx(ac->module), plain_dn); - if (!os->dn || !ldb_dn_validate(os->dn)) { + os->dsdb_dn = dsdb_dn_parse(os, ldb_module_get_ctx(ac->module), plain_dn, oid); + if (!os->dsdb_dn || !ldb_dn_validate(os->dsdb_dn->dn)) { talloc_free(os); ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), - "could not parse %.*s as a DN", (int)plain_dn->length, plain_dn->data); + "could not parse %.*s as a %s DN", (int)plain_dn->length, plain_dn->data, + oid); return LDB_ERR_INVALID_DN_SYNTAX; } + if (is_delete && !ldb_dn_has_extended(os->dsdb_dn->dn)) { + /* NO need to figure this DN out, this element is + * going to be deleted anyway, and becuase it's not + * extended, we have enough information to do the + * delete */ + talloc_free(os); + return LDB_SUCCESS; + } + + os->replace_dn = plain_dn; /* The search request here might happen to be for an @@ -243,7 +264,7 @@ static int extended_store_replace(struct extended_dn_context *ac, * module in the stack will convert this into a normal DN for * processing */ ret = ldb_build_search_req(&os->search_req, - ldb_module_get_ctx(ac->module), os, os->dn, LDB_SCOPE_BASE, NULL, + ldb_module_get_ctx(ac->module), os, os->dsdb_dn->dn, LDB_SCOPE_BASE, NULL, attrs, NULL, os, extended_replace_dn, ac->req); @@ -302,9 +323,8 @@ static int extended_dn_add(struct ldb_module *module, struct ldb_request *req) continue; } - /* We only setup an extended DN GUID on these particular DN objects */ - if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 && - strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) { + /* We only setup an extended DN GUID on DN elements */ + if (dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid) == DSDB_INVALID_DN) { continue; } @@ -324,14 +344,15 @@ static int extended_dn_add(struct ldb_module *module, struct ldb_request *req) /* Re-calculate el */ el = &ac->new_req->op.add.message->elements[i]; for (j = 0; j < el->num_values; j++) { - ret = extended_store_replace(ac, ac->new_req->op.add.message->elements, &el->values[j]); + ret = extended_store_replace(ac, ac->new_req->op.add.message->elements, &el->values[j], + false, schema_attr->syntax->ldap_oid); if (ret != LDB_SUCCESS) { return ret; } } } - /* if DNs were set continue */ + /* if no DNs were set continue */ if (ac->ops == NULL) { talloc_free(ac); return ldb_next_request(module, req); @@ -377,11 +398,10 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req } /* We only setup an extended DN GUID on these particular DN objects */ - if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 && - strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) { + if (dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid) == DSDB_INVALID_DN) { continue; } - + /* Before we setup a procedure to modify the incoming message, we must copy it */ if (!ac->new_req) { struct ldb_message *msg = ldb_msg_copy(ac, req->op.mod.message); @@ -399,17 +419,14 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req el = &ac->new_req->op.mod.message->elements[i]; /* For each value being added, we need to setup the lookups to fill in the extended DN */ for (j = 0; j < el->num_values; j++) { - struct ldb_dn *dn = ldb_dn_from_ldb_val(ac, ldb_module_get_ctx(module), &el->values[j]); - if (!dn || !ldb_dn_validate(dn)) { - ldb_asprintf_errstring(ldb_module_get_ctx(module), - "could not parse attribute %s as a DN", el->name); - return LDB_ERR_INVALID_DN_SYNTAX; - } - if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE) && !ldb_dn_has_extended(dn)) { - /* NO need to figure this DN out, it's going to be deleted anyway */ - continue; - } - ret = extended_store_replace(ac, req->op.mod.message->elements, &el->values[j]); + /* If we are just going to delete this + * element, only do a lookup if + * extended_store_replace determines it's an + * input of an extended DN */ + bool is_delete = ((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE); + + ret = extended_store_replace(ac, req->op.mod.message->elements, &el->values[j], + is_delete, schema_attr->syntax->ldap_oid); if (ret != LDB_SUCCESS) { return ret; } diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index 65baaeb070b..d50044acd07 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -1229,6 +1229,7 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, enum ndr_err_code ndr_err; DATA_BLOB guid_blob; struct ldb_dn *dn; + struct dsdb_dn *dsdb_dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { W_ERROR_HAVE_NO_MEMORY(tmp_ctx); @@ -1296,9 +1297,9 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, } /* set binary stuff */ - ldb_dn_set_binary(dn, &id3.binary); + dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid); - out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1)); + out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1)); talloc_free(tmp_ctx); } @@ -1333,17 +1334,20 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, struct drsuapi_DsReplicaObjectIdentifier3Binary id3; enum ndr_err_code ndr_err; const DATA_BLOB *guid_blob, *sid_blob; - struct ldb_dn *dn; + struct dsdb_dn *dsdb_dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); out->value_ctr.values[i].blob = &blobs[i]; - dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]); + dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid); - W_ERROR_HAVE_NO_MEMORY(dn); + if (dsdb_dn) { + talloc_free(tmp_ctx); + return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER); + } - guid_blob = ldb_dn_get_extended_component(dn, "GUID"); + guid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "GUID"); ZERO_STRUCT(id3); @@ -1358,7 +1362,7 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, } } - sid_blob = ldb_dn_get_extended_component(dn, "SID"); + sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID"); if (sid_blob) { ndr_err = ndr_pull_struct_blob_all(sid_blob, @@ -1371,16 +1375,10 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, } } - 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++; - } + id3.dn = ldb_dn_get_linearized(dsdb_dn->dn); /* get binary stuff */ - ldb_dn_get_binary(dn, &id3.binary); + id3.binary = dsdb_dn->extra_part; 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)) { @@ -1661,7 +1659,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .comment = "Object(DS-DN) == a DN", },{ .name = "Object(DN-Binary)", - .ldap_oid = "1.2.840.113556.1.4.903", + .ldap_oid = DSDB_SYNTAX_BINARY_DN, .oMSyntax = 127, .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"), .attributeSyntax_oid = "2.5.5.7", @@ -1669,7 +1667,6 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .ldb_to_drsuapi = dsdb_syntax_DN_BINARY_ldb_to_drsuapi, .equality = "octetStringMatch", .comment = "OctetString: Binary+DN", - .ldb_syntax = LDB_SYNTAX_OCTET_STRING, },{ /* not used in w2k3 schema */ .name = "Object(OR-Name)", @@ -1716,7 +1713,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { },{ /* not used in w2k3 schema */ .name = "Object(DN-String)", - .ldap_oid = "1.2.840.113556.1.4.904", + .ldap_oid = DSDB_SYNTAX_STRING_DN, .oMSyntax = 127, .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"), .attributeSyntax_oid = "2.5.5.14", @@ -1724,7 +1721,6 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .ldb_to_drsuapi = dsdb_syntax_DN_BINARY_ldb_to_drsuapi, .equality = "octetStringMatch", .comment = "OctetString: String+DN", - .ldb_syntax = LDB_SYNTAX_OCTET_STRING, } }; diff --git a/source4/lib/ldb-samba/ldif_handlers.c b/source4/lib/ldb-samba/ldif_handlers.c index f716fa676ef..f2c985e81a2 100644 --- a/source4/lib/ldb-samba/ldif_handlers.c +++ b/source4/lib/ldb-samba/ldif_handlers.c @@ -810,6 +810,18 @@ static const struct ldb_schema_syntax samba_syntaxes[] = { .ldif_write_fn = ldif_write_replUpToDateVector, .canonicalise_fn = ldb_handler_copy, .comparison_fn = ldb_comparison_binary + },{ + .name = DSDB_SYNTAX_BINARY_DN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = dsdb_dn_binary_canonicalise, + .comparison_fn = dsdb_dn_binary_comparison + },{ + .name = DSDB_SYNTAX_STRING_DN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = dsdb_dn_string_canonicalise, + .comparison_fn = dsdb_dn_string_comparison }, }; -- 2.34.1