1 /* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
3 Copyright (C) 2018 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
46 #ifdef HAVE_SYS_STAT_H
55 #include "portable-endian.h"
62 #include "libsmb2-raw.h"
63 #include "libsmb2-private.h"
76 unsigned char *ntlm_buf;
82 const char *workstation;
83 const char *client_challenge;
85 uint8_t exported_session_key[SMB2_KEY_SIZE];
88 #define NEGOTIATE_MESSAGE 0x00000001
89 #define CHALLENGE_MESSAGE 0x00000002
90 #define AUTHENTICATION_MESSAGE 0x00000003
92 #define NTLMSSP_NEGOTIATE_56 0x80000000
93 #define NTLMSSP_NEGOTIATE_128 0x20000000
94 #define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000
95 #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
96 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
97 #define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800
98 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200
99 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020
100 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010
101 #define NTLMSSP_REQUEST_TARGET 0x00000004
102 #define NTLMSSP_NEGOTIATE_OEM 0x00000002
103 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
104 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
107 ntlmssp_destroy_context(struct auth_data *auth)
109 free(auth->ntlm_buf);
115 ntlmssp_init_context(const char *user,
116 const char *password,
118 const char *workstation,
119 const char *client_challenge)
121 struct auth_data *auth_data = NULL;
123 auth_data = calloc(1, sizeof(struct auth_data));
124 if (auth_data == NULL) {
128 auth_data->user = user;
129 auth_data->password = password;
130 auth_data->domain = domain;
131 auth_data->workstation = workstation;
132 auth_data->client_challenge = client_challenge;
134 memset(auth_data->exported_session_key, 0, SMB2_KEY_SIZE);
140 encoder(const void *buffer, size_t size, void *ptr)
142 struct auth_data *auth_data = ptr;
144 if (size + auth_data->len > auth_data->allocated) {
145 unsigned char *tmp = auth_data->buf;
147 auth_data->allocated = 2 * ((size + auth_data->allocated + 256) & ~0xff);
148 auth_data->buf = malloc(auth_data->allocated);
149 if (auth_data->buf == NULL) {
153 memcpy(auth_data->buf, tmp, auth_data->len);
157 memcpy(auth_data->buf + auth_data->len, buffer, size);
158 auth_data->len += size;
164 ntlm_negotiate_message(struct smb2_context *smb2, struct auth_data *auth_data)
166 unsigned char ntlm[32];
170 memcpy(ntlm, "NTLMSSP", 8);
172 u32 = htole32(NEGOTIATE_MESSAGE);
173 memcpy(&ntlm[8], &u32, 4);
175 u32 = NTLMSSP_NEGOTIATE_56|NTLMSSP_NEGOTIATE_128|
176 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY|
177 //NTLMSSP_NEGOTIATE_ALWAYS_SIGN|
178 NTLMSSP_NEGOTIATE_NTLM|
179 //NTLMSSP_NEGOTIATE_SIGN|
180 NTLMSSP_REQUEST_TARGET|NTLMSSP_NEGOTIATE_OEM|
181 NTLMSSP_NEGOTIATE_UNICODE;
183 u32 |= NTLMSSP_NEGOTIATE_SEAL;
185 memcpy(&ntlm[12], &u32, 4);
187 if (encoder(&ntlm[0], 32, auth_data) < 0) {
195 ntlm_challenge_message(struct auth_data *auth_data, unsigned char *buf,
198 free(auth_data->ntlm_buf);
199 auth_data->ntlm_len = len;
200 auth_data->ntlm_buf = malloc(auth_data->ntlm_len);
201 if (auth_data->ntlm_buf == NULL) {
204 memcpy(auth_data->ntlm_buf, buf, auth_data->ntlm_len);
210 NTOWFv1(const char *password, unsigned char password_hash[16])
213 struct ucs2 *ucs2_password = NULL;
215 ucs2_password = utf8_to_ucs2(password);
216 if (ucs2_password == NULL) {
220 MD4Update(&ctx, (unsigned char *)ucs2_password->val, ucs2_password->len * 2);
221 MD4Final(password_hash, &ctx);
228 NTOWFv2(const char *user, const char *password, const char *domain,
229 unsigned char ntlmv2_hash[16])
233 struct ucs2 *ucs2_userdomain = NULL;
234 unsigned char ntlm_hash[16];
236 if (NTOWFv1(password, ntlm_hash) < 0) {
240 len = strlen(user) + 1;
242 len += strlen(domain);
244 userdomain = malloc(len);
245 if (userdomain == NULL) {
249 strcpy(userdomain, user);
250 for (i = strlen(userdomain) - 1; i >=0; i--) {
251 if (islower((unsigned int) userdomain[i])) {
252 userdomain[i] = toupper((unsigned int) userdomain[i]);
256 strcat(userdomain, domain);
259 ucs2_userdomain = utf8_to_ucs2(userdomain);
260 if (ucs2_userdomain == NULL) {
265 smb2_hmac_md5((unsigned char *)ucs2_userdomain->val,
266 ucs2_userdomain->len * 2,
267 ntlm_hash, 16, ntlmv2_hash);
269 free(ucs2_userdomain);
274 /* This is not the same temp as in MS-NLMP. This temp has an additional
275 * 16 bytes at the start of the buffer.
276 * Use &auth_data->val[16] if you want the temp from MS-NLMP
279 encode_temp(struct auth_data *auth_data, uint64_t t, char *client_challenge,
280 char *server_challenge, char *server_name, int server_name_len)
282 unsigned char sign[8] = {0x01, 0x01, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00};
284 unsigned char zero[8] = {0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00};
287 if (encoder(&zero, 8, auth_data) < 0) {
290 if (encoder(server_challenge, 8, auth_data) < 0) {
293 if (encoder(sign, 8, auth_data) < 0) {
296 if (encoder(&t, 8, auth_data) < 0) {
299 if (encoder(client_challenge, 8, auth_data) < 0) {
302 if (encoder(&zero, 4, auth_data) < 0) {
305 if (encoder(server_name, server_name_len, auth_data) < 0) {
308 if (encoder(&zero, 4, auth_data) < 0) {
316 encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
317 struct auth_data *auth_data, char *server_challenge)
320 unsigned char lm_buf[16];
321 unsigned char *NTChallengeResponse_buf = NULL;
322 unsigned char ResponseKeyNT[16];
323 struct ucs2 *ucs2_domain = NULL;
324 struct ucs2 *ucs2_user = NULL;
325 struct ucs2 *ucs2_workstation = NULL;
326 int NTChallengeResponse_len = 0;
327 unsigned char NTProofStr[16];
328 unsigned char LMStr[16];
330 struct smb2_timeval tv;
331 char *server_name_buf;
334 uint32_t server_neg_flags;
335 unsigned char key_exch[SMB2_KEY_SIZE];
336 uint8_t anonymous = 0;
340 t = timeval_to_win(&tv);
342 if (auth_data->password == NULL) {
348 * Generate Concatenation of(NTProofStr, temp)
350 if (NTOWFv2(auth_data->user, auth_data->password,
351 auth_data->domain, ResponseKeyNT)
356 /* get the server neg flags */
357 memcpy(&server_neg_flags, &auth_data->ntlm_buf[20], 4);
358 server_neg_flags = le32toh(server_neg_flags);
360 memcpy(&u32, &auth_data->ntlm_buf[40], 4);
362 server_name_len = u32 >> 16;
364 memcpy(&u32, &auth_data->ntlm_buf[44], 4);
366 server_name_buf = (char *)&auth_data->ntlm_buf[u32];
368 if (encode_temp(auth_data, t, (char *)auth_data->client_challenge,
369 server_challenge, server_name_buf,
370 server_name_len) < 0) {
374 smb2_hmac_md5(&auth_data->buf[8], auth_data->len-8,
375 ResponseKeyNT, 16, NTProofStr);
376 memcpy(auth_data->buf, NTProofStr, 16);
378 NTChallengeResponse_buf = auth_data->buf;
379 NTChallengeResponse_len = auth_data->len;
380 auth_data->buf = NULL;
382 auth_data->allocated = 0;
384 /* get the NTLMv2 Key-Exchange Key
385 For NTLMv2 - Key Exchange Key is the Session Base Key
387 smb2_hmac_md5(NTProofStr, 16, ResponseKeyNT, 16, key_exch);
388 memcpy(auth_data->exported_session_key, key_exch, 16);
392 * Generate AUTHENTICATE_MESSAGE
394 encoder("NTLMSSP", 8, auth_data);
397 u32 = htole32(AUTHENTICATION_MESSAGE);
398 encoder(&u32, 4, auth_data);
400 /* lm challenge response fields */
402 memcpy(&lm_buf[0], server_challenge, 8);
403 memcpy(&lm_buf[8], auth_data->client_challenge, 8);
404 smb2_hmac_md5(&lm_buf[0], 16,
405 ResponseKeyNT, 16, LMStr);
406 u32 = htole32(0x00180018);
407 encoder(&u32, 4, auth_data);
409 encoder(&u32, 4, auth_data);
412 encoder(&u32, 4, auth_data);
413 encoder(&u32, 4, auth_data);
416 /* nt challenge response fields */
417 u32 = htole32((NTChallengeResponse_len<<16)|
418 NTChallengeResponse_len);
419 encoder(&u32, 4, auth_data);
421 encoder(&u32, 4, auth_data);
423 /* domain name fields */
424 if (!anonymous && auth_data->domain) {
425 ucs2_domain = utf8_to_ucs2(auth_data->domain);
426 if (ucs2_domain == NULL) {
429 u32 = ucs2_domain->len * 2;
430 u32 = htole32((u32 << 16) | u32);
431 encoder(&u32, 4, auth_data);
433 encoder(&u32, 4, auth_data);
436 encoder(&u32, 4, auth_data);
437 encoder(&u32, 4, auth_data);
440 /* user name fields */
442 ucs2_user = utf8_to_ucs2(auth_data->user);
443 if (ucs2_user == NULL) {
446 u32 = ucs2_user->len * 2;
447 u32 = htole32((u32 << 16) | u32);
448 encoder(&u32, 4, auth_data);
450 encoder(&u32, 4, auth_data);
453 encoder(&u32, 4, auth_data);
454 encoder(&u32, 4, auth_data);
457 /* workstation name fields */
458 if (!anonymous && auth_data->workstation) {
459 ucs2_workstation = utf8_to_ucs2(auth_data->workstation);
460 if (ucs2_workstation == NULL) {
463 u32 = ucs2_workstation->len * 2;
464 u32 = htole32((u32 << 16) | u32);
465 encoder(&u32, 4, auth_data);
467 encoder(&u32, 4, auth_data);
470 encoder(&u32, 4, auth_data);
471 encoder(&u32, 4, auth_data);
474 /* encrypted random session key */
476 encoder(&u32, 4, auth_data);
477 encoder(&u32, 4, auth_data);
479 /* negotiate flags */
480 u32 = NTLMSSP_NEGOTIATE_56|NTLMSSP_NEGOTIATE_128|
481 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY|
482 //NTLMSSP_NEGOTIATE_ALWAYS_SIGN|
483 NTLMSSP_NEGOTIATE_NTLM|
484 //NTLMSSP_NEGOTIATE_SIGN|
485 NTLMSSP_REQUEST_TARGET|NTLMSSP_NEGOTIATE_OEM|
486 NTLMSSP_NEGOTIATE_UNICODE;
488 u32 |= NTLMSSP_NEGOTIATE_ANONYMOUS;
490 u32 |= NTLMSSP_NEGOTIATE_SEAL;
492 encoder(&u32, 4, auth_data);
496 u32 = htole32(auth_data->len);
497 memcpy(&auth_data->buf[32], &u32, 4);
499 encoder(ucs2_domain->val, ucs2_domain->len * 2,
504 u32 = htole32(auth_data->len);
505 memcpy(&auth_data->buf[40], &u32, 4);
506 encoder(ucs2_user->val, ucs2_user->len * 2, auth_data);
508 /* append workstation */
509 u32 = htole32(auth_data->len);
510 memcpy(&auth_data->buf[48], &u32, 4);
511 if (ucs2_workstation) {
512 encoder(ucs2_workstation->val,
513 ucs2_workstation->len * 2, auth_data);
516 /* append LMChallengeResponse */
517 u32 = htole32(auth_data->len);
518 memcpy(&auth_data->buf[16], &u32, 4);
519 encoder(LMStr, 16, auth_data);
520 encoder(auth_data->client_challenge, 8, auth_data);
522 /* append NTChallengeResponse */
523 u32 = htole32(auth_data->len);
524 memcpy(&auth_data->buf[24], &u32, 4);
525 encoder(NTChallengeResponse_buf, NTChallengeResponse_len,
533 free(ucs2_workstation);
534 free(NTChallengeResponse_buf);
540 ntlmssp_generate_blob(struct smb2_context *smb2, time_t t,
541 struct auth_data *auth_data,
542 unsigned char *input_buf, int input_len,
543 unsigned char **output_buf, uint16_t *output_len)
545 free(auth_data->buf);
546 auth_data->buf = NULL;
548 auth_data->allocated = 0;
550 if (input_buf == NULL) {
551 ntlm_negotiate_message(smb2, auth_data);
553 if (ntlm_challenge_message(auth_data, input_buf,
557 if (encode_ntlm_auth(smb2, t, auth_data,
558 (char *)&auth_data->ntlm_buf[24]) < 0) {
563 *output_buf = auth_data->buf;
564 *output_len = auth_data->len;
570 ntlmssp_get_session_key(struct auth_data *auth,
574 uint8_t *mkey = NULL;
576 if (auth == NULL || key == NULL || key_size == NULL) {
580 mkey = (uint8_t *) malloc(SMB2_KEY_SIZE);
584 memcpy(mkey, auth->exported_session_key, SMB2_KEY_SIZE);
587 *key_size = SMB2_KEY_SIZE;