]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libcli/auth: also use netlogon_creds_CredentialState_extra_info for the client
authorStefan Metzmacher <metze@samba.org>
Wed, 2 Oct 2024 17:06:59 +0000 (19:06 +0200)
committerDouglas Bagnall <dbagnall@samba.org>
Wed, 30 Oct 2024 23:08:36 +0000 (23:08 +0000)
In order to allow backports and cluster updates we simulate a
dom_sid, so that the old code is able to parse the blob.

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

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
libcli/auth/credentials.c
libcli/auth/netlogon_creds_cli.c
libcli/auth/proto.h
librpc/idl/schannel.idl
source4/librpc/rpc/dcerpc_schannel.c
source4/torture/ntp/ntp_signd.c
source4/torture/rpc/lsa.c
source4/torture/rpc/netlogon.c
source4/torture/rpc/netlogon_crypto.c
source4/torture/rpc/samba3rpc.c

index 59db4bc28ea77300227dbb92f8ab1e861f2b2fa1..75ac4ddb0f2486dd7fa03e80c20a09c57b715bcf 100644 (file)
@@ -491,16 +491,19 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me
                                                                  const struct netr_Credential *server_challenge,
                                                                  const struct samr_Password *machine_password,
                                                                  struct netr_Credential *initial_credential,
+                                                                 uint32_t client_requested_flags,
                                                                  uint32_t negotiate_flags)
 {
        struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
+       struct timeval tv = timeval_current();
+       NTTIME now = timeval_to_nttime(&tv);
        NTSTATUS status;
 
        if (!creds) {
                return NULL;
        }
 
-       creds->sequence = time(NULL);
+       creds->sequence = tv.tv_sec;
        creds->negotiate_flags = negotiate_flags;
        creds->secure_channel_type = secure_channel_type;
 
@@ -515,6 +518,16 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me
                return NULL;
        }
 
+       creds->ex = talloc_zero(creds,
+                       struct netlogon_creds_CredentialState_extra_info);
+       if (creds->ex == NULL) {
+               talloc_free(creds);
+               return NULL;
+       }
+       creds->ex->client_requested_flags = client_requested_flags;
+       creds->ex->auth_time = now;
+       creds->ex->client_sid = global_sid_NULL;
+
        dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
        dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
        dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
index 40a40cb99aede4353054d3d5db149bef4cdfa0e6..35a5462ff2e76bf7b9a4c63c05877682a6da2443 100644 (file)
@@ -1355,6 +1355,7 @@ static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq)
                                                  &state->server_challenge,
                                                  state->used_nt_hash,
                                                  &state->client_credential,
+                                                 state->context->client.proposed_flags,
                                                  state->current_flags);
        if (tevent_req_nomem(state->creds, req)) {
                return;
@@ -1558,6 +1559,7 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq)
                return;
        }
 
+       state->creds->ex->client_sid.sub_auths[0] = state->rid;
        status = netlogon_creds_cli_store_internal(state->context,
                                                   state->creds);
        if (tevent_req_nterror(req, status)) {
@@ -1935,6 +1937,7 @@ static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq)
        struct netlogon_creds_cli_check_state *state =
                tevent_req_data(req,
                struct netlogon_creds_cli_check_state);
+       uint32_t requested_flags;
        NTSTATUS status;
        NTSTATUS result;
        bool ok;
@@ -1986,9 +1989,13 @@ static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq)
                return;
        }
 
-       if (state->client_caps.requested_flags !=
-           state->context->client.proposed_flags)
-       {
+       if (state->creds->ex != NULL) {
+               requested_flags = state->creds->ex->client_requested_flags;
+       } else {
+               requested_flags = state->context->client.proposed_flags;
+       }
+
+       if (state->client_caps.requested_flags != requested_flags) {
                status = NT_STATUS_DOWNGRADE_DETECTED;
                tevent_req_nterror(req, status);
                netlogon_creds_cli_check_cleanup(req, status);
index 3094292657abc53a479b753d11b79a794d2bdede..ae68aab192a93a3c53c252488c9a35d1769c3da8 100644 (file)
@@ -46,6 +46,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me
                                                                  const struct netr_Credential *server_challenge,
                                                                  const struct samr_Password *machine_password,
                                                                  struct netr_Credential *initial_credential,
+                                                                 uint32_t client_requested_flags,
                                                                  uint32_t negotiate_flags);
 NTSTATUS
 netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
index 619e9e5591c6a793fbd74894c5b1f7bd68c5e947..8905d514f557a038e7d753ea6a4f66c1be908a11 100644 (file)
@@ -20,8 +20,53 @@ interface schannel
                 * with a single dom_sid for the client_sid.
                 *
                 * On the server we use CLEAR_IF_FIRST,
-                * so db layout changes don't matter there.
+                * so db layout changes don't matter there,
+                * but on the client side we need to handle
+                * the ctdb case were CLEAR_IF_FIRST only
+                * works if all cluster nodes are restarted.
+                *
+                * As this was a single dom_sid before,
+                * we add some magic in order to let
+                * old code (on other nodes to parse the new layout).
+                *
+                * We have basically this definition of dom_sid:
+                *
+                * typedef struct {
+                *    uint8 sid_rev_num;
+                *    [range(0,15)] int8 num_auths;
+                *    uint8  id_auth[6];
+                *    uint32 sub_auths[num_auths];
+                * } dom_sid;
+                *
+                * It means it consumes at least 8 bytes while
+                * and it's also 4 byte aligned (before sid_rev_num).
+                * The largest sid would have 68 bytes.
+                *
+                * The old client side code would see a sid like
+                * this: S-1-RSV-CRF-ATL-ATH-257-0-RID
+                *
+                * RSV => reserved (the last 4 bytes of id_auth)
+                *
+                * CRF => client_requested_flags (sub_auths[0]
+                *
+                * Note NTTIME used ndr_pull_udlong, it's not NTTIME_hyper!
+                * ATL => low 4 bytes of auth_time (sub_auths[1])
+                * ATH => high 4 bytes of auth_time (sub_auths[2])
+                *
+                * From client_sid (S-1-0-RID): sub_auth[3-5]
+                *
+                * 257 => 0x01 0x01 0x00 0x00 =
+                *        (sid_rev_num = 1, num_auths =1,
+                *         id_auth[0] = 0, id_auth[1] = 0)
+                * 0   => id_auth[2-6]
+                *
+                * RID => the RID of the client
+                *
+                * It means the magic needs to simulate
+                * num_auths = 6
                 */
+               [value(0x00000601)] uint32 magic;
+               [value(0)] uint32 reserved;
                netr_NegotiateFlags client_requested_flags;
                NTTIME auth_time;
                dom_sid client_sid;
index 0d31eb38d664bb14ca5d486b6b4bca7608081bed..e2f4a8fa3d51bf521ecb077d15c112ba10a44542 100644 (file)
@@ -199,6 +199,7 @@ static void continue_srv_challenge(struct tevent_req *subreq)
                                              s->a.in.secure_channel_type,
                                              &s->credentials1, &s->credentials2,
                                              s->mach_pwd, &s->credentials3,
+                                             s->requested_negotiate_flags,
                                              s->local_negotiate_flags);
        if (composite_nomem(s->creds, c)) {
                return;
index fd7da67c5518b26af3859ad48021ebe10496ce0d..2bf8e0fe127262641de568bbc723ed358f853df2 100644 (file)
@@ -119,6 +119,7 @@ static bool test_ntp_signd(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2, 
                                           pwhash, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
        
        torture_assert(tctx, creds != NULL, "memory allocation");
index 8f5338bcc652f529eed96f39bc860538370121a5..badb95bd6aabed82d90d08e736468e535fca1814 100644 (file)
@@ -2953,6 +2953,7 @@ static bool check_pw_with_ServerAuthenticate3(struct dcerpc_pipe *p,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           new_password, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2978,6 +2979,7 @@ static bool check_pw_with_ServerAuthenticate3(struct dcerpc_pipe *p,
                                                   a.in.secure_channel_type,
                                                   &credentials1, &credentials2,
                                                   old_password, &credentials3,
+                                                  negotiate_flags,
                                                   negotiate_flags);
 
                torture_assert(tctx, creds != NULL, "memory allocation");
index 97b916a7ad4d943b81eb99b8acf2b57174744886..14428439ab4b46374fcdff7724793e2a6cd1bee3 100644 (file)
@@ -180,6 +180,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          0,
                                           0);
        torture_assert(tctx, creds != NULL, "memory allocation");
 
@@ -251,6 +252,7 @@ bool test_SetupCredentials2ex(struct dcerpc_pipe *p, struct torture_context *tct
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -349,6 +351,7 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -421,6 +424,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -437,6 +441,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          negotiate_flags,
                                           negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -543,6 +548,7 @@ static bool test_ServerReqChallenge(
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          in_negotiate_flags,
                                           in_negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -620,6 +626,7 @@ static bool test_ServerReqChallenge_zero_challenge(
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          in_negotiate_flags,
                                           in_negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -704,6 +711,7 @@ static bool test_ServerReqChallenge_5_repeats(
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          in_negotiate_flags,
                                           in_negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -790,6 +798,7 @@ static bool test_ServerReqChallenge_4_repeats(
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           mach_password, &credentials3,
+                                          in_negotiate_flags,
                                           in_negotiate_flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -883,6 +892,7 @@ static bool test_ServerAuthenticate2_encrypts_to_zero(
                        &credentials2,
                        mach_password,
                        &credentials3,
+                       flags,
                        flags);
 
                torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2275,6 +2285,7 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2365,6 +2376,7 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2382,6 +2394,7 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b3, tctx, &a),
@@ -2455,6 +2468,7 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2472,6 +2486,7 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b2, tctx, &a),
@@ -2546,6 +2561,7 @@ static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2563,6 +2579,7 @@ static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2662,6 +2679,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2679,6 +2697,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b1, tctx, &a),
@@ -2738,6 +2757,7 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
@@ -2755,6 +2775,7 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
@@ -2769,6 +2790,7 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
                                           a.in.secure_channel_type,
                                           &credentials1, &credentials2,
                                           &mach_password, &credentials3,
+                                          flags,
                                           flags);
 
        torture_assert(tctx, creds != NULL, "memory allocation");
index eec8a75317919fcadbddaf65a006551f0e434dc4..858a17e0ea8b168b65c72b80a1f694e3de745dea 100644 (file)
@@ -124,6 +124,7 @@ static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p,
                                                 &netr_creds2,
                                                 &machine_password,
                                                 &netr_creds3,
+                                                negotiate_flags,
                                                 negotiate_flags);
        GNUTLS_FIPS140_SET_STRICT_MODE();
        /* Test that we fail to encrypt with RC4 */
index 8b9cc2cb87186410803aa148ccc0b0deecc4c65d..4f6d01f3759fa6ce57da126a5c0dc882f7ba187b 100644 (file)
@@ -1097,7 +1097,9 @@ static bool auth2(struct torture_context *tctx,
                                                 a.in.secure_channel_type,
                                                 r.in.credentials,
                                                 r.out.return_credentials, &mach_pw,
-                                                &netr_cred, negotiate_flags);
+                                                &netr_cred,
+                                                negotiate_flags,
+                                                negotiate_flags);
        torture_assert(tctx, (creds_state != NULL), "memory allocation failed");
 
        status = dcerpc_netr_ServerAuthenticate2_r(net_handle, mem_ctx, &a);
@@ -2163,7 +2165,9 @@ static bool torture_samba3_rpc_randomauth2(struct torture_context *torture)
                                                 a.in.secure_channel_type,
                                                 r.in.credentials,
                                                 r.out.return_credentials, &mach_pw,
-                                                &netr_cred, negotiate_flags);
+                                                &netr_cred,
+                                                negotiate_flags,
+                                                negotiate_flags);
        torture_assert(torture, (creds_state != NULL), "memory allocation failed");
 
        status = dcerpc_netr_ServerAuthenticate2_r(net_handle, mem_ctx, &a);