Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
authorAndrew Bartlett <abartlet@samba.org>
Wed, 20 Aug 2008 06:02:13 +0000 (16:02 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 20 Aug 2008 06:02:13 +0000 (16:02 +1000)
(This used to be commit ae502f9e3991209d70a745bef3a3e6e7484cdb5f)

12 files changed:
source4/cldap_server/netlogon.c
source4/dsdb/common/flags.h
source4/dsdb/config.mk
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/ldb/include/ldb_private.h
source4/librpc/idl/nbt.idl
source4/scripting/python/samba/provision.py
source4/setup/provision-backend
source4/setup/provision_init.ldif
source4/torture/ldap/cldap.c

index f263f33d48889ac89d5154c0be3a875b24a03064..084714f4cf5c5f9972791cea3187052cb6ae3774 100644 (file)
@@ -256,7 +256,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 +275,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 +290,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 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..b8b39bd
--- /dev/null
@@ -0,0 +1,303 @@
+/* 
+   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 schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+       int ret = LDB_SUCCESS;
+       
+       struct dsdb_attribute *attr;
+       
+       for (attr = schema->attributes; attr; attr = attr->next) {
+               const struct ldb_schema_syntax *s;
+               if (!attr->syntax) {
+                       continue;
+               }
+               if (attr->syntax->ldb_syntax) {
+                       ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, 0,
+                                                      attr->syntax->ldb_syntax);
+               } else {
+                       s = ldb_standard_syntax_by_name(ldb, attr->syntax->ldap_oid);
+                       if (s) {
+                               ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, 0, s);
+                       } else {
+                               s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
+                               if (s) {
+                                       ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, 0, s);
+                               } else {
+                                       ret = LDB_SUCCESS; /* Nothing to do here */
+                               }
+                       }
+               }
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       /* Now put back the hardcoded Samba special handlers */
+       return ldb_register_samba_handlers(ldb);
+}
+
+
+/**
+ * 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;
+       }
+
+       ret = schema_set_attributes(ldb, 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;
+       }
+
+       ret = schema_set_attributes(ldb, 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;
+}
index d7c2efe8a1a2b86c9aa3c1abbe27ba067bb6bdb0..62a6e35999d69c3e5382191c02b6570110ab7051 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;
 };
 
 /*
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..d14ce58f045a56e8278b5bc9f715b7e2f80c7a88 100644 (file)
@@ -1281,39 +1281,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]
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;