From 09898e58480aa73fa5dc70be507cad8d00df650f Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Tue, 20 Feb 2024 16:46:07 +1300 Subject: [PATCH 01/71] s4:rpc_server: Make some arrays static Signed-off-by: Jo Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit beaeeaff501b22fdfb3928d788597398fcbbbe29) Backported for https://bugzilla.samba.org/show_bug.cgi?id=15425 --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 2c7fecca1a07..457af26fb5c2 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -410,8 +410,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( int num_records; struct ldb_message **msgs; NTSTATUS nt_status; - const char *attrs[] = {"unicodePwd", "userAccountControl", - "objectSid", "samAccountName", NULL}; + static const char *attrs[] = {"unicodePwd", + "userAccountControl", + "objectSid", + "samAccountName", + NULL}; uint32_t server_flags = 0; uint32_t negotiate_flags = 0; @@ -536,12 +539,10 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) { struct ldb_message *tdo_msg = NULL; - const char * const tdo_attrs[] = { - "trustAuthIncoming", - "trustAttributes", - "flatName", - NULL - }; + static const char *const tdo_attrs[] = {"trustAuthIncoming", + "trustAttributes", + "flatName", + NULL}; char *encoded_name = NULL; size_t len; const char *flatname = NULL; @@ -2618,17 +2619,17 @@ 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 char * const trusts_attrs[] = { - "securityIdentifier", - "flatName", - "trustPartner", - "trustAttributes", - "trustDirection", - "trustType", - NULL - }; - const char * const attrs2[] = { "sAMAccountName", "dNSHostName", - "msDS-SupportedEncryptionTypes", NULL }; + static const char *const trusts_attrs[] = {"securityIdentifier", + "flatName", + "trustPartner", + "trustAttributes", + "trustDirection", + "trustType", + NULL}; + static const char *const attrs2[] = {"sAMAccountName", + "dNSHostName", + "msDS-SupportedEncryptionTypes", + NULL}; const char *sam_account_name, *old_dns_hostname; struct ldb_context *sam_ctx; const struct GUID *our_domain_guid = NULL; @@ -2994,11 +2995,15 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, struct dom_sid *user_sid, struct ldb_dn *obj_dn) { - const char *rodc_attrs[] = { "msDS-NeverRevealGroup", - "msDS-RevealOnDemandGroup", - "userAccountControl", - NULL }; - const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; + static const char *rodc_attrs[] = {"msDS-NeverRevealGroup", + "msDS-RevealOnDemandGroup", + "userAccountControl", + NULL}; + static const char *obj_attrs[] = {"tokenGroups", + "objectSid", + "UserAccountControl", + "msDS-KrbTgtLinkBL", + NULL}; struct ldb_dn *rodc_dn; int ret; struct ldb_result *rodc_res = NULL, *obj_res = NULL; @@ -3938,9 +3943,13 @@ static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx, { struct ldb_dn *system_dn; struct ldb_message **dom_res = NULL; - const char *trust_attrs[] = { "flatname", "trustPartner", - "securityIdentifier", "trustDirection", - "trustType", "trustAttributes", NULL }; + static const char *trust_attrs[] = {"flatname", + "trustPartner", + "securityIdentifier", + "trustDirection", + "trustType", + "trustAttributes", + NULL}; uint32_t n; int i; int ret; -- 2.34.1 From 6c458a68b6a9f0f083d61937d8d446fccc98f9c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 15:08:01 +0200 Subject: [PATCH 02/71] 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 ed0746a4110b5cb558aa916cda2b3fe0a1a87482 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 15:02:16 +0200 Subject: [PATCH 03/71] 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 ce49b17d36f99474fa1136bc5e9cf66a6b49ec50 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 12:55:33 +0200 Subject: [PATCH 04/71] 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 fa3e597fa8e4..0fb0371c79bd 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -886,6 +886,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; @@ -902,7 +903,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 | @@ -912,20 +912,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. @@ -947,6 +937,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"; @@ -961,6 +953,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 */ @@ -1000,7 +1005,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", @@ -1032,7 +1037,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 c24647a9acf5a2fbfe7743e2164f177e84b87b8b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:34:33 +0200 Subject: [PATCH 05/71] 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 0fb0371c79bd..47c08bcd516e 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -917,6 +917,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. * @@ -930,13 +942,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 fda3ed85b043e2e7b62f8fcbf541568c1d19790d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:34:33 +0200 Subject: [PATCH 06/71] 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 457af26fb5c2..6a1740dc83ed 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -497,12 +497,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 f4c7153b043786725d6c31c8dde458e9e6b111f0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 09:27:48 +0200 Subject: [PATCH 07/71] 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 7834f9af660f421bddac1da4e485374a7309425c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 08/71] 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 4b4e43036684aadcedb4aa1b82e94a0dc603d7db Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 17:43:00 +0200 Subject: [PATCH 09/71] 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 1501b24e9c99c3bb05dd5b3c56777bd2cdc29289 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 15:03:21 +0200 Subject: [PATCH 10/71] 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 b1dbd0e04feb598bd98b89e5dc6e476bbdf3a4ee Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 12:31:18 +0200 Subject: [PATCH 11/71] 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 f7d4407401f92702232e6ea9c21160e5f0d91ca8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 14:25:19 +0200 Subject: [PATCH 12/71] 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 1962ef5fb8f141462be10f15342b21ea479d6851 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 13:43:36 +0200 Subject: [PATCH 13/71] 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 18485610f51db4b1a808fb24ced4510a88395473 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:15:46 +0200 Subject: [PATCH 14/71] 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 424ae005849339fbe6a1ec5a8bf46d5b4bb3cfb2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:44:26 +0200 Subject: [PATCH 15/71] 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 df39ea9091f7c40e06a5834b8e3e977374c2a759 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:38:53 +0200 Subject: [PATCH 16/71] 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 41943259272a69b477310411898d00261a5b2ad7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 16:38:53 +0200 Subject: [PATCH 17/71] 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 53260fc084d66774204d5ecbea9a4cec4c2e30bf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 20 Jul 2023 13:29:12 +0200 Subject: [PATCH 18/71] 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 c3715619cb77..beac67c4c5bf 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 d6dca3666702..42b6f5d52644 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" @@ -591,6 +592,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), @@ -630,8 +632,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 */ @@ -719,8 +739,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 6b2b620c03c8f9fb7f7baeb4f013c389d6bdbee5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Oct 2024 12:10:49 +0100 Subject: [PATCH 19/71] 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 778f3b9652848437b76dbf4220dd9e71291b96e0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:04:27 +0200 Subject: [PATCH 20/71] 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 b4982aee9ed4..2b2a0ae78268 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 5f8d3273754fdd93e59aab2bed66d6c573362ec2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:06:44 +0200 Subject: [PATCH 21/71] 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 47c08bcd516e..53c100c7a6c5 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1311,6 +1311,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__)); @@ -1335,6 +1336,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)); @@ -1353,7 +1355,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; } @@ -1370,6 +1372,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; @@ -1395,6 +1398,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", @@ -1515,7 +1519,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 ab74a0ac89edf00165acf54f97c40b735d77a8a1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:06:44 +0200 Subject: [PATCH 22/71] 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 6a1740dc83ed..1fc7c4d15882 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -927,6 +927,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; @@ -936,6 +937,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) { @@ -947,7 +949,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, @@ -964,6 +966,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; @@ -980,6 +983,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) { @@ -1088,7 +1092,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, @@ -2624,6 +2628,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", @@ -2672,6 +2677,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); @@ -2688,7 +2694,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. */ @@ -2997,7 +3003,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", @@ -3052,6 +3058,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; @@ -3066,6 +3073,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: @@ -3137,7 +3145,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))); @@ -4422,6 +4430,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; const char * const attrs[] = { "unicodePwd", @@ -4456,6 +4465,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 */ @@ -4476,7 +4486,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; } @@ -4631,6 +4641,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, @@ -4639,6 +4650,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; @@ -4652,7 +4664,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 b82535fd70cc74442b7dae676d9381a5a0336dc5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:46:43 +0200 Subject: [PATCH 23/71] 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 53c100c7a6c5..467d337f5529 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1010,6 +1010,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 " @@ -1020,12 +1021,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 1fc7c4d15882..4d3e2c106cd8 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -768,6 +768,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, @@ -777,6 +782,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( curNtHash, r->in.credentials, r->out.return_credentials, + *sid, negotiate_flags); if (creds == NULL && prevNtHash != NULL) { /* @@ -794,14 +800,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 5bb813e653d32001c39dfae9beb6cd5584ffd3c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 18:54:05 +0200 Subject: [PATCH 24/71] 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 846e4b6417668070d35037e5b8006c0a3fb2d4f8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:00:45 +0200 Subject: [PATCH 25/71] 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 843322dd5b4de767b66ccb708005a619d40e9e32 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:01:39 +0200 Subject: [PATCH 26/71] 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 467d337f5529..bce18636b523 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1331,7 +1331,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)); @@ -1393,7 +1393,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 d1091d4b414149caebab56b6d6e864e1190dc556 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:01:39 +0200 Subject: [PATCH 27/71] 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 4d3e2c106cd8..439383cafc68 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -942,7 +942,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) { @@ -988,7 +988,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) { @@ -1339,7 +1339,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: @@ -2682,7 +2682,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); @@ -3078,7 +3078,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: @@ -4470,7 +4470,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 */ @@ -4655,7 +4655,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 95e7b43a14336df67d3ca0e1b141f729e748cafa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:04:02 +0200 Subject: [PATCH 28/71] 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 6c8995e8262e3fc715d4c6f1231cc6129465601a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 29/71] 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 bce18636b523..384191f76e49 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1010,6 +1010,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 439383cafc68..4fb2a7774049 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -416,6 +416,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( "samAccountName", NULL}; uint32_t server_flags = 0; + uint32_t client_flags = 0; uint32_t negotiate_flags = 0; ZERO_STRUCTP(r->out.return_credentials); @@ -509,7 +510,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: @@ -782,6 +784,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) { @@ -800,6 +803,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( prevNtHash, r->in.credentials, r->out.return_credentials, + client_flags, *sid, negotiate_flags); } -- 2.34.1 From f548f7fd0b3059bf68a4c542a8a47f8db8ec506f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 18:03:09 +0200 Subject: [PATCH 30/71] 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 384191f76e49..fb5894ffefb2 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -2307,12 +2307,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 @@ -2340,7 +2335,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 49111244af2585fa1d71d0878e2607e6e2673c23 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 18:00:31 +0200 Subject: [PATCH 31/71] 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 4fb2a7774049..1e23c4450cd6 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2400,12 +2400,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 @@ -2431,7 +2426,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 b6bbc5b186063f8cdb76fab99b7f4110b9c38ef4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:27:30 +0100 Subject: [PATCH 32/71] 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 beac67c4c5bf..6b74de03db2d 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 e55a5c4c65c52ad492ce6d451fa5bba72f8c3130 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Oct 2024 19:06:59 +0200 Subject: [PATCH 33/71] 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 c2190e55da37..25dde5485e1c 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -3064,6 +3064,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"); @@ -3089,6 +3090,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 6b74de03db2d..2ce0acb160a8 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 52aa793d2b4c698caa7ba33865526ad92017de63 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 13:24:37 +0200 Subject: [PATCH 34/71] 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 5af4c0d4a068ddd065c3c5e71afe7851b66440d2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Oct 2024 13:39:38 +0200 Subject: [PATCH 35/71] 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 686152a2cc80ab21f40f985351f7b3e0f1f1aacd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:47:22 +0200 Subject: [PATCH 36/71] 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 b52d9a94c01c920e90aeeeb631796f65d762f4bf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:49:26 +0200 Subject: [PATCH 37/71] 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 5003e7499b01..34a836a6a6f2 100644 --- a/source4/dsdb/common/util_trusts.c +++ b/source4/dsdb/common/util_trusts.c @@ -2646,7 +2646,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 1385bec638e44427fec585338e8e8e69f24ad404 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Oct 2024 17:55:41 +0200 Subject: [PATCH 38/71] 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 1e23c4450cd6..a2c4dbd5292a 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -387,14 +387,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) @@ -404,11 +413,10 @@ 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; int num_records; struct ldb_message **msgs; + struct ldb_message *tdo_msg = NULL; NTSTATUS nt_status; static const char *attrs[] = {"unicodePwd", "userAccountControl", @@ -545,7 +553,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", @@ -614,22 +621,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( @@ -750,28 +741,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; } @@ -779,13 +834,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) { /* @@ -798,32 +853,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 68cb6c0403fa40d061444ee659e53bef0641a254 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 10 Sep 2024 13:56:38 +0200 Subject: [PATCH 39/71] 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 2bc194008990..24750872b3f5 100644 --- a/librpc/rpc/dcesrv_core.h +++ b/librpc/rpc/dcesrv_core.h @@ -578,6 +578,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 8566b4af198f7115a3eb840c0afaeb656b5b96a4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 10 Sep 2024 13:56:38 +0200 Subject: [PATCH 40/71] 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 e28cc5eb944713d613faee9a4c3aa18e5551c1c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Apr 2024 15:14:47 +0200 Subject: [PATCH 41/71] 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 fb5894ffefb2..4900742c6bf7 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -2906,6 +2906,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 a2c4dbd5292a..be7c56656557 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -4776,6 +4776,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 29a28391470b84ad14664e811a77e51bdcb346cc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:43:44 +0100 Subject: [PATCH 42/71] 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 4900742c6bf7..843b2c4dfbe4 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1938,7 +1938,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 be7c56656557..70e41699b9b7 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1673,9 +1673,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 34c47883add2b7543d52a8c113aee9905228d5df Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:55:12 +0100 Subject: [PATCH 43/71] 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 843b2c4dfbe4..8dce49946171 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1755,7 +1755,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 70e41699b9b7..050e6e4bcdde 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1377,7 +1377,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 883c3aa5d4ada3773f5efa9503d3dda6370e4395 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:03:37 +0100 Subject: [PATCH 44/71] 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 8820b06e6ed30175f0e3fd117135e6bf1cd95514 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:12:24 +0100 Subject: [PATCH 45/71] 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 17be921304a1fc7762faf49430656c1e27ed752a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 13:13:50 +0100 Subject: [PATCH 46/71] 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 740c089897004ae564f996fadb95aa1fb12af47d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 14:06:28 +0100 Subject: [PATCH 47/71] 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 a27e02d1aa53..cdba997b7d66 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1024,9 +1024,11 @@ static PyObject *py_creds_get_aes256_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; @@ -1045,9 +1047,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 ebb8c153564d652d11809aa290ef876519bb82b6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:22:47 +0100 Subject: [PATCH 48/71] 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 cdba997b7d66..35869b47478a 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1107,6 +1107,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; @@ -1622,6 +1684,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 a21def96a5a27431ea88dfdeddc084e60d8ab40f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:39:57 +0100 Subject: [PATCH 49/71] 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 d983c631a468..5efdb2e9eb60 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -51,6 +51,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, @@ -3685,10 +3686,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() @@ -3698,11 +3701,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 5d3929cb334a954ba06a3332d8fd47b936ab5c99 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:52:13 +0100 Subject: [PATCH 50/71] 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 a95762dda59fdb2371a0dfb956c8f51bbc929521 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 15:56:09 +0100 Subject: [PATCH 51/71] 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 788ca924814174e557631789441abe253e985cdf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:00:52 +0100 Subject: [PATCH 52/71] 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 85489916f793f744475f0b2087734bc128d55dc7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:19:09 +0100 Subject: [PATCH 53/71] 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 f4a36305cac59a55348e66a4380666b4619c7dce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 12:58:11 +0100 Subject: [PATCH 54/71] 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 22e0606de96e..ce57cdc055e6 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 138814ee52521875931649f58d8d1dff942a8a44 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:57:53 +0100 Subject: [PATCH 55/71] 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 42b6f5d52644..cbd9e7ecac8d 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])); @@ -277,6 +277,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; @@ -342,7 +343,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; @@ -413,13 +414,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 13f995177f05d727d3acd7137a7e6288e01b52e2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:22:36 +0100 Subject: [PATCH 56/71] 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 25dde5485e1c..c4439bfcb934 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -4483,6 +4483,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"); @@ -4638,15 +4640,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 2ce0acb160a8..c31f24eed169 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 8a1fd34399e149150f627879e239e5443fcaa82c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:43:40 +0100 Subject: [PATCH 57/71] 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 e7b641e161a8..4a46382f32a1 100644 --- a/source4/torture/rpc/forest_trust.c +++ b/source4/torture/rpc/forest_trust.c @@ -533,6 +533,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"); @@ -608,8 +610,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 c31f24eed169..c5a7929d7038 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", @@ -5038,6 +5054,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)) { @@ -5069,7 +5088,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 cbd9e7ecac8d..371a78716441 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -1286,6 +1286,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, @@ -1310,7 +1312,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 b619c5a0f876bd8f7d235d2b0ba1354e4203fc34 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 17:12:16 +0100 Subject: [PATCH 58/71] 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 8dce49946171..da1bdce2d0b1 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1308,6 +1308,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__)); @@ -1337,7 +1341,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; } @@ -2741,7 +2748,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; @@ -2758,7 +2767,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; } @@ -2772,7 +2784,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; } @@ -2797,6 +2812,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 */ @@ -2873,8 +2892,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 d371c051035b6299ee69dd3f6aad78ea7f8fce96 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:25:11 +0100 Subject: [PATCH 59/71] 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 da1bdce2d0b1..0147602bc47e 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1384,6 +1384,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, @@ -1412,15 +1416,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 3390490bd154c9151d505a5a8ef774536d1455c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:28:47 +0100 Subject: [PATCH 60/71] 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 050e6e4bcdde..fa859e1125ef 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1010,6 +1010,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, @@ -1024,7 +1028,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 */ @@ -4544,6 +4551,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); @@ -4661,14 +4672,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 207f33e00ed740ddea4ee8aee1c079d017d64c50 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:30:19 +0100 Subject: [PATCH 61/71] 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 fa859e1125ef..2597ee90eab9 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1063,6 +1063,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, @@ -1080,16 +1084,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 a02965006314a80f5249d38ff079e75e0e08c2ad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:30:19 +0100 Subject: [PATCH 62/71] 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 2597ee90eab9..8f1eb7abb6dd 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -3161,6 +3161,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, @@ -3193,15 +3197,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 c4669c81b6ce0083cf712d40ff3bbde4f3ab2059 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Oct 2024 16:54:48 +0100 Subject: [PATCH 63/71] 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 9ce0680e00b2b9b08432647531df69d0deab7b35 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:44:52 +0100 Subject: [PATCH 64/71] 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 1e746591aa1a3948867b98067fc38c544b233a11 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:46:07 +0100 Subject: [PATCH 65/71] 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 3473804bf3f7e8a986f9b793cf3e5996f0b97e39 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 09:54:42 +0100 Subject: [PATCH 66/71] 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 3d483429adc7b0a3972604c33e26a566e2ae3af5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 10:02:40 +0100 Subject: [PATCH 67/71] 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 101b9e9611f8b26302b4170e1215c7321b335750 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 10:31:52 +0100 Subject: [PATCH 68/71] 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 32f3a13163d3c79cb6bd7fa6a2b319aeba025dc5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 19 Jul 2023 21:02:23 +0200 Subject: [PATCH 69/71] 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 b2121d59235fa195d13d5e2b7e046bcea37f881b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Oct 2024 13:42:06 +0100 Subject: [PATCH 70/71] 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 From abcdafa10466efe0b48738f8a7360989a5787cfe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 6 Nov 2024 17:18:58 +0100 Subject: [PATCH 71/71] libcli/auth: make use of netlogon_creds_cli_check_transport() in more places This was somehow missing in commit 7a5ad9f64a905f5744430c6e0796c646baf9432e BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Nov 7 09:14:33 UTC 2024 on atb-devel-224 (cherry picked from commit f340dce6546a22d857cad440f8afaee9815dbdb1) --- libcli/auth/netlogon_creds_cli.c | 96 ++++++-------------------------- 1 file changed, 18 insertions(+), 78 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 19c4a104937f..c452623d12e1 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -3748,32 +3748,12 @@ static void netlogon_creds_cli_GetForestTrustInformation_locked(struct tevent_re 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; } /* @@ -4027,32 +4007,12 @@ static void netlogon_creds_cli_SendToSam_locked(struct tevent_req *subreq) 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; } /* @@ -4303,32 +4263,12 @@ static void netlogon_creds_cli_LogonGetDomainInfo_locked(struct tevent_req *subr 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; } /* -- 2.34.1