Lots of doc updates. Getting ready for 2.2.5 release.
[Samba.git] / source / libsmb / smbencrypt.c
blob9d862444e0e0589f9da44b02ddd84b868fe11c19
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.
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.
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.
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.
23 #include "includes.h"
25 #include "byteorder.h"
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(const uchar *passwd, uchar *c8, uchar *p24)
33 uchar p14[15], p21[21];
35 memset(p21,'\0',21);
36 memset(p14,'\0',14);
37 StrnCpy((char *)p14,(const char *)passwd,14);
39 strupper((char *)p14);
40 E_P16(p14, p21);
42 SMBOWFencrypt(p21, c8, p24);
44 #ifdef DEBUG_PASSWORD
45 DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
46 dump_data(100, (char *)p21, 16);
47 dump_data(100, (char *)c8, 8);
48 dump_data(100, (char *)p24, 24);
49 #endif
52 /*
53 * Creates the MD4 Hash of the users password in NT UNICODE.
56 void E_md4hash(const uchar *passwd, uchar *p16)
58 int len;
59 int16 wpwd[129];
61 /* Password cannot be longer than 128 characters */
62 len = strlen((const char *)passwd);
63 if(len > 128)
64 len = 128;
65 /* Password must be converted to NT unicode - null terminated. */
66 dos_struni2((char *)wpwd, (const char *)passwd, 256);
67 /* Calculate length in bytes */
68 len = strlen_w((const smb_ucs2_t *)wpwd) * sizeof(int16);
70 mdfour(p16, (unsigned char *)wpwd, len);
73 /* Does both the NT and LM owfs of a user's password */
74 void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16])
76 char passwd[514];
78 memset(passwd,'\0',514);
79 safe_strcpy( passwd, pwd, sizeof(passwd)-1);
81 /* Calculate the MD4 hash (NT compatible) of the password */
82 memset(nt_p16, '\0', 16);
83 E_md4hash((uchar *)passwd, nt_p16);
85 #ifdef DEBUG_PASSWORD
86 DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
87 dump_data(120, passwd, strlen(passwd));
88 dump_data(100, (char *)nt_p16, 16);
89 #endif
91 /* Mangle the passwords into Lanman format */
92 passwd[14] = '\0';
93 strupper(passwd);
95 /* Calculate the SMB (lanman) hash functions of the password */
97 memset(p16, '\0', 16);
98 E_P16((uchar *) passwd, (uchar *)p16);
100 #ifdef DEBUG_PASSWORD
101 DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
102 dump_data(120, passwd, strlen(passwd));
103 dump_data(100, (char *)p16, 16);
104 #endif
105 /* clear out local copy of user's password (just being paranoid). */
106 memset(passwd, '\0', sizeof(passwd));
109 /* Does the des encryption from the NT or LM MD4 hash. */
110 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
112 uchar p21[21];
114 memset(p21,'\0',21);
116 memcpy(p21, passwd, 16);
117 E_P24(p21, c8, p24);
120 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
121 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
123 uchar p21[21];
125 memset(p21,'\0',21);
126 memcpy(p21, passwd, 8);
127 memset(p21 + 8, 0xbd, 8);
129 E_P24(p21, ntlmchalresp, p24);
130 #ifdef DEBUG_PASSWORD
131 DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n"));
132 dump_data(100, (char *)p21, 21);
133 dump_data(100, (char *)ntlmchalresp, 8);
134 dump_data(100, (char *)p24, 24);
135 #endif
139 /* Does the NT MD4 hash then des encryption. */
141 void SMBNTencrypt(const uchar *passwd, uchar *c8, uchar *p24)
143 uchar p21[21];
145 memset(p21,'\0',21);
147 E_md4hash(passwd, p21);
148 SMBOWFencrypt(p21, c8, p24);
150 #ifdef DEBUG_PASSWORD
151 DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
152 dump_data(100, (char *)p21, 16);
153 dump_data(100, (char *)c8, 8);
154 dump_data(100, (char *)p24, 24);
155 #endif
158 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
160 int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
162 if (new_pw_len > 512)
164 DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
165 return False;
169 * Now setup the data area.
170 * We need to generate a random fill
171 * for this area to make it harder to
172 * decrypt. JRA.
174 generate_random_buffer((unsigned char *)data, 516, False);
175 if (unicode)
177 /* Note that passwd should be in DOS oem character set. */
178 dos_struni2( &data[512 - new_pw_len], passwd, 512);
180 else
182 /* Note that passwd should be in DOS oem character set. */
183 fstrcpy( &data[512 - new_pw_len], passwd);
185 SIVAL(data, 512, new_pw_len);
187 #ifdef DEBUG_PASSWORD
188 DEBUG(100,("make_oem_passwd_hash\n"));
189 dump_data(100, data, 516);
190 #endif
191 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
193 return True;
196 /***********************************************************
197 Encode a password buffer.
198 ************************************************************/
200 BOOL encode_pw_buffer(char buffer[516], const char *new_pass,
201 int new_pw_len, BOOL nt_pass_set)
203 generate_random_buffer((unsigned char *)buffer, 516, True);
205 if (new_pw_len < 0 || new_pw_len > 512)
206 return False;
208 if (nt_pass_set) {
209 new_pw_len *= 2;
210 dos_struni2(&buffer[512 - new_pw_len], new_pass, 256);
211 } else {
212 memcpy(&buffer[512 - new_pw_len], new_pass, new_pw_len);
216 * The length of the new password is in the last 4 bytes of
217 * the data buffer.
219 SIVAL(buffer, 512, new_pw_len);
221 return True;
224 /***********************************************************
225 decode a password buffer
226 ************************************************************/
227 BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
228 int new_pwrd_size, uint32 *new_pw_len,
229 uchar nt_p16[16], uchar p16[16])
231 char *pw;
233 int uni_pw_len=0;
234 int byte_len=0;
235 char unicode_passwd[514];
236 char lm_ascii_passwd[514];
237 char passwd[514];
240 Warning !!! : This function is called from some rpc call.
241 The password IN the buffer is a UNICODE string.
242 The password IN new_pwrd is an ASCII string
243 If you reuse that code somewhere else check first.
246 ZERO_STRUCT(unicode_passwd);
247 ZERO_STRUCT(lm_ascii_passwd);
248 ZERO_STRUCT(passwd);
250 memset(nt_p16, '\0', 16);
251 memset(p16, '\0', 16);
253 /* The length of the new password is in the last 4 bytes of the data buffer. */
255 byte_len = IVAL(in_buffer, 512);
257 #ifdef DEBUG_PASSWORD
258 dump_data(100, in_buffer, 516);
259 #endif
261 /* Password cannot be longer than 128 characters */
262 if ( (byte_len < 0) || (byte_len > new_pwrd_size - 1)) {
263 DEBUG(0, ("decode_pw_buffer: incorrect password length (%d).\n", byte_len));
264 return False;
267 uni_pw_len = byte_len/2;
268 pw = dos_unistrn2((uint16 *)(&in_buffer[512 - byte_len]), byte_len);
269 memcpy(passwd, pw, uni_pw_len);
271 #ifdef DEBUG_PASSWORD
272 DEBUG(100,("nt_lm_owf_gen: passwd: "));
273 dump_data(100, (char *)passwd, uni_pw_len);
274 DEBUG(100,("len:%d\n", uni_pw_len));
275 #endif
276 memcpy(unicode_passwd, &in_buffer[512 - byte_len], byte_len);
278 mdfour(nt_p16, (unsigned char *)unicode_passwd, byte_len);
280 #ifdef DEBUG_PASSWORD
281 DEBUG(100,("nt_lm_owf_gen: nt#:"));
282 dump_data(100, (char *)nt_p16, 16);
283 DEBUG(100,("\n"));
284 #endif
286 /* Mangle the passwords into Lanman format */
287 memcpy(lm_ascii_passwd, passwd, uni_pw_len);
288 lm_ascii_passwd[14] = '\0';
289 strupper(lm_ascii_passwd);
291 /* Calculate the SMB (lanman) hash functions of the password */
292 E_P16((uchar *) lm_ascii_passwd, (uchar *)p16);
294 #ifdef DEBUG_PASSWORD
295 DEBUG(100,("nt_lm_owf_gen: lm#:"));
296 dump_data(100, (char *)p16, 16);
297 DEBUG(100,("\n"));
298 #endif
300 /* copy the password and it's length to the return buffer */
301 *new_pw_len=uni_pw_len;
302 memcpy(new_pwrd, passwd, uni_pw_len);
303 new_pwrd[uni_pw_len]='\0';
306 /* clear out local copy of user's password (just being paranoid). */
307 ZERO_STRUCT(unicode_passwd);
308 ZERO_STRUCT(lm_ascii_passwd);
309 ZERO_STRUCT(passwd);
311 return True;
315 /* Calculate the NT owfs of a user's password */
316 void nt_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16])
318 char buf[512];
319 int i;
321 for (i = 0; i < MIN(pwd->uni_str_len, sizeof(buf) / 2); i++)
322 SIVAL(buf, i * 2, pwd->buffer[i]);
324 /* Calculate the MD4 hash (NT compatible) of the password */
325 mdfour(nt_p16, (unsigned char *)buf, pwd->uni_str_len * 2);
327 /* clear out local copy of user's password (just being paranoid). */
328 ZERO_STRUCT(buf);