1 /* $Cambridge: exim/src/src/auths/auth-spa.c,v 1.3 2005/08/02 13:23:19 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
8 * This file provides the necessary methods for authenticating with
9 * Microsoft's Secure Password Authentication.
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).
14 * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
15 * support server authentication mode.
17 * Mark Lyda provided a patch to solve this problem:
19 - Exim is indicating in its Authentication Request message (Type 1) that it
20 can transmit text in either Unicode or OEM format.
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.
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.
29 * http://www.innovation.ch/java/ntlm.html
30 * http://www.kuro5hin.org/story/2002/4/28/1436/66154
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.
37 * typedef signed short int16;
38 * typedef unsigned short uint16;
39 * typedef unsigned uint32;
40 * typedef unsigned char uint8;
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.
51 int main (int argc, char ** argv)
53 SPAAuthRequest request;
54 SPAAuthChallenge challenge;
55 SPAAuthResponse response;
58 char *username, *password, *domain, *challenge_str;
62 printf ("Usage: %s <username> <password> [SPA Challenge]\n",
71 spa_build_auth_request (&request, username, domain);
73 spa_bits_to_base64 (msgbuf, (unsigned char*)&request,
74 spa_request_length(&request));
76 printf ("SPA Login request for username=%s:\n %s\n",
81 printf ("Run: %s <username> <password> [NTLM Challenge] " \
82 "to complete authenitcation\n", argv [0]);
86 challenge_str = argv [3];
88 if (spa_base64_to_bits ((char *)&challenge, sizeof(challenge),
89 (const char *)(challenge_str))<0)
91 printf("bad base64 data in challenge: %s\n", challenge_str);
95 spa_build_auth_response (&challenge, &response, username, password);
96 spa_bits_to_base64 (msgbuf, (unsigned char*)&response,
97 spa_request_length(&response));
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);
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:
112 Unix SMB/Netbios implementation.
115 a partial implementation of DES designed for use in the
116 SMB authentication protocol
118 Copyright (C) Andrew Tridgell 1998
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.
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.
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.
138 This code makes no attempt to be fast! In fact, it is a very
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)
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.
149 There is no entry point into this code that allows normal DES operation.
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)
160 extern int DEBUGLEVEL;
162 #include <sys/types.h> /* For size_t */
163 #include "auth-spa.h"
173 typedef unsigned char uchar;
184 #define RW_PCVAL(read,inbuf,outbuf,len) \
185 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
186 else { PSCVAL(inbuf,0,outbuf,len); } }
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); } } }
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); } } }
196 #define RW_CVAL(read, inbuf, outbuf, offset) \
197 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
198 else { SCVAL(inbuf,offset,outbuf); } }
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); } } }
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); } } }
208 #undef CAREFUL_ALIGNMENT
210 /* we know that the 386 can handle misalignment and has the "right"
213 #define CAREFUL_ALIGNMENT 0
216 #ifndef CAREFUL_ALIGNMENT
217 #define CAREFUL_ALIGNMENT 1
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))
225 #if CAREFUL_ALIGNMENT
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)))
238 #else /* CAREFUL_ALIGNMENT */
240 /* this handles things for architectures like the 386 that can handle
243 WARNING: This section is dependent on the length of int16x and int32x
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)))
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))
259 #endif /* CAREFUL_ALIGNMENT */
261 /* macros for reading / writing arrays */
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); }
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]); }
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)
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)
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)))
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))
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)
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)
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])); } } \
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])); } } \
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])); } } \
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)); }
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)); }
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)); }
350 #endif /* _BYTEORDER_H */
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]);
357 void mdfour (unsigned char *out, unsigned char *in, int n);
361 * base64.c -- base-64 conversion routines.
363 * For license terms, see the file COPYING in this directory.
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
370 static const char base64digits[] =
371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
374 static const char base64val[] = {
375 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
377 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
379 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
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
387 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
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) */
393 for (; inlen >= 3; inlen -= 3)
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];
403 unsigned char fragment;
405 *out++ = base64digits[in[0] >> 2];
406 fragment = (in[0] << 4) & 0x30;
408 fragment |= in[1] >> 4;
409 *out++ = base64digits[fragment];
410 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
417 /* The outlength parameter was added by PH, December 2004 */
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 */
424 register unsigned char digit1, digit2, digit3, digit4;
426 if (in[0] == '+' && in[1] == ' ')
433 if (len >= outlength) /* Added by PH */
434 return (-1); /* Added by PH */
436 if (DECODE64 (digit1) == BAD)
439 if (DECODE64 (digit2) == BAD)
442 if (digit3 != '=' && DECODE64 (digit3) == BAD)
445 if (digit4 != '=' && DECODE64 (digit4) == BAD)
448 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
452 if (len >= outlength) /* Added by PH */
453 return (-1); /* Added by PH */
455 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
459 if (len >= outlength) /* Added by PH */
460 return (-1); /* Added by PH */
461 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
466 while (*in && *in != '\r' && digit4 != '=');
472 #define uchar unsigned char
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
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
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
504 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
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
514 static uchar perm5[32] = { 16, 7, 20, 21,
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
536 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}}
581 permute (char *out, char *in, uchar * p, int n)
584 for (i = 0; i < n; i++)
585 out[i] = in[p[i] - 1];
589 lshift (char *d, int count, int n)
593 for (i = 0; i < n; i++)
594 out[i] = d[(i + count) % n];
595 for (i = 0; i < n; i++)
600 concat (char *out, char *in1, char *in2, int l1, int l2)
609 xor (char *out, char *in1, char *in2, int n)
612 for (i = 0; i < n; i++)
613 out[i] = in1[i] ^ in2[i];
617 dohash (char *out, char *in, char *key, int forw)
629 permute (pk1, key, perm1, 56);
631 for (i = 0; i < 28; i++)
633 for (i = 0; i < 28; i++)
636 for (i = 0; i < 16; i++)
638 lshift (c, sc[i], 28);
639 lshift (d, sc[i], 28);
641 concat (cd, c, d, 28, 28);
642 permute (ki[i], cd, perm2, 48);
645 permute (pd1, in, perm3, 64);
647 for (j = 0; j < 32; j++)
653 for (i = 0; i < 16; i++)
662 permute (er, r, perm4, 48);
664 xor (erk, er, ki[forw ? i : 15 - i], 48);
666 for (j = 0; j < 8; j++)
667 for (k = 0; k < 6; k++)
668 b[j][k] = erk[j * 6 + k];
670 for (j = 0; j < 8; j++)
673 m = (b[j][0] << 1) | b[j][5];
675 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
677 for (k = 0; k < 4; k++)
678 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
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);
686 xor (r2, l, pcb, 32);
688 for (j = 0; j < 32; j++)
691 for (j = 0; j < 32; j++)
695 concat (rl, r, l, 32, 32);
697 permute (out, rl, perm6, 64);
701 str_to_key (unsigned char *str, unsigned char *key)
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++)
715 key[i] = (key[i] << 1);
721 smbhash (unsigned char *out, unsigned char *in, unsigned char *key, int forw)
727 unsigned char key2[8];
729 str_to_key (key, key2);
731 for (i = 0; i < 64; i++)
733 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
734 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
738 dohash (outb, inb, keyb, forw);
740 for (i = 0; i < 8; i++)
745 for (i = 0; i < 64; i++)
748 out[i / 8] |= (1 << (7 - (i % 8)));
753 E_P16 (unsigned char *p14, unsigned char *p16)
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);
761 E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24)
763 smbhash (p24, c8, p21, 1);
764 smbhash (p24 + 8, c8, p21 + 7, 1);
765 smbhash (p24 + 16, c8, p21 + 14, 1);
769 D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out)
771 smbhash (out, in, p14, 0);
772 smbhash (out + 8, in + 8, p14 + 7, 0);
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 ****************************************************************************/
781 StrnCpy (char *dest, const char *src, size_t n)
791 while (n-- && (*d++ = *src++));
797 skip_multibyte_char (char c)
799 /* bogus if to get rid of unused compiler warning */
807 /*******************************************************************
808 safe string copy into a known length string. maxlength does not
809 include the terminating zero.
810 ********************************************************************/
813 safe_strcpy (char *dest, const char *src, size_t maxlength)
819 DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
833 DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
834 (int) (len - maxlength), src));
838 memcpy (dest, src, len);
850 size_t skip = skip_multibyte_char (*s);
855 if (islower ((unsigned char)(*s)))
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
871 spa_smb_encrypt (uchar * passwd, uchar * c8, uchar * p24)
873 uchar p14[15], p21[21];
875 memset (p21, '\0', 21);
876 memset (p14, '\0', 14);
877 StrnCpy ((char *) p14, (char *) passwd, 14);
879 strupper ((char *) p14);
882 SMBOWFencrypt (p21, c8, p24);
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);
892 /* Routines for Windows NT MD4 Hash functions. */
894 _my_wcslen (int16x * str)
903 * Convert a string into an NT UNICODE string.
904 * Note that regardless of processor type
905 * this must be in intel (little-endian)
910 _my_mbstowcs (int16x * dst, uchar * src, int len)
915 for (i = 0; i < len; i++)
928 * Creates the MD4 Hash of the users password in NT UNICODE.
932 E_md4hash (uchar * passwd, uchar * p16)
937 /* Password cannot be longer than 128 characters */
938 len = strlen ((char *) passwd);
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);
947 mdfour (p16, (unsigned char *) wpwd, len);
950 /* Does both the NT and LM owfs of a user's password */
952 nt_lm_owf_gen (char *pwd, uchar nt_p16[16], uchar p16[16])
956 memset (passwd, '\0', 130);
957 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
959 /* Calculate the MD4 hash (NT compatible) of the password */
960 memset (nt_p16, '\0', 16);
961 E_md4hash ((uchar *) passwd, nt_p16);
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);
969 /* Mangle the passwords into Lanman format */
973 /* Calculate the SMB (lanman) hash functions of the password */
975 memset (p16, '\0', 16);
976 E_P16 ((uchar *) passwd, (uchar *) p16);
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);
983 /* clear out local copy of user's password (just being paranoid). */
984 memset (passwd, '\0', sizeof (passwd));
987 /* Does the des encryption from the NT or LM MD4 hash. */
989 SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24])
993 memset (p21, '\0', 21);
995 memcpy (p21, passwd, 16);
996 E_P24 (p21, c8, p24);
999 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
1001 NTLMSSPOWFencrypt (uchar passwd[8], uchar * ntlmchalresp, uchar p24[24])
1005 memset (p21, '\0', 21);
1006 memcpy (p21, passwd, 8);
1007 memset (p21 + 8, 0xbd, 8);
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);
1019 /* Does the NT MD4 hash then des encryption. */
1022 spa_smb_nt_encrypt (uchar * passwd, uchar * c8, uchar * p24)
1026 memset (p21, '\0', 21);
1028 E_md4hash (passwd, p21);
1029 SMBOWFencrypt (p21, c8, p24);
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);
1039 static uint32x A, B, C, D;
1042 F (uint32x X, uint32x Y, uint32x Z)
1044 return (X & Y) | ((~X) & Z);
1048 G (uint32x X, uint32x Y, uint32x Z)
1050 return (X & Y) | (X & Z) | (Y & Z);
1054 H (uint32x X, uint32x Y, uint32x Z)
1060 lshift_a (uint32x x, int s)
1063 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
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)
1070 /* this applies md4 to 64 byte chunks */
1072 spa_mdfour64 (uint32x * M)
1075 uint32x AA, BB, CC, DD;
1078 for (j = 0; j < 16; j++)
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);
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);
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);
1147 for (j = 0; j < 16; j++)
1152 copy64 (uint32x * M, unsigned char *in)
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);
1162 copy4 (unsigned char *out, uint32x x)
1165 out[1] = (x >> 8) & 0xFF;
1166 out[2] = (x >> 16) & 0xFF;
1167 out[3] = (x >> 24) & 0xFF;
1170 /* produce a md4 message digest from data of length n bytes */
1172 mdfour (unsigned char *out, unsigned char *in, int n)
1174 unsigned char buf[128];
1192 for (i = 0; i < 128; i++)
1194 memcpy (buf, in, n);
1199 copy4 (buf + 56, b);
1205 copy4 (buf + 120, b);
1208 copy64 (M, buf + 64);
1212 for (i = 0; i < 128; i++)
1219 copy4 (out + 12, D);
1224 char versionString[] = "libntlm version 0.21";
1226 /* Utility routines that handle NTLM auth structures. */
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.
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
1239 #define spa_bytes_add(ptr, header, buf, count) \
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; \
1252 ptr->header.maxlen = 0; \
1253 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1257 #define spa_string_add(ptr, header, string) \
1261 if (p) len = strlen(p); \
1262 spa_bytes_add(ptr, header, ((unsigned char*)p), len); \
1265 #define spa_unicode_add_string(ptr, header, string) \
1268 unsigned char *b = NULL; \
1273 b = strToUnicode(p); \
1275 spa_bytes_add(ptr, header, b, len*2); \
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))
1288 dumpRaw (FILE * fp, unsigned char *buf, size_t len)
1292 for (i = 0; i < len; ++i)
1293 fprintf (fp, "%02x ", buf[i]);
1299 unicodeToString (char *p, size_t len)
1302 static char buf[1024];
1304 assert (len + 1 < sizeof buf);
1306 for (i = 0; i < len; ++i)
1316 static unsigned char *
1317 strToUnicode (char *p)
1319 static unsigned char buf[1024];
1320 size_t l = strlen (p);
1323 assert (l * 2 < sizeof buf);
1334 static unsigned char *
1335 toString (char *p, size_t len)
1337 static unsigned char buf[1024];
1339 assert (len + 1 < sizeof buf);
1341 memcpy (buf, p, len);
1347 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
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));
1358 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
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);
1370 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
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));
1388 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1390 char *u = strdup (user);
1391 char *p = strchr (u, '@');
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);
1412 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1416 int p = (int)getpid();
1417 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1419 request = request; /* Added by PH to stop compilers whinging */
1421 /* Ensure challenge data is cleared, in case it isn't all used. This
1422 patch added by PH on suggestion of Russell King */
1424 memset(challenge, 0, sizeof(SPAAuthChallenge));
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);
1434 /* generate eight pseudo random bytes (method ripped from host.c) */
1437 chalstr[i] = (unsigned char)(random_seed >> 16) % 256;
1438 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1441 memcpy(challenge->challengeData,chalstr,8);
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. */
1455 spa_build_auth_response (SPAAuthChallenge * challenge,
1456 SPAAuthResponse * response, char *user,
1459 uint8x lmRespData[24];
1460 uint8x ntRespData[24];
1461 char *d = strdup (GetUnicodeString (challenge, uDomain));
1463 char *u = strdup (user);
1464 char *p = strchr (u, '@');
1472 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1473 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1475 response->bufIndex = 0;
1476 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1477 SIVAL (&response->msgType, 0, 3);
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);
1486 response->flags = challenge->flags;
1494 /* This is the re-organized version (see comments above) */
1497 spa_build_auth_response (SPAAuthChallenge * challenge,
1498 SPAAuthResponse * response, char *user,
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, '@');
1515 else domain = d = strdup((cf & 0x1)?
1516 (const char *)GetUnicodeString(challenge, uDomain) :
1517 (const char *)GetString(challenge, uDomain));
1519 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1520 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1522 response->bufIndex = 0;
1523 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1524 SIVAL (&response->msgType, 0, 3);
1526 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1527 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
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);
1539 spa_string_add (response, sessionKey, NULL);
1540 response->flags = challenge->flags;
1542 if (d != NULL) free (d);