s4-dsdb: In rootdse module, catch rename on any DN that has an impact on our NTDS...
authorMatthieu Patou <mat@matws.net>
Fri, 13 May 2011 00:15:56 +0000 (04:15 +0400)
committerMatthieu Patou <mat@matws.net>
Sat, 11 Jun 2011 19:18:55 +0000 (23:18 +0400)
So anything touching a DN in this kind of hierarchy CN=NTDS
Settings,CN=SERVER,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=domain,DC=tld
 has to be monitored and we need once the full subtree rename has been
 done, so that we can update the rootDSE record for dsServiceName.

source4/dsdb/samdb/ldb_modules/rootdse.c

index c584a11b2c6e9f389003feaec9f2014e3216ad64..5fc89f42f1d1e55dd21b6f7f258b695d3751f0d1 100644 (file)
@@ -180,6 +180,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
                "rootDomainNamingContext",
                "schemaNamingContext",
                "serverName",
+               "namingContexts",
                NULL
        };
 
@@ -1314,12 +1315,16 @@ static int rootdse_rename(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        int ret;
+       const struct GUID *ntds_guid = NULL;
+       struct ldb_dn *old_ntds_dn;
+       struct ldb_dn *new_ntds_dn;
+       struct ldb_message *msg;
+       bool ok = false;
 
        ret = rootdse_filter_operations(module, req);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
-
        ret = rootdse_filter_controls(module, req);
        if (ret != LDB_SUCCESS) {
                return ret;
@@ -1328,12 +1333,64 @@ static int rootdse_rename(struct ldb_module *module, struct ldb_request *req)
        /*
                If dn is not "" we should let it pass through
        */
-       if (!ldb_dn_is_null(req->op.rename.olddn)) {
+       if (ldb_dn_is_null(req->op.rename.olddn)) {
+               ldb_set_errstring(ldb, "rootdse_remove: you cannot rename the rootdse entry!");
+               return LDB_ERR_NO_SUCH_OBJECT;
+       }
+
+       old_ntds_dn = samdb_ntds_settings_dn(ldb);
+       if (ldb_dn_compare_base(req->op.rename.olddn, old_ntds_dn) == 0) {
+               ntds_guid = samdb_ntds_objectGUID(ldb);
+               if (ntds_guid == NULL) {
+                       return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Unable to find the GUID of the NTDS Settings object");
+               }
+       }
+
+       if (ntds_guid == NULL) {
                return ldb_next_request(module, req);
        }
 
-       ldb_set_errstring(ldb, "rootdse_remove: you cannot rename the rootdse entry!");
-       return LDB_ERR_NO_SUCH_OBJECT;
+       ret = dsdb_module_rename(module,
+                                req->op.rename.olddn,
+                                req->op.rename.newdn,
+                                DSDB_FLAG_NEXT_MODULE,
+                                req);
+       if (ret != LDB_SUCCESS) {
+               /* Error msg is most probably done by module bellow*/
+               return ret;
+       }
+
+       ret = dsdb_module_dn_by_guid(module, req, ntds_guid, &new_ntds_dn, req);
+       if (ret != LDB_SUCCESS) {
+               return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Unable to find the new DN of NTDS Settings object");
+       }
+
+       msg = ldb_msg_new(req);
+       if (msg == NULL) {
+               return ldb_module_oom(module);
+       }
+
+       msg->dn = ldb_dn_new(msg, ldb, "@ROOTDSE");
+       if (msg->dn == NULL) {
+               return ldb_module_oom(module);
+       }
+
+       ret = ldb_msg_add_linearized_dn(msg, "dsServiceName", new_ntds_dn);
+       if (ret != LDB_SUCCESS) {
+               return ldb_module_oom(module);
+       }
+
+       ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM);
+       if (ret != LDB_SUCCESS) {
+               return ldb_error(ldb, ret, "Unable to update dsServiceName of ROOTDSE");
+       }
+
+       ok = samdb_set_ntds_settings_dn(ldb, new_ntds_dn);
+       if (!ok) {
+               return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Call to samdb_set_ntds_settings_dn has failed");
+       }
+
+       return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
 }
 
 static int rootdse_delete(struct ldb_module *module, struct ldb_request *req)