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