auth:ntlmssp: Use GnuTLS MD5 and HMAC MD5 in ntlmssp server
authorAndreas Schneider <asn@samba.org>
Tue, 30 Oct 2018 09:31:11 +0000 (10:31 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 21 May 2019 00:03:21 +0000 (00:03 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
auth/ntlmssp/ntlmssp_server.c

index 140e89daeb1383a58372fb15f5eebe8b556f433a..48bd743ef7405daea5c9080c8f7ce265840b5262 100644 (file)
@@ -29,7 +29,6 @@
 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
 #include "auth/ntlmssp/ntlmssp_ndr.h"
 #include "../libcli/auth/libcli_auth.h"
-#include "../lib/crypto/crypto.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_internal.h"
 #include "auth/common_auth.h"
@@ -37,6 +36,9 @@
 #include "param/loadparm.h"
 #include "libcli/security/session.h"
 
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
 
@@ -424,7 +426,6 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
        DATA_BLOB version_blob = data_blob_null;
        const unsigned int mic_len = NTLMSSP_MIC_SIZE;
        DATA_BLOB mic_blob = data_blob_null;
-       uint8_t session_nonce_hash[16];
        const char *parse_string;
        bool ok;
        struct timeval endtime;
@@ -751,7 +752,6 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
        */
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
                if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
-                       MD5_CTX md5_session_nonce_ctx;
                        state->doing_ntlm2 = true;
 
                        memcpy(state->session_nonce, ntlmssp_state->internal_chal.data, 8);
@@ -759,18 +759,30 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 
                        SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
 
-                       MD5Init(&md5_session_nonce_ctx);
-                       MD5Update(&md5_session_nonce_ctx, state->session_nonce, 16);
-                       MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
-
                        /* LM response is no longer useful */
                        data_blob_free(&ntlmssp_state->lm_resp);
 
                        /* We changed the effective challenge - set it */
                        if (auth_context->set_ntlm_challenge) {
+                               uint8_t session_nonce_hash[16];
+                               int rc;
+
+                               rc = gnutls_hash_fast(GNUTLS_DIG_MD5,
+                                                     state->session_nonce,
+                                                     16,
+                                                     session_nonce_hash);
+                               if (rc < 0) {
+                                       if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
+                                               return NT_STATUS_NTLM_BLOCKED;
+                                       }
+                                       return NT_STATUS_INTERNAL_ERROR;
+                               }
+
+
                                nt_status = auth_context->set_ntlm_challenge(auth_context,
                                                                             session_nonce_hash,
                                                                             "NTLMSSP callback (NTLM2)");
+                               ZERO_ARRAY(session_nonce_hash);
                                if (!NT_STATUS_IS_OK(nt_status)) {
                                        DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
                                                  nt_errstr(nt_status)));
@@ -927,10 +939,24 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
        /* Handle the different session key derivation for NTLM2 */
        if (state->doing_ntlm2) {
                if (user_session_key.data && user_session_key.length == 16) {
+                       int rc;
+
                        session_key = data_blob_talloc(ntlmssp_state,
                                                       NULL, 16);
-                       hmac_md5(user_session_key.data, state->session_nonce,
-                                sizeof(state->session_nonce), session_key.data);
+
+                       rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
+                                             user_session_key.data,
+                                             user_session_key.length,
+                                             state->session_nonce,
+                                             sizeof(state->session_nonce),
+                                             session_key.data);
+                       if (rc < 0) {
+                               if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
+                                       return NT_STATUS_NTLM_BLOCKED;
+                               }
+                               return NT_STATUS_INTERNAL_ERROR;
+                       }
+
                        DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
                        dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
 
@@ -1031,33 +1057,58 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
        }
 
        if (ntlmssp_state->new_spnego) {
-               HMACMD5Context ctx;
+               gnutls_hmac_hd_t hmac_hnd = NULL;
                uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
                int cmp;
-
-               hmac_md5_init_limK_to_64(ntlmssp_state->session_key.data,
-                                        ntlmssp_state->session_key.length,
-                                        &ctx);
-
-               hmac_md5_update(ntlmssp_state->negotiate_blob.data,
-                               ntlmssp_state->negotiate_blob.length,
-                               &ctx);
-               hmac_md5_update(ntlmssp_state->challenge_blob.data,
-                               ntlmssp_state->challenge_blob.length,
-                               &ctx);
+               int rc;
+
+               rc = gnutls_hmac_init(&hmac_hnd,
+                                GNUTLS_MAC_MD5,
+                                ntlmssp_state->session_key.data,
+                                MIN(ntlmssp_state->session_key.length, 64));
+               if (rc < 0) {
+                       if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
+                               return NT_STATUS_NTLM_BLOCKED;
+                       }
+                       return NT_STATUS_NO_MEMORY;
+               }
+               rc = gnutls_hmac(hmac_hnd,
+                                ntlmssp_state->negotiate_blob.data,
+                                ntlmssp_state->negotiate_blob.length);
+               if (rc < 0) {
+                       gnutls_hmac_deinit(hmac_hnd, NULL);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               rc = gnutls_hmac(hmac_hnd,
+                                 ntlmssp_state->challenge_blob.data,
+                                 ntlmssp_state->challenge_blob.length);
+               if (rc < 0) {
+                       gnutls_hmac_deinit(hmac_hnd, NULL);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
 
                /* checked were we set ntlmssp_state->new_spnego */
                SMB_ASSERT(request.length >
                           (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE));
 
-               hmac_md5_update(request.data, NTLMSSP_MIC_OFFSET, &ctx);
-               hmac_md5_update(mic_buffer, NTLMSSP_MIC_SIZE, &ctx);
-               hmac_md5_update(request.data +
-                               (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE),
-                               request.length -
-                               (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE),
-                               &ctx);
-               hmac_md5_final(mic_buffer, &ctx);
+               rc = gnutls_hmac(hmac_hnd, request.data, NTLMSSP_MIC_OFFSET);
+               if (rc < 0) {
+                       gnutls_hmac_deinit(hmac_hnd, NULL);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               rc = gnutls_hmac(hmac_hnd, mic_buffer, NTLMSSP_MIC_SIZE);
+               if (rc < 0) {
+                       gnutls_hmac_deinit(hmac_hnd, NULL);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               rc = gnutls_hmac(hmac_hnd,
+                                request.data + (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE),
+                                request.length - (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE));
+               if (rc < 0) {
+                       gnutls_hmac_deinit(hmac_hnd, NULL);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               gnutls_hmac_deinit(hmac_hnd, mic_buffer);
 
                cmp = memcmp(request.data + NTLMSSP_MIC_OFFSET,
                             mic_buffer, NTLMSSP_MIC_SIZE);
@@ -1068,10 +1119,15 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
                                 ntlmssp_state->user,
                                 ntlmssp_state->domain,
                                 ntlmssp_state->client.netbios_name));
-                       dump_data(1, request.data + NTLMSSP_MIC_OFFSET,
+                       dump_data(11, request.data + NTLMSSP_MIC_OFFSET,
                                  NTLMSSP_MIC_SIZE);
-                       dump_data(1, mic_buffer,
+                       dump_data(11, mic_buffer,
                                  NTLMSSP_MIC_SIZE);
+               }
+
+               ZERO_ARRAY(mic_buffer);
+
+               if (cmp != 0) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
        }