implement server-side generation of NTLMv2 session key. YESSS :-)
[samba.git] / source3 / libsmb / smbencrypt.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB parameters and setup
5    Copyright (C) Andrew Tridgell 1992-1998
6    Modified by Jeremy Allison 1995.
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 extern int DEBUGLEVEL;
26
27 #include "byteorder.h"
28
29 /*
30    This implements the X/Open SMB password encryption
31    It takes a password, a 8 byte "crypt key" and puts 24 bytes of 
32    encrypted password into p24 */
33 void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
34 {
35         uchar p21[21];
36
37         lm_owf_gen(passwd, p21);
38         SMBOWFencrypt(p21, c8, p24);
39
40 #ifdef DEBUG_PASSWORD
41         DEBUG(100,("SMBencrypt: 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 void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
49 {
50         uchar p21[21];
51  
52         memset(p21,'\0',21);
53  
54         nt_owf_gen(passwd, p21);    
55         SMBOWFencrypt(p21, c8, p24);
56
57 #ifdef DEBUG_PASSWORD
58         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
59         dump_data(100, p21, 16);
60         dump_data(100, c8, 8);
61         dump_data(100, p24, 24);
62 #endif
63 }
64
65 /* Routines for Windows NT MD4 Hash functions. */
66 static int _my_wcslen(int16 *str)
67 {
68         int len = 0;
69         while(*str++ != 0)
70                 len++;
71         return len;
72 }
73
74 /*
75  * Convert a string into an NT UNICODE string.
76  * Note that regardless of processor type 
77  * this must be in intel (little-endian)
78  * format.
79  */
80  
81 static int _my_mbstowcsupper(int16 *dst, const uchar *src, int len)
82 {
83         int i;
84         int16 val;
85  
86         for(i = 0; i < len; i++) {
87                 val = toupper(*src);
88                 SSVAL(dst,0,val);
89                 dst++;
90                 src++;
91                 if(val == 0)
92                         break;
93         }
94         return i;
95 }
96
97 static int _my_mbstowcs(int16 *dst, const uchar *src, int len)
98 {
99         int i;
100         int16 val;
101  
102         for(i = 0; i < len; i++) {
103                 val = *src;
104                 SSVAL(dst,0,val);
105                 dst++;
106                 src++;
107                 if(val == 0)
108                         break;
109         }
110         return i;
111 }
112
113 /* 
114  * Creates the MD4 Hash of the users password in NT UNICODE.
115  */
116  
117 void E_md4hash(uchar *passwd, uchar *p16)
118 {
119         int len;
120         int16 wpwd[129];
121         
122         /* Password cannot be longer than 128 characters */
123         len = strlen((char *)passwd);
124         if(len > 128)
125                 len = 128;
126         /* Password must be converted to NT unicode */
127         _my_mbstowcs(wpwd, passwd, len);
128         wpwd[len] = 0; /* Ensure string is null terminated */
129         /* Calculate length in bytes */
130         len = _my_wcslen(wpwd) * sizeof(int16);
131
132         mdfour(p16, (unsigned char *)wpwd, len);
133 }
134
135 /* Does the LM owf of a user's password */
136 void lm_owf_genW(const UNISTR2 *pwd, uchar p16[16])
137 {
138         char passwd[15];
139
140         memset(passwd,'\0',15);
141         if (pwd != NULL)
142         {
143                 unistr2_to_ascii( passwd, pwd, sizeof(passwd)-1);
144         }
145
146         /* Mangle the passwords into Lanman format */
147         passwd[14] = '\0';
148         strupper(passwd);
149
150         /* Calculate the SMB (lanman) hash functions of the password */
151
152         memset(p16, '\0', 16);
153         E_P16((uchar *) passwd, (uchar *)p16);
154
155 #ifdef DEBUG_PASSWORD
156         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
157         dump_data(120, passwd, strlen(passwd));
158         dump_data(100, p16, 16);
159 #endif
160         /* clear out local copy of user's password (just being paranoid). */
161         bzero(passwd, sizeof(passwd));
162 }
163
164 /* Does the LM owf of a user's password */
165 void lm_owf_gen(const char *pwd, uchar p16[16])
166 {
167         char passwd[15];
168
169         memset(passwd,'\0',15);
170         if (pwd != NULL)
171         {
172                 safe_strcpy( passwd, pwd, sizeof(passwd)-1);
173         }
174
175         /* Mangle the passwords into Lanman format */
176         passwd[14] = '\0';
177         strupper(passwd);
178
179         /* Calculate the SMB (lanman) hash functions of the password */
180
181         memset(p16, '\0', 16);
182         E_P16((uchar *) passwd, (uchar *)p16);
183
184 #ifdef DEBUG_PASSWORD
185         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
186         dump_data(120, passwd, strlen(passwd));
187         dump_data(100, p16, 16);
188 #endif
189         /* clear out local copy of user's password (just being paranoid). */
190         bzero(passwd, sizeof(passwd));
191 }
192
193 /* Does both the NT and LM owfs of a user's password */
194 void nt_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16])
195 {
196         UNISTR2 passwd;
197
198         memset(&passwd,'\0',sizeof(passwd));
199         if (pwd != NULL)
200         {
201                 copy_unistr2(&passwd, pwd);
202         }
203
204         /* Calculate the MD4 hash (NT compatible) of the password */
205         memset(nt_p16, '\0', 16);
206         mdfour(nt_p16, (unsigned char *)passwd.buffer, passwd.uni_str_len * 2);
207
208 #ifdef DEBUG_PASSWORD
209         DEBUG(100,("nt_owf_gen: pwd, nt#\n"));
210         dump_data(120, (const char*)passwd.buffer, passwd.uni_str_len * 2);
211         dump_data(100, nt_p16, 16);
212 #endif
213         /* clear out local copy of user's password (just being paranoid). */
214         memset(&passwd, 0, sizeof(passwd));
215 }
216
217 /* Does both the NT and LM owfs of a user's password */
218 void nt_owf_gen(const char *pwd, uchar nt_p16[16])
219 {
220         char passwd[130];
221
222         memset(passwd,'\0',130);
223         if (pwd != NULL)
224         {
225                 safe_strcpy( passwd, pwd, sizeof(passwd)-1);
226         }
227
228         /* Calculate the MD4 hash (NT compatible) of the password */
229         memset(nt_p16, '\0', 16);
230         E_md4hash((uchar *)passwd, nt_p16);
231
232 #ifdef DEBUG_PASSWORD
233         DEBUG(100,("nt_owf_gen: pwd, nt#\n"));
234         dump_data(120, passwd, strlen(passwd));
235         dump_data(100, nt_p16, 16);
236 #endif
237         /* clear out local copy of user's password (just being paranoid). */
238         bzero(passwd, sizeof(passwd));
239 }
240
241 /* Does both the NT and LM owfs of a user's UNICODE password */
242 void nt_lm_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16], uchar lm_p16[16])
243 {
244         nt_owf_genW(pwd, nt_p16);
245         lm_owf_genW(pwd, lm_p16);
246 }
247
248 /* Does both the NT and LM owfs of a user's password */
249 void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar lm_p16[16])
250 {
251         nt_owf_gen(pwd, nt_p16);
252         lm_owf_gen(pwd, lm_p16);
253 }
254
255 /* Does the des encryption from the NT or LM MD4 hash. */
256 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
257 {
258         uchar p21[21];
259  
260         memset(p21,'\0',21);
261  
262         memcpy(p21, passwd, 16);    
263         E_P24(p21, c8, p24);
264 }
265
266 void SMBOWFencrypt_ntv2(const uchar kr[16], 
267                                 const uchar *srv_chal, int srv_chal_len,
268                                 const uchar *cli_chal, int cli_chal_len,
269                                 char resp_buf[16])
270 {
271         HMACMD5Context ctx;
272
273         hmac_md5_init_limK_to_64(kr, 16, &ctx);
274         hmac_md5_update(srv_chal, srv_chal_len, &ctx);
275         hmac_md5_update(cli_chal, cli_chal_len, &ctx);
276         hmac_md5_final(resp_buf, &ctx);
277
278 #ifdef DEBUG_PASSWORD
279         DEBUG(100,("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
280         dump_data(100, srv_chal, srv_chal_len);
281         dump_data(100, cli_chal, cli_chal_len);
282         dump_data(100, resp_buf, 16);
283 #endif
284 }
285
286 void SMBsesskeygen_ntv2(const uchar kr[16], 
287                                 const uchar *nt_resp, 
288                                 char sess_key[16])
289 {
290         HMACMD5Context ctx;
291
292         hmac_md5_init_limK_to_64(kr, 16, &ctx);
293         hmac_md5_update(nt_resp, 16, &ctx);
294         hmac_md5_final(sess_key, &ctx);
295
296 #ifdef DEBUG_PASSWORD
297         DEBUG(100,("SMBsesskeygen_ntv2:\n"));
298         dump_data(100, sess_key, 16);
299 #endif
300 }
301
302 void SMBsesskeygen_ntv1(const uchar kr[16], 
303                                 const uchar *nt_resp, 
304                                 char sess_key[16])
305 {
306         mdfour(sess_key, kr, 16);
307
308 #ifdef DEBUG_PASSWORD
309         DEBUG(100,("SMBsesskeygen_ntv2:\n"));
310         dump_data(100, sess_key, 16);
311 #endif
312 }
313
314 void SMBgenclientchals(char *lm_cli_chal,
315                                 char *nt_cli_chal, int *nt_cli_chal_len,
316                                 const char *srv, const char *dom)
317 {
318         NTTIME nt_time;
319         int srv_len = strlen(srv);
320         int dom_len = strlen(dom);
321         fstring server;
322         fstring domain;
323         fstrcpy(server, srv);
324         fstrcpy(domain, dom);
325         strupper(server);
326         strupper(domain);
327
328         generate_random_buffer(lm_cli_chal, 8, False);
329         unix_to_nt_time(&nt_time, time(NULL));
330
331         CVAL(nt_cli_chal,0) = 0x1;
332         CVAL(nt_cli_chal,1) = 0x1;
333         SSVAL(nt_cli_chal, 2, 0x0);
334         SIVAL(nt_cli_chal, 4, 0x0);
335         SIVAL(nt_cli_chal, 8, nt_time.low);
336         SIVAL(nt_cli_chal, 12, nt_time.high);
337         memcpy(nt_cli_chal+16, lm_cli_chal, 8);
338         /* fill in offset 24, size of structure, later */
339
340         *nt_cli_chal_len = 28;
341
342         SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
343         *nt_cli_chal_len += 2;
344         SSVAL(nt_cli_chal, *nt_cli_chal_len, dom_len*2);
345         *nt_cli_chal_len += 2;
346         ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), domain, dom_len*2);
347         *nt_cli_chal_len += dom_len*2;
348         *nt_cli_chal_len += 4 - ((*nt_cli_chal_len) % 4);
349
350         SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
351         *nt_cli_chal_len += 2;
352         SSVAL(nt_cli_chal, 30, srv_len*2);
353         *nt_cli_chal_len += 2;
354         ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), server, srv_len*2);
355         *nt_cli_chal_len += srv_len*2;
356
357         SSVAL(nt_cli_chal, 24, (*nt_cli_chal_len)+16);
358         SSVAL(nt_cli_chal, 26, (*nt_cli_chal_len)+15);
359
360         DEBUG(100,("SMBgenclientchals: srv %s, dom %s\n", server, domain));
361         dump_data(100, nt_cli_chal, *nt_cli_chal_len);
362 }
363
364 void ntv2_owf_gen(const uchar owf[16], 
365                                 const char *user_n,
366                                 const char *domain_n,
367                                 uchar kr_buf[16])
368 {
369         pstring user_u;
370         pstring dom_u;
371         HMACMD5Context ctx;
372
373         int user_l   = strlen(user_n  );
374         int domain_l = strlen(domain_n);
375
376         _my_mbstowcsupper((int16*)user_u, user_n  , user_l*2  );
377         _my_mbstowcsupper((int16*)dom_u , domain_n, domain_l*2);
378
379         hmac_md5_init_limK_to_64(owf, 16, &ctx);
380         hmac_md5_update(user_u, user_l*2, &ctx);
381         hmac_md5_update(dom_u, domain_l*2, &ctx);
382         hmac_md5_final(kr_buf, &ctx);
383
384 #ifdef DEBUG_PASSWORD
385         DEBUG(100,("ntv2_owf_gen: user, domain, owfkey, kr\n"));
386         dump_data(100, user_u, user_l*2);
387         dump_data(100, dom_u, domain_l*2);
388         dump_data(100, owf, 16);
389         dump_data(100, kr_buf, 16);
390 #endif
391 }
392
393 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
394 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
395 {
396         uchar p21[21];
397  
398         memset(p21,'\0',21);
399         memcpy(p21, passwd, 8);    
400         memset(p21 + 8, 0xbd, 8);    
401
402         E_P24(p21, ntlmchalresp, p24);
403 #ifdef DEBUG_PASSWORD
404         DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n"));
405         dump_data(100, p21, 21);
406         dump_data(100, ntlmchalresp, 8);
407         dump_data(100, p24, 24);
408 #endif
409 }
410
411 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
412 {
413         int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
414
415         if (new_pw_len > 512)
416         {
417                 DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
418                 return False;
419         }
420
421         /*
422          * Now setup the data area.
423          * We need to generate a random fill
424          * for this area to make it harder to
425          * decrypt. JRA.
426          */
427         generate_random_buffer((unsigned char *)data, 516, False);
428         if (unicode)
429         {
430                 ascii_to_unibuf(&data[512 - new_pw_len], passwd, new_pw_len);
431         }
432         else
433         {
434                 fstrcpy( &data[512 - new_pw_len], passwd);
435         }
436         SIVAL(data, 512, new_pw_len);
437
438 #ifdef DEBUG_PASSWORD
439         DEBUG(100,("make_oem_passwd_hash\n"));
440         dump_data(100, data, 516);
441 #endif
442         SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
443
444         return True;
445 }
446
447 BOOL nt_decrypt_string2(STRING2 *out, const STRING2 *in, char nt_hash[16])
448 {
449         uchar bufhdr[8];
450         int datalen;
451
452         uchar key[16];
453         uchar *keyptr = key;
454         uchar *keyend = key + sizeof(key);
455
456         uchar *outbuf = (uchar *)out->buffer;
457         const uchar *inbuf = (const uchar *)in->buffer;
458         const uchar *inbufend;
459
460         mdfour(key, nt_hash, 16);
461
462         smbhash(bufhdr, inbuf, keyptr, 0);
463         datalen = IVAL(bufhdr, 0);
464
465         if ((datalen > in->str_str_len) || (datalen > MAX_STRINGLEN))
466         {
467                 DEBUG(0, ("nt_decrypt_string2: failed\n"));
468                 return False;
469         }
470
471         out->str_max_len = out->str_str_len = datalen;
472         inbuf += 8;
473         inbufend = inbuf + datalen;
474
475         while (inbuf < inbufend)
476         {
477                 keyptr += 7;
478                 if (keyptr + 7 > keyend)
479                 {
480                         keyptr = (keyend - keyptr) + key;
481                 }
482
483                 smbhash(outbuf, inbuf, keyptr, 0);
484
485                 inbuf += 8;
486                 outbuf += 8;
487         }
488
489         return True;
490 }
491
492 /*******************************************************************
493  creates a DCE/RPC bind authentication response
494
495  - initialises the parse structure.
496  - dynamically allocates the header data structure
497  - caller is expected to free the header data structure once used.
498
499  ********************************************************************/
500 void create_ntlmssp_resp(struct pwd_info *pwd,
501                                 char *domain, char *user_name, char *my_name,
502                                 uint32 ntlmssp_cli_flgs,
503                                 prs_struct *auth_resp)
504 {
505         RPC_AUTH_NTLMSSP_RESP     ntlmssp_resp;
506         unsigned char lm_owf[24];
507         unsigned char nt_owf[128];
508         size_t nt_owf_len;
509
510         pwd_get_lm_nt_owf(pwd, lm_owf, nt_owf, &nt_owf_len, NULL);
511                         
512         make_rpc_auth_ntlmssp_resp(&ntlmssp_resp,
513                                  lm_owf, nt_owf, nt_owf_len,
514                                  domain, user_name, my_name,
515                                  ntlmssp_cli_flgs);
516
517         smb_io_rpc_auth_ntlmssp_resp("ntlmssp_resp", &ntlmssp_resp, auth_resp, 0);
518         mem_realloc_data(auth_resp->data, auth_resp->offset);
519 }
520
521 /***********************************************************
522  decode a password buffer
523 ************************************************************/
524 BOOL decode_pw_buffer(const char buffer[516], char *new_passwd,
525                         int new_passwd_size, uint32 *new_pw_len)
526 {
527         /* 
528          * The length of the new password is in the last 4 bytes of
529          * the data buffer.
530          */
531
532         (*new_pw_len) = IVAL(buffer, 512);
533
534 #ifdef DEBUG_PASSWORD
535         dump_data(100, buffer, 516);
536 #endif
537
538         if ((*new_pw_len) < 0 || (*new_pw_len) > new_passwd_size - 1)
539         {
540                 DEBUG(0,("check_oem_password: incorrect password length (%d).\n", (*new_pw_len)));
541                 return False;
542         }
543
544         memcpy(new_passwd, &buffer[512-(*new_pw_len)], (*new_pw_len));
545         new_passwd[(*new_pw_len)] = '\0';
546
547         return True;
548 }
549
550 /***********************************************************
551  encode a password buffer
552 ************************************************************/
553 BOOL encode_pw_buffer(char buffer[516], const char *new_pass,
554                         int new_pw_len, BOOL nt_pass_set)
555 {
556         generate_random_buffer(buffer, 516, True);
557
558         if (nt_pass_set)
559         {
560                 /*
561                  * nt passwords are in unicode.  last char overwrites NULL
562                  * in ascii_to_unibuf, so use SIVAL *afterwards*.
563                  */
564                 new_pw_len *= 2;
565                 ascii_to_unibuf(&buffer[512-new_pw_len], new_pass, new_pw_len);
566         }
567         else
568         {
569                 memcpy(&buffer[512-new_pw_len], new_pass, new_pw_len);
570         }
571
572         /* 
573          * The length of the new password is in the last 4 bytes of
574          * the data buffer.
575          */
576
577         SIVAL(buffer, 512, new_pw_len);
578
579 #ifdef DEBUG_PASSWORD
580         dump_data(100, buffer, 516);
581 #endif
582
583         return True;
584 }