CVE-2016-2110: libcli/auth: pass server_timestamp to SMBNTLMv2encrypt_hash()
[samba.git] / libcli / auth / smbencrypt.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB parameters and setup
4    Copyright (C) Andrew Tridgell 1992-1998
5    Modified by Jeremy Allison 1995.
6    Copyright (C) Jeremy Allison 1995-2000.
7    Copyright (C) Luke Kennethc Casson Leighton 1996-2000.
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "system/time.h"
26 #include "../libcli/auth/msrpc_parse.h"
27 #include "../lib/crypto/crypto.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../librpc/gen_ndr/ntlmssp.h"
30
31 void SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24])
32 {
33         uint8_t p21[21];
34
35         memset(p21,'\0',21);
36         memcpy(p21, lm_hash, 16);
37
38         SMBOWFencrypt(p21, c8, p24);
39
40 #ifdef DEBUG_PASSWORD
41         DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n"));
42         dump_data(100, p21, 16);
43         dump_data(100, c8, 8);
44         dump_data(100, p24, 24);
45 #endif
46 }
47
48 /*
49    This implements the X/Open SMB password encryption
50    It takes a password ('unix' string), a 8 byte "crypt key"
51    and puts 24 bytes of encrypted password into p24
52
53    Returns False if password must have been truncated to create LM hash
54 */
55
56 bool SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
57 {
58         bool ret;
59         uint8_t lm_hash[16];
60
61         ret = E_deshash(passwd, lm_hash);
62         SMBencrypt_hash(lm_hash, c8, p24);
63         return ret;
64 }
65
66 /**
67  * Creates the MD4 Hash of the users password in NT UNICODE.
68  * @param passwd password in 'unix' charset.
69  * @param p16 return password hashed with md4, caller allocated 16 byte buffer
70  */
71
72 bool E_md4hash(const char *passwd, uint8_t p16[16])
73 {
74         size_t len;
75         smb_ucs2_t *wpwd;
76         bool ret;
77
78         ret = push_ucs2_talloc(NULL, &wpwd, passwd, &len);
79         if (!ret || len < 2) {
80                 /* We don't want to return fixed data, as most callers
81                  * don't check */
82                 mdfour(p16, (const uint8_t *)passwd, strlen(passwd));
83                 return false;
84         }
85
86         len -= 2;
87         mdfour(p16, (const uint8_t *)wpwd, len);
88
89         talloc_free(wpwd);
90         return true;
91 }
92
93 /**
94  * Creates the MD5 Hash of a combination of 16 byte salt and 16 byte NT hash.
95  * @param 16 byte salt.
96  * @param 16 byte NT hash.
97  * @param 16 byte return hashed with md5, caller allocated 16 byte buffer
98  */
99
100 void E_md5hash(const uint8_t salt[16], const uint8_t nthash[16], uint8_t hash_out[16])
101 {
102         MD5_CTX tctx;
103         MD5Init(&tctx);
104         MD5Update(&tctx, salt, 16);
105         MD5Update(&tctx, nthash, 16);
106         MD5Final(hash_out, &tctx);
107 }
108
109 /**
110  * Creates the DES forward-only Hash of the users password in DOS ASCII charset
111  * @param passwd password in 'unix' charset.
112  * @param p16 return password hashed with DES, caller allocated 16 byte buffer
113  * @return false if password was > 14 characters, and therefore may be incorrect, otherwise true
114  * @note p16 is filled in regardless
115  */
116
117 bool E_deshash(const char *passwd, uint8_t p16[16])
118 {
119         bool ret;
120         uint8_t dospwd[14];
121         TALLOC_CTX *frame = talloc_stackframe();
122
123         size_t converted_size;
124
125         char *tmpbuf;
126
127         ZERO_STRUCT(dospwd);
128
129         tmpbuf = strupper_talloc(frame, passwd);
130         if (tmpbuf == NULL) {
131                 /* Too many callers don't check this result, we need to fill in the buffer with something */
132                 strlcpy((char *)dospwd, passwd ? passwd : "", sizeof(dospwd));
133                 E_P16(dospwd, p16);
134                 talloc_free(frame);
135                 return false;
136         }
137
138         ZERO_STRUCT(dospwd);
139
140         ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size);
141         talloc_free(frame);
142
143         /* Only the first 14 chars are considered, password need not
144          * be null terminated.  We do this in the error and success
145          * case to avoid returning a fixed 'password' buffer, but
146          * callers should not use it when E_deshash returns false */
147
148         E_P16((const uint8_t *)dospwd, p16);
149
150         ZERO_STRUCT(dospwd);
151
152         return ret;
153 }
154
155 /**
156  * Creates the MD4 and DES (LM) Hash of the users password.
157  * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password.
158  * @param passwd password in 'unix' charset.
159  * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer
160  * @param p16 return password hashed with des, caller allocated 16 byte buffer
161  */
162
163 /* Does both the NT and LM owfs of a user's password */
164 void nt_lm_owf_gen(const char *pwd, uint8_t nt_p16[16], uint8_t p16[16])
165 {
166         /* Calculate the MD4 hash (NT compatible) of the password */
167         memset(nt_p16, '\0', 16);
168         E_md4hash(pwd, nt_p16);
169
170 #ifdef DEBUG_PASSWORD
171         DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
172         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
173         dump_data(100, nt_p16, 16);
174 #endif
175
176         E_deshash(pwd, (uint8_t *)p16);
177
178 #ifdef DEBUG_PASSWORD
179         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
180         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
181         dump_data(100, p16, 16);
182 #endif
183 }
184
185 /* Does both the NTLMv2 owfs of a user's password */
186 bool ntv2_owf_gen(const uint8_t owf[16],
187                   const char *user_in, const char *domain_in,
188                   uint8_t kr_buf[16])
189 {
190         smb_ucs2_t *user;
191         smb_ucs2_t *domain;
192         size_t user_byte_len;
193         size_t domain_byte_len;
194         bool ret;
195
196         HMACMD5Context ctx;
197         TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in);
198
199         if (!mem_ctx) {
200                 return false;
201         }
202
203         if (!user_in) {
204                 user_in = "";
205         }
206
207         if (!domain_in) {
208                 domain_in = "";
209         }
210
211         user_in = strupper_talloc(mem_ctx, user_in);
212         if (user_in == NULL) {
213                 talloc_free(mem_ctx);
214                 return false;
215         }
216
217         ret = push_ucs2_talloc(mem_ctx, &user, user_in, &user_byte_len );
218         if (!ret) {
219                 DEBUG(0, ("push_uss2_talloc() for user failed)\n"));
220                 talloc_free(mem_ctx);
221                 return false;
222         }
223
224         ret = push_ucs2_talloc(mem_ctx, &domain, domain_in, &domain_byte_len);
225         if (!ret) {
226                 DEBUG(0, ("push_ucs2_talloc() for domain failed\n"));
227                 talloc_free(mem_ctx);
228                 return false;
229         }
230
231         SMB_ASSERT(user_byte_len >= 2);
232         SMB_ASSERT(domain_byte_len >= 2);
233
234         /* We don't want null termination */
235         user_byte_len = user_byte_len - 2;
236         domain_byte_len = domain_byte_len - 2;
237
238         hmac_md5_init_limK_to_64(owf, 16, &ctx);
239         hmac_md5_update((uint8_t *)user, user_byte_len, &ctx);
240         hmac_md5_update((uint8_t *)domain, domain_byte_len, &ctx);
241         hmac_md5_final(kr_buf, &ctx);
242
243 #ifdef DEBUG_PASSWORD
244         DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
245         dump_data(100, (uint8_t *)user, user_byte_len);
246         dump_data(100, (uint8_t *)domain, domain_byte_len);
247         dump_data(100, owf, 16);
248         dump_data(100, kr_buf, 16);
249 #endif
250
251         talloc_free(mem_ctx);
252         return true;
253 }
254
255 /* Does the des encryption from the NT or LM MD4 hash. */
256 void SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24])
257 {
258         uint8_t p21[21];
259
260         ZERO_STRUCT(p21);
261
262         memcpy(p21, passwd, 16);
263         E_P24(p21, c8, p24);
264 }
265
266 /* Does the des encryption. */
267
268 void SMBNTencrypt_hash(const uint8_t nt_hash[16], const uint8_t *c8, uint8_t *p24)
269 {
270         uint8_t p21[21];
271
272         memset(p21,'\0',21);
273         memcpy(p21, nt_hash, 16);
274         SMBOWFencrypt(p21, c8, p24);
275
276 #ifdef DEBUG_PASSWORD
277         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
278         dump_data(100, p21, 16);
279         dump_data(100, c8, 8);
280         dump_data(100, p24, 24);
281 #endif
282 }
283
284 /* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
285
286 void SMBNTencrypt(const char *passwd, const uint8_t *c8, uint8_t *p24)
287 {
288         uint8_t nt_hash[16];
289         E_md4hash(passwd, nt_hash);
290         SMBNTencrypt_hash(nt_hash, c8, p24);
291 }
292
293
294 /* Does the md5 encryption from the Key Response for NTLMv2. */
295 void SMBOWFencrypt_ntv2(const uint8_t kr[16],
296                         const DATA_BLOB *srv_chal,
297                         const DATA_BLOB *smbcli_chal,
298                         uint8_t resp_buf[16])
299 {
300         HMACMD5Context ctx;
301
302         hmac_md5_init_limK_to_64(kr, 16, &ctx);
303         hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
304         hmac_md5_update(smbcli_chal->data, smbcli_chal->length, &ctx);
305         hmac_md5_final(resp_buf, &ctx);
306
307 #ifdef DEBUG_PASSWORD
308         DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, smbcli_chal, resp_buf\n"));
309         dump_data(100, srv_chal->data, srv_chal->length);
310         dump_data(100, smbcli_chal->data, smbcli_chal->length);
311         dump_data(100, resp_buf, 16);
312 #endif
313 }
314
315 void SMBsesskeygen_ntv2(const uint8_t kr[16],
316                         const uint8_t * nt_resp, uint8_t sess_key[16])
317 {
318         /* a very nice, 128 bit, variable session key */
319
320         HMACMD5Context ctx;
321
322         hmac_md5_init_limK_to_64(kr, 16, &ctx);
323         hmac_md5_update(nt_resp, 16, &ctx);
324         hmac_md5_final((uint8_t *)sess_key, &ctx);
325
326 #ifdef DEBUG_PASSWORD
327         DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
328         dump_data(100, sess_key, 16);
329 #endif
330 }
331
332 void SMBsesskeygen_ntv1(const uint8_t kr[16], uint8_t sess_key[16])
333 {
334         /* yes, this session key does not change - yes, this
335            is a problem - but it is 128 bits */
336
337         mdfour((uint8_t *)sess_key, kr, 16);
338
339 #ifdef DEBUG_PASSWORD
340         DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
341         dump_data(100, sess_key, 16);
342 #endif
343 }
344
345 void SMBsesskeygen_lm_sess_key(const uint8_t lm_hash[16],
346                                const uint8_t lm_resp[24], /* only uses 8 */
347                                uint8_t sess_key[16])
348 {
349         /* Calculate the LM session key (effective length 40 bits,
350            but changes with each session) */
351         uint8_t p24[24];
352         uint8_t partial_lm_hash[14];
353
354         memcpy(partial_lm_hash, lm_hash, 8);
355         memset(partial_lm_hash + 8, 0xbd, 6);
356
357         des_crypt56(p24,   lm_resp, partial_lm_hash,     1);
358         des_crypt56(p24+8, lm_resp, partial_lm_hash + 7, 1);
359
360         memcpy(sess_key, p24, 16);
361
362 #ifdef DEBUG_PASSWORD
363         DEBUG(100, ("SMBsesskeygen_lm_sess_key: \n"));
364         dump_data(100, sess_key, 16);
365 #endif
366 }
367
368 DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
369                                      const char *hostname,
370                                      const char *domain)
371 {
372         DATA_BLOB names_blob = data_blob_talloc(mem_ctx, NULL, 0);
373
374         /* Deliberately ignore return here.. */
375         if (hostname != NULL) {
376                 (void)msrpc_gen(mem_ctx, &names_blob,
377                           "aaa",
378                           MsvAvNbDomainName, domain,
379                           MsvAvNbComputerName, hostname,
380                           MsvAvEOL, "");
381         } else {
382                 (void)msrpc_gen(mem_ctx, &names_blob,
383                           "aa",
384                           MsvAvNbDomainName, domain,
385                           MsvAvEOL, "");
386         }
387         return names_blob;
388 }
389
390 static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx,
391                                              NTTIME nttime,
392                                              const DATA_BLOB *names_blob)
393 {
394         uint8_t client_chal[8];
395         DATA_BLOB response = data_blob(NULL, 0);
396         uint8_t long_date[8];
397
398         generate_random_buffer(client_chal, sizeof(client_chal));
399
400         push_nttime(long_date, 0, nttime);
401
402         /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */
403
404         /* Deliberately ignore return here.. */
405         (void)msrpc_gen(mem_ctx, &response, "ddbbdb",
406                   0x00000101,     /* Header  */
407                   0,              /* 'Reserved'  */
408                   long_date, 8,   /* Timestamp */
409                   client_chal, 8, /* client challenge */
410                   0,              /* Unknown */
411                   names_blob->data, names_blob->length);        /* End of name list */
412
413         return response;
414 }
415
416 static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
417                                           const uint8_t ntlm_v2_hash[16],
418                                           const DATA_BLOB *server_chal,
419                                           NTTIME nttime,
420                                           const DATA_BLOB *names_blob)
421 {
422         uint8_t ntlmv2_response[16];
423         DATA_BLOB ntlmv2_client_data;
424         DATA_BLOB final_response;
425
426         TALLOC_CTX *mem_ctx = talloc_named(out_mem_ctx, 0,
427                                            "NTLMv2_generate_response internal context");
428
429         if (!mem_ctx) {
430                 return data_blob(NULL, 0);
431         }
432
433         /* NTLMv2 */
434         /* generate some data to pass into the response function - including
435            the hostname and domain name of the server */
436         ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, nttime, names_blob);
437
438         /* Given that data, and the challenge from the server, generate a response */
439         SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response);
440
441         final_response = data_blob_talloc(out_mem_ctx, NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
442
443         memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
444
445         memcpy(final_response.data+sizeof(ntlmv2_response),
446                ntlmv2_client_data.data, ntlmv2_client_data.length);
447
448         talloc_free(mem_ctx);
449
450         return final_response;
451 }
452
453 static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx,
454                                         const uint8_t ntlm_v2_hash[16],
455                                         const DATA_BLOB *server_chal)
456 {
457         uint8_t lmv2_response[16];
458         DATA_BLOB lmv2_client_data = data_blob_talloc(mem_ctx, NULL, 8);
459         DATA_BLOB final_response = data_blob_talloc(mem_ctx, NULL,24);
460
461         /* LMv2 */
462         /* client-supplied random data */
463         generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length);
464
465         /* Given that data, and the challenge from the server, generate a response */
466         SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
467         memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
468
469         /* after the first 16 bytes is the random data we generated above,
470            so the server can verify us with it */
471         memcpy(final_response.data+sizeof(lmv2_response),
472                lmv2_client_data.data, lmv2_client_data.length);
473
474         data_blob_free(&lmv2_client_data);
475
476         return final_response;
477 }
478
479 bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
480                            const char *user, const char *domain, const uint8_t nt_hash[16],
481                            const DATA_BLOB *server_chal,
482                            const NTTIME *server_timestamp,
483                            const DATA_BLOB *names_blob,
484                            DATA_BLOB *lm_response, DATA_BLOB *nt_response,
485                            DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
486 {
487         uint8_t ntlm_v2_hash[16];
488
489         /* We don't use the NT# directly.  Instead we use it mashed up with
490            the username and domain.
491            This prevents username swapping during the auth exchange
492         */
493         if (!ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash)) {
494                 return false;
495         }
496
497         if (nt_response) {
498                 const NTTIME *nttime = server_timestamp;
499                 NTTIME _now = 0;
500
501                 if (nttime == NULL) {
502                         struct timeval tv_now = timeval_current();
503                         _now = timeval_to_nttime(&tv_now);
504                         nttime = &_now;
505                 }
506
507                 *nt_response = NTLMv2_generate_response(mem_ctx,
508                                                         ntlm_v2_hash,
509                                                         server_chal,
510                                                         *nttime,
511                                                         names_blob);
512                 if (user_session_key) {
513                         *user_session_key = data_blob_talloc(mem_ctx, NULL, 16);
514
515                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
516                         /* use only the first 16 bytes of nt_response for session key */
517                         SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, user_session_key->data);
518                 }
519         }
520
521         /* LMv2 */
522
523         if (lm_response) {
524                 if (server_timestamp != NULL) {
525                         *lm_response = data_blob_talloc_zero(mem_ctx, 24);
526                 } else {
527                         *lm_response = LMv2_generate_response(mem_ctx,
528                                                               ntlm_v2_hash,
529                                                               server_chal);
530                 }
531                 if (lm_session_key) {
532                         *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
533
534                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
535                         /* use only the first 16 bytes of lm_response for session key */
536                         SMBsesskeygen_ntv2(ntlm_v2_hash, lm_response->data, lm_session_key->data);
537                 }
538         }
539
540         return true;
541 }
542
543 bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
544                       const char *user, const char *domain,
545                       const char *password,
546                       const DATA_BLOB *server_chal,
547                       const DATA_BLOB *names_blob,
548                       DATA_BLOB *lm_response, DATA_BLOB *nt_response,
549                       DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
550 {
551         uint8_t nt_hash[16];
552         E_md4hash(password, nt_hash);
553
554         return SMBNTLMv2encrypt_hash(mem_ctx,
555                                      user, domain, nt_hash,
556                                      server_chal, NULL, names_blob,
557                                      lm_response, nt_response, lm_session_key, user_session_key);
558 }
559
560 /***********************************************************
561  encode a password buffer with a unicode password.  The buffer
562  is filled with random data to make it harder to attack.
563 ************************************************************/
564 bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags)
565 {
566         uint8_t new_pw[512];
567         ssize_t new_pw_len;
568
569         /* the incoming buffer can be any alignment. */
570         string_flags |= STR_NOALIGN;
571
572         new_pw_len = push_string(new_pw,
573                                  password,
574                                  sizeof(new_pw), string_flags);
575         if (new_pw_len == -1) {
576                 return false;
577         }
578
579         memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
580
581         generate_random_buffer(buffer, 512 - new_pw_len);
582
583         /*
584          * The length of the new password is in the last 4 bytes of
585          * the data buffer.
586          */
587         SIVAL(buffer, 512, new_pw_len);
588         ZERO_STRUCT(new_pw);
589         return true;
590 }
591
592
593 /***********************************************************
594  decode a password buffer
595  *new_pw_len is the length in bytes of the possibly mulitbyte
596  returned password including termination.
597 ************************************************************/
598
599 bool decode_pw_buffer(TALLOC_CTX *ctx,
600                       uint8_t in_buffer[516],
601                       char **pp_new_pwrd,
602                       size_t *new_pw_len,
603                       charset_t string_charset)
604 {
605         int byte_len=0;
606
607         *pp_new_pwrd = NULL;
608         *new_pw_len = 0;
609
610         /*
611           Warning !!! : This function is called from some rpc call.
612           The password IN the buffer may be a UNICODE string.
613           The password IN new_pwrd is an ASCII string
614           If you reuse that code somewhere else check first.
615         */
616
617         /* The length of the new password is in the last 4 bytes of the data buffer. */
618
619         byte_len = IVAL(in_buffer, 512);
620
621 #ifdef DEBUG_PASSWORD
622         dump_data(100, in_buffer, 516);
623 #endif
624
625         /* Password cannot be longer than the size of the password buffer */
626         if ( (byte_len < 0) || (byte_len > 512)) {
627                 DEBUG(0, ("decode_pw_buffer: incorrect password length (%d).\n", byte_len));
628                 DEBUG(0, ("decode_pw_buffer: check that 'encrypt passwords = yes'\n"));
629                 return false;
630         }
631
632         /* decode into the return buffer. */
633         if (!convert_string_talloc(ctx, string_charset, CH_UNIX,
634                                    &in_buffer[512 - byte_len],
635                                    byte_len,
636                                    (void *)pp_new_pwrd,
637                                    new_pw_len)) {
638                 DEBUG(0, ("decode_pw_buffer: failed to convert incoming password\n"));
639                 return false;
640         }
641
642 #ifdef DEBUG_PASSWORD
643         DEBUG(100,("decode_pw_buffer: new_pwrd: "));
644         dump_data(100, (uint8_t *)*pp_new_pwrd, *new_pw_len);
645         DEBUG(100,("multibyte len:%lu\n", (unsigned long int)*new_pw_len));
646         DEBUG(100,("original char len:%d\n", byte_len/2));
647 #endif
648
649         return true;
650 }
651
652 /***********************************************************
653  Decode an arc4 encrypted password change buffer.
654 ************************************************************/
655
656 void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key)
657 {
658         MD5_CTX tctx;
659         unsigned char key_out[16];
660
661         /* Confounder is last 16 bytes. */
662
663         MD5Init(&tctx);
664         MD5Update(&tctx, &pw_buf[516], 16);
665         MD5Update(&tctx, psession_key->data, psession_key->length);
666         MD5Final(key_out, &tctx);
667         /* arc4 with key_out. */
668         arcfour_crypt(pw_buf, key_out, 516);
669 }
670
671 /***********************************************************
672  encode a password buffer with an already unicode password.  The
673  rest of the buffer is filled with random data to make it harder to attack.
674 ************************************************************/
675 bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password)
676 {
677         if (password->length > 512) {
678                 return false;
679         }
680
681         memcpy(&buffer[512 - password->length], password->data, password->length);
682
683         generate_random_buffer(buffer, 512 - password->length);
684
685         /*
686          * The length of the new password is in the last 4 bytes of
687          * the data buffer.
688          */
689         SIVAL(buffer, 512, password->length);
690         return true;
691 }
692
693 /***********************************************************
694  decode a password buffer
695  *new_pw_size is the length in bytes of the extracted unicode password
696 ************************************************************/
697 bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx,
698                             uint8_t in_buffer[516], DATA_BLOB *new_pass)
699 {
700         int byte_len=0;
701
702         /* The length of the new password is in the last 4 bytes of the data buffer. */
703
704         byte_len = IVAL(in_buffer, 512);
705
706 #ifdef DEBUG_PASSWORD
707         dump_data(100, in_buffer, 516);
708 #endif
709
710         /* Password cannot be longer than the size of the password buffer */
711         if ( (byte_len < 0) || (byte_len > 512)) {
712                 return false;
713         }
714
715         *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
716
717         if (!new_pass->data) {
718                 return false;
719         }
720
721         return true;
722 }
723
724
725 /* encode a wkssvc_PasswordBuffer:
726  *
727  * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of
728  * 16byte), confounder in front of the 516 byte buffer (instead of after that
729  * buffer), calling MD5Update() first with session_key and then with confounder
730  * (vice versa in samr) - Guenther */
731
732 void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
733                                         const char *pwd,
734                                         DATA_BLOB *session_key,
735                                         struct wkssvc_PasswordBuffer **pwd_buf)
736 {
737         uint8_t buffer[516];
738         MD5_CTX ctx;
739         struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
740         DATA_BLOB confounded_session_key;
741         int confounder_len = 8;
742         uint8_t confounder[8];
743
744         my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
745         if (!my_pwd_buf) {
746                 return;
747         }
748
749         confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
750
751         encode_pw_buffer(buffer, pwd, STR_UNICODE);
752
753         generate_random_buffer((uint8_t *)confounder, confounder_len);
754
755         MD5Init(&ctx);
756         MD5Update(&ctx, session_key->data, session_key->length);
757         MD5Update(&ctx, confounder, confounder_len);
758         MD5Final(confounded_session_key.data, &ctx);
759
760         arcfour_crypt_blob(buffer, 516, &confounded_session_key);
761
762         memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
763         memcpy(&my_pwd_buf->data[8], buffer, 516);
764
765         data_blob_free(&confounded_session_key);
766
767         *pwd_buf = my_pwd_buf;
768 }
769
770 WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
771                                           struct wkssvc_PasswordBuffer *pwd_buf,
772                                           DATA_BLOB *session_key,
773                                           char **pwd)
774 {
775         uint8_t buffer[516];
776         MD5_CTX ctx;
777         size_t pwd_len;
778
779         DATA_BLOB confounded_session_key;
780
781         int confounder_len = 8;
782         uint8_t confounder[8];
783
784         *pwd = NULL;
785
786         if (!pwd_buf) {
787                 return WERR_INVALID_PASSWORD;
788         }
789
790         if (session_key->length != 16) {
791                 DEBUG(10,("invalid session key\n"));
792                 return WERR_INVALID_PASSWORD;
793         }
794
795         confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
796
797         memcpy(&confounder, &pwd_buf->data[0], confounder_len);
798         memcpy(&buffer, &pwd_buf->data[8], 516);
799
800         MD5Init(&ctx);
801         MD5Update(&ctx, session_key->data, session_key->length);
802         MD5Update(&ctx, confounder, confounder_len);
803         MD5Final(confounded_session_key.data, &ctx);
804
805         arcfour_crypt_blob(buffer, 516, &confounded_session_key);
806
807         if (!decode_pw_buffer(mem_ctx, buffer, pwd, &pwd_len, CH_UTF16)) {
808                 data_blob_free(&confounded_session_key);
809                 return WERR_INVALID_PASSWORD;
810         }
811
812         data_blob_free(&confounded_session_key);
813
814         return WERR_OK;
815 }
816