From 898fe5a142fd195f5db72c0372ecc452e0f3dc74 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 30 Oct 2018 10:31:11 +0100 Subject: auth:ntlmssp: Use GnuTLS MD5 and HMAC MD5 in ntlmssp server Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- auth/ntlmssp/ntlmssp_server.c | 118 +++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 31 deletions(-) (limited to 'auth') diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c index 140e89daeb1..48bd743ef74 100644 --- a/auth/ntlmssp/ntlmssp_server.c +++ b/auth/ntlmssp/ntlmssp_server.c @@ -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 +#include + #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; } } -- cgit v1.2.1