15static const uint8_t NTLMSSP_SIG[8] = {
'N',
'T',
'L',
'M',
'S',
'S',
'P', 0};
17static uint16_t rd16(
const uint8_t *p)
19 return (uint16_t)(p[0] | (p[1] << 8));
21static uint32_t rd32(
const uint8_t *p)
23 return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
25static void wr16(uint8_t *p, uint16_t v)
28 p[1] = (uint8_t)(v >> 8);
30static void wr32(uint8_t *p, uint32_t v)
33 p[1] = (uint8_t)(v >> 8);
34 p[2] = (uint8_t)(v >> 16);
35 p[3] = (uint8_t)(v >> 24);
39static void wr_field(uint8_t *f, uint16_t len, uint32_t off)
46size_t ntlmssp_build_negotiate(uint8_t *buf,
size_t cap, uint32_t flags)
51 memcpy(buf + 0, NTLMSSP_SIG, 8);
53 wr32(buf + 12, flags);
54 wr_field(buf + 16, 0, 32);
55 wr_field(buf + 24, 0, 32);
59bool ntlmssp_parse_challenge(
const uint8_t *msg,
size_t len, NtlmChallenge *out)
61 if (!msg || !out || len < 48)
63 if (memcmp(msg, NTLMSSP_SIG, 8) != 0 || rd32(msg + 8) != 2)
65 out->flags = rd32(msg + 20);
66 memcpy(out->server_challenge, msg + 24, 8);
67 uint16_t ti_len = rd16(msg + 40);
68 uint32_t ti_off = rd32(msg + 44);
71 out->target_info =
nullptr;
72 out->target_info_len = 0;
75 if ((
size_t)ti_off + ti_len > len)
77 out->target_info = msg + ti_off;
78 out->target_info_len = ti_len;
83static size_t put_utf16le(uint8_t *buf,
const char *s)
87 for (
const char *p = s; *p; p++)
89 buf[n++] = (uint8_t)*p;
94static size_t utf16_len(
const char *s)
103size_t ntlmssp_build_authenticate(uint8_t *buf,
size_t cap,
const uint8_t *lm_resp,
size_t lm_len,
104 const uint8_t *nt_resp,
size_t nt_len,
const char *domain,
const char *user,
105 const char *workstation, uint32_t flags)
107 const size_t HDR = 64;
108 size_t dlen = utf16_len(domain);
109 size_t ulen = utf16_len(user);
110 size_t wlen = utf16_len(workstation);
111 size_t total = HDR + lm_len + nt_len + dlen + ulen + wlen;
112 if (!buf || total > cap)
116 memcpy(buf + 0, NTLMSSP_SIG, 8);
122 if (lm_resp && lm_len)
123 memcpy(buf + off, lm_resp, lm_len);
126 if (nt_resp && nt_len)
127 memcpy(buf + off, nt_resp, nt_len);
129 size_t dom_off = off;
130 off += put_utf16le(buf + off, domain);
131 size_t usr_off = off;
132 off += put_utf16le(buf + off, user);
133 size_t wks_off = off;
134 off += put_utf16le(buf + off, workstation);
135 size_t key_off = off;
137 wr_field(buf + 12, (uint16_t)lm_len, (uint32_t)lm_off);
138 wr_field(buf + 20, (uint16_t)nt_len, (uint32_t)nt_off);
139 wr_field(buf + 28, (uint16_t)dlen, (uint32_t)dom_off);
140 wr_field(buf + 36, (uint16_t)ulen, (uint32_t)usr_off);
141 wr_field(buf + 44, (uint16_t)wlen, (uint32_t)wks_off);
142 wr_field(buf + 52, 0, (uint32_t)key_off);
143 wr32(buf + 60, flags);
NTLMSSP message codec (MS-NLMP §2.2.1) for the SMB2 client (DETWS_ENABLE_SMB).