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:
parent
44fcb59908
commit
898fe5a142
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user