s4-dsdb: disallow changes based on instanceType
authorAndrew Tridgell <tridge@samba.org>
Fri, 23 Sep 2011 07:28:25 +0000 (17:28 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 4 Oct 2011 04:08:56 +0000 (15:08 +1100)
if instanceType does not include INSTANCE_TYPE_WRITE, then disallow
changes to any replicated attributes. This ensures partial replicates
are not alterered

source4/dsdb/samdb/ldb_modules/repl_meta_data.c

index 3b4e2804a3eeb48f5a82adb8448f18da88bda1ac..32b8ab25c9f3fab0c60b1dddd6be77eddd218b2e 100644 (file)
@@ -1162,7 +1162,7 @@ static int replmd_update_rpmd(struct ldb_module *module,
        int ret;
        const char * const *attrs = NULL;
        const char * const attrs1[] = { "replPropertyMetaData", "*", NULL };
        int ret;
        const char * const *attrs = NULL;
        const char * const attrs1[] = { "replPropertyMetaData", "*", NULL };
-       const char * const attrs2[] = { "uSNChanged", "objectClass", NULL };
+       const char * const attrs2[] = { "uSNChanged", "objectClass", "instanceType", NULL };
        struct ldb_result *res;
        struct ldb_context *ldb;
        struct ldb_message_element *objectclass_el;
        struct ldb_result *res;
        struct ldb_context *ldb;
        struct ldb_message_element *objectclass_el;
@@ -1333,6 +1333,8 @@ static int replmd_update_rpmd(struct ldb_module *module,
 
                /*if we are RODC and this is a DRSR update then its ok*/
                if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
 
                /*if we are RODC and this is a DRSR update then its ok*/
                if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
+                       unsigned instanceType;
+
                        ret = samdb_rodc(ldb, &rodc);
                        if (ret != LDB_SUCCESS) {
                                DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
                        ret = samdb_rodc(ldb, &rodc);
                        if (ret != LDB_SUCCESS) {
                                DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
@@ -1340,6 +1342,12 @@ static int replmd_update_rpmd(struct ldb_module *module,
                                ldb_asprintf_errstring(ldb, "RODC modify is forbidden\n");
                                return LDB_ERR_REFERRAL;
                        }
                                ldb_asprintf_errstring(ldb, "RODC modify is forbidden\n");
                                return LDB_ERR_REFERRAL;
                        }
+
+                       instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], "instanceType", INSTANCE_TYPE_WRITE);
+                       if (!(instanceType & INSTANCE_TYPE_WRITE)) {
+                               return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM,
+                                                "cannot change replicated attribute on partial replica");
+                       }
                }
 
                md_value = talloc(msg, struct ldb_val);
                }
 
                md_value = talloc(msg, struct ldb_val);
@@ -2420,7 +2428,7 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are
        const struct dsdb_attribute *rdn_attr;
        const char *rdn_name;
        const struct ldb_val *rdn_val;
        const struct dsdb_attribute *rdn_attr;
        const char *rdn_name;
        const struct ldb_val *rdn_val;
-       const char *attrs[4] = { NULL, };
+       const char *attrs[5] = { NULL, };
        time_t t = time(NULL);
        int ret;
        bool is_urgent = false;
        time_t t = time(NULL);
        int ret;
        bool is_urgent = false;
@@ -2533,8 +2541,9 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are
         */
        attrs[0] = "replPropertyMetaData";
        attrs[1] = "objectClass";
         */
        attrs[0] = "replPropertyMetaData";
        attrs[1] = "objectClass";
-       attrs[2] = rdn_name;
-       attrs[3] = NULL;
+       attrs[2] = "instanceType";
+       attrs[3] = rdn_name;
+       attrs[4] = NULL;
 
        ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
                                 msg, &ac->seq_num, t, &is_urgent);
 
        ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
                                 msg, &ac->seq_num, t, &is_urgent);