r16066: The OSX AD plugin uses objectCategory searches a lot, and uses them
authorAndrew Bartlett <abartlet@samba.org>
Tue, 6 Jun 2006 22:04:55 +0000 (22:04 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:08:55 +0000 (14:08 -0500)
both fully qualified and in the 'short' form.  Now we test and support
this query format.

Andrew Bartlett
(This used to be commit 9ddcfacbcedc5eea2730d4bf902c0fcd02bcfa11)

source4/lib/ldb/common/ldb_attributes.c
source4/lib/ldb/common/ldb_match.c
source4/lib/ldb/samba/ldif_handlers.c
testprogs/ejs/ldap.js

index 679a05f244001a8cff38d66805677ed5b5e74c51..13e721a266eab6c0bf1932bc565b20bbc6db462f 100644 (file)
@@ -166,7 +166,6 @@ int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
                { "dn", LDB_SYNTAX_DN },
                { "ncName", LDB_SYNTAX_DN },
                { "distinguishedName", LDB_SYNTAX_DN },
-               { "objectCategory", LDB_SYNTAX_DN },
                { "cn", LDB_SYNTAX_DIRECTORY_STRING },
                { "dc", LDB_SYNTAX_DIRECTORY_STRING },
                { "ou", LDB_SYNTAX_DIRECTORY_STRING },
index 810191c5ec367932ea055c5a61eb584a9a510f77..f3ecbe0381594456c35de21fe84e4d2e0193fd95 100644 (file)
@@ -207,8 +207,11 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
                chunk = tree->u.substring.chunks[c];
                if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
 
-               /* FIXME: case of embedded nulls */
-               if (strncmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed;
+               /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
+               if (cnk.length > val.length) {
+                       goto failed;
+               }
+               if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed;
                val.length -= cnk.length;
                val.data += cnk.length;
                c++;
index e84dfea60047ea2adf3666da3735793fba13b04d..28bc5ea997df46a35eeb1f9367364e2f1776d6b2 100644 (file)
@@ -1,8 +1,8 @@
 /* 
    ldb database library - ldif handlers for Samba
 
-   Copyright (C) Andrew Tridgell  2005
-
+   Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Andrew Bartlett 2006
      ** NOTE! The following LGPL license applies to the ldb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
@@ -275,6 +275,75 @@ static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ct
        return 0;
 }
 
+/* 
+   canonicolise an objectCategory.  We use the short form as the cannoical form:
+   cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
+*/
+
+static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
+                                           const struct ldb_val *in, struct ldb_val *out)
+{
+       struct ldb_dn *dn1 = NULL;
+       const char *oc1;
+
+       dn1 = ldb_dn_explode(mem_ctx, (char *)in->data);
+       if (dn1 == NULL) {
+               oc1 = talloc_strndup(mem_ctx, in->data, in->length);
+       } else if (dn1->comp_num >= 1 && strcasecmp(dn1->components[0].name, "cn") == 0) {
+               oc1 = talloc_strndup(mem_ctx, dn1->components[0].value.data, 
+                                    dn1->components[0].value.length);
+       } else {
+               return -1;
+       }
+
+       oc1 = ldb_casefold(ldb, mem_ctx, oc1);
+       out->data = oc1;
+       out->length = strlen(oc1);
+       return 0;
+}
+
+static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
+                                         const struct ldb_val *v1,
+                                         const struct ldb_val *v2)
+{
+       struct ldb_dn *dn1 = NULL, *dn2 = NULL;
+       const char *oc1, *oc2;
+
+       dn1 = ldb_dn_explode(mem_ctx, (char *)v1->data);
+       if (dn1 == NULL) {
+               oc1 = talloc_strndup(mem_ctx, v1->data, v1->length);
+       } else if (dn1->comp_num >= 1 && strcasecmp(dn1->components[0].name, "cn") == 0) {
+               oc1 = talloc_strndup(mem_ctx, dn1->components[0].value.data, 
+                                    dn1->components[0].value.length);
+       } else {
+               oc1 = NULL;
+       }
+
+       dn2 = ldb_dn_explode(mem_ctx, (char *)v2->data);
+       if (dn2 == NULL) {
+               oc2 = talloc_strndup(mem_ctx, v2->data, v2->length);
+       } else if (dn2->comp_num >= 2 && strcasecmp(dn2->components[0].name, "cn") == 0) {
+               oc2 = talloc_strndup(mem_ctx, dn2->components[0].value.data, 
+                                    dn2->components[0].value.length);
+       } else {
+               oc2 = NULL;
+       }
+
+       oc1 = ldb_casefold(ldb, mem_ctx, oc1);
+       oc2 = ldb_casefold(ldb, mem_ctx, oc2);
+       if (!oc1 && oc2) {
+               return -1;
+       } 
+       if (oc1 && !oc2) {
+               return 1;
+       }       
+       if (!oc1 && !oc2) {
+               return -1;
+       }
+
+       return strcmp(oc1, oc2);
+}
+
 static const struct ldb_attrib_handler samba_handlers[] = {
        { 
                .attr            = "objectSid",
@@ -323,6 +392,14 @@ static const struct ldb_attrib_handler samba_handlers[] = {
                .ldif_write_fn   = ldif_write_objectGUID,
                .canonicalise_fn = ldb_canonicalise_objectGUID,
                .comparison_fn   = ldb_comparison_objectGUID
+       },
+       { 
+               .attr            = "objectCategory",
+               .flags           = 0,
+               .ldif_read_fn    = ldb_handler_copy,
+               .ldif_write_fn   = ldb_handler_copy,
+               .canonicalise_fn = ldif_canonicalise_objectCategory,
+               .comparison_fn   = ldif_comparison_objectCategory,
        }
 };
 
index db36e8cb6ac88e63d032616cdb53b5bc3b068d94..2429b9da5ad22704420c09aeece1befdbf8579e1 100755 (executable)
@@ -167,6 +167,15 @@ objectClass: user
 
        assert(res[0].dn == res2[0].dn);
 
+       println("Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))");
+       var res3 = ldb.search("(&(cn=ldaptestuser)(objectCategory=PerSon))");
+       if (res.length != 1) {
+               println("Could not find (&(cn=ldaptestuser)(objectCategory=PerSon))");
+               assert(res.length == 1);
+       }
+
+       assert(res[0].dn == res3[0].dn);
+
        ok = ldb.del(res[0].dn);
        if (!ok) {
                println(ldb.errstring());
@@ -194,13 +203,22 @@ objectClass: user
 
        println("Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + base_dn + "))");
        var res2 = ldb.search("(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + base_dn + "))");
-       if (res.length != 1) {
+       if (res2.length != 1) {
                println("Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + base_dn + "))");
-               assert(res.length == 1);
+               assert(res2.length == 1);
        }
 
        assert(res[0].dn == res2[0].dn);
 
+       println("Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))");
+       var res3 = ldb.search("(&(cn=ldaptestcomputer)(objectCategory=compuTER))");
+       if (res3.length != 1) {
+               println("Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))");
+               assert(res3.length == 1);
+       }
+
+       assert(res[0].dn == res3[0].dn);
+
        ok = ldb.del(res[0].dn);
        if (!ok) {
                println(ldb.errstring());