1 /* $Cambridge: exim/src/src/auths/auth-spa.c,v 1.2 2004/12/29 10:55:58 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 spa_build_auth_response (&challenge, &response, username, password);
89 spa_bits_to_base64 (msgbuf, (unsigned char*)&response,
90 spa_request_length(&response));
92 printf ("SPA Response to challenge:\n %s\n for " \
93 "username=%s, password=%s:\n %s\n",
94 argv[3], argv [1], argv [2], msgbuf);
99 * All the client code used here was torn by Marc Prud'hommeaux out of the
100 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
101 * Previous comments are below:
105 Unix SMB/Netbios implementation.
108 a partial implementation of DES designed for use in the
109 SMB authentication protocol
111 Copyright (C) Andrew Tridgell 1998
113 This program is free software; you can redistribute it and/or modify
114 it under the terms of the GNU General Public License as published by
115 the Free Software Foundation; either version 2 of the License, or
116 (at your option) any later version.
118 This program is distributed in the hope that it will be useful,
119 but WITHOUT ANY WARRANTY; without even the implied warranty of
120 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
121 GNU General Public License for more details.
123 You should have received a copy of the GNU General Public License
124 along with this program; if not, write to the Free Software
125 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
131 This code makes no attempt to be fast! In fact, it is a very
134 This code is NOT a complete DES implementation. It implements only
135 the minimum necessary for SMB authentication, as used by all SMB
136 products (including every copy of Microsoft Windows95 ever sold)
138 In particular, it can only do a unchained forward DES pass. This
139 means it is not possible to use this code for encryption/decryption
140 of data, instead it is only useful as a "hash" algorithm.
142 There is no entry point into this code that allows normal DES operation.
144 I believe this means that this code does not come under ITAR
145 regulations but this is NOT a legal opinion. If you are concerned
146 about the applicability of ITAR regulations to this code then you
147 should confirm it for yourself (and maybe let me know if you come
148 up with a different answer to the one above)
153 extern int DEBUGLEVEL;
155 #include <sys/types.h> /* For size_t */
156 #include "auth-spa.h"
166 typedef unsigned char uchar;
177 #define RW_PCVAL(read,inbuf,outbuf,len) \
178 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
179 else { PSCVAL(inbuf,0,outbuf,len); } }
181 #define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
182 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
183 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
185 #define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
186 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
187 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
189 #define RW_CVAL(read, inbuf, outbuf, offset) \
190 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
191 else { SCVAL(inbuf,offset,outbuf); } }
193 #define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
194 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
195 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
197 #define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
198 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
199 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
201 #undef CAREFUL_ALIGNMENT
203 /* we know that the 386 can handle misalignment and has the "right"
206 #define CAREFUL_ALIGNMENT 0
209 #ifndef CAREFUL_ALIGNMENT
210 #define CAREFUL_ALIGNMENT 1
213 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
214 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
215 #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
218 #if CAREFUL_ALIGNMENT
220 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
221 #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
222 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
223 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
224 #define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
225 #define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
226 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
227 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
228 #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
229 #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
231 #else /* CAREFUL_ALIGNMENT */
233 /* this handles things for architectures like the 386 that can handle
236 WARNING: This section is dependent on the length of int16x and int32x
240 /* get single value from an SMB buffer */
241 #define SVAL(buf,pos) (*(uint16x *)((char *)(buf) + (pos)))
242 #define IVAL(buf,pos) (*(uint32x *)((char *)(buf) + (pos)))
243 #define SVALS(buf,pos) (*(int16x *)((char *)(buf) + (pos)))
244 #define IVALS(buf,pos) (*(int32x *)((char *)(buf) + (pos)))
246 /* store single value in an SMB buffer */
247 #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
248 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
249 #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
250 #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
252 #endif /* CAREFUL_ALIGNMENT */
254 /* macros for reading / writing arrays */
256 #define SMBMACRO(macro,buf,pos,val,len,size) \
257 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
259 #define SSMBMACRO(macro,buf,pos,val,len,size) \
260 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
262 /* reads multiple data from an SMB buffer */
263 #define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
264 #define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
265 #define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
266 #define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
267 #define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
268 #define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
270 /* stores multiple data in an SMB buffer */
271 #define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
272 #define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
273 #define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
274 #define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
275 #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
276 #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
279 /* now the reverse routines - these are used in nmb packets (mostly) */
280 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
281 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
283 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))
284 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))
285 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))
286 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))
287 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
288 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
289 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
290 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
292 /* reads multiple data from an SMB buffer (big-endian) */
293 #define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
294 #define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
295 #define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
296 #define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
298 /* stores multiple data in an SMB buffer (big-endian) */
299 #define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
300 #define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
301 #define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
302 #define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
304 #define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
305 { RW_PCVAL(read,inbuf,outbuf,len) \
306 DEBUG(5,("%s%04x %s: ", \
307 tab_depth(depth), base,string)); \
308 if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
309 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
312 #define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
313 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
314 DEBUG(5,("%s%04x %s: ", \
315 tab_depth(depth), base,string)); \
316 if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
317 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
320 #define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
321 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
322 DEBUG(5,("%s%04x %s: ", \
323 tab_depth(depth), base,string)); \
324 if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
325 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
328 #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
329 { RW_CVAL(read,inbuf,outbuf,0) \
330 DEBUG(5,("%s%04x %s: %02x\n", \
331 tab_depth(depth), base, string, outbuf)); }
333 #define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
334 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
335 DEBUG(5,("%s%04x %s: %04x\n", \
336 tab_depth(depth), base, string, outbuf)); }
338 #define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
339 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
340 DEBUG(5,("%s%04x %s: %08x\n", \
341 tab_depth(depth), base, string, outbuf)); }
343 #endif /* _BYTEORDER_H */
345 void E_P16 (unsigned char *p14, unsigned char *p16);
346 void E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24);
347 void D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out);
348 void SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24]);
350 void mdfour (unsigned char *out, unsigned char *in, int n);
354 * base64.c -- base-64 conversion routines.
356 * For license terms, see the file COPYING in this directory.
358 * This base 64 encoding is defined in RFC2045 section 6.8,
359 * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
363 static const char base64digits[] =
364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
367 static const char base64val[] = {
368 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
370 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
372 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
374 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
375 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
376 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
377 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
378 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
380 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
383 spa_bits_to_base64 (unsigned char *out, const unsigned char *in, int inlen)
384 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
386 for (; inlen >= 3; inlen -= 3)
388 *out++ = base64digits[in[0] >> 2];
389 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
390 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
391 *out++ = base64digits[in[2] & 0x3f];
396 unsigned char fragment;
398 *out++ = base64digits[in[0] >> 2];
399 fragment = (in[0] << 4) & 0x30;
401 fragment |= in[1] >> 4;
402 *out++ = base64digits[fragment];
403 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
410 /* The outlength parameter was added by PH, December 2004 */
413 spa_base64_to_bits (char *out, int outlength, const char *in)
414 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
417 register unsigned char digit1, digit2, digit3, digit4;
419 if (in[0] == '+' && in[1] == ' ')
426 if (len >= outlength) /* Added by PH */
427 return (-1); /* Added by PH */
429 if (DECODE64 (digit1) == BAD)
432 if (DECODE64 (digit2) == BAD)
435 if (digit3 != '=' && DECODE64 (digit3) == BAD)
438 if (digit4 != '=' && DECODE64 (digit4) == BAD)
441 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
445 if (len >= outlength) /* Added by PH */
446 return (-1); /* Added by PH */
448 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
452 if (len >= outlength) /* Added by PH */
453 return (-1); /* Added by PH */
454 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
459 while (*in && *in != '\r' && digit4 != '=');
465 #define uchar unsigned char
467 static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
468 1, 58, 50, 42, 34, 26, 18,
469 10, 2, 59, 51, 43, 35, 27,
470 19, 11, 3, 60, 52, 44, 36,
471 63, 55, 47, 39, 31, 23, 15,
472 7, 62, 54, 46, 38, 30, 22,
473 14, 6, 61, 53, 45, 37, 29,
474 21, 13, 5, 28, 20, 12, 4
477 static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
478 3, 28, 15, 6, 21, 10,
479 23, 19, 12, 4, 26, 8,
480 16, 7, 27, 20, 13, 2,
481 41, 52, 31, 37, 47, 55,
482 30, 40, 51, 45, 33, 48,
483 44, 49, 39, 56, 34, 53,
484 46, 42, 50, 36, 29, 32
487 static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
488 60, 52, 44, 36, 28, 20, 12, 4,
489 62, 54, 46, 38, 30, 22, 14, 6,
490 64, 56, 48, 40, 32, 24, 16, 8,
491 57, 49, 41, 33, 25, 17, 9, 1,
492 59, 51, 43, 35, 27, 19, 11, 3,
493 61, 53, 45, 37, 29, 21, 13, 5,
494 63, 55, 47, 39, 31, 23, 15, 7
497 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
499 8, 9, 10, 11, 12, 13,
500 12, 13, 14, 15, 16, 17,
501 16, 17, 18, 19, 20, 21,
502 20, 21, 22, 23, 24, 25,
503 24, 25, 26, 27, 28, 29,
504 28, 29, 30, 31, 32, 1
507 static uchar perm5[32] = { 16, 7, 20, 21,
518 static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
519 39, 7, 47, 15, 55, 23, 63, 31,
520 38, 6, 46, 14, 54, 22, 62, 30,
521 37, 5, 45, 13, 53, 21, 61, 29,
522 36, 4, 44, 12, 52, 20, 60, 28,
523 35, 3, 43, 11, 51, 19, 59, 27,
524 34, 2, 42, 10, 50, 18, 58, 26,
525 33, 1, 41, 9, 49, 17, 57, 25
529 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
531 static uchar sbox[8][4][16] = {
532 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
533 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
534 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
535 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
537 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
538 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
539 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
540 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
542 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
543 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
544 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
545 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
547 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
548 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
549 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
550 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
552 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
553 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
554 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
555 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
557 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
558 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
559 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
560 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
562 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
563 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
564 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
565 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
567 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
568 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
569 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
570 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
574 permute (char *out, char *in, uchar * p, int n)
577 for (i = 0; i < n; i++)
578 out[i] = in[p[i] - 1];
582 lshift (char *d, int count, int n)
586 for (i = 0; i < n; i++)
587 out[i] = d[(i + count) % n];
588 for (i = 0; i < n; i++)
593 concat (char *out, char *in1, char *in2, int l1, int l2)
602 xor (char *out, char *in1, char *in2, int n)
605 for (i = 0; i < n; i++)
606 out[i] = in1[i] ^ in2[i];
610 dohash (char *out, char *in, char *key, int forw)
622 permute (pk1, key, perm1, 56);
624 for (i = 0; i < 28; i++)
626 for (i = 0; i < 28; i++)
629 for (i = 0; i < 16; i++)
631 lshift (c, sc[i], 28);
632 lshift (d, sc[i], 28);
634 concat (cd, c, d, 28, 28);
635 permute (ki[i], cd, perm2, 48);
638 permute (pd1, in, perm3, 64);
640 for (j = 0; j < 32; j++)
646 for (i = 0; i < 16; i++)
655 permute (er, r, perm4, 48);
657 xor (erk, er, ki[forw ? i : 15 - i], 48);
659 for (j = 0; j < 8; j++)
660 for (k = 0; k < 6; k++)
661 b[j][k] = erk[j * 6 + k];
663 for (j = 0; j < 8; j++)
666 m = (b[j][0] << 1) | b[j][5];
668 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
670 for (k = 0; k < 4; k++)
671 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
674 for (j = 0; j < 8; j++)
675 for (k = 0; k < 4; k++)
676 cb[j * 4 + k] = b[j][k];
677 permute (pcb, cb, perm5, 32);
679 xor (r2, l, pcb, 32);
681 for (j = 0; j < 32; j++)
684 for (j = 0; j < 32; j++)
688 concat (rl, r, l, 32, 32);
690 permute (out, rl, perm6, 64);
694 str_to_key (unsigned char *str, unsigned char *key)
698 key[0] = str[0] >> 1;
699 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
700 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
701 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
702 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
703 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
704 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
705 key[7] = str[6] & 0x7F;
706 for (i = 0; i < 8; i++)
708 key[i] = (key[i] << 1);
714 smbhash (unsigned char *out, unsigned char *in, unsigned char *key, int forw)
720 unsigned char key2[8];
722 str_to_key (key, key2);
724 for (i = 0; i < 64; i++)
726 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
727 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
731 dohash (outb, inb, keyb, forw);
733 for (i = 0; i < 8; i++)
738 for (i = 0; i < 64; i++)
741 out[i / 8] |= (1 << (7 - (i % 8)));
746 E_P16 (unsigned char *p14, unsigned char *p16)
748 unsigned char sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
749 smbhash (p16, sp8, p14, 1);
750 smbhash (p16 + 8, sp8, p14 + 7, 1);
754 E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24)
756 smbhash (p24, c8, p21, 1);
757 smbhash (p24 + 8, c8, p21 + 7, 1);
758 smbhash (p24 + 16, c8, p21 + 14, 1);
762 D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out)
764 smbhash (out, in, p14, 0);
765 smbhash (out + 8, in + 8, p14 + 7, 0);
768 /****************************************************************************
769 Like strncpy but always null terminates. Make sure there is room!
770 The variable n should always be one less than the available size.
771 ****************************************************************************/
774 StrnCpy (char *dest, const char *src, size_t n)
784 while (n-- && (*d++ = *src++));
790 skip_multibyte_char (char c)
792 /* bogus if to get rid of unused compiler warning */
800 /*******************************************************************
801 safe string copy into a known length string. maxlength does not
802 include the terminating zero.
803 ********************************************************************/
806 safe_strcpy (char *dest, const char *src, size_t maxlength)
812 DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
826 DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
827 (int) (len - maxlength), src));
831 memcpy (dest, src, len);
843 size_t skip = skip_multibyte_char (*s);
848 if (islower ((unsigned char)(*s)))
858 This implements the X/Open SMB password encryption
859 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
860 encrypted password into p24
864 spa_smb_encrypt (uchar * passwd, uchar * c8, uchar * p24)
866 uchar p14[15], p21[21];
868 memset (p21, '\0', 21);
869 memset (p14, '\0', 14);
870 StrnCpy ((char *) p14, (char *) passwd, 14);
872 strupper ((char *) p14);
875 SMBOWFencrypt (p21, c8, p24);
877 #ifdef DEBUG_PASSWORD
878 DEBUG (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
879 dump_data (100, (char *) p21, 16);
880 dump_data (100, (char *) c8, 8);
881 dump_data (100, (char *) p24, 24);
885 /* Routines for Windows NT MD4 Hash functions. */
887 _my_wcslen (int16x * str)
896 * Convert a string into an NT UNICODE string.
897 * Note that regardless of processor type
898 * this must be in intel (little-endian)
903 _my_mbstowcs (int16x * dst, uchar * src, int len)
908 for (i = 0; i < len; i++)
921 * Creates the MD4 Hash of the users password in NT UNICODE.
925 E_md4hash (uchar * passwd, uchar * p16)
930 /* Password cannot be longer than 128 characters */
931 len = strlen ((char *) passwd);
934 /* Password must be converted to NT unicode */
935 _my_mbstowcs (wpwd, passwd, len);
936 wpwd[len] = 0; /* Ensure string is null terminated */
937 /* Calculate length in bytes */
938 len = _my_wcslen (wpwd) * sizeof (int16x);
940 mdfour (p16, (unsigned char *) wpwd, len);
943 /* Does both the NT and LM owfs of a user's password */
945 nt_lm_owf_gen (char *pwd, uchar nt_p16[16], uchar p16[16])
949 memset (passwd, '\0', 130);
950 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
952 /* Calculate the MD4 hash (NT compatible) of the password */
953 memset (nt_p16, '\0', 16);
954 E_md4hash ((uchar *) passwd, nt_p16);
956 #ifdef DEBUG_PASSWORD
957 DEBUG (100, ("nt_lm_owf_gen: pwd, nt#\n"));
958 dump_data (120, passwd, strlen (passwd));
959 dump_data (100, (char *) nt_p16, 16);
962 /* Mangle the passwords into Lanman format */
966 /* Calculate the SMB (lanman) hash functions of the password */
968 memset (p16, '\0', 16);
969 E_P16 ((uchar *) passwd, (uchar *) p16);
971 #ifdef DEBUG_PASSWORD
972 DEBUG (100, ("nt_lm_owf_gen: pwd, lm#\n"));
973 dump_data (120, passwd, strlen (passwd));
974 dump_data (100, (char *) p16, 16);
976 /* clear out local copy of user's password (just being paranoid). */
977 memset (passwd, '\0', sizeof (passwd));
980 /* Does the des encryption from the NT or LM MD4 hash. */
982 SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24])
986 memset (p21, '\0', 21);
988 memcpy (p21, passwd, 16);
989 E_P24 (p21, c8, p24);
992 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
994 NTLMSSPOWFencrypt (uchar passwd[8], uchar * ntlmchalresp, uchar p24[24])
998 memset (p21, '\0', 21);
999 memcpy (p21, passwd, 8);
1000 memset (p21 + 8, 0xbd, 8);
1002 E_P24 (p21, ntlmchalresp, p24);
1003 #ifdef DEBUG_PASSWORD
1004 DEBUG (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
1005 dump_data (100, (char *) p21, 21);
1006 dump_data (100, (char *) ntlmchalresp, 8);
1007 dump_data (100, (char *) p24, 24);
1012 /* Does the NT MD4 hash then des encryption. */
1015 spa_smb_nt_encrypt (uchar * passwd, uchar * c8, uchar * p24)
1019 memset (p21, '\0', 21);
1021 E_md4hash (passwd, p21);
1022 SMBOWFencrypt (p21, c8, p24);
1024 #ifdef DEBUG_PASSWORD
1025 DEBUG (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1026 dump_data (100, (char *) p21, 16);
1027 dump_data (100, (char *) c8, 8);
1028 dump_data (100, (char *) p24, 24);
1032 static uint32x A, B, C, D;
1035 F (uint32x X, uint32x Y, uint32x Z)
1037 return (X & Y) | ((~X) & Z);
1041 G (uint32x X, uint32x Y, uint32x Z)
1043 return (X & Y) | (X & Z) | (Y & Z);
1047 H (uint32x X, uint32x Y, uint32x Z)
1053 lshift_a (uint32x x, int s)
1056 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1059 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1060 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1061 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1063 /* this applies md4 to 64 byte chunks */
1065 spa_mdfour64 (uint32x * M)
1068 uint32x AA, BB, CC, DD;
1071 for (j = 0; j < 16; j++)
1079 ROUND1 (A, B, C, D, 0, 3);
1080 ROUND1 (D, A, B, C, 1, 7);
1081 ROUND1 (C, D, A, B, 2, 11);
1082 ROUND1 (B, C, D, A, 3, 19);
1083 ROUND1 (A, B, C, D, 4, 3);
1084 ROUND1 (D, A, B, C, 5, 7);
1085 ROUND1 (C, D, A, B, 6, 11);
1086 ROUND1 (B, C, D, A, 7, 19);
1087 ROUND1 (A, B, C, D, 8, 3);
1088 ROUND1 (D, A, B, C, 9, 7);
1089 ROUND1 (C, D, A, B, 10, 11);
1090 ROUND1 (B, C, D, A, 11, 19);
1091 ROUND1 (A, B, C, D, 12, 3);
1092 ROUND1 (D, A, B, C, 13, 7);
1093 ROUND1 (C, D, A, B, 14, 11);
1094 ROUND1 (B, C, D, A, 15, 19);
1096 ROUND2 (A, B, C, D, 0, 3);
1097 ROUND2 (D, A, B, C, 4, 5);
1098 ROUND2 (C, D, A, B, 8, 9);
1099 ROUND2 (B, C, D, A, 12, 13);
1100 ROUND2 (A, B, C, D, 1, 3);
1101 ROUND2 (D, A, B, C, 5, 5);
1102 ROUND2 (C, D, A, B, 9, 9);
1103 ROUND2 (B, C, D, A, 13, 13);
1104 ROUND2 (A, B, C, D, 2, 3);
1105 ROUND2 (D, A, B, C, 6, 5);
1106 ROUND2 (C, D, A, B, 10, 9);
1107 ROUND2 (B, C, D, A, 14, 13);
1108 ROUND2 (A, B, C, D, 3, 3);
1109 ROUND2 (D, A, B, C, 7, 5);
1110 ROUND2 (C, D, A, B, 11, 9);
1111 ROUND2 (B, C, D, A, 15, 13);
1113 ROUND3 (A, B, C, D, 0, 3);
1114 ROUND3 (D, A, B, C, 8, 9);
1115 ROUND3 (C, D, A, B, 4, 11);
1116 ROUND3 (B, C, D, A, 12, 15);
1117 ROUND3 (A, B, C, D, 2, 3);
1118 ROUND3 (D, A, B, C, 10, 9);
1119 ROUND3 (C, D, A, B, 6, 11);
1120 ROUND3 (B, C, D, A, 14, 15);
1121 ROUND3 (A, B, C, D, 1, 3);
1122 ROUND3 (D, A, B, C, 9, 9);
1123 ROUND3 (C, D, A, B, 5, 11);
1124 ROUND3 (B, C, D, A, 13, 15);
1125 ROUND3 (A, B, C, D, 3, 3);
1126 ROUND3 (D, A, B, C, 11, 9);
1127 ROUND3 (C, D, A, B, 7, 11);
1128 ROUND3 (B, C, D, A, 15, 15);
1140 for (j = 0; j < 16; j++)
1145 copy64 (uint32x * M, unsigned char *in)
1149 for (i = 0; i < 16; i++)
1150 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1151 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1155 copy4 (unsigned char *out, uint32x x)
1158 out[1] = (x >> 8) & 0xFF;
1159 out[2] = (x >> 16) & 0xFF;
1160 out[3] = (x >> 24) & 0xFF;
1163 /* produce a md4 message digest from data of length n bytes */
1165 mdfour (unsigned char *out, unsigned char *in, int n)
1167 unsigned char buf[128];
1185 for (i = 0; i < 128; i++)
1187 memcpy (buf, in, n);
1192 copy4 (buf + 56, b);
1198 copy4 (buf + 120, b);
1201 copy64 (M, buf + 64);
1205 for (i = 0; i < 128; i++)
1212 copy4 (out + 12, D);
1217 char versionString[] = "libntlm version 0.21";
1219 /* Utility routines that handle NTLM auth structures. */
1221 /* The [IS]VAL macros are to take care of byte order for non-Intel
1222 * Machines -- I think this file is OK, but it hasn't been tested.
1223 * The other files (the ones stolen from Samba) should be OK.
1227 /* I am not crazy about these macros -- they seem to have gotten
1228 * a bit complex. A new scheme for handling string/buffer fields
1229 * in the structures probably needs to be designed
1232 #define spa_bytes_add(ptr, header, buf, count) \
1236 SSVAL(&ptr->header.len,0,count); \
1237 SSVAL(&ptr->header.maxlen,0,count); \
1238 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1239 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1240 ptr->bufIndex += count; \
1245 ptr->header.maxlen = 0; \
1246 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1250 #define spa_string_add(ptr, header, string) \
1254 if (p) len = strlen(p); \
1255 spa_bytes_add(ptr, header, ((unsigned char*)p), len); \
1258 #define spa_unicode_add_string(ptr, header, string) \
1261 unsigned char *b = NULL; \
1266 b = strToUnicode(p); \
1268 spa_bytes_add(ptr, header, b, len*2); \
1272 #define GetUnicodeString(structPtr, header) \
1273 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1274 #define GetString(structPtr, header) \
1275 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1276 #define DumpBuffer(fp, structPtr, header) \
1277 dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1281 dumpRaw (FILE * fp, unsigned char *buf, size_t len)
1285 for (i = 0; i < len; ++i)
1286 fprintf (fp, "%02x ", buf[i]);
1292 unicodeToString (char *p, size_t len)
1295 static char buf[1024];
1297 assert (len + 1 < sizeof buf);
1299 for (i = 0; i < len; ++i)
1309 static unsigned char *
1310 strToUnicode (char *p)
1312 static unsigned char buf[1024];
1313 size_t l = strlen (p);
1316 assert (l * 2 < sizeof buf);
1327 static unsigned char *
1328 toString (char *p, size_t len)
1330 static unsigned char buf[1024];
1332 assert (len + 1 < sizeof buf);
1334 memcpy (buf, p, len);
1340 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1342 fprintf (fp, "NTLM Request:\n");
1343 fprintf (fp, " Ident = %s\n", request->ident);
1344 fprintf (fp, " mType = %d\n", IVAL (&request->msgType, 0));
1345 fprintf (fp, " Flags = %08x\n", IVAL (&request->flags, 0));
1346 fprintf (fp, " User = %s\n", GetString (request, user));
1347 fprintf (fp, " Domain = %s\n", GetString (request, domain));
1351 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1353 fprintf (fp, "NTLM Challenge:\n");
1354 fprintf (fp, " Ident = %s\n", challenge->ident);
1355 fprintf (fp, " mType = %d\n", IVAL (&challenge->msgType, 0));
1356 fprintf (fp, " Domain = %s\n", GetUnicodeString (challenge, uDomain));
1357 fprintf (fp, " Flags = %08x\n", IVAL (&challenge->flags, 0));
1358 fprintf (fp, " Challenge = ");
1359 dumpRaw (fp, challenge->challengeData, 8);
1363 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1365 fprintf (fp, "NTLM Response:\n");
1366 fprintf (fp, " Ident = %s\n", response->ident);
1367 fprintf (fp, " mType = %d\n", IVAL (&response->msgType, 0));
1368 fprintf (fp, " LmResp = ");
1369 DumpBuffer (fp, response, lmResponse);
1370 fprintf (fp, " NTResp = ");
1371 DumpBuffer (fp, response, ntResponse);
1372 fprintf (fp, " Domain = %s\n", GetUnicodeString (response, uDomain));
1373 fprintf (fp, " User = %s\n", GetUnicodeString (response, uUser));
1374 fprintf (fp, " Wks = %s\n", GetUnicodeString (response, uWks));
1375 fprintf (fp, " sKey = ");
1376 DumpBuffer (fp, response, sessionKey);
1377 fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0));
1381 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1383 char *u = strdup (user);
1384 char *p = strchr (u, '@');
1393 request->bufIndex = 0;
1394 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1395 SIVAL (&request->msgType, 0, 1);
1396 SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */
1397 spa_string_add (request, user, u);
1398 spa_string_add (request, domain, domain);
1405 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1409 int p = (int)getpid();
1410 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1412 request = request; /* Added by PH to stop compilers whinging */
1414 /* Ensure challenge data is cleared, in case it isn't all used. This
1415 patch added by PH on suggestion of Russell King */
1417 memset(challenge, 0, sizeof(SPAAuthChallenge));
1419 challenge->bufIndex = 0;
1420 memcpy (challenge->ident, "NTLMSSP\0", 8);
1421 SIVAL (&challenge->msgType, 0, 2);
1422 SIVAL (&challenge->flags, 0, 0x00008201);
1423 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1424 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1425 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1427 /* generate eight pseudo random bytes (method ripped from host.c) */
1430 chalstr[i] = (unsigned char)(random_seed >> 16) % 256;
1431 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1434 memcpy(challenge->challengeData,chalstr,8);
1440 /* This is the original source of this function, preserved here for reference.
1441 The new version below was re-organized by PH following a patch and some further
1442 suggestions from Mark Lyda to fix the problem that is described at the head of
1443 this module. At the same time, I removed the untidiness in the code below that
1444 involves the "d" and "domain" variables. */
1448 spa_build_auth_response (SPAAuthChallenge * challenge,
1449 SPAAuthResponse * response, char *user,
1452 uint8x lmRespData[24];
1453 uint8x ntRespData[24];
1454 char *d = strdup (GetUnicodeString (challenge, uDomain));
1456 char *u = strdup (user);
1457 char *p = strchr (u, '@');
1465 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1466 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1468 response->bufIndex = 0;
1469 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1470 SIVAL (&response->msgType, 0, 3);
1472 spa_bytes_add (response, lmResponse, lmRespData, 24);
1473 spa_bytes_add (response, ntResponse, ntRespData, 24);
1474 spa_unicode_add_string (response, uDomain, domain);
1475 spa_unicode_add_string (response, uUser, u);
1476 spa_unicode_add_string (response, uWks, u);
1477 spa_string_add (response, sessionKey, NULL);
1479 response->flags = challenge->flags;
1487 /* This is the re-organized version (see comments above) */
1490 spa_build_auth_response (SPAAuthChallenge * challenge,
1491 SPAAuthResponse * response, char *user,
1494 uint8x lmRespData[24];
1495 uint8x ntRespData[24];
1496 uint32x cf = IVAL(&challenge->flags, 0);
1497 char *u = strdup (user);
1498 char *p = strchr (u, '@');
1508 else domain = d = strdup((cf & 0x1)?
1509 (const char *)GetUnicodeString(challenge, uDomain) :
1510 (const char *)GetString(challenge, uDomain));
1512 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1513 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1515 response->bufIndex = 0;
1516 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1517 SIVAL (&response->msgType, 0, 3);
1519 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1520 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1522 if (cf & 0x1) { /* Unicode Text */
1523 spa_unicode_add_string (response, uDomain, domain);
1524 spa_unicode_add_string (response, uUser, u);
1525 spa_unicode_add_string (response, uWks, u);
1526 } else { /* OEM Text */
1527 spa_string_add (response, uDomain, domain);
1528 spa_string_add (response, uUser, u);
1529 spa_string_add (response, uWks, u);
1532 spa_string_add (response, sessionKey, NULL);
1533 response->flags = challenge->flags;
1535 if (d != NULL) free (d);