s4:dsdb Try to cope with linked attribute updates where the DN has changed.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 4 May 2010 10:32:54 +0000 (20:32 +1000)
committerKamen Mazdrashki <kamenim@samba.org>
Thu, 10 Jun 2010 22:22:11 +0000 (01:22 +0300)
We need to try and search by GUID if we can.

Andrew Bartlett

source4/dsdb/samdb/ldb_modules/linked_attributes.c

index 56ed447771e1e3a58f5daf755b6d10869e535178..f6e60185120bf4254aef752c60b9d5aa9a4ba866 100644 (file)
@@ -57,9 +57,11 @@ static int linked_attributes_fix_links(struct ldb_module *module,
        attrs[1] = NULL;
 
        for (i=0; i<el->num_values; i++) {
+               NTSTATUS status;
                struct dsdb_dn *dsdb_dn;
                unsigned int j;
                int ret;
+               struct GUID guid;
                struct ldb_result *res;
                struct ldb_message *msg;
                struct ldb_message_element *el2;
@@ -70,12 +72,37 @@ static int linked_attributes_fix_links(struct ldb_module *module,
                        return LDB_ERR_INVALID_DN_SYNTAX;
                }
 
-               ret = dsdb_module_search_dn(module, tmp_ctx, &res, dsdb_dn->dn,
-                                           attrs,
-                                           DSDB_SEARCH_SHOW_DELETED |
-                                           DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
-                                           DSDB_SEARCH_REVEAL_INTERNALS);
-               if (ret != LDB_SUCCESS) {
+               status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid, "GUID");
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                       ret = dsdb_module_search_dn(module, tmp_ctx, &res, dsdb_dn->dn,
+                                                   attrs,
+                                                   DSDB_SEARCH_SHOW_DELETED |
+                                                   DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
+                                                   DSDB_SEARCH_REVEAL_INTERNALS);
+               } else if (NT_STATUS_IS_OK(status)) {
+                       ret = dsdb_module_search(module, tmp_ctx, &res, NULL,
+                                                LDB_SCOPE_SUBTREE, attrs,
+                                                DSDB_SEARCH_SHOW_DELETED |
+                                                DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
+                                                DSDB_SEARCH_REVEAL_INTERNALS | DSDB_SEARCH_ONE_ONLY,
+                                                "objectGUID=%s", GUID_string(tmp_ctx, &guid));
+               } else {
+                       ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - failed to parse GUID in DN %s",
+                                              el->name, target->lDAPDisplayName,
+                                              ldb_dn_get_linearized(old_dn),
+                                              ldb_dn_get_linearized(dsdb_dn->dn),
+                                              ldb_dn_get_extended_linearized(tmp_ctx, dsdb_dn->dn, 1));
+                       talloc_free(tmp_ctx);
+                       return LDB_ERR_INVALID_DN_SYNTAX;
+               }
+               if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+                       /* Perhaps this is a link to an object outside
+                        * our server - we don't need to update the
+                        * other end, as it's not in our DB. */
+                       DEBUG(2,(__location__ ": WARNING: Failed to find target DN %s for linked attribute update\n",
+                                ldb_dn_get_extended_linearized(tmp_ctx, dsdb_dn->dn, 1)));
+                       continue;
+               } else if (ret != LDB_SUCCESS) {
                        ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - remote not found - %s",
                                               el->name, target->lDAPDisplayName,
                                               ldb_dn_get_linearized(old_dn),