1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
6 * This file provides the necessary methods for authenticating with
7 * Microsoft's Secure Password Authentication.
9 * All the original code used here was torn by Marc Prud'hommeaux out of the
10 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
12 * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
13 * support server authentication mode.
15 * Mark Lyda provided a patch to solve this problem:
17 - Exim is indicating in its Authentication Request message (Type 1) that it
18 can transmit text in either Unicode or OEM format.
20 - Microsoft's SMTP server (smtp.email.msn.com) is responding in its
21 Challenge message (Type 2) that it will be expecting the OEM format.
23 - Exim does not pay attention to the text format requested by Microsoft's
24 SMTP server and, instead, defaults to using the Unicode format.
27 * http://www.innovation.ch/java/ntlm.html
28 * http://www.kuro5hin.org/story/2002/4/28/1436/66154
30 * It seems that some systems have existing but different definitions of some
31 * of the following types. I received a complaint about "int16" causing
32 * compilation problems. So I (PH) have renamed them all, to be on the safe
33 * side, by adding 'x' on the end.
35 * typedef signed short int16;
36 * typedef unsigned short uint16;
37 * typedef unsigned uint32;
38 * typedef unsigned char uint8;
40 * The API is extremely simple:
41 * 1. Form a SPA authentication request based on the username
42 * and (optional) domain
43 * 2. Send the request to the server and get an SPA challenge
44 * 3. Build the challenge response and send it back.
49 int main (int argc, char ** argv)
51 SPAAuthRequest request;
52 SPAAuthChallenge challenge;
53 SPAAuthResponse response;
56 char *username, *password, *domain, *challenge_str;
60 printf ("Usage: %s <username> <password> [SPA Challenge]\n",
69 spa_build_auth_request (&request, username, domain);
71 spa_bits_to_base64 (msgbuf, (unsigned char*)&request,
72 spa_request_length(&request));
74 printf ("SPA Login request for username=%s:\n %s\n",
79 printf ("Run: %s <username> <password> [NTLM Challenge] " \
80 "to complete authenitcation\n", argv [0]);
84 challenge_str = argv [3];
86 if (spa_base64_to_bits ((char *)&challenge, sizeof(challenge),
87 (const char *)(challenge_str))<0)
89 printf("bad base64 data in challenge: %s\n", challenge_str);
93 spa_build_auth_response (&challenge, &response, username, password);
94 spa_bits_to_base64 (msgbuf, (unsigned char*)&response,
95 spa_request_length(&response));
97 printf ("SPA Response to challenge:\n %s\n for " \
98 "username=%s, password=%s:\n %s\n",
99 argv[3], argv [1], argv [2], msgbuf);
104 * All the client code used here was torn by Marc Prud'hommeaux out of the
105 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
106 * Previous comments are below:
110 Unix SMB/Netbios implementation.
113 a partial implementation of DES designed for use in the
114 SMB authentication protocol
116 Copyright (C) Andrew Tridgell 1998
118 This program is free software; you can redistribute it and/or modify
119 it under the terms of the GNU General Public License as published by
120 the Free Software Foundation; either version 2 of the License, or
121 (at your option) any later version.
123 This program is distributed in the hope that it will be useful,
124 but WITHOUT ANY WARRANTY; without even the implied warranty of
125 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
126 GNU General Public License for more details.
128 You should have received a copy of the GNU General Public License
129 along with this program; if not, write to the Free Software
130 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
136 This code makes no attempt to be fast! In fact, it is a very
139 This code is NOT a complete DES implementation. It implements only
140 the minimum necessary for SMB authentication, as used by all SMB
141 products (including every copy of Microsoft Windows95 ever sold)
143 In particular, it can only do a unchained forward DES pass. This
144 means it is not possible to use this code for encryption/decryption
145 of data, instead it is only useful as a "hash" algorithm.
147 There is no entry point into this code that allows normal DES operation.
149 I believe this means that this code does not come under ITAR
150 regulations but this is NOT a legal opinion. If you are concerned
151 about the applicability of ITAR regulations to this code then you
152 should confirm it for yourself (and maybe let me know if you come
153 up with a different answer to the one above)
158 extern int DEBUGLEVEL;
160 #include <sys/types.h> /* For size_t */
161 #include "auth-spa.h"
171 typedef unsigned char uchar;
182 #define RW_PCVAL(read,inbuf,outbuf,len) \
183 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
184 else { PSCVAL(inbuf,0,outbuf,len); } }
186 #define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
187 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
188 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
190 #define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
191 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
192 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
194 #define RW_CVAL(read, inbuf, outbuf, offset) \
195 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
196 else { SCVAL(inbuf,offset,outbuf); } }
198 #define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
199 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
200 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
202 #define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
203 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
204 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
206 #undef CAREFUL_ALIGNMENT
208 /* we know that the 386 can handle misalignment and has the "right"
211 #define CAREFUL_ALIGNMENT 0
214 #ifndef CAREFUL_ALIGNMENT
215 #define CAREFUL_ALIGNMENT 1
218 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
219 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
220 #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
223 #if CAREFUL_ALIGNMENT
225 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
226 #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
227 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
228 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
229 #define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
230 #define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
231 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
232 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
233 #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
234 #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
236 #else /* CAREFUL_ALIGNMENT */
238 /* this handles things for architectures like the 386 that can handle
241 WARNING: This section is dependent on the length of int16x and int32x
245 /* get single value from an SMB buffer */
246 #define SVAL(buf,pos) (*(uint16x *)((char *)(buf) + (pos)))
247 #define IVAL(buf,pos) (*(uint32x *)((char *)(buf) + (pos)))
248 #define SVALS(buf,pos) (*(int16x *)((char *)(buf) + (pos)))
249 #define IVALS(buf,pos) (*(int32x *)((char *)(buf) + (pos)))
251 /* store single value in an SMB buffer */
252 #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
253 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
254 #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
255 #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
257 #endif /* CAREFUL_ALIGNMENT */
259 /* macros for reading / writing arrays */
261 #define SMBMACRO(macro,buf,pos,val,len,size) \
262 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
264 #define SSMBMACRO(macro,buf,pos,val,len,size) \
265 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
267 /* reads multiple data from an SMB buffer */
268 #define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
269 #define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
270 #define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
271 #define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
272 #define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
273 #define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
275 /* stores multiple data in an SMB buffer */
276 #define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
277 #define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
278 #define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
279 #define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
280 #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
281 #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
284 /* now the reverse routines - these are used in nmb packets (mostly) */
285 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
286 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
288 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))
289 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))
290 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))
291 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))
292 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
293 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
294 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
295 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
297 /* reads multiple data from an SMB buffer (big-endian) */
298 #define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
299 #define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
300 #define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
301 #define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
303 /* stores multiple data in an SMB buffer (big-endian) */
304 #define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
305 #define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
306 #define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
307 #define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
309 #define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
310 { RW_PCVAL(read,inbuf,outbuf,len) \
311 DEBUG(5,("%s%04x %s: ", \
312 tab_depth(depth), base,string)); \
313 if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
314 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
317 #define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
318 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
319 DEBUG(5,("%s%04x %s: ", \
320 tab_depth(depth), base,string)); \
321 if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
322 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
325 #define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
326 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
327 DEBUG(5,("%s%04x %s: ", \
328 tab_depth(depth), base,string)); \
329 if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
330 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
333 #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
334 { RW_CVAL(read,inbuf,outbuf,0) \
335 DEBUG(5,("%s%04x %s: %02x\n", \
336 tab_depth(depth), base, string, outbuf)); }
338 #define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
339 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
340 DEBUG(5,("%s%04x %s: %04x\n", \
341 tab_depth(depth), base, string, outbuf)); }
343 #define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
344 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
345 DEBUG(5,("%s%04x %s: %08x\n", \
346 tab_depth(depth), base, string, outbuf)); }
348 #endif /* _BYTEORDER_H */
350 void E_P16 (unsigned char *p14, unsigned char *p16);
351 void E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24);
352 void D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out);
353 void SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24]);
355 void mdfour (unsigned char *out, unsigned char *in, int n);
359 * base64.c -- base-64 conversion routines.
361 * For license terms, see the file COPYING in this directory.
363 * This base 64 encoding is defined in RFC2045 section 6.8,
364 * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
368 static const char base64digits[] =
369 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
372 static const char base64val[] = {
373 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
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, 62, BAD, BAD, BAD,
379 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
380 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
381 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
382 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
383 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
385 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
388 spa_bits_to_base64 (unsigned char *out, const unsigned char *in, int inlen)
389 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
391 for (; inlen >= 3; inlen -= 3)
393 *out++ = base64digits[in[0] >> 2];
394 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
395 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
396 *out++ = base64digits[in[2] & 0x3f];
401 unsigned char fragment;
403 *out++ = base64digits[in[0] >> 2];
404 fragment = (in[0] << 4) & 0x30;
406 fragment |= in[1] >> 4;
407 *out++ = base64digits[fragment];
408 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
415 /* The outlength parameter was added by PH, December 2004 */
418 spa_base64_to_bits (char *out, int outlength, const char *in)
419 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
422 register unsigned char digit1, digit2, digit3, digit4;
424 if (in[0] == '+' && in[1] == ' ')
431 if (len >= outlength) /* Added by PH */
432 return (-1); /* Added by PH */
434 if (DECODE64 (digit1) == BAD)
437 if (DECODE64 (digit2) == BAD)
440 if (digit3 != '=' && DECODE64 (digit3) == BAD)
443 if (digit4 != '=' && DECODE64 (digit4) == BAD)
446 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
450 if (len >= outlength) /* Added by PH */
451 return (-1); /* Added by PH */
453 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
457 if (len >= outlength) /* Added by PH */
458 return (-1); /* Added by PH */
459 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
464 while (*in && *in != '\r' && digit4 != '=');
470 #define uchar unsigned char
472 static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
473 1, 58, 50, 42, 34, 26, 18,
474 10, 2, 59, 51, 43, 35, 27,
475 19, 11, 3, 60, 52, 44, 36,
476 63, 55, 47, 39, 31, 23, 15,
477 7, 62, 54, 46, 38, 30, 22,
478 14, 6, 61, 53, 45, 37, 29,
479 21, 13, 5, 28, 20, 12, 4
482 static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
483 3, 28, 15, 6, 21, 10,
484 23, 19, 12, 4, 26, 8,
485 16, 7, 27, 20, 13, 2,
486 41, 52, 31, 37, 47, 55,
487 30, 40, 51, 45, 33, 48,
488 44, 49, 39, 56, 34, 53,
489 46, 42, 50, 36, 29, 32
492 static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
493 60, 52, 44, 36, 28, 20, 12, 4,
494 62, 54, 46, 38, 30, 22, 14, 6,
495 64, 56, 48, 40, 32, 24, 16, 8,
496 57, 49, 41, 33, 25, 17, 9, 1,
497 59, 51, 43, 35, 27, 19, 11, 3,
498 61, 53, 45, 37, 29, 21, 13, 5,
499 63, 55, 47, 39, 31, 23, 15, 7
502 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
504 8, 9, 10, 11, 12, 13,
505 12, 13, 14, 15, 16, 17,
506 16, 17, 18, 19, 20, 21,
507 20, 21, 22, 23, 24, 25,
508 24, 25, 26, 27, 28, 29,
509 28, 29, 30, 31, 32, 1
512 static uchar perm5[32] = { 16, 7, 20, 21,
523 static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
524 39, 7, 47, 15, 55, 23, 63, 31,
525 38, 6, 46, 14, 54, 22, 62, 30,
526 37, 5, 45, 13, 53, 21, 61, 29,
527 36, 4, 44, 12, 52, 20, 60, 28,
528 35, 3, 43, 11, 51, 19, 59, 27,
529 34, 2, 42, 10, 50, 18, 58, 26,
530 33, 1, 41, 9, 49, 17, 57, 25
534 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
536 static uchar sbox[8][4][16] = {
537 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
538 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
539 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
540 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
542 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
543 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
544 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
545 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
547 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
548 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
549 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
550 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
552 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
553 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
554 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
555 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
557 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
558 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
559 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
560 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
562 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
563 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
564 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
565 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
567 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
568 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
569 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
570 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
572 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
573 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
574 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
575 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
579 permute (char *out, char *in, uchar * p, int n)
582 for (i = 0; i < n; i++)
583 out[i] = in[p[i] - 1];
587 lshift (char *d, int count, int n)
591 for (i = 0; i < n; i++)
592 out[i] = d[(i + count) % n];
593 for (i = 0; i < n; i++)
598 concat (char *out, char *in1, char *in2, int l1, int l2)
607 xor (char *out, char *in1, char *in2, int n)
610 for (i = 0; i < n; i++)
611 out[i] = in1[i] ^ in2[i];
615 dohash (char *out, char *in, char *key, int forw)
627 permute (pk1, key, perm1, 56);
629 for (i = 0; i < 28; i++)
631 for (i = 0; i < 28; i++)
634 for (i = 0; i < 16; i++)
636 lshift (c, sc[i], 28);
637 lshift (d, sc[i], 28);
639 concat (cd, c, d, 28, 28);
640 permute (ki[i], cd, perm2, 48);
643 permute (pd1, in, perm3, 64);
645 for (j = 0; j < 32; j++)
651 for (i = 0; i < 16; i++)
660 permute (er, r, perm4, 48);
662 xor (erk, er, ki[forw ? i : 15 - i], 48);
664 for (j = 0; j < 8; j++)
665 for (k = 0; k < 6; k++)
666 b[j][k] = erk[j * 6 + k];
668 for (j = 0; j < 8; j++)
671 m = (b[j][0] << 1) | b[j][5];
673 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
675 for (k = 0; k < 4; k++)
676 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
679 for (j = 0; j < 8; j++)
680 for (k = 0; k < 4; k++)
681 cb[j * 4 + k] = b[j][k];
682 permute (pcb, cb, perm5, 32);
684 xor (r2, l, pcb, 32);
686 for (j = 0; j < 32; j++)
689 for (j = 0; j < 32; j++)
693 concat (rl, r, l, 32, 32);
695 permute (out, rl, perm6, 64);
699 str_to_key (unsigned char *str, unsigned char *key)
703 key[0] = str[0] >> 1;
704 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
705 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
706 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
707 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
708 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
709 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
710 key[7] = str[6] & 0x7F;
711 for (i = 0; i < 8; i++)
713 key[i] = (key[i] << 1);
719 smbhash (unsigned char *out, unsigned char *in, unsigned char *key, int forw)
725 unsigned char key2[8];
727 str_to_key (key, key2);
729 for (i = 0; i < 64; i++)
731 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
732 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
736 dohash (outb, inb, keyb, forw);
738 for (i = 0; i < 8; i++)
743 for (i = 0; i < 64; i++)
746 out[i / 8] |= (1 << (7 - (i % 8)));
751 E_P16 (unsigned char *p14, unsigned char *p16)
753 unsigned char sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
754 smbhash (p16, sp8, p14, 1);
755 smbhash (p16 + 8, sp8, p14 + 7, 1);
759 E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24)
761 smbhash (p24, c8, p21, 1);
762 smbhash (p24 + 8, c8, p21 + 7, 1);
763 smbhash (p24 + 16, c8, p21 + 14, 1);
767 D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out)
769 smbhash (out, in, p14, 0);
770 smbhash (out + 8, in + 8, p14 + 7, 0);
773 /****************************************************************************
774 Like strncpy but always null terminates. Make sure there is room!
775 The variable n should always be one less than the available size.
776 ****************************************************************************/
779 StrnCpy (char *dest, const char *src, size_t n)
789 while (n-- && (*d++ = *src++));
795 skip_multibyte_char (char c)
797 /* bogus if to get rid of unused compiler warning */
805 /*******************************************************************
806 safe string copy into a known length string. maxlength does not
807 include the terminating zero.
808 ********************************************************************/
811 safe_strcpy (char *dest, const char *src, size_t maxlength)
817 DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
831 DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
832 (int) (len - maxlength), src));
836 memcpy (dest, src, len);
848 size_t skip = skip_multibyte_char (*s);
853 if (islower ((unsigned char)(*s)))
863 This implements the X/Open SMB password encryption
864 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
865 encrypted password into p24
869 spa_smb_encrypt (uchar * passwd, uchar * c8, uchar * p24)
871 uchar p14[15], p21[21];
873 memset (p21, '\0', 21);
874 memset (p14, '\0', 14);
875 StrnCpy ((char *) p14, (char *) passwd, 14);
877 strupper ((char *) p14);
880 SMBOWFencrypt (p21, c8, p24);
882 #ifdef DEBUG_PASSWORD
883 DEBUG (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
884 dump_data (100, (char *) p21, 16);
885 dump_data (100, (char *) c8, 8);
886 dump_data (100, (char *) p24, 24);
890 /* Routines for Windows NT MD4 Hash functions. */
892 _my_wcslen (int16x * str)
901 * Convert a string into an NT UNICODE string.
902 * Note that regardless of processor type
903 * this must be in intel (little-endian)
908 _my_mbstowcs (int16x * dst, uchar * src, int len)
913 for (i = 0; i < len; i++)
926 * Creates the MD4 Hash of the users password in NT UNICODE.
930 E_md4hash (uchar * passwd, uchar * p16)
935 /* Password cannot be longer than 128 characters */
936 len = strlen ((char *) passwd);
939 /* Password must be converted to NT unicode */
940 _my_mbstowcs (wpwd, passwd, len);
941 wpwd[len] = 0; /* Ensure string is null terminated */
942 /* Calculate length in bytes */
943 len = _my_wcslen (wpwd) * sizeof (int16x);
945 mdfour (p16, (unsigned char *) wpwd, len);
948 /* Does both the NT and LM owfs of a user's password */
950 nt_lm_owf_gen (char *pwd, uchar nt_p16[16], uchar p16[16])
954 memset (passwd, '\0', 130);
955 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
957 /* Calculate the MD4 hash (NT compatible) of the password */
958 memset (nt_p16, '\0', 16);
959 E_md4hash ((uchar *) passwd, nt_p16);
961 #ifdef DEBUG_PASSWORD
962 DEBUG (100, ("nt_lm_owf_gen: pwd, nt#\n"));
963 dump_data (120, passwd, strlen (passwd));
964 dump_data (100, (char *) nt_p16, 16);
967 /* Mangle the passwords into Lanman format */
971 /* Calculate the SMB (lanman) hash functions of the password */
973 memset (p16, '\0', 16);
974 E_P16 ((uchar *) passwd, (uchar *) p16);
976 #ifdef DEBUG_PASSWORD
977 DEBUG (100, ("nt_lm_owf_gen: pwd, lm#\n"));
978 dump_data (120, passwd, strlen (passwd));
979 dump_data (100, (char *) p16, 16);
981 /* clear out local copy of user's password (just being paranoid). */
982 memset (passwd, '\0', sizeof (passwd));
985 /* Does the des encryption from the NT or LM MD4 hash. */
987 SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24])
991 memset (p21, '\0', 21);
993 memcpy (p21, passwd, 16);
994 E_P24 (p21, c8, p24);
997 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
999 NTLMSSPOWFencrypt (uchar passwd[8], uchar * ntlmchalresp, uchar p24[24])
1003 memset (p21, '\0', 21);
1004 memcpy (p21, passwd, 8);
1005 memset (p21 + 8, 0xbd, 8);
1007 E_P24 (p21, ntlmchalresp, p24);
1008 #ifdef DEBUG_PASSWORD
1009 DEBUG (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
1010 dump_data (100, (char *) p21, 21);
1011 dump_data (100, (char *) ntlmchalresp, 8);
1012 dump_data (100, (char *) p24, 24);
1017 /* Does the NT MD4 hash then des encryption. */
1020 spa_smb_nt_encrypt (uchar * passwd, uchar * c8, uchar * p24)
1024 memset (p21, '\0', 21);
1026 E_md4hash (passwd, p21);
1027 SMBOWFencrypt (p21, c8, p24);
1029 #ifdef DEBUG_PASSWORD
1030 DEBUG (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1031 dump_data (100, (char *) p21, 16);
1032 dump_data (100, (char *) c8, 8);
1033 dump_data (100, (char *) p24, 24);
1037 static uint32x A, B, C, D;
1040 F (uint32x X, uint32x Y, uint32x Z)
1042 return (X & Y) | ((~X) & Z);
1046 G (uint32x X, uint32x Y, uint32x Z)
1048 return (X & Y) | (X & Z) | (Y & Z);
1052 H (uint32x X, uint32x Y, uint32x Z)
1058 lshift_a (uint32x x, int s)
1061 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1064 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1065 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1066 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1068 /* this applies md4 to 64 byte chunks */
1070 spa_mdfour64 (uint32x * M)
1073 uint32x AA, BB, CC, DD;
1076 for (j = 0; j < 16; j++)
1084 ROUND1 (A, B, C, D, 0, 3);
1085 ROUND1 (D, A, B, C, 1, 7);
1086 ROUND1 (C, D, A, B, 2, 11);
1087 ROUND1 (B, C, D, A, 3, 19);
1088 ROUND1 (A, B, C, D, 4, 3);
1089 ROUND1 (D, A, B, C, 5, 7);
1090 ROUND1 (C, D, A, B, 6, 11);
1091 ROUND1 (B, C, D, A, 7, 19);
1092 ROUND1 (A, B, C, D, 8, 3);
1093 ROUND1 (D, A, B, C, 9, 7);
1094 ROUND1 (C, D, A, B, 10, 11);
1095 ROUND1 (B, C, D, A, 11, 19);
1096 ROUND1 (A, B, C, D, 12, 3);
1097 ROUND1 (D, A, B, C, 13, 7);
1098 ROUND1 (C, D, A, B, 14, 11);
1099 ROUND1 (B, C, D, A, 15, 19);
1101 ROUND2 (A, B, C, D, 0, 3);
1102 ROUND2 (D, A, B, C, 4, 5);
1103 ROUND2 (C, D, A, B, 8, 9);
1104 ROUND2 (B, C, D, A, 12, 13);
1105 ROUND2 (A, B, C, D, 1, 3);
1106 ROUND2 (D, A, B, C, 5, 5);
1107 ROUND2 (C, D, A, B, 9, 9);
1108 ROUND2 (B, C, D, A, 13, 13);
1109 ROUND2 (A, B, C, D, 2, 3);
1110 ROUND2 (D, A, B, C, 6, 5);
1111 ROUND2 (C, D, A, B, 10, 9);
1112 ROUND2 (B, C, D, A, 14, 13);
1113 ROUND2 (A, B, C, D, 3, 3);
1114 ROUND2 (D, A, B, C, 7, 5);
1115 ROUND2 (C, D, A, B, 11, 9);
1116 ROUND2 (B, C, D, A, 15, 13);
1118 ROUND3 (A, B, C, D, 0, 3);
1119 ROUND3 (D, A, B, C, 8, 9);
1120 ROUND3 (C, D, A, B, 4, 11);
1121 ROUND3 (B, C, D, A, 12, 15);
1122 ROUND3 (A, B, C, D, 2, 3);
1123 ROUND3 (D, A, B, C, 10, 9);
1124 ROUND3 (C, D, A, B, 6, 11);
1125 ROUND3 (B, C, D, A, 14, 15);
1126 ROUND3 (A, B, C, D, 1, 3);
1127 ROUND3 (D, A, B, C, 9, 9);
1128 ROUND3 (C, D, A, B, 5, 11);
1129 ROUND3 (B, C, D, A, 13, 15);
1130 ROUND3 (A, B, C, D, 3, 3);
1131 ROUND3 (D, A, B, C, 11, 9);
1132 ROUND3 (C, D, A, B, 7, 11);
1133 ROUND3 (B, C, D, A, 15, 15);
1145 for (j = 0; j < 16; j++)
1150 copy64 (uint32x * M, unsigned char *in)
1154 for (i = 0; i < 16; i++)
1155 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1156 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1160 copy4 (unsigned char *out, uint32x x)
1163 out[1] = (x >> 8) & 0xFF;
1164 out[2] = (x >> 16) & 0xFF;
1165 out[3] = (x >> 24) & 0xFF;
1168 /* produce a md4 message digest from data of length n bytes */
1170 mdfour (unsigned char *out, unsigned char *in, int n)
1172 unsigned char buf[128];
1190 for (i = 0; i < 128; i++)
1192 memcpy (buf, in, n);
1197 copy4 (buf + 56, b);
1203 copy4 (buf + 120, b);
1206 copy64 (M, buf + 64);
1210 for (i = 0; i < 128; i++)
1217 copy4 (out + 12, D);
1222 char versionString[] = "libntlm version 0.21";
1224 /* Utility routines that handle NTLM auth structures. */
1226 /* The [IS]VAL macros are to take care of byte order for non-Intel
1227 * Machines -- I think this file is OK, but it hasn't been tested.
1228 * The other files (the ones stolen from Samba) should be OK.
1232 /* I am not crazy about these macros -- they seem to have gotten
1233 * a bit complex. A new scheme for handling string/buffer fields
1234 * in the structures probably needs to be designed
1237 #define spa_bytes_add(ptr, header, buf, count) \
1241 SSVAL(&ptr->header.len,0,count); \
1242 SSVAL(&ptr->header.maxlen,0,count); \
1243 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1244 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1245 ptr->bufIndex += count; \
1250 ptr->header.maxlen = 0; \
1251 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1255 #define spa_string_add(ptr, header, string) \
1259 if (p) len = strlen(p); \
1260 spa_bytes_add(ptr, header, ((unsigned char*)p), len); \
1263 #define spa_unicode_add_string(ptr, header, string) \
1266 unsigned char *b = NULL; \
1271 b = strToUnicode(p); \
1273 spa_bytes_add(ptr, header, b, len*2); \
1277 #define GetUnicodeString(structPtr, header) \
1278 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1279 #define GetString(structPtr, header) \
1280 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1281 #define DumpBuffer(fp, structPtr, header) \
1282 dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1286 dumpRaw (FILE * fp, unsigned char *buf, size_t len)
1290 for (i = 0; i < len; ++i)
1291 fprintf (fp, "%02x ", buf[i]);
1297 unicodeToString (char *p, size_t len)
1300 static char buf[1024];
1302 assert (len + 1 < sizeof buf);
1304 for (i = 0; i < len; ++i)
1314 static unsigned char *
1315 strToUnicode (char *p)
1317 static unsigned char buf[1024];
1318 size_t l = strlen (p);
1321 assert (l * 2 < sizeof buf);
1332 static unsigned char *
1333 toString (char *p, size_t len)
1335 static unsigned char buf[1024];
1337 assert (len + 1 < sizeof buf);
1339 memcpy (buf, p, len);
1345 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1347 fprintf (fp, "NTLM Request:\n");
1348 fprintf (fp, " Ident = %s\n", request->ident);
1349 fprintf (fp, " mType = %d\n", IVAL (&request->msgType, 0));
1350 fprintf (fp, " Flags = %08x\n", IVAL (&request->flags, 0));
1351 fprintf (fp, " User = %s\n", GetString (request, user));
1352 fprintf (fp, " Domain = %s\n", GetString (request, domain));
1356 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1358 fprintf (fp, "NTLM Challenge:\n");
1359 fprintf (fp, " Ident = %s\n", challenge->ident);
1360 fprintf (fp, " mType = %d\n", IVAL (&challenge->msgType, 0));
1361 fprintf (fp, " Domain = %s\n", GetUnicodeString (challenge, uDomain));
1362 fprintf (fp, " Flags = %08x\n", IVAL (&challenge->flags, 0));
1363 fprintf (fp, " Challenge = ");
1364 dumpRaw (fp, challenge->challengeData, 8);
1368 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1370 fprintf (fp, "NTLM Response:\n");
1371 fprintf (fp, " Ident = %s\n", response->ident);
1372 fprintf (fp, " mType = %d\n", IVAL (&response->msgType, 0));
1373 fprintf (fp, " LmResp = ");
1374 DumpBuffer (fp, response, lmResponse);
1375 fprintf (fp, " NTResp = ");
1376 DumpBuffer (fp, response, ntResponse);
1377 fprintf (fp, " Domain = %s\n", GetUnicodeString (response, uDomain));
1378 fprintf (fp, " User = %s\n", GetUnicodeString (response, uUser));
1379 fprintf (fp, " Wks = %s\n", GetUnicodeString (response, uWks));
1380 fprintf (fp, " sKey = ");
1381 DumpBuffer (fp, response, sessionKey);
1382 fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0));
1386 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1388 char *u = strdup (user);
1389 char *p = strchr (u, '@');
1398 request->bufIndex = 0;
1399 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1400 SIVAL (&request->msgType, 0, 1);
1401 SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */
1402 spa_string_add (request, user, u);
1403 spa_string_add (request, domain, domain);
1410 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1414 int p = (int)getpid();
1415 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1417 request = request; /* Added by PH to stop compilers whinging */
1419 /* Ensure challenge data is cleared, in case it isn't all used. This
1420 patch added by PH on suggestion of Russell King */
1422 memset(challenge, 0, sizeof(SPAAuthChallenge));
1424 challenge->bufIndex = 0;
1425 memcpy (challenge->ident, "NTLMSSP\0", 8);
1426 SIVAL (&challenge->msgType, 0, 2);
1427 SIVAL (&challenge->flags, 0, 0x00008201);
1428 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1429 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1430 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1432 /* generate eight pseudo random bytes (method ripped from host.c) */
1435 chalstr[i] = (unsigned char)(random_seed >> 16) % 256;
1436 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1439 memcpy(challenge->challengeData,chalstr,8);
1445 /* This is the original source of this function, preserved here for reference.
1446 The new version below was re-organized by PH following a patch and some further
1447 suggestions from Mark Lyda to fix the problem that is described at the head of
1448 this module. At the same time, I removed the untidiness in the code below that
1449 involves the "d" and "domain" variables. */
1453 spa_build_auth_response (SPAAuthChallenge * challenge,
1454 SPAAuthResponse * response, char *user,
1457 uint8x lmRespData[24];
1458 uint8x ntRespData[24];
1459 char *d = strdup (GetUnicodeString (challenge, uDomain));
1461 char *u = strdup (user);
1462 char *p = strchr (u, '@');
1470 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1471 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1473 response->bufIndex = 0;
1474 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1475 SIVAL (&response->msgType, 0, 3);
1477 spa_bytes_add (response, lmResponse, lmRespData, 24);
1478 spa_bytes_add (response, ntResponse, ntRespData, 24);
1479 spa_unicode_add_string (response, uDomain, domain);
1480 spa_unicode_add_string (response, uUser, u);
1481 spa_unicode_add_string (response, uWks, u);
1482 spa_string_add (response, sessionKey, NULL);
1484 response->flags = challenge->flags;
1492 /* This is the re-organized version (see comments above) */
1495 spa_build_auth_response (SPAAuthChallenge * challenge,
1496 SPAAuthResponse * response, char *user,
1499 uint8x lmRespData[24];
1500 uint8x ntRespData[24];
1501 uint32x cf = IVAL(&challenge->flags, 0);
1502 char *u = strdup (user);
1503 char *p = strchr (u, '@');
1513 else domain = d = strdup((cf & 0x1)?
1514 (const char *)GetUnicodeString(challenge, uDomain) :
1515 (const char *)GetString(challenge, uDomain));
1517 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1518 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1520 response->bufIndex = 0;
1521 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1522 SIVAL (&response->msgType, 0, 3);
1524 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1525 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1527 if (cf & 0x1) { /* Unicode Text */
1528 spa_unicode_add_string (response, uDomain, domain);
1529 spa_unicode_add_string (response, uUser, u);
1530 spa_unicode_add_string (response, uWks, u);
1531 } else { /* OEM Text */
1532 spa_string_add (response, uDomain, domain);
1533 spa_string_add (response, uUser, u);
1534 spa_string_add (response, uWks, u);
1537 spa_string_add (response, sessionKey, NULL);
1538 response->flags = challenge->flags;
1540 if (d != NULL) free (d);