]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:drsuapi:getncchanges: allow 0 reserved_usn reply
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 7 Aug 2024 05:25:30 +0000 (17:25 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Wed, 28 Aug 2024 04:24:39 +0000 (04:24 +0000)
Azure AD will set reserved_usn to zero when we expect it to be
the number we gave them.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15701

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Jennifer Sutton <josutton@catalyst.net.nz>
selftest/knownfail.d/getncchanges-azure-ad [deleted file]
source4/rpc_server/drsuapi/getncchanges.c

diff --git a/selftest/knownfail.d/getncchanges-azure-ad b/selftest/knownfail.d/getncchanges-azure-ad
deleted file mode 100644 (file)
index a8e05bb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-^samba4.drs.getncchanges.python\(vampire_dc\).getncchanges.DrsReplicaSyncFakeAzureAdTests.test_repl_get_tgt_multivalued_links\(vampire_dc\)
-^samba4.drs.getncchanges.python\(vampire_dc\).getncchanges.DrsReplicaSyncFakeAzureAdTests.test_repl_integrity\(vampire_dc\)
-^samba4.drs.getncchanges.python\(vampire_dc\).getncchanges.DrsReplicaSyncFakeAzureAdTests.test_repl_integrity_link_attr\(vampire_dc\)
-^samba4.drs.getncchanges.python\(promoted_dc\).getncchanges.DrsReplicaSyncFakeAzureAdTests.test_repl_integrity\(promoted_dc\)
-^samba4.drs.getncchanges.python\(promoted_dc\).getncchanges.DrsReplicaSyncFakeAzureAdTests.test_repl_integrity_link_attr\(promoted_dc\)
index d37662bdcebeba9ffc321a9d712b97e37049e665..a73efe93eb9c77d6f9668337343fbb816f31c715 100644 (file)
@@ -3029,16 +3029,67 @@ allowed:
                ret = drsuapi_DsReplicaHighWaterMark_cmp(&getnc_state->last_hwm,
                                                         &req10->highwatermark);
                if (ret != 0) {
-                       DBG_ERR("DsGetNCChanges 2nd replication "
-                               "on DN %s %s highwatermark "
-                               "(last_dn %s)\n",
-                               ldb_dn_get_linearized(
-                                       getnc_state->ncRoot_dn),
-                               (ret > 0) ? "older" : "newer",
-                               ldb_dn_get_linearized(
-                                       getnc_state->last_dn));
-                       TALLOC_FREE(getnc_state);
-                       b_state->getncchanges_full_repl_state = NULL;
+                       if (req10->highwatermark.reserved_usn == 0) {
+                               /*
+                                * Entra ID Connect / Azure AD is known to set
+                                * reserved_usn to zero in replies, when we
+                                * were expecting it to be returned unchanged
+                                * (it is supposed to be an opaque cookie).
+                                *
+                                * If the only difference is in the
+                                * reserved_usn, and it is 0 on the return, we
+                                * assume it is Azure AD and treat the
+                                * highwatermarks as equal.
+                                */
+                               req10->highwatermark.reserved_usn =
+                                       getnc_state->last_hwm.reserved_usn;
+
+                               ret = drsuapi_DsReplicaHighWaterMark_cmp(
+                                       &getnc_state->last_hwm,
+                                       &req10->highwatermark);
+
+                               /* put things as they were */
+                               req10->highwatermark.reserved_usn = 0;
+
+                               if (ret != 0) {
+                                       /* we will start again */
+                                       DBG_ERR("DsGetNCChanges 2nd replication "
+                                               "on DN %s %s highwatermark "
+                                               "(last_dn %s) after Azure AD "
+                                               "reserved_usn adjustment\n",
+                                               ldb_dn_get_linearized(
+                                                       getnc_state->ncRoot_dn),
+                                               (ret > 0) ? "older" : "newer",
+                                               ldb_dn_get_linearized(
+                                                       getnc_state->last_dn));
+                                       TALLOC_FREE(getnc_state);
+                                       b_state->getncchanges_full_repl_state =
+                                               NULL;
+                               } else {
+                                       /* log and continue as normal */
+                                       DBG_NOTICE(
+                                               "DsGetNCChanges 2nd replication "
+                                               "on DN %s: highwatermark "
+                                               "matches only after Azure AD "
+                                               "reserved_usn adjustment "
+                                               "(last_dn %s)\n",
+                                               ldb_dn_get_linearized(
+                                                       getnc_state->ncRoot_dn),
+                                               ldb_dn_get_linearized(
+                                                       getnc_state->last_dn));
+                               }
+                       } else {
+                               DBG_ERR("DsGetNCChanges 2nd replication "
+                                       "on DN %s %s highwatermark "
+                                       "(last_dn %s)\n",
+                                       ldb_dn_get_linearized(
+                                               getnc_state->ncRoot_dn),
+                                       (ret > 0) ? "older" : "newer",
+                                       ldb_dn_get_linearized(
+                                               getnc_state->last_dn));
+                               TALLOC_FREE(getnc_state);
+                               b_state->getncchanges_full_repl_state = NULL;
+                       }
                }
        }