From cc520d1ffd93a4c037674c70adf1de36f1cfa74a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 15:08:01 +0200 Subject: [PATCH 01/69] s4:torture/rpc: check that DOWNGRADE_DETECTED has no bits negotiated BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 36310650ee7a64603128139f512d3a4e039f8822) --- source4/torture/rpc/netlogon_crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c index 85844604ee27..8defd439a888 100644 --- a/source4/torture/rpc/netlogon_crypto.c +++ b/source4/torture/rpc/netlogon_crypto.c @@ -152,6 +152,8 @@ static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p, a.out.result, NT_STATUS_DOWNGRADE_DETECTED, "Unexpected status code"); + torture_assert_int_equal(tctx, negotiate_flags, 0, + "NT_STATUS_DOWNGRADE_DETECTED..."); return false; } torture_assert_ntstatus_ok(tctx, -- 2.34.1 From ae06ee139beb56bdac7f2e47a01ffca272abccbc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 15:02:16 +0200 Subject: [PATCH 02/69] s4:torture/rpc: without weak crypto we should require AES We should check that we can actually negotiated the strong AES crypto instead of just checking that NETLOGON_NEG_ARCFOUR is not there... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 3dcbc8eea5bc53a8332b3ad93ea4c3df99af7830) --- source4/torture/rpc/netlogon_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c index 8defd439a888..eec8a7531791 100644 --- a/source4/torture/rpc/netlogon_crypto.c +++ b/source4/torture/rpc/netlogon_crypto.c @@ -169,8 +169,8 @@ static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p, if (!weak_crypto_allowed) { torture_assert(tctx, - (negotiate_flags & NETLOGON_NEG_ARCFOUR) == 0, - "Server should not announce RC4 support"); + (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES), + "Server negotiate AES support"); } /* Prove that requesting a challenge again won't break it */ -- 2.34.1 From d6c7634a8ef4269389831fb4987beafcd8318b8d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 12:55:33 +0200 Subject: [PATCH 03/69] s3:rpc_server/netlogon: correctly negotiate flags in ServerAuthenticate2/3 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit b27661f832cc4c56cc582cf7041d90f178736ef7) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 39 ++++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index ccae62083cc0..f9d3dcca6b07 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -896,6 +896,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, /* r->in.negotiate_flags is an aliased pointer to r->out.negotiate_flags, * so use a copy to avoid destroying the client values. */ uint32_t in_neg_flags = *r->in.negotiate_flags; + uint32_t neg_flags = 0; const char *fn; struct loadparm_context *lp_ctx = p->dce_call->conn->dce_ctx->lp_ctx; struct dom_sid sid; @@ -912,7 +913,6 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, * an error or not. */ - /* 0x000001ff */ srv_flgs = NETLOGON_NEG_ACCOUNT_LOCKOUT | NETLOGON_NEG_PERSISTENT_SAMREPL | NETLOGON_NEG_ARCFOUR | @@ -922,20 +922,10 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, NETLOGON_NEG_MULTIPLE_SIDS | NETLOGON_NEG_REDO | NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | - NETLOGON_NEG_PASSWORD_SET2; - - /* Ensure we support strong (128-bit) keys. */ - if (in_neg_flags & NETLOGON_NEG_STRONG_KEYS) { - srv_flgs |= NETLOGON_NEG_STRONG_KEYS; - } - - if (in_neg_flags & NETLOGON_NEG_SUPPORTS_AES) { - srv_flgs |= NETLOGON_NEG_SUPPORTS_AES; - } - - if (in_neg_flags & NETLOGON_NEG_SCHANNEL) { - srv_flgs |= NETLOGON_NEG_SCHANNEL; - } + NETLOGON_NEG_PASSWORD_SET2 | + NETLOGON_NEG_STRONG_KEYS | + NETLOGON_NEG_SUPPORTS_AES | + NETLOGON_NEG_SCHANNEL; /* * Support authentication of trusted domains. @@ -957,6 +947,8 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, srv_flgs &= ~NETLOGON_NEG_ARCFOUR; } + neg_flags = in_neg_flags & srv_flgs; + switch (dce_call->pkt.u.request.opnum) { case NDR_NETR_SERVERAUTHENTICATE: fn = "_netr_ServerAuthenticate"; @@ -971,6 +963,19 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, return NT_STATUS_INTERNAL_ERROR; } + if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) { + if (!(neg_flags & NETLOGON_NEG_SUPPORTS_AES)) { + DBG_NOTICE("%s: no AES support negotiated from client %s\n", + fn, r->in.computer_name); + /* + * Here we match Windows 2012 and return no flags. + */ + neg_flags = 0; + status = NT_STATUS_DOWNGRADE_DETECTED; + goto out; + } + } + /* We use this as the key to store the creds: */ /* r->in.computer_name */ @@ -1010,7 +1015,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, &mach_pwd, r->in.credentials, r->out.return_credentials, - srv_flgs); + neg_flags); if (!creds) { DEBUG(0,("%s: netlogon_creds_server_check failed. Rejecting auth " "request from client %s machine account %s\n", @@ -1042,7 +1047,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, out: - *r->out.negotiate_flags = srv_flgs; + *r->out.negotiate_flags = neg_flags; return status; } -- 2.34.1 From c739232eb41b44b39fe91d3de039a5ddf170761e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:34:33 +0200 Subject: [PATCH 04/69] s3:rpc_server/netlogon: if we require AES there's no need to remove the ARCFOUR flag With SAMBA_WEAK_CRYPTO_DISALLOWED we will return DOWNGRADE_DETECTED with negotiate_flags = 0, if AES was not negotiated... And if AES was negotiated there's no harm in returning the ARCFOUR flag... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit e5bc5ee3e04138b10c0630640469a08fad847e56) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index f9d3dcca6b07..4a258874d16d 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -927,6 +927,18 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, NETLOGON_NEG_SUPPORTS_AES | NETLOGON_NEG_SCHANNEL; + /* + * With SAMBA_WEAK_CRYPTO_DISALLOWED we will return DOWNGRADE_DETECTED + * with negotiate_flags = 0 below, if NETLOGON_NEG_SUPPORTS_AES was not + * negotiated... + * + * And if NETLOGON_NEG_SUPPORTS_AES was negotiated there's no harm in + * returning the NETLOGON_NEG_ARCFOUR flag too... + * + * So there's no reason to remove NETLOGON_NEG_ARCFOUR nor + * NETLOGON_NEG_STRONG_KEYS from srv_flgs... + */ + /* * Support authentication of trusted domains. * @@ -940,13 +952,6 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION; } - /* - * If weak crypto is disabled, do not announce that we support RC4. - */ - if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) { - srv_flgs &= ~NETLOGON_NEG_ARCFOUR; - } - neg_flags = in_neg_flags & srv_flgs; switch (dce_call->pkt.u.request.opnum) { -- 2.34.1 From efd956f08b9195dea8706397754fe2ff769dc0c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:34:33 +0200 Subject: [PATCH 05/69] s4:rpc_server/netlogon: if we require AES there's no need to remove the ARCFOUR flag With SAMBA_WEAK_CRYPTO_DISALLOWED dcesrv_netr_ServerAuthenticate3_check_downgrade() will return DOWNGRADE_DETECTED with negotiate_flags = 0, if AES was not negotiated... And if AES was negotiated there's no harm in returning the ARCFOUR flag... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a0bc372dee68ad255da005d2e2078da754bbef2a) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 175ff532b4a4..e9cd56b8084d 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -503,12 +503,17 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( NETLOGON_NEG_AUTHENTICATED_RPC; /* - * If weak crypto is disabled, do not announce that we support RC4. + * With SAMBA_WEAK_CRYPTO_DISALLOWED + * dcesrv_netr_ServerAuthenticate3_check_downgrade() will return + * DOWNGRADE_DETECTED with negotiate_flags = 0, + * if NETLOGON_NEG_SUPPORTS_AES was not negotiated... + * + * And if NETLOGON_NEG_SUPPORTS_AES was negotiated there's no harm in + * returning the NETLOGON_NEG_ARCFOUR flag too... + * + * So there's no reason to remove NETLOGON_NEG_ARCFOUR nor + * NETLOGON_NEG_STRONG_KEYS from server_flags... */ - if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) == - SAMBA_WEAK_CRYPTO_DISALLOWED) { - server_flags &= ~NETLOGON_NEG_ARCFOUR; - } negotiate_flags = *r->in.negotiate_flags & server_flags; -- 2.34.1 From 2865cd734fbcd8420a919426eefc8dc886e39825 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 09:27:48 +0200 Subject: [PATCH 06/69] netlogon.idl: the capabilities in query_level=2 are the ones send by the client BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 86176598eee4c83dc63a9dac163f32c886477129) --- librpc/idl/netlogon.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl index 383c7b567e30..ed75fe3797af 100644 --- a/librpc/idl/netlogon.idl +++ b/librpc/idl/netlogon.idl @@ -1236,7 +1236,7 @@ interface netlogon /* Function 0x15 */ typedef [switch_type(uint32)] union { [case(1)] netr_NegotiateFlags server_capabilities; - [case(2)] netr_NegotiateFlags server_capabilities; + [case(2)] netr_NegotiateFlags requested_flags; } netr_Capabilities; NTSTATUS netr_LogonGetCapabilities( -- 2.34.1 From e39bc72ac4253dbd453b9a1c56430a9119401fac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 07/69] libcli/auth: remove unused netlogon_creds_client_init_session_key() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit cf0e07a3d2a085d31f7d682633af9ec57c155e57) --- libcli/auth/credentials.c | 19 ------------------- libcli/auth/proto.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 84838be6e73c..d18759604480 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -563,25 +563,6 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me return creds; } -/* - initialise the credentials structure with only a session key. The caller better know what they are doing! - */ - -struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx, - const uint8_t session_key[16]) -{ - struct netlogon_creds_CredentialState *creds; - - creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); - if (!creds) { - return NULL; - } - - memcpy(creds->session_key, session_key, 16); - - return creds; -} - /* step the credentials to the next element in the chain, updating the current client and server credentials and the seed diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index b202542068d1..9f6a8b68b8b1 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -47,8 +47,6 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me const struct samr_Password *machine_password, struct netr_Credential *initial_credential, uint32_t negotiate_flags); -struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx, - const uint8_t session_key[16]); NTSTATUS netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, struct netr_Authenticator *next); -- 2.34.1 From 0fd5d3d6c9038c85e2a2723a5dbf1893c3eee22d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 17:43:00 +0200 Subject: [PATCH 08/69] libcli/auth: make use of netlogon_creds_cli_store_internal() in netlogon_creds_cli_auth_srvauth_done() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 69cb9aea67de0613f467f7ce2d460364ff2be241) --- libcli/auth/netlogon_creds_cli.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 118c81f6246b..154906342b7b 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1417,9 +1417,6 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) NTSTATUS status; NTSTATUS result; bool ok; - enum ndr_err_code ndr_err; - DATA_BLOB blob; - TDB_DATA data; bool downgraded; if (state->try_auth3) { @@ -1518,20 +1515,8 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) return; } - ndr_err = ndr_push_struct_blob(&blob, state, state->creds, - (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - status = ndr_map_error2ntstatus(ndr_err); - tevent_req_nterror(req, status); - return; - } - - data.dptr = blob.data; - data.dsize = blob.length; - - status = dbwrap_store(state->context->db.ctx, - state->context->db.key_data, - data, TDB_REPLACE); + status = netlogon_creds_cli_store_internal(state->context, + state->creds); if (tevent_req_nterror(req, status)) { return; } -- 2.34.1 From 895ac1f6169ae459e8b78c82419b559a86885dcb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 15:03:21 +0200 Subject: [PATCH 09/69] libcli/auth: don't allow any unexpected upgrades of negotiate_flags Only remove the unsupported flags from state->current_flags for the next try... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a9040c8ce76cb9911c4c0c5d623cc479e49f460d) --- libcli/auth/netlogon_creds_cli.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 154906342b7b..1a1966207511 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1478,14 +1478,16 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) } if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { - uint32_t tmp_flags = state->context->client.proposed_flags; - if ((state->current_flags == tmp_flags) && - (state->creds->negotiate_flags != tmp_flags)) - { + uint32_t prop_f = state->context->client.proposed_flags; + uint32_t cli_f = state->current_flags; + uint32_t srv_f = state->creds->negotiate_flags; + uint32_t nego_f = cli_f & srv_f; + + if (cli_f == prop_f && nego_f != prop_f) { /* * lets retry with the negotiated flags */ - state->current_flags = state->creds->negotiate_flags; + state->current_flags = nego_f; netlogon_creds_cli_auth_challenge_start(req); return; } -- 2.34.1 From e06f04522ade682f454beb0a765ea5b04fd0334c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:31:18 +0200 Subject: [PATCH 10/69] libcli/auth: if we require aes we don't need to require arcfour nor strong key But we can send arcfour and strong key on the wire and don't need to remove them from the proposed flags. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 3da40f1c6818550eb08a6d7d680c213c3f1d0649) --- libcli/auth/netlogon_creds_cli.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 1a1966207511..f4b3560f42ce 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -502,14 +502,16 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, * require AES. */ if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { - required_flags &= ~NETLOGON_NEG_ARCFOUR; required_flags |= NETLOGON_NEG_SUPPORTS_AES; - proposed_flags &= ~NETLOGON_NEG_ARCFOUR; - proposed_flags |= NETLOGON_NEG_SUPPORTS_AES; } proposed_flags |= required_flags; + if (required_flags & NETLOGON_NEG_SUPPORTS_AES) { + required_flags &= ~NETLOGON_NEG_ARCFOUR; + required_flags &= ~NETLOGON_NEG_STRONG_KEYS; + } + if (seal_secure_channel) { auth_level = DCERPC_AUTH_LEVEL_PRIVACY; } else { -- 2.34.1 From 3ea908e83598fc2e3aaa003527006601703ac180 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 14:25:19 +0200 Subject: [PATCH 11/69] libcli/auth: use a LogonControl after a LogonGetCapabilities downgrade If LogonGetCapabilities was downgraded by an DCERPC Fault, we rely on the schannel message ordering to detect failures. Instead of letting any real winbindd request trigger this, we do it directly in netlogon_creds_cli_check() with a LogonControl that is also used for 'wbinfo --ping-dc'. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 276137e950696fbf36450dceebd6c0250c6242d0) --- libcli/auth/netlogon_creds_cli.c | 76 +++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index f4b3560f42ce..935697be0096 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1591,6 +1591,8 @@ struct netlogon_creds_cli_check_state { struct netlogon_creds_CredentialState *creds; struct netr_Authenticator req_auth; struct netr_Authenticator rep_auth; + + union netr_CONTROL_QUERY_INFORMATION ctrl_info; }; static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, @@ -1709,6 +1711,8 @@ static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, TALLOC_FREE(state->creds); } +static void netlogon_creds_cli_check_control_do(struct tevent_req *req); + static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) { struct tevent_req *req = @@ -1769,9 +1773,10 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE * with the next request as the sequence number processing * gets out of sync. + * + * So we'll do a LogonControl message to check that... */ - netlogon_creds_cli_check_cleanup(req, status); - tevent_req_done(req); + netlogon_creds_cli_check_control_do(req); return; } if (tevent_req_nterror(req, status)) { @@ -1854,6 +1859,73 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) tevent_req_done(req); } +static void netlogon_creds_cli_check_control_done(struct tevent_req *subreq); + +static void netlogon_creds_cli_check_control_do(struct tevent_req *req) +{ + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + struct tevent_req *subreq = NULL; + + /* + * In case we got a downgrade based on a FAULT + * we use a LogonControl that is supposed to + * return WERR_NOT_SUPPORTED (without a DCERPC FAULT) + * to verify that the connection is still ok and didn't + * get out of sync. + */ + subreq = dcerpc_netr_LogonControl_send(state, + state->ev, + state->binding_handle, + state->srv_name_slash, + NETLOGON_CONTROL_QUERY, + 2, + &state->ctrl_info); + if (tevent_req_nomem(subreq, req)) { + return; + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_check_control_done, + req); + return; +} + +static void netlogon_creds_cli_check_control_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + NTSTATUS status; + WERROR result; + + status = dcerpc_netr_LogonControl_recv(subreq, state, &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + /* + * We want to delete the creds, + * so we pass NT_STATUS_DOWNGRADE_DETECTED + * to netlogon_creds_cli_check_cleanup() + */ + status = NT_STATUS_DOWNGRADE_DETECTED; + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + if (!W_ERROR_EQUAL(result, WERR_NOT_SUPPORTED)) { + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + tevent_req_done(req); +} + NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req, union netr_Capabilities *capabilities) { -- 2.34.1 From ecd54ad0c8e590d61b806b4bb1c1df308dfb3b98 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 13:43:36 +0200 Subject: [PATCH 12/69] libcli/auth: use netr_LogonGetCapabilities query_level=2 to verify the proposed capabilities BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 25a2105ca7816c47a9c4a7fded88a922e4ccf88b) --- libcli/auth/netlogon_creds_cli.c | 159 +++++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 7 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 935697be0096..40a40cb99aed 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1215,6 +1215,7 @@ struct netlogon_creds_cli_auth_state { struct netlogon_creds_CredentialState *creds; struct netr_Credential client_credential; struct netr_Credential server_credential; + uint32_t negotiate_flags; uint32_t rid; bool try_auth3; bool try_auth2; @@ -1360,6 +1361,17 @@ static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) } if (state->try_auth3) { + /* + * We always need to send our proposed flags, + * even if state->current_flags we passed to + * netlogon_creds_client_init() is already downgraded, + * + * An old server will just ignore the bits it doesn't + * know about, but LogonGetCapabilities(level=2) will + * report what we proposed. + */ + state->negotiate_flags = state->context->client.proposed_flags; + subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev, state->binding_handle, state->srv_name_slash, @@ -1368,12 +1380,22 @@ static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) state->context->client.computer, &state->client_credential, &state->server_credential, - &state->creds->negotiate_flags, + &state->negotiate_flags, &state->rid); if (tevent_req_nomem(subreq, req)) { return; } } else if (state->try_auth2) { + /* + * We always need to send our proposed flags, + * even if state->current_flags we passed to + * netlogon_creds_client_init() is already downgraded, + * + * An old server will just ignore the bits it doesn't + * know about, but LogonGetCapabilities(level=2) will + * report what we proposed. + */ + state->negotiate_flags = state->context->client.proposed_flags; state->rid = 0; subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev, @@ -1384,11 +1406,12 @@ static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) state->context->client.computer, &state->client_credential, &state->server_credential, - &state->creds->negotiate_flags); + &state->negotiate_flags); if (tevent_req_nomem(subreq, req)) { return; } } else { + state->negotiate_flags = 0; state->rid = 0; subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev, @@ -1467,7 +1490,7 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) } downgraded = netlogon_creds_cli_downgraded( - state->creds->negotiate_flags, + state->negotiate_flags, state->context->client.proposed_flags, state->context->client.required_flags); if (downgraded) { @@ -1482,7 +1505,7 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { uint32_t prop_f = state->context->client.proposed_flags; uint32_t cli_f = state->current_flags; - uint32_t srv_f = state->creds->negotiate_flags; + uint32_t srv_f = state->negotiate_flags; uint32_t nego_f = cli_f & srv_f; if (cli_f == prop_f && nego_f != prop_f) { @@ -1519,6 +1542,22 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) return; } + if (state->current_flags == state->context->client.proposed_flags) { + /* + * Without a downgrade in the crypto we proposed + * we can adjust the otherwise downgraded flags + * before storing. + */ + state->creds->negotiate_flags &= state->negotiate_flags; + } else if (state->current_flags != state->negotiate_flags) { + /* + * We downgraded our crypto once, we should not + * allow any additional downgrade! + */ + tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + status = netlogon_creds_cli_store_internal(state->context, state->creds); if (tevent_req_nterror(req, status)) { @@ -1587,6 +1626,7 @@ struct netlogon_creds_cli_check_state { char *srv_name_slash; union netr_Capabilities caps; + union netr_Capabilities client_caps; struct netlogon_creds_CredentialState *creds; struct netr_Authenticator req_auth; @@ -1597,7 +1637,8 @@ struct netlogon_creds_cli_check_state { static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, NTSTATUS status); -static void netlogon_creds_cli_check_caps(struct tevent_req *subreq); +static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req *subreq); +static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq); struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -1681,7 +1722,7 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, } tevent_req_set_callback(subreq, - netlogon_creds_cli_check_caps, + netlogon_creds_cli_check_negotiate_caps, req); return req; @@ -1713,7 +1754,7 @@ static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, static void netlogon_creds_cli_check_control_do(struct tevent_req *req); -static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) +static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, @@ -1856,6 +1897,110 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) return; } + /* + * Now try to verify our client proposed flags + * arrived at the server, using query_level = 2 + */ + + status = netlogon_creds_client_authenticator(state->creds, + &state->req_auth); + if (tevent_req_nterror(req, status)) { + return; + } + ZERO_STRUCT(state->rep_auth); + + subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + &state->req_auth, + &state->rep_auth, + 2, + &state->client_caps); + if (tevent_req_nomem(subreq, req)) { + return; + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_check_client_caps, + req); + return; +} + +static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + NTSTATUS status; + NTSTATUS result; + bool ok; + + status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_BAD_STUB_DATA)) { + /* + * unpatched Samba server, see + * https://bugzilla.samba.org/show_bug.cgi?id=15418 + */ + status = NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) { + /* + * Here we know the negotiated flags were already + * verified with query_level=1, which means + * the server supported NETLOGON_NEG_SUPPORTS_AES + * and also NETLOGON_NEG_AUTHENTICATED_RPC + * + * As we're using DCERPC_AUTH_TYPE_SCHANNEL with + * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY + * we should detect a faked + * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + * with the next request as the sequence number processing + * gets out of sync. + * + * So we'll do a LogonControl message to check that... + */ + netlogon_creds_cli_check_control_do(req); + return; + } + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + ok = netlogon_creds_client_check(state->creds, + &state->rep_auth.cred); + if (!ok) { + status = NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + if (tevent_req_nterror(req, result)) { + netlogon_creds_cli_check_cleanup(req, result); + return; + } + + if (state->client_caps.requested_flags != + state->context->client.proposed_flags) + { + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + status = netlogon_creds_cli_store_internal(state->context, + state->creds); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); } -- 2.34.1 From 4b0052b96af561059a8ff58e2ff4410d5194fd9c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:15:46 +0200 Subject: [PATCH 13/69] s4:librpc/rpc: do LogonControl after LogonGetCapabilities downgrade BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 24de5d1cbd25fabae6b01565907b53f5e51ea06d) --- source4/librpc/rpc/dcerpc_schannel.c | 76 ++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index ebc7a5e8d374..3f69b849bb8d 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -407,6 +407,7 @@ struct auth_schannel_state { struct netr_Authenticator return_auth; union netr_Capabilities capabilities; struct netr_LogonGetCapabilities c; + union netr_CONTROL_QUERY_INFORMATION ctrl_info; }; @@ -503,6 +504,8 @@ static void continue_bind_auth(struct composite_context *ctx) composite_done(c); } +static void continue_logon_control_do(struct composite_context *c); + /* Stage 4 of auth_schannel: Get the Logon Capabilities and verify them. */ @@ -519,13 +522,18 @@ static void continue_get_capabilities(struct tevent_req *subreq) TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); return; - } else { - /* This is probably NT */ - composite_done(c); + } else if (s->creds_state->negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); return; } + + /* This is probably NT */ + continue_logon_control_do(c); + return; } else if (!composite_is_ok(c)) { return; } @@ -533,7 +541,8 @@ static void continue_get_capabilities(struct tevent_req *subreq) if (NT_STATUS_EQUAL(s->c.out.result, NT_STATUS_NOT_IMPLEMENTED)) { if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { /* This means AES isn't supported. */ - composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); return; } @@ -559,11 +568,11 @@ static void continue_get_capabilities(struct tevent_req *subreq) /* compare capabilities */ if (s->creds_state->negotiate_flags != s->capabilities.server_capabilities) { - DEBUG(2, ("The client capabilities don't match the server " - "capabilities: local[0x%08X] remote[0x%08X]\n", - s->creds_state->negotiate_flags, - s->capabilities.server_capabilities)); - composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + DBG_ERR("The client capabilities don't match the server " + "capabilities: local[0x%08X] remote[0x%08X]\n", + s->creds_state->negotiate_flags, + s->capabilities.server_capabilities); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); return; } @@ -572,6 +581,53 @@ static void continue_get_capabilities(struct tevent_req *subreq) composite_done(c); } +static void continue_logon_control_done(struct tevent_req *subreq); + +static void continue_logon_control_do(struct composite_context *c) +{ + struct auth_schannel_state *s = NULL; + struct tevent_req *subreq = NULL; + + s = talloc_get_type(c->private_data, struct auth_schannel_state); + + subreq = dcerpc_netr_LogonControl_send(s, + c->event_ctx, + s->pipe->binding_handle, + s->c.in.server_name, + NETLOGON_CONTROL_QUERY, + 2, + &s->ctrl_info); + if (composite_nomem(subreq, c)) return; + + tevent_req_set_callback(subreq, continue_logon_control_done, c); +} + +static void continue_logon_control_done(struct tevent_req *subreq) +{ + struct composite_context *c = NULL; + struct auth_schannel_state *s = NULL; + WERROR werr; + + c = tevent_req_callback_data(subreq, struct composite_context); + s = talloc_get_type(c->private_data, struct auth_schannel_state); + + /* receive rpc request result */ + c->status = dcerpc_netr_LogonControl_recv(subreq, s, &werr); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(c->status)) { + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + + if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) { + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + + composite_done(c); +} /* Initiate schannel authentication request -- 2.34.1 From 8ed90176a39f52bbbfb254b58f324e336fed392d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:44:26 +0200 Subject: [PATCH 14/69] s4:librpc/rpc: don't allow any unexpected upgrades of negotiate_flags Only remove the unsupported flags from local_negotiate_flags for the next try... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 69b0cbd13d06fa640a900acab6757425b5b77cac) --- source4/librpc/rpc/dcerpc_schannel.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 3f69b849bb8d..4e237d841f26 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -243,6 +243,14 @@ static void continue_srv_auth2(struct tevent_req *subreq) uint32_t rf = s->remote_negotiate_flags; const char *rn = NULL; + if ((lf & rf) == lf) { + /* + * without a change in flags + * there's no need to retry... + */ + s->dcerpc_schannel_auto = false; + } + if (!s->dcerpc_schannel_auto) { composite_error(c, s->a.out.result); return; @@ -277,7 +285,7 @@ static void continue_srv_auth2(struct tevent_req *subreq) "and retry! local[0x%08X] remote[0x%08X]\n", ln, rn, lf, rf)); - s->local_negotiate_flags = s->remote_negotiate_flags; + s->local_negotiate_flags &= s->remote_negotiate_flags; generate_random_buffer(s->credentials1.data, sizeof(s->credentials1.data)); @@ -292,14 +300,14 @@ static void continue_srv_auth2(struct tevent_req *subreq) return; } - s->creds->negotiate_flags = s->remote_negotiate_flags; - /* verify credentials */ if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) { composite_error(c, NT_STATUS_UNSUCCESSFUL); return; } + s->creds->negotiate_flags &= s->remote_negotiate_flags; + composite_done(c); } -- 2.34.1 From e740b71150e8fb7e884f0391df456e5180bef769 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:38:53 +0200 Subject: [PATCH 15/69] s4:librpc/rpc: define required schannel flags and enforce them BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 25294685b1c2c8652f0ca0220e8f3729e0b347e2) --- source4/librpc/rpc/dcerpc_schannel.c | 61 +++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 4e237d841f26..a8216c7fde26 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -40,6 +40,7 @@ struct schannel_key_state { bool dcerpc_schannel_auto; struct cli_credentials *credentials; struct netlogon_creds_CredentialState *creds; + uint32_t required_negotiate_flags; uint32_t local_negotiate_flags; uint32_t remote_negotiate_flags; struct netr_Credential credentials1; @@ -233,6 +234,29 @@ static void continue_srv_auth2(struct tevent_req *subreq) return; } + { + uint32_t rqf = s->required_negotiate_flags; + uint32_t rf = s->remote_negotiate_flags; + uint32_t lf = s->local_negotiate_flags; + + if ((rf & NETLOGON_NEG_SUPPORTS_AES) && + (lf & NETLOGON_NEG_SUPPORTS_AES)) + { + rqf &= ~NETLOGON_NEG_ARCFOUR; + rqf &= ~NETLOGON_NEG_STRONG_KEYS; + } + + if ((rqf & rf) != rqf) { + rqf = s->required_negotiate_flags; + DBG_ERR("The client capabilities don't match " + "the server capabilities: local[0x%08X] " + "required[0x%08X] remote[0x%08X]\n", + lf, rqf, rf); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + } + /* * Strong keys could be unsupported (NT4) or disabled. So retry with the * flags returned by the server. - asn @@ -325,6 +349,8 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, struct composite_context *epm_map_req; enum netr_SchannelType schannel_type = cli_credentials_get_secure_channel_type(credentials); struct cli_credentials *epm_creds = NULL; + bool reject_md5_servers = false; + bool require_strong_key = false; /* composite context allocation and setup */ c = composite_create(mem_ctx, p->conn->event_ctx); @@ -338,19 +364,48 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, s->pipe = p; s->credentials = credentials; s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; + s->required_negotiate_flags = NETLOGON_NEG_AUTHENTICATED_RPC; /* allocate credentials */ if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) { s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + require_strong_key = true; } if (s->pipe->conn->flags & DCERPC_SCHANNEL_AES) { s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES; + reject_md5_servers = true; } if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) { s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES; s->dcerpc_schannel_auto = true; + reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx); + require_strong_key = lpcfg_require_strong_key(lp_ctx); + } + + if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { + reject_md5_servers = true; + } + + if (reject_md5_servers) { + require_strong_key = true; + } + + if (require_strong_key) { + s->required_negotiate_flags |= NETLOGON_NEG_ARCFOUR; + s->required_negotiate_flags |= NETLOGON_NEG_STRONG_KEYS; + } + + if (reject_md5_servers) { + s->required_negotiate_flags |= NETLOGON_NEG_PASSWORD_SET2; + s->required_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + + s->local_negotiate_flags |= s->required_negotiate_flags; + + if (s->required_negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + s->required_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR; + s->required_negotiate_flags &= ~NETLOGON_NEG_STRONG_KEYS; } /* type of authentication depends on schannel type */ @@ -358,10 +413,6 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH; } - if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { - s->local_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR; - } - epm_creds = cli_credentials_init_anon(s); if (composite_nomem(epm_creds, c)) return c; -- 2.34.1 From e7ff4cf1d17b16028531867bc043b47c3bf06b9b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:38:53 +0200 Subject: [PATCH 16/69] s4:librpc/rpc: use netr_LogonGetCapabilities query_level=2 to verify the proposed capabilities BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 0b6ac4b082ddec5dae1392537727f3a7123ec279) --- source4/librpc/rpc/dcerpc_schannel.c | 145 +++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 8 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index a8216c7fde26..9d96abd2521e 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -40,6 +40,7 @@ struct schannel_key_state { bool dcerpc_schannel_auto; struct cli_credentials *credentials; struct netlogon_creds_CredentialState *creds; + uint32_t requested_negotiate_flags; uint32_t required_negotiate_flags; uint32_t local_negotiate_flags; uint32_t remote_negotiate_flags; @@ -56,7 +57,8 @@ static void continue_secondary_connection(struct composite_context *ctx); static void continue_bind_auth_none(struct composite_context *ctx); static void continue_srv_challenge(struct tevent_req *subreq); static void continue_srv_auth2(struct tevent_req *subreq); -static void continue_get_capabilities(struct tevent_req *subreq); +static void continue_get_negotiated_capabilities(struct tevent_req *subreq); +static void continue_get_client_capabilities(struct tevent_req *subreq); /* @@ -184,7 +186,7 @@ static void continue_srv_challenge(struct tevent_req *subreq) s->a.in.secure_channel_type = cli_credentials_get_secure_channel_type(s->credentials); s->a.in.computer_name = cli_credentials_get_workstation(s->credentials); - s->a.in.negotiate_flags = &s->local_negotiate_flags; + s->a.in.negotiate_flags = &s->requested_negotiate_flags; s->a.in.credentials = &s->credentials3; s->a.out.negotiate_flags = &s->remote_negotiate_flags; s->a.out.return_credentials = &s->credentials3; @@ -330,7 +332,22 @@ static void continue_srv_auth2(struct tevent_req *subreq) return; } - s->creds->negotiate_flags &= s->remote_negotiate_flags; + if (s->requested_negotiate_flags == s->local_negotiate_flags) { + /* + * Without a downgrade in the crypto we proposed + * we can adjust the otherwise downgraded flags + * before storing. + */ + s->creds->negotiate_flags &= s->remote_negotiate_flags; + } else if (s->local_negotiate_flags != s->remote_negotiate_flags) { + /* + * We downgraded our crypto once, we should not + * allow any additional downgrade! + */ + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } composite_done(c); } @@ -413,6 +430,8 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH; } + s->requested_negotiate_flags = s->local_negotiate_flags; + epm_creds = cli_credentials_init_anon(s); if (composite_nomem(epm_creds, c)) return c; @@ -438,7 +457,8 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, */ static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState **creds) + struct netlogon_creds_CredentialState **creds, + uint32_t *requested_negotiate_flags) { NTSTATUS status = composite_wait(c); @@ -447,6 +467,7 @@ static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c, talloc_get_type_abort(c->private_data, struct schannel_key_state); *creds = talloc_move(mem_ctx, &s->creds); + *requested_negotiate_flags = s->requested_negotiate_flags; } talloc_free(c); @@ -457,6 +478,7 @@ static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c, struct auth_schannel_state { struct dcerpc_pipe *pipe; struct cli_credentials *credentials; + uint32_t requested_negotiate_flags; const struct ndr_interface_table *table; struct loadparm_context *lp_ctx; uint8_t auth_level; @@ -465,6 +487,7 @@ struct auth_schannel_state { struct netr_Authenticator auth; struct netr_Authenticator return_auth; union netr_Capabilities capabilities; + union netr_Capabilities client_caps; struct netr_LogonGetCapabilities c; union netr_CONTROL_QUERY_INFORMATION ctrl_info; }; @@ -487,7 +510,11 @@ static void continue_schannel_key(struct composite_context *ctx) NTSTATUS status; /* receive schannel key */ - status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state); + c->status = dcerpc_schannel_key_recv(ctx, + s, + &s->creds_state, + &s->requested_negotiate_flags); + status = c->status; if (!composite_is_ok(c)) { DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status))); return; @@ -556,7 +583,9 @@ static void continue_bind_auth(struct composite_context *ctx) &s->c); if (composite_nomem(subreq, c)) return; - tevent_req_set_callback(subreq, continue_get_capabilities, c); + tevent_req_set_callback(subreq, + continue_get_negotiated_capabilities, + c); return; } @@ -568,10 +597,11 @@ static void continue_logon_control_do(struct composite_context *c); /* Stage 4 of auth_schannel: Get the Logon Capabilities and verify them. */ -static void continue_get_capabilities(struct tevent_req *subreq) +static void continue_get_negotiated_capabilities(struct tevent_req *subreq) { struct composite_context *c; struct auth_schannel_state *s; + NTSTATUS status; c = tevent_req_callback_data(subreq, struct composite_context); s = talloc_get_type(c->private_data, struct auth_schannel_state); @@ -635,7 +665,106 @@ static void continue_get_capabilities(struct tevent_req *subreq) return; } - /* TODO: Add downgrade detection. */ + if ((s->requested_negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) && + (!(s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES))) + { + DBG_ERR("%s: NT_STATUS_DOWNGRADE_DETECTED\n", __location__); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + + ZERO_STRUCT(s->return_auth); + + s->save_creds_state = *s->creds_state; + status = netlogon_creds_client_authenticator(&s->save_creds_state, + &s->auth); + if (!NT_STATUS_IS_OK(status)) { + composite_error(c, status); + return; + } + + s->c.in.credential = &s->auth; + s->c.in.return_authenticator = &s->return_auth; + s->c.in.query_level = 2; + + s->c.out.capabilities = &s->client_caps; + s->c.out.return_authenticator = &s->return_auth; + + subreq = dcerpc_netr_LogonGetCapabilities_r_send(s, + c->event_ctx, + s->pipe->binding_handle, + &s->c); + if (composite_nomem(subreq, c)) return; + + tevent_req_set_callback(subreq, continue_get_client_capabilities, c); + return; +} + +static void continue_get_client_capabilities(struct tevent_req *subreq) +{ + struct composite_context *c; + struct auth_schannel_state *s; + + c = tevent_req_callback_data(subreq, struct composite_context); + s = talloc_get_type(c->private_data, struct auth_schannel_state); + + /* receive rpc request result */ + c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_BAD_STUB_DATA)) { + /* + * unpatched Samba server, see + * https://bugzilla.samba.org/show_bug.cgi?id=15418 + */ + c->status = NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE; + } + if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) { + /* + * Here we know the negotiated flags were already + * verified with query_level=1, which means + * the server supported NETLOGON_NEG_SUPPORTS_AES + * and also NETLOGON_NEG_AUTHENTICATED_RPC + * + * As we're using DCERPC_AUTH_TYPE_SCHANNEL with + * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY + * we should detect a faked + * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + * with the next request as the sequence number processing + * gets out of sync. + * + * So we'll do a LogonControl message to check that... + */ + continue_logon_control_do(c); + return; + } + if (!composite_is_ok(c)) { + return; + } + + /* verify credentials */ + if (!netlogon_creds_client_check(&s->save_creds_state, + &s->c.out.return_authenticator->cred)) { + composite_error(c, NT_STATUS_UNSUCCESSFUL); + return; + } + + if (!NT_STATUS_IS_OK(s->c.out.result)) { + composite_error(c, s->c.out.result); + return; + } + + /* compare capabilities */ + if (s->requested_negotiate_flags != s->client_caps.requested_flags) { + DBG_ERR("The client requested capabilities did not reach" + "the server! local[0x%08X] remote[0x%08X]\n", + s->requested_negotiate_flags, + s->client_caps.requested_flags); + composite_error(c, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + + *s->creds_state = s->save_creds_state; + cli_credentials_set_netlogon_creds(s->credentials, s->creds_state); composite_done(c); } -- 2.34.1 From 79a3e9e0917d18c6f16323055f5b1b40b352fbbf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 20 Jul 2023 13:29:12 +0200 Subject: [PATCH 17/69] s4:torture/rpc/netlogon: adjust test_netlogon_capabilities query_level=2 to request_flags BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit d174b6595a962230bf71cc5c2f512a2c93a4cc1b) --- source4/torture/rpc/netlogon.c | 5 ++-- source4/torture/rpc/schannel.c | 42 ++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 1f04af119ac0..9d01ff1461ac 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -2039,6 +2039,7 @@ bool test_netlogon_ops(struct dcerpc_pipe *p, struct torture_context *tctx, */ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *tctx, struct cli_credentials *credentials, + uint32_t requested_flags, struct netlogon_creds_CredentialState *creds) { NTSTATUS status; @@ -2156,8 +2157,8 @@ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *t &r.out.return_authenticator->cred), "Credential chaining failed"); - torture_assert_int_equal(tctx, creds->negotiate_flags, - capabilities.server_capabilities, + torture_assert_int_equal(tctx, requested_flags, + capabilities.requested_flags, "negotiate flags"); return true; diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index fab1fa4af455..497e15455ab7 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -32,6 +32,7 @@ #include "libcli/security/security.h" #include "system/filesys.h" #include "param/param.h" +#include "param/loadparm.h" #include "librpc/rpc/dcerpc_proto.h" #include "libcli/composite/composite.h" #include "lib/events/events.h" @@ -595,6 +596,7 @@ static bool test_schannel(struct torture_context *tctx, struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; enum dcerpc_transport_t transport; + uint32_t requested_flags; join_ctx = torture_join_domain(tctx, talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i), @@ -634,8 +636,26 @@ static bool test_schannel(struct torture_context *tctx, creds = cli_credentials_get_netlogon_creds(credentials); torture_assert(tctx, (creds != NULL), "schannel creds"); + requested_flags = NETLOGON_NEG_AUTH2_FLAGS; + if (dcerpc_flags & DCERPC_SCHANNEL_128) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + } + if (dcerpc_flags & DCERPC_SCHANNEL_AES) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + if (dcerpc_flags & DCERPC_SCHANNEL_AUTO) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + if (lpcfg_weak_crypto(tctx->lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { + requested_flags &= ~NETLOGON_NEG_ARCFOUR; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + /* checks the capabilities */ - torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds), + torture_assert(tctx, + test_netlogon_capabilities(p_netlogon, tctx, credentials, requested_flags, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* do a couple of logins */ @@ -723,8 +743,26 @@ static bool test_schannel(struct torture_context *tctx, tctx, &p_netlogon2); torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection"); + requested_flags = NETLOGON_NEG_AUTH2_FLAGS; + if (dcerpc_flags & DCERPC_SCHANNEL_128) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + } + if (dcerpc_flags & DCERPC_SCHANNEL_AES) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + if (dcerpc_flags & DCERPC_SCHANNEL_AUTO) { + requested_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + if (lpcfg_weak_crypto(tctx->lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { + requested_flags &= ~NETLOGON_NEG_ARCFOUR; + requested_flags |= NETLOGON_NEG_SUPPORTS_AES; + } + /* checks the capabilities */ - torture_assert(tctx, test_netlogon_capabilities(p_netlogon2, tctx, credentials, creds), + torture_assert(tctx, + test_netlogon_capabilities(p_netlogon2, tctx, credentials, requested_flags, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* Try the schannel-only SamLogonEx operation */ -- 2.34.1 From 693da36466520d9cbb1a863d8c1c3c4a50e53cd7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Oct 2024 12:10:49 +0100 Subject: [PATCH 18/69] s3:cli_netlogon: let rpccli_connect_netlogon() use force_reauth = true on retry BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 7f478656dcf08619bc3a7ad390c7db3bfdef924e) --- source3/rpc_client/cli_netlogon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 762802d32780..84122584cb82 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -387,6 +387,7 @@ again: if (!retry && NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { DBG_DEBUG("Retrying with serverauthenticate\n"); TALLOC_FREE(lck); + force_reauth = true; retry = true; goto again; } -- 2.34.1 From 8aabb4c579f03a9a1c3df957dd8ec4b68d8f1ffb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:04:27 +0200 Subject: [PATCH 19/69] s4:dsdb/common: samdb_confirm_rodc_allowed_to_repl_to() only needs a const sid BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit c9eaf5e22de730f1e7575f6697f32dbb377eae06) --- source4/dsdb/common/rodc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/common/rodc_helper.c b/source4/dsdb/common/rodc_helper.c index 5ed60e0af438..a3cef8704976 100644 --- a/source4/dsdb/common/rodc_helper.c +++ b/source4/dsdb/common/rodc_helper.c @@ -237,7 +237,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct * rather than relying on the caller providing those */ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, - struct dom_sid *rodc_machine_account_sid, + const struct dom_sid *rodc_machine_account_sid, struct ldb_message *rodc_msg, struct ldb_message *obj_msg) { -- 2.34.1 From 2986bafaddf52a0c6732c9ccb2e1eccfdf5e3f19 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:06:44 +0200 Subject: [PATCH 20/69] s3:rpc_server/netlogon: add client_sid helper variables This will make the following changes simpler... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit eda3728a4079c5399f693b1d68e64e5660647c72) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 4a258874d16d..1c740fa4730b 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1321,6 +1321,7 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, size_t i; struct netlogon_creds_CredentialState *creds = NULL; struct _samr_Credentials_t cr = { CRED_TYPE_NT_HASH, {0}}; + const struct dom_sid *client_sid = NULL; DEBUG(5,("_netr_ServerPasswordSet: %d\n", __LINE__)); @@ -1345,6 +1346,7 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, TALLOC_FREE(creds); return status; } + client_sid = creds->sid; DEBUG(3,("_netr_ServerPasswordSet: Server Password Set by remote machine:[%s] on account [%s]\n", r->in.computer_name, creds->computer_name)); @@ -1363,7 +1365,7 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, status = netr_set_machine_account_password(p->mem_ctx, session_info, p->msg_ctx, - creds->sid, + client_sid, &cr); return status; } @@ -1380,6 +1382,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, dcesrv_call_session_info(dce_call); NTSTATUS status; struct netlogon_creds_CredentialState *creds = NULL; + const struct dom_sid *client_sid = NULL; DATA_BLOB plaintext = data_blob_null; DATA_BLOB new_password = data_blob_null; size_t confounder_len; @@ -1405,6 +1408,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, TALLOC_FREE(creds); return status; } + client_sid = creds->sid; DBG_NOTICE("Server Password Set2 by remote " "machine:[%s] on account [%s]\n", @@ -1525,7 +1529,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, status = netr_set_machine_account_password(p->mem_ctx, session_info, p->msg_ctx, - creds->sid, + client_sid, &cr); TALLOC_FREE(creds); return status; -- 2.34.1 From 1b2469256765cb7055b8ac0bea7dd1f7472e8280 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:06:44 +0200 Subject: [PATCH 21/69] s4:rpc_server/netlogon: add client_sid helper variables This will make the following changes simpler... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 2e8949495f601d3fd117cceccd1b464a6ae43251) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index e9cd56b8084d..61c97042f176 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -937,6 +937,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call struct netr_ServerPasswordSet *r) { struct netlogon_creds_CredentialState *creds; + const struct dom_sid *client_sid = NULL; struct ldb_context *sam_ctx; NTSTATUS nt_status; @@ -946,6 +947,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call r->in.credential, r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); + client_sid = creds->sid; sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); if (sam_ctx == NULL) { @@ -957,7 +959,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call /* Using the sid for the account as the key, set the password */ nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, - creds->sid, + client_sid, NULL, /* Don't have version */ NULL, /* Don't have plaintext */ r->in.new_password, @@ -974,6 +976,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal struct netr_ServerPasswordSet2 *r) { struct netlogon_creds_CredentialState *creds; + const struct dom_sid *client_sid = NULL; struct ldb_context *sam_ctx; struct NL_PASSWORD_VERSION version = {}; const uint32_t *new_version = NULL; @@ -990,6 +993,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal r->in.credential, r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); + client_sid = creds->sid; sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); if (sam_ctx == NULL) { @@ -1098,7 +1102,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal /* Using the sid for the account as the key, set the password */ nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, - creds->sid, + client_sid, new_version, &new_password, /* we have plaintext */ NULL, @@ -2634,6 +2638,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r) { struct netlogon_creds_CredentialState *creds; + const struct dom_sid *client_sid = NULL; static const char *const trusts_attrs[] = {"securityIdentifier", "flatName", "trustPartner", @@ -2682,6 +2687,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal talloc_free(frame); } NT_STATUS_NOT_OK_RETURN(status); + client_sid = creds->sid; /* We want to avoid connecting as system. */ sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call); @@ -2698,7 +2704,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal /* Prepares the workstation DN */ workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "", - dom_sid_string(mem_ctx, creds->sid)); + dom_sid_string(mem_ctx, client_sid)); NT_STATUS_HAVE_NO_MEMORY(workstation_dn); /* Get the workstation's session info from the database. */ @@ -3007,7 +3013,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call static bool sam_rodc_access_check(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, - struct dom_sid *user_sid, + const struct dom_sid *user_sid, struct ldb_dn *obj_dn) { static const char *rodc_attrs[] = {"msDS-NeverRevealGroup", @@ -3062,6 +3068,7 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal struct netr_NetrLogonSendToSam *r) { struct netlogon_creds_CredentialState *creds; + const struct dom_sid *client_sid = NULL; struct ldb_context *sam_ctx; NTSTATUS nt_status; DATA_BLOB decrypted_blob; @@ -3076,6 +3083,7 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal &creds); NT_STATUS_NOT_OK_RETURN(nt_status); + client_sid = creds->sid; switch (creds->secure_channel_type) { case SEC_CHAN_BDC: @@ -3147,7 +3155,7 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal } if (creds->secure_channel_type == SEC_CHAN_RODC && - !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) { + !sam_rodc_access_check(sam_ctx, mem_ctx, client_sid, dn)) { DEBUG(1, ("Client asked to reset bad password on " "an arbitrary user: %s\n", ldb_dn_get_linearized(dn))); @@ -4432,6 +4440,7 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; struct netlogon_creds_CredentialState *creds = NULL; + const struct dom_sid *client_sid = NULL; struct ldb_context *sam_ctx = NULL; static const char * const attrs[] = { "unicodePwd", @@ -4472,6 +4481,7 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } + client_sid = creds->sid; /* TODO: check r->in.server_name is our name */ @@ -4492,7 +4502,7 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal return NT_STATUS_INVALID_SYSTEM_SERVICE; } - asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid); + asid = ldap_encode_ndr_dom_sid(mem_ctx, client_sid); if (asid == NULL) { return NT_STATUS_NO_MEMORY; } @@ -4661,6 +4671,7 @@ static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call struct tevent_req *subreq; struct imessaging_context *imsg_ctx = dcesrv_imessaging_context(dce_call->conn); + struct dom_sid *client_sid = NULL; nt_status = dcesrv_netr_creds_server_step_check(dce_call, mem_ctx, @@ -4669,6 +4680,7 @@ static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); + client_sid = creds->sid; if (creds->secure_channel_type != SEC_CHAN_RODC) { return NT_STATUS_ACCESS_DENIED; @@ -4682,7 +4694,7 @@ static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call st->r2 = talloc_zero(st, struct dnsupdate_RODC); NT_STATUS_HAVE_NO_MEMORY(st->r2); - st->r2->in.dom_sid = creds->sid; + st->r2->in.dom_sid = client_sid; st->r2->in.site_name = r->in.site_name; st->r2->in.dns_ttl = r->in.dns_ttl; st->r2->in.dns_names = r->in.dns_names; -- 2.34.1 From f23c2c280eff2e89031c0c9345db11098bba82a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:46:43 +0200 Subject: [PATCH 22/69] libcli/auth: pass client_sid to netlogon_creds_server_init() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit c2ef866fca296c8f3eb1620fdd2bb9bf289d96fc) --- libcli/auth/credentials.c | 7 +++++++ libcli/auth/proto.h | 1 + source3/rpc_server/netlogon/srv_netlog_nt.c | 7 +------ source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 +++++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index d18759604480..236cb6fc1803 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -657,6 +657,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me const struct samr_Password *machine_password, const struct netr_Credential *credentials_in, struct netr_Credential *credentials_out, + const struct dom_sid *client_sid, uint32_t negotiate_flags) { @@ -700,6 +701,12 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me return NULL; } + creds->sid = dom_sid_dup(creds, client_sid); + if (creds->sid == NULL) { + talloc_free(creds); + return NULL; + } + if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { status = netlogon_creds_init_hmac_sha256(creds, client_challenge, diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 9f6a8b68b8b1..edc3284d32cd 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -69,6 +69,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me const struct samr_Password *machine_password, const struct netr_Credential *credentials_in, struct netr_Credential *credentials_out, + const struct dom_sid *client_sid, uint32_t negotiate_flags); NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, const struct netr_Authenticator *received_authenticator, diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 1c740fa4730b..fb41cda5bbbc 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1020,6 +1020,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, &mach_pwd, r->in.credentials, r->out.return_credentials, + &sid, neg_flags); if (!creds) { DEBUG(0,("%s: netlogon_creds_server_check failed. Rejecting auth " @@ -1030,12 +1031,6 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, goto out; } - creds->sid = dom_sid_dup(creds, &sid); - if (!creds->sid) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - /* Store off the state so we can continue after client disconnect. */ become_root(); status = schannel_save_creds_state(p->mem_ctx, lp_ctx, creds); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 61c97042f176..ad0eb9ac0760 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -778,6 +778,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( return NT_STATUS_ACCESS_DENIED; } + *sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid"); + if (*sid == NULL) { + return NT_STATUS_ACCESS_DENIED; + } + creds = netlogon_creds_server_init(mem_ctx, r->in.account_name, r->in.computer_name, @@ -787,6 +792,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( curNtHash, r->in.credentials, r->out.return_credentials, + *sid, negotiate_flags); if (creds == NULL && prevNtHash != NULL) { /* @@ -804,14 +810,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( prevNtHash, r->in.credentials, r->out.return_credentials, + *sid, negotiate_flags); } if (creds == NULL) { return NT_STATUS_ACCESS_DENIED; } - creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid"); - *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid)); nt_status = schannel_save_creds_state(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, -- 2.34.1 From 404cc7e7ef20a027d07ed127c6d3d2224ba6c545 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:54:05 +0200 Subject: [PATCH 23/69] libcli/auth: split out netlogon_creds_CredentialState_extra_info As server we are free to change the netlogon_creds_CredentialState database record format at will as it uses CLEAR_IF_FIRST. For now that format doesn't really changes, because we only move dom_sid into a wrapper structure. In order to avoid changing all callers in this commit, we maintain creds->sid as in memory pointer. In the following patches we'll also use it in order to store client related information... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 518f57b93bdb84900d3b58cd94bdf1046f82a5a6) --- libcli/auth/credentials.c | 22 +++++++++++++++++----- libcli/auth/schannel_state_tdb.c | 15 +++++++++++++++ librpc/idl/schannel.idl | 14 +++++++++++++- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 236cb6fc1803..342dcd95154a 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -701,11 +701,15 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me return NULL; } - creds->sid = dom_sid_dup(creds, client_sid); - if (creds->sid == NULL) { + creds->ex = talloc_zero(creds, + struct netlogon_creds_CredentialState_extra_info); + if (creds->ex == NULL) { talloc_free(creds); return NULL; } + creds->ex->client_sid = *client_sid; + + creds->sid = &creds->ex->client_sid; if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { status = netlogon_creds_init_hmac_sha256(creds, @@ -1193,12 +1197,20 @@ struct netlogon_creds_CredentialState *netlogon_creds_copy( return NULL; } - if (creds_in->sid) { - creds->sid = dom_sid_dup(creds, creds_in->sid); - if (!creds->sid) { + if (creds_in->ex != NULL) { + creds->ex = talloc_zero(creds, + struct netlogon_creds_CredentialState_extra_info); + if (creds->ex == NULL) { talloc_free(creds); return NULL; } + *creds->ex = *creds_in->ex; + } + + if (creds->ex != NULL) { + creds->sid = &creds->ex->client_sid; + } else { + creds->sid = NULL; } memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key)); diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index 2454a4338194..ee7ee546baff 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -88,6 +88,14 @@ NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc, char *name_upper; NTSTATUS status; + if (creds->ex == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + + if (creds->sid == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + if (strlen(creds->computer_name) > 15) { /* * We may want to check for a completely @@ -195,6 +203,13 @@ NTSTATUS schannel_fetch_session_key_tdb(struct db_context *db_sc, NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds); } + if (creds->ex == NULL) { + status = NT_STATUS_INTERNAL_ERROR; + goto done; + } + + creds->sid = &creds->ex->client_sid; + DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n", keystr)); diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index 3bc8a92c92f6..76b0dfd4c553 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -14,6 +14,17 @@ interface schannel { /* this structure is used internally in the NETLOGON server */ + typedef [flag(NDR_PAHEX)] struct { + /* + * These were only used on the server part + * 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. + */ + dom_sid client_sid; + } netlogon_creds_CredentialState_extra_info; + typedef [public,flag(NDR_PAHEX)] struct { netr_NegotiateFlags negotiate_flags; uint8 session_key[16]; @@ -24,7 +35,8 @@ interface schannel netr_SchannelType secure_channel_type; [string,charset(UTF8)] uint8 computer_name[]; [string,charset(UTF8)] uint8 account_name[]; - dom_sid *sid; + [skip] dom_sid *sid; + netlogon_creds_CredentialState_extra_info *ex; } netlogon_creds_CredentialState; /* This is used in the schannel_store.tdb */ -- 2.34.1 From 2d3c99f17c6cf9a8203b9b36cc4dbd8be257278d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:00:45 +0200 Subject: [PATCH 24/69] librpc/rpc: make use of creds->ex->client_sid in dcesrv_netr_check_schannel_get_state() creds->sid will be removed soon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 453587fbc1ef74a3b997235e84040553261fa13e) --- librpc/rpc/server/netlogon/schannel_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librpc/rpc/server/netlogon/schannel_util.c b/librpc/rpc/server/netlogon/schannel_util.c index b14497b13ce3..b98b4706aac1 100644 --- a/librpc/rpc/server/netlogon/schannel_util.c +++ b/librpc/rpc/server/netlogon/schannel_util.c @@ -70,7 +70,7 @@ static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *d DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, struct dcesrv_netr_check_schannel_state); if (s != NULL) { - if (!dom_sid_equal(&s->account_sid, creds->sid)) { + if (!dom_sid_equal(&s->account_sid, &creds->ex->client_sid)) { goto new_state; } if (s->auth_type != auth_type) { @@ -92,7 +92,7 @@ new_state: return NT_STATUS_NO_MEMORY; } - s->account_sid = *creds->sid; + s->account_sid = creds->ex->client_sid; s->auth_type = auth_type; s->auth_level = auth_level; s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; -- 2.34.1 From 8237d998037e62c765a3ccc22f6a22127b55ae5d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:01:39 +0200 Subject: [PATCH 25/69] s3:rpc_server/netlogon: make use of creds->ex->client_sid creds->sid will be removed soon... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 88a84d9330d2bb03176f888a0d8e5066e1e21bf6) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index fb41cda5bbbc..936d3214173c 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1341,7 +1341,7 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, TALLOC_FREE(creds); return status; } - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; DEBUG(3,("_netr_ServerPasswordSet: Server Password Set by remote machine:[%s] on account [%s]\n", r->in.computer_name, creds->computer_name)); @@ -1403,7 +1403,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, TALLOC_FREE(creds); return status; } - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; DBG_NOTICE("Server Password Set2 by remote " "machine:[%s] on account [%s]\n", -- 2.34.1 From 318cb21a60042648650146eb604131bbb23169b6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:01:39 +0200 Subject: [PATCH 26/69] s4:rpc_server/netlogon: make use of creds->ex->client_sid creds->sid will be removed soon... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 4533afc9e12c4dbbc7d11c13e775888c113d497c) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ad0eb9ac0760..5b7ca45ba426 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -952,7 +952,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call r->in.credential, r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); if (sam_ctx == NULL) { @@ -998,7 +998,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal r->in.credential, r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); if (sam_ctx == NULL) { @@ -1349,7 +1349,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL user_info->netlogon_trust_account.account_name = creds->account_name; user_info->netlogon_trust_account.sid - = creds->sid; + = &creds->ex->client_sid; break; default: @@ -2692,7 +2692,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal talloc_free(frame); } NT_STATUS_NOT_OK_RETURN(status); - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; /* We want to avoid connecting as system. */ sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call); @@ -3088,7 +3088,7 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal &creds); NT_STATUS_NOT_OK_RETURN(nt_status); - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; switch (creds->secure_channel_type) { case SEC_CHAN_BDC: @@ -4486,7 +4486,7 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; /* TODO: check r->in.server_name is our name */ @@ -4685,7 +4685,7 @@ static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); - client_sid = creds->sid; + client_sid = &creds->ex->client_sid; if (creds->secure_channel_type != SEC_CHAN_RODC) { return NT_STATUS_ACCESS_DENIED; -- 2.34.1 From 5ac661fcee28ce5777d1f8f76fb36ee5e58336d4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:04:02 +0200 Subject: [PATCH 27/69] libcli/auth: remove unused creds->sid BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a9308c490cb5ec8908a3e4c13e2ce8a08b9027e9) --- libcli/auth/credentials.c | 8 -------- libcli/auth/schannel_state_tdb.c | 6 ------ librpc/idl/schannel.idl | 1 - 3 files changed, 15 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 342dcd95154a..07b146579f67 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -709,8 +709,6 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me } creds->ex->client_sid = *client_sid; - creds->sid = &creds->ex->client_sid; - if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { status = netlogon_creds_init_hmac_sha256(creds, client_challenge, @@ -1207,12 +1205,6 @@ struct netlogon_creds_CredentialState *netlogon_creds_copy( *creds->ex = *creds_in->ex; } - if (creds->ex != NULL) { - creds->sid = &creds->ex->client_sid; - } else { - creds->sid = NULL; - } - memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key)); memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data)); memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data)); diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index ee7ee546baff..4154997fc025 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -92,10 +92,6 @@ NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc, return NT_STATUS_INTERNAL_ERROR; } - if (creds->sid == NULL) { - return NT_STATUS_INTERNAL_ERROR; - } - if (strlen(creds->computer_name) > 15) { /* * We may want to check for a completely @@ -208,8 +204,6 @@ NTSTATUS schannel_fetch_session_key_tdb(struct db_context *db_sc, goto done; } - creds->sid = &creds->ex->client_sid; - DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n", keystr)); diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index 76b0dfd4c553..ad296f48d845 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -35,7 +35,6 @@ interface schannel netr_SchannelType secure_channel_type; [string,charset(UTF8)] uint8 computer_name[]; [string,charset(UTF8)] uint8 account_name[]; - [skip] dom_sid *sid; netlogon_creds_CredentialState_extra_info *ex; } netlogon_creds_CredentialState; -- 2.34.1 From 59a08cdfd131ba7b5d705735597dad922ffd5456 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 28/69] libcli/auth: remember client_requested_flags and auth_time in netlogon_creds_server_init() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit dfbc5e5a19420311eac3db5ede1c665a9198395d) --- libcli/auth/credentials.c | 5 +++++ libcli/auth/proto.h | 1 + librpc/idl/schannel.idl | 2 ++ source3/rpc_server/netlogon/srv_netlog_nt.c | 1 + source4/rpc_server/netlogon/dcerpc_netlogon.c | 6 +++++- 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 07b146579f67..59db4bc28ea7 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -657,11 +657,14 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me const struct samr_Password *machine_password, const struct netr_Credential *credentials_in, struct netr_Credential *credentials_out, + uint32_t client_requested_flags, const struct dom_sid *client_sid, 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; bool ok; @@ -707,6 +710,8 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me talloc_free(creds); return NULL; } + creds->ex->client_requested_flags = client_requested_flags; + creds->ex->auth_time = now; creds->ex->client_sid = *client_sid; if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index edc3284d32cd..3094292657ab 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -69,6 +69,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me const struct samr_Password *machine_password, const struct netr_Credential *credentials_in, struct netr_Credential *credentials_out, + uint32_t client_requested_flags, const struct dom_sid *client_sid, uint32_t negotiate_flags); NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index ad296f48d845..619e9e5591c6 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -22,6 +22,8 @@ interface schannel * On the server we use CLEAR_IF_FIRST, * so db layout changes don't matter there. */ + netr_NegotiateFlags client_requested_flags; + NTTIME auth_time; dom_sid client_sid; } netlogon_creds_CredentialState_extra_info; diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 936d3214173c..ad1d5dc33d7e 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1020,6 +1020,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, &mach_pwd, r->in.credentials, r->out.return_credentials, + in_neg_flags, &sid, neg_flags); if (!creds) { diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 5b7ca45ba426..01cc36111557 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -422,6 +422,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( "whenCreated", NULL}; uint32_t server_flags = 0; + uint32_t client_flags = 0; uint32_t negotiate_flags = 0; ZERO_STRUCTP(r->out.return_credentials); @@ -515,7 +516,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( * NETLOGON_NEG_STRONG_KEYS from server_flags... */ - negotiate_flags = *r->in.negotiate_flags & server_flags; + client_flags = *r->in.negotiate_flags; + negotiate_flags = client_flags & server_flags; switch (r->in.secure_channel_type) { case SEC_CHAN_WKSTA: @@ -792,6 +794,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( curNtHash, r->in.credentials, r->out.return_credentials, + client_flags, *sid, negotiate_flags); if (creds == NULL && prevNtHash != NULL) { @@ -810,6 +813,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( prevNtHash, r->in.credentials, r->out.return_credentials, + client_flags, *sid, negotiate_flags); } -- 2.34.1 From 66e5f80577362fc83d8d915757fc2b93f54f7c5b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 18:03:09 +0200 Subject: [PATCH 29/69] s3:rpc_server/netlogon: implement netr_LogonGetCapabilities query_level=2 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 484a046d8e179a3b21ead8b5bc3660095314e816) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index ad1d5dc33d7e..06ea1c0b756c 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -2317,12 +2317,7 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, case 1: break; case 2: - /* - * Until we know the details behind KB5028166 - * just return DCERPC_NCA_S_FAULT_INVALID_TAG - * like an unpatched Windows Server. - */ - FALL_THROUGH; + break; default: /* * There would not be a way to marshall the @@ -2350,7 +2345,15 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, return status; } - r->out.capabilities->server_capabilities = creds->negotiate_flags; + switch (r->in.query_level) { + case 1: + r->out.capabilities->server_capabilities = creds->negotiate_flags; + break; + case 2: + r->out.capabilities->requested_flags = + creds->ex->client_requested_flags; + break; + } return NT_STATUS_OK; } -- 2.34.1 From bd2ae3b3f1b44bdf97b08ad89e3b78db6a2ede54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 18:00:31 +0200 Subject: [PATCH 30/69] s4:rpc_server/netlogon: implement netr_LogonGetCapabilities query_level=2 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit fd4b027511b18615e215b66183f95b54bcab683e) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 01cc36111557..f0b01297f96e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2410,12 +2410,7 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c case 1: break; case 2: - /* - * Until we know the details behind KB5028166 - * just return DCERPC_NCA_S_FAULT_INVALID_TAG - * like an unpatched Windows Server. - */ - FALL_THROUGH; + break; default: /* * There would not be a way to marshall the @@ -2441,7 +2436,15 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c } NT_STATUS_NOT_OK_RETURN(status); - r->out.capabilities->server_capabilities = creds->negotiate_flags; + switch (r->in.query_level) { + case 1: + r->out.capabilities->server_capabilities = creds->negotiate_flags; + break; + case 2: + r->out.capabilities->requested_flags = + creds->ex->client_requested_flags; + break; + } return NT_STATUS_OK; } -- 2.34.1 From ebb9e955dbb78a8884111e670f009f4835face55 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:27:30 +0100 Subject: [PATCH 31/69] s4:torture/rpc: let test_netlogon_capabilities() fail on legacy servers BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 498fc88c155b57a0de6150c3b1e3cfcac181d45b) --- source4/torture/rpc/netlogon.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 9d01ff1461ac..6b403e2cf509 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -2110,10 +2110,10 @@ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *t netlogon_creds_client_authenticator(&tmp_creds, &auth); status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r); - torture_assert_ntstatus_ok(tctx, status, "LogonGetCapabilities failed"); - if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { - return true; - } + torture_assert_ntstatus_ok(tctx, status, + "LogonGetCapabilities query_level=1 failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "LogonGetCapabilities query_level=1 failed"); *creds = tmp_creds; @@ -2141,15 +2141,10 @@ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *t netlogon_creds_client_authenticator(&tmp_creds, &auth); status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) { - /* - * an server without KB5028166 returns - * DCERPC_NCA_S_FAULT_INVALID_TAG => - * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE - */ - return true; - } - torture_assert_ntstatus_ok(tctx, status, "LogonGetCapabilities query_level=2 failed"); + torture_assert_ntstatus_ok(tctx, status, + "LogonGetCapabilities query_level=2 failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "LogonGetCapabilities query_level=2 failed"); *creds = tmp_creds; -- 2.34.1 From 47d44a3ec6ef40969c835b89b8900a642f5ad3c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 32/69] libcli/auth: also use netlogon_creds_CredentialState_extra_info for the client 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 Reviewed-by: Douglas Bagnall (cherry picked from commit 8b972fea0978101575f847eac33b09d2fd8d02e7) --- libcli/auth/credentials.c | 15 ++++++++- libcli/auth/netlogon_creds_cli.c | 13 ++++++-- libcli/auth/proto.h | 1 + librpc/idl/schannel.idl | 47 ++++++++++++++++++++++++++- source4/librpc/rpc/dcerpc_schannel.c | 1 + source4/torture/ntp/ntp_signd.c | 1 + source4/torture/rpc/lsa.c | 2 ++ source4/torture/rpc/netlogon.c | 22 +++++++++++++ source4/torture/rpc/netlogon_crypto.c | 1 + source4/torture/rpc/samba3rpc.c | 8 +++-- 10 files changed, 104 insertions(+), 7 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 59db4bc28ea7..75ac4ddb0f24 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -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)); diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 40a40cb99aed..35a5462ff2e7 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -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); diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 3094292657ab..ae68aab192a9 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -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, diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index 619e9e5591c6..8905d514f557 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -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; diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 9d96abd2521e..ca0495c4d472 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -197,6 +197,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; diff --git a/source4/torture/ntp/ntp_signd.c b/source4/torture/ntp/ntp_signd.c index fd7da67c5518..2bf8e0fe1272 100644 --- a/source4/torture/ntp/ntp_signd.c +++ b/source4/torture/ntp/ntp_signd.c @@ -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"); diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index d91a5414de1c..60186693ea29 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -2951,6 +2951,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"); @@ -2976,6 +2977,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"); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 6b403e2cf509..c9a9202892ed 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -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"); @@ -541,6 +546,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"); @@ -618,6 +624,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"); @@ -702,6 +709,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"); @@ -788,6 +796,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"); @@ -881,6 +890,7 @@ static bool test_ServerAuthenticate2_encrypts_to_zero( &credentials2, mach_password, &credentials3, + flags, flags); torture_assert(tctx, creds != NULL, "memory allocation"); @@ -2272,6 +2282,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"); @@ -2361,6 +2372,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"); @@ -2378,6 +2390,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), @@ -2450,6 +2463,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"); @@ -2467,6 +2481,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), @@ -2540,6 +2555,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"); @@ -2557,6 +2573,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"); @@ -2655,6 +2672,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"); @@ -2672,6 +2690,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), @@ -2731,6 +2750,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"); @@ -2748,6 +2768,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), @@ -2762,6 +2783,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"); diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c index eec8a7531791..858a17e0ea8b 100644 --- a/source4/torture/rpc/netlogon_crypto.c +++ b/source4/torture/rpc/netlogon_crypto.c @@ -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 */ diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 10f0fccde73f..96ff34f52700 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -1091,7 +1091,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); @@ -2158,7 +2160,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); -- 2.34.1 From b7caf710263823be21a2719273cfad59339d9873 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 13:24:37 +0200 Subject: [PATCH 33/69] libcli/auth: let netlogon_creds_cli_store_internal() use talloc_stackframe() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 17394ed7bbf8fa50570a5732f1ce84ccd5e69393) --- libcli/auth/netlogon_creds_cli.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 35a5462ff2e7..1b9d26171e10 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -747,6 +747,7 @@ static NTSTATUS netlogon_creds_cli_store_internal( struct netlogon_creds_cli_context *context, struct netlogon_creds_CredentialState *creds) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; enum ndr_err_code ndr_err; DATA_BLOB blob; @@ -756,10 +757,11 @@ static NTSTATUS netlogon_creds_cli_store_internal( NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds); } - ndr_err = ndr_push_struct_blob(&blob, creds, creds, + ndr_err = ndr_push_struct_blob(&blob, frame, creds, (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); + TALLOC_FREE(frame); return status; } @@ -769,11 +771,12 @@ static NTSTATUS netlogon_creds_cli_store_internal( status = dbwrap_store(context->db.ctx, context->db.key_data, data, TDB_REPLACE); - TALLOC_FREE(data.dptr); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return status; } + TALLOC_FREE(frame); return NT_STATUS_OK; } -- 2.34.1 From 90d630925bb0fccfd7d8549ed9c0519c37afdff8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 13:39:38 +0200 Subject: [PATCH 34/69] libcli/auth: let netlogon_creds_cli_store_internal check netlogon_creds_CredentialState_legacy Before storing the structure into a ctdb managed volatile database we check against netlogon_creds_CredentialState_legacy (the structure used before recent changes). This makes sure unpatched cluster nodes would not get a parsing error. We'll remove this again in master when we try to implement netr_ServerAuthenticateKerberos() and the related changes to netlogon_creds_CredentialState, which will break the compat... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 3792fe372884aad6ea2893f2e62629dd1cddc129) --- libcli/auth/netlogon_creds_cli.c | 13 +++++++++++++ librpc/idl/schannel.idl | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 1b9d26171e10..07547a9178ce 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -752,6 +752,7 @@ static NTSTATUS netlogon_creds_cli_store_internal( enum ndr_err_code ndr_err; DATA_BLOB blob; TDB_DATA data; + struct netlogon_creds_CredentialState_legacy lc = { .sequence = 0, }; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds); @@ -765,6 +766,18 @@ static NTSTATUS netlogon_creds_cli_store_internal( return status; } + ndr_err = ndr_pull_struct_blob_all(&blob, frame, &lc, + (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState_legacy); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + TALLOC_FREE(frame); + return status; + } + + if (DEBUGLEVEL >= 11) { + NDR_PRINT_DEBUG(netlogon_creds_CredentialState_legacy, &lc); + } + data.dptr = blob.data; data.dsize = blob.length; diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index 8905d514f557..9fe4b7aed7c7 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -85,6 +85,19 @@ interface schannel netlogon_creds_CredentialState_extra_info *ex; } netlogon_creds_CredentialState; + typedef [public,flag(NDR_PAHEX)] struct { + netr_NegotiateFlags negotiate_flags; + uint8 session_key[16]; + uint32 sequence; + netr_Credential seed; + netr_Credential client; + netr_Credential server; + netr_SchannelType secure_channel_type; + [string,charset(UTF8)] uint8 computer_name[]; + [string,charset(UTF8)] uint8 account_name[]; + dom_sid *sid; + } netlogon_creds_CredentialState_legacy; + /* This is used in the schannel_store.tdb */ typedef [public] struct { [string,charset(UTF16)] uint16 *computer_name; -- 2.34.1 From d87d72b3f906e259f46323506d18a2ba0abb2af6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:47:22 +0200 Subject: [PATCH 35/69] libcli/auth: split out netlogon_creds_alloc() Review with: git show --patience BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit e9767315cf06bcb257b40014441dd4cd9aad0fb0) --- libcli/auth/credentials.c | 118 +++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 75ac4ddb0f24..c9c8ddb5394d 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -473,37 +473,27 @@ NTSTATUS netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds return NT_STATUS_OK; } -/***************************************************************** -The above functions are common to the client and server interface -next comes the client specific functions -******************************************************************/ - -/* - initialise the credentials chain and return the first client - credentials -*/ - -struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx, - const char *client_account, - const char *client_computer_name, - uint16_t secure_channel_type, - const struct netr_Credential *client_challenge, - 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) +static struct netlogon_creds_CredentialState * +netlogon_creds_alloc(TALLOC_CTX *mem_ctx, + const char *client_account, + const char *client_computer_name, + uint16_t secure_channel_type, + uint32_t client_requested_flags, + const struct dom_sid *client_sid, + uint32_t negotiate_flags) { - struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); + struct netlogon_creds_CredentialState *creds = NULL; struct timeval tv = timeval_current(); NTTIME now = timeval_to_nttime(&tv); - NTSTATUS status; - if (!creds) { + creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); + if (creds == NULL) { return NULL; } - creds->sequence = tv.tv_sec; + if (client_sid == NULL) { + creds->sequence = tv.tv_sec; + } creds->negotiate_flags = negotiate_flags; creds->secure_channel_type = secure_channel_type; @@ -526,7 +516,49 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me } creds->ex->client_requested_flags = client_requested_flags; creds->ex->auth_time = now; - creds->ex->client_sid = global_sid_NULL; + if (client_sid != NULL) { + creds->ex->client_sid = *client_sid; + } else { + creds->ex->client_sid = global_sid_NULL; + } + + return creds; +} + +/***************************************************************** +The above functions are common to the client and server interface +next comes the client specific functions +******************************************************************/ + +/* + initialise the credentials chain and return the first client + credentials +*/ + +struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx, + const char *client_account, + const char *client_computer_name, + uint16_t secure_channel_type, + const struct netr_Credential *client_challenge, + 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 = NULL; + NTSTATUS status; + + creds = netlogon_creds_alloc(mem_ctx, + client_account, + client_computer_name, + secure_channel_type, + client_requested_flags, + NULL, /* client_sid */ + negotiate_flags); + if (!creds) { + return 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)); @@ -674,20 +706,21 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me const struct dom_sid *client_sid, 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); + struct netlogon_creds_CredentialState *creds = NULL; NTSTATUS status; bool ok; + creds = netlogon_creds_alloc(mem_ctx, + client_account, + client_computer_name, + secure_channel_type, + client_requested_flags, + client_sid, + negotiate_flags); if (!creds) { return NULL; } - creds->negotiate_flags = negotiate_flags; - creds->secure_channel_type = secure_channel_type; - 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)); @@ -706,27 +739,6 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me return NULL; } - creds->computer_name = talloc_strdup(creds, client_computer_name); - if (!creds->computer_name) { - talloc_free(creds); - return NULL; - } - creds->account_name = talloc_strdup(creds, client_account); - if (!creds->account_name) { - talloc_free(creds); - 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 = *client_sid; - if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { status = netlogon_creds_init_hmac_sha256(creds, client_challenge, -- 2.34.1 From 81a0c55ff83084a4e64691b90925ad68a88c8a25 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:49:26 +0200 Subject: [PATCH 36/69] s4:dsdb/common: dsdb_trust_get_incoming_passwords only needs a const ldb_message BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit f92def2f943917d8946b03f71fcf676998701815) --- source4/dsdb/common/util_trusts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/common/util_trusts.c b/source4/dsdb/common/util_trusts.c index dcd4d315dda7..be7e2012053e 100644 --- a/source4/dsdb/common/util_trusts.c +++ b/source4/dsdb/common/util_trusts.c @@ -2668,7 +2668,7 @@ NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx, return NT_STATUS_OK; } -NTSTATUS dsdb_trust_get_incoming_passwords(struct ldb_message *msg, +NTSTATUS dsdb_trust_get_incoming_passwords(const struct ldb_message *msg, TALLOC_CTX *mem_ctx, struct samr_Password **_current, struct samr_Password **_previous) -- 2.34.1 From 9dc9fc4b818f3059edaf913715b4f61539a694d3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:55:41 +0200 Subject: [PATCH 37/69] s4:rpc_server/netlogon: split out dcesrv_netr_ServerAuthenticateGeneric() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit e4132c492ded7cadc60371b524e72e41f71f75e9) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 179 ++++++++++++------ 1 file changed, 125 insertions(+), 54 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index f0b01297f96e..61c214af7e26 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -388,14 +388,23 @@ return_downgrade: return orig_status; } -/* - * Do the actual processing of a netr_ServerAuthenticate3 message. - * called from dcesrv_netr_ServerAuthenticate3, which handles the logging. - */ -static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( +typedef NTSTATUS (*dcesrv_netr_ServerAuthenticateGenericCallback_fn)( + struct dcesrv_call_state *dce_call, + const struct netlogon_server_pipe_state *challenge, + const struct netr_ServerAuthenticate3 *r, + uint32_t client_flags, + const struct dom_sid *client_sid, + uint32_t negotiate_flags, + const struct ldb_message *sam_msg, + const struct ldb_message *tdo_msg, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **_creds); + +static NTSTATUS dcesrv_netr_ServerAuthenticateGeneric( struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerAuthenticate3 *r, + dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn, const char **trust_account_for_search, const char **trust_account_in_db, struct dom_sid **sid) @@ -405,10 +414,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( struct netlogon_server_pipe_state challenge; struct netlogon_creds_CredentialState *creds; struct ldb_context *sam_ctx; - struct samr_Password *curNtHash = NULL; - struct samr_Password *prevNtHash = NULL; uint32_t user_account_control; struct ldb_message **msgs; + struct ldb_message *tdo_msg = NULL; NTSTATUS nt_status; static const char *attrs[] = { "unicodePwd", @@ -551,7 +559,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) { - struct ldb_message *tdo_msg = NULL; static const char *const tdo_attrs[] = {"trustAuthIncoming", "trustAttributes", "flatName", @@ -620,22 +627,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( nt_status); } - nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx, - &curNtHash, - &prevNtHash); - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { - return dcesrv_netr_ServerAuthenticate3_check_downgrade( - dce_call, r, pipe_state, negotiate_flags, - NULL, /* trust_account_in_db */ - NT_STATUS_NO_TRUST_SAM_ACCOUNT); - } - if (!NT_STATUS_IS_OK(nt_status)) { - return dcesrv_netr_ServerAuthenticate3_check_downgrade( - dce_call, r, pipe_state, negotiate_flags, - NULL, /* trust_account_in_db */ - nt_status); - } - flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL); if (flatname == NULL) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( @@ -760,28 +751,92 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( } if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) { - nt_status = samdb_result_passwords_no_lockout(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, - msgs[0], &curNtHash); - if (!NT_STATUS_IS_OK(nt_status)) { - return NT_STATUS_ACCESS_DENIED; - } + tdo_msg = NULL; } - if (curNtHash == NULL) { + *sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid"); + if (*sid == NULL) { return NT_STATUS_ACCESS_DENIED; } - if (!challenge_valid) { - DEBUG(1, ("No challenge requested by client [%s/%s], " - "cannot authenticate\n", - log_escape(mem_ctx, r->in.computer_name), - log_escape(mem_ctx, r->in.account_name))); + nt_status = auth_fn(dce_call, + challenge_valid ? &challenge : NULL, + r, + client_flags, + *sid, + negotiate_flags, + msgs[0], + tdo_msg, + mem_ctx, + &creds); + if (!NT_STATUS_IS_OK(nt_status)) { + ZERO_STRUCTP(r->out.return_credentials); + return nt_status; + } + + nt_status = schannel_save_creds_state(mem_ctx, + dce_call->conn->dce_ctx->lp_ctx, + creds); + if (!NT_STATUS_IS_OK(nt_status)) { + ZERO_STRUCTP(r->out.return_credentials); + return nt_status; + } + + *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], + "objectSid", 0); + + return NT_STATUS_OK; +} + +static NTSTATUS dcesrv_netr_ServerAuthenticateNTHash_cb( + struct dcesrv_call_state *dce_call, + const struct netlogon_server_pipe_state *challenge, + const struct netr_ServerAuthenticate3 *r, + uint32_t client_flags, + const struct dom_sid *client_sid, + uint32_t negotiate_flags, + const struct ldb_message *sam_msg, + const struct ldb_message *tdo_msg, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **_creds) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + struct netlogon_creds_CredentialState *creds = NULL; + struct samr_Password *curNtHash = NULL; + struct samr_Password *prevNtHash = NULL; + NTSTATUS status; + + if (tdo_msg != NULL) { + status = dsdb_trust_get_incoming_passwords(tdo_msg, + frame, + &curNtHash, + &prevNtHash); + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_DISABLED)) { + status = NT_STATUS_NO_TRUST_SAM_ACCOUNT; + } + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + } else { + status = samdb_result_passwords_no_lockout(frame, + lp_ctx, + sam_msg, + &curNtHash); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return NT_STATUS_ACCESS_DENIED; + } + } + + if (curNtHash == NULL) { + TALLOC_FREE(frame); return NT_STATUS_ACCESS_DENIED; } - *sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid"); - if (*sid == NULL) { + if (challenge == NULL) { + TALLOC_FREE(frame); return NT_STATUS_ACCESS_DENIED; } @@ -789,13 +844,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( r->in.account_name, r->in.computer_name, r->in.secure_channel_type, - &challenge.client_challenge, - &challenge.server_challenge, + &challenge->client_challenge, + &challenge->server_challenge, curNtHash, r->in.credentials, r->out.return_credentials, client_flags, - *sid, + client_sid, negotiate_flags); if (creds == NULL && prevNtHash != NULL) { /* @@ -808,32 +863,48 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( r->in.account_name, r->in.computer_name, r->in.secure_channel_type, - &challenge.client_challenge, - &challenge.server_challenge, + &challenge->client_challenge, + &challenge->server_challenge, prevNtHash, r->in.credentials, r->out.return_credentials, client_flags, - *sid, + client_sid, negotiate_flags); } if (creds == NULL) { + TALLOC_FREE(frame); return NT_STATUS_ACCESS_DENIED; } - nt_status = schannel_save_creds_state(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, - creds); - if (!NT_STATUS_IS_OK(nt_status)) { - ZERO_STRUCTP(r->out.return_credentials); - return nt_status; - } + *_creds = creds; + TALLOC_FREE(frame); + return NT_STATUS_OK; +} - *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], - "objectSid", 0); +/* + * Do the actual processing of a netr_ServerAuthenticate3 message. + * called from dcesrv_netr_ServerAuthenticate3, which handles the logging. + */ +static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct netr_ServerAuthenticate3 *r, + const char **trust_account_for_search, + const char **trust_account_in_db, + struct dom_sid **sid) +{ + dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn = + dcesrv_netr_ServerAuthenticateNTHash_cb; - return NT_STATUS_OK; + return dcesrv_netr_ServerAuthenticateGeneric(dce_call, + mem_ctx, + r, + auth_fn, + trust_account_for_search, + trust_account_in_db, + sid); } /* -- 2.34.1 From b735e9de1d94d9b01ec51f765659104b64c8b7af Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 10 Sep 2024 13:56:38 +0200 Subject: [PATCH 38/69] dcesrv_core: add DCESRV_NOT_USED_ON_WIRE() helper macro BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 01577b93cbb0a26aba3209cde69475be2e1c5fb8) --- librpc/rpc/dcesrv_core.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/librpc/rpc/dcesrv_core.h b/librpc/rpc/dcesrv_core.h index 3758c8d7de2e..df60a8bf92e6 100644 --- a/librpc/rpc/dcesrv_core.h +++ b/librpc/rpc/dcesrv_core.h @@ -576,6 +576,14 @@ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call, return; \ } while(0) +#define DCESRV_NOT_USED_ON_WIRE(__opname) \ +static void dcesrv_## __opname(struct dcesrv_call_state *dce_call,\ + TALLOC_CTX *mem_ctx, \ + struct __opname *r) \ +{ \ + DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR); \ +} + /* a useful macro for checking the validity of a dcerpc policy handle and giving the right fault code if invalid */ #define DCESRV_CHECK_HANDLE(h) do {if (!(h)) DCESRV_FAULT(DCERPC_FAULT_CONTEXT_MISMATCH); } while (0) -- 2.34.1 From d03dcf0cc9b90b84e8a81dd39dc5214336e64682 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 10 Sep 2024 13:56:38 +0200 Subject: [PATCH 39/69] s3:rpc_server: add DCESRV_COMPAT_NOT_USED_ON_WIRE() helper macro BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 62afadb3ebac49a684fb0e5a1beb6d7db6f5e515) --- source3/rpc_server/rpc_pipes.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source3/rpc_server/rpc_pipes.h b/source3/rpc_server/rpc_pipes.h index 17922b07bbe3..09ad8d7a523b 100644 --- a/source3/rpc_server/rpc_pipes.h +++ b/source3/rpc_server/rpc_pipes.h @@ -70,4 +70,10 @@ void *_find_policy_by_hnd(struct pipes_struct *p, bool close_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd); bool pipe_access_check(struct pipes_struct *p); +#define DCESRV_COMPAT_NOT_USED_ON_WIRE(__opname) \ +void _## __opname(struct pipes_struct *p, struct __opname *r) \ +{ \ + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; \ +} + #endif /* _RPC_PIPES_H_ */ -- 2.34.1 From 0cdbe5ff0aa603ba983e07f9273078ce42c6fda2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Apr 2024 15:14:47 +0200 Subject: [PATCH 40/69] netlogon.idl: add netr_ServerAuthenticateKerberos() and related stuff BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit de8de55a5fee573d0718fa8dd13168a4f0a14614) --- librpc/idl/netlogon.idl | 31 ++++++++++++++++++- source3/rpc_server/netlogon/srv_netlog_nt.c | 25 +++++++++++++++ source4/rpc_server/netlogon/dcerpc_netlogon.c | 30 ++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl index ed75fe3797af..f9672b1bf547 100644 --- a/librpc/idl/netlogon.idl +++ b/librpc/idl/netlogon.idl @@ -1036,7 +1036,8 @@ interface netlogon NETLOGON_NEG_SUPPORTS_AES_SHA2 = 0x00400000, NETLOGON_NEG_SUPPORTS_AES = 0x01000000, NETLOGON_NEG_AUTHENTICATED_RPC_LSASS = 0x20000000, - NETLOGON_NEG_AUTHENTICATED_RPC = 0x40000000 + NETLOGON_NEG_AUTHENTICATED_RPC = 0x40000000, + NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH = 0x80000000 } netr_NegotiateFlags; const uint32 NETLOGON_NEG_128BIT = NETLOGON_NEG_STRONG_KEYS; @@ -1885,4 +1886,32 @@ interface netlogon [in] uint32 dns_ttl, [in,out,ref] NL_DNS_NAME_INFO_ARRAY *dns_names ); + + [todo] void netr_Opnum49NotUsedOnWire(void); + [todo] void netr_Opnum50NotUsedOnWire(void); + [todo] void netr_Opnum51NotUsedOnWire(void); + [todo] void netr_Opnum52NotUsedOnWire(void); + [todo] void netr_Opnum53NotUsedOnWire(void); + + /**********************/ + /* Function 0x36 (54) */ + /* from wireshark: */ + /* This is documented as 49 (0x31) but it's 54) */ + [todo] NTSTATUS netr_ChainSetClientAttributes(); + + [todo] void netr_Opnum55NotUsedOnWire(void); + [todo] void netr_Opnum56NotUsedOnWire(void); + [todo] void netr_Opnum57NotUsedOnWire(void); + [todo] void netr_Opnum58NotUsedOnWire(void); + + /*****************/ + /* Function 0x3b (59) */ + [public] NTSTATUS netr_ServerAuthenticateKerberos( + [in,unique] [string,charset(UTF16)] uint16 *server_name, + [in] [string,charset(UTF16)] uint16 *account_name, + [in] netr_SchannelType account_type, + [in] [string,charset(UTF16)] uint16 *computer_name, + [in,out,ref] netr_NegotiateFlags *negotiate_flags, + [out,ref] uint32 *rid + ); } diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 06ea1c0b756c..f473af2dce14 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -2916,6 +2916,31 @@ NTSTATUS _netr_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p, return NT_STATUS_NOT_IMPLEMENTED; } +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum49NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum50NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum51NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum52NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum53NotUsedOnWire) + +NTSTATUS _netr_ChainSetClientAttributes(struct pipes_struct *p, + struct netr_ChainSetClientAttributes *r) +{ + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return NT_STATUS_NOT_IMPLEMENTED; +} + +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum55NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum56NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum57NotUsedOnWire) +DCESRV_COMPAT_NOT_USED_ON_WIRE(netr_Opnum58NotUsedOnWire) + +NTSTATUS _netr_ServerAuthenticateKerberos(struct pipes_struct *p, + struct netr_ServerAuthenticateKerberos *r) +{ + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return NT_STATUS_NOT_IMPLEMENTED; +} + /* * Define the bind function that will be used by ndr_netlogon_scompat.c, * included at the bottom of this file. diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 61c214af7e26..2223bb7cace7 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -4806,6 +4806,36 @@ static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call return NT_STATUS_OK; } +DCESRV_NOT_USED_ON_WIRE(netr_Opnum49NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum50NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum51NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum52NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum53NotUsedOnWire) + +/* + netr_ChainSetClientAttributes + */ +static NTSTATUS dcesrv_netr_ChainSetClientAttributes(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct netr_ChainSetClientAttributes *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + +DCESRV_NOT_USED_ON_WIRE(netr_Opnum55NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum56NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum57NotUsedOnWire) +DCESRV_NOT_USED_ON_WIRE(netr_Opnum58NotUsedOnWire) + +/* + netr_ServerAuthenticateKerberos + */ +static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct netr_ServerAuthenticateKerberos *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} /* include the generated boilerplate */ #include "librpc/gen_ndr/ndr_netlogon_s.c" -- 2.34.1 From adf59c9edba6064b6512f8f1f965afd20857b1a6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:43:44 +0100 Subject: [PATCH 41/69] libcli/auth: pass auth_{type,level} to netlogon_creds_{de,en}crypt_samlogon_validation() This will be needed when we implement netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a56356e399339d5bce2e699431cd3e6186229170) --- libcli/auth/credentials.c | 14 ++++++++++++-- libcli/auth/libcli_auth.h | 1 + libcli/auth/netlogon_creds_cli.c | 14 ++++++++++++-- libcli/auth/proto.h | 8 ++++++-- source3/rpc_server/netlogon/srv_netlog_nt.c | 4 +++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 ++++++++- source4/torture/rpc/samlogon.c | 18 +++++++++++++++--- 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index c9c8ddb5394d..0f5dd1a676ac 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -830,6 +830,8 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, union netr_Validation *validation, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, bool do_encrypt) { struct netr_SamBaseInfo *base = NULL; @@ -945,21 +947,29 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C NTSTATUS netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, - union netr_Validation *validation) + union netr_Validation *validation, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { return netlogon_creds_crypt_samlogon_validation(creds, validation_level, validation, + auth_type, + auth_level, false); } NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, - union netr_Validation *validation) + union netr_Validation *validation, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { return netlogon_creds_crypt_samlogon_validation(creds, validation_level, validation, + auth_type, + auth_level, true); } diff --git a/libcli/auth/libcli_auth.h b/libcli/auth/libcli_auth.h index c5c7a7b0fa89..518dc3c2ca51 100644 --- a/libcli/auth/libcli_auth.h +++ b/libcli/auth/libcli_auth.h @@ -17,6 +17,7 @@ #ifndef __LIBCLI_AUTH_H__ #define __LIBCLI_AUTH_H__ +#include "librpc/gen_ndr/dcerpc.h" #include "librpc/gen_ndr/netlogon.h" #include "librpc/gen_ndr/wkssvc.h" #include "librpc/gen_ndr/schannel.h" diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 07547a9178ce..4f5a5f5d2ca9 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -2862,10 +2862,16 @@ static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) struct netlogon_creds_cli_LogonSamLogon_state *state = tevent_req_data(req, struct netlogon_creds_cli_LogonSamLogon_state); + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; NTSTATUS status; NTSTATUS result; bool ok; + dcerpc_binding_handle_auth_info(state->binding_handle, + &auth_type, + &auth_level); + if (state->try_logon_ex) { status = dcerpc_netr_LogonSamLogonEx_recv(subreq, state->validation, @@ -2918,7 +2924,9 @@ static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) status = netlogon_creds_decrypt_samlogon_validation(state->ro_creds, state->validation_level, - state->validation); + state->validation, + auth_type, + auth_level); if (tevent_req_nterror(req, status)) { netlogon_creds_cli_LogonSamLogon_cleanup(req, status); return; @@ -2992,7 +3000,9 @@ static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) status = netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds, state->validation_level, - state->validation); + state->validation, + auth_type, + auth_level); if (tevent_req_nterror(req, status)) { netlogon_creds_cli_LogonSamLogon_cleanup(req, result); return; diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index ae68aab192a9..1eec792d8041 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -78,10 +78,14 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState struct netr_Authenticator *return_authenticator) ; NTSTATUS netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, - union netr_Validation *validation); + union netr_Validation *validation, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, - union netr_Validation *validation); + union netr_Validation *validation, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); NTSTATUS netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, union netr_LogonLevel *logon); diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index f473af2dce14..b1743b8ee347 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1948,7 +1948,9 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, status = netlogon_creds_encrypt_samlogon_validation(creds, r->in.validation_level, - r->out.validation); + r->out.validation, + auth_type, + auth_level); return status; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 2223bb7cace7..0f4a1bd858bb 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1683,9 +1683,16 @@ static void dcesrv_netr_LogonSamLogon_base_reply( NTSTATUS status; if (NT_STATUS_IS_OK(r->out.result)) { + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(state->dce_call, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samlogon_validation(state->creds, r->in.validation_level, - r->out.validation); + r->out.validation, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("netlogon_creds_encrypt_samlogon_validation() " "failed - %s\n", diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index f16db6442411..a9f8ff5b5b6a 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -91,6 +91,12 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, struct netr_NetworkInfo ninfo; struct netr_SamBaseInfo *base = NULL; uint16_t validation_level = 0; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + dcerpc_binding_handle_auth_info(samlogon_state->p->binding_handle, + &auth_type, + &auth_level); samlogon_state->r.in.logon->network = &ninfo; samlogon_state->r_ex.in.logon->network = &ninfo; @@ -178,7 +184,9 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, validation_level, - r->out.validation); + r->out.validation, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { if (error_string) { *error_string = strdup(nt_errstr(status)); @@ -218,7 +226,9 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, validation_level, - r_ex->out.validation); + r_ex->out.validation, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { if (error_string) { *error_string = strdup(nt_errstr(status)); @@ -266,7 +276,9 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, validation_level, - r_flags->out.validation); + r_flags->out.validation, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { if (error_string) { *error_string = strdup(nt_errstr(status)); -- 2.34.1 From 85dd3ae65de077cd595628aaf5f3ae5b2172683b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:55:12 +0100 Subject: [PATCH 42/69] libcli/auth: pass auth_{type,level} to netlogon_creds_{de,en}crypt_samlogon_logon() This will be needed when we implement netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 3d4ea276bdf44202250246cd6edae2bc17e92c74) --- libcli/auth/credentials.c | 24 +++++++++++++++---- libcli/auth/netlogon_creds_cli.c | 8 +++++-- libcli/auth/proto.h | 8 +++++-- source3/rpc_server/netlogon/srv_netlog_nt.c | 4 +++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 4 +++- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 0f5dd1a676ac..dd43036c9bc4 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -976,6 +976,8 @@ NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_Creden static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, union netr_LogonLevel *logon, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, bool do_encrypt) { NTSTATUS status; @@ -1121,16 +1123,30 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden NTSTATUS netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, - union netr_LogonLevel *logon) + union netr_LogonLevel *logon, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { - return netlogon_creds_crypt_samlogon_logon(creds, level, logon, false); + return netlogon_creds_crypt_samlogon_logon(creds, + level, + logon, + auth_type, + auth_level, + false); } NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, - union netr_LogonLevel *logon) + union netr_LogonLevel *logon, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { - return netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); + return netlogon_creds_crypt_samlogon_logon(creds, + level, + logon, + auth_type, + auth_level, + true); } union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 4f5a5f5d2ca9..78aa9bf8b759 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -2738,7 +2738,9 @@ static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req) status = netlogon_creds_encrypt_samlogon_logon(state->ro_creds, state->logon_level, - state->logon); + state->logon, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; tevent_req_nterror(req, status); @@ -2802,7 +2804,9 @@ static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req) status = netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds, state->logon_level, - state->logon); + state->logon, + auth_type, + auth_level); if (tevent_req_nterror(req, status)) { netlogon_creds_cli_LogonSamLogon_cleanup(req, status); return; diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 1eec792d8041..c5e26d183ab4 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -88,10 +88,14 @@ NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_Creden enum dcerpc_AuthLevel auth_level); NTSTATUS netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, - union netr_LogonLevel *logon); + union netr_LogonLevel *logon, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, - union netr_LogonLevel *logon); + union netr_LogonLevel *logon, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in); diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index b1743b8ee347..6b6100477774 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1765,7 +1765,9 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, status = netlogon_creds_decrypt_samlogon_logon(creds, r->in.logon_level, - logon); + logon, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 0f4a1bd858bb..9090718be382 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1387,7 +1387,9 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL nt_status = netlogon_creds_decrypt_samlogon_logon(creds, r->in.logon_level, - r->in.logon); + r->in.logon, + auth_type, + auth_level); NT_STATUS_NOT_OK_RETURN(nt_status); switch (r->in.logon_level) { -- 2.34.1 From 158f607ec7599410dbfbd538077922bcc03edccb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:03:37 +0100 Subject: [PATCH 43/69] libcli/auth: add netlogon_creds_{de,en}crypt_samr_Password() These will simplify adding the logic for netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 851a9b18eccece64c3ae0cedd7c7b26a44f0eec6) --- libcli/auth/credentials.c | 47 +++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 8 +++++++ 2 files changed, 55 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index dd43036c9bc4..fcc06a948369 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -1149,6 +1149,53 @@ NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialS true); } +static NTSTATUS netlogon_creds_crypt_samr_Password( + struct netlogon_creds_CredentialState *creds, + struct samr_Password *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + bool do_encrypt) +{ + if (all_zero(pass->hash, ARRAY_SIZE(pass->hash))) { + return NT_STATUS_OK; + } + + /* + * Even with NETLOGON_NEG_SUPPORTS_AES or + * NETLOGON_NEG_ARCFOUR this uses DES + */ + + if (do_encrypt) { + return netlogon_creds_des_encrypt(creds, pass); + } + + return netlogon_creds_des_decrypt(creds, pass); +} + +NTSTATUS netlogon_creds_decrypt_samr_Password(struct netlogon_creds_CredentialState *creds, + struct samr_Password *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_samr_Password(creds, + pass, + auth_type, + auth_level, + false); +} + +NTSTATUS netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialState *creds, + struct samr_Password *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_samr_Password(creds, + pass, + auth_type, + auth_level, + true); +} + union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in) diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index c5e26d183ab4..b43781191bce 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -96,6 +96,14 @@ NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialS union netr_LogonLevel *logon, enum dcerpc_AuthType auth_type, enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_decrypt_samr_Password(struct netlogon_creds_CredentialState *creds, + struct samr_Password *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialState *creds, + struct samr_Password *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in); -- 2.34.1 From ed27fd6923dd9dc026407432438c151b0b300d85 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:12:24 +0100 Subject: [PATCH 44/69] libcli/auth: add netlogon_creds_{de,en}crypt_samr_CryptPassword() These will simplify adding the logic for netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 8eb95a155de396981375c7f11221695fd3c7f9d5) --- libcli/auth/credentials.c | 48 +++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 8 +++++++ 2 files changed, 56 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index fcc06a948369..6fdd4213b543 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -1196,6 +1196,54 @@ NTSTATUS netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialSt true); } +static NTSTATUS netlogon_creds_crypt_samr_CryptPassword( + struct netlogon_creds_CredentialState *creds, + struct samr_CryptPassword *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + bool do_encrypt) +{ + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + if (do_encrypt) { + return netlogon_creds_aes_encrypt(creds, + pass->data, + ARRAY_SIZE(pass->data)); + } + + return netlogon_creds_aes_decrypt(creds, + pass->data, + ARRAY_SIZE(pass->data)); + } + + return netlogon_creds_arcfour_crypt(creds, + pass->data, + ARRAY_SIZE(pass->data)); +} + +NTSTATUS netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds, + struct samr_CryptPassword *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_samr_CryptPassword(creds, + pass, + auth_type, + auth_level, + false); +} + +NTSTATUS netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds, + struct samr_CryptPassword *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_samr_CryptPassword(creds, + pass, + auth_type, + auth_level, + true); +} + union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in) diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index b43781191bce..d02ffa64c10c 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -104,6 +104,14 @@ NTSTATUS netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialSt struct samr_Password *pass, enum dcerpc_AuthType auth_type, enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds, + struct samr_CryptPassword *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds, + struct samr_CryptPassword *pass, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in); -- 2.34.1 From 1c6776f98e12ead8e4aebfca4a0968ac350811d6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:13:50 +0100 Subject: [PATCH 45/69] libcli/auth: add netlogon_creds_{de,en}crypt_SendToSam() These will simplify adding the logic for netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit b8681c165731666bb5eed073ab862490c33ea095) --- libcli/auth/credentials.c | 53 +++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 10 ++++++++ 2 files changed, 63 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 6fdd4213b543..3bc6b741c069 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -1244,6 +1244,59 @@ NTSTATUS netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_Credent true); } +static NTSTATUS netlogon_creds_crypt_SendToSam( + struct netlogon_creds_CredentialState *creds, + uint8_t *opaque_data, + size_t opaque_length, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + bool do_encrypt) +{ + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + if (do_encrypt) { + return netlogon_creds_aes_encrypt(creds, + opaque_data, + opaque_length); + } + + return netlogon_creds_aes_decrypt(creds, + opaque_data, + opaque_length); + } + + return netlogon_creds_arcfour_crypt(creds, + opaque_data, + opaque_length); +} + +NTSTATUS netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState *creds, + uint8_t *opaque_data, + size_t opaque_length, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_SendToSam(creds, + opaque_data, + opaque_length, + auth_type, + auth_level, + false); +} + +NTSTATUS netlogon_creds_encrypt_SendToSam(struct netlogon_creds_CredentialState *creds, + uint8_t *opaque_data, + size_t opaque_length, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) +{ + return netlogon_creds_crypt_SendToSam(creds, + opaque_data, + opaque_length, + auth_type, + auth_level, + true); +} + union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in) diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index d02ffa64c10c..f108c756a1f7 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -112,6 +112,16 @@ NTSTATUS netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_Credent struct samr_CryptPassword *pass, enum dcerpc_AuthType auth_type, enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState *creds, + uint8_t *opaque_data, + size_t opaque_length, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); +NTSTATUS netlogon_creds_encrypt_SendToSam(struct netlogon_creds_CredentialState *creds, + uint8_t *opaque_data, + size_t opaque_length, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, enum netr_LogonInfoClass level, const union netr_LogonLevel *in); -- 2.34.1 From 5e3a2383502246d6637411161f36e32b459c9db7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 14:06:28 +0100 Subject: [PATCH 46/69] pycredentials: make use of netlogon_creds_encrypt_samr_CryptPassword in py_creds_encrypt_netr_crypt_password These will simplify adding the logic for netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit ea792fa342deebefa75b77832c9057924cdcb6f6) --- auth/credentials/pycredentials.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 8008bd0418d5..9533392b6239 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1074,9 +1074,11 @@ static PyObject *py_creds_get_old_kerberos_key(PyObject *self, PyObject *args) static PyObject *py_creds_encrypt_netr_crypt_password(PyObject *self, PyObject *args) { - DATA_BLOB data = data_blob_null; struct cli_credentials *creds = NULL; struct netr_CryptPassword *pwd = NULL; + struct samr_CryptPassword spwd; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; NTSTATUS status; PyObject *py_cp = Py_None; @@ -1100,9 +1102,18 @@ static PyObject *py_creds_encrypt_netr_crypt_password(PyObject *self, /* pytalloc_get_type sets TypeError */ return NULL; } - data.length = sizeof(struct netr_CryptPassword); - data.data = (uint8_t *)pwd; - status = netlogon_creds_session_encrypt(creds->netlogon_creds, data); + + memcpy(spwd.data, pwd->data, 512); + PUSH_LE_U32(spwd.data, 512, pwd->length); + + status = netlogon_creds_encrypt_samr_CryptPassword(creds->netlogon_creds, + &spwd, + auth_type, + auth_level); + + memcpy(pwd->data, spwd.data, 512); + pwd->length = PULL_LE_U32(spwd.data, 512); + ZERO_STRUCT(spwd); PyErr_NTSTATUS_IS_ERR_RAISE(status); -- 2.34.1 From 526b443f576005a94c25db8e821c7a95de912cda Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:22:47 +0100 Subject: [PATCH 47/69] pycredentials: add py_creds_encrypt_netr_PasswordInfo helper This will replace py_creds_encrypt_samr_password in the next steps and prepares the introduction of netr_ServerAuthenticateKerberos(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit fac378485f5f15ac0a11c3d82207c4bc780bfb80) --- auth/credentials/pycredentials.c | 73 ++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 9533392b6239..b123c2e986a0 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1162,6 +1162,68 @@ static PyObject *py_creds_encrypt_samr_password(PyObject *self, Py_RETURN_NONE; } +static PyObject *py_creds_encrypt_netr_PasswordInfo(PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + const char * const kwnames[] = { + "info", + "auth_type", + "auth_level", + NULL + }; + struct cli_credentials *creds = NULL; + PyObject *py_info = Py_None; + enum netr_LogonInfoClass level = NetlogonInteractiveInformation; + union netr_LogonLevel logon = { .password = NULL, }; + uint8_t auth_type = DCERPC_AUTH_TYPE_NONE; + uint8_t auth_level = DCERPC_AUTH_LEVEL_NONE; + NTSTATUS status; + bool ok; + + creds = PyCredentials_AsCliCredentials(self); + if (creds == NULL) { + PyErr_Format(PyExc_TypeError, "Credentials expected"); + return NULL; + } + + if (creds->netlogon_creds == NULL) { + PyErr_Format(PyExc_ValueError, "NetLogon credentials not set"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Obb", + discard_const_p(char *, kwnames), + &py_info, &auth_type, &auth_level)) + { + return NULL; + } + + ok = py_check_dcerpc_type(py_info, + "samba.dcerpc.netlogon", + "netr_PasswordInfo"); + if (!ok) { + /* py_check_dcerpc_type sets TypeError */ + return NULL; + } + + logon.password = pytalloc_get_type(py_info, struct netr_PasswordInfo); + if (logon.password == NULL) { + /* pytalloc_get_type sets TypeError */ + return NULL; + } + + status = netlogon_creds_encrypt_samlogon_logon(creds->netlogon_creds, + level, + &logon, + auth_type, + auth_level); + + PyErr_NTSTATUS_IS_ERR_RAISE(status); + + Py_RETURN_NONE; +} + static PyObject *py_creds_get_smb_signing(PyObject *self, PyObject *unused) { enum smb_signing_setting signing_state; @@ -1695,6 +1757,17 @@ static PyMethodDef py_creds_methods[] = { "the negotiated encryption algorithm in place\n" "i.e. it overwrites the original data" }, + { + .ml_name = "encrypt_netr_PasswordInfo", + .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, + py_creds_encrypt_netr_PasswordInfo), + .ml_flags = METH_VARARGS | METH_KEYWORDS, + .ml_doc = "S.encrypt_netr_PasswordInfo(info, " + "auth_type, auth_level) -> None\n" + "Encrypt the supplied password info using the session key and\n" + "the negotiated encryption algorithm in place\n" + "i.e. it overwrites the original data" + }, { .ml_name = "get_smb_signing", .ml_meth = py_creds_get_smb_signing, -- 2.34.1 From ad205a99c1a0b2c1a38c4dfb2ffc9c7457867c54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:39:57 +0100 Subject: [PATCH 48/69] python/tests: use encrypt_netr_PasswordInfo in KDCBaseTest._test_samlogon() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit e7d57fc6e992ca212b834d5dd4d381244bca55c6) --- python/samba/tests/krb5/kdc_base_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index df5e22be4ae3..66e222caa477 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -54,6 +54,7 @@ from samba.credentials import ( from samba.crypto import des_crypt_blob_16, md4_hash_blob from samba.dcerpc import ( claims, + dcerpc, drsblobs, drsuapi, krb5ccache, @@ -3702,10 +3703,12 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): workstation = domain_joined_mach_creds.get_username() # Calling this initializes netlogon_creds on mach_creds, as is required - # before calling mach_creds.encrypt_samr_password(). + # before calling mach_creds.encrypt_netr_PasswordInfo(). conn = netlogon.netlogon(f'ncacn_ip_tcp:{dc_server}[schannel,seal]', self.get_lp(), domain_joined_mach_creds) + auth_type = dcerpc.DCERPC_AUTH_TYPE_SCHANNEL + auth_level = dcerpc.DCERPC_AUTH_LEVEL_PRIVACY if logon_type == netlogon.NetlogonInteractiveInformation: logon = netlogon.netr_PasswordInfo() @@ -3715,11 +3718,14 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): nt_pass = samr.Password() nt_pass.hash = list(creds.get_nt_hash()) - domain_joined_mach_creds.encrypt_samr_password(nt_pass) logon.lmpassword = lm_pass logon.ntpassword = nt_pass + domain_joined_mach_creds.encrypt_netr_PasswordInfo(info=logon, + auth_type=auth_type, + auth_level=auth_level) + elif logon_type == netlogon.NetlogonNetworkInformation: computername = ntlmssp.AV_PAIR() computername.AvId = ntlmssp.MsvAvNbComputerName -- 2.34.1 From 5e53c5a4fcc97f5ebce280921e9f05fc2a60b76b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:52:13 +0100 Subject: [PATCH 49/69] libcli/auth: make netlogon_creds_des_{de,en}crypt_LMKey() static BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 1edcd5df80bdbc4d4da5bdd5e534d7a17ec61f77) --- libcli/auth/credentials.c | 4 ++-- libcli/auth/proto.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 3bc6b741c069..ec5552e60c07 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -290,7 +290,7 @@ static NTSTATUS netlogon_creds_step(struct netlogon_creds_CredentialState *creds /* DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key */ -NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, +static NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key) { int rc; @@ -308,7 +308,7 @@ NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState /* DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key */ -NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, +static NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key) { int rc; diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index f108c756a1f7..53a7d2062dbd 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -16,10 +16,6 @@ bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge); void netlogon_creds_random_challenge(struct netr_Credential *challenge); -NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, - struct netr_LMSessionKey *key); -NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, - struct netr_LMSessionKey *key); NTSTATUS netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass); NTSTATUS netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds, -- 2.34.1 From d44300816e8245fcefb9f1e578268782693d3e74 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:56:09 +0100 Subject: [PATCH 50/69] libcli/auth: make use of netlogon_creds_encrypt_samr_CryptPassword This will help when implementing netr_ServerAuthenticateKerberos()... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 285ec9ecde712e40e6f0981bcb379ee911bfe9d8) --- libcli/auth/netlogon_creds_cli.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 78aa9bf8b759..017f30601396 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -2346,22 +2346,13 @@ static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subre if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { - if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - status = netlogon_creds_aes_encrypt(&state->tmp_creds, - state->samr_crypt_password.data, - 516); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); - return; - } - } else { - status = netlogon_creds_arcfour_crypt(&state->tmp_creds, - state->samr_crypt_password.data, - 516); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); - return; - } + status = netlogon_creds_encrypt_samr_CryptPassword(&state->tmp_creds, + &state->samr_crypt_password, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; } memcpy(state->netr_crypt_password.data, -- 2.34.1 From d58bd90ed2db12881f058c312357a65a5733c901 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:00:52 +0100 Subject: [PATCH 51/69] libcli/auth: make use of netlogon_creds_encrypt_SendToSam This will help when implementing netr_ServerAuthenticateKerberos()... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 2bd77ff7314932dc4116773731a810fe0f7ce4b7) --- libcli/auth/netlogon_creds_cli.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 017f30601396..3a42d57f0019 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -4079,22 +4079,14 @@ static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq) } ZERO_STRUCT(state->rep_auth); - if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - status = netlogon_creds_aes_encrypt(&state->tmp_creds, - state->opaque.data, - state->opaque.length); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_SendToSam_cleanup(req, status); - return; - } - } else { - status = netlogon_creds_arcfour_crypt(&state->tmp_creds, - state->opaque.data, - state->opaque.length); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_SendToSam_cleanup(req, status); - return; - } + status = netlogon_creds_encrypt_SendToSam(&state->tmp_creds, + state->opaque.data, + state->opaque.length, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_SendToSam_cleanup(req, status); + return; } subreq = dcerpc_netr_NetrLogonSendToSam_send(state, state->ev, -- 2.34.1 From c9388c7c1939fcb5888a34cad104d13a28168437 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:19:09 +0100 Subject: [PATCH 52/69] libcli/auth: make use of netlogon_creds_{de,en}crypt_samr_Password This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit e92d0509d6b4d7f86e8626ba8c5efc5b786823f1) --- libcli/auth/netlogon_creds_cli.c | 40 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 3a42d57f0019..fd9e71ad8c67 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -2375,8 +2375,10 @@ static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subre return; } } else { - status = netlogon_creds_des_encrypt(&state->tmp_creds, - &state->samr_password); + status = netlogon_creds_encrypt_samr_Password(&state->tmp_creds, + &state->samr_password, + state->auth_type, + state->auth_level); if (tevent_req_nterror(req, status)) { netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); return; @@ -3518,8 +3520,6 @@ static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq struct netlogon_creds_cli_ServerGetTrustInfo_state); NTSTATUS status; NTSTATUS result; - const struct samr_Password zero = {}; - bool cmp; bool ok; /* @@ -3545,25 +3545,21 @@ static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq return; } - cmp = mem_equal_const_time(state->new_owf_password.hash, - zero.hash, sizeof(zero.hash)); - if (!cmp) { - status = netlogon_creds_des_decrypt(&state->tmp_creds, - &state->new_owf_password); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status); - return; - } + status = netlogon_creds_decrypt_samr_Password(&state->tmp_creds, + &state->new_owf_password, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status); + return; } - cmp = mem_equal_const_time(state->old_owf_password.hash, - zero.hash, sizeof(zero.hash)); - if (!cmp) { - status = netlogon_creds_des_decrypt(&state->tmp_creds, - &state->old_owf_password); - if (tevent_req_nterror(req, status)) { - netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status); - return; - } + status = netlogon_creds_decrypt_samr_Password(&state->tmp_creds, + &state->old_owf_password, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status); + return; } *state->creds = state->tmp_creds; -- 2.34.1 From 9a3aef855375eb7a9de0e352090e447f8e640061 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:58:11 +0100 Subject: [PATCH 53/69] s4:torture/rpc: make use of netlogon_creds_encrypt_samlogon_logon() This will make it easier to catch all places where we need to implement the logic for netr_ServerAuthenticateKerberos... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 1666d1d74dec3978837ab49f8749d59c0abcf595) --- source4/torture/rpc/remote_pac.c | 42 ++++++++++++++++++++------------ source4/torture/rpc/samlogon.c | 20 +++++++++------ source4/torture/rpc/samr.c | 21 ++++++++-------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index 8f4ee2bbc445..668962181640 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/source4/torture/rpc/remote_pac.c @@ -406,6 +406,9 @@ static bool netlogon_validate_pac(struct torture_context *tctx, struct dcerpc_binding_handle *b = NULL; enum ndr_err_code ndr_err; DATA_BLOB payload, pac_wrapped; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + NTSTATUS status; if (!test_SetupCredentials2(p1, tctx, negotiate_flags, server_creds, secure_channel_type, @@ -437,11 +440,6 @@ static bool netlogon_validate_pac(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length); - } else { - netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); - } generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -471,6 +469,14 @@ static bool netlogon_validate_pac(struct torture_context *tctx, r.out.authoritative = &authoritative; r.out.return_authenticator = &return_authenticator; + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samlogon_logon(creds, + r.in.logon_level, + r.in.logon, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samlogon_logon"); + torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r), "LogonSamLogon failed"); @@ -546,11 +552,6 @@ static bool netlogon_validate_pac(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length); - } else { - netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); - } generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -567,6 +568,14 @@ static bool netlogon_validate_pac(struct torture_context *tctx, r.in.computer_name = cli_credentials_get_workstation(server_creds); r.in.validation_level = NetlogonValidationGenericInfo2; + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samlogon_logon(creds, + r.in.logon_level, + r.in.logon, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samlogon_logon"); + torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r), "LogonSamLogon failed"); @@ -598,11 +607,6 @@ static bool netlogon_validate_pac(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length); - } else { - netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); - } generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -619,6 +623,14 @@ static bool netlogon_validate_pac(struct torture_context *tctx, r.in.computer_name = cli_credentials_get_workstation(server_creds); r.in.validation_level = NetlogonValidationGenericInfo2; + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samlogon_logon(creds, + r.in.logon_level, + r.in.logon, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samlogon_logon"); + torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r), "LogonSamLogon failed"); diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index a9f8ff5b5b6a..57768aeb4113 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -1551,6 +1551,10 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, union netr_Validation validation; uint8_t authoritative = 1; struct dcerpc_binding_handle *b = p->binding_handle; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); ZERO_STRUCT(a); ZERO_STRUCT(r); @@ -1586,13 +1590,15 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } E_md4hash(plain_pass, pinfo.ntpassword.hash); - if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); - netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); - } else { - netlogon_creds_des_encrypt(creds, &pinfo.lmpassword); - netlogon_creds_des_encrypt(creds, &pinfo.ntpassword); - } + status = netlogon_creds_encrypt_samlogon_logon(creds, + r.in.logon_level, + r.in.logon, + auth_type, + auth_level); + torture_assert_ntstatus_ok_goto(tctx, + status, + ret, failed, + "netlogon_creds_encrypt_samlogon_logon"); torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment); diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 36dd86f6770d..806936e9055f 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -3607,6 +3607,8 @@ static bool test_SamLogon(struct torture_context *tctx, struct netlogon_creds_CredentialState *creds; struct netr_Authenticator a; struct dcerpc_binding_handle *b = p->binding_handle; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), ""); @@ -3636,17 +3638,6 @@ static bool test_SamLogon(struct torture_context *tctx, } E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16); - netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16); - } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); - netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); - } else { - netlogon_creds_des_encrypt(creds, &pinfo.lmpassword); - netlogon_creds_des_encrypt(creds, &pinfo.ntpassword); - } - pinfo.identity_info = identity; logon.password = &pinfo; @@ -3693,6 +3684,14 @@ static bool test_SamLogon(struct torture_context *tctx, r.in.validation_level = 6; + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samlogon_logon(creds, + r.in.logon_level, + r.in.logon, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samlogon_logon"); + torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r), "netr_LogonSamLogonEx failed"); if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) { -- 2.34.1 From b58230f09c6ea73f149b327c792dd67932cc2189 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:57:53 +0100 Subject: [PATCH 54/69] s4:torture/rpc: make use of netlogon_creds_decrypt_samlogon_validation() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a177d15c875030dfc6c11ead3ec3a3ec851261cb) --- source4/torture/rpc/schannel.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index 497e15455ab7..32a7380761cf 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -64,6 +64,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx, struct netr_SamBaseInfo *base = NULL; const char *crypto_alg = ""; bool can_do_validation_6 = true; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; if (lpcfg_client_lanman_auth(tctx->lp_ctx)) { @@ -137,7 +138,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx, } } - dcerpc_binding_handle_auth_info(b, NULL, &auth_level); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { r.in.validation_level = 6; @@ -208,13 +209,12 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx, dump_data(1, base->key.key, 16); dump_data(1, base->LMSessKey.key, 8); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_decrypt(creds, base->key.key, 16); - netlogon_creds_aes_decrypt(creds, base->LMSessKey.key, 8); - } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, base->key.key, 16); - netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, 8); - } + status = netlogon_creds_decrypt_samlogon_validation(creds, + r.in.validation_level, + r.out.validation, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samlogon_validation"); DEBUG(1,("decrypted keys validation_level %d\n", validation_levels[i])); @@ -281,6 +281,7 @@ static bool test_netlogon_ex_bug14932(struct dcerpc_pipe *p, struct netr_SamBaseInfo *base = NULL; const char *crypto_alg = ""; bool can_do_validation_6 = true; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; flags |= CLI_CRED_NTLMv2_AUTH; @@ -346,7 +347,7 @@ static bool test_netlogon_ex_bug14932(struct dcerpc_pipe *p, } } - dcerpc_binding_handle_auth_info(b, NULL, &auth_level); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { r.in.validation_level = 6; @@ -417,13 +418,12 @@ static bool test_netlogon_ex_bug14932(struct dcerpc_pipe *p, dump_data(1, base->key.key, 16); dump_data(1, base->LMSessKey.key, 8); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_decrypt(creds, base->key.key, 16); - netlogon_creds_aes_decrypt(creds, base->LMSessKey.key, 8); - } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, base->key.key, 16); - netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, 8); - } + status = netlogon_creds_decrypt_samlogon_validation(creds, + r.in.validation_level, + r.out.validation, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samlogon_validation"); DEBUG(1,("decrypted keys validation_level %d\n", validation_levels[i])); -- 2.34.1 From f989867d25fccd0752be92380966f0b59f16abb9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:22:36 +0100 Subject: [PATCH 55/69] s4:torture/rpc: make use of netlogon_creds_encrypt_samr_CryptPassword() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 2d7a47a175337729f4c671d7a6223f6e0ea23ebe) --- source4/torture/rpc/lsa.c | 19 +++--- source4/torture/rpc/netlogon.c | 111 ++++++++++++++++++++++++--------- 2 files changed, 91 insertions(+), 39 deletions(-) diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 60186693ea29..4d729f3e7fea 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -4370,6 +4370,8 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, struct tsocket_address *dest_addr; struct cldap_socket *cldap; struct cldap_netlogon cldap1; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; incoming_creds = cli_credentials_init(tctx); torture_assert(tctx, incoming_creds, "cli_credentials_init"); @@ -4525,15 +4527,14 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, netlogon_creds_client_authenticator(creds, &req_auth); ZERO_STRUCT(rep_auth); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, - samr_crypt_password.data, - 516); - } else { - netlogon_creds_arcfour_crypt(creds, - samr_crypt_password.data, - 516); - } + dcerpc_binding_handle_auth_info(p2->binding_handle, + &auth_type, + &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &samr_crypt_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(netr_crypt_password.data, samr_crypt_password.data, 512); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index c9a9202892ed..216c14c440cc 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -1112,6 +1112,9 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_SetupCredentials2(p1, tctx, flags, machine_credentials, cli_credentials_get_secure_channel_type(machine_credentials), @@ -1134,11 +1137,12 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, password = generate_random_password(tctx, 8, 255); encode_pw_buffer(password_buf.data, password, STR_UNICODE); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); - } else { - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); - } + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1168,11 +1172,12 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, */ password = ""; encode_pw_buffer(password_buf.data, password, STR_UNICODE); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); - } else { - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); - } + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1195,11 +1200,12 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, /* now try a random password */ password = generate_random_password(tctx, 8, 255); encode_pw_buffer(password_buf.data, password, STR_UNICODE); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); - } else { - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); - } + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1246,11 +1252,12 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, /* now try a random stream of bytes for a password */ set_pw_in_buffer(password_buf.data, &new_random_pass); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); - } else { - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); - } + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1299,6 +1306,9 @@ static bool test_SetPassword2_encrypted_to_all_zeros( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_ServerAuthenticate2_encrypts_to_zero( tctx, @@ -1338,7 +1348,12 @@ static bool test_SetPassword2_encrypted_to_all_zeros( if (!(creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES not set"); } - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); if(!all_zero(password_buf.data, 516)) { torture_fail(tctx, "Password did not encrypt to all zeros\n"); } @@ -1385,6 +1400,9 @@ static bool test_SetPassword2_password_encrypts_to_zero( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_ServerAuthenticate2_encrypts_to_zero( tctx, @@ -1425,7 +1443,12 @@ static bool test_SetPassword2_password_encrypts_to_zero( if (!(creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES not set"); } - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1461,6 +1484,9 @@ static bool test_SetPassword2_confounder( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_ServerAuthenticate2_encrypts_to_zero( tctx, @@ -1502,7 +1528,12 @@ static bool test_SetPassword2_confounder( if (!(creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES not set"); } - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1538,6 +1569,9 @@ static bool test_SetPassword2_all_zeros( struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_SetupCredentials2( p1, @@ -1576,7 +1610,12 @@ static bool test_SetPassword2_all_zeros( if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES enabled\n"); } - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1615,6 +1654,9 @@ static bool test_SetPassword2_maximum_length_password( struct dcerpc_binding_handle *b = NULL; uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; DATA_BLOB new_random_pass = data_blob_null; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_SetupCredentials2( p1, @@ -1652,11 +1694,12 @@ static bool test_SetPassword2_maximum_length_password( new_random_pass = netlogon_very_rand_pass(tctx, 256); set_pw_in_buffer(password_buf.data, &new_random_pass); SIVAL(password_buf.data, 512, 512); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(creds, password_buf.data, 516); - } else { - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); - } + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -1697,6 +1740,9 @@ static bool test_SetPassword2_all_zero_password( struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_SetupCredentials2( p1, @@ -1736,7 +1782,12 @@ static bool test_SetPassword2_all_zero_password( if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES set"); } - netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_CryptPassword"); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); -- 2.34.1 From eccd2d6d01c8d042d5a83f7125954a6343c713e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:43:40 +0100 Subject: [PATCH 56/69] s4:torture/rpc: make use of netlogon_creds_{de,en}crypt_samr_Password BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 172ce406d48916c57f0742b6a0e064ac170ec8ff) --- source4/torture/rpc/forest_trust.c | 17 +++++++++++++-- source4/torture/rpc/netlogon.c | 35 +++++++++++++++++++++++++++--- source4/torture/rpc/samba3rpc.c | 11 +++++++++- source4/torture/rpc/schannel.c | 11 +++++++++- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/source4/torture/rpc/forest_trust.c b/source4/torture/rpc/forest_trust.c index 284d5e4441ce..c4ca02da58ee 100644 --- a/source4/torture/rpc/forest_trust.c +++ b/source4/torture/rpc/forest_trust.c @@ -658,6 +658,8 @@ static bool test_validate_trust(struct torture_context *tctx, struct samr_Password *old_nt_hash; char *dummy; uint32_t trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); @@ -733,8 +735,19 @@ static bool test_validate_trust(struct torture_context *tctx, old_nt_hash = cli_credentials_get_old_nt_hash(credentials, tctx); torture_assert(tctx, old_nt_hash != NULL, "cli_credentials_get_old_nt_hash()"); - netlogon_creds_des_decrypt(creds, &new_owf_password); - netlogon_creds_des_decrypt(creds, &old_owf_password); + dcerpc_binding_handle_auth_info(p->binding_handle, + &auth_type, + &auth_level); + status = netlogon_creds_decrypt_samr_Password(creds, + &new_owf_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samr_Password"); + status = netlogon_creds_decrypt_samr_Password(creds, + &old_owf_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samr_Password"); dump_data(1, new_owf_password.hash, 16); dump_data(1, new_nt_hash->hash, 16); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 216c14c440cc..b9f5e66f0d89 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -932,6 +932,9 @@ static bool test_SetPassword(struct torture_context *tctx, struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; struct dcerpc_binding_handle *b = p->binding_handle; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + NTSTATUS status; if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) { return false; @@ -948,7 +951,12 @@ static bool test_SetPassword(struct torture_context *tctx, password = generate_random_password(tctx, 8, 255); E_md4hash(password, new_password.hash); - netlogon_creds_des_encrypt(creds, &new_password); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_Password(creds, + &new_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_Password"); torture_comment(tctx, "Testing ServerPasswordSet on machine account\n"); torture_comment(tctx, "Changing machine account password to '%s'\n", @@ -1007,6 +1015,9 @@ static bool test_SetPassword_flags(struct torture_context *tctx, struct samr_Password new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; if (!test_SetupCredentials2(p1, tctx, negotiate_flags, machine_credentials, @@ -1031,7 +1042,12 @@ static bool test_SetPassword_flags(struct torture_context *tctx, password = generate_random_password(tctx, 8, 255); E_md4hash(password, new_password.hash); - netlogon_creds_des_encrypt(creds, &new_password); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_encrypt_samr_Password(creds, + &new_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_Password"); torture_comment(tctx, "Testing ServerPasswordSet on machine account\n"); torture_comment(tctx, "Changing machine account password to '%s'\n", @@ -5042,6 +5058,9 @@ static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx, struct dcerpc_binding_handle *b = NULL; struct samr_Password nt_hash; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + NTSTATUS status; if (!test_SetupCredentials3(p1, tctx, negotiate_flags, machine_credentials, &creds)) { @@ -5073,7 +5092,17 @@ static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx, E_md4hash(cli_credentials_get_password(machine_credentials), nt_hash.hash); - netlogon_creds_des_decrypt(creds, &new_owf_password); + dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level); + status = netlogon_creds_decrypt_samr_Password(creds, + &new_owf_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samr_Password"); + status = netlogon_creds_decrypt_samr_Password(creds, + &old_owf_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "decrypt_samr_Password"); dump_data(1, new_owf_password.hash, 16); dump_data(1, nt_hash.hash, 16); diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 96ff34f52700..0ce948895bc7 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -1305,6 +1305,8 @@ static bool schan(struct torture_context *tctx, struct netlogon_creds_CredentialState *creds_state; struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; s.in.server_name = talloc_asprintf( mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe)); @@ -1319,7 +1321,14 @@ static bool schan(struct torture_context *tctx, E_md4hash(password, new_password.hash); creds_state = cli_credentials_get_netlogon_creds(wks_creds); - netlogon_creds_des_encrypt(creds_state, &new_password); + dcerpc_binding_handle_auth_info(net_handle, + &auth_type, + &auth_level); + status = netlogon_creds_encrypt_samr_Password(creds_state, + &new_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(tctx, status, "encrypt_samr_Password"); netlogon_creds_client_authenticator(creds_state, &credential); status = dcerpc_netr_ServerPasswordSet_r(net_handle, mem_ctx, &s); diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index 32a7380761cf..238952f93f9d 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -1290,6 +1290,8 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) struct dcerpc_pipe *net_pipe; struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; status = dcerpc_pipe_connect_b(s, &net_pipe, s->b, &ndr_table_netlogon, @@ -1314,7 +1316,14 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) creds_state = cli_credentials_get_netlogon_creds( s->wks_creds1); - netlogon_creds_des_encrypt(creds_state, &new_password); + dcerpc_binding_handle_auth_info(net_pipe->binding_handle, + &auth_type, + &auth_level); + status = netlogon_creds_encrypt_samr_Password(creds_state, + &new_password, + auth_type, + auth_level); + torture_assert_ntstatus_ok(torture, status, "encrypt_samr_Password"); netlogon_creds_client_authenticator(creds_state, &credential); torture_assert_ntstatus_ok(torture, dcerpc_netr_ServerPasswordSet_r(net_pipe->binding_handle, torture, &pwset), -- 2.34.1 From c10ed31731103f80b107ded765ea53f374c2ac65 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:12:16 +0100 Subject: [PATCH 57/69] s3:rpc_server/netlogon: make use of netlogon_creds_{de,en}crypt_samr_Password BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 550d20fd3dd04397b3a38f8b9e0cfa574453eea1) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 32 +++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 6b6100477774..5f189688d7bb 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1318,6 +1318,10 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, struct netlogon_creds_CredentialState *creds = NULL; struct _samr_Credentials_t cr = { CRED_TYPE_NT_HASH, {0}}; const struct dom_sid *client_sid = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); DEBUG(5,("_netr_ServerPasswordSet: %d\n", __LINE__)); @@ -1347,7 +1351,10 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, DEBUG(3,("_netr_ServerPasswordSet: Server Password Set by remote machine:[%s] on account [%s]\n", r->in.computer_name, creds->computer_name)); - status = netlogon_creds_des_decrypt(creds, r->in.new_password); + status = netlogon_creds_decrypt_samr_Password(creds, + r->in.new_password, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2751,7 +2758,9 @@ static NTSTATUS get_password_from_trustAuth(TALLOC_CTX *mem_ctx, const DATA_BLOB *trustAuth_blob, struct netlogon_creds_CredentialState *creds, struct samr_Password *current_pw_enc, - struct samr_Password *previous_pw_enc) + struct samr_Password *previous_pw_enc, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { enum ndr_err_code ndr_err; struct trustAuthInOutBlob trustAuth; @@ -2768,7 +2777,10 @@ static NTSTATUS get_password_from_trustAuth(TALLOC_CTX *mem_ctx, mdfour(current_pw_enc->hash, trustAuth.current.array[0].AuthInfo.clear.password, trustAuth.current.array[0].AuthInfo.clear.size); - status = netlogon_creds_des_encrypt(creds, current_pw_enc); + status = netlogon_creds_encrypt_samr_Password(creds, + current_pw_enc, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2782,7 +2794,10 @@ static NTSTATUS get_password_from_trustAuth(TALLOC_CTX *mem_ctx, mdfour(previous_pw_enc->hash, trustAuth.previous.array[0].AuthInfo.clear.password, trustAuth.previous.array[0].AuthInfo.clear.size); - status = netlogon_creds_des_encrypt(creds, previous_pw_enc); + status = netlogon_creds_encrypt_samr_Password(creds, + previous_pw_enc, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2807,6 +2822,10 @@ NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p, bool trusted; struct netr_TrustInfo *trust_info; struct pdb_trusted_domain *td; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(p->dce_call, &auth_type, &auth_level); /* TODO: check server name */ @@ -2883,8 +2902,9 @@ NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p, &td->trust_auth_incoming, creds, r->out.new_owf_password, - r->out.old_owf_password); - + r->out.old_owf_password, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } -- 2.34.1 From 78bff5ce50845cc858218a5259141cf4ecf09192 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:25:11 +0100 Subject: [PATCH 58/69] s3:rpc_server/netlogon: make use of netlogon_creds_decrypt_samr_CryptPassword() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit a359b4139c8043ee3c3277b7559cb6d4f58f4044) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 5f189688d7bb..2ba16d423e3c 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1394,6 +1394,10 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, struct samr_CryptPassword password_buf; struct _samr_Credentials_t cr = { CRED_TYPE_PLAIN_TEXT, {0}}; bool ok; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); become_root(); status = dcesrv_netr_creds_server_step_check(p->dce_call, @@ -1422,15 +1426,10 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, memcpy(password_buf.data, r->in.new_password->data, 512); SIVAL(password_buf.data, 512, r->in.new_password->length); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - status = netlogon_creds_aes_decrypt(creds, - password_buf.data, - 516); - } else { - status = netlogon_creds_arcfour_crypt(creds, - password_buf.data, - 516); - } + status = netlogon_creds_decrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(creds); return status; -- 2.34.1 From 5c01b3203268e4753a789a29b860f84bfc49fa5a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:28:47 +0100 Subject: [PATCH 59/69] s4:rpc_server/netlogon: make use of netlogon_creds_{de,en}crypt_samr_Password() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 7a7cb0d0426a891185f5acf825573d98360e98e1) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 9090718be382..7d6034199d6d 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1020,6 +1020,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call const struct dom_sid *client_sid = NULL; struct ldb_context *sam_ctx; NTSTATUS nt_status; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); nt_status = dcesrv_netr_creds_server_step_check(dce_call, mem_ctx, @@ -1034,7 +1038,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call return NT_STATUS_INVALID_SYSTEM_SERVICE; } - nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password); + nt_status = netlogon_creds_decrypt_samr_Password(creds, + r->in.new_password, + auth_type, + auth_level); NT_STATUS_NOT_OK_RETURN(nt_status); /* Using the sid for the account as the key, set the password */ @@ -4560,6 +4567,10 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal NULL }; struct netr_TrustInfo *trust_info = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); ZERO_STRUCTP(r->out.new_owf_password); ZERO_STRUCTP(r->out.old_owf_password); @@ -4691,14 +4702,20 @@ static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_cal if (curNtHash != NULL) { *r->out.new_owf_password = *curNtHash; - nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password); + nt_status = netlogon_creds_encrypt_samr_Password(creds, + r->out.new_owf_password, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } } if (prevNtHash != NULL) { *r->out.old_owf_password = *prevNtHash; - nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password); + nt_status = netlogon_creds_encrypt_samr_Password(creds, + r->out.old_owf_password, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } -- 2.34.1 From 5838c8272b36548562a8582db2c626cd72bc9135 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:30:19 +0100 Subject: [PATCH 60/69] s4:rpc_server/netlogon: make use of netlogon_creds_decrypt_samr_CryptPassword This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit f1c1b8661a9121e1ff02784955c98d9f33bca8bd) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 7d6034199d6d..c3b134a92afd 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1073,6 +1073,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal DATA_BLOB dec_blob = data_blob_null; DATA_BLOB enc_blob = data_blob_null; struct samr_CryptPassword password_buf; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); nt_status = dcesrv_netr_creds_server_step_check(dce_call, mem_ctx, @@ -1090,16 +1094,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal memcpy(password_buf.data, r->in.new_password->data, 512); SIVAL(password_buf.data, 512, r->in.new_password->length); - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - nt_status = netlogon_creds_aes_decrypt(creds, - password_buf.data, - 516); - } else { - nt_status = netlogon_creds_arcfour_crypt(creds, - password_buf.data, - 516); - } - + nt_status = netlogon_creds_decrypt_samr_CryptPassword(creds, + &password_buf, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } -- 2.34.1 From a11760c6c73a437dbec7d68fc9af6a2e8ba79888 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:30:19 +0100 Subject: [PATCH 61/69] s4:rpc_server/netlogon: make use of netlogon_creds_decrypt_SendToSam This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 834197dafef0f3779ba69c8e350cbd7bb9333284) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index c3b134a92afd..01a5f9f6e9d3 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -3171,6 +3171,10 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal DATA_BLOB decrypted_blob; enum ndr_err_code ndr_err; struct netr_SendToSamBase base_msg = { 0 }; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); nt_status = dcesrv_netr_creds_server_step_check(dce_call, mem_ctx, @@ -3203,15 +3207,12 @@ static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_cal } /* Buffer is meant to be 16-bit aligned */ - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - nt_status = netlogon_creds_aes_decrypt(creds, - r->in.opaque_buffer, - r->in.buffer_len); - } else { - nt_status = netlogon_creds_arcfour_crypt(creds, - r->in.opaque_buffer, - r->in.buffer_len); - } + + nt_status = netlogon_creds_decrypt_SendToSam(creds, + r->in.opaque_buffer, + r->in.buffer_len, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } -- 2.34.1 From 9ea86ae7cbe2d55896e6a05ca1cd16af82255aa0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:54:48 +0100 Subject: [PATCH 62/69] libcli/auth: return INVALID_PARAMETER for DES in netlogon_creds_{de,en}crypt_samlogon_logon For the NetlogonGenericInformation case we want an error instead of no encryption if only DES was negotiated... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 131f5c0b251e456c466eaca744525504e1d69492) --- libcli/auth/credentials.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index ec5552e60c07..4fcd1ff96c5b 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -1114,6 +1114,7 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden } } else { /* Using DES to verify kerberos tickets makes no sense */ + return NT_STATUS_INVALID_PARAMETER; } break; } -- 2.34.1 From 8d0ef37efe48dd6b8f28d094e4dcc4b82d1c84c2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:44:52 +0100 Subject: [PATCH 63/69] libcli/auth: pass auth_{type,level} to schannel_check_creds_state() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 7b02fb50143ba5044605ec67ed41180391835dcb) --- libcli/auth/schannel_state.h | 2 ++ libcli/auth/schannel_state_tdb.c | 2 ++ librpc/rpc/server/netlogon/schannel_util.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/libcli/auth/schannel_state.h b/libcli/auth/schannel_state.h index a333098458f8..5b33ba0ab23e 100644 --- a/libcli/auth/schannel_state.h +++ b/libcli/auth/schannel_state.h @@ -37,6 +37,8 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, const char *computer_name, struct netr_Authenticator *received_authenticator, struct netr_Authenticator *return_authenticator, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, struct netlogon_creds_CredentialState **creds_out); NTSTATUS schannel_get_challenge(struct loadparm_context *lp_ctx, diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index 4154997fc025..717d41b05d7b 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -569,6 +569,8 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, const char *computer_name, struct netr_Authenticator *received_authenticator, struct netr_Authenticator *return_authenticator, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, struct netlogon_creds_CredentialState **creds_out) { TALLOC_CTX *tmpctx; diff --git a/librpc/rpc/server/netlogon/schannel_util.c b/librpc/rpc/server/netlogon/schannel_util.c index b98b4706aac1..359f4b8ed081 100644 --- a/librpc/rpc/server/netlogon/schannel_util.c +++ b/librpc/rpc/server/netlogon/schannel_util.c @@ -548,6 +548,8 @@ NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, computer_name, received_authenticator, return_authenticator, + auth_type, + auth_level, &creds); if (!NT_STATUS_IS_OK(nt_status)) { ZERO_STRUCTP(return_authenticator); -- 2.34.1 From 5eab692e7931286105d422387eb411264c52f985 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:46:07 +0100 Subject: [PATCH 64/69] libcli/auth: pass auth_{type,level} to netlogon_creds_server_step_check() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 2956c7eb3c9fc2161fd2748e5aac1fc94478e8c7) --- libcli/auth/credentials.c | 4 +++- libcli/auth/proto.h | 4 +++- libcli/auth/schannel_state_tdb.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 4fcd1ff96c5b..2c46c5a582c0 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -798,7 +798,9 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, const struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator) + struct netr_Authenticator *return_authenticator, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { NTSTATUS status; diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 53a7d2062dbd..75eb41abed1f 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -71,7 +71,9 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me uint32_t negotiate_flags); NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, const struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator) ; + struct netr_Authenticator *return_authenticator, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); NTSTATUS netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, union netr_Validation *validation, diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index 717d41b05d7b..b823ab6471d7 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -630,7 +630,9 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, status = netlogon_creds_server_step_check(creds, received_authenticator, - return_authenticator); + return_authenticator, + auth_type, + auth_level); if (!NT_STATUS_IS_OK(status)) { goto done; } -- 2.34.1 From 71c47b7255bd5e13d6346c3d1edcba306e86948c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:54:42 +0100 Subject: [PATCH 65/69] libcli/auth: split out netlogon_creds_client_verify() that takes auth_{type,level} This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 45faf6c35a033ec46a546dfb9d5d6aeb2fb2b83c) --- libcli/auth/credentials.c | 24 ++++++++++++++++++++++-- libcli/auth/proto.h | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 2c46c5a582c0..2d2da080efe3 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -657,14 +657,34 @@ netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds /* check that a credentials reply from a server is correct */ -bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds, - const struct netr_Credential *received_credentials) +NTSTATUS netlogon_creds_client_verify(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *received_credentials, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level) { if (!received_credentials || !mem_equal_const_time(received_credentials->data, creds->server.data, 8)) { DEBUG(2,("credentials check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + return NT_STATUS_OK; +} + +bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *received_credentials) +{ + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + NTSTATUS status; + + status = netlogon_creds_client_verify(creds, + received_credentials, + auth_type, + auth_level); + if (!NT_STATUS_IS_OK(status)) { return false; } + return true; } diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 75eb41abed1f..4c0c4243217c 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -47,6 +47,10 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me NTSTATUS netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, struct netr_Authenticator *next); +NTSTATUS netlogon_creds_client_verify(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *received_credentials, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level); bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds, const struct netr_Credential *received_credentials); struct netlogon_creds_CredentialState *netlogon_creds_copy( -- 2.34.1 From d739a9476dbbfa5f23f1ce697ac5c5460bc8b79f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 10:02:40 +0100 Subject: [PATCH 66/69] libcli/auth: make use of netlogon_creds_client_verify() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 1a5984ac6312b204b51590057b8327cf4698383b) --- libcli/auth/netlogon_creds_cli.c | 124 +++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index fd9e71ad8c67..eabd2183f8c3 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1220,6 +1220,8 @@ struct netlogon_creds_cli_auth_state { struct tevent_context *ev; struct netlogon_creds_cli_context *context; struct dcerpc_binding_handle *binding_handle; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; uint8_t num_nt_hashes; uint8_t idx_nt_hashes; const struct samr_Password * const *nt_hashes; @@ -1284,6 +1286,10 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + dcerpc_binding_handle_auth_info(state->binding_handle, + &state->auth_type, + &state->auth_level); + state->try_auth3 = true; state->try_auth2 = true; @@ -1458,7 +1464,6 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) struct netlogon_creds_cli_auth_state); NTSTATUS status; NTSTATUS result; - bool ok; bool downgraded; if (state->try_auth3) { @@ -1552,10 +1557,11 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) return; } - ok = netlogon_creds_client_check(state->creds, - &state->server_credential); - if (!ok) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + status = netlogon_creds_client_verify(state->creds, + &state->server_credential, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { return; } @@ -1640,6 +1646,8 @@ struct netlogon_creds_cli_check_state { struct tevent_context *ev; struct netlogon_creds_cli_context *context; struct dcerpc_binding_handle *binding_handle; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; char *srv_name_slash; @@ -1666,8 +1674,6 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct netlogon_creds_cli_check_state *state; struct tevent_req *subreq; - enum dcerpc_AuthType auth_type; - enum dcerpc_AuthLevel auth_level; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, @@ -1698,14 +1704,15 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, } dcerpc_binding_handle_auth_info(state->binding_handle, - &auth_type, &auth_level); + &state->auth_type, + &state->auth_level); - if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { + if (state->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); } - switch (auth_level) { + switch (state->auth_level) { case DCERPC_AUTH_LEVEL_INTEGRITY: case DCERPC_AUTH_LEVEL_PRIVACY: break; @@ -1782,7 +1789,6 @@ static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req *subreq) struct netlogon_creds_cli_check_state); NTSTATUS status; NTSTATUS result; - bool ok; status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state, &result); @@ -1874,10 +1880,11 @@ static void netlogon_creds_cli_check_negotiate_caps(struct tevent_req *subreq) return; } - ok = netlogon_creds_client_check(state->creds, &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(state->creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_check_cleanup(req, status); return; } @@ -1956,7 +1963,6 @@ static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq) uint32_t requested_flags; NTSTATUS status; NTSTATUS result; - bool ok; status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state, &result); @@ -1992,11 +1998,11 @@ static void netlogon_creds_cli_check_client_caps(struct tevent_req *subreq) return; } - ok = netlogon_creds_client_check(state->creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(state->creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_check_cleanup(req, status); return; } @@ -2415,7 +2421,6 @@ static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq) struct netlogon_creds_cli_ServerPasswordSet_state); NTSTATUS status; NTSTATUS result; - bool ok; if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state, @@ -2435,11 +2440,11 @@ static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq) } } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); return; } @@ -2971,11 +2976,11 @@ static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) } } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + auth_type, + auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_LogonSamLogon_cleanup(req, status); return; } @@ -3263,7 +3268,6 @@ static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tev struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state); NTSTATUS status; NTSTATUS result; - bool ok; /* * We use state->dns_names as the memory context, as this is @@ -3280,11 +3284,11 @@ static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tev return; } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status); return; } @@ -3520,7 +3524,6 @@ static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq struct netlogon_creds_cli_ServerGetTrustInfo_state); NTSTATUS status; NTSTATUS result; - bool ok; /* * We use state->dns_names as the memory context, as this is @@ -3536,11 +3539,11 @@ static void netlogon_creds_cli_ServerGetTrustInfo_done(struct tevent_req *subreq return; } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_ServerGetTrustInfo_cleanup(req, status); return; } @@ -3824,7 +3827,6 @@ static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req struct netlogon_creds_cli_GetForestTrustInformation_state); NTSTATUS status; NTSTATUS result; - bool ok; /* * We use state->dns_names as the memory context, as this is @@ -3840,11 +3842,11 @@ static void netlogon_creds_cli_GetForestTrustInformation_done(struct tevent_req return; } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_GetForestTrustInformation_cleanup(req, status); return; } @@ -4114,7 +4116,6 @@ static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq) struct netlogon_creds_cli_SendToSam_state); NTSTATUS status; NTSTATUS result; - bool ok; status = dcerpc_netr_NetrLogonSendToSam_recv(subreq, state, &result); TALLOC_FREE(subreq); @@ -4123,11 +4124,11 @@ static void netlogon_creds_cli_SendToSam_done(struct tevent_req *subreq) return; } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_SendToSam_cleanup(req, status); return; } @@ -4382,7 +4383,6 @@ static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req *subreq struct netlogon_creds_cli_LogonGetDomainInfo_state); NTSTATUS status; NTSTATUS result; - bool ok; /* * We use state->dns_names as the memory context, as this is @@ -4398,11 +4398,11 @@ static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req *subreq return; } - ok = netlogon_creds_client_check(&state->tmp_creds, - &state->rep_auth.cred); - if (!ok) { - status = NT_STATUS_ACCESS_DENIED; - tevent_req_nterror(req, status); + status = netlogon_creds_client_verify(&state->tmp_creds, + &state->rep_auth.cred, + state->auth_type, + state->auth_level); + if (tevent_req_nterror(req, status)) { netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status); return; } -- 2.34.1 From 665526268ef55d7ba32c06b439b3473547c08f4e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 10:31:52 +0100 Subject: [PATCH 67/69] s4:librpc/rpc: make use of netlogon_creds_client_verify() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 132629ee3a9b73d0888d1110e4d0a45ded778e5a) --- source4/librpc/rpc/dcerpc_schannel.c | 46 +++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index ca0495c4d472..8622791fe302 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -222,10 +222,17 @@ static void continue_srv_auth2(struct tevent_req *subreq) { struct composite_context *c; struct schannel_key_state *s; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; c = tevent_req_callback_data(subreq, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); + dcerpc_binding_handle_auth_info(s->pipe2->binding_handle, + &auth_type, + &auth_level); + /* receive rpc request result - auth2 credentials */ c->status = dcerpc_netr_ServerAuthenticate2_r_recv(subreq, s); TALLOC_FREE(subreq); @@ -328,8 +335,12 @@ static void continue_srv_auth2(struct tevent_req *subreq) } /* verify credentials */ - if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) { - composite_error(c, NT_STATUS_UNSUCCESSFUL); + status = netlogon_creds_client_verify(s->creds, + s->a.out.return_credentials, + auth_type, + auth_level); + if (!NT_STATUS_IS_OK(status)) { + composite_error(c, status); return; } @@ -602,11 +613,17 @@ static void continue_get_negotiated_capabilities(struct tevent_req *subreq) { struct composite_context *c; struct auth_schannel_state *s; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; NTSTATUS status; c = tevent_req_callback_data(subreq, struct composite_context); s = talloc_get_type(c->private_data, struct auth_schannel_state); + dcerpc_binding_handle_auth_info(s->pipe->binding_handle, + &auth_type, + &auth_level); + /* receive rpc request result */ c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s); TALLOC_FREE(subreq); @@ -642,9 +659,12 @@ static void continue_get_negotiated_capabilities(struct tevent_req *subreq) } /* verify credentials */ - if (!netlogon_creds_client_check(&s->save_creds_state, - &s->c.out.return_authenticator->cred)) { - composite_error(c, NT_STATUS_UNSUCCESSFUL); + status = netlogon_creds_client_verify(&s->save_creds_state, + &s->c.out.return_authenticator->cred, + auth_type, + auth_level); + if (!NT_STATUS_IS_OK(status)) { + composite_error(c, status); return; } @@ -705,10 +725,17 @@ static void continue_get_client_capabilities(struct tevent_req *subreq) { struct composite_context *c; struct auth_schannel_state *s; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + NTSTATUS status; c = tevent_req_callback_data(subreq, struct composite_context); s = talloc_get_type(c->private_data, struct auth_schannel_state); + dcerpc_binding_handle_auth_info(s->pipe->binding_handle, + &auth_type, + &auth_level); + /* receive rpc request result */ c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s); TALLOC_FREE(subreq); @@ -743,9 +770,12 @@ static void continue_get_client_capabilities(struct tevent_req *subreq) } /* verify credentials */ - if (!netlogon_creds_client_check(&s->save_creds_state, - &s->c.out.return_authenticator->cred)) { - composite_error(c, NT_STATUS_UNSUCCESSFUL); + status = netlogon_creds_client_verify(&s->save_creds_state, + &s->c.out.return_authenticator->cred, + auth_type, + auth_level); + if (!NT_STATUS_IS_OK(status)) { + composite_error(c, status); return; } -- 2.34.1 From 4ade7fd5e8af4543758ed9c4929ad89aa09fe05f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 21:02:23 +0200 Subject: [PATCH 68/69] libcli/auth: let netlogon_creds_copy() copy all scalar elements This version is good for now, as we want it to be backportable. For master we'll add a ndr_deepcopy_struct() helper in order to avoid future problems. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 8edbdd65ef78e3f26357d0254b58db3120a32880) --- libcli/auth/credentials.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 2d2da080efe3..12f4b1fbb8ce 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -1407,9 +1407,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_copy( return NULL; } - creds->sequence = creds_in->sequence; - creds->negotiate_flags = creds_in->negotiate_flags; - creds->secure_channel_type = creds_in->secure_channel_type; + *creds = *creds_in; creds->computer_name = talloc_strdup(creds, creds_in->computer_name); if (!creds->computer_name) { @@ -1432,10 +1430,5 @@ struct netlogon_creds_CredentialState *netlogon_creds_copy( *creds->ex = *creds_in->ex; } - memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key)); - memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data)); - memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data)); - memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data)); - return creds; } -- 2.34.1 From dca2a5234b119bf1bc54c26da29e57b2ede66166 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 13:42:06 +0100 Subject: [PATCH 69/69] libcli/auth: split out netlogon_creds_cli_check_transport() This will make it easier to implement netr_ServerAuthenticateKerberos() later... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall (cherry picked from commit 7a5ad9f64a905f5744430c6e0796c646baf9432e) --- libcli/auth/netlogon_creds_cli.c | 138 +++++++++++++++---------------- 1 file changed, 65 insertions(+), 73 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index eabd2183f8c3..19c4a104937f 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1216,6 +1216,49 @@ NTSTATUS netlogon_creds_cli_lck( return status; } +static NTSTATUS netlogon_creds_cli_check_transport( + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthLevel min_auth_level) +{ + if (auth_level < min_auth_level) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + if (creds == NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + switch (auth_level) { + case DCERPC_AUTH_LEVEL_INTEGRITY: + case DCERPC_AUTH_LEVEL_PRIVACY: + return NT_STATUS_OK; + default: + break; + } + + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + if (creds->negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) { + /* + * if DCERPC_AUTH_TYPE_SCHANNEL is supported + * it should be used, which means + * we had a chance to verify no downgrade + * happened. + * + * This relies on netlogon_creds_cli_check* + * being called before, as first request after + * the DCERPC bind. + */ + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + return NT_STATUS_OK; +} + struct netlogon_creds_cli_auth_state { struct tevent_context *ev; struct netlogon_creds_cli_context *context; @@ -1707,17 +1750,11 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, &state->auth_type, &state->auth_level); - if (state->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return tevent_req_post(req, ev); - } - - switch (state->auth_level) { - case DCERPC_AUTH_LEVEL_INTEGRITY: - case DCERPC_AUTH_LEVEL_PRIVACY: - break; - default: - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + status = netlogon_creds_cli_check_transport(state->auth_type, + state->auth_level, + state->creds, + DCERPC_AUTH_LEVEL_INTEGRITY); + if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); } @@ -2305,32 +2342,12 @@ static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subre return; } - if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - switch (state->auth_level) { - case DCERPC_AUTH_LEVEL_INTEGRITY: - case DCERPC_AUTH_LEVEL_PRIVACY: - break; - default: - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return; - } - } else { - uint32_t tmp = state->creds->negotiate_flags; - - if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) { - /* - * if DCERPC_AUTH_TYPE_SCHANNEL is supported - * it should be used, which means - * we had a chance to verify no downgrade - * happened. - * - * This relies on netlogon_creds_cli_check* - * being called before, as first request after - * the DCERPC bind. - */ - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return; - } + status = netlogon_creds_cli_check_transport(state->auth_type, + state->auth_level, + state->creds, + DCERPC_AUTH_LEVEL_NONE); + if (tevent_req_nterror(req, status)) { + return; } state->old_timeout = dcerpc_binding_handle_set_timeout( @@ -3196,32 +3213,12 @@ static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct t return; } - if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - switch (state->auth_level) { - case DCERPC_AUTH_LEVEL_INTEGRITY: - case DCERPC_AUTH_LEVEL_PRIVACY: - break; - default: - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return; - } - } else { - uint32_t tmp = state->creds->negotiate_flags; - - if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) { - /* - * if DCERPC_AUTH_TYPE_SCHANNEL is supported - * it should be used, which means - * we had a chance to verify no downgrade - * happened. - * - * This relies on netlogon_creds_cli_check* - * being called before, as first request after - * the DCERPC bind. - */ - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return; - } + status = netlogon_creds_cli_check_transport(state->auth_type, + state->auth_level, + state->creds, + DCERPC_AUTH_LEVEL_NONE); + if (tevent_req_nterror(req, status)) { + return; } /* @@ -3465,16 +3462,11 @@ static void netlogon_creds_cli_ServerGetTrustInfo_locked(struct tevent_req *subr return; } - if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - switch (state->auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - break; - default: - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); - return; - } - } else { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + status = netlogon_creds_cli_check_transport(state->auth_type, + state->auth_level, + state->creds, + DCERPC_AUTH_LEVEL_PRIVACY); + if (tevent_req_nterror(req, status)) { return; } -- 2.34.1