cbb2eb5c9c226559e0844c5dc5dd0c6243640641
[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         struct MD5Context 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
122         size_t converted_size;
123
124         char *tmpbuf;
125
126         ZERO_STRUCT(dospwd);
127
128         tmpbuf = strupper_talloc(NULL, passwd);
129         if (tmpbuf == NULL) {
130                 /* Too many callers don't check this result, we need to fill in the buffer with something */
131                 safe_strcpy((char *)dospwd, passwd, sizeof(dospwd)-1);
132                 E_P16(dospwd, p16);
133                 return false;
134         }
135
136         ZERO_STRUCT(dospwd);
137
138         ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size);
139         talloc_free(tmpbuf);
140
141         /* Only the first 14 chars are considered, password need not
142          * be null terminated.  We do this in the error and success
143          * case to avoid returning a fixed 'password' buffer, but
144          * callers should not use it when E_deshash returns false */
145
146         E_P16((const uint8_t *)dospwd, p16);
147
148         ZERO_STRUCT(dospwd);
149
150         return ret;
151 }
152
153 /**
154  * Creates the MD4 and DES (LM) Hash of the users password.
155  * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password.
156  * @param passwd password in 'unix' charset.
157  * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer
158  * @param p16 return password hashed with des, caller allocated 16 byte buffer
159  */
160
161 /* Does both the NT and LM owfs of a user's password */
162 void nt_lm_owf_gen(const char *pwd, uint8_t nt_p16[16], uint8_t p16[16])
163 {
164         /* Calculate the MD4 hash (NT compatible) of the password */
165         memset(nt_p16, '\0', 16);
166         E_md4hash(pwd, nt_p16);
167
168 #ifdef DEBUG_PASSWORD
169         DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
170         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
171         dump_data(100, nt_p16, 16);
172 #endif
173
174         E_deshash(pwd, (uint8_t *)p16);
175
176 #ifdef DEBUG_PASSWORD
177         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
178         dump_data(120, (const uint8_t *)pwd, strlen(pwd));
179         dump_data(100, p16, 16);
180 #endif
181 }
182
183 /* Does both the NTLMv2 owfs of a user's password */
184 bool ntv2_owf_gen(const uint8_t owf[16],
185                   const char *user_in, const char *domain_in,
186                   bool upper_case_domain, /* Transform the domain into UPPER case */
187                   uint8_t kr_buf[16])
188 {
189         smb_ucs2_t *user;
190         smb_ucs2_t *domain;
191         size_t user_byte_len;
192         size_t domain_byte_len;
193         bool ret;
194
195         HMACMD5Context ctx;
196         TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in);
197
198         if (!mem_ctx) {
199                 return false;
200         }
201
202         if (!user_in) {
203                 user_in = "";
204         }
205
206         if (!domain_in) {
207                 domain_in = "";
208         }
209
210         user_in = strupper_talloc(mem_ctx, user_in);
211         if (user_in == NULL) {
212                 talloc_free(mem_ctx);
213                 return false;
214         }
215
216         if (upper_case_domain) {
217                 domain_in = strupper_talloc(mem_ctx, domain_in);
218                 if (domain_in == NULL) {
219                         talloc_free(mem_ctx);
220                         return false;
221                 }
222         }
223
224         ret = push_ucs2_talloc(mem_ctx, &user, user_in, &user_byte_len );
225         if (!ret) {
226                 DEBUG(0, ("push_uss2_talloc() for user failed)\n"));
227                 talloc_free(mem_ctx);
228                 return false;
229         }
230
231         ret = push_ucs2_talloc(mem_ctx, &domain, domain_in, &domain_byte_len);
232         if (!ret) {
233                 DEBUG(0, ("push_ucs2_talloc() for domain failed\n"));
234                 talloc_free(mem_ctx);
235                 return false;
236         }
237
238         SMB_ASSERT(user_byte_len >= 2);
239         SMB_ASSERT(domain_byte_len >= 2);
240
241         /* We don't want null termination */
242         user_byte_len = user_byte_len - 2;
243         domain_byte_len = domain_byte_len - 2;
244
245         hmac_md5_init_limK_to_64(owf, 16, &ctx);
246         hmac_md5_update((uint8_t *)user, user_byte_len, &ctx);
247         hmac_md5_update((uint8_t *)domain, domain_byte_len, &ctx);
248         hmac_md5_final(kr_buf, &ctx);
249
250 #ifdef DEBUG_PASSWORD
251         DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
252         dump_data(100, (uint8_t *)user, user_byte_len);
253         dump_data(100, (uint8_t *)domain, domain_byte_len);
254         dump_data(100, owf, 16);
255         dump_data(100, kr_buf, 16);
256 #endif
257
258         talloc_free(mem_ctx);
259         return true;
260 }
261
262 /* Does the des encryption from the NT or LM MD4 hash. */
263 void SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24])
264 {
265         uint8_t p21[21];
266
267         ZERO_STRUCT(p21);
268
269         memcpy(p21, passwd, 16);
270         E_P24(p21, c8, p24);
271 }
272
273 /* Does the des encryption. */
274
275 void SMBNTencrypt_hash(const uint8_t nt_hash[16], uint8_t *c8, uint8_t *p24)
276 {
277         uint8_t p21[21];
278
279         memset(p21,'\0',21);
280         memcpy(p21, nt_hash, 16);
281         SMBOWFencrypt(p21, c8, p24);
282
283 #ifdef DEBUG_PASSWORD
284         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
285         dump_data(100, p21, 16);
286         dump_data(100, c8, 8);
287         dump_data(100, p24, 24);
288 #endif
289 }
290
291 /* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
292
293 void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24)
294 {
295         uint8_t nt_hash[16];
296         E_md4hash(passwd, nt_hash);
297         SMBNTencrypt_hash(nt_hash, c8, p24);
298 }
299
300
301 /* Does the md5 encryption from the Key Response for NTLMv2. */
302 void SMBOWFencrypt_ntv2(const uint8_t kr[16],
303                         const DATA_BLOB *srv_chal,
304                         const DATA_BLOB *smbcli_chal,
305                         uint8_t resp_buf[16])
306 {
307         HMACMD5Context ctx;
308
309         hmac_md5_init_limK_to_64(kr, 16, &ctx);
310         hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
311         hmac_md5_update(smbcli_chal->data, smbcli_chal->length, &ctx);
312         hmac_md5_final(resp_buf, &ctx);
313
314 #ifdef DEBUG_PASSWORD
315         DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, smbcli_chal, resp_buf\n"));
316         dump_data(100, srv_chal->data, srv_chal->length);
317         dump_data(100, smbcli_chal->data, smbcli_chal->length);
318         dump_data(100, resp_buf, 16);
319 #endif
320 }
321
322 void SMBsesskeygen_ntv2(const uint8_t kr[16],
323                         const uint8_t * nt_resp, uint8_t sess_key[16])
324 {
325         /* a very nice, 128 bit, variable session key */
326
327         HMACMD5Context ctx;
328
329         hmac_md5_init_limK_to_64(kr, 16, &ctx);
330         hmac_md5_update(nt_resp, 16, &ctx);
331         hmac_md5_final((uint8_t *)sess_key, &ctx);
332
333 #ifdef DEBUG_PASSWORD
334         DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
335         dump_data(100, sess_key, 16);
336 #endif
337 }
338
339 void SMBsesskeygen_ntv1(const uint8_t kr[16], uint8_t sess_key[16])
340 {
341         /* yes, this session key does not change - yes, this
342            is a problem - but it is 128 bits */
343
344         mdfour((uint8_t *)sess_key, kr, 16);
345
346 #ifdef DEBUG_PASSWORD
347         DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
348         dump_data(100, sess_key, 16);
349 #endif
350 }
351
352 void SMBsesskeygen_lm_sess_key(const uint8_t lm_hash[16],
353                                const uint8_t lm_resp[24], /* only uses 8 */
354                                uint8_t sess_key[16])
355 {
356         /* Calculate the LM session key (effective length 40 bits,
357            but changes with each session) */
358         uint8_t p24[24];
359         uint8_t partial_lm_hash[14];
360
361         memcpy(partial_lm_hash, lm_hash, 8);
362         memset(partial_lm_hash + 8, 0xbd, 6);
363
364         des_crypt56(p24,   lm_resp, partial_lm_hash,     1);
365         des_crypt56(p24+8, lm_resp, partial_lm_hash + 7, 1);
366
367         memcpy(sess_key, p24, 16);
368
369 #ifdef DEBUG_PASSWORD
370         DEBUG(100, ("SMBsesskeygen_lm_sess_key: \n"));
371         dump_data(100, sess_key, 16);
372 #endif
373 }
374
375 DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
376                                      const char *hostname,
377                                      const char *domain)
378 {
379         DATA_BLOB names_blob = data_blob_talloc(mem_ctx, NULL, 0);
380
381         /* Deliberately ignore return here.. */
382         (void)msrpc_gen(mem_ctx, &names_blob,
383                   "aaa",
384                   MsvAvNbDomainName, domain,
385                   MsvAvNbComputerName, hostname,
386                   MsvAvEOL, "");
387         return names_blob;
388 }
389
390 static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob)
391 {
392         uint8_t client_chal[8];
393         DATA_BLOB response = data_blob(NULL, 0);
394         uint8_t long_date[8];
395         NTTIME nttime;
396
397         unix_to_nt_time(&nttime, time(NULL));
398
399         generate_random_buffer(client_chal, sizeof(client_chal));
400
401         push_nttime(long_date, 0, nttime);
402
403         /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */
404
405         /* Deliberately ignore return here.. */
406         (void)msrpc_gen(mem_ctx, &response, "ddbbdb",
407                   0x00000101,     /* Header  */
408                   0,              /* 'Reserved'  */
409                   long_date, 8,   /* Timestamp */
410                   client_chal, 8, /* client challenge */
411                   0,              /* Unknown */
412                   names_blob->data, names_blob->length);        /* End of name list */
413
414         return response;
415 }
416
417 static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
418                                           const uint8_t ntlm_v2_hash[16],
419                                           const DATA_BLOB *server_chal,
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, 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 DATA_BLOB *names_blob,
483                            DATA_BLOB *lm_response, DATA_BLOB *nt_response,
484                            DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
485 {
486         uint8_t ntlm_v2_hash[16];
487
488         /* We don't use the NT# directly.  Instead we use it mashed up with
489            the username and domain.
490            This prevents username swapping during the auth exchange
491         */
492         if (!ntv2_owf_gen(nt_hash, user, domain, true, ntlm_v2_hash)) {
493                 return false;
494         }
495
496         if (nt_response) {
497                 *nt_response = NTLMv2_generate_response(mem_ctx,
498                                                         ntlm_v2_hash, server_chal,
499                                                         names_blob);
500                 if (user_session_key) {
501                         *user_session_key = data_blob_talloc(mem_ctx, NULL, 16);
502
503                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
504                         /* use only the first 16 bytes of nt_response for session key */
505                         SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, user_session_key->data);
506                 }
507         }
508
509         /* LMv2 */
510
511         if (lm_response) {
512                 *lm_response = LMv2_generate_response(mem_ctx,
513                                                       ntlm_v2_hash, server_chal);
514                 if (lm_session_key) {
515                         *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
516
517                         /* The NTLMv2 calculations also provide a session key, for signing etc later */
518                         /* use only the first 16 bytes of lm_response for session key */
519                         SMBsesskeygen_ntv2(ntlm_v2_hash, lm_response->data, lm_session_key->data);
520                 }
521         }
522
523         return true;
524 }
525
526 bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
527                       const char *user, const char *domain,
528                       const char *password,
529                       const DATA_BLOB *server_chal,
530                       const DATA_BLOB *names_blob,
531                       DATA_BLOB *lm_response, DATA_BLOB *nt_response,
532                       DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
533 {
534         uint8_t nt_hash[16];
535         E_md4hash(password, nt_hash);
536
537         return SMBNTLMv2encrypt_hash(mem_ctx,
538                                      user, domain, nt_hash, server_chal, names_blob,
539                                      lm_response, nt_response, lm_session_key, user_session_key);
540 }
541
542 /***********************************************************
543  encode a password buffer with a unicode password.  The buffer
544  is filled with random data to make it harder to attack.
545 ************************************************************/
546 bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags)
547 {
548         uint8_t new_pw[512];
549         ssize_t new_pw_len;
550
551         /* the incoming buffer can be any alignment. */
552         string_flags |= STR_NOALIGN;
553
554         new_pw_len = push_string(new_pw,
555                                  password,
556                                  sizeof(new_pw), string_flags);
557         if (new_pw_len == -1) {
558                 return false;
559         }
560
561         memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
562
563         generate_random_buffer(buffer, 512 - new_pw_len);
564
565         /*
566          * The length of the new password is in the last 4 bytes of
567          * the data buffer.
568          */
569         SIVAL(buffer, 512, new_pw_len);
570         ZERO_STRUCT(new_pw);
571         return true;
572 }
573
574
575 /***********************************************************
576  decode a password buffer
577  *new_pw_len is the length in bytes of the possibly mulitbyte
578  returned password including termination.
579 ************************************************************/
580
581 bool decode_pw_buffer(TALLOC_CTX *ctx,
582                       uint8_t in_buffer[516],
583                       char **pp_new_pwrd,
584                       size_t *new_pw_len,
585                       charset_t string_charset)
586 {
587         int byte_len=0;
588
589         *pp_new_pwrd = NULL;
590         *new_pw_len = 0;
591
592         /*
593           Warning !!! : This function is called from some rpc call.
594           The password IN the buffer may be a UNICODE string.
595           The password IN new_pwrd is an ASCII string
596           If you reuse that code somewhere else check first.
597         */
598
599         /* The length of the new password is in the last 4 bytes of the data buffer. */
600
601         byte_len = IVAL(in_buffer, 512);
602
603 #ifdef DEBUG_PASSWORD
604         dump_data(100, in_buffer, 516);
605 #endif
606
607         /* Password cannot be longer than the size of the password buffer */
608         if ( (byte_len < 0) || (byte_len > 512)) {
609                 DEBUG(0, ("decode_pw_buffer: incorrect password length (%d).\n", byte_len));
610                 DEBUG(0, ("decode_pw_buffer: check that 'encrypt passwords = yes'\n"));
611                 return false;
612         }
613
614         /* decode into the return buffer. */
615         if (!convert_string_talloc(ctx, string_charset, CH_UNIX,
616                                    &in_buffer[512 - byte_len],
617                                    byte_len,
618                                    (void *)pp_new_pwrd,
619                                    new_pw_len)) {
620                 DEBUG(0, ("decode_pw_buffer: failed to convert incoming password\n"));
621                 return false;
622         }
623
624 #ifdef DEBUG_PASSWORD
625         DEBUG(100,("decode_pw_buffer: new_pwrd: "));
626         dump_data(100, (uint8_t *)*pp_new_pwrd, *new_pw_len);
627         DEBUG(100,("multibyte len:%lu\n", (unsigned long int)*new_pw_len));
628         DEBUG(100,("original char len:%d\n", byte_len/2));
629 #endif
630
631         return true;
632 }
633
634 /***********************************************************
635  Decode an arc4 encrypted password change buffer.
636 ************************************************************/
637
638 void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key)
639 {
640         struct MD5Context tctx;
641         unsigned char key_out[16];
642
643         /* Confounder is last 16 bytes. */
644
645         MD5Init(&tctx);
646         MD5Update(&tctx, &pw_buf[516], 16);
647         MD5Update(&tctx, psession_key->data, psession_key->length);
648         MD5Final(key_out, &tctx);
649         /* arc4 with key_out. */
650         arcfour_crypt(pw_buf, key_out, 516);
651 }
652
653 /***********************************************************
654  encode a password buffer with an already unicode password.  The
655  rest of the buffer is filled with random data to make it harder to attack.
656 ************************************************************/
657 bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password)
658 {
659         if (password->length > 512) {
660                 return false;
661         }
662
663         memcpy(&buffer[512 - password->length], password->data, password->length);
664
665         generate_random_buffer(buffer, 512 - password->length);
666
667         /*
668          * The length of the new password is in the last 4 bytes of
669          * the data buffer.
670          */
671         SIVAL(buffer, 512, password->length);
672         return true;
673 }
674
675 /***********************************************************
676  decode a password buffer
677  *new_pw_size is the length in bytes of the extracted unicode password
678 ************************************************************/
679 bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx,
680                             uint8_t in_buffer[516], DATA_BLOB *new_pass)
681 {
682         int byte_len=0;
683
684         /* The length of the new password is in the last 4 bytes of the data buffer. */
685
686         byte_len = IVAL(in_buffer, 512);
687
688 #ifdef DEBUG_PASSWORD
689         dump_data(100, in_buffer, 516);
690 #endif
691
692         /* Password cannot be longer than the size of the password buffer */
693         if ( (byte_len < 0) || (byte_len > 512)) {
694                 return false;
695         }
696
697         *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
698
699         if (!new_pass->data) {
700                 return false;
701         }
702
703         return true;
704 }
705
706
707 /* encode a wkssvc_PasswordBuffer:
708  *
709  * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of
710  * 16byte), confounder in front of the 516 byte buffer (instead of after that
711  * buffer), calling MD5Update() first with session_key and then with confounder
712  * (vice versa in samr) - Guenther */
713
714 void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
715                                         const char *pwd,
716                                         DATA_BLOB *session_key,
717                                         struct wkssvc_PasswordBuffer **pwd_buf)
718 {
719         uint8_t buffer[516];
720         struct MD5Context ctx;
721         struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
722         DATA_BLOB confounded_session_key;
723         int confounder_len = 8;
724         uint8_t confounder[8];
725
726         my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
727         if (!my_pwd_buf) {
728                 return;
729         }
730
731         confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
732
733         encode_pw_buffer(buffer, pwd, STR_UNICODE);
734
735         generate_random_buffer((uint8_t *)confounder, confounder_len);
736
737         MD5Init(&ctx);
738         MD5Update(&ctx, session_key->data, session_key->length);
739         MD5Update(&ctx, confounder, confounder_len);
740         MD5Final(confounded_session_key.data, &ctx);
741
742         arcfour_crypt_blob(buffer, 516, &confounded_session_key);
743
744         memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
745         memcpy(&my_pwd_buf->data[8], buffer, 516);
746
747         data_blob_free(&confounded_session_key);
748
749         *pwd_buf = my_pwd_buf;
750 }
751
752 WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
753                                           struct wkssvc_PasswordBuffer *pwd_buf,
754                                           DATA_BLOB *session_key,
755                                           char **pwd)
756 {
757         uint8_t buffer[516];
758         struct MD5Context ctx;
759         size_t pwd_len;
760
761         DATA_BLOB confounded_session_key;
762
763         int confounder_len = 8;
764         uint8_t confounder[8];
765
766         *pwd = NULL;
767
768         if (!pwd_buf) {
769                 return WERR_BAD_PASSWORD;
770         }
771
772         if (session_key->length != 16) {
773                 DEBUG(10,("invalid session key\n"));
774                 return WERR_BAD_PASSWORD;
775         }
776
777         confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
778
779         memcpy(&confounder, &pwd_buf->data[0], confounder_len);
780         memcpy(&buffer, &pwd_buf->data[8], 516);
781
782         MD5Init(&ctx);
783         MD5Update(&ctx, session_key->data, session_key->length);
784         MD5Update(&ctx, confounder, confounder_len);
785         MD5Final(confounded_session_key.data, &ctx);
786
787         arcfour_crypt_blob(buffer, 516, &confounded_session_key);
788
789         if (!decode_pw_buffer(mem_ctx, buffer, pwd, &pwd_len, CH_UTF16)) {
790                 data_blob_free(&confounded_session_key);
791                 return WERR_BAD_PASSWORD;
792         }
793
794         data_blob_free(&confounded_session_key);
795
796         return WERR_OK;
797 }
798