s4/rodc: implement read-only database
authorAnatoliy Atanasov <anatoliy.atanasov@postpath.com>
Wed, 24 Mar 2010 14:53:38 +0000 (16:53 +0200)
committerAnatoliy Atanasov <anatoliy.atanasov@postpath.com>
Fri, 26 Mar 2010 10:48:22 +0000 (12:48 +0200)
When we are RODC we shoudl deny modify's on the database and return
referral instead.

source4/dsdb/samdb/ldb_modules/repl_meta_data.c

index 8b4e012ba9af8cd5be02d6a56fae62102bc3ec6e..198f4c92bc2130f6bd9e4cdfcb2895b2de13f3cd 100644 (file)
@@ -1077,6 +1077,7 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb,
  */
 static int replmd_update_rpmd(struct ldb_module *module, 
                              const struct dsdb_schema *schema, 
+                             struct ldb_request *req,
                              struct ldb_message *msg, uint64_t *seq_num,
                              time_t t,
                              bool *is_urgent)
@@ -1158,6 +1159,15 @@ static int replmd_update_rpmd(struct ldb_module *module,
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
+       /*we have elements that will be modified*/
+       if (msg->num_elements > 0) {
+               /*if we are RODC and this is a DRSR update then its ok*/
+               if (samdb_rodc(ldb) && !ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
+                       ldb_asprintf_errstring(ldb, "RODC modify is forbidden\n");
+                       return LDB_ERR_REFERRAL;
+               }
+       }
+
        for (i=0; i<msg->num_elements; i++) {
                struct ldb_message_element *old_el;
                old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name);
@@ -2042,6 +2052,8 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
        time_t t = time(NULL);
        int ret;
        bool is_urgent = false;
+       struct loadparm_context *lp_ctx;
+       struct ldb_reply *ares;
 
        /* do not manipulate our control entries */
        if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -2049,6 +2061,8 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
        }
 
        ldb = ldb_module_get_ctx(module);
+       lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+                                struct loadparm_context);
 
        ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
 
@@ -2068,7 +2082,24 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
        ldb_msg_remove_attr(msg, "whenChanged");
        ldb_msg_remove_attr(msg, "uSNChanged");
 
-       ret = replmd_update_rpmd(module, ac->schema, msg, &ac->seq_num, t, &is_urgent);
+       ret = replmd_update_rpmd(module, ac->schema, req, msg, &ac->seq_num, t, &is_urgent);
+       if (ret == LDB_ERR_REFERRAL) {
+               talloc_free(ac);
+               ares = talloc_zero(req, struct ldb_reply);
+               if ( ares == NULL ){
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+
+               ares->type = LDB_REPLY_REFERRAL;
+               ares->referral = talloc_asprintf(ares,
+                                                "ldap://%s/%s",
+                                                lp_dnsdomain(lp_ctx),
+                                                ldb_dn_get_linearized(msg->dn));
+               ares->error = ret;
+
+               return ldb_module_done(req, ares->controls, ares->response, ares->error);
+       }
+
        if (ret != LDB_SUCCESS) {
                talloc_free(ac);
                return ret;