The branch, v4-0-test has been updated
       via  bbe895db7144b192981fad9ab6bbd3ebacb8d299 (commit)
       via  39f9184ddf215f2b512319211c0a05702218ef87 (commit)
      from  a7bfa1fb1bc6fb8e412990b7ff4c3ce9bc55099d (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit bbe895db7144b192981fad9ab6bbd3ebacb8d299
Author: Anatoliy Atanasov <[EMAIL PROTECTED]>
Date:   Mon Jul 21 17:04:49 2008 +0300

    dsdb_create_prefix_mapping() implementation checks for existing prefix 
maping in ldb.
    if one not found it creates a mapping for it and updates the prefixMap 
schema attribute in ldb.

commit 39f9184ddf215f2b512319211c0a05702218ef87
Author: Anatoliy Atanasov <[EMAIL PROTECTED]>
Date:   Wed Jul 23 09:59:17 2008 +0300

    Handle schema reloading request.
    The ldif for that operation looks like this:
    
    dn:
    changetype: Modify
    add: schemaUpdateNow
    schemaUpdateNow: 1
    
    It uses the rootdse's object functional attribute schemaUpdateNow.
    In rootdse_modify() this command is being recognized and it is send as 
extended operation with DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID.
    In the partition module its dispatched to the schema_fsmo module.
    The request is processed in the schema_fsmo module by 
schema_fsmo_extended().

-----------------------------------------------------------------------

Summary of changes:
 source/dsdb/samdb/ldb_modules/partition.c   |   49 +++++
 source/dsdb/samdb/ldb_modules/rootdse.c     |   47 ++++-
 source/dsdb/samdb/ldb_modules/schema_fsmo.c |   64 ++++++-
 source/dsdb/samdb/samdb.h                   |    2 +
 source/dsdb/schema/schema_init.c            |  293 +++++++++++++++++++++++----
 5 files changed, 415 insertions(+), 40 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/dsdb/samdb/ldb_modules/partition.c 
b/source/dsdb/samdb/ldb_modules/partition.c
index 22826e4..9285d6d 100644
--- a/source/dsdb/samdb/ldb_modules/partition.c
+++ b/source/dsdb/samdb/ldb_modules/partition.c
@@ -699,6 +699,50 @@ static int partition_extended_replicated_objects(struct 
ldb_module *module, stru
        return partition_replicate(module, req, ext->partition_dn);
 }
 
+static int partition_extended_schema_update_now(struct ldb_module *module, 
struct ldb_request *req)
+{
+       struct dsdb_control_current_partition *partition;
+       struct partition_private_data *data;
+       struct ldb_dn *schema_dn;
+       struct partition_context *ac;
+       struct ldb_module *backend;
+       int ret;
+
+       schema_dn = talloc_get_type(req->op.extended.data, struct ldb_dn);
+       if (!schema_dn) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "partition_extended: 
invalid extended data\n");
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
+
+       data = talloc_get_type(module->private_data, struct 
partition_private_data);
+       if (!data) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       partition = find_partition( data, schema_dn );
+       if (!partition) {
+               return ldb_next_request(module, req);
+       }
+
+       ac = partition_init_handle(req, module);
+       if (!ac) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       backend = make_module_for_next_request(req, module->ldb, 
partition->module);
+       if (!backend) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, 
false, partition);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       return ldb_next_request(backend, req);
+}
+
+
 /* extended */
 static int partition_extended(struct ldb_module *module, struct ldb_request 
*req)
 {
@@ -708,6 +752,11 @@ static int partition_extended(struct ldb_module *module, 
struct ldb_request *req
                return partition_extended_replicated_objects(module, req);
        }
 
+       /* forward schemaUpdateNow operation to schema_fsmo module*/
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) 
== 0) {
+               return partition_extended_schema_update_now( module, req );
+       }       
+
        /* 
         * as the extended operation has no dn
         * we need to send it to all partitions
diff --git a/source/dsdb/samdb/ldb_modules/rootdse.c 
b/source/dsdb/samdb/ldb_modules/rootdse.c
index 75f99a1..97491a2 100644
--- a/source/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source/dsdb/samdb/ldb_modules/rootdse.c
@@ -391,9 +391,50 @@ static int rootdse_init(struct ldb_module *module)
        return ldb_next_init(module);
 }
 
+static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
+{
+       struct ldb_result *ext_res;
+       int ret;
+       struct ldb_dn *schema_dn;
+       struct ldb_message_element *schemaUpdateNowAttr;
+       
+       /*
+               If dn is not "" we should let it pass through
+       */
+       if (!ldb_dn_is_null(req->op.mod.message->dn)) {
+               return ldb_next_request(module, req);
+       }
+       
+       /*
+               dn is empty so check for schemaUpdateNow attribute
+               "The type of modification and values specified in the LDAP 
modify operation do not matter." MSDN
+       */
+       schemaUpdateNowAttr = ldb_msg_find_element(req->op.mod.message, 
"schemaUpdateNow");
+       if (!schemaUpdateNowAttr) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       schema_dn = samdb_schema_dn(module->ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "rootdse_modify: no schema dn present: (skip 
ldb_extended call)\n");
+               return ldb_next_request(module, req);
+       }
+
+       ret = ldb_extended(module->ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, 
schema_dn, &ext_res);
+       if (ret != LDB_SUCCESS) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       talloc_free(ext_res);
+       return ret;
+}
+
 _PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
        .name                   = "rootdse",
-       .init_context           = rootdse_init,
-       .search                 = rootdse_search,
-       .request                = rootdse_request
+       .init_context   = rootdse_init,
+       .search         = rootdse_search,
+       .request                = rootdse_request,
+       .modify         = rootdse_modify
 };
diff --git a/source/dsdb/samdb/ldb_modules/schema_fsmo.c 
b/source/dsdb/samdb/ldb_modules/schema_fsmo.c
index a397228..2acc5c0 100644
--- a/source/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -148,8 +148,70 @@ static int schema_fsmo_add(struct ldb_module *module, 
struct ldb_request *req)
        return ldb_next_request(module, req);
 }
 
+static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request 
*req)
+{
+       WERROR status;
+       struct ldb_dn *schema_dn;
+       struct dsdb_schema *schema;
+       char *error_string = NULL;
+       int ret;
+       TALLOC_CTX *mem_ctx;
+       
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) 
!= 0) {
+               return ldb_next_request(module, req);
+       }
+       
+       schema_dn = samdb_schema_dn(module->ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "schema_fsmo_extended: no schema dn present: (skip 
schema loading)\n");
+               return ldb_next_request(module, req);
+       }
+       
+       mem_ctx = talloc_new(module);
+       if (!mem_ctx) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
+                                        
lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
+                                        schema_dn, &schema, &error_string);
+
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "schema_fsmo_extended: no schema head present: (skip 
schema loading)\n");
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(module->ldb, 
+                                      "schema_fsmo_extended: dsdb_schema load 
failed: %s",
+                                      error_string);
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       /* Replace the old schema*/
+       ret = dsdb_set_schema(module->ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
+                             "schema_fsmo_extended: dsdb_set_schema() failed: 
%d:%s",
+                             ret, ldb_strerror(ret));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       talloc_free(mem_ctx);
+       return LDB_SUCCESS;
+}
+
 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
        .name           = "schema_fsmo",
        .init_context   = schema_fsmo_init,
-       .add            = schema_fsmo_add
+       .add            = schema_fsmo_add,
+       .extended       = schema_fsmo_extended
 };
diff --git a/source/dsdb/samdb/samdb.h b/source/dsdb/samdb/samdb.h
index 75aa819..b8a3e16 100644
--- a/source/dsdb/samdb/samdb.h
+++ b/source/dsdb/samdb/samdb.h
@@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo {
        struct ldb_dn *master_dn;
 };
 
+#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
+
 #endif /* __SAMDB_H__ */
diff --git a/source/dsdb/schema/schema_init.c b/source/dsdb/schema/schema_init.c
index 71d952b..2ec5ad3 100644
--- a/source/dsdb/schema/schema_init.c
+++ b/source/dsdb/schema/schema_init.c
@@ -268,18 +268,145 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct 
dsdb_schema *schema, const
 
 WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, 
uint32_t *out)
 {
+       return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, 
in, out);
+}
+
+
+WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, 
TALLOC_CTX *mem_ctx, const char **out)
+{
        uint32_t i;
 
        for (i=0; i < schema->num_prefixes; i++) {
+               const char *val;
+               if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
+                       continue;
+               }
+
+               val = talloc_asprintf(mem_ctx, "%s%u",
+                                     schema->prefixes[i].oid,
+                                     in & 0xFFFF);
+               W_ERROR_HAVE_NO_MEMORY(val);
+
+               *out = val;
+               return WERR_OK;
+       }
+
+       return WERR_DS_NO_MSDS_INTID;
+}
+
+/*
+ * this function is called from within a ldb transaction from the schema_fsmo 
module
+ */
+WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema 
*schema, const char *full_oid)
+{
+       WERROR status;
+       uint32_t num_prefixes;
+       struct dsdb_schema_oid_prefix *prefixes;
+       struct ldb_val ndr_blob;
+       TALLOC_CTX *mem_ctx;
+       uint32_t out;
+
+       mem_ctx = talloc_new(ldb);
+       W_ERROR_HAVE_NO_MEMORY(mem_ctx);
+
+       /* Read prefixes from disk*/
+       status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, 
&prefixes ); 
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(0,("dsdb_create_prefix_mapping: 
dsdb_read_prefixes_from_ldb failed\n"));
+               talloc_free(mem_ctx);
+               return status;
+       }
+
+       /* Check if there is a prefix for the oid in the prefixes array*/
+       status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, 
&out ); 
+       if (W_ERROR_IS_OK(status)) {
+               /* prefix found*/
+               talloc_free(mem_ctx);
+               return status;
+       }
+       /* Update prefix map in ldb*/
+       /* Update the prefixes */
+       status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, 
full_oid);
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update 
failed\n"));
+               talloc_free(mem_ctx);
+               return status;
+       }
+       /* Convert prefixes in ndr blob*/
+       status = dsdb_write_prefixes_to_ndr( mem_ctx, ldb, num_prefixes, 
prefixes, &ndr_blob );
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(0,("dsdb_create_prefix_mapping: 
dsdb_write_prefixes_to_ndr failed\n"));
+               talloc_free(mem_ctx);
+               return status;
+       }
+
+       /* Update prefixMap in ldb*/
+       status = dsdb_write_prefixes_to_ldb( mem_ctx, ldb, &ndr_blob );
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(0,("dsdb_create_prefix_mapping: 
dsdb_write_prefixes_to_ldb failed\n"));
+               talloc_free(mem_ctx);
+               return status;
+       }
+
+       talloc_free(mem_ctx);
+       return status;
+}
+
+WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, 
struct dsdb_schema_oid_prefix **prefixes, const char *oid)
+{
+       uint32_t new_num_prefixes, index_new_prefix, new_entry_id;
+       const char* lastDotOffset;
+       size_t size;
+       
+       new_num_prefixes = *num_prefixes + 1;
+       index_new_prefix = *num_prefixes;
+       new_entry_id = (*num_prefixes)<<16;
+
+       /* Extract the prefix from the oid*/
+       lastDotOffset = strrchr(oid, '.');
+       if (lastDotOffset == NULL) {
+               DEBUG(0,("dsdb_prefix_map_update: failed to find the last 
dot\n"));
+               return WERR_NOT_FOUND;
+       }
+
+       /* Calculate the size of the remainig string that should be the prefix 
of it */
+       size = strlen(oid) - strlen(lastDotOffset);
+       if (size <= 0) {
+               DEBUG(0,("dsdb_prefix_map_update: size of the remaining string 
invalid\n"));
+               return WERR_FOOBAR;
+       }
+       /* Add one because we need to copy the dot */
+       size += 1;
+
+       /* Create a spot in the prefixMap for one more prefix*/
+       (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct 
dsdb_schema_oid_prefix, new_num_prefixes);
+       W_ERROR_HAVE_NO_MEMORY(*prefixes);
+
+       /* Add the new prefix entry*/
+       (*prefixes)[index_new_prefix].id = new_entry_id;
+       (*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size);
+       (*prefixes)[index_new_prefix].oid_len = 
strlen((*prefixes)[index_new_prefix].oid);
+
+       /* Increase num_prefixes because new prefix has been added */
+       ++(*num_prefixes);
+
+       return WERR_OK;
+}
+
+WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct 
dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
+{
+       uint32_t i;
+
+       for (i=0; i < num_prefixes; i++) {
                const char *val_str;
                char *end_str;
                unsigned val;
 
-               if (strncmp(schema->prefixes[i].oid, in, 
schema->prefixes[i].oid_len) != 0) {
+               if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
                        continue;
                }
 
-               val_str = in + schema->prefixes[i].oid_len;
+               val_str = in + prefixes[i].oid_len;
                end_str = NULL;
                errno = 0;
 
@@ -305,58 +432,152 @@ WERROR dsdb_map_oid2int(const struct dsdb_schema 
*schema, const char *in, uint32
                        return WERR_INVALID_PARAM;
                }
 
-               *out = schema->prefixes[i].id | val;
+               *out = prefixes[i].id | val;
                return WERR_OK;
        }
 
        return WERR_DS_NO_MSDS_INTID;
 }
 
-WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, 
TALLOC_CTX *mem_ctx, const char **out)
+WERROR dsdb_write_prefixes_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context 
*ldb, struct ldb_val *ndr_blob)
 {
+       struct ldb_message msg;
+       struct ldb_dn *schema_dn;
+       struct ldb_message_element el;
+       int ret;
+       
+       schema_dn = samdb_schema_dn(ldb);
+       if (!schema_dn) {
+               DEBUG(0,("dsdb_write_prefixes_to_ldb: no schema dn 
present\n"));        
+               return WERR_FOOBAR;
+       }
+ 
+       el.num_values = 1;
+       el.values = ndr_blob;
+       el.flags = LDB_FLAG_MOD_REPLACE;
+       el.name = talloc_strdup(mem_ctx, "prefixMap");
+ 
+       msg.dn = ldb_dn_copy(mem_ctx, schema_dn);
+       msg.num_elements = 1;
+       msg.elements = &el;
+ 
+       ret = ldb_modify( ldb, &msg );
+       if (ret != 0) {
+               DEBUG(0,("dsdb_write_prefixes_to_ldb: ldb_modify failed\n"));   
+               return WERR_FOOBAR;
+       }
+ 
+       return WERR_OK;
+}
+
+WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context 
*ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
+{
+       struct prefixMapBlob *blob;
+       enum ndr_err_code ndr_err;
        uint32_t i;
+       const struct ldb_val *prefix_val;
+       struct ldb_dn *schema_dn;
+       struct ldb_result *schema_res;
+       int ret;    
+       static const char *schema_attrs[] = {
+               "prefixMap",
+               NULL
+       };
 
-       for (i=0; i < schema->num_prefixes; i++) {
-               const char *val;
-               if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
-                       continue;
-               }
+       schema_dn = samdb_schema_dn(ldb);
+       if (!schema_dn) {
+               DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn 
present\n"));
+               return WERR_FOOBAR;
+       }
 
-               val = talloc_asprintf(mem_ctx, "%s%u",
-                                     schema->prefixes[i].oid,
-                                     in & 0xFFFF);
-               W_ERROR_HAVE_NO_MEMORY(val);
+       ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, 
schema_attrs,&schema_res);
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map 
present\n"));
+               return WERR_FOOBAR;
+       } else if (ret != LDB_SUCCESS) {
+               DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the 
schema head\n"));
+               return WERR_FOOBAR;
+       }
 
-               *out = val;
-               return WERR_OK;
+       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"));
+               return WERR_FOOBAR;
        }
 
-       return WERR_DS_NO_MSDS_INTID;
+       blob = talloc(mem_ctx, struct prefixMapBlob);
+       W_ERROR_HAVE_NO_MEMORY(blob);
+
+       ndr_err = ndr_pull_struct_blob(prefix_val, blob, 
+                                          
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
+                                          blob,
+                                          
(ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob 
failed\n"));
+               talloc_free(blob);
+               return WERR_FOOBAR;
+       }
+
+       if (blob->version != PREFIX_MAP_VERSION_DSDB) {
+               DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version 
incorect\n"));
+               talloc_free(blob);
+               return WERR_FOOBAR;
+       }
+       
+       *num_prefixes = blob->ctr.dsdb.num_mappings;
+       *prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, 
*num_prefixes);
+       if(!(*prefixes)) {
+               talloc_free(blob);
+               return WERR_NOMEM;
+       }
+       for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
+               (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
+               (*prefixes)[i].oid = talloc_strdup(mem_ctx, 
blob->ctr.dsdb.mappings[i].oid.oid);
+               (*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, 
"."); 
+               (*prefixes)[i].oid_len = 
strlen(blob->ctr.dsdb.mappings[i].oid.oid);
+       }
+
+       talloc_free(blob);
+       return WERR_OK;
 }
 
-/*
- * this function is called from within a ldb transaction from the schema_fsmo 
module
- */
-WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema 
*schema, const char *full_oid)
+
+WERROR dsdb_write_prefixes_to_ndr(TALLOC_CTX *mem_ctx, struct ldb_context 
*ldb, uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, 
struct ldb_val *out)
 {
-       /*
-        * TODO:


-- 
Samba Shared Repository

Reply via email to