s4-dsdb: added an extended operation for allocating a new RID pool
authorAndrew Tridgell <tridge@samba.org>
Wed, 6 Jan 2010 08:34:14 +0000 (19:34 +1100)
committerAndrew Tridgell <tridge@samba.org>
Fri, 8 Jan 2010 02:03:02 +0000 (13:03 +1100)
This will be called by getncchanges when a client asks for a
DRSUAPI_EXOP_FSMO_RID_ALLOC operation

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/dsdb/samdb/ldb_modules/ridalloc.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/dsdb/samdb/samdb.h
source4/setup/schema_samba4.ldif

index c3d334ff3a39d032097c1dbb8e97607686eaf7d8..2d0753f3930f6d4469a4e4a019588c923a534336 100644 (file)
@@ -33,6 +33,7 @@
 #include "dsdb/samdb/ldb_modules/util.h"
 #include "lib/messaging/irpc.h"
 #include "param/param.h"
+#include "librpc/gen_ndr/ndr_misc.h"
 
 /*
   Note: the RID allocation attributes in AD are very badly named. Here
@@ -140,6 +141,7 @@ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *m
        server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
        if (!server_dn) {
                ldb_module_oom(module);
+               talloc_free(tmp_ctx);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
@@ -315,6 +317,7 @@ static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
        server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
        if (!server_dn) {
                ldb_module_oom(module);
+               talloc_free(tmp_ctx);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
@@ -560,6 +563,93 @@ int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
 
        talloc_free(tmp_ctx);
 
+       return ret;
+}
+
+
+/*
+  called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
+ */
+int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
+{
+       struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
+       struct ldb_dn *rid_manager_dn;
+       TALLOC_CTX *tmp_ctx = talloc_new(module);
+       int ret;
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
+       uint64_t new_pool;
+
+       ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
+                                      GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
+       if (!server_dn) {
+               ldb_module_oom(module);
+               talloc_free(tmp_ctx);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
+                                      ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
 
+       ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
+                                      ldb_errstring(ldb));
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+       if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+               ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
+                                      ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       if (exop->fsmo_info != 0) {
+               const char *attrs[] = { "rIDAllocationPool", NULL };
+               struct ldb_result *res;
+               uint64_t alloc_pool;
+
+               ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
+               if (ret != LDB_SUCCESS) {
+                       ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
+                                              ldb_dn_get_linearized(rid_set_dn));
+                       talloc_free(tmp_ctx);
+                       return ret;
+               }
+
+               alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+               if (alloc_pool != exop->fsmo_info) {
+                       /* it has already been updated */
+                       DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
+                                (unsigned long long)exop->fsmo_info,
+                                (unsigned long long)alloc_pool));
+                       talloc_free(tmp_ctx);
+                       return LDB_SUCCESS;
+               }
+       }
+
+       ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, ntds_dn, &new_pool);
+       talloc_free(tmp_ctx);
        return ret;
 }
index eb83633fe2dc7d356cdb70bbd9be9c523f365060..79bfc0a15cb15cbbbf2b8b211a9f43a34bfacf0e 100644 (file)
@@ -1860,11 +1860,41 @@ static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
        return samldb_prim_group_users_check(ac);
 }
 
+static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
+{
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
+       struct dsdb_fsmo_extended_op *exop;
+       int ret;
+
+       exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
+       if (!exop) {
+               ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
+
+       ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
+
+static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
+{
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
+               return samldb_extended_allocate_rid_pool(module, req);
+       }
+
+       return ldb_next_request(module, req);
+}
+
 
 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
        .name          = "samldb",
        .add           = samldb_add,
        .modify        = samldb_modify,
-       .del           = samldb_delete
+       .del           = samldb_delete,
+       .extended      = samldb_extended
 };
 
index a05aa00f7acf8fa90e7ea4f1356ece5d10bc442d..6df30b2904be3dc547368e8e02bb4d9408014788 100644 (file)
@@ -142,4 +142,12 @@ struct dsdb_extended_dn_store_format {
 
 #define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
 
+/* this takes a struct dsdb_fsmo_extended_op */
+#define DSDB_EXTENDED_ALLOCATE_RID_POOL "1.3.6.1.4.1.7165.4.4.5"
+
+struct dsdb_fsmo_extended_op {
+       uint64_t fsmo_info;
+       struct GUID destination_dsa_guid;
+};
+
 #endif /* __SAMDB_H__ */
index 70ae5d8d776e86047985baa600d99936912a0953..e28aa0e5cba2d85d66935672810b4db9688d5931 100644 (file)
 #Allocated: DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID 1.3.6.1.4.1.7165.4.4.2
 #Allocated: LDB_EXTENDED_SEQUENCE_NUMBER 1.3.6.1.4.1.7165.4.4.3
 #Allocated: DSDB_EXTENDED_CREATE_PARTITION_OID 1.3.6.1.4.1.7165.4.4.4
+#Allocated: DSDB_EXTENDED_ALLOCATE_RID_POOL 1.3.6.1.4.1.7165.4.4.5
 
 #Allocated: (middleName) attributeID: 1.3.6.1.4.1.7165.4.255.1