Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix offset calculation for the MIC field to match the specification #64

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/gss_ntlmssp.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
NTLMSSP_NEGOTIATE_NTLM | \
NTLMSSP_REQUEST_TARGET | \
NTLMSSP_NEGOTIATE_OEM | \
NTLMSSP_NEGOTIATE_UNICODE)
NTLMSSP_NEGOTIATE_UNICODE | \
NTLMSSP_NEGOTIATE_VERSION)

#define NTLMSSP_DEFAULT_SERVER_FLAGS ( \
NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \
Expand Down
28 changes: 21 additions & 7 deletions src/ntlm.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,10 @@ int ntlm_encode_neg_msg(struct ntlm_ctx *ctx, uint32_t flags,

buffer.length = sizeof(struct wire_neg_msg);

if (flags & NTLMSSP_NEGOTIATE_VERSION) {
buffer.length += sizeof(struct wire_version);
}

/* Strings MUST use OEM charset in negotiate message */
if (flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) {
if (!domain) return EINVAL;
Expand All @@ -920,6 +924,11 @@ int ntlm_encode_neg_msg(struct ntlm_ctx *ctx, uint32_t flags,

msg->neg_flags = htole32(flags);

if (flags & NTLMSSP_NEGOTIATE_VERSION) {
ret = ntlm_encode_version(ctx, &buffer, &data_offs);
if (ret) goto done;
}

if (dom_len) {
ret = ntlm_encode_oem_str(&msg->domain_name, &buffer,
&data_offs, domain, dom_len);
Expand Down Expand Up @@ -1190,9 +1199,7 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
if (enc_sess_key) {
buffer.length += enc_sess_key->length;
}
if (flags & NTLMSSP_NEGOTIATE_VERSION) {
buffer.length += sizeof(struct wire_version);
}
buffer.length += sizeof(struct wire_version);
if (mic) {
buffer.length += 16;
}
Expand All @@ -1210,6 +1217,10 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
ret = ntlm_encode_version(ctx, &buffer, &data_offs);
if (ret) goto done;
}
else {
memset(&buffer.data[data_offs], 0, sizeof(struct wire_version));
data_offs += sizeof(struct wire_version);
}

/* this must be second as it pushes the payload further down */
if (mic) {
Expand Down Expand Up @@ -1294,6 +1305,7 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
{
struct wire_auth_msg *msg;
size_t payload_offs;
size_t mic_offs;
char *dom = NULL;
char *usr = NULL;
char *wks = NULL;
Expand All @@ -1306,7 +1318,9 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
if (enc_sess_key) enc_sess_key->data = NULL;

msg = (struct wire_auth_msg *)buffer->data;
payload_offs = (char *)msg->payload - (char *)msg;
mic_offs = payload_offs = (char *)msg->payload - (char *)msg;
/* if MIC is present then there's always a reserved space for version */
mic_offs += sizeof(struct wire_version);

/* this must be first as it pushes the payload further down */
if (flags & NTLMSSP_NEGOTIATE_VERSION) {
Expand All @@ -1320,9 +1334,9 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
* and the MIC checked otherwise these 16 bytes will just be ignored */
if (mic) {
if (mic->length < 16) return ERR_DECODE;
/* mic is at payload_offs right now */
if (buffer->length - payload_offs < 16) return ERR_DECODE;
memcpy(mic->data, &buffer->data[payload_offs], 16);
/* mic is at mic_offs right now */
if (buffer->length - mic_offs < 16) return ERR_DECODE;
memcpy(mic->data, &buffer->data[mic_offs], 16);
/* NOTE: we do not push down the payload because we do not know that
* the MIC is actually present yet for real */
}
Expand Down
12 changes: 2 additions & 10 deletions src/ntlm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -962,20 +962,12 @@ int ntlm_verify_mic(struct ntlm_key *key,
{
uint8_t micbuf[NTLM_SIGNATURE_SIZE];
struct ntlm_buffer check_mic = { micbuf, NTLM_SIGNATURE_SIZE };
struct wire_auth_msg *msg;
size_t payload_offs;
uint32_t flags;
int ret;

msg = (struct wire_auth_msg *)authenticate_message->data;
payload_offs = offsetof(struct wire_auth_msg, payload);

/* flags must be checked as they may push the payload further down */
flags = le32toh(msg->neg_flags);
if (flags & NTLMSSP_NEGOTIATE_VERSION) {
/* skip version for now */
payload_offs += sizeof(struct wire_version);
}
/* if MIC is present then there's always a reserved space for version */
payload_offs += sizeof(struct wire_version);

if (payload_offs + NTLM_SIGNATURE_SIZE > authenticate_message->length) {
return EINVAL;
Expand Down