1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

auth:ntlmssp: Use GnuTLS MD5 and HMAC MD5 in ntlmssp server

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Andreas Schneider 2018-10-30 10:31:11 +01:00 committed by Andrew Bartlett
parent 44fcb59908
commit 898fe5a142

View 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;
int rc;
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);
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;
}
}