Merge commit 'origin/v4-0-test' into v4-0-test
authorAndrew Tridgell <tridge@samba.org>
Fri, 22 Aug 2008 08:39:52 +0000 (18:39 +1000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 22 Aug 2008 08:39:52 +0000 (18:39 +1000)
(This used to be commit 93cf0b3c7e6d8a4758c44519de51e51be89f76c7)

39 files changed:
source4/cldap_server/netlogon.c
source4/dsdb/common/flags.h
source4/dsdb/config.mk
source4/dsdb/samdb/ldb_modules/anr.c
source4/dsdb/samdb/ldb_modules/linked_attributes.c
source4/dsdb/samdb/ldb_modules/normalise.c
source4/dsdb/samdb/ldb_modules/partition.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/dsdb/samdb/ldb_modules/schema_syntax.c
source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
source4/dsdb/schema/schema_init.c
source4/dsdb/schema/schema_query.c [new file with mode: 0644]
source4/dsdb/schema/schema_set.c [new file with mode: 0644]
source4/lib/charset/charset.h
source4/lib/charset/util_unistr.c
source4/lib/ldb-samba/ldif_handlers.c
source4/lib/ldb/common/attrib_handlers.c
source4/lib/ldb/common/ldb_attributes.c
source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/common/ldb_msg.c
source4/lib/ldb/common/ldb_utf8.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/ldb_tdb/ldb_index.c
source4/lib/ldb/modules/operational.c
source4/lib/ldb/tests/python/ldap.py
source4/lib/ldb/tools/ldbtest.c
source4/lib/ldb_wrap.c
source4/lib/ldb_wrap.h
source4/lib/util/data_blob.c
source4/lib/util/util_ldb.c
source4/lib/util/util_ldb.h
source4/libcli/security/dom_sid.c
source4/librpc/idl/nbt.idl
source4/scripting/python/samba/provision.py
source4/setup/provision-backend
source4/setup/provision_index.ldif [deleted file]
source4/setup/provision_init.ldif
source4/torture/ldap/cldap.c

index f263f33d48889ac89d5154c0be3a875b24a03064..d4242061f45cd90e178a21da43c678b1e1e94fac 100644 (file)
@@ -71,6 +71,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
        struct ldb_dn *partitions_basedn;
        struct interface *ifaces;
        bool user_known;
+       NTSTATUS status;
 
        partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
 
@@ -87,7 +88,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                         ref_attrs, 
                                         "(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))",
-                                        domain);
+                                        ldb_binary_encode_string(mem_ctx, domain));
        
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -126,7 +127,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                         ref_attrs, 
                                         "(&(objectClass=crossRef)(ncName=*)(nETBIOSName=%s))",
-                                        netbios_domain);
+                                        ldb_binary_encode_string(mem_ctx, netbios_domain));
        
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -161,17 +162,45 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                ref_res = NULL;
 
                if (domain_guid) {
+                       struct GUID binary_guid;
+                       struct ldb_val guid_val;
+                       enum ndr_err_code ndr_err;
+
+                       /* By this means, we ensure we don't have funny stuff in the GUID */
+
+                       status = GUID_from_string(domain_guid, &binary_guid);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+
+                       /* And this gets the result into the binary format we want anyway */
+                       ndr_err = ndr_push_struct_blob(&guid_val, mem_ctx, NULL, &binary_guid,
+                                                      (ndr_push_flags_fn_t)ndr_push_GUID);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               return NT_STATUS_INVALID_PARAMETER;
+                       }
                        ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
                                                 NULL, LDB_SCOPE_SUBTREE, 
                                                 dom_attrs, 
-                                                "(&(objectClass=domainDNS)(objectGUID=%s))", 
-                                                domain_guid);
+                                                "(&(objectCategory=Domain-DNS)(objectGUID=%s))", 
+                                                ldb_binary_encode(mem_ctx, guid_val));
                } else { /* domain_sid case */
+                       struct dom_sid *sid;
+                       struct ldb_val sid_val;
+                       enum ndr_err_code ndr_err;
+                       
+                       /* Rather than go via the string, just push into the NDR form */
+                       ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, NULL, &sid,
+                                                      (ndr_push_flags_fn_t)ndr_push_dom_sid);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               return NT_STATUS_INVALID_PARAMETER;
+                       }
+
                        ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
                                                 NULL, LDB_SCOPE_SUBTREE, 
                                                 dom_attrs, 
-                                                "(&(objectClass=domainDNS)(objectSID=%s))", 
-                                                dom_sid_string(mem_ctx, domain_sid));
+                                                "(&(objectCategory=Domain-DNS)(objectSID=%s))", 
+                                                ldb_binary_encode(mem_ctx, sid_val));
                }
                
                if (ret != LDB_SUCCESS) {
@@ -237,7 +266,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         "(&(objectClass=user)(samAccountName=%s)"
                                         "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
                                         "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", 
-                                        user, UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
+                                        ldb_binary_encode_string(mem_ctx, user),
+                                        UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to user '%s' with ACB 0x%8x under %s: %s\n",
                                 user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
@@ -256,7 +286,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
        server_type      = 
                NBT_SERVER_DS | NBT_SERVER_TIMESERV |
                NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | 
-               NBT_SERVER_GOOD_TIMESERV;
+               NBT_SERVER_GOOD_TIMESERV | NBT_SERVER_DS_DNS_CONTR |
+               NBT_SERVER_DS_DNS_DOMAIN;
 
        if (samdb_is_pdc(sam_ctx)) {
                server_type |= NBT_SERVER_PDC;
@@ -274,6 +305,10 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                server_type |= NBT_SERVER_KDC;
        }
 
+       if (!ldb_dn_compare_base(ldb_get_root_basedn(sam_ctx), ldb_get_default_basedn(sam_ctx))) {
+               server_type |= NBT_SERVER_DS_DNS_FOREST;
+       }
+
        pdc_name         = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name(lp_ctx));
        domain_uuid      = samdb_result_guid(dom_res->msgs[0], "objectGUID");
        realm            = samdb_result_string(ref_res->msgs[0], "dnsRoot", lp_realm(lp_ctx));
@@ -285,6 +320,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
 
        flatname         = samdb_result_string(ref_res->msgs[0], "nETBIOSName", 
                                               lp_workgroup(lp_ctx));
+       /* FIXME: Hardcoded site names */
        server_site      = "Default-First-Site-Name";
        client_site      = "Default-First-Site-Name";
        load_interfaces(mem_ctx, lp_interfaces(lp_ctx), &ifaces);
index e8802fdf9c1b5d0d1588976cdccdb9ee238e9a7a..bdd61a363c4545c0dde2174f1cb28367f43114dc 100644 (file)
 #define SYSTEM_FLAG_CONFIG_ALLOW_RENAME                0x40000000
 #define SYSTEM_FLAG_DISALLOW_DELTE             0x80000000
 
+#define SEARCH_FLAG_ATTINDEX            0x0000001
+#define SEARCH_FLAG_PDNTATTINDEX        0x0000002
+#define SEARCH_FLAG_ANR                 0x0000004
+#define SEARCH_FLAG_PRESERVEONDELETE    0x0000008
+#define SEARCH_FLAG_COPY                0x0000010
+#define SEARCH_FLAG_TUPLEINDEX          0x0000020
+#define SEARCH_FLAG_SUBTREEATTRINDEX    0x0000040
+#define SEARCH_FLAG_CONFIDENTIAL        0x0000080
+#define SEARCH_FLAG_NEVERVALUEAUDIT     0x0000100
+#define SEARCH_FLAG_RODC_ATTRIBUTE      0x0000200
+
 #define DS_BEHAVIOR_WIN2000            0
 #define DS_BEHAVIOR_WIN2003_INTERIM    1
 #define DS_BEHAVIOR_WIN2003            2
index ae35078537242f87af56769367884fb5741ad42c..63e8a77ce4c96ec79b53c0ac32719098ae599986 100644 (file)
@@ -34,6 +34,8 @@ PRIVATE_DEPENDENCIES = SAMDB_COMMON NDR_DRSUAPI NDR_DRSBLOBS
 
 SAMDB_SCHEMA_OBJ_FILES = $(addprefix $(dsdbsrcdir)/schema/, \
                schema_init.o \
+               schema_set.o \
+               schema_query.o \
                schema_syntax.o \
                schema_description.o)
 
index 1252c9ee42f1ae2c65fbb82dd875baae34101850..4e2c527fe9c31335590511f6cd6c8a4b3b7f2198 100644 (file)
@@ -146,7 +146,7 @@ struct ldb_parse_tree *anr_replace_callback(TALLOC_CTX *mem_ctx,
                op = LDB_OP_SUBSTRING;
        }
        for (cur = schema->attributes; cur; cur = cur->next) {
-               if (!(cur->searchFlags & 0x4)) continue;
+               if (!(cur->searchFlags & SEARCH_FLAG_ANR)) continue;
                match_tree = make_match_tree(module, mem_ctx, op, cur->lDAPDisplayName, match);
 
                if (tree) {
@@ -224,30 +224,26 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
                                            void *context)
 {
        int i;
+       struct ldb_parse_tree *tmp;
+
        switch (tree->operation) {
        case LDB_OP_AND:
        case LDB_OP_OR:
                for (i=0;i<tree->u.list.num_elements;i++) {
-                       tree->u.list.elements[i] = anr_replace_subtrees(tree->u.list.elements[i],
-                                                                       attr, callback, context);
-                       if (!tree->u.list.elements[i]) {
-                               return NULL;
-                       }
+                       tmp = anr_replace_subtrees(tree->u.list.elements[i],
+                                                  attr, callback, context);
+                       if (tmp) tree->u.list.elements[i] = tmp;
                }
                break;
        case LDB_OP_NOT:
-               tree->u.isnot.child = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
-                       if (!tree->u.isnot.child) {
-                               return NULL;
-                       }
+               tmp = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
+               if (tmp) tree->u.isnot.child = tmp;
                break;
        case LDB_OP_EQUALITY:
                if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
-                       tree = callback(tree, &tree->u.equality.value, 
+                       tmp = callback(tree, &tree->u.equality.value, 
                                        context);
-                       if (!tree) {
-                               return NULL;
-                       }
+                       if (tmp) tree = tmp;
                }
                break;
        case LDB_OP_SUBSTRING:
@@ -256,10 +252,8 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
                            tree->u.substring.end_with_wildcard == 1 && 
                            tree->u.substring.chunks[0] != NULL && 
                            tree->u.substring.chunks[1] == NULL) {
-                               tree = callback(tree, tree->u.substring.chunks[0], context);
-                               if (!tree) {
-                                       return NULL;
-                               }
+                               tmp = callback(tree, tree->u.substring.chunks[0], context);
+                               if (tmp) tree = tmp;
                        }
                }
                break;
@@ -280,17 +274,29 @@ static int anr_search(struct ldb_module *module, struct ldb_request *req)
        context->module = module;
        context->found_anr = false;
 
+#if 0
+       printf("oldanr : %s\n", ldb_filter_from_tree (0, req->op.search.tree));
+#endif
+
        /* Yes, this is a problem with req->op.search.tree being const... */
        anr_tree = anr_replace_subtrees(req->op.search.tree, "anr", anr_replace_callback, context);
        if (!anr_tree) {
+               talloc_free(context);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
        if (context->found_anr) {
                /* The above function modifies the tree if it finds "anr", so no
                 * point just setting this on the down_req */
+#if 0
+               printf("newtree: %s\n", ldb_filter_from_tree (0, anr_tree));
+#endif
                req->op.search.tree = talloc_steal(req, anr_tree);
-
+       } else {
+               if (anr_tree != req->op.search.tree) {
+                       talloc_free(anr_tree);
+               }
+               talloc_free(context);
        }
        return ldb_next_request(module, req);
 }
index 04b9987071df30aba5e783a8b34ef5c63ffee72c..e64472432d21d2293b1bfd173144a1942a16169e 100644 (file)
@@ -160,7 +160,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                                ldb_oom(ldb);
                                return LDB_ERR_OPERATIONS_ERROR;
                        }
-                       new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data);
+                       new_msg->dn = ldb_dn_from_ldb_val(new_msg, ldb, &el->values[j]);
                        if (!new_msg->dn) {
                                ldb_asprintf_errstring(ldb, 
                                                       "attribute %s value %s was not a valid DN", msg->elements[i].name,
@@ -330,7 +330,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
                        /* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */
                        for (i=0; i < search_el->num_values; i++) {
                                merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
-                               merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data);
+                               merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &search_el->values[i]);
                                merged_list[size].add = false;
                                merged_list[size].ignore = false;
                                size++;
@@ -339,7 +339,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
                        /* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */
                        for (i=0; i < ac2->el->num_values; i++) {
                                merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
-                               merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data);
+                               merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &ac2->el->values[i]);
                                merged_list[size].add = true;
                                merged_list[size].ignore = false;
                                size++;
@@ -610,7 +610,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
                                ldb_oom(module->ldb);
                                return LDB_ERR_OPERATIONS_ERROR;
                        }
-                       new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data);
+                       new_msg->dn = ldb_dn_from_ldb_val(new_msg, module->ldb, &el->values[j]);
                        if (!new_msg->dn) {
                                ldb_asprintf_errstring(module->ldb, 
                                               "attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name,
index 8de9e33002bace5f76d8173373f09f12ed3ddc3b..3306fd3c33b9f8cba6b1bd76d674465c3160d83c 100644 (file)
@@ -112,7 +112,7 @@ static int normalise_search_callback(struct ldb_context *ldb, void *context, str
                }
                for (j = 0; j < ares->message->elements[i].num_values; j++) {
                        const char *dn_str;
-                       struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, (const char *)ares->message->elements[i].values[j].data);
+                       struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, ldb, &ares->message->elements[i].values[j]);
                        if (!dn) {
                                talloc_free(mem_ctx);
                                return LDB_ERR_OPERATIONS_ERROR;
index 9285d6d0d862e6e2d73b05f5db85d412ff356fed..9cae6ab7b538e96165ec7a011655270f674f8e15 100644 (file)
@@ -925,7 +925,7 @@ static int partition_init(struct ldb_module *module)
                }
                
                for (i=0; i < replicate_attributes->num_values; i++) {
-                       data->replicate[i] = ldb_dn_new(data->replicate, module->ldb, (const char *)replicate_attributes->values[i].data);
+                       data->replicate[i] = ldb_dn_from_ldb_val(data->replicate, module->ldb, &replicate_attributes->values[i]);
                        if (!ldb_dn_validate(data->replicate[i])) {
                                ldb_asprintf_errstring(module->ldb, 
                                                        "partition_init: "
index 88590f306beddbf2a6712f5ca49202f727b2af39..bd491bd011e580f19a9b05a5a1a5f993004757ba 100644 (file)
@@ -768,6 +768,10 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
        struct ldb_message_element *el, *el2;
        int ret;
        unsigned int group_type, user_account_control, account_type;
+       if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
+               return ldb_next_request(module, req);
+       }
+
        if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
                ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified");
                return LDB_ERR_UNWILLING_TO_PERFORM;
index d800e4b6d242e9b24e0106d58a08582c1eed0427..ab9f32c913c7d2a928cdcfa7678a3da1cf53661d 100644 (file)
@@ -248,7 +248,7 @@ static int schema_validate_dn(struct ldb_context *ldb, struct ldb_val *val, int
        struct ldb_dn *dn;
        int ret = LDB_SUCCESS;
 
-       dn = ldb_dn_new(ldb, ldb, (const char *)val->data);
+       dn = ldb_dn_from_ldb_val(ldb, ldb, val);
        if ( ! ldb_dn_validate(dn)) {
                ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
        }
index 6e967aab2f2061fac9fc9a1c2ff7cc17b735f8ac..8f9299514551a61af6eb1f4c75bbf8795729813a 100644 (file)
@@ -154,7 +154,7 @@ static struct ldb_val objectCategory_always_dn(struct ldb_module *module, TALLOC
        struct ldb_val out = data_blob(NULL, 0);
        const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(module->ldb, "objectCategory");
 
-       dn = ldb_dn_new(ctx, module->ldb, val->data);
+       dn = ldb_dn_from_ldb_val(ctx, module->ldb, val);
        if (dn && ldb_dn_validate(dn)) {
                talloc_free(dn);
                return val_copy(module, ctx, val);
index 73be58034791961db0f1f82118a49390b7d5607d..3ed7daee5953aa8a778436a01baf08ea286708dc 100644 (file)
@@ -1409,548 +1409,3 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema,
        return WERR_OK;
 }
 
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
-                                                             uint32_t id)
-{
-       struct dsdb_attribute *cur;
-
-       /*
-        * 0xFFFFFFFF is used as value when no mapping table is available,
-        * so don't try to match with it
-        */
-       if (id == 0xFFFFFFFF) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->attributeID_id != id) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
-                                                              const char *oid)
-{
-       struct dsdb_attribute *cur;
-
-       if (!oid) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (strcmp(cur->attributeID_oid, oid) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
-                                                              const char *name)
-{
-       struct dsdb_attribute *cur;
-
-       if (!name) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
-                                                     int linkID)
-{
-       struct dsdb_attribute *cur;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->linkID != linkID) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
-                                                   uint32_t id)
-{
-       struct dsdb_class *cur;
-
-       /*
-        * 0xFFFFFFFF is used as value when no mapping table is available,
-        * so don't try to match with it
-        */
-       if (id == 0xFFFFFFFF) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (cur->governsID_id != id) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
-                                                    const char *oid)
-{
-       struct dsdb_class *cur;
-
-       if (!oid) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcmp(cur->governsID_oid, oid) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
-                                                      const char *name)
-{
-       struct dsdb_class *cur;
-
-       if (!name) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
-                                         const char *cn)
-{
-       struct dsdb_class *cur;
-
-       if (!cn) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcasecmp(cur->cn, cn) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
-                                      uint32_t id)
-{
-       const struct dsdb_attribute *a;
-       const struct dsdb_class *c;
-
-       /* TODO: add binary search */
-       a = dsdb_attribute_by_attributeID_id(schema, id);
-       if (a) {
-               return a->lDAPDisplayName;
-       }
-
-       c = dsdb_class_by_governsID_id(schema, id);
-       if (c) {
-               return c->lDAPDisplayName;
-       }
-
-       return NULL;
-}
-
-/** 
-    Return a list of linked attributes, in lDAPDisplayName format.
-
-    This may be used to determine if a modification would require
-    backlinks to be updated, for example
-*/
-
-WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
-{
-       const char **attr_list = NULL;
-       struct dsdb_attribute *cur;
-       int i = 0;
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->linkID == 0) continue;
-               
-               attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
-               if (!attr_list) {
-                       return WERR_NOMEM;
-               }
-               attr_list[i] = cur->lDAPDisplayName;
-               i++;
-       }
-       attr_list[i] = NULL;
-       *attr_list_ret = attr_list;
-       return WERR_OK;
-}
-
-char **merge_attr_list(TALLOC_CTX *mem_ctx, 
-                      char **attrs, const char **new_attrs) 
-{
-       char **ret_attrs;
-       int i;
-       size_t new_len, orig_len = str_list_length((const char **)attrs);
-       if (!new_attrs) {
-               return attrs;
-       }
-
-       ret_attrs = talloc_realloc(mem_ctx, 
-                                  attrs, char *, orig_len + str_list_length(new_attrs) + 1);
-       if (ret_attrs) {
-               for (i=0; i < str_list_length(new_attrs); i++) {
-                       ret_attrs[orig_len + i] = new_attrs[i];
-               }
-               new_len = orig_len + str_list_length(new_attrs);
-
-               ret_attrs[new_len] = NULL;
-       }
-
-       return ret_attrs;
-}
-
-/*
-  Return a merged list of the attributes of exactly one class (not
-  considering subclasses, auxillary classes etc)
-*/
-
-char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, enum dsdb_attr_list_query query)
-{
-       char **attr_list = NULL;
-       switch (query) {
-       case DSDB_SCHEMA_ALL_MAY:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-               break;
-               
-       case DSDB_SCHEMA_ALL_MUST:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-               break;
-               
-       case DSDB_SCHEMA_SYS_MAY:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-               break;
-               
-       case DSDB_SCHEMA_SYS_MUST:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-               break;
-               
-       case DSDB_SCHEMA_MAY:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-               break;
-               
-       case DSDB_SCHEMA_MUST:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-               break;
-               
-       case DSDB_SCHEMA_ALL:
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-               break;
-       }
-       return attr_list;
-}
-
-static char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 
-                                               const struct dsdb_schema *schema, 
-                                               const char **class_list,
-                                               enum dsdb_attr_list_query query)
-{
-       int i;
-       const struct dsdb_class *class;
-       
-       char **attr_list = NULL;
-       char **this_class_list;
-       char **recursive_list;
-
-       for (i=0; class_list && class_list[i]; i++) {
-               class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
-               
-               this_class_list = dsdb_attribute_list(mem_ctx, class, query);
-               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)this_class_list);
-
-               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
-                                                                  class->systemAuxiliaryClass, 
-                                                                  query);
-               
-               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-               
-               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
-                                                                  class->auxiliaryClass, 
-                                                                  query);
-               
-               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-               
-       }
-       return attr_list;
-}
-
-char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, 
-                               const struct dsdb_schema *schema, 
-                               const char **class_list,
-                               enum dsdb_attr_list_query query)
-{
-       char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
-       size_t new_len = str_list_length((const char **)attr_list);
-
-       /* Remove duplicates */
-       if (new_len > 1) {
-               int i;
-               qsort(attr_list, new_len,
-                     sizeof(*attr_list),
-                     (comparison_fn_t)strcasecmp);
-               
-               for (i=1 ; i < new_len; i++) {
-                       char **val1 = &attr_list[i-1];
-                       char **val2 = &attr_list[i];
-                       if (ldb_attr_cmp(*val1, *val2) == 0) {
-                               memmove(val1, val2, (new_len - i) * sizeof( *attr_list)); 
-                               new_len--;
-                               i--;
-                       }
-               }
-       }
-       return attr_list;
-}
-/**
- * Attach the schema to an opaque pointer on the ldb, so ldb modules
- * can find it 
- */
-
-int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
-{
-       int ret;
-
-       ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
-       if (ret != LDB_SUCCESS) {
-               return ret;
-       }
-
-       talloc_steal(ldb, schema);
-
-       return LDB_SUCCESS;
-}
-
-/**
- * Global variable to hold one copy of the schema, used to avoid memory bloat
- */
-static struct dsdb_schema *global_schema;
-
-/**
- * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
- */
-int dsdb_set_global_schema(struct ldb_context *ldb)
-{
-       int ret;
-       if (!global_schema) {
-               return LDB_SUCCESS;
-       }
-       ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
-       if (ret != LDB_SUCCESS) {
-               return ret;
-       }
-
-       /* Keep a reference to this schema, just incase the global copy is replaced */
-       if (talloc_reference(ldb, global_schema) == NULL) {
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       return LDB_SUCCESS;
-}
-
-/**
- * Find the schema object for this ldb
- */
-
-struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
-{
-       const void *p;
-       struct dsdb_schema *schema;
-
-       /* see if we have a cached copy */
-       p = ldb_get_opaque(ldb, "dsdb_schema");
-       if (!p) {
-               return NULL;
-       }
-
-       schema = talloc_get_type(p, struct dsdb_schema);
-       if (!schema) {
-               return NULL;
-       }
-
-       return schema;
-}
-
-/**
- * Make the schema found on this ldb the 'global' schema
- */
-
-void dsdb_make_schema_global(struct ldb_context *ldb)
-{
-       struct dsdb_schema *schema = dsdb_get_schema(ldb);
-       if (!schema) {
-               return;
-       }
-
-       if (global_schema) {
-               talloc_unlink(talloc_autofree_context(), schema);
-       }
-
-       talloc_steal(talloc_autofree_context(), schema);
-       global_schema = schema;
-
-       dsdb_set_global_schema(ldb);
-}
-
-
-/**
- * Rather than read a schema from the LDB itself, read it from an ldif
- * file.  This allows schema to be loaded and used while adding the
- * schema itself to the directory.
- */
-
-WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
-{
-       struct ldb_ldif *ldif;
-       struct ldb_message *msg;
-       TALLOC_CTX *mem_ctx;
-       WERROR status;
-       int ret;
-       struct dsdb_schema *schema;
-       const struct ldb_val *prefix_val;
-       const struct ldb_val *info_val;
-       struct ldb_val info_val_default;
-
-       mem_ctx = talloc_new(ldb);
-       if (!mem_ctx) {
-               goto nomem;
-       }
-
-       schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
-
-       schema->fsmo.we_are_master = true;
-       schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
-       if (!schema->fsmo.master_dn) {
-               goto nomem;
-       }
-
-       /*
-        * load the prefixMap attribute from pf
-        */
-       ldif = ldb_ldif_read_string(ldb, &pf);
-       if (!ldif) {
-               status = WERR_INVALID_PARAM;
-               goto failed;
-       }
-       talloc_steal(mem_ctx, ldif);
-
-       msg = ldb_msg_canonicalize(ldb, ldif->msg);
-       if (!msg) {
-               goto nomem;
-       }
-       talloc_steal(mem_ctx, msg);
-       talloc_free(ldif);
-
-       prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
-       if (!prefix_val) {
-               status = WERR_INVALID_PARAM;
-               goto failed;
-       }
-
-       info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
-       if (!info_val) {
-               info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
-               if (!info_val_default.data) {
-                       goto nomem;
-               }
-               talloc_steal(mem_ctx, info_val_default.data);
-               info_val = &info_val_default;
-       }
-
-       status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
-       if (!W_ERROR_IS_OK(status)) {
-               goto failed;
-       }
-
-       /*
-        * load the attribute and class definitions outof df
-        */
-       while ((ldif = ldb_ldif_read_string(ldb, &df))) {
-               bool is_sa;
-               bool is_sc;
-
-               talloc_steal(mem_ctx, ldif);
-
-               msg = ldb_msg_canonicalize(ldb, ldif->msg);
-               if (!msg) {
-                       goto nomem;
-               }
-
-               talloc_steal(mem_ctx, msg);
-               talloc_free(ldif);
-
-               is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
-               is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
-
-               if (is_sa) {
-                       struct dsdb_attribute *sa;
-
-                       sa = talloc_zero(schema, struct dsdb_attribute);
-                       if (!sa) {
-                               goto nomem;
-                       }
-
-                       status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto failed;
-                       }
-
-                       DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
-               } else if (is_sc) {
-                       struct dsdb_class *sc;
-
-                       sc = talloc_zero(schema, struct dsdb_class);
-                       if (!sc) {
-                               goto nomem;
-                       }
-
-                       status = dsdb_class_from_ldb(schema, msg, sc, sc);
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto failed;
-                       }
-
-                       DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
-               }
-       }
-
-       ret = dsdb_set_schema(ldb, schema);
-       if (ret != LDB_SUCCESS) {
-               status = WERR_FOOBAR;
-               goto failed;
-       }
-
-       goto done;
-
-nomem:
-       status = WERR_NOMEM;
-failed:
-done:
-       talloc_free(mem_ctx);
-       return status;
-}
diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c
new file mode 100644 (file)
index 0000000..ca26ffd
--- /dev/null
@@ -0,0 +1,344 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   DSDB schema header
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+   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 <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
+                                                             uint32_t id)
+{
+       struct dsdb_attribute *cur;
+
+       /*
+        * 0xFFFFFFFF is used as value when no mapping table is available,
+        * so don't try to match with it
+        */
+       if (id == 0xFFFFFFFF) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->attributeID_id != id) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
+                                                              const char *oid)
+{
+       struct dsdb_attribute *cur;
+
+       if (!oid) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (strcmp(cur->attributeID_oid, oid) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
+                                                              const char *name)
+{
+       struct dsdb_attribute *cur;
+
+       if (!name) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
+                                                     int linkID)
+{
+       struct dsdb_attribute *cur;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->linkID != linkID) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
+                                                   uint32_t id)
+{
+       struct dsdb_class *cur;
+
+       /*
+        * 0xFFFFFFFF is used as value when no mapping table is available,
+        * so don't try to match with it
+        */
+       if (id == 0xFFFFFFFF) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (cur->governsID_id != id) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
+                                                    const char *oid)
+{
+       struct dsdb_class *cur;
+
+       if (!oid) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcmp(cur->governsID_oid, oid) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
+                                                      const char *name)
+{
+       struct dsdb_class *cur;
+
+       if (!name) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
+                                         const char *cn)
+{
+       struct dsdb_class *cur;
+
+       if (!cn) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcasecmp(cur->cn, cn) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
+                                      uint32_t id)
+{
+       const struct dsdb_attribute *a;
+       const struct dsdb_class *c;
+
+       /* TODO: add binary search */
+       a = dsdb_attribute_by_attributeID_id(schema, id);
+       if (a) {
+               return a->lDAPDisplayName;
+       }
+
+       c = dsdb_class_by_governsID_id(schema, id);
+       if (c) {
+               return c->lDAPDisplayName;
+       }
+
+       return NULL;
+}
+
+/** 
+    Return a list of linked attributes, in lDAPDisplayName format.
+
+    This may be used to determine if a modification would require
+    backlinks to be updated, for example
+*/
+
+WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
+{
+       const char **attr_list = NULL;
+       struct dsdb_attribute *cur;
+       int i = 0;
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->linkID == 0) continue;
+               
+               attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
+               if (!attr_list) {
+                       return WERR_NOMEM;
+               }
+               attr_list[i] = cur->lDAPDisplayName;
+               i++;
+       }
+       attr_list[i] = NULL;
+       *attr_list_ret = attr_list;
+       return WERR_OK;
+}
+
+char **merge_attr_list(TALLOC_CTX *mem_ctx, 
+                      char **attrs, const char **new_attrs) 
+{
+       char **ret_attrs;
+       int i;
+       size_t new_len, orig_len = str_list_length((const char **)attrs);
+       if (!new_attrs) {
+               return attrs;
+       }
+
+       ret_attrs = talloc_realloc(mem_ctx, 
+                                  attrs, char *, orig_len + str_list_length(new_attrs) + 1);
+       if (ret_attrs) {
+               for (i=0; i < str_list_length(new_attrs); i++) {
+                       ret_attrs[orig_len + i] = new_attrs[i];
+               }
+               new_len = orig_len + str_list_length(new_attrs);
+
+               ret_attrs[new_len] = NULL;
+       }
+
+       return ret_attrs;
+}
+
+/*
+  Return a merged list of the attributes of exactly one class (not
+  considering subclasses, auxillary classes etc)
+*/
+
+char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, enum dsdb_attr_list_query query)
+{
+       char **attr_list = NULL;
+       switch (query) {
+       case DSDB_SCHEMA_ALL_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               break;
+               
+       case DSDB_SCHEMA_ALL_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+               
+       case DSDB_SCHEMA_SYS_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               break;
+               
+       case DSDB_SCHEMA_SYS_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+               
+       case DSDB_SCHEMA_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               break;
+               
+       case DSDB_SCHEMA_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               break;
+               
+       case DSDB_SCHEMA_ALL:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+       }
+       return attr_list;
+}
+
+static char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 
+                                               const struct dsdb_schema *schema, 
+                                               const char **class_list,
+                                               enum dsdb_attr_list_query query)
+{
+       int i;
+       const struct dsdb_class *class;
+       
+       char **attr_list = NULL;
+       char **this_class_list;
+       char **recursive_list;
+
+       for (i=0; class_list && class_list[i]; i++) {
+               class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
+               
+               this_class_list = dsdb_attribute_list(mem_ctx, class, query);
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)this_class_list);
+
+               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
+                                                                  class->systemAuxiliaryClass, 
+                                                                  query);
+               
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+               
+               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
+                                                                  class->auxiliaryClass, 
+                                                                  query);
+               
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+               
+       }
+       return attr_list;
+}
+
+char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, 
+                               const struct dsdb_schema *schema, 
+                               const char **class_list,
+                               enum dsdb_attr_list_query query)
+{
+       char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
+       size_t new_len = str_list_length((const char **)attr_list);
+
+       /* Remove duplicates */
+       if (new_len > 1) {
+               int i;
+               qsort(attr_list, new_len,
+                     sizeof(*attr_list),
+                     (comparison_fn_t)strcasecmp);
+               
+               for (i=1 ; i < new_len; i++) {
+                       char **val1 = &attr_list[i-1];
+                       char **val2 = &attr_list[i];
+                       if (ldb_attr_cmp(*val1, *val2) == 0) {
+                               memmove(val1, val2, (new_len - i) * sizeof( *attr_list)); 
+                               new_len--;
+                               i--;
+                       }
+               }
+       }
+       return attr_list;
+}
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
new file mode 100644 (file)
index 0000000..0ca26c0
--- /dev/null
@@ -0,0 +1,434 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   DSDB schema header
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+   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 <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "lib/ldb/include/ldb_private.h"
+#include "lib/util/dlinklist.h"
+#include "param/param.h"
+
+
+static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
+{
+       int ret = LDB_SUCCESS;
+       struct ldb_result *res;
+       struct ldb_result *res_idx;
+       struct dsdb_attribute *attr;
+       struct ldb_message *mod_msg;
+       TALLOC_CTX *mem_ctx = talloc_new(ldb);
+       
+       struct ldb_message *msg;
+       struct ldb_message *msg_idx;
+
+       if (!mem_ctx) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       msg = ldb_msg_new(mem_ctx);
+       if (!msg) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg_idx = ldb_msg_new(mem_ctx);
+       if (!msg_idx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
+       if (!msg->dn) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST");
+       if (!msg_idx->dn) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (attr = schema->attributes; attr; attr = attr->next) {
+               const struct ldb_schema_syntax *s;
+               const char *syntax = attr->syntax->ldb_syntax;
+               if (!syntax) {
+                       syntax = attr->syntax->ldap_oid;
+               }
+
+               /* Write out a rough approximation of the schema as an @ATTRIBUTES value, for bootstrapping */
+               if (strcmp(syntax, LDB_SYNTAX_INTEGER) == 0) {
+                       ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "INTEGER");
+               } else if (strcmp(syntax, LDB_SYNTAX_DIRECTORY_STRING) == 0) {
+                       ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE");
+               } 
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+
+               if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+                       ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
+
+               if (!attr->syntax) {
+                       continue;
+               }
+
+               ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED,
+                                              syntax);
+               if (ret != LDB_SUCCESS) {
+                       s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
+                       if (s) {
+                               ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, s);
+                       } else {
+                               ret = LDB_SUCCESS; /* Nothing to do here */
+                       }
+               }
+               
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       if (!write_attributes) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+
+       ret = ldb_transaction_start(ldb);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Try to avoid churning the attributes too much - we only want to do this if they have changed */
+       ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn));
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ret = ldb_add(ldb, msg);
+       } else if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               ldb_transaction_cancel(ldb);
+               return ret;
+       } else {
+
+               if (res->count != 1) {
+                       talloc_free(mem_ctx);
+                       ldb_transaction_cancel(ldb);
+                       return LDB_ERR_NO_SUCH_OBJECT;
+               }
+               
+               ret = LDB_SUCCESS;
+               /* Annoyingly added to our search results */
+               ldb_msg_remove_attr(res->msgs[0], "distinguishedName");
+
+               mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
+               if (mod_msg->num_elements > 0) {
+                       ret = ldb_modify(ldb, mod_msg);
+               }
+       }
+
+       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+               /* We might be on a read-only DB */
+               talloc_free(mem_ctx);
+               ret = ldb_transaction_cancel(ldb);
+               return ret;
+       } else if (ret != LDB_SUCCESS) {
+               ldb_transaction_cancel(ldb);
+               return ret;
+       }
+
+       /* Now write out the indexs, as found in the schema (if they have changed) */
+
+       ret = ldb_search_exp_fmt(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg_idx->dn));
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ret = ldb_add(ldb, msg_idx);
+       } else if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               ldb_transaction_cancel(ldb);
+               return ret;
+       } else {
+               if (res_idx->count != 1) {
+                       talloc_free(mem_ctx);
+                       ldb_transaction_cancel(ldb);
+                       return LDB_ERR_NO_SUCH_OBJECT;
+               }
+               
+               /* Annoyingly added to our search results */
+               ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName");
+
+               mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
+               if (mod_msg->num_elements > 0) {
+                       ret = ldb_modify(ldb, mod_msg);
+               }
+       }
+       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+               /* We might be on a read-only DB */
+               talloc_free(mem_ctx);
+               return ldb_transaction_cancel(ldb);
+       } else if (ret == LDB_SUCCESS) {
+               ret = ldb_transaction_commit(ldb);
+       } else {
+               ldb_transaction_cancel(ldb);
+       }
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+
+/**
+ * Attach the schema to an opaque pointer on the ldb, so ldb modules
+ * can find it 
+ */
+
+int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+       int ret;
+
+       ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Set the new attributes based on the new schema */
+       ret = dsdb_schema_set_attributes(ldb, schema, true);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       talloc_steal(ldb, schema);
+
+       return LDB_SUCCESS;
+}
+
+/**
+ * Global variable to hold one copy of the schema, used to avoid memory bloat
+ */
+static struct dsdb_schema *global_schema;
+
+/**
+ * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ */
+int dsdb_set_global_schema(struct ldb_context *ldb)
+{
+       int ret;
+       if (!global_schema) {
+               return LDB_SUCCESS;
+       }
+       ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Set the new attributes based on the new schema */
+       ret = dsdb_schema_set_attributes(ldb, global_schema, false);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Keep a reference to this schema, just incase the global copy is replaced */
+       if (talloc_reference(ldb, global_schema) == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       return LDB_SUCCESS;
+}
+
+/**
+ * Find the schema object for this ldb
+ */
+
+struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
+{
+       const void *p;
+       struct dsdb_schema *schema;
+
+       /* see if we have a cached copy */
+       p = ldb_get_opaque(ldb, "dsdb_schema");
+       if (!p) {
+               return NULL;
+       }
+
+       schema = talloc_get_type(p, struct dsdb_schema);
+       if (!schema) {
+               return NULL;
+       }
+
+       return schema;
+}
+
+/**
+ * Make the schema found on this ldb the 'global' schema
+ */
+
+void dsdb_make_schema_global(struct ldb_context *ldb)
+{
+       struct dsdb_schema *schema = dsdb_get_schema(ldb);
+       if (!schema) {
+               return;
+       }
+
+       if (global_schema) {
+               talloc_unlink(talloc_autofree_context(), schema);
+       }
+
+       talloc_steal(talloc_autofree_context(), schema);
+       global_schema = schema;
+
+       dsdb_set_global_schema(ldb);
+}
+
+
+/**
+ * Rather than read a schema from the LDB itself, read it from an ldif
+ * file.  This allows schema to be loaded and used while adding the
+ * schema itself to the directory.
+ */
+
+WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
+{
+       struct ldb_ldif *ldif;
+       struct ldb_message *msg;
+       TALLOC_CTX *mem_ctx;
+       WERROR status;
+       int ret;
+       struct dsdb_schema *schema;
+       const struct ldb_val *prefix_val;
+       const struct ldb_val *info_val;
+       struct ldb_val info_val_default;
+
+       mem_ctx = talloc_new(ldb);
+       if (!mem_ctx) {
+               goto nomem;
+       }
+
+       schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
+
+       schema->fsmo.we_are_master = true;
+       schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
+       if (!schema->fsmo.master_dn) {
+               goto nomem;
+       }
+
+       /*
+        * load the prefixMap attribute from pf
+        */
+       ldif = ldb_ldif_read_string(ldb, &pf);
+       if (!ldif) {
+               status = WERR_INVALID_PARAM;
+               goto failed;
+       }
+       talloc_steal(mem_ctx, ldif);
+
+       msg = ldb_msg_canonicalize(ldb, ldif->msg);
+       if (!msg) {
+               goto nomem;
+       }
+       talloc_steal(mem_ctx, msg);
+       talloc_free(ldif);
+
+       prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
+       if (!prefix_val) {
+               status = WERR_INVALID_PARAM;
+               goto failed;
+       }
+
+       info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
+       if (!info_val) {
+               info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
+               if (!info_val_default.data) {
+                       goto nomem;
+               }
+               talloc_steal(mem_ctx, info_val_default.data);
+               info_val = &info_val_default;
+       }
+
+       status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
+       if (!W_ERROR_IS_OK(status)) {
+               goto failed;
+       }
+
+       /*
+        * load the attribute and class definitions outof df
+        */
+       while ((ldif = ldb_ldif_read_string(ldb, &df))) {
+               bool is_sa;
+               bool is_sc;
+
+               talloc_steal(mem_ctx, ldif);
+
+               msg = ldb_msg_canonicalize(ldb, ldif->msg);
+               if (!msg) {
+                       goto nomem;
+               }
+
+               talloc_steal(mem_ctx, msg);
+               talloc_free(ldif);
+
+               is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
+               is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
+
+               if (is_sa) {
+                       struct dsdb_attribute *sa;
+
+                       sa = talloc_zero(schema, struct dsdb_attribute);
+                       if (!sa) {
+                               goto nomem;
+                       }
+
+                       status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
+                       if (!W_ERROR_IS_OK(status)) {
+                               goto failed;
+                       }
+
+                       DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
+               } else if (is_sc) {
+                       struct dsdb_class *sc;
+
+                       sc = talloc_zero(schema, struct dsdb_class);
+                       if (!sc) {
+                               goto nomem;
+                       }
+
+                       status = dsdb_class_from_ldb(schema, msg, sc, sc);
+                       if (!W_ERROR_IS_OK(status)) {
+                               goto failed;
+                       }
+
+                       DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
+               }
+       }
+
+       ret = dsdb_set_schema(ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               status = WERR_FOOBAR;
+               goto failed;
+       }
+
+       goto done;
+
+nomem:
+       status = WERR_NOMEM;
+failed:
+done:
+       talloc_free(mem_ctx);
+       return status;
+}
index baa7df532b6d78fa1c5db0aa53138f13ba5edf96..c49745cd7f1799a2897483e7bbcb625941ff891b 100644 (file)
@@ -97,6 +97,7 @@ size_t count_chars_w(const char *s, char c);
 void strupper_m(char *s);
 void strlower_m(char *s);
 char *strupper_talloc(TALLOC_CTX *ctx, const char *src);
+char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n);
 char *strlower_talloc(TALLOC_CTX *ctx, const char *src);
 bool strhasupper(const char *string);
 bool strhaslower(const char *string);
index 19a4f3236cfdedcdc5cffe9541d7b9cb427021c8..09ec7b04716d1db271fd906f6cf94ab53e869a3e 100644 (file)
@@ -518,8 +518,9 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
 
 /**
  Convert a string to UPPER case, allocated with talloc
+ source length limited to n bytes
 **/
-_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
 {
        size_t size=0;
        char *dest;
@@ -531,12 +532,12 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
 
        /* this takes advantage of the fact that upper/lower can't
           change the length of a character by more than 1 byte */
-       dest = talloc_array(ctx, char, 2*(strlen(src))+1);
+       dest = talloc_array(ctx, char, 2*(n+1));
        if (dest == NULL) {
                return NULL;
        }
 
-       while (*src) {
+       while (*src && n--) {
                size_t c_size;
                codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
                src += c_size;
@@ -561,6 +562,16 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
        return dest;
 }
 
+/**
+ Convert a string to UPPER case, allocated with talloc
+**/
+_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+{
+       return strupper_talloc_n(ctx, src, src?strlen(src):0);
+}
+
+
+
 /**
  Convert a string to lower case.
 **/
index 22a57da10bfd6b029c0fc98b65b57b14268ac8e9..a16582d29458a1e0b23cfa7e822c0e1e8fecf4a1 100644 (file)
@@ -38,7 +38,7 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
 {
        enum ndr_err_code ndr_err;
        struct dom_sid *sid;
-       sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
+       sid = dom_sid_parse_length(mem_ctx, in);
        if (sid == NULL) {
                return -1;
        }
@@ -70,12 +70,11 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
                talloc_free(sid);
                return -1;
        }
-       out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
+       *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
        talloc_free(sid);
        if (out->data == NULL) {
                return -1;
        }
-       out->length = strlen((const char *)out->data);
        return 0;
 }
 
@@ -97,13 +96,14 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                    const struct ldb_val *v1, const struct ldb_val *v2)
 {
        if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
-               return strcmp((const char *)v1->data, (const char *)v2->data);
+               return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
        } else if (ldb_comparision_objectSid_isString(v1)
                   && !ldb_comparision_objectSid_isString(v2)) {
                struct ldb_val v;
                int ret;
                if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
-                       return -1;
+                       /* Perhaps not a string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
                talloc_free(v.data);
@@ -113,7 +113,8 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
                struct ldb_val v;
                int ret;
                if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
-                       return -1;
+                       /* Perhaps not a string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
                talloc_free(v.data);
@@ -129,7 +130,11 @@ static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                      const struct ldb_val *in, struct ldb_val *out)
 {
        if (ldb_comparision_objectSid_isString(in)) {
-               return ldif_read_objectSid(ldb, mem_ctx, in, out);
+               if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
+                       /* Perhaps not a string after all */
+                       return ldb_handler_copy(ldb, mem_ctx, in, out);
+               }
+               return 0;
        }
        return ldb_handler_copy(ldb, mem_ctx, in, out);
 }
@@ -141,10 +146,16 @@ static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                const struct ldb_val *in, struct ldb_val *out)
 {
        struct GUID guid;
+       char *guid_string;
        NTSTATUS status;
        enum ndr_err_code ndr_err;
+       guid_string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
+       if (!guid_string) {
+               return -1;
+       }
 
-       status = GUID_from_string((const char *)in->data, &guid);
+       status = GUID_from_string(guid_string, &guid);
+       talloc_free(guid_string);
        if (!NT_STATUS_IS_OK(status)) {
                return -1;
        }
@@ -203,13 +214,14 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                     const struct ldb_val *v1, const struct ldb_val *v2)
 {
        if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
-               return strcmp((const char *)v1->data, (const char *)v2->data);
+               return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
        } else if (ldb_comparision_objectGUID_isString(v1)
                   && !ldb_comparision_objectGUID_isString(v2)) {
                struct ldb_val v;
                int ret;
                if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
-                       return -1;
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
                talloc_free(v.data);
@@ -219,7 +231,8 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                struct ldb_val v;
                int ret;
                if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
-                       return -1;
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
                talloc_free(v.data);
@@ -235,7 +248,11 @@ static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                       const struct ldb_val *in, struct ldb_val *out)
 {
        if (ldb_comparision_objectGUID_isString(in)) {
-               return ldif_read_objectGUID(ldb, mem_ctx, in, out);
+               if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_handler_copy(ldb, mem_ctx, in, out);
+               }
+               return 0;
        }
        return ldb_handler_copy(ldb, mem_ctx, in, out);
 }
@@ -314,7 +331,7 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
                }
                return LDB_SUCCESS;
        }
-       dn1 = ldb_dn_new(tmp_ctx, ldb, (char *)in->data);
+       dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
        if ( ! ldb_dn_validate(dn1)) {
                const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
                class = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
@@ -617,19 +634,6 @@ static const struct {
        { "fRSReplicaSetGUID",          LDB_SYNTAX_SAMBA_GUID },
        { "netbootGUID",                LDB_SYNTAX_SAMBA_GUID },
        { "objectCategory",             LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
-       { "member",                     LDB_SYNTAX_DN },
-       { "memberOf",                   LDB_SYNTAX_DN },
-       { "nCName",                     LDB_SYNTAX_DN },
-       { "schemaNamingContext",        LDB_SYNTAX_DN },
-       { "configurationNamingContext", LDB_SYNTAX_DN },
-       { "rootDomainNamingContext",    LDB_SYNTAX_DN },
-       { "defaultNamingContext",       LDB_SYNTAX_DN },
-       { "subRefs",                    LDB_SYNTAX_DN },
-       { "dMDLocation",                LDB_SYNTAX_DN },
-       { "serverReference",            LDB_SYNTAX_DN },
-       { "masteredBy",                 LDB_SYNTAX_DN },
-       { "msDs-masteredBy",            LDB_SYNTAX_DN },
-       { "fSMORoleOwner",              LDB_SYNTAX_DN },
        { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP }
 };
 
@@ -669,7 +673,7 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
                        return -1;
                }
 
-               ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, 0, s);
+               ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
index 8ed2763d4df5112af67f89b43b109f0e3c359cbc..fb57e2dadc084fb74bf06d1dc7a9b1bc5fca42de 100644 (file)
@@ -55,11 +55,12 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
 {
        char *s, *t;
        int l;
+
        if (!in || !out || !(in->data)) {
                return -1;
        }
 
-       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data));
+       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
        if (out->data == NULL) {
                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
                return -1;
@@ -153,13 +154,14 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                               const struct ldb_val *v1, const struct ldb_val *v2)
 {
        const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
+       size_t n1 = v1->length, n2 = v2->length;
        const char *u1, *u2;
        char *b1, *b2;
        int ret;
-       while (*s1 == ' ') s1++;
-       while (*s2 == ' ') s2++;
+       while (*s1 == ' ' && n1) { s1++; n1--; };
+       while (*s2 == ' ' && n2) { s2++; n2--; };
        /* TODO: make utf8 safe, possibly with helper function from application */
-       while (*s1 && *s2) {
+       while (*s1 && *s2 && n1 && n2) {
                /* the first 127 (0x7F) chars are ascii and utf8 guarantes they
                 * never appear in multibyte sequences */
                if (((unsigned char)s1[0]) & 0x80) goto utf8str;
@@ -167,10 +169,11 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
                        break;
                if (*s1 == ' ') {
-                       while (s1[0] == s1[1]) s1++;
-                       while (s2[0] == s2[1]) s2++;
+                       while (s1[0] == s1[1] && n1) { s1++; n1--; }
+                       while (s2[0] == s2[1] && n2) { s2++; n2--; }
                }
                s1++; s2++;
+               n1--; n2--;
        }
        if (! (*s1 && *s2)) {
                /* check for trailing spaces only if one of the pointers
@@ -178,15 +181,18 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                 * can mistakenly match.
                 * ex. "domain users" <-> "domainUpdates"
                 */
-               while (*s1 == ' ') s1++;
-               while (*s2 == ' ') s2++;
+               while (*s1 == ' ') { s1++; n1--; }
+               while (*s2 == ' ') { s2++; n2--; }
+       }
+       if (n1 != n2) {
+               return n1 - n2;
        }
        return (int)(toupper(*s1)) - (int)(toupper(*s2));
 
 utf8str:
        /* no need to recheck from the start, just from the first utf8 char found */
-       b1 = ldb_casefold(ldb, mem_ctx, s1);
-       b2 = ldb_casefold(ldb, mem_ctx, s2);
+       b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
+       b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
 
        if (b1 && b2) {
                /* Both strings converted correctly */
@@ -221,6 +227,7 @@ utf8str:
        return ret;
 }
 
+
 /*
   canonicalise a attribute in DN format
 */
index 3b9d01682ccc402513a1e5abb1ff97dedd81c77f..747f2417811a9069b1ed4391b70672b6d54f590b 100644 (file)
@@ -51,6 +51,10 @@ int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
        int i, n;
        struct ldb_schema_attribute *a;
 
+       if (!syntax) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        n = ldb->schema.num_attributes + 1;
 
        a = talloc_realloc(ldb, ldb->schema.attributes,
index 08911344b759cada33bac9786b1d2cbce1722ba1..c0d36cfbf3e0c48239b123a8920fbd4d065cc068 100644 (file)
@@ -71,7 +71,7 @@ struct ldb_dn {
 };
 
 /* strdn may be NULL */
-struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
 {
        struct ldb_dn *dn;
 
@@ -82,27 +82,27 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
 
        dn->ldb = ldb;
 
-       if (strdn) {
-               if (strdn[0] == '@') {
+       if (strdn->data && strdn->length) {
+               if (strdn->data[0] == '@') {
                        dn->special = true;
                }
-               if (strncasecmp(strdn, "<GUID=", 6) == 0) {
+               if (strdn->length >= 6 && strncasecmp((const char *)strdn->data, "<GUID=", 6) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a GUID string to ldb_dn structure */
-               } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
+               } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<SID=", 8) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a SID string to ldb_dn structure */
-               } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
+               } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<WKGUID=", 8) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a WKGUID string to ldb_dn structure */
                }
-               dn->linearized = talloc_strdup(dn, strdn);
+               dn->linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
        } else {
                dn->linearized = talloc_strdup(dn, "");
        }
@@ -115,6 +115,15 @@ failed:
        return NULL;
 }
 
+/* strdn may be NULL */
+struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+{
+       struct ldb_val blob;
+       blob.data = strdn;
+       blob.length = strdn ? strlen(strdn) : 0;
+       return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
+}
+
 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
 {
        struct ldb_dn *dn;
index c1ea9db56bfb11a4319fb6503258199bcac471dd..2f5fe1d18c143cde271958948605ca0d82eea896 100644 (file)
@@ -389,10 +389,10 @@ int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
        if (!v || !v->data) {
                return default_value;
        }
-       if (strcasecmp((const char *)v->data, "FALSE") == 0) {
+       if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
                return 0;
        }
-       if (strcasecmp((const char *)v->data, "TRUE") == 0) {
+       if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
                return 1;
        }
        return default_value;
@@ -421,7 +421,7 @@ struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
        if (!v || !v->data) {
                return NULL;
        }
-       res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
+       res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
        if ( ! ldb_dn_validate(res_dn)) {
                talloc_free(res_dn);
                return NULL;
index b7b4a60122f8c5b9d6e1ec7f66cca410457ae8a8..69ee2b6964f81e8a66b634f80965b3cabb823bb0 100644 (file)
@@ -40,8 +40,8 @@
   function to handle utf8 caseless comparisons
  */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *))
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t))
 {
        if (context)
                ldb->utf8_fns.context = context;
@@ -53,10 +53,10 @@ void ldb_set_utf8_fns(struct ldb_context *ldb,
   a simple case folding function
   NOTE: does not handle UTF8
 */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
 {
        int i;
-       char *ret = talloc_strdup(mem_ctx, s);
+       char *ret = talloc_strndup(mem_ctx, s, n);
        if (!s) {
                errno = ENOMEM;
                return NULL;
@@ -72,9 +72,9 @@ void ldb_set_utf8_default(struct ldb_context *ldb)
        ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default);
 }
 
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
 {
-       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
+       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
 }
 
 /*
index 7ce61034228da9dd9d176cd8f7e3908106968699..937029f52ce3f53f2ec78274430a9d05416500d0 100644 (file)
@@ -203,7 +203,7 @@ struct ldb_debug_ops {
 */
 struct ldb_utf8_fns {
        void *context;
-       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s);
+       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 };
 
 /**
@@ -1216,7 +1216,7 @@ void ldb_set_utf8_default(struct ldb_context *ldb);
    \note The default function is not yet UTF8 aware. Provide your own
          set of functions through ldb_set_utf8_fns()
 */
-char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 
 /**
    Check the attribute name is valid according to rfc2251
@@ -1381,6 +1381,7 @@ int ldb_base64_decode(char *s);
 
 struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn);
 struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4);
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
 bool ldb_dn_validate(struct ldb_dn *dn);
 
 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value);
@@ -1602,8 +1603,8 @@ int ldb_set_debug(struct ldb_context *ldb,
   this allows the user to set custom utf8 function for error reporting
 */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *));
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t n));
 
 /**
    this sets up debug to print messages on stderr
index d7c2efe8a1a2b86c9aa3c1abbe27ba067bb6bdb0..e1026ab781170a412cd12dcc12fddcec2c9da827 100644 (file)
@@ -91,13 +91,6 @@ struct ldb_schema {
        /* attribute handling table */
        unsigned num_attributes;
        struct ldb_schema_attribute *attributes;
-
-       /* objectclass information */
-       unsigned num_classes;
-       struct ldb_subclass {
-               char *name;
-               char **subclasses;
-       } *classes;
 };
 
 /*
@@ -242,7 +235,7 @@ int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct l
 int check_critical_controls(struct ldb_control **controls);
 
 /* The following definitions come from lib/ldb/common/ldb_utf8.c */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n);
 
 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
 
index 1b6d9feed6117cd5175176c347540e560af54ca6..269305a4680c90c94ad4dc625486ad3b5bcaffcc 100644 (file)
@@ -767,7 +767,7 @@ int ltdb_search_indexed(struct ldb_handle *handle)
 
        if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
            (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
-               /* no indexs? must do full search */
+               /* no indexes? must do full search */
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
index 7dc4ae08c380eee8947643e5afc7bb8394728ac8..a59e81becdd4e50eb764484eba6b2ae1a27254ce 100644 (file)
@@ -291,12 +291,6 @@ static int operational_init(struct ldb_module *ctx)
 {
        int ret = 0;
 
-       /* setup some standard attribute handlers */
-       ret |= ldb_schema_attribute_add(ctx->ldb, "whenCreated", 0, LDB_SYNTAX_UTC_TIME);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "whenChanged", 0, LDB_SYNTAX_UTC_TIME);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "subschemaSubentry", 0, LDB_SYNTAX_DN);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "structuralObjectClass", 0, LDB_SYNTAX_OBJECTCLASS);
-
        if (ret != 0) {
                return ret;
        }
index 13d4adf6d4f44a4c8326fdfeb8ef24d4c3cec0ba..11a824a5492ea467b591edd90ea57ca81f70c825 100755 (executable)
@@ -331,15 +331,15 @@ servicePrincipalName: host/ldaptest2computer29
         print "Testing Ambigious Name Resolution"
         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
-        self.assertEquals(len(res), 3, "Could not find (&(anr=ldap testy)(objectClass=user))")
+        self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
-        self.assertEquals(len(res), 4, "Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
@@ -353,13 +353,13 @@ servicePrincipalName: host/ldaptest2computer29
         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
 
-        # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
+        # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 2, "Found only %d for (&(anr=ldap testy)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
 
-        # Testing ldb.search for (&(anr==ldap testy)(objectClass=user))
+        # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 1, "Found only %d for (&(anr==ldap testy)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
 
         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
index 6d141478ad4a097d162a0a3deb922047e351251e..169ff02da1ad9dfb75862886e156549ccff81a96 100644 (file)
@@ -93,7 +93,7 @@ static void add_records(struct ldb_context *ldb,
                el[2].name = talloc_strdup(tmp_ctx, "uid");
                el[2].num_values = 1;
                el[2].values = vals[2];
-               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
+               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name, strlen(name));
                vals[2][0].length = strlen((char *)vals[2][0].data);
 
                el[3].flags = 0;
index 883597108a03638696bf671689ebf91be95d9d33..6c683a1e33068eb49f8d210f7c403966a3df75b7 100644 (file)
@@ -147,17 +147,21 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
                talloc_free(ldb);
                return NULL;
        }
-       
-       if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
-               dsdb_set_global_schema(ldb);
-       }
 
+       /* This must be done before we load the schema, as these
+        * handlers for objectSid and objectGUID etc must take
+        * precedence over the 'binary attribute' declaration in the
+        * schema */
        ret = ldb_register_samba_handlers(ldb);
        if (ret == -1) {
                talloc_free(ldb);
                return NULL;
        }
 
+       if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
+               dsdb_set_global_schema(ldb);
+       }
+
        ldb_set_debug(ldb, ldb_wrap_debug, NULL);
 
        ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
index e626b6ef8aa7d0797e59e4117553ed5a0a219365..f2982302abb2ac9794b3d36a5215ba93e3377444 100644 (file)
@@ -29,7 +29,7 @@ struct cli_credentials;
 struct loadparm_context;
 struct event_context;
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
                                     struct event_context *ev,
index b258e47bbaf1646b5d09d7c36ea33baa9eab5fa8..57b34b7ae73d8aa698dc9df4fc164dc22a8b4512 100644 (file)
@@ -176,7 +176,7 @@ _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
 {
        DATA_BLOB blob;
        blob.data = discard_const_p(uint8_t, str);
-       blob.length = strlen(str);
+       blob.length = str ? strlen(str) : 0;
        return blob;
 }
 
index 0a7433696e586e84d2a43aa77c6471dd254c5f49..fab729c0367b07985ef8014ff35e7db8268e4399 100644 (file)
@@ -125,9 +125,9 @@ int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string)
        return ret;
 }
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s)
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
 {
-       return strupper_talloc(mem_ctx, s);
+       return strupper_talloc_n(mem_ctx, s, n);
 }
 
 
index 030ba7ebeef6aa0a4145eb47bbf61d665ba35bc5..43f98ae1a9f2f6f6abaace007b6345b875f191de 100644 (file)
@@ -22,6 +22,6 @@ int gendb_search_dn(struct ldb_context *ldb,
                 struct ldb_message ***res,
                 const char * const *attrs);
 int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string);
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 #endif /* __LIB_UTIL_UTIL_LDB_H__ */
index f5457e7e0e4bcf8d927f6fa27b5585e9eb136449..1a7519e362988095b9bb945c7556a5f37f4adceb 100644 (file)
@@ -151,6 +151,21 @@ struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
        return ret;
 }
 
+/*
+  convert a string to a dom_sid, returning a talloc'd dom_sid
+*/
+struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid)
+{
+       struct dom_sid *ret;
+       char *p = talloc_strndup(mem_ctx, sid->data, sid->length);
+       if (!p) {
+               return NULL;
+       }
+       ret = dom_sid_parse_talloc(mem_ctx, p);
+       talloc_free(p);
+       return ret;
+}
+
 /*
   copy a dom_sid structure
 */
index a6d0245455b6a070724f392f7d9052abb6dd7170..63be489e0d9c5c7d7d3b1de7a689d72beedb9ff5 100644 (file)
@@ -353,7 +353,13 @@ interface nbt
                NBT_SERVER_TIMESERV      = 0x00000040,
                NBT_SERVER_CLOSEST       = 0x00000080,
                NBT_SERVER_WRITABLE      = 0x00000100, 
-               NBT_SERVER_GOOD_TIMESERV = 0x00000200
+               NBT_SERVER_GOOD_TIMESERV = 0x00000200,
+               NBT_SERVER_NDNC          = 0x00000400,
+               NBT_SERVER_SEL_SEC_DOM_6 = 0x00000800,
+               NBT_SERVER_FUL_SEC_DOM_6 = 0x00001000,
+               NBT_SERVER_DS_DNS_CONTR  = 0x04000000,
+               NBT_SERVER_DS_DNS_DOMAIN = 0x02000000,
+               NBT_SERVER_DS_DNS_FOREST = 0x01000000
        } nbt_server_type;
 
        typedef [bitmap32bit,public] bitmap {
index 0855efe3bbf572055c7f0222681506bf6272efcc..9c2a208460eb2f59e0e2b27d7bb19dc12e926d10 100644 (file)
@@ -745,12 +745,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
     samdb = SamDB(path, session_info=session_info, 
                   credentials=credentials, lp=lp)
 
-    if fill == FILL_DRS:
-       # We want to finish here, but setup the index before we do so
-        message("Setting up sam.ldb index")
-        samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
-        return samdb
-
     message("Pre-loading the Samba 4 and AD schema")
     samdb.set_domain_sid(domainsid)
     if serverrole == "domain controller":
@@ -886,9 +880,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
                                 domainsid=domainsid, policyguid=policyguid,
                                 setup_path=setup_path)
 
-    #We want to setup the index last, as adds are faster unindexed
-        message("Setting up sam.ldb index")
-        samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
     except:
         samdb.transaction_cancel()
         raise
@@ -1281,39 +1272,38 @@ def provision_backend(setup_dir=None, message=None,
        mmr_syncrepl_user_config = "" 
        
        if ol_mmr_urls is not None:
-               mmr_hosts=filter(None,ol_mmr_urls.split(' ')) 
-                if (len(mmr_hosts) == 1):
-                    mmr_hosts=filter(None,ol_mmr_urls.split(',')) 
+               url_list=filter(None,ol_mmr_urls.split(' ')) 
+                if (len(url_list) == 1):
+                    url_list=filter(None,ol_mmr_urls.split(',')) 
                      
 
                mmr_on_config = "MirrorMode On"
-               
-               z=0
-               for i in mmr_hosts:
-                       z=z+1
+               serverid=0
+               for url in url_list:
+                       serverid=serverid+1
                        mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"),
-                                                                    { "SERVERID" : str(z),
-                                                                      "LDAPSERVER" : i })
-
-                       z=z+1
+                                                                    { "SERVERID" : str(serverid),
+                                                                      "LDAPSERVER" : url })
+                        rid=serverid*10
+                       rid=rid+1
                        mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(z),
+                                                                    {  "RID" : str(rid),
                                                                        "MMRDN": names.schemadn,
-                                                                       "LDAPSERVER" : i,
+                                                                       "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": adminpass})
 
-                       z=z+1
+                       rid=rid+1
                        mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(z),
+                                                                    {  "RID" : str(rid),
                                                                        "MMRDN": names.configdn,
-                                                                       "LDAPSERVER" : i,
+                                                                       "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": adminpass})
 
-                       z=z+1
+                       rid=rid+1
                        mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(z),
+                                                                    {  "RID" : str(rid),
                                                                        "MMRDN": names.domaindn,
-                                                                       "LDAPSERVER" : i,
+                                                                       "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": adminpass })
 
 
index 049b8752a6fefebb82f000c9313bd1d3d437747a..0943da29b616bd2cfc3b0271c635cabff67e67d2 100755 (executable)
@@ -65,7 +65,7 @@ parser.add_option("--server-role", type="choice", metavar="ROLE",
 parser.add_option("--targetdir", type="string", metavar="DIR", 
                          help="Set target directory")
 parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER",
-                help="List of LDAP-URLS separated with whitespaces for Use with OpenLDAP-MMR")
+                help="List of LDAP-URLS [ ldap://<FQDN>:port/  (where port != 389) ] separated with whitespaces for use with OpenLDAP-MMR")
 
 
 opts = parser.parse_args()[0]
diff --git a/source4/setup/provision_index.ldif b/source4/setup/provision_index.ldif
deleted file mode 100644 (file)
index 9597081..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-dn: @INDEXLIST
-@IDXATTR: name
-@IDXATTR: cn
-@IDXATTR: userPrincipalName
-@IDXATTR: servicePrincipalName
-@IDXATTR: sAMAccountName
-@IDXATTR: objectSid
-@IDXATTR: objectCategory
-@IDXATTR: member
-@IDXATTR: uidNumber
-@IDXATTR: gidNumber
-@IDXATTR: unixName
-@IDXATTR: privilege
-@IDXATTR: nCName
-@IDXATTR: lDAPDisplayName
-@IDXATTR: subClassOf
-@IDXATTR: dnsRoot
-@IDXATTR: nETBIOSName
-@IDXATTR: objectGUID
index 65a12f1afa3543a3c176800b0bcbfbec94ce1dbf..a6c591dd51cdf2f04d57ba313312cf18c93852e7 100644 (file)
@@ -1,3 +1,8 @@
+#These attributes are only used as far as the bootstrapping of the
+# schema.  After that, the attributes from the schema are used.
+#
+# Therefore, they must strictly match the schema
+
 dn: @ATTRIBUTES
 userPrincipalName: CASE_INSENSITIVE
 servicePrincipalName: CASE_INSENSITIVE
@@ -7,6 +12,8 @@ nETBIOSName: CASE_INSENSITIVE
 cn: CASE_INSENSITIVE
 dc: CASE_INSENSITIVE
 name: CASE_INSENSITIVE
+lDAPDisplayName: CASE_INSENSITIVE
+subClassOf: CASE_INSENSITIVE
 dn: CASE_INSENSITIVE
 sAMAccountName: CASE_INSENSITIVE
 objectClass: CASE_INSENSITIVE
index 1631297793c8217e19b427bf019479293f3eeb92..3730193c86fb22034eba4a6113d56944aba4f8e8 100644 (file)
@@ -227,6 +227,75 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        return true;
 }
 
+/*
+  test cldap netlogon server type flags
+*/
+static bool test_cldap_netlogon_flags(struct torture_context *tctx,
+       const char *dest)
+{
+       struct cldap_socket *cldap;
+       NTSTATUS status;
+       struct cldap_netlogon search;
+       struct netlogon_samlogon_response n1;
+       uint32_t server_type;
+
+       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
+       printf("Printing out netlogon server type flags:\n");
+
+       ZERO_STRUCT(search);
+       search.in.dest_address = dest;
+       search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+       search.in.acct_control = -1;
+       search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+       search.in.map_response = true;
+
+       status = cldap_netlogon(cldap, tctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       n1 = search.out.netlogon;
+       if (n1.ntver == NETLOGON_NT_VERSION_5)
+               server_type = n1.nt5.server_type;
+       else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
+               server_type = n1.nt5_ex.server_type;    
+
+       printf("The word is: %i\n", server_type);
+       if (server_type & NBT_SERVER_PDC)
+               printf("NBT_SERVER_PDC ");
+       if (server_type & NBT_SERVER_GC)
+               printf("NBT_SERVER_GC ");
+       if (server_type & NBT_SERVER_LDAP)
+               printf("NBT_SERVER_LDAP ");
+       if (server_type & NBT_SERVER_DS)
+               printf("NBT_SERVER_DS ");
+       if (server_type & NBT_SERVER_KDC)
+               printf("NBT_SERVER_KDC ");
+       if (server_type & NBT_SERVER_TIMESERV)
+               printf("NBT_SERVER_TIMESERV ");
+       if (server_type & NBT_SERVER_CLOSEST)
+               printf("NBT_SERVER_CLOSEST ");
+       if (server_type & NBT_SERVER_WRITABLE)
+               printf("NBT_SERVER_WRITABLE ");
+       if (server_type & NBT_SERVER_GOOD_TIMESERV)
+               printf("NBT_SERVER_GOOD_TIMESERV ");
+       if (server_type & NBT_SERVER_NDNC)
+               printf("NBT_SERVER_NDNC ");
+       if (server_type & NBT_SERVER_SEL_SEC_DOM_6)
+               printf("NBT_SERVER_SEL_SEC_DOM_6 ");
+       if (server_type & NBT_SERVER_FUL_SEC_DOM_6)
+               printf("NBT_SERVER_FUL_SEC_DOM_6 ");
+       if (server_type & NBT_SERVER_DS_DNS_CONTR)
+               printf("NBT_SERVER_DS_DNS_CONTR ");
+       if (server_type & NBT_SERVER_DS_DNS_DOMAIN)
+               printf("NBT_SERVER_DS_DNS_DOMAIN ");
+       if (server_type & NBT_SERVER_DS_DNS_FOREST)
+               printf("NBT_SERVER_DS_DNS_FOREST ");
+
+       printf("\n");
+
+       return true;
+}
+
 /*
   convert a ldap result message to a ldb message. This allows us to
   use the convenient ldif dump routines in ldb to print out cldap
@@ -266,6 +335,81 @@ static void cldap_dump_results(struct cldap_search *search)
        talloc_free(ldb);
 }
 
+
+/*
+  test cldap netlogon server type flag "NBT_SERVER_DS_DNS_FOREST"
+*/
+static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
+       const char *dest)
+{
+       struct cldap_socket *cldap;
+       NTSTATUS status;
+       struct cldap_netlogon search;
+       uint32_t server_type;
+       struct netlogon_samlogon_response n1;
+
+       bool result = true;
+
+       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
+       printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: ");
+
+       ZERO_STRUCT(search);
+       search.in.dest_address = dest;
+       search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+       search.in.acct_control = -1;
+       search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+       search.in.map_response = true;
+
+       status = cldap_netlogon(cldap, tctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       n1 = search.out.netlogon;
+       if (n1.ntver == NETLOGON_NT_VERSION_5)
+               server_type = n1.nt5.server_type;
+       else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
+               server_type = n1.nt5_ex.server_type;
+
+       if (server_type & NBT_SERVER_DS_DNS_FOREST) {
+               struct cldap_search search2;
+               const char *attrs[] = { "defaultNamingContext", "rootDomainNamingContext", 
+                       NULL };
+               struct ldb_context *ldb;
+               struct ldb_message *msg;
+
+               /* Trying to fetch the attributes "defaultNamingContext" and
+                  "rootDomainNamingContext" */
+               ZERO_STRUCT(search2);
+               search2.in.dest_address = dest;
+               search2.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+               search2.in.timeout = 10;
+               search2.in.retries = 3;
+               search2.in.filter = "(objectclass=*)";
+               search2.in.attributes = attrs;
+
+               status = cldap_search(cldap, tctx, &search2);
+               CHECK_STATUS(status, NT_STATUS_OK);
+
+               ldb = ldb_init(NULL, NULL);
+
+               msg = ldap_msg_to_ldb(ldb, ldb, search2.out.response);
+
+               /* Try to compare the two attributes */
+               if (ldb_msg_element_compare(ldb_msg_find_element(msg, attrs[0]),
+                       ldb_msg_find_element(msg, attrs[1])))
+                       result = false;
+
+               talloc_free(ldb);
+       }
+
+       if (result)
+               printf("passed\n");
+       else
+               printf("failed\n");
+
+       return result;
+}
+
 /*
   test generic cldap operations
 */
@@ -343,6 +487,8 @@ bool torture_cldap(struct torture_context *torture)
        const char *host = torture_setting_string(torture, "host", NULL);
 
        ret &= test_cldap_netlogon(torture, host);
+       ret &= test_cldap_netlogon_flags(torture, host);
+       ret &= test_cldap_netlogon_flag_ds_dns_forest(torture, host);
        ret &= test_cldap_generic(torture, host);
 
        return ret;