preparing for release of alpha.2.5
[Samba.git] / source / libsmb / smbencrypt.c
blob68314adb1c256e9fbd5920ec3a9fdae32d2d1f2b
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB parameters and setup
5 Copyright (C) Andrew Tridgell 1992-2000
6 Modified by Jeremy Allison.
7 Copyright (C) Jeremy Allison 1995-2000.
8 Copyright (C) Luke Kennethc Casson Leighton 1996-2000.
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 2 of the License, or
13 (at your option) any later version.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 extern int DEBUGLEVEL;
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 * pwrd, uchar * c8, uchar * p24)
35 uchar p21[21];
37 lm_owf_gen(pwrd, p21);
38 SMBOWFencrypt(p21, c8, p24);
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
48 /* Routines for Windows NT MD4 Hash functions. */
49 static int _my_wcslen(int16 * str)
51 int len = 0;
52 while (*str++ != 0)
53 len++;
54 return len;
58 * Convert a string into an NT UNICODE string.
59 * Note that regardless of processor type
60 * this must be in intel (little-endian)
61 * format.
64 static int _my_mbstowcs(int16 * dst, const uchar * src, int len)
66 int i;
67 int16 val;
69 for (i = 0; i < len; i++)
71 val = *src;
72 SSVAL(dst, 0, val);
73 dst++;
74 src++;
75 if (val == 0)
76 break;
78 return i;
81 static int _my_mbstowcsupper(int16 * dst, const uchar * src, int len)
83 int i;
84 int16 val;
86 for (i = 0; i < len; i++)
88 val = toupper(*src);
89 SSVAL(dst, 0, val);
90 dst++;
91 src++;
92 if (val == 0)
93 break;
95 return i;
98 /*
99 * Creates the MD4 Hash of the users password in NT UNICODE.
102 void E_md4hash(uchar * pwrd, uchar * p16)
104 int len;
105 int16 wpwd[129];
107 /* Password cannot be longer than 128 characters */
108 len = strlen((char *)pwrd);
109 if (len > 128)
110 len = 128;
111 /* Password must be converted to NT unicode */
112 _my_mbstowcs(wpwd, pwrd, len);
113 wpwd[len] = 0; /* Ensure string is null terminated */
114 /* Calculate length in bytes */
115 len = _my_wcslen(wpwd) * sizeof(int16);
117 mdfour(p16, (uchar *) wpwd, len);
120 /* Does the LM owf of a user's password */
121 void lm_owf_gen(const char *pwd, uchar p16[16])
123 char pwrd[15];
125 ZERO_STRUCT(pwrd);
127 if (pwd != NULL)
129 safe_strcpy(pwrd, pwd, sizeof(pwrd) - 1);
132 /* Mangle the passwords into Lanman format */
133 pwrd[14] = '\0';
134 strupper(pwrd);
136 /* Calculate the SMB (lanman) hash functions of the password */
138 E_P16((uchar *) pwrd, (uchar *) p16);
140 #ifdef DEBUG_PASSWORD
141 DEBUG(100, ("nt_lm_owf_gen: pwd, lm#\n"));
142 dump_data(120, pwrd, strlen(pwrd));
143 dump_data(100, p16, 16);
144 #endif
145 /* clear out local copy of user's password (just being paranoid). */
146 ZERO_STRUCT(pwrd);
149 /* Does both the NT and LM owfs of a user's password */
150 void nt_owf_gen(const char *pwd, uchar nt_p16[16])
152 char pwrd[130];
154 ZERO_STRUCT(pwrd);
155 if (pwd != NULL)
157 safe_strcpy(pwrd, pwd, sizeof(pwrd) - 1);
160 /* Calculate the MD4 hash (NT compatible) of the password */
161 E_md4hash((uchar *) pwrd, nt_p16);
163 #ifdef DEBUG_PASSWORD
164 DEBUG(100, ("nt_owf_gen: pwd, nt#\n"));
165 dump_data(120, pwrd, strlen(pwrd));
166 dump_data(100, nt_p16, 16);
167 #endif
168 /* clear out local copy of user's password (just being paranoid). */
169 ZERO_STRUCT(pwrd);
172 /* Does both the NT and LM owfs of a user's password */
173 void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar lm_p16[16])
175 nt_owf_gen(pwd, nt_p16);
176 lm_owf_gen(pwd, lm_p16);
179 /* Does the des encryption from the NT or LM MD4 hash. */
180 void SMBOWFencrypt(const uchar pwrd[16], const uchar * c8, uchar p24[24])
182 uchar p21[21];
184 ZERO_STRUCT(p21);
186 memcpy(p21, pwrd, 16);
187 E_P24(p21, c8, p24);
190 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
191 void NTLMSSPOWFencrypt(const uchar pwrd[8], const uchar * ntlmchalresp,
192 uchar p24[24])
194 uchar p21[21];
196 ZERO_STRUCT(p21);
197 memcpy(p21, pwrd, 8);
198 memset(p21 + 8, 0xbd, 8);
200 E_P24(p21, ntlmchalresp, p24);
201 #ifdef DEBUG_PASSWORD
202 DEBUG(100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
203 dump_data(100, p21, 21);
204 dump_data(100, ntlmchalresp, 8);
205 dump_data(100, p24, 24);
206 #endif
210 void SMBNTencrypt(uchar * pwrd, uchar * c8, uchar * p24)
212 uchar p21[21];
214 ZERO_STRUCT(p21);
216 nt_owf_gen(pwrd, p21);
217 SMBOWFencrypt(p21, c8, p24);
219 #ifdef DEBUG_PASSWORD
220 DEBUG(100, ("SMBNTencrypt: nt#, challenge, response\n"));
221 dump_data(100, p21, 16);
222 dump_data(100, c8, 8);
223 dump_data(100, p24, 24);
224 #endif
227 BOOL make_oem_passwd_hash(uchar data[516],
228 const char *pwrd, int new_pw_len,
229 const uchar old_pw_hash[16], BOOL unicode)
231 if (new_pw_len == 0)
233 new_pw_len = strlen(pwrd) * (unicode ? 2 : 1);
236 if (new_pw_len > 512)
238 DEBUG(0,
239 ("make_oem_passwd_hash: new password is too long.\n"));
240 return False;
244 * Now setup the data area.
245 * We need to generate a random fill
246 * for this area to make it harder to
247 * decrypt. JRA.
249 generate_random_buffer(data, 516, False);
250 if (unicode)
252 ascii_to_unibuf(&data[512 - new_pw_len], pwrd, new_pw_len);
254 else
256 fstrcpy(&data[512 - new_pw_len], pwrd);
258 SIVAL(data, 512, new_pw_len);
260 #ifdef DEBUG_PASSWORD
261 DEBUG(100, ("make_oem_passwd_hash\n"));
262 dump_data(100, data, 516);
263 #endif
264 if (old_pw_hash != NULL)
266 SamOEMhash(data, old_pw_hash, True);
269 return True;
272 void SMBOWFencrypt_ntv2(const uchar kr[16],
273 const uchar * srv_chal, int srv_chal_len,
274 const uchar * cli_chal, int cli_chal_len,
275 char resp_buf[16])
277 HMACMD5Context ctx;
279 hmac_md5_init_limK_to_64(kr, 16, &ctx);
280 hmac_md5_update(srv_chal, srv_chal_len, &ctx);
281 hmac_md5_update(cli_chal, cli_chal_len, &ctx);
282 hmac_md5_final(resp_buf, &ctx);
284 #ifdef DEBUG_PASSWORD
285 DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
286 dump_data(100, srv_chal, srv_chal_len);
287 dump_data(100, cli_chal, cli_chal_len);
288 dump_data(100, resp_buf, 16);
289 #endif
292 void SMBsesskeygen_ntv2(const uchar kr[16],
293 const uchar * nt_resp, char sess_key[16])
295 HMACMD5Context ctx;
297 hmac_md5_init_limK_to_64(kr, 16, &ctx);
298 hmac_md5_update(nt_resp, 16, &ctx);
299 hmac_md5_final(sess_key, &ctx);
301 #ifdef DEBUG_PASSWORD
302 DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
303 dump_data(100, sess_key, 16);
304 #endif
307 void SMBsesskeygen_ntv1(const uchar kr[16],
308 const uchar * nt_resp, char sess_key[16])
310 mdfour(sess_key, kr, 16);
312 #ifdef DEBUG_PASSWORD
313 DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
314 dump_data(100, sess_key, 16);
315 #endif
318 /***************************************************************************
319 tests showed that the nt challenge can be total random-length garbage!
320 ***************************************************************************/
321 void SMBgenclientchals(char *lm_cli_chal,
322 char *nt_cli_chal, int *nt_cli_chal_len,
323 const char *srv, const char *dom)
325 NTTIME nt_time;
326 int srv_len = strlen(srv);
327 int dom_len = strlen(dom);
328 fstring server;
329 fstring domain;
330 fstrcpy(server, srv);
331 fstrcpy(domain, dom);
332 strupper(server);
333 strupper(domain);
335 #ifdef EXPERIMENTATION_THIS_ACTUALLY_WORKS
336 generate_random_buffer(nt_cli_chal, 64, False);
337 (*nt_cli_chal_len) = 64;
338 memcpy(lm_cli_chal, nt_cli_chal + 16, 8);
339 generate_random_buffer(lm_cli_chal, 8, False);
341 return;
342 #endif
344 generate_random_buffer(lm_cli_chal, 8, False);
345 unix_to_nt_time(&nt_time, time(NULL));
347 CVAL(nt_cli_chal, 0) = 0x1;
348 CVAL(nt_cli_chal, 1) = 0x1;
349 SSVAL(nt_cli_chal, 2, 0x0);
350 SIVAL(nt_cli_chal, 4, 0x0);
351 SIVAL(nt_cli_chal, 8, nt_time.low);
352 SIVAL(nt_cli_chal, 12, nt_time.high);
353 memcpy(nt_cli_chal + 16, lm_cli_chal, 8);
354 /* fill in offset 24, size of structure, later */
356 *nt_cli_chal_len = 28;
358 SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
359 *nt_cli_chal_len += 2;
360 SSVAL(nt_cli_chal, *nt_cli_chal_len, dom_len * 2);
361 *nt_cli_chal_len += 2;
362 ascii_to_unibuf(nt_cli_chal + (*nt_cli_chal_len), domain,
363 dom_len * 2);
364 *nt_cli_chal_len += dom_len * 2;
365 *nt_cli_chal_len += 4 - ((*nt_cli_chal_len) % 4);
367 SSVAL(nt_cli_chal, *nt_cli_chal_len, 2);
368 *nt_cli_chal_len += 2;
369 SSVAL(nt_cli_chal, 30, srv_len * 2);
370 *nt_cli_chal_len += 2;
371 ascii_to_unibuf(nt_cli_chal + (*nt_cli_chal_len), server,
372 srv_len * 2);
373 *nt_cli_chal_len += srv_len * 2;
375 SSVAL(nt_cli_chal, 24, (*nt_cli_chal_len) + 16);
376 SSVAL(nt_cli_chal, 26, (*nt_cli_chal_len) + 15);
378 DEBUG(100, ("SMBgenclientchals: srv %s, dom %s\n", server, domain));
379 dump_data(100, nt_cli_chal, *nt_cli_chal_len);
382 void ntv2_owf_gen(const uchar owf[16],
383 const char *user_n, const char *domain_n, uchar kr_buf[16])
385 pstring user_u;
386 pstring dom_u;
387 HMACMD5Context ctx;
389 int user_l = strlen(user_n);
390 int domain_l = strlen(domain_n);
392 _my_mbstowcsupper((int16 *) user_u, user_n, user_l * 2);
393 _my_mbstowcsupper((int16 *) dom_u, domain_n, domain_l * 2);
395 hmac_md5_init_limK_to_64(owf, 16, &ctx);
396 hmac_md5_update(user_u, user_l * 2, &ctx);
397 hmac_md5_update(dom_u, domain_l * 2, &ctx);
398 hmac_md5_final(kr_buf, &ctx);
400 #ifdef DEBUG_PASSWORD
401 DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
402 dump_data(100, user_u, user_l * 2);
403 dump_data(100, dom_u, domain_l * 2);
404 dump_data(100, owf, 16);
405 dump_data(100, kr_buf, 16);
406 #endif
409 /* Does the LM owf of a user's password */
410 void lm_owf_genW(const UNISTR2 *pwd, uchar p16[16])
412 char pwrd[15];
414 ZERO_STRUCT(pwrd);
415 if (pwd != NULL)
417 unistr2_to_ascii(pwrd, pwd, sizeof(pwrd) - 1);
420 /* Mangle the passwords into Lanman format */
421 pwrd[14] = '\0';
422 strupper(pwrd);
424 /* Calculate the SMB (lanman) hash functions of the password */
426 E_P16((uchar *) pwrd, (uchar *) p16);
428 #ifdef DEBUG_PASSWORD
429 DEBUG(100, ("lm_owf_genW: pwd, lm#\n"));
430 dump_data(120, pwrd, strlen(pwrd));
431 dump_data(100, p16, 16);
432 #endif
433 /* clear out local copy of user's password (just being paranoid). */
434 ZERO_STRUCT(pwrd);
437 /* Does both the NT and LM owfs of a user's password */
438 void nt_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16])
440 char buf[512];
441 int i;
443 for (i = 0; i < MIN(pwd->uni_str_len, sizeof(buf) / 2); i++)
445 SIVAL(buf, i * 2, pwd->buffer[i]);
447 /* Calculate the MD4 hash (NT compatible) of the password */
448 mdfour(nt_p16, buf, pwd->uni_str_len * 2);
450 dump_data_pw("nt_owf_genW:", buf, pwd->uni_str_len * 2);
451 dump_data_pw("nt#:", nt_p16, 16);
453 /* clear out local copy of user's password (just being paranoid). */
454 ZERO_STRUCT(buf);
457 /* Does both the NT and LM owfs of a user's UNICODE password */
458 void nt_lm_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16], uchar lm_p16[16])
460 nt_owf_genW(pwd, nt_p16);
461 lm_owf_genW(pwd, lm_p16);
464 BOOL nt_encrypt_string2(STRING2 * out, const STRING2 * in, const uchar * key)
466 const uchar *keyptr = key;
467 const uchar *keyend = key + 16;
468 int datalen = in->str_str_len;
470 uchar *outbuf = (uchar *) out->buffer;
471 const uchar *inbuf = (const uchar *)in->buffer;
472 const uchar *inbufend;
474 out->str_max_len = in->str_max_len;
475 out->str_str_len = in->str_str_len;
476 out->undoc = 0;
478 inbufend = inbuf + datalen;
480 dump_data_pw("nt_encrypt_string2\n", inbuf, datalen);
482 while (inbuf < inbufend)
484 smbhash(outbuf, inbuf, keyptr, 1);
486 keyptr += 7;
487 if (keyptr + 7 > keyend)
489 keyptr = (keyend - keyptr) + key;
492 inbuf += 8;
493 outbuf += 8;
496 dump_data_pw("nt_encrypt_string2\n", out->buffer, datalen);
498 return True;
501 BOOL nt_decrypt_string2(STRING2 * out, const STRING2 * in, const uchar * key)
503 int datalen = in->str_str_len;
505 const uchar *keyptr = key;
506 const uchar *keyend = key + 16;
508 uchar *outbuf = (uchar *) out->buffer;
509 const uchar *inbuf = (const uchar *)in->buffer;
510 const uchar *inbufend;
512 if (in->str_str_len > MAX_STRINGLEN)
514 DEBUG(0, ("nt_decrypt_string2: failed\n"));
515 return False;
518 out->str_max_len = in->str_max_len;
519 out->str_str_len = in->str_str_len;
520 out->undoc = in->undoc;
522 inbufend = inbuf + datalen;
524 while (inbuf < inbufend)
526 smbhash(outbuf, inbuf, keyptr, 0);
527 keyptr += 7;
528 if (keyptr + 7 > keyend)
530 keyptr = (keyend - keyptr) + key;
533 inbuf += 8;
534 outbuf += 8;
537 datalen = IVAL(out->buffer, 0);
539 dump_data_pw("nt_decrypt_string2\n", out->buffer, out->str_str_len);
541 if (datalen != in->str_str_len - 8)
543 DEBUG(2, ("nt_decrypt_string2: length-match failed\n"));
544 return False;
547 return True;
550 /***********************************************************
551 decode a password buffer
552 ************************************************************/
553 BOOL decode_pw_buffer(const char buffer[516], char *new_pwrd,
554 int new_pwrd_size, uint32 *new_pw_len)
557 * The length of the new password is in the last 4 bytes of
558 * the data buffer.
561 (*new_pw_len) = IVAL(buffer, 512);
563 #ifdef DEBUG_PASSWORD
564 dump_data(100, buffer, 516);
565 #endif
567 if ((*new_pw_len) < 0 || (*new_pw_len) > new_pwrd_size - 1)
569 DEBUG(0,
570 ("decode_pw_buffer: incorrect password length (%d).\n",
571 (*new_pw_len)));
572 return False;
575 memcpy(new_pwrd, &buffer[512 - (*new_pw_len)], (*new_pw_len));
576 new_pwrd[(*new_pw_len)] = '\0';
578 #ifdef DEBUG_PASSWORD
579 dump_data(100, new_pwrd, (*new_pw_len));
580 #endif
582 return True;
585 /***********************************************************
586 encode a password buffer
587 ************************************************************/
588 BOOL encode_pw_buffer(char buffer[516], const char *new_pass,
589 int new_pw_len, BOOL nt_pass_set)
591 generate_random_buffer(buffer, 516, True);
593 if (nt_pass_set)
596 * nt passwords are in unicode. last char overwrites NULL
597 * in ascii_to_unibuf, so use SIVAL *afterwards*.
599 new_pw_len *= 2;
600 ascii_to_unibuf(&buffer[512 - new_pw_len], new_pass,
601 new_pw_len);
603 else
605 memcpy(&buffer[512 - new_pw_len], new_pass, new_pw_len);
609 * The length of the new password is in the last 4 bytes of
610 * the data buffer.
613 SIVAL(buffer, 512, new_pw_len);
615 #ifdef DEBUG_PASSWORD
616 dump_data(100, buffer, 516);
617 #endif
619 return True;