libsmb2: fix potential memory leak
[libsmb2.git] / lib / ntlmssp.c
1 /* -*-  mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil;  -*- */
2 /*
3    Copyright (C) 2018 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
4
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.
9
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.
14
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/>.
17 */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #ifndef _GNU_SOURCE
23 #define _GNU_SOURCE
24 #endif
25
26 #ifdef HAVE_STDINT_H
27 #include <stdint.h>
28 #endif
29
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33
34 #ifdef HAVE_STRING_H
35 #include <string.h>
36 #endif
37
38 #ifdef STDC_HEADERS
39 #include <stddef.h>
40 #endif
41
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h>
48 #endif
49
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53
54 #include <ctype.h>
55 #include "portable-endian.h"
56 #include <stdio.h>
57 #include <time.h>
58
59 #include "slist.h"
60 #include "smb2.h"
61 #include "libsmb2.h"
62 #include "libsmb2-raw.h"
63 #include "libsmb2-private.h"
64
65 #include "md4.h"
66 #include "md5.h"
67 #include "hmac-md5.h"
68 #include "ntlmssp.h"
69
70 struct auth_data {
71         unsigned char *buf;
72         int len;
73         int allocated;
74
75         int neg_result;
76         unsigned char *ntlm_buf;
77         int ntlm_len;
78
79         const char *user;
80         const char *password;
81         const char *domain;
82         const char *workstation;
83         const char *client_challenge;
84
85         uint8_t exported_session_key[SMB2_KEY_SIZE];
86 };
87
88 #define NEGOTIATE_MESSAGE      0x00000001
89 #define CHALLENGE_MESSAGE      0x00000002
90 #define AUTHENTICATION_MESSAGE 0x00000003
91
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
105
106 void
107 ntlmssp_destroy_context(struct auth_data *auth)
108 {
109         free(auth->ntlm_buf);
110         free(auth->buf);
111         free(auth);
112 }
113
114 struct auth_data *
115 ntlmssp_init_context(const char *user,
116                      const char *password,
117                      const char *domain,
118                      const char *workstation,
119                      const char *client_challenge)
120 {
121         struct auth_data *auth_data = NULL;
122
123         auth_data = calloc(1, sizeof(struct auth_data));
124         if (auth_data == NULL) {
125                 return NULL;
126         }
127
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;
133
134         memset(auth_data->exported_session_key, 0, SMB2_KEY_SIZE);
135
136         return auth_data;
137 }
138
139 static int
140 encoder(const void *buffer, size_t size, void *ptr)
141 {
142         struct auth_data *auth_data = ptr;
143
144         if (size + auth_data->len > auth_data->allocated) {
145                 unsigned char *tmp = auth_data->buf;
146
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) {
150                         free(tmp);
151                         return -1;
152                 }
153                 memcpy(auth_data->buf, tmp, auth_data->len);
154                 free(tmp);
155         }
156
157         memcpy(auth_data->buf + auth_data->len, buffer, size);
158         auth_data->len += size;
159
160         return 0;
161 }
162
163 static int
164 ntlm_negotiate_message(struct smb2_context *smb2, struct auth_data *auth_data)
165 {
166         unsigned char ntlm[32];
167         uint32_t u32;
168
169         memset(ntlm, 0, 32);
170         memcpy(ntlm, "NTLMSSP", 8);
171
172         u32 = htole32(NEGOTIATE_MESSAGE);
173         memcpy(&ntlm[8], &u32, 4);
174
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;
182         if (smb2->seal)
183                 u32 |= NTLMSSP_NEGOTIATE_SEAL;
184         u32 = htole32(u32);
185         memcpy(&ntlm[12], &u32, 4);
186
187         if (encoder(&ntlm[0], 32, auth_data) < 0) {
188                 return -1;
189         }
190
191         return 0;
192 }
193
194 static int
195 ntlm_challenge_message(struct auth_data *auth_data, unsigned char *buf,
196                        int len)
197 {
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) {
202                 return -1;
203         }
204         memcpy(auth_data->ntlm_buf, buf, auth_data->ntlm_len);
205
206         return 0;
207 }
208
209 static int
210 NTOWFv1(const char *password, unsigned char password_hash[16])
211 {
212         MD4_CTX ctx;
213         struct ucs2 *ucs2_password = NULL;
214
215         ucs2_password = utf8_to_ucs2(password);
216         if (ucs2_password == NULL) {
217                 return -1;
218         }
219         MD4Init(&ctx);
220         MD4Update(&ctx, (unsigned char *)ucs2_password->val, ucs2_password->len * 2);
221         MD4Final(password_hash, &ctx);
222         free(ucs2_password);
223
224         return 0;
225 }
226
227 static int
228 NTOWFv2(const char *user, const char *password, const char *domain,
229         unsigned char ntlmv2_hash[16])
230 {
231         int i, len;
232         char *userdomain;
233         struct ucs2 *ucs2_userdomain = NULL;
234         unsigned char ntlm_hash[16];
235
236         if (NTOWFv1(password, ntlm_hash) < 0) {
237                 return -1;
238         }
239
240         len = strlen(user) + 1;
241         if (domain) {
242                 len += strlen(domain);
243         }
244         userdomain = malloc(len);
245         if (userdomain == NULL) {
246                 return -1;
247         }
248
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]);
253                 }
254         }
255         if (domain) {
256                 strcat(userdomain, domain);
257         }
258
259         ucs2_userdomain = utf8_to_ucs2(userdomain);
260         if (ucs2_userdomain == NULL) {
261                 free(userdomain);
262                 return -1;
263         }
264
265         smb2_hmac_md5((unsigned char *)ucs2_userdomain->val,
266                  ucs2_userdomain->len * 2,
267                  ntlm_hash, 16, ntlmv2_hash);
268         free(userdomain);
269         free(ucs2_userdomain);
270
271         return 0;
272 }
273
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
277  */
278 static int
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)
281 {
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};
286
287         if (encoder(&zero, 8, auth_data) < 0) {
288                 return -1;
289         }
290         if (encoder(server_challenge, 8, auth_data) < 0) {
291                 return -1;
292         }
293         if (encoder(sign, 8, auth_data) < 0) {
294                 return -1;
295         }
296         if (encoder(&t, 8, auth_data) < 0) {
297                 return -1;
298         }
299         if (encoder(client_challenge, 8, auth_data) < 0) {
300                 return -1;
301         }
302         if (encoder(&zero, 4, auth_data) < 0) {
303                 return -1;
304         }
305         if (encoder(server_name, server_name_len, auth_data) < 0) {
306                 return -1;
307         }
308         if (encoder(&zero, 4, auth_data) < 0) {
309                 return -1;
310         }
311
312         return 0;
313 }
314
315 static int
316 encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
317                  struct auth_data *auth_data, char *server_challenge)
318 {
319         int ret = -1;
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];
329         uint64_t t;
330         struct smb2_timeval tv;
331         char *server_name_buf;
332         int server_name_len;
333         uint32_t u32;
334         uint32_t server_neg_flags;
335         unsigned char key_exch[SMB2_KEY_SIZE];
336         uint8_t anonymous = 0;
337
338         tv.tv_sec = ti;
339         tv.tv_usec = 0;
340         t = timeval_to_win(&tv);
341
342         if (auth_data->password == NULL) {
343                 anonymous = 1;
344                 goto encode;
345         }
346
347         /*
348          * Generate Concatenation of(NTProofStr, temp)
349          */
350         if (NTOWFv2(auth_data->user, auth_data->password,
351                     auth_data->domain, ResponseKeyNT)
352             < 0) {
353                 goto finished;
354         }
355
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);
359
360         memcpy(&u32, &auth_data->ntlm_buf[40], 4);
361         u32 = le32toh(u32);
362         server_name_len = u32 >> 16;
363
364         memcpy(&u32, &auth_data->ntlm_buf[44], 4);
365         u32 = le32toh(u32);
366         server_name_buf = (char *)&auth_data->ntlm_buf[u32];
367
368         if (encode_temp(auth_data, t, (char *)auth_data->client_challenge,
369                         server_challenge, server_name_buf,
370                         server_name_len) < 0) {
371                 return -1;
372         }
373
374         smb2_hmac_md5(&auth_data->buf[8], auth_data->len-8,
375                  ResponseKeyNT, 16, NTProofStr);
376         memcpy(auth_data->buf, NTProofStr, 16);
377
378         NTChallengeResponse_buf = auth_data->buf;
379         NTChallengeResponse_len = auth_data->len;
380         auth_data->buf = NULL;
381         auth_data->len = 0;
382         auth_data->allocated = 0;
383
384         /* get the NTLMv2 Key-Exchange Key
385            For NTLMv2 - Key Exchange Key is the Session Base Key
386          */
387         smb2_hmac_md5(NTProofStr, 16, ResponseKeyNT, 16, key_exch);
388         memcpy(auth_data->exported_session_key, key_exch, 16);
389
390  encode:
391         /*
392          * Generate AUTHENTICATE_MESSAGE
393          */
394         encoder("NTLMSSP", 8, auth_data);
395
396         /* message type */
397         u32 = htole32(AUTHENTICATION_MESSAGE);
398         encoder(&u32, 4, auth_data);
399
400         /* lm challenge response fields */
401         if (!anonymous) {
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);
408                 u32 = 0;
409                 encoder(&u32, 4, auth_data);
410         } else {
411                 u32 = 0;
412                 encoder(&u32, 4, auth_data);
413                 encoder(&u32, 4, auth_data);
414         }
415
416         /* nt challenge response fields */
417         u32 = htole32((NTChallengeResponse_len<<16)|
418                       NTChallengeResponse_len);
419         encoder(&u32, 4, auth_data);
420         u32 = 0;
421         encoder(&u32, 4, auth_data);
422
423         /* domain name fields */
424         if (!anonymous && auth_data->domain) {
425                 ucs2_domain = utf8_to_ucs2(auth_data->domain);
426                 if (ucs2_domain == NULL) {
427                         goto finished;
428                 }
429                 u32 = ucs2_domain->len * 2;
430                 u32 = htole32((u32 << 16) | u32);
431                 encoder(&u32, 4, auth_data);
432                 u32 = 0;
433                 encoder(&u32, 4, auth_data);
434         } else {
435                 u32 = 0;
436                 encoder(&u32, 4, auth_data);
437                 encoder(&u32, 4, auth_data);
438         }
439
440         /* user name fields */
441         if (!anonymous) {
442                 ucs2_user = utf8_to_ucs2(auth_data->user);
443                 if (ucs2_user == NULL) {
444                         goto finished;
445                 }
446                 u32 = ucs2_user->len * 2;
447                 u32 = htole32((u32 << 16) | u32);
448                 encoder(&u32, 4, auth_data);
449                 u32 = 0;
450                 encoder(&u32, 4, auth_data);
451         } else {
452                 u32 = 0;
453                 encoder(&u32, 4, auth_data);
454                 encoder(&u32, 4, auth_data);
455         }
456
457         /* workstation name fields */
458         if (!anonymous && auth_data->workstation) {
459                 ucs2_workstation = utf8_to_ucs2(auth_data->workstation);
460                 if (ucs2_workstation == NULL) {
461                         goto finished;
462                 }
463                 u32 = ucs2_workstation->len * 2;
464                 u32 = htole32((u32 << 16) | u32);
465                 encoder(&u32, 4, auth_data);
466                 u32 = 0;
467                 encoder(&u32, 4, auth_data);
468         } else {
469                 u32 = 0;
470                 encoder(&u32, 4, auth_data);
471                 encoder(&u32, 4, auth_data);
472         }
473
474         /* encrypted random session key */
475         u32 = 0;
476         encoder(&u32, 4, auth_data);
477         encoder(&u32, 4, auth_data);
478
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;
487         if (anonymous)
488                 u32 |= NTLMSSP_NEGOTIATE_ANONYMOUS;
489         if (smb2->seal)
490                 u32 |= NTLMSSP_NEGOTIATE_SEAL;
491         u32 = htole32(u32);
492         encoder(&u32, 4, auth_data);
493
494         if (!anonymous) {
495                 /* append domain */
496                 u32 = htole32(auth_data->len);
497                 memcpy(&auth_data->buf[32], &u32, 4);
498                 if (ucs2_domain) {
499                         encoder(ucs2_domain->val, ucs2_domain->len * 2,
500                                 auth_data);
501                 }
502
503                 /* append user */
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);
507
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);
514                 }
515
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);
521
522                 /* append NTChallengeResponse */
523                 u32 = htole32(auth_data->len);
524                 memcpy(&auth_data->buf[24], &u32, 4);
525                 encoder(NTChallengeResponse_buf, NTChallengeResponse_len,
526                         auth_data);
527         }
528
529         ret = 0;
530 finished:
531         free(ucs2_domain);
532         free(ucs2_user);
533         free(ucs2_workstation);
534         free(NTChallengeResponse_buf);
535
536         return ret;
537 }
538
539 int
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)
544 {
545         free(auth_data->buf);
546         auth_data->buf = NULL;
547         auth_data->len = 0;
548         auth_data->allocated = 0;
549
550         if (input_buf == NULL) {
551                 ntlm_negotiate_message(smb2, auth_data);
552         } else {
553                 if (ntlm_challenge_message(auth_data, input_buf,
554                                            input_len) < 0) {
555                         return -1;
556                 }
557                 if (encode_ntlm_auth(smb2, t, auth_data,
558                                      (char *)&auth_data->ntlm_buf[24]) < 0) {
559                         return -1;
560                 }
561         }
562
563         *output_buf = auth_data->buf;
564         *output_len = auth_data->len;
565
566         return 0;
567 }
568
569 int
570 ntlmssp_get_session_key(struct auth_data *auth,
571                         uint8_t **key,
572                         uint8_t *key_size)
573 {
574         uint8_t *mkey = NULL;
575
576         if (auth == NULL || key == NULL || key_size == NULL) {
577                 return -1;
578         }
579
580         mkey = (uint8_t *) malloc(SMB2_KEY_SIZE);
581         if (mkey == NULL) {
582                 return -1;
583         }
584         memcpy(mkey, auth->exported_session_key, SMB2_KEY_SIZE);
585
586         *key = mkey;
587         *key_size = SMB2_KEY_SIZE;
588
589         return 0;
590 }