Pull in all the schema information during DRS schema fetch
[kai/samba.git] / source4 / dsdb / schema / schema_init.c
index 3ed7daee5953aa8a778436a01baf08ea286708dc..a67aecd1e866289cf6e119eb8e74e3524ef9ab1e 100644 (file)
@@ -23,7 +23,7 @@
 #include "includes.h"
 #include "dsdb/samdb/samdb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
@@ -199,9 +199,8 @@ WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
                return ntstatus_to_werror(nt_status);
        }
 
-       *schemaInfo = strhex_to_data_blob(schema->schema_info);
+       *schemaInfo = strhex_to_data_blob(mem_ctx, schema->schema_info);
        W_ERROR_HAVE_NO_MEMORY(schemaInfo->data);
-       talloc_steal(mem_ctx, schemaInfo->data);
 
        return WERR_OK;
 }
@@ -525,18 +524,21 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                return WERR_FOOBAR;
        }
 
-       ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, schema_attrs,&schema_res);
+       ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
                DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
+               talloc_free(schema_res);
                return WERR_FOOBAR;
        } else if (ret != LDB_SUCCESS) {
                DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
+               talloc_free(schema_res);
                return WERR_FOOBAR;
        }
 
        prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
        if (!prefix_val) {
                DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
+               talloc_free(schema_res);
                return WERR_FOOBAR;
        }
 
@@ -550,9 +552,12 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n"));
                talloc_free(blob);
+               talloc_free(schema_res);
                return WERR_FOOBAR;
        }
 
+       talloc_free(schema_res);
+
        if (blob->version != PREFIX_MAP_VERSION_DSDB) {
                DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n"));
                talloc_free(blob);
@@ -638,6 +643,24 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        (p)->elem = samdb_result_uint(msg, attr, 0);\
 } while (0)
 
+#define GET_UINT32_PTR_LDB(msg, attr, p, elem) do { \
+       uint64_t _v = samdb_result_uint64(msg, attr, UINT64_MAX);\
+       if (_v == UINT64_MAX) { \
+               (p)->elem = NULL; \
+       } else if (_v > UINT32_MAX) { \
+               d_printf("%s: %s == 0x%llX\n", __location__, \
+                        attr, (unsigned long long)_v); \
+               return WERR_INVALID_PARAM; \
+       } else { \
+               (p)->elem = talloc(mem_ctx, uint32_t); \
+               if (!(p)->elem) { \
+                       d_printf("%s: talloc failed for %s\n", __location__, attr); \
+                       return WERR_NOMEM; \
+               } \
+               *(p)->elem = (uint32_t)_v; \
+       } \
+} while (0)
+
 #define GET_GUID_LDB(msg, attr, p, elem) do { \
        (p)->elem = samdb_result_guid(msg, attr);\
 } while (0)
@@ -702,8 +725,8 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema,
        GET_BLOB_LDB(msg, "oMObjectClass", mem_ctx, attr, oMObjectClass);
 
        GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
-       GET_UINT32_LDB(msg, "rangeLower", attr, rangeLower);
-       GET_UINT32_LDB(msg, "rangeUpper", attr, rangeUpper);
+       GET_UINT32_PTR_LDB(msg, "rangeLower", attr, rangeLower);
+       GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, rangeUpper);
        GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
 
        GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
@@ -813,12 +836,11 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        }
        info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
        if (!info_val) {
-               info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
+               info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000");
                if (!info_val_default.data) {
                        dsdb_oom(error_string, mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
-               talloc_steal(mem_ctx, info_val_default.data);
                info_val = &info_val_default;
        }
 
@@ -905,7 +927,7 @@ static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,
                const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i], 
                                                               "lDAPDisplayname", NULL);
 
-               ret = ldb_search_exp_fmt(ldb, mem_ctx, &res,
+               ret = ldb_search(ldb, mem_ctx, &res,
                                        schemadn, LDB_SCOPE_SUBTREE, NULL,
                                        "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))",
                                        name, name);
@@ -946,9 +968,9 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche
        }
        
        /* Download 'top' */
-       ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, 
-                        "(&(objectClass=classSchema)(lDAPDisplayName=top))", 
-                        NULL, &top_res);
+       ret = ldb_search(ldb, local_ctx, &top_res,
+                        schemadn, LDB_SCOPE_SUBTREE, NULL,
+                        "(&(objectClass=classSchema)(lDAPDisplayName=top))");
        if (ret != LDB_SUCCESS) {
                *error_string = talloc_asprintf(mem_ctx, 
                                                "dsdb_schema: failed to search for top classSchema object: %s",
@@ -956,8 +978,6 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche
                return ret;
        }
 
-       talloc_steal(local_ctx, top_res);
-
        if (top_res->count != 1) {
                *error_string = talloc_asprintf(mem_ctx, 
                                                "dsdb_schema: failed to find top classSchema object");
@@ -1008,10 +1028,8 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        /*
         * setup the prefix mappings and schema info
         */
-       ret = ldb_search(ldb, schema_dn,
-                        LDB_SCOPE_BASE,
-                        NULL, schema_attrs,
-                        &schema_res);
+       ret = ldb_search(ldb, tmp_ctx, &schema_res,
+                        schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
                talloc_free(tmp_ctx);
                return ret;
@@ -1022,7 +1040,6 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                talloc_free(tmp_ctx);
                return ret;
        }
-       talloc_steal(tmp_ctx, schema_res);
        if (schema_res->count != 1) {
                *error_string_out = talloc_asprintf(mem_ctx, 
                              "dsdb_schema: [%u] schema heads found on a base search",
@@ -1034,10 +1051,9 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        /*
         * load the attribute definitions
         */
-       ret = ldb_search(ldb, schema_dn,
-                        LDB_SCOPE_ONELEVEL,
-                        "(objectClass=attributeSchema)", NULL,
-                        &a_res);
+       ret = ldb_search(ldb, tmp_ctx, &a_res,
+                        schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+                        "(objectClass=attributeSchema)");
        if (ret != LDB_SUCCESS) {
                *error_string_out = talloc_asprintf(mem_ctx, 
                                       "dsdb_schema: failed to search attributeSchema objects: %s",
@@ -1045,7 +1061,6 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                talloc_free(tmp_ctx);
                return ret;
        }
-       talloc_steal(tmp_ctx, a_res);
 
        /*
         * load the objectClass definitions
@@ -1171,12 +1186,11 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
                return WERR_INVALID_PARAM; \
        } \
        if (_a && _a->value_ctr.num_values >= 1) { \
-               ssize_t _ret; \
-               _ret = convert_string_talloc(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \
+               size_t _ret; \
+               if (!convert_string_talloc_convenience(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \
                                             _a->value_ctr.values[0].blob->data, \
                                             _a->value_ctr.values[0].blob->length, \
-                                            (void **)discard_const(&(p)->elem)); \
-               if (_ret == -1) { \
+                                            (void **)discard_const(&(p)->elem), &_ret, false)) { \
                        DEBUG(0,("%s: invalid data!\n", attr)); \
                        dump_data(0, \
                                     _a->value_ctr.values[0].blob->data, \
@@ -1188,6 +1202,34 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
        } \
 } while (0)
 
+#define GET_STRING_LIST_DS(s, r, attr, mem_ctx, p, elem, strict) do { \
+       int get_string_list_counter;                                    \
+       struct drsuapi_DsReplicaAttribute *_a; \
+       _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
+       if (strict && !_a) { \
+               d_printf("%s: %s == NULL\n", __location__, attr); \
+               return WERR_INVALID_PARAM; \
+       } \
+       (p)->elem = _a ? talloc_array(mem_ctx, const char *, _a->value_ctr.num_values + 1) : NULL; \
+        for (get_string_list_counter=0;                                        \
+            _a && get_string_list_counter < _a->value_ctr.num_values;  \
+            get_string_list_counter++) {                               \
+               size_t _ret;                                            \
+               if (!convert_string_talloc_convenience(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \
+                                            _a->value_ctr.values[get_string_list_counter].blob->data, \
+                                            _a->value_ctr.values[get_string_list_counter].blob->length, \
+                                                      (void **)discard_const(&(p)->elem[get_string_list_counter]), &_ret, false)) { \
+                       DEBUG(0,("%s: invalid data!\n", attr)); \
+                       dump_data(0, \
+                                    _a->value_ctr.values[get_string_list_counter].blob->data, \
+                                    _a->value_ctr.values[get_string_list_counter].blob->length); \
+                       return WERR_FOOBAR; \
+               } \
+               (p)->elem[get_string_list_counter+1] = NULL;            \
+       }                                                               \
+       talloc_steal(mem_ctx, (p)->elem);                               \
+} while (0)
+
 #define GET_DN_DS(s, r, attr, mem_ctx, p, elem, strict) do { \
        struct drsuapi_DsReplicaAttribute *_a; \
        _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
@@ -1263,6 +1305,23 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
        } \
 } while (0)
 
+#define GET_UINT32_PTR_DS(s, r, attr, p, elem) do { \
+       struct drsuapi_DsReplicaAttribute *_a; \
+       _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
+       if (_a && _a->value_ctr.num_values >= 1 \
+           && _a->value_ctr.values[0].blob \
+           && _a->value_ctr.values[0].blob->length == 4) { \
+               (p)->elem = talloc(mem_ctx, uint32_t); \
+               if (!(p)->elem) { \
+                       d_printf("%s: talloc failed for %s\n", __location__, attr); \
+                       return WERR_NOMEM; \
+               } \
+               *(p)->elem = IVAL(_a->value_ctr.values[0].blob->data,0);\
+       } else { \
+               (p)->elem = NULL; \
+       } \
+} while (0)
+
 #define GET_GUID_DS(s, r, attr, mem_ctx, p, elem) do { \
        struct drsuapi_DsReplicaAttribute *_a; \
        _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
@@ -1333,8 +1392,8 @@ WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema,
        GET_BLOB_DS(schema, r, "oMObjectClass", mem_ctx, attr, oMObjectClass);
 
        GET_BOOL_DS(schema, r, "isSingleValued", attr, isSingleValued, true);
-       GET_UINT32_DS(schema, r, "rangeLower", attr, rangeLower);
-       GET_UINT32_DS(schema, r, "rangeUpper", attr, rangeUpper);
+       GET_UINT32_PTR_DS(schema, r, "rangeLower", attr, rangeLower);
+       GET_UINT32_PTR_DS(schema, r, "rangeUpper", attr, rangeUpper);
        GET_BOOL_DS(schema, r, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
 
        GET_UINT32_DS(schema, r, "schemaFlagsEx", attr, schemaFlagsEx);
@@ -1381,17 +1440,18 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema,
 
        GET_STRING_DS(schema, r, "subClassOf", mem_ctx, obj, subClassOf, true);
 
-       obj->systemAuxiliaryClass       = NULL;
-       obj->systemPossSuperiors        = NULL;
-       obj->systemMustContain          = NULL;
-       obj->systemMayContain           = NULL;
 
-       obj->auxiliaryClass             = NULL;
-       obj->possSuperiors              = NULL;
-       obj->mustContain                = NULL;
-       obj->mayContain                 = NULL;
+       GET_STRING_LIST_DS(schema, r, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass, false);
+       GET_STRING_LIST_DS(schema, r, "auxiliaryClass", mem_ctx, obj, auxiliaryClass, false);
+
+       GET_STRING_LIST_DS(schema, r, "systemMustContain", mem_ctx, obj, systemMustContain, false);
+       GET_STRING_LIST_DS(schema, r, "systemMayContain", mem_ctx, obj, systemMayContain, false);
+       GET_STRING_LIST_DS(schema, r, "mustContain", mem_ctx, obj, mustContain, false);
+       GET_STRING_LIST_DS(schema, r, "mayContain", mem_ctx, obj, mayContain, false);
 
-       obj->possibleInferiors          = NULL;
+       GET_STRING_LIST_DS(schema, r, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false);
+       GET_STRING_LIST_DS(schema, r, "possSuperiors", mem_ctx, obj, possSuperiors, false);
+       GET_STRING_LIST_DS(schema, r, "possibleInferiors", mem_ctx, obj, possibleInferiors, false);
 
        GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false);