s4/rodc: Implement msDS-isRODC constructed attr
authorAnatoliy Atanasov <anatoliy.atanasov@postpath.com>
Wed, 28 Apr 2010 14:02:55 +0000 (17:02 +0300)
committerAnatoliy Atanasov <anatoliy.atanasov@postpath.com>
Mon, 3 May 2010 16:28:00 +0000 (18:28 +0200)
source4/dsdb/common/util.c
source4/dsdb/samdb/ldb_modules/operational.c

index e4e55fc530fe17248a3499cf41a4ae1c2051c79d..771d30a4cddbc2fafe92937a759add85bb5cc6a3 100644 (file)
@@ -2720,7 +2720,7 @@ int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
 /*
   see if a computer identified by its invocationId is a RODC
 */
-int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *invocationId, bool *is_rodc)
+int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
 {
        /* 1) find the DN for this servers NTDSDSA object
           2) search for the msDS-isRODC attribute
@@ -2740,8 +2740,17 @@ int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *invocationId,
        }
 
        ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
-                         DSDB_SEARCH_ONE_ONLY, "invocationID=%s", GUID_string(tmp_ctx, invocationId));
+                         DSDB_SEARCH_ONE_ONLY, "objectGUID=%s", GUID_string(tmp_ctx, objectGUID));
+
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               *is_rodc = false;
+               talloc_free(tmp_ctx);
+               return LDB_SUCCESS;
+       }
+
        if (ret != LDB_SUCCESS) {
+               DEBUG(1,(("Failed to find our own NTDS Settings object by objectGUID=%s!\n"),
+                        GUID_string(tmp_ctx, objectGUID)));
                talloc_free(tmp_ctx);
                return ret;
        }
@@ -2759,12 +2768,12 @@ int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *invocationId,
 */
 int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
 {
-       const struct GUID *invocationId;
-       invocationId = samdb_ntds_invocation_id(sam_ctx);
-       if (!invocationId) {
+       const struct GUID *objectGUID;
+       objectGUID = samdb_ntds_objectGUID(sam_ctx);
+       if (!objectGUID) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
-       return samdb_is_rodc(sam_ctx, invocationId, am_rodc);
+       return samdb_is_rodc(sam_ctx, objectGUID, am_rodc);
 }
 
 
index 94fe411157266b44d34b7b438de6e59902274a61..bc2afa26276a92c5343f30cc4439be29de2957ea 100644 (file)
@@ -287,6 +287,156 @@ static int construct_subschema_subentry(struct ldb_module *module,
 }
 
 
+static int construct_msds_isrodc_with_dn(struct ldb_module *module,
+                                        struct ldb_message *msg,
+                                        struct ldb_message_element *object_category)
+{
+       struct ldb_context *ldb;
+       struct ldb_dn *dn;
+       const struct ldb_val *val;
+
+       ldb = ldb_module_get_ctx(module);
+       if (!ldb) {
+               DEBUG(4, (__location__ ": Failed to get ldb \n"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       dn = ldb_dn_new(msg, ldb, (const char *)object_category->values[0].data);
+       if (!dn) {
+               DEBUG(4, (__location__ ": Failed to create dn from %s \n",
+                         (const char *)object_category->values[0].data));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       val = ldb_dn_get_rdn_val(dn);
+       if (!val) {
+               DEBUG(4, (__location__ ": Failed to get rdn val from %s \n",
+                         ldb_dn_get_linearized(dn)));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       if (strequal((const char *)val->data, "NTDS-DSA")) {
+               ldb_msg_add_string(msg, "msDS-isRODC", "FALSE");
+       } else {
+               ldb_msg_add_string(msg, "msDS-isRODC", "TRUE");
+       }
+       return LDB_SUCCESS;
+}
+
+static int construct_msds_isrodc_with_server_dn(struct ldb_module *module,
+                                               struct ldb_message *msg,
+                                               struct ldb_dn *dn)
+{
+       struct ldb_dn *server_dn;
+       const char *attr_obj_cat[] = { "objectCategory", NULL };
+       struct ldb_result *res;
+       struct ldb_message_element *object_category;
+       int ret;
+
+       server_dn = ldb_dn_copy(msg, dn);
+       if (!ldb_dn_add_child_fmt(server_dn, "CN=NTDS Settings")) {
+               DEBUG(4, (__location__ ": Failed to add child to %s \n",
+                         ldb_dn_get_linearized(server_dn)));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = dsdb_module_search_dn(module, msg, &res, server_dn, attr_obj_cat, 0);
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               DEBUG(4,(__location__ ": Can't get objectCategory for %s \n",
+                                        ldb_dn_get_linearized(server_dn)));
+               return LDB_SUCCESS;
+       } else if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       object_category = ldb_msg_find_element(res->msgs[0], "objectCategory");
+       if (!object_category) {
+               DEBUG(4,(__location__ ": Can't find objectCategory for %s \n",
+                        ldb_dn_get_linearized(res->msgs[0]->dn)));
+               return LDB_SUCCESS;
+       }
+       return construct_msds_isrodc_with_dn(module, msg, object_category);
+}
+
+static int construct_msds_isrodc_with_computer_dn(struct ldb_module *module,
+                                                 struct ldb_message *msg)
+{
+       struct ldb_context *ldb;
+       const char *attr[] = { "serverReferenceBL", NULL };
+       struct ldb_result *res;
+       int ret;
+       struct ldb_dn *server_dn;
+
+       ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attr, 0);
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               DEBUG(4,(__location__ ": Can't get serverReferenceBL for %s \n",
+                        ldb_dn_get_linearized(msg->dn)));
+               return LDB_SUCCESS;
+       } else if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       ldb = ldb_module_get_ctx(module);
+       if (!ldb) {
+               return LDB_SUCCESS;
+       }
+
+       server_dn = ldb_msg_find_attr_as_dn(ldb, msg, res->msgs[0], "serverReferenceBL");
+       if (!server_dn) {
+               DEBUG(4,(__location__ ": Can't find serverReferenceBL for %s \n",
+                        ldb_dn_get_linearized(res->msgs[0]->dn)));
+               return LDB_SUCCESS;
+       }
+       return construct_msds_isrodc_with_server_dn(module, msg, server_dn);
+}
+
+/*
+  construct msDS-isRODC attr
+*/
+static int construct_msds_isrodc(struct ldb_module *module, struct ldb_message *msg)
+{
+       struct ldb_message_element * object_class;
+       struct ldb_message_element * object_category;
+       unsigned int i;
+
+       object_class = ldb_msg_find_element(msg, "objectClass");
+       if (!object_class) {
+               DEBUG(4,(__location__ ": Can't get objectClass for %s \n",
+                        ldb_dn_get_linearized(msg->dn)));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (i=0; i<object_class->num_values; i++) {
+               if (strequal((const char*)object_class->values[i].data, "nTDSDSA")) {
+                       /* If TO!objectCategory  equals the DN of the classSchema  object for the nTDSDSA
+                        * object class, then TO!msDS-isRODC  is false. Otherwise, TO!msDS-isRODC  is true.
+                        */
+                       object_category = ldb_msg_find_element(msg, "objectCategory");
+                       if (!object_category) {
+                               DEBUG(4,(__location__ ": Can't get objectCategory for %s \n",
+                                        ldb_dn_get_linearized(msg->dn)));
+                               return LDB_SUCCESS;
+                       }
+                       return construct_msds_isrodc_with_dn(module, msg, object_category);
+               }
+               if (strequal((const char*)object_class->values[i].data, "server")) {
+                       /* Let TN be the nTDSDSA  object whose DN is "CN=NTDS Settings," prepended to
+                        * the DN of TO. Apply the previous rule for the "TO is an nTDSDSA  object" case,
+                        * substituting TN for TO.
+                        */
+                       return construct_msds_isrodc_with_server_dn(module, msg, msg->dn);
+               }
+               if (strequal((const char*)object_class->values[i].data, "computer")) {
+                       /* Let TS be the server  object named by TO!serverReferenceBL. Apply the previous
+                        * rule for the "TO is a server  object" case, substituting TS for TO.
+                        */
+                       return construct_msds_isrodc_with_computer_dn(module, msg);
+               }
+       }
+
+       return LDB_SUCCESS;
+}
+
 /*
   a list of attribute names that should be substituted in the parse
   tree before the search is done
@@ -317,7 +467,8 @@ static const struct {
        { "primaryGroupToken", "objectClass", "objectSid", construct_primary_group_token },
        { "tokenGroups", "objectSid", "primaryGroupID", construct_token_groups },
        { "parentGUID", NULL, NULL, construct_parent_guid },
-       { "subSchemaSubEntry", NULL, NULL, construct_subschema_subentry }
+       { "subSchemaSubEntry", NULL, NULL, construct_subschema_subentry },
+       { "msDS-isRODC", "objectClass", "objectCategory", construct_msds_isrodc }
 };