s4-dsdb: added new control DSDB_MODIFY_PARTIAL_REPLICA
authorAndrew Tridgell <tridge@samba.org>
Wed, 28 Sep 2011 01:04:29 +0000 (11:04 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 4 Oct 2011 04:08:57 +0000 (15:08 +1100)
this control tells the partition module that the DN being created is a
partial replica, so it should modify the @PARTITION object to add the
partialReplica attribute

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

source4/dsdb/common/util.c
source4/dsdb/common/util.h
source4/dsdb/repl/replicated_objects.c
source4/dsdb/samdb/ldb_modules/new_partition.c
source4/dsdb/samdb/ldb_modules/partition_init.c
source4/dsdb/samdb/samdb.h
source4/setup/schema_samba4.ldif

index cf28f1dd01238e9a08e2dd88cecbf519eb9a2492..3a55a553068026cc4498f58e1d25c9c8c2e60850 100644 (file)
@@ -3751,6 +3751,13 @@ int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
                }
        }
 
+       if (dsdb_flags & DSDB_MODIFY_PARTIAL_REPLICA) {
+               ret = ldb_request_add_control(req, DSDB_CONTROL_PARTIAL_REPLICA, false, NULL);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
        return LDB_SUCCESS;
 }
 
@@ -4467,3 +4474,62 @@ NTSTATUS dsdb_ldb_err_to_ntstatus(int err)
        }
        return NT_STATUS_UNSUCCESSFUL;
 }
+
+
+/*
+  create a new naming context that will hold a partial replica
+ */
+int dsdb_create_partial_replica_NC(struct ldb_context *ldb,  struct ldb_dn *dn)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(ldb);
+       struct ldb_message *msg;
+       int ret;
+
+       msg = ldb_msg_new(tmp_ctx);
+       if (msg == NULL) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+
+       msg->dn = dn;
+       ret = ldb_msg_add_string(msg, "objectClass", "top");
+       if (ret != LDB_SUCCESS) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+
+       /* [MS-DRSR] implies that we should only add the 'top'
+        * objectclass, but that would cause lots of problems with our
+        * objectclass code as top is not structural, so we add
+        * 'domainDNS' as well to keep things sane. We're expecting
+        * this new NC to be of objectclass domainDNS after
+        * replication anyway
+        */
+       ret = ldb_msg_add_string(msg, "objectClass", "domainDNS");
+       if (ret != LDB_SUCCESS) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+
+       ret = ldb_msg_add_fmt(msg, "instanceType", "%u",
+                             INSTANCE_TYPE_IS_NC_HEAD|
+                             INSTANCE_TYPE_NC_ABOVE|
+                             INSTANCE_TYPE_UNINSTANT);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+
+       ret = dsdb_add(ldb, msg, DSDB_MODIFY_PARTIAL_REPLICA);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to create new NC for %s - %s\n",
+                        ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       DEBUG(1,("Created new NC for %s\n", ldb_dn_get_linearized(dn)));
+
+       talloc_free(tmp_ctx);
+       return LDB_SUCCESS;
+}
index 75ef49e1c33749fc034afb3c66dc5b4f60bbd58c..b2f7aa5b32d1ba1a1793c62e20cfe1e407e2d5bc 100644 (file)
@@ -37,6 +37,7 @@
 #define DSDB_PROVISION                       0x0800
 #define DSDB_BYPASS_PASSWORD_HASH            0x1000
 #define DSDB_SEARCH_NO_GLOBAL_CATALOG        0x2000
+#define DSDB_MODIFY_PARTIAL_REPLICA          0x4000
 
 bool is_attr_in_list(const char * const * attrs, const char *attr);
 
index e1e6b0c92656684a445fb67a6d1135e6d0070c44..5ccf05255487213c7e3a76dec7a7a9b6743a1067 100644 (file)
@@ -686,64 +686,6 @@ static WERROR dsdb_origin_object_convert(struct ldb_context *ldb,
        return WERR_OK;
 }
 
-/*
-  create a new naming context via a DsAddEntry() with a nCName in a
-  crossRef object
- */
-static WERROR dsdb_origin_create_NC(struct ldb_context *ldb,
-                                   struct ldb_dn *dn)
-{
-       TALLOC_CTX *tmp_ctx = talloc_new(ldb);
-       struct ldb_message *msg;
-       int ret;
-
-       msg = ldb_msg_new(tmp_ctx);
-       W_ERROR_HAVE_NO_MEMORY_AND_FREE(msg, tmp_ctx);
-
-       msg->dn = dn;
-       ret = ldb_msg_add_string(msg, "objectClass", "top");
-       if (ret != LDB_SUCCESS) {
-               talloc_free(tmp_ctx);
-               return WERR_NOMEM;
-       }
-
-       /* [MS-DRSR] implies that we should only add the 'top'
-        * objectclass, but that would cause lots of problems with our
-        * objectclass code as top is not structural, so we add
-        * 'domainDNS' as well to keep things sane. We're expecting
-        * this new NC to be of objectclass domainDNS after
-        * replication anyway
-        */
-       ret = ldb_msg_add_string(msg, "objectClass", "domainDNS");
-       if (ret != LDB_SUCCESS) {
-               talloc_free(tmp_ctx);
-               return WERR_NOMEM;
-       }
-
-       ret = ldb_msg_add_fmt(msg, "instanceType", "%u",
-                       INSTANCE_TYPE_IS_NC_HEAD|
-                       INSTANCE_TYPE_NC_ABOVE|
-                       INSTANCE_TYPE_UNINSTANT);
-       if (ret != LDB_SUCCESS) {
-               talloc_free(tmp_ctx);
-               return WERR_NOMEM;
-       }
-
-       ret = dsdb_add(ldb, msg, 0);
-       if (ret != LDB_SUCCESS) {
-               DEBUG(0,("Failed to create new NC for %s - %s\n",
-                        ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
-               talloc_free(tmp_ctx);
-               return WERR_NOMEM;
-       }
-
-       DEBUG(1,("Created new NC for %s\n", ldb_dn_get_linearized(dn)));
-
-       talloc_free(tmp_ctx);
-       return WERR_OK;
-}
-
-
 WERROR dsdb_origin_objects_commit(struct ldb_context *ldb,
                                  TALLOC_CTX *mem_ctx,
                                  const struct drsuapi_DsReplicaObjectListItem *first_object,
@@ -825,8 +767,9 @@ WERROR dsdb_origin_objects_commit(struct ldb_context *ldb,
                        if (!ldb_dn_validate(nc_dn)) {
                                continue;
                        }
-                       status = dsdb_origin_create_NC(ldb, nc_dn);
-                       if (!W_ERROR_IS_OK(status)) {
+                       ret = dsdb_create_partial_replica_NC(ldb, nc_dn);
+                       if (ret != LDB_SUCCESS) {
+                               status = WERR_DS_INTERNAL_FAILURE;
                                goto cancel;
                        }
                }
index 87983f41c8ce7b8f3031ac8792f5b885f902b15e..3f730f97db598a94d8b934218e8b8b739e8b2cd8 100644 (file)
@@ -36,6 +36,7 @@
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "dsdb/samdb/samdb.h"
 #include "../libds/common/flags.h"
+#include "dsdb/common/util.h"
 
 struct np_context {
        struct ldb_module *module;
@@ -122,6 +123,17 @@ static int np_part_search_callback(struct ldb_request *req, struct ldb_reply *ar
        ret = ldb_build_extended_req(&ac->part_add, 
                                     ldb, ac, DSDB_EXTENDED_CREATE_PARTITION_OID, ex_op, 
                                     NULL, ac, np_part_mod_callback, req);
+
+       /* if the parent was asking for a partial replica, then we
+        * need the extended operation to also ask for a partial
+        * replica */
+       if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) {
+               ret = dsdb_request_add_controls(ac->part_add, DSDB_MODIFY_PARTIAL_REPLICA);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
        
        LDB_REQ_SET_LOCATION(ac->part_add);
        if (ret != LDB_SUCCESS) {
index 0dd3a472c2a39bf66885736f347e834b459afcf1..030f592d3a365b91ce2355eb4f272bd5c7ce156e 100644 (file)
@@ -770,6 +770,18 @@ int partition_create(struct ldb_module *module, struct ldb_request *req)
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
+
+               if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) {
+                       /* this new partition is a partial replica */
+                       ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+                       ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn));
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
                
                /* Perform modify on @PARTITION record */
                ret = ldb_build_mod_req(&mod_req, ldb, req, mod_msg, NULL, NULL, 
index 601b6765d1c50b207c83418097c90f8a9b0a974b..4c89f242472f1c5e3594b1eb05dddb7ad1705889 100644 (file)
@@ -96,6 +96,9 @@ struct dsdb_control_password_change_status {
 /* passed when we want to get the behaviour of the non-global catalog port */
 #define DSDB_CONTROL_NO_GLOBAL_CATALOG "1.3.6.1.4.1.7165.4.3.17"
 
+/* passed when we want special behaviour for partial replicas */
+#define DSDB_CONTROL_PARTIAL_REPLICA "1.3.6.1.4.1.7165.4.3.18"
+
 struct dsdb_control_password_change {
        const struct samr_Password *old_nt_pwd_hash;
        const struct samr_Password *old_lm_pwd_hash;
index aa3426dbf8e0bd55133f7ba66bf85fd8ad685c73..496a73296e71679b896a86c6aff563fcdc6b9b0c 100644 (file)
 #Allocated: (not used anymore) DSDB_CONTROL_SEARCH_APPLY_ACCESS 1.3.6.1.4.1.7165.4.3.15
 #Allocated: LDB_CONTROL_PROVISION_OID 1.3.6.1.4.1.7165.4.3.16
 #Allocated: DSDB_CONTROL_NO_GLOBAL_CATALOG 1.3.6.1.4.1.7165.4.3.17
+#Allocated: DSDB_CONTROL_PARTIAL_REPLICA 1.3.6.1.4.1.7165.4.3.18
 
 # Extended 1.3.6.1.4.1.7165.4.4.x
 #Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1