s4:dsdb Use new dsdb_dn code in LDB modules and Samba4 schema
authorAndrew Bartlett <abartlet@samba.org>
Thu, 5 Nov 2009 06:04:10 +0000 (17:04 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 11 Nov 2009 21:11:17 +0000 (08:11 +1100)
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

source4/dsdb/samdb/ldb_modules/extended_dn_out.c
source4/dsdb/samdb/ldb_modules/extended_dn_store.c
source4/dsdb/schema/schema_syntax.c
source4/lib/ldb-samba/ldif_handlers.c

index cbbf8c60781129524082a615c511e589c88fabc1..c4ddf6781f5c8d1aad1f4894c871224c71e71020 100644 (file)
@@ -2,7 +2,7 @@
    ldb database library
 
    Copyright (C) Simo Sorce 2005-2008
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2008
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 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
index 122a9bb2b7d648897674fa53ce9ee1818f94d023..ef8532c82aecd8b5dfb9c88b19c01ec0ead94e49 100644 (file)
@@ -2,7 +2,7 @@
    ldb database library
 
    Copyright (C) Simo Sorce 2005-2008
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2008
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 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;
                        }
index 65baaeb070b23c1427d58f59b1cf863058d6de21..d50044acd078a8cf1bfa9e6eab7c96b1a88606db 100644 (file)
@@ -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,
        }
 };
 
index f716fa676ef87062d484355e4f09424259f08a5c..f2c985e81a2075ca9d444c1ffa58fddef791ff0b 100644 (file)
@@ -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
        },
 };