Fix example usage in comment at the start of the SPA/NTLM code.
[exim.git] / src / src / auths / auth-spa.c
1 /* $Cambridge: exim/src/src/auths/auth-spa.c,v 1.3 2005/08/02 13:23:19 ph10 Exp $ */
2
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
6
7 /*
8 * This file provides the necessary methods for authenticating with
9 * Microsoft's Secure Password Authentication.
10
11 * All the original code used here was torn by Marc Prud'hommeaux out of the
12 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
13
14 * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
15 * support server authentication mode.
16
17 * Mark Lyda provided a patch to solve this problem:
18
19 - Exim is indicating in its Authentication Request message (Type 1) that it
20 can transmit text in either Unicode or OEM format.
21
22 - Microsoft's SMTP server (smtp.email.msn.com) is responding in its
23 Challenge message (Type 2) that it will be expecting the OEM format.
24
25 - Exim does not pay attention to the text format requested by Microsoft's
26 SMTP server and, instead, defaults to using the Unicode format.
27
28 * References:
29 * http://www.innovation.ch/java/ntlm.html
30 * http://www.kuro5hin.org/story/2002/4/28/1436/66154
31
32 * It seems that some systems have existing but different definitions of some
33 * of the following types. I received a complaint about "int16" causing
34 * compilation problems. So I (PH) have renamed them all, to be on the safe
35 * side, by adding 'x' on the end.
36
37 * typedef signed short int16;
38 * typedef unsigned short uint16;
39 * typedef unsigned uint32;
40 * typedef unsigned char uint8;
41
42 * The API is extremely simple:
43 * 1. Form a SPA authentication request based on the username
44 * and (optional) domain
45 * 2. Send the request to the server and get an SPA challenge
46 * 3. Build the challenge response and send it back.
47 *
48 * Example usage is as
49 * follows:
50 *
51 int main (int argc, char ** argv)
52 {
53 SPAAuthRequest request;
54 SPAAuthChallenge challenge;
55 SPAAuthResponse response;
56 char msgbuf[2048];
57 char buffer[512];
58 char *username, *password, *domain, *challenge_str;
59
60 if (argc < 3)
61 {
62 printf ("Usage: %s <username> <password> [SPA Challenge]\n",
63 argv [0]);
64 exit (1);
65 }
66
67 username = argv [1];
68 password = argv [2];
69 domain = 0;
70
71 spa_build_auth_request (&request, username, domain);
72
73 spa_bits_to_base64 (msgbuf, (unsigned char*)&request,
74 spa_request_length(&request));
75
76 printf ("SPA Login request for username=%s:\n %s\n",
77 argv [1], msgbuf);
78
79 if (argc < 4)
80 {
81 printf ("Run: %s <username> <password> [NTLM Challenge] " \
82 "to complete authenitcation\n", argv [0]);
83 exit (0);
84 }
85
86 challenge_str = argv [3];
87
88 if (spa_base64_to_bits ((char *)&challenge, sizeof(challenge),
89 (const char *)(challenge_str))<0)
90 {
91 printf("bad base64 data in challenge: %s\n", challenge_str);
92 exit (1);
93 }
94
95 spa_build_auth_response (&challenge, &response, username, password);
96 spa_bits_to_base64 (msgbuf, (unsigned char*)&response,
97 spa_request_length(&response));
98
99 printf ("SPA Response to challenge:\n %s\n for " \
100 "username=%s, password=%s:\n %s\n",
101 argv[3], argv [1], argv [2], msgbuf);
102 return 0;
103 }
104 *
105 *
106 * All the client code used here was torn by Marc Prud'hommeaux out of the
107 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
108 * Previous comments are below:
109 */
110
111 /*
112 Unix SMB/Netbios implementation.
113 Version 1.9.
114
115 a partial implementation of DES designed for use in the
116 SMB authentication protocol
117
118 Copyright (C) Andrew Tridgell 1998
119
120 This program is free software; you can redistribute it and/or modify
121 it under the terms of the GNU General Public License as published by
122 the Free Software Foundation; either version 2 of the License, or
123 (at your option) any later version.
124
125 This program is distributed in the hope that it will be useful,
126 but WITHOUT ANY WARRANTY; without even the implied warranty of
127 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128 GNU General Public License for more details.
129
130 You should have received a copy of the GNU General Public License
131 along with this program; if not, write to the Free Software
132 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
133 */
134
135
136 /* NOTES:
137
138 This code makes no attempt to be fast! In fact, it is a very
139 slow implementation
140
141 This code is NOT a complete DES implementation. It implements only
142 the minimum necessary for SMB authentication, as used by all SMB
143 products (including every copy of Microsoft Windows95 ever sold)
144
145 In particular, it can only do a unchained forward DES pass. This
146 means it is not possible to use this code for encryption/decryption
147 of data, instead it is only useful as a "hash" algorithm.
148
149 There is no entry point into this code that allows normal DES operation.
150
151 I believe this means that this code does not come under ITAR
152 regulations but this is NOT a legal opinion. If you are concerned
153 about the applicability of ITAR regulations to this code then you
154 should confirm it for yourself (and maybe let me know if you come
155 up with a different answer to the one above)
156 */
157
158 #define DEBUG(a,b) ;
159
160 extern int DEBUGLEVEL;
161
162 #include <sys/types.h> /* For size_t */
163 #include "auth-spa.h"
164 #include <assert.h>
165 #include <ctype.h>
166 #include <stdio.h>
167 #include <stdlib.h>
168 #include <string.h>
169 #include <time.h>
170 #include <unistd.h>
171
172 #ifndef _AIX
173 typedef unsigned char uchar;
174 #endif
175
176
177 typedef int BOOL;
178 #define False 0
179 #define True 1
180
181 #ifndef _BYTEORDER_H
182 #define _BYTEORDER_H
183
184 #define RW_PCVAL(read,inbuf,outbuf,len) \
185 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
186 else { PSCVAL(inbuf,0,outbuf,len); } }
187
188 #define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
189 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
190 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
191
192 #define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
193 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
194 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
195
196 #define RW_CVAL(read, inbuf, outbuf, offset) \
197 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
198 else { SCVAL(inbuf,offset,outbuf); } }
199
200 #define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
201 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
202 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
203
204 #define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
205 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
206 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
207
208 #undef CAREFUL_ALIGNMENT
209
210 /* we know that the 386 can handle misalignment and has the "right"
211 byteorder */
212 #ifdef __i386__
213 #define CAREFUL_ALIGNMENT 0
214 #endif
215
216 #ifndef CAREFUL_ALIGNMENT
217 #define CAREFUL_ALIGNMENT 1
218 #endif
219
220 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
221 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
222 #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
223
224
225 #if CAREFUL_ALIGNMENT
226
227 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
228 #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
229 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
230 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
231 #define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
232 #define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
233 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
234 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
235 #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
236 #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
237
238 #else /* CAREFUL_ALIGNMENT */
239
240 /* this handles things for architectures like the 386 that can handle
241 alignment errors */
242 /*
243 WARNING: This section is dependent on the length of int16x and int32x
244 being correct
245 */
246
247 /* get single value from an SMB buffer */
248 #define SVAL(buf,pos) (*(uint16x *)((char *)(buf) + (pos)))
249 #define IVAL(buf,pos) (*(uint32x *)((char *)(buf) + (pos)))
250 #define SVALS(buf,pos) (*(int16x *)((char *)(buf) + (pos)))
251 #define IVALS(buf,pos) (*(int32x *)((char *)(buf) + (pos)))
252
253 /* store single value in an SMB buffer */
254 #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
255 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
256 #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
257 #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
258
259 #endif /* CAREFUL_ALIGNMENT */
260
261 /* macros for reading / writing arrays */
262
263 #define SMBMACRO(macro,buf,pos,val,len,size) \
264 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
265
266 #define SSMBMACRO(macro,buf,pos,val,len,size) \
267 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
268
269 /* reads multiple data from an SMB buffer */
270 #define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
271 #define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
272 #define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
273 #define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
274 #define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
275 #define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
276
277 /* stores multiple data in an SMB buffer */
278 #define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
279 #define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
280 #define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
281 #define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
282 #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
283 #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
284
285
286 /* now the reverse routines - these are used in nmb packets (mostly) */
287 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
288 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
289
290 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))
291 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))
292 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))
293 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))
294 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
295 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
296 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
297 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
298
299 /* reads multiple data from an SMB buffer (big-endian) */
300 #define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
301 #define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
302 #define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
303 #define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
304
305 /* stores multiple data in an SMB buffer (big-endian) */
306 #define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
307 #define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
308 #define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
309 #define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
310
311 #define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
312 { RW_PCVAL(read,inbuf,outbuf,len) \
313 DEBUG(5,("%s%04x %s: ", \
314 tab_depth(depth), base,string)); \
315 if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
316 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
317 DEBUG(5,("\n")); }
318
319 #define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
320 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
321 DEBUG(5,("%s%04x %s: ", \
322 tab_depth(depth), base,string)); \
323 if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
324 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
325 DEBUG(5,("\n")); }
326
327 #define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
328 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
329 DEBUG(5,("%s%04x %s: ", \
330 tab_depth(depth), base,string)); \
331 if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
332 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
333 DEBUG(5,("\n")); }
334
335 #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
336 { RW_CVAL(read,inbuf,outbuf,0) \
337 DEBUG(5,("%s%04x %s: %02x\n", \
338 tab_depth(depth), base, string, outbuf)); }
339
340 #define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
341 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
342 DEBUG(5,("%s%04x %s: %04x\n", \
343 tab_depth(depth), base, string, outbuf)); }
344
345 #define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
346 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
347 DEBUG(5,("%s%04x %s: %08x\n", \
348 tab_depth(depth), base, string, outbuf)); }
349
350 #endif /* _BYTEORDER_H */
351
352 void E_P16 (unsigned char *p14, unsigned char *p16);
353 void E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24);
354 void D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out);
355 void SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24]);
356
357 void mdfour (unsigned char *out, unsigned char *in, int n);
358
359
360 /*
361 * base64.c -- base-64 conversion routines.
362 *
363 * For license terms, see the file COPYING in this directory.
364 *
365 * This base 64 encoding is defined in RFC2045 section 6.8,
366 * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
367 * scheme used here.
368 */
369
370 static const char base64digits[] =
371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
372
373 #define BAD -1
374 static const char base64val[] = {
375 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
376 BAD,
377 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
378 BAD,
379 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
380 63,
381 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
382 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
383 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
384 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
385 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
386 };
387 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
388
389 void
390 spa_bits_to_base64 (unsigned char *out, const unsigned char *in, int inlen)
391 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
392 {
393 for (; inlen >= 3; inlen -= 3)
394 {
395 *out++ = base64digits[in[0] >> 2];
396 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
397 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
398 *out++ = base64digits[in[2] & 0x3f];
399 in += 3;
400 }
401 if (inlen > 0)
402 {
403 unsigned char fragment;
404
405 *out++ = base64digits[in[0] >> 2];
406 fragment = (in[0] << 4) & 0x30;
407 if (inlen > 1)
408 fragment |= in[1] >> 4;
409 *out++ = base64digits[fragment];
410 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
411 *out++ = '=';
412 }
413 *out = '\0';
414 }
415
416
417 /* The outlength parameter was added by PH, December 2004 */
418
419 int
420 spa_base64_to_bits (char *out, int outlength, const char *in)
421 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
422 {
423 int len = 0;
424 register unsigned char digit1, digit2, digit3, digit4;
425
426 if (in[0] == '+' && in[1] == ' ')
427 in += 2;
428 if (*in == '\r')
429 return (0);
430
431 do
432 {
433 if (len >= outlength) /* Added by PH */
434 return (-1); /* Added by PH */
435 digit1 = in[0];
436 if (DECODE64 (digit1) == BAD)
437 return (-1);
438 digit2 = in[1];
439 if (DECODE64 (digit2) == BAD)
440 return (-1);
441 digit3 = in[2];
442 if (digit3 != '=' && DECODE64 (digit3) == BAD)
443 return (-1);
444 digit4 = in[3];
445 if (digit4 != '=' && DECODE64 (digit4) == BAD)
446 return (-1);
447 in += 4;
448 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
449 ++len;
450 if (digit3 != '=')
451 {
452 if (len >= outlength) /* Added by PH */
453 return (-1); /* Added by PH */
454 *out++ =
455 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
456 ++len;
457 if (digit4 != '=')
458 {
459 if (len >= outlength) /* Added by PH */
460 return (-1); /* Added by PH */
461 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
462 ++len;
463 }
464 }
465 }
466 while (*in && *in != '\r' && digit4 != '=');
467
468 return (len);
469 }
470
471
472 #define uchar unsigned char
473
474 static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
475 1, 58, 50, 42, 34, 26, 18,
476 10, 2, 59, 51, 43, 35, 27,
477 19, 11, 3, 60, 52, 44, 36,
478 63, 55, 47, 39, 31, 23, 15,
479 7, 62, 54, 46, 38, 30, 22,
480 14, 6, 61, 53, 45, 37, 29,
481 21, 13, 5, 28, 20, 12, 4
482 };
483
484 static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
485 3, 28, 15, 6, 21, 10,
486 23, 19, 12, 4, 26, 8,
487 16, 7, 27, 20, 13, 2,
488 41, 52, 31, 37, 47, 55,
489 30, 40, 51, 45, 33, 48,
490 44, 49, 39, 56, 34, 53,
491 46, 42, 50, 36, 29, 32
492 };
493
494 static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
495 60, 52, 44, 36, 28, 20, 12, 4,
496 62, 54, 46, 38, 30, 22, 14, 6,
497 64, 56, 48, 40, 32, 24, 16, 8,
498 57, 49, 41, 33, 25, 17, 9, 1,
499 59, 51, 43, 35, 27, 19, 11, 3,
500 61, 53, 45, 37, 29, 21, 13, 5,
501 63, 55, 47, 39, 31, 23, 15, 7
502 };
503
504 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
505 4, 5, 6, 7, 8, 9,
506 8, 9, 10, 11, 12, 13,
507 12, 13, 14, 15, 16, 17,
508 16, 17, 18, 19, 20, 21,
509 20, 21, 22, 23, 24, 25,
510 24, 25, 26, 27, 28, 29,
511 28, 29, 30, 31, 32, 1
512 };
513
514 static uchar perm5[32] = { 16, 7, 20, 21,
515 29, 12, 28, 17,
516 1, 15, 23, 26,
517 5, 18, 31, 10,
518 2, 8, 24, 14,
519 32, 27, 3, 9,
520 19, 13, 30, 6,
521 22, 11, 4, 25
522 };
523
524
525 static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
526 39, 7, 47, 15, 55, 23, 63, 31,
527 38, 6, 46, 14, 54, 22, 62, 30,
528 37, 5, 45, 13, 53, 21, 61, 29,
529 36, 4, 44, 12, 52, 20, 60, 28,
530 35, 3, 43, 11, 51, 19, 59, 27,
531 34, 2, 42, 10, 50, 18, 58, 26,
532 33, 1, 41, 9, 49, 17, 57, 25
533 };
534
535
536 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
537
538 static uchar sbox[8][4][16] = {
539 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
540 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
541 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
542 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
543
544 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
545 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
546 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
547 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
548
549 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
550 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
551 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
552 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
553
554 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
555 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
556 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
557 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
558
559 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
560 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
561 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
562 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
563
564 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
565 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
566 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
567 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
568
569 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
570 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
571 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
572 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
573
574 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
575 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
576 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
577 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
578 };
579
580 static void
581 permute (char *out, char *in, uchar * p, int n)
582 {
583 int i;
584 for (i = 0; i < n; i++)
585 out[i] = in[p[i] - 1];
586 }
587
588 static void
589 lshift (char *d, int count, int n)
590 {
591 char out[64];
592 int i;
593 for (i = 0; i < n; i++)
594 out[i] = d[(i + count) % n];
595 for (i = 0; i < n; i++)
596 d[i] = out[i];
597 }
598
599 static void
600 concat (char *out, char *in1, char *in2, int l1, int l2)
601 {
602 while (l1--)
603 *out++ = *in1++;
604 while (l2--)
605 *out++ = *in2++;
606 }
607
608 static void
609 xor (char *out, char *in1, char *in2, int n)
610 {
611 int i;
612 for (i = 0; i < n; i++)
613 out[i] = in1[i] ^ in2[i];
614 }
615
616 static void
617 dohash (char *out, char *in, char *key, int forw)
618 {
619 int i, j, k;
620 char pk1[56];
621 char c[28];
622 char d[28];
623 char cd[56];
624 char ki[16][48];
625 char pd1[64];
626 char l[32], r[32];
627 char rl[64];
628
629 permute (pk1, key, perm1, 56);
630
631 for (i = 0; i < 28; i++)
632 c[i] = pk1[i];
633 for (i = 0; i < 28; i++)
634 d[i] = pk1[i + 28];
635
636 for (i = 0; i < 16; i++)
637 {
638 lshift (c, sc[i], 28);
639 lshift (d, sc[i], 28);
640
641 concat (cd, c, d, 28, 28);
642 permute (ki[i], cd, perm2, 48);
643 }
644
645 permute (pd1, in, perm3, 64);
646
647 for (j = 0; j < 32; j++)
648 {
649 l[j] = pd1[j];
650 r[j] = pd1[j + 32];
651 }
652
653 for (i = 0; i < 16; i++)
654 {
655 char er[48];
656 char erk[48];
657 char b[8][6];
658 char cb[32];
659 char pcb[32];
660 char r2[32];
661
662 permute (er, r, perm4, 48);
663
664 xor (erk, er, ki[forw ? i : 15 - i], 48);
665
666 for (j = 0; j < 8; j++)
667 for (k = 0; k < 6; k++)
668 b[j][k] = erk[j * 6 + k];
669
670 for (j = 0; j < 8; j++)
671 {
672 int m, n;
673 m = (b[j][0] << 1) | b[j][5];
674
675 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
676
677 for (k = 0; k < 4; k++)
678 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
679 }
680
681 for (j = 0; j < 8; j++)
682 for (k = 0; k < 4; k++)
683 cb[j * 4 + k] = b[j][k];
684 permute (pcb, cb, perm5, 32);
685
686 xor (r2, l, pcb, 32);
687
688 for (j = 0; j < 32; j++)
689 l[j] = r[j];
690
691 for (j = 0; j < 32; j++)
692 r[j] = r2[j];
693 }
694
695 concat (rl, r, l, 32, 32);
696
697 permute (out, rl, perm6, 64);
698 }
699
700 static void
701 str_to_key (unsigned char *str, unsigned char *key)
702 {
703 int i;
704
705 key[0] = str[0] >> 1;
706 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
707 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
708 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
709 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
710 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
711 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
712 key[7] = str[6] & 0x7F;
713 for (i = 0; i < 8; i++)
714 {
715 key[i] = (key[i] << 1);
716 }
717 }
718
719
720 static void
721 smbhash (unsigned char *out, unsigned char *in, unsigned char *key, int forw)
722 {
723 int i;
724 char outb[64];
725 char inb[64];
726 char keyb[64];
727 unsigned char key2[8];
728
729 str_to_key (key, key2);
730
731 for (i = 0; i < 64; i++)
732 {
733 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
734 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
735 outb[i] = 0;
736 }
737
738 dohash (outb, inb, keyb, forw);
739
740 for (i = 0; i < 8; i++)
741 {
742 out[i] = 0;
743 }
744
745 for (i = 0; i < 64; i++)
746 {
747 if (outb[i])
748 out[i / 8] |= (1 << (7 - (i % 8)));
749 }
750 }
751
752 void
753 E_P16 (unsigned char *p14, unsigned char *p16)
754 {
755 unsigned char sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
756 smbhash (p16, sp8, p14, 1);
757 smbhash (p16 + 8, sp8, p14 + 7, 1);
758 }
759
760 void
761 E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24)
762 {
763 smbhash (p24, c8, p21, 1);
764 smbhash (p24 + 8, c8, p21 + 7, 1);
765 smbhash (p24 + 16, c8, p21 + 14, 1);
766 }
767
768 void
769 D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out)
770 {
771 smbhash (out, in, p14, 0);
772 smbhash (out + 8, in + 8, p14 + 7, 0);
773 }
774
775 /****************************************************************************
776 Like strncpy but always null terminates. Make sure there is room!
777 The variable n should always be one less than the available size.
778 ****************************************************************************/
779
780 char *
781 StrnCpy (char *dest, const char *src, size_t n)
782 {
783 char *d = dest;
784 if (!dest)
785 return (NULL);
786 if (!src)
787 {
788 *dest = 0;
789 return (dest);
790 }
791 while (n-- && (*d++ = *src++));
792 *d = 0;
793 return (dest);
794 }
795
796 size_t
797 skip_multibyte_char (char c)
798 {
799 /* bogus if to get rid of unused compiler warning */
800 if (c)
801 return 0;
802 else
803 return 0;
804 }
805
806
807 /*******************************************************************
808 safe string copy into a known length string. maxlength does not
809 include the terminating zero.
810 ********************************************************************/
811
812 char *
813 safe_strcpy (char *dest, const char *src, size_t maxlength)
814 {
815 size_t len;
816
817 if (!dest)
818 {
819 DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
820 return NULL;
821 }
822
823 if (!src)
824 {
825 *dest = 0;
826 return dest;
827 }
828
829 len = strlen (src);
830
831 if (len > maxlength)
832 {
833 DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
834 (int) (len - maxlength), src));
835 len = maxlength;
836 }
837
838 memcpy (dest, src, len);
839 dest[len] = 0;
840 return dest;
841 }
842
843
844 void
845 strupper (char *s)
846 {
847 while (*s)
848 {
849 {
850 size_t skip = skip_multibyte_char (*s);
851 if (skip != 0)
852 s += skip;
853 else
854 {
855 if (islower ((unsigned char)(*s)))
856 *s = toupper (*s);
857 s++;
858 }
859 }
860 }
861 }
862
863
864 /*
865 This implements the X/Open SMB password encryption
866 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
867 encrypted password into p24
868 */
869
870 void
871 spa_smb_encrypt (uchar * passwd, uchar * c8, uchar * p24)
872 {
873 uchar p14[15], p21[21];
874
875 memset (p21, '\0', 21);
876 memset (p14, '\0', 14);
877 StrnCpy ((char *) p14, (char *) passwd, 14);
878
879 strupper ((char *) p14);
880 E_P16 (p14, p21);
881
882 SMBOWFencrypt (p21, c8, p24);
883
884 #ifdef DEBUG_PASSWORD
885 DEBUG (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
886 dump_data (100, (char *) p21, 16);
887 dump_data (100, (char *) c8, 8);
888 dump_data (100, (char *) p24, 24);
889 #endif
890 }
891
892 /* Routines for Windows NT MD4 Hash functions. */
893 static int
894 _my_wcslen (int16x * str)
895 {
896 int len = 0;
897 while (*str++ != 0)
898 len++;
899 return len;
900 }
901
902 /*
903 * Convert a string into an NT UNICODE string.
904 * Note that regardless of processor type
905 * this must be in intel (little-endian)
906 * format.
907 */
908
909 static int
910 _my_mbstowcs (int16x * dst, uchar * src, int len)
911 {
912 int i;
913 int16x val;
914
915 for (i = 0; i < len; i++)
916 {
917 val = *src;
918 SSVAL (dst, 0, val);
919 dst++;
920 src++;
921 if (val == 0)
922 break;
923 }
924 return i;
925 }
926
927 /*
928 * Creates the MD4 Hash of the users password in NT UNICODE.
929 */
930
931 void
932 E_md4hash (uchar * passwd, uchar * p16)
933 {
934 int len;
935 int16x wpwd[129];
936
937 /* Password cannot be longer than 128 characters */
938 len = strlen ((char *) passwd);
939 if (len > 128)
940 len = 128;
941 /* Password must be converted to NT unicode */
942 _my_mbstowcs (wpwd, passwd, len);
943 wpwd[len] = 0; /* Ensure string is null terminated */
944 /* Calculate length in bytes */
945 len = _my_wcslen (wpwd) * sizeof (int16x);
946
947 mdfour (p16, (unsigned char *) wpwd, len);
948 }
949
950 /* Does both the NT and LM owfs of a user's password */
951 void
952 nt_lm_owf_gen (char *pwd, uchar nt_p16[16], uchar p16[16])
953 {
954 char passwd[130];
955
956 memset (passwd, '\0', 130);
957 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
958
959 /* Calculate the MD4 hash (NT compatible) of the password */
960 memset (nt_p16, '\0', 16);
961 E_md4hash ((uchar *) passwd, nt_p16);
962
963 #ifdef DEBUG_PASSWORD
964 DEBUG (100, ("nt_lm_owf_gen: pwd, nt#\n"));
965 dump_data (120, passwd, strlen (passwd));
966 dump_data (100, (char *) nt_p16, 16);
967 #endif
968
969 /* Mangle the passwords into Lanman format */
970 passwd[14] = '\0';
971 strupper (passwd);
972
973 /* Calculate the SMB (lanman) hash functions of the password */
974
975 memset (p16, '\0', 16);
976 E_P16 ((uchar *) passwd, (uchar *) p16);
977
978 #ifdef DEBUG_PASSWORD
979 DEBUG (100, ("nt_lm_owf_gen: pwd, lm#\n"));
980 dump_data (120, passwd, strlen (passwd));
981 dump_data (100, (char *) p16, 16);
982 #endif
983 /* clear out local copy of user's password (just being paranoid). */
984 memset (passwd, '\0', sizeof (passwd));
985 }
986
987 /* Does the des encryption from the NT or LM MD4 hash. */
988 void
989 SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24])
990 {
991 uchar p21[21];
992
993 memset (p21, '\0', 21);
994
995 memcpy (p21, passwd, 16);
996 E_P24 (p21, c8, p24);
997 }
998
999 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
1000 void
1001 NTLMSSPOWFencrypt (uchar passwd[8], uchar * ntlmchalresp, uchar p24[24])
1002 {
1003 uchar p21[21];
1004
1005 memset (p21, '\0', 21);
1006 memcpy (p21, passwd, 8);
1007 memset (p21 + 8, 0xbd, 8);
1008
1009 E_P24 (p21, ntlmchalresp, p24);
1010 #ifdef DEBUG_PASSWORD
1011 DEBUG (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
1012 dump_data (100, (char *) p21, 21);
1013 dump_data (100, (char *) ntlmchalresp, 8);
1014 dump_data (100, (char *) p24, 24);
1015 #endif
1016 }
1017
1018
1019 /* Does the NT MD4 hash then des encryption. */
1020
1021 void
1022 spa_smb_nt_encrypt (uchar * passwd, uchar * c8, uchar * p24)
1023 {
1024 uchar p21[21];
1025
1026 memset (p21, '\0', 21);
1027
1028 E_md4hash (passwd, p21);
1029 SMBOWFencrypt (p21, c8, p24);
1030
1031 #ifdef DEBUG_PASSWORD
1032 DEBUG (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1033 dump_data (100, (char *) p21, 16);
1034 dump_data (100, (char *) c8, 8);
1035 dump_data (100, (char *) p24, 24);
1036 #endif
1037 }
1038
1039 static uint32x A, B, C, D;
1040
1041 static uint32x
1042 F (uint32x X, uint32x Y, uint32x Z)
1043 {
1044 return (X & Y) | ((~X) & Z);
1045 }
1046
1047 static uint32x
1048 G (uint32x X, uint32x Y, uint32x Z)
1049 {
1050 return (X & Y) | (X & Z) | (Y & Z);
1051 }
1052
1053 static uint32x
1054 H (uint32x X, uint32x Y, uint32x Z)
1055 {
1056 return X ^ Y ^ Z;
1057 }
1058
1059 static uint32x
1060 lshift_a (uint32x x, int s)
1061 {
1062 x &= 0xFFFFFFFF;
1063 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1064 }
1065
1066 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1067 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1068 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1069
1070 /* this applies md4 to 64 byte chunks */
1071 static void
1072 spa_mdfour64 (uint32x * M)
1073 {
1074 int j;
1075 uint32x AA, BB, CC, DD;
1076 uint32x X[16];
1077
1078 for (j = 0; j < 16; j++)
1079 X[j] = M[j];
1080
1081 AA = A;
1082 BB = B;
1083 CC = C;
1084 DD = D;
1085
1086 ROUND1 (A, B, C, D, 0, 3);
1087 ROUND1 (D, A, B, C, 1, 7);
1088 ROUND1 (C, D, A, B, 2, 11);
1089 ROUND1 (B, C, D, A, 3, 19);
1090 ROUND1 (A, B, C, D, 4, 3);
1091 ROUND1 (D, A, B, C, 5, 7);
1092 ROUND1 (C, D, A, B, 6, 11);
1093 ROUND1 (B, C, D, A, 7, 19);
1094 ROUND1 (A, B, C, D, 8, 3);
1095 ROUND1 (D, A, B, C, 9, 7);
1096 ROUND1 (C, D, A, B, 10, 11);
1097 ROUND1 (B, C, D, A, 11, 19);
1098 ROUND1 (A, B, C, D, 12, 3);
1099 ROUND1 (D, A, B, C, 13, 7);
1100 ROUND1 (C, D, A, B, 14, 11);
1101 ROUND1 (B, C, D, A, 15, 19);
1102
1103 ROUND2 (A, B, C, D, 0, 3);
1104 ROUND2 (D, A, B, C, 4, 5);
1105 ROUND2 (C, D, A, B, 8, 9);
1106 ROUND2 (B, C, D, A, 12, 13);
1107 ROUND2 (A, B, C, D, 1, 3);
1108 ROUND2 (D, A, B, C, 5, 5);
1109 ROUND2 (C, D, A, B, 9, 9);
1110 ROUND2 (B, C, D, A, 13, 13);
1111 ROUND2 (A, B, C, D, 2, 3);
1112 ROUND2 (D, A, B, C, 6, 5);
1113 ROUND2 (C, D, A, B, 10, 9);
1114 ROUND2 (B, C, D, A, 14, 13);
1115 ROUND2 (A, B, C, D, 3, 3);
1116 ROUND2 (D, A, B, C, 7, 5);
1117 ROUND2 (C, D, A, B, 11, 9);
1118 ROUND2 (B, C, D, A, 15, 13);
1119
1120 ROUND3 (A, B, C, D, 0, 3);
1121 ROUND3 (D, A, B, C, 8, 9);
1122 ROUND3 (C, D, A, B, 4, 11);
1123 ROUND3 (B, C, D, A, 12, 15);
1124 ROUND3 (A, B, C, D, 2, 3);
1125 ROUND3 (D, A, B, C, 10, 9);
1126 ROUND3 (C, D, A, B, 6, 11);
1127 ROUND3 (B, C, D, A, 14, 15);
1128 ROUND3 (A, B, C, D, 1, 3);
1129 ROUND3 (D, A, B, C, 9, 9);
1130 ROUND3 (C, D, A, B, 5, 11);
1131 ROUND3 (B, C, D, A, 13, 15);
1132 ROUND3 (A, B, C, D, 3, 3);
1133 ROUND3 (D, A, B, C, 11, 9);
1134 ROUND3 (C, D, A, B, 7, 11);
1135 ROUND3 (B, C, D, A, 15, 15);
1136
1137 A += AA;
1138 B += BB;
1139 C += CC;
1140 D += DD;
1141
1142 A &= 0xFFFFFFFF;
1143 B &= 0xFFFFFFFF;
1144 C &= 0xFFFFFFFF;
1145 D &= 0xFFFFFFFF;
1146
1147 for (j = 0; j < 16; j++)
1148 X[j] = 0;
1149 }
1150
1151 static void
1152 copy64 (uint32x * M, unsigned char *in)
1153 {
1154 int i;
1155
1156 for (i = 0; i < 16; i++)
1157 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1158 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1159 }
1160
1161 static void
1162 copy4 (unsigned char *out, uint32x x)
1163 {
1164 out[0] = x & 0xFF;
1165 out[1] = (x >> 8) & 0xFF;
1166 out[2] = (x >> 16) & 0xFF;
1167 out[3] = (x >> 24) & 0xFF;
1168 }
1169
1170 /* produce a md4 message digest from data of length n bytes */
1171 void
1172 mdfour (unsigned char *out, unsigned char *in, int n)
1173 {
1174 unsigned char buf[128];
1175 uint32x M[16];
1176 uint32x b = n * 8;
1177 int i;
1178
1179 A = 0x67452301;
1180 B = 0xefcdab89;
1181 C = 0x98badcfe;
1182 D = 0x10325476;
1183
1184 while (n > 64)
1185 {
1186 copy64 (M, in);
1187 spa_mdfour64 (M);
1188 in += 64;
1189 n -= 64;
1190 }
1191
1192 for (i = 0; i < 128; i++)
1193 buf[i] = 0;
1194 memcpy (buf, in, n);
1195 buf[n] = 0x80;
1196
1197 if (n <= 55)
1198 {
1199 copy4 (buf + 56, b);
1200 copy64 (M, buf);
1201 spa_mdfour64 (M);
1202 }
1203 else
1204 {
1205 copy4 (buf + 120, b);
1206 copy64 (M, buf);
1207 spa_mdfour64 (M);
1208 copy64 (M, buf + 64);
1209 spa_mdfour64 (M);
1210 }
1211
1212 for (i = 0; i < 128; i++)
1213 buf[i] = 0;
1214 copy64 (M, buf);
1215
1216 copy4 (out, A);
1217 copy4 (out + 4, B);
1218 copy4 (out + 8, C);
1219 copy4 (out + 12, D);
1220
1221 A = B = C = D = 0;
1222 }
1223
1224 char versionString[] = "libntlm version 0.21";
1225
1226 /* Utility routines that handle NTLM auth structures. */
1227
1228 /* The [IS]VAL macros are to take care of byte order for non-Intel
1229 * Machines -- I think this file is OK, but it hasn't been tested.
1230 * The other files (the ones stolen from Samba) should be OK.
1231 */
1232
1233
1234 /* I am not crazy about these macros -- they seem to have gotten
1235 * a bit complex. A new scheme for handling string/buffer fields
1236 * in the structures probably needs to be designed
1237 */
1238
1239 #define spa_bytes_add(ptr, header, buf, count) \
1240 { \
1241 if (buf && count) \
1242 { \
1243 SSVAL(&ptr->header.len,0,count); \
1244 SSVAL(&ptr->header.maxlen,0,count); \
1245 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1246 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1247 ptr->bufIndex += count; \
1248 } \
1249 else \
1250 { \
1251 ptr->header.len = \
1252 ptr->header.maxlen = 0; \
1253 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1254 } \
1255 }
1256
1257 #define spa_string_add(ptr, header, string) \
1258 { \
1259 char *p = string; \
1260 int len = 0; \
1261 if (p) len = strlen(p); \
1262 spa_bytes_add(ptr, header, ((unsigned char*)p), len); \
1263 }
1264
1265 #define spa_unicode_add_string(ptr, header, string) \
1266 { \
1267 char *p = string; \
1268 unsigned char *b = NULL; \
1269 int len = 0; \
1270 if (p) \
1271 { \
1272 len = strlen(p); \
1273 b = strToUnicode(p); \
1274 } \
1275 spa_bytes_add(ptr, header, b, len*2); \
1276 }
1277
1278
1279 #define GetUnicodeString(structPtr, header) \
1280 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1281 #define GetString(structPtr, header) \
1282 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1283 #define DumpBuffer(fp, structPtr, header) \
1284 dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1285
1286
1287 static void
1288 dumpRaw (FILE * fp, unsigned char *buf, size_t len)
1289 {
1290 int i;
1291
1292 for (i = 0; i < len; ++i)
1293 fprintf (fp, "%02x ", buf[i]);
1294
1295 fprintf (fp, "\n");
1296 }
1297
1298 char *
1299 unicodeToString (char *p, size_t len)
1300 {
1301 int i;
1302 static char buf[1024];
1303
1304 assert (len + 1 < sizeof buf);
1305
1306 for (i = 0; i < len; ++i)
1307 {
1308 buf[i] = *p & 0x7f;
1309 p += 2;
1310 }
1311
1312 buf[i] = '\0';
1313 return buf;
1314 }
1315
1316 static unsigned char *
1317 strToUnicode (char *p)
1318 {
1319 static unsigned char buf[1024];
1320 size_t l = strlen (p);
1321 int i = 0;
1322
1323 assert (l * 2 < sizeof buf);
1324
1325 while (l--)
1326 {
1327 buf[i++] = *p++;
1328 buf[i++] = 0;
1329 }
1330
1331 return buf;
1332 }
1333
1334 static unsigned char *
1335 toString (char *p, size_t len)
1336 {
1337 static unsigned char buf[1024];
1338
1339 assert (len + 1 < sizeof buf);
1340
1341 memcpy (buf, p, len);
1342 buf[len] = 0;
1343 return buf;
1344 }
1345
1346 void
1347 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1348 {
1349 fprintf (fp, "NTLM Request:\n");
1350 fprintf (fp, " Ident = %s\n", request->ident);
1351 fprintf (fp, " mType = %d\n", IVAL (&request->msgType, 0));
1352 fprintf (fp, " Flags = %08x\n", IVAL (&request->flags, 0));
1353 fprintf (fp, " User = %s\n", GetString (request, user));
1354 fprintf (fp, " Domain = %s\n", GetString (request, domain));
1355 }
1356
1357 void
1358 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1359 {
1360 fprintf (fp, "NTLM Challenge:\n");
1361 fprintf (fp, " Ident = %s\n", challenge->ident);
1362 fprintf (fp, " mType = %d\n", IVAL (&challenge->msgType, 0));
1363 fprintf (fp, " Domain = %s\n", GetUnicodeString (challenge, uDomain));
1364 fprintf (fp, " Flags = %08x\n", IVAL (&challenge->flags, 0));
1365 fprintf (fp, " Challenge = ");
1366 dumpRaw (fp, challenge->challengeData, 8);
1367 }
1368
1369 void
1370 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1371 {
1372 fprintf (fp, "NTLM Response:\n");
1373 fprintf (fp, " Ident = %s\n", response->ident);
1374 fprintf (fp, " mType = %d\n", IVAL (&response->msgType, 0));
1375 fprintf (fp, " LmResp = ");
1376 DumpBuffer (fp, response, lmResponse);
1377 fprintf (fp, " NTResp = ");
1378 DumpBuffer (fp, response, ntResponse);
1379 fprintf (fp, " Domain = %s\n", GetUnicodeString (response, uDomain));
1380 fprintf (fp, " User = %s\n", GetUnicodeString (response, uUser));
1381 fprintf (fp, " Wks = %s\n", GetUnicodeString (response, uWks));
1382 fprintf (fp, " sKey = ");
1383 DumpBuffer (fp, response, sessionKey);
1384 fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0));
1385 }
1386
1387 void
1388 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1389 {
1390 char *u = strdup (user);
1391 char *p = strchr (u, '@');
1392
1393 if (p)
1394 {
1395 if (!domain)
1396 domain = p + 1;
1397 *p = '\0';
1398 }
1399
1400 request->bufIndex = 0;
1401 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1402 SIVAL (&request->msgType, 0, 1);
1403 SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */
1404 spa_string_add (request, user, u);
1405 spa_string_add (request, domain, domain);
1406 free (u);
1407 }
1408
1409
1410
1411 void
1412 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1413 {
1414 char chalstr[8];
1415 int i;
1416 int p = (int)getpid();
1417 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1418
1419 request = request; /* Added by PH to stop compilers whinging */
1420
1421 /* Ensure challenge data is cleared, in case it isn't all used. This
1422 patch added by PH on suggestion of Russell King */
1423
1424 memset(challenge, 0, sizeof(SPAAuthChallenge));
1425
1426 challenge->bufIndex = 0;
1427 memcpy (challenge->ident, "NTLMSSP\0", 8);
1428 SIVAL (&challenge->msgType, 0, 2);
1429 SIVAL (&challenge->flags, 0, 0x00008201);
1430 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1431 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1432 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1433
1434 /* generate eight pseudo random bytes (method ripped from host.c) */
1435
1436 for(i=0;i<8;i++) {
1437 chalstr[i] = (unsigned char)(random_seed >> 16) % 256;
1438 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1439 };
1440
1441 memcpy(challenge->challengeData,chalstr,8);
1442 }
1443
1444
1445
1446
1447 /* This is the original source of this function, preserved here for reference.
1448 The new version below was re-organized by PH following a patch and some further
1449 suggestions from Mark Lyda to fix the problem that is described at the head of
1450 this module. At the same time, I removed the untidiness in the code below that
1451 involves the "d" and "domain" variables. */
1452
1453 #ifdef NEVER
1454 void
1455 spa_build_auth_response (SPAAuthChallenge * challenge,
1456 SPAAuthResponse * response, char *user,
1457 char *password)
1458 {
1459 uint8x lmRespData[24];
1460 uint8x ntRespData[24];
1461 char *d = strdup (GetUnicodeString (challenge, uDomain));
1462 char *domain = d;
1463 char *u = strdup (user);
1464 char *p = strchr (u, '@');
1465
1466 if (p)
1467 {
1468 domain = p + 1;
1469 *p = '\0';
1470 }
1471
1472 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1473 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1474
1475 response->bufIndex = 0;
1476 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1477 SIVAL (&response->msgType, 0, 3);
1478
1479 spa_bytes_add (response, lmResponse, lmRespData, 24);
1480 spa_bytes_add (response, ntResponse, ntRespData, 24);
1481 spa_unicode_add_string (response, uDomain, domain);
1482 spa_unicode_add_string (response, uUser, u);
1483 spa_unicode_add_string (response, uWks, u);
1484 spa_string_add (response, sessionKey, NULL);
1485
1486 response->flags = challenge->flags;
1487
1488 free (d);
1489 free (u);
1490 }
1491 #endif
1492
1493
1494 /* This is the re-organized version (see comments above) */
1495
1496 void
1497 spa_build_auth_response (SPAAuthChallenge * challenge,
1498 SPAAuthResponse * response, char *user,
1499 char *password)
1500 {
1501 uint8x lmRespData[24];
1502 uint8x ntRespData[24];
1503 uint32x cf = IVAL(&challenge->flags, 0);
1504 char *u = strdup (user);
1505 char *p = strchr (u, '@');
1506 char *d = NULL;
1507 char *domain;
1508
1509 if (p)
1510 {
1511 domain = p + 1;
1512 *p = '\0';
1513 }
1514
1515 else domain = d = strdup((cf & 0x1)?
1516 (const char *)GetUnicodeString(challenge, uDomain) :
1517 (const char *)GetString(challenge, uDomain));
1518
1519 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1520 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1521
1522 response->bufIndex = 0;
1523 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1524 SIVAL (&response->msgType, 0, 3);
1525
1526 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1527 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1528
1529 if (cf & 0x1) { /* Unicode Text */
1530 spa_unicode_add_string (response, uDomain, domain);
1531 spa_unicode_add_string (response, uUser, u);
1532 spa_unicode_add_string (response, uWks, u);
1533 } else { /* OEM Text */
1534 spa_string_add (response, uDomain, domain);
1535 spa_string_add (response, uUser, u);
1536 spa_string_add (response, uWks, u);
1537 }
1538
1539 spa_string_add (response, sessionKey, NULL);
1540 response->flags = challenge->flags;
1541
1542 if (d != NULL) free (d);
1543 free (u);
1544 }