Skip to content

Commit

Permalink
Merge pull request #42 from skbehera1984/ntlmssp_signing
Browse files Browse the repository at this point in the history
Signing support for the built-in NTLMSSP mode
  • Loading branch information
sahlberg committed May 18, 2018
2 parents 56fccd7 + 21d06a9 commit 983a749
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 35 deletions.
88 changes: 54 additions & 34 deletions lib/libsmb2.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,42 +602,62 @@ session_setup_cb(struct smb2_context *smb2, int status,
free_c_data(smb2, c_data);
return;
}

if (smb2->signing_required) {
uint8_t zero_key[SMB2_KEY_SIZE] = {0};
int have_valid_session_key = 1;
#ifdef HAVE_LIBKRB5
if (smb2->signing_required &&
krb5_session_get_session_key(smb2, c_data->auth_data) < 0) {
smb2_close_context(smb2);
smb2_set_error(smb2, "Signing required by server. Session "
"Key is not available %s",
smb2_get_error(smb2));
c_data->cb(smb2, -1, NULL, c_data->cb_data);
free_c_data(smb2, c_data);
return;
}
if (krb5_session_get_session_key(smb2, c_data->auth_data) < 0) {
have_valid_session_key = 0;
}
#else
if (ntlmssp_get_session_key(c_data->auth_data,
&smb2->session_key,
&smb2->session_key_size) < 0) {
have_valid_session_key = 0;
}
#endif
/* check if the session key is proper */
if (smb2->session_key == NULL || memcmp(smb2->session_key, zero_key, SMB2_KEY_SIZE) == 0) {
have_valid_session_key = 0;
}
if (have_valid_session_key == 0)
{
smb2_close_context(smb2);
smb2_set_error(smb2, "Signing required by server. Session "
"Key is not available %s",
smb2_get_error(smb2));
c_data->cb(smb2, -1, NULL, c_data->cb_data);
free_c_data(smb2, c_data);
return;
}

/* Derive the signing key from session key
* This is based on negotiated protocol
*/
if (smb2->dialect == SMB2_VERSION_0202 || smb2->dialect == SMB2_VERSION_0210) {
/* For SMB2 session key is the signing key */
memcpy(smb2->signing_key,
smb2->session_key,
MIN(smb2->session_key_size, SMB2_KEY_SIZE));
} else if (smb2->dialect <= SMB2_VERSION_0302) {
smb2_derive_key(smb2->session_key,
smb2->session_key_size,
SMB2AESCMAC,
sizeof(SMB2AESCMAC),
SmbSign,
sizeof(SmbSign),
smb2->signing_key);
} else if (smb2->dialect > SMB2_VERSION_0302) {
smb2_close_context(smb2);
smb2_set_error(smb2, "Signing Required by server. Not yet implemented for SMB3.1");
c_data->cb(smb2, -EINVAL, NULL, c_data->cb_data);
free_c_data(smb2, c_data);
return;
/* Derive the signing key from session key
* This is based on negotiated protocol
*/
if (smb2->dialect == SMB2_VERSION_0202 ||
smb2->dialect == SMB2_VERSION_0210) {
/* For SMB2 session key is the signing key */
memcpy(smb2->signing_key,
smb2->session_key,
MIN(smb2->session_key_size, SMB2_KEY_SIZE));
} else if (smb2->dialect <= SMB2_VERSION_0302) {
smb2_derive_key(smb2->session_key,
smb2->session_key_size,
SMB2AESCMAC,
sizeof(SMB2AESCMAC),
SmbSign,
sizeof(SmbSign),
smb2->signing_key);
} else if (smb2->dialect > SMB2_VERSION_0302) {
smb2_close_context(smb2);
smb2_set_error(smb2, "Signing Required by server. "
"Not yet implemented for SMB3.1");
c_data->cb(smb2, -EINVAL, NULL, c_data->cb_data);
free_c_data(smb2, c_data);
return;
}
}
#endif

memset(&req, 0, sizeof(struct smb2_tree_connect_request));
req.flags = 0;
Expand Down Expand Up @@ -729,7 +749,7 @@ negotiate_cb(struct smb2_context *smb2, int status,
smb2->dialect = rep->dialect_revision;

if (rep->security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
#if !defined(HAVE_OPENSSL_LIBS) || !defined(HAVE_LIBKRB5)
#if !defined(HAVE_OPENSSL_LIBS)
smb2_set_error(smb2, "Signing Required by server. Not yet implemented");
c_data->cb(smb2, -EINVAL, NULL, c_data->cb_data);
free_c_data(smb2, c_data);
Expand Down
39 changes: 39 additions & 0 deletions lib/ntlmssp.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct auth_data {
const char *domain;
const char *workstation;
const char *client_challenge;

uint8_t exported_session_key[SMB2_KEY_SIZE];
};

#define NEGOTIATE_MESSAGE 0x00000001
Expand All @@ -99,13 +101,15 @@ struct auth_data {
#define NTLMSSP_REQUEST_TARGET 0x00000004
#define NTLMSSP_NEGOTIATE_OEM 0x00000002
#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000

void
ntlmssp_destroy_context(struct auth_data *auth)
{
free(auth->ntlm_buf);
free(auth->buf);
free(auth);
memset(auth->exported_session_key, 0, SMB2_KEY_SIZE);
}

struct auth_data *
Expand All @@ -129,6 +133,8 @@ ntlmssp_init_context(const char *user,
auth_data->workstation = workstation;
auth_data->client_challenge = client_challenge;

memset(auth_data->exported_session_key, 0, SMB2_KEY_SIZE);

return auth_data;
}

Expand Down Expand Up @@ -323,6 +329,8 @@ encode_ntlm_auth(struct auth_data *auth_data,
char *server_name_buf;
int server_name_len;
uint32_t u32;
uint32_t server_neg_flags;
unsigned char key_exch[SMB2_KEY_SIZE];

tv.tv_sec = time(NULL);
tv.tv_usec = 0;
Expand All @@ -337,6 +345,10 @@ encode_ntlm_auth(struct auth_data *auth_data,
goto finished;
}

/* get the server neg flags */
memcpy(&server_neg_flags, &auth_data->ntlm_buf[20], 4);
server_neg_flags = le32toh(server_neg_flags);

memcpy(&u32, &auth_data->ntlm_buf[40], 4);
u32 = le32toh(u32);
server_name_len = u32 >> 16;
Expand All @@ -361,6 +373,11 @@ encode_ntlm_auth(struct auth_data *auth_data,
auth_data->len = 0;
auth_data->allocated = 0;

/* get the NTLMv2 Key-Exchange Key
For NTLMv2 - Key Exchange Key is the Session Base Key
*/
hmac_md5(NTProofStr, 16, ResponseKeyNT, 16, key_exch);
memcpy(auth_data->exported_session_key, key_exch, 16);

/*
* Generate AUTHENTICATE_MESSAGE
Expand Down Expand Up @@ -517,4 +534,26 @@ ntlmssp_generate_blob(struct auth_data *auth_data,
return 0;
}

int
ntlmssp_get_session_key(struct auth_data *auth,
uint8_t **key,
uint8_t *key_size)
{
uint8_t *mkey = NULL;

if (auth == NULL || key == NULL || key_size == NULL) {
return -1;
}

mkey = (uint8_t *) malloc(SMB2_KEY_SIZE);
if (mkey == NULL) {
return -1;
}
memcpy(mkey, auth->exported_session_key, SMB2_KEY_SIZE);

*key = mkey;
*key_size = SMB2_KEY_SIZE;

return 0;
}
#endif /* HAVE_LIBKRB5 */
2 changes: 2 additions & 0 deletions lib/ntlmssp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ ntlmssp_generate_blob(struct auth_data *auth_data,
void
ntlmssp_destroy_context(struct auth_data *auth);

int ntlmssp_get_session_key(struct auth_data *auth, uint8_t **key, uint8_t *key_size);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ smb2_queue_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu)
/* Update all the PDU headers in this chain */
for (p = pdu; p; p = p->next_compound) {
smb2_encode_header(smb2, &p->out.iov[0], &p->header);
#if defined(HAVE_OPENSSL_LIBS) && defined(HAVE_LIBKRB5)
#if defined(HAVE_OPENSSL_LIBS)
if (smb2->signing_required) {
if (smb2_pdu_add_signature(smb2, p) < 0) {
smb2_set_error(smb2, "Failure to add "
Expand Down

0 comments on commit 983a749

Please sign in to comment.