]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2022-38023 s4:rpc_server/netlogon: split out dcesrv_netr_ServerAuthenticate3_chec...
authorStefan Metzmacher <metze@samba.org>
Fri, 25 Nov 2022 08:54:17 +0000 (09:54 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 13 Dec 2022 20:37:59 +0000 (21:37 +0100)
We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no',
which means we'll need the downgrade detection in more places.

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

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit b6339fd1dcbe903e73efeea074ab0bd04ef83561)

source4/rpc_server/netlogon/dcerpc_netlogon.c

index d4bbb1261c3a3a879cd6a2a02c93a4cc0f63ee34..49aa91816abef59235b78c2495f62815941f515f 100644 (file)
@@ -130,6 +130,67 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal
        return NT_STATUS_OK;
 }
 
+static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
+       struct dcesrv_call_state *dce_call,
+       struct netr_ServerAuthenticate3 *r,
+       struct netlogon_server_pipe_state *pipe_state,
+       uint32_t negotiate_flags,
+       NTSTATUS orig_status)
+{
+       struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+       bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
+       bool reject_des_client = !allow_nt4_crypto;
+       bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
+
+       if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
+               reject_des_client = false;
+       }
+
+       if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+               reject_des_client = false;
+               reject_md5_client = false;
+       }
+
+       if (reject_des_client || reject_md5_client) {
+               /*
+                * Here we match Windows 2012 and return no flags.
+                */
+               *r->out.negotiate_flags = 0;
+               return NT_STATUS_DOWNGRADE_DETECTED;
+       }
+
+       /*
+        * This talloc_free is important to prevent re-use of the
+        * challenge.  We have to delay it this far due to NETApp
+        * servers per:
+        * https://bugzilla.samba.org/show_bug.cgi?id=11291
+        */
+       TALLOC_FREE(pipe_state);
+
+       /*
+        * At this point we must also cleanup the TDB cache
+        * entry, if we fail the client needs to call
+        * netr_ServerReqChallenge again.
+        *
+        * Note: this handles a non existing record just fine,
+        * the r->in.computer_name might not be the one used
+        * in netr_ServerReqChallenge(), but we are trying to
+        * just tidy up the normal case to prevent re-use.
+        */
+       schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
+                                 r->in.computer_name);
+
+       /*
+        * According to Microsoft (see bugid #6099)
+        * Windows 7 looks at the negotiate_flags
+        * returned in this structure *even if the
+        * call fails with access denied!
+        */
+       *r->out.negotiate_flags = negotiate_flags;
+
+       return orig_status;
+}
+
 /*
  * Do the actual processing of a netr_ServerAuthenticate3 message.
  * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
@@ -157,11 +218,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
                               "objectSid", "samAccountName", NULL};
        uint32_t server_flags = 0;
        uint32_t negotiate_flags = 0;
-       bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
-       bool reject_des_client = !allow_nt4_crypto;
-       bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
 
        ZERO_STRUCTP(r->out.return_credentials);
+       *r->out.negotiate_flags = 0;
        *r->out.rid = 0;
 
        pipe_state = dcesrv_iface_state_find_conn(dce_call,
@@ -240,52 +299,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 
        negotiate_flags = *r->in.negotiate_flags & server_flags;
 
-       if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
-               reject_des_client = false;
-       }
-
-       if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
-               reject_des_client = false;
-               reject_md5_client = false;
-       }
-
-       if (reject_des_client || reject_md5_client) {
-               /*
-                * Here we match Windows 2012 and return no flags.
-                */
-               *r->out.negotiate_flags = 0;
-               return NT_STATUS_DOWNGRADE_DETECTED;
+       nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
+                       dce_call, r, pipe_state, negotiate_flags,
+                       NT_STATUS_OK);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
        }
 
-       /*
-        * This talloc_free is important to prevent re-use of the
-        * challenge.  We have to delay it this far due to NETApp
-        * servers per:
-        * https://bugzilla.samba.org/show_bug.cgi?id=11291
-        */
-       TALLOC_FREE(pipe_state);
-
-       /*
-        * At this point we must also cleanup the TDB cache
-        * entry, if we fail the client needs to call
-        * netr_ServerReqChallenge again.
-        *
-        * Note: this handles a non existing record just fine,
-        * the r->in.computer_name might not be the one used
-        * in netr_ServerReqChallenge(), but we are trying to
-        * just tidy up the normal case to prevent re-use.
-        */
-       schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
-                                 r->in.computer_name);
-
-       /*
-        * According to Microsoft (see bugid #6099)
-        * Windows 7 looks at the negotiate_flags
-        * returned in this structure *even if the
-        * call fails with access denied!
-        */
-       *r->out.negotiate_flags = negotiate_flags;
-
        switch (r->in.secure_channel_type) {
        case SEC_CHAN_WKSTA:
        case SEC_CHAN_DNS_DOMAIN: