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, US &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, US &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)
156 #define DEBUG_X(a,b) ;
158 extern int DEBUGLEVEL;
161 #include "auth-spa.h"
166 # define _BYTEORDER_H
168 # define RW_PCVAL(read,inbuf,outbuf,len) \
169 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
170 else { PSCVAL(inbuf,0,outbuf,len); } }
172 # define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
173 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
174 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
176 # define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
177 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
178 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
180 # define RW_CVAL(read, inbuf, outbuf, offset) \
181 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
182 else { SCVAL(inbuf,offset,outbuf); } }
184 # define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
185 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
186 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
188 # define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
189 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
190 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
192 # undef CAREFUL_ALIGNMENT
194 /* we know that the 386 can handle misalignment and has the "right"
197 # define CAREFUL_ALIGNMENT 0
200 # ifndef CAREFUL_ALIGNMENT
201 # define CAREFUL_ALIGNMENT 1
204 # define CVAL(buf,pos) ((US (buf))[pos])
205 # define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
206 # define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
209 # if CAREFUL_ALIGNMENT
211 # define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
212 # define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
213 # define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
214 # define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
215 # define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
216 # define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
217 # define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
218 # define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
219 # define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
220 # define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
222 # else /* CAREFUL_ALIGNMENT */
224 /* this handles things for architectures like the 386 that can handle
227 WARNING: This section is dependent on the length of int16x and int32x
231 /* get single value from an SMB buffer */
232 # define SVAL(buf,pos) (*(uint16x *)((char *)(buf) + (pos)))
233 # define IVAL(buf,pos) (*(uint32x *)((char *)(buf) + (pos)))
234 # define SVALS(buf,pos) (*(int16x *)((char *)(buf) + (pos)))
235 # define IVALS(buf,pos) (*(int32x *)((char *)(buf) + (pos)))
237 /* store single value in an SMB buffer */
238 # define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
239 # define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
240 # define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
241 # define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
243 # endif /* CAREFUL_ALIGNMENT */
245 /* macros for reading / writing arrays */
247 # define SMBMACRO(macro,buf,pos,val,len,size) \
248 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
250 # define SSMBMACRO(macro,buf,pos,val,len,size) \
251 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
253 /* reads multiple data from an SMB buffer */
254 # define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
255 # define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
256 # define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
257 # define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
258 # define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
259 # define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
261 /* stores multiple data in an SMB buffer */
262 # define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
263 # define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
264 # define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
265 # define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
266 # define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
267 # define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
270 /* now the reverse routines - these are used in nmb packets (mostly) */
271 # define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
272 # define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
274 # define RSVAL(buf,pos) SREV(SVAL(buf,pos))
275 # define RSVALS(buf,pos) SREV(SVALS(buf,pos))
276 # define RIVAL(buf,pos) IREV(IVAL(buf,pos))
277 # define RIVALS(buf,pos) IREV(IVALS(buf,pos))
278 # define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
279 # define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
280 # define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
281 # define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
283 /* reads multiple data from an SMB buffer (big-endian) */
284 # define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
285 # define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
286 # define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
287 # define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
289 /* stores multiple data in an SMB buffer (big-endian) */
290 # define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
291 # define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
292 # define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
293 # define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
295 # define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
296 { RW_PCVAL(read,inbuf,outbuf,len) \
297 DEBUG_X(5,("%s%04x %s: ", \
298 tab_depth(depth), base,string)); \
299 if (charmode) print_asc(5, US (outbuf), (len)); else \
300 { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%02x ", (outbuf)[idx])); } } \
303 # define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
304 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
305 DEBUG_X(5,("%s%04x %s: ", \
306 tab_depth(depth), base,string)); \
307 if (charmode) print_asc(5, US (outbuf), 2*(len)); else \
308 { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%04x ", (outbuf)[idx])); } } \
311 # define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
312 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
313 DEBUG_X(5,("%s%04x %s: ", \
314 tab_depth(depth), base,string)); \
315 if (charmode) print_asc(5, US (outbuf), 4*(len)); else \
316 { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%08x ", (outbuf)[idx])); } } \
319 # define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
320 { RW_CVAL(read,inbuf,outbuf,0) \
321 DEBUG_X(5,("%s%04x %s: %02x\n", \
322 tab_depth(depth), base, string, outbuf)); }
324 # define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
325 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
326 DEBUG_X(5,("%s%04x %s: %04x\n", \
327 tab_depth(depth), base, string, outbuf)); }
329 # define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
330 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
331 DEBUG_X(5,("%s%04x %s: %08x\n", \
332 tab_depth(depth), base, string, outbuf)); }
334 #endif /* _BYTEORDER_H */
336 void E_P16 (uschar *p14, uschar *p16);
337 void E_P24 (uschar *p21, uschar *c8, uschar *p24);
338 void D_P16 (uschar *p14, uschar *in, uschar *out);
339 void SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24]);
341 void mdfour (uschar *out, uschar *in, int n);
345 * base64.c -- base-64 conversion routines.
347 * For license terms, see the file COPYING in this directory.
349 * This base 64 encoding is defined in RFC2045 section 6.8,
350 * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
354 static const char base64digits[] =
355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
357 #define BAD (char) -1
358 static const char base64val[] = {
359 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
361 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
363 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
365 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
366 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
367 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
368 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
369 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
371 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
374 spa_bits_to_base64 (uschar *out, const uschar *in, int inlen)
375 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
377 for (; inlen >= 3; inlen -= 3)
379 *out++ = base64digits[in[0] >> 2];
380 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
381 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
382 *out++ = base64digits[in[2] & 0x3f];
389 *out++ = base64digits[in[0] >> 2];
390 fragment = (in[0] << 4) & 0x30;
392 fragment |= in[1] >> 4;
393 *out++ = base64digits[fragment];
394 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
401 /* The outlength parameter was added by PH, December 2004 */
404 spa_base64_to_bits (char *out, int outlength, const char *in)
405 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
408 register uschar digit1, digit2, digit3, digit4;
410 if (in[0] == '+' && in[1] == ' ')
417 if (len >= outlength) /* Added by PH */
418 return (-1); /* Added by PH */
420 if (DECODE64 (digit1) == BAD)
423 if (DECODE64 (digit2) == BAD)
426 if (digit3 != '=' && DECODE64 (digit3) == BAD)
429 if (digit4 != '=' && DECODE64 (digit4) == BAD)
432 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
436 if (len >= outlength) /* Added by PH */
437 return (-1); /* Added by PH */
439 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
443 if (len >= outlength) /* Added by PH */
444 return (-1); /* Added by PH */
445 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
450 while (*in && *in != '\r' && digit4 != '=');
456 static uschar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
457 1, 58, 50, 42, 34, 26, 18,
458 10, 2, 59, 51, 43, 35, 27,
459 19, 11, 3, 60, 52, 44, 36,
460 63, 55, 47, 39, 31, 23, 15,
461 7, 62, 54, 46, 38, 30, 22,
462 14, 6, 61, 53, 45, 37, 29,
463 21, 13, 5, 28, 20, 12, 4
466 static uschar perm2[48] = { 14, 17, 11, 24, 1, 5,
467 3, 28, 15, 6, 21, 10,
468 23, 19, 12, 4, 26, 8,
469 16, 7, 27, 20, 13, 2,
470 41, 52, 31, 37, 47, 55,
471 30, 40, 51, 45, 33, 48,
472 44, 49, 39, 56, 34, 53,
473 46, 42, 50, 36, 29, 32
476 static uschar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
477 60, 52, 44, 36, 28, 20, 12, 4,
478 62, 54, 46, 38, 30, 22, 14, 6,
479 64, 56, 48, 40, 32, 24, 16, 8,
480 57, 49, 41, 33, 25, 17, 9, 1,
481 59, 51, 43, 35, 27, 19, 11, 3,
482 61, 53, 45, 37, 29, 21, 13, 5,
483 63, 55, 47, 39, 31, 23, 15, 7
486 static uschar perm4[48] = { 32, 1, 2, 3, 4, 5,
488 8, 9, 10, 11, 12, 13,
489 12, 13, 14, 15, 16, 17,
490 16, 17, 18, 19, 20, 21,
491 20, 21, 22, 23, 24, 25,
492 24, 25, 26, 27, 28, 29,
493 28, 29, 30, 31, 32, 1
496 static uschar perm5[32] = { 16, 7, 20, 21,
507 static uschar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
508 39, 7, 47, 15, 55, 23, 63, 31,
509 38, 6, 46, 14, 54, 22, 62, 30,
510 37, 5, 45, 13, 53, 21, 61, 29,
511 36, 4, 44, 12, 52, 20, 60, 28,
512 35, 3, 43, 11, 51, 19, 59, 27,
513 34, 2, 42, 10, 50, 18, 58, 26,
514 33, 1, 41, 9, 49, 17, 57, 25
518 static uschar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
520 static uschar sbox[8][4][16] = {
521 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
522 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
523 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
524 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
526 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
527 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
528 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
529 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
531 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
532 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
533 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
534 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
536 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
537 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
538 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
539 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
541 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
542 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
543 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
544 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
546 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
547 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
548 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
549 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
551 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
552 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
553 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
554 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
556 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
557 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
558 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
559 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
563 permute (char *out, char *in, uschar * p, int n)
566 for (i = 0; i < n; i++)
567 out[i] = in[p[i] - 1];
571 lshift (char *d, int count, int n)
575 for (i = 0; i < n; i++)
576 out[i] = d[(i + count) % n];
577 for (i = 0; i < n; i++)
582 concat (char *out, char *in1, char *in2, int l1, int l2)
591 xor (char *out, char *in1, char *in2, int n)
594 for (i = 0; i < n; i++)
595 out[i] = in1[i] ^ in2[i];
599 dohash (char *out, char *in, char *key, int forw)
611 permute (pk1, key, perm1, 56);
613 for (i = 0; i < 28; i++)
615 for (i = 0; i < 28; i++)
618 for (i = 0; i < 16; i++)
620 lshift (c, sc[i], 28);
621 lshift (d, sc[i], 28);
623 concat (cd, c, d, 28, 28);
624 permute (ki[i], cd, perm2, 48);
627 permute (pd1, in, perm3, 64);
629 for (j = 0; j < 32; j++)
635 for (i = 0; i < 16; i++)
644 permute (er, r, perm4, 48);
646 xor (erk, er, ki[forw ? i : 15 - i], 48);
648 for (j = 0; j < 8; j++)
649 for (k = 0; k < 6; k++)
650 b[j][k] = erk[j * 6 + k];
652 for (j = 0; j < 8; j++)
655 m = (b[j][0] << 1) | b[j][5];
657 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
659 for (k = 0; k < 4; k++)
660 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
663 for (j = 0; j < 8; j++)
664 for (k = 0; k < 4; k++)
665 cb[j * 4 + k] = b[j][k];
666 permute (pcb, cb, perm5, 32);
668 xor (r2, l, pcb, 32);
670 for (j = 0; j < 32; j++)
673 for (j = 0; j < 32; j++)
677 concat (rl, r, l, 32, 32);
679 permute (out, rl, perm6, 64);
683 str_to_key (uschar *str, uschar *key)
687 key[0] = str[0] >> 1;
688 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
689 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
690 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
691 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
692 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
693 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
694 key[7] = str[6] & 0x7F;
695 for (i = 0; i < 8; i++)
697 key[i] = (key[i] << 1);
703 smbhash (uschar *out, uschar *in, uschar *key, int forw)
711 str_to_key (key, key2);
713 for (i = 0; i < 64; i++)
715 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
716 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
720 dohash (outb, inb, keyb, forw);
722 for (i = 0; i < 8; i++)
727 for (i = 0; i < 64; i++)
730 out[i / 8] |= (1 << (7 - (i % 8)));
735 E_P16 (uschar *p14, uschar *p16)
737 uschar sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
738 smbhash (p16, sp8, p14, 1);
739 smbhash (p16 + 8, sp8, p14 + 7, 1);
743 E_P24 (uschar *p21, uschar *c8, uschar *p24)
745 smbhash (p24, c8, p21, 1);
746 smbhash (p24 + 8, c8, p21 + 7, 1);
747 smbhash (p24 + 16, c8, p21 + 14, 1);
751 D_P16 (uschar *p14, uschar *in, uschar *out)
753 smbhash (out, in, p14, 0);
754 smbhash (out + 8, in + 8, p14 + 7, 0);
757 /****************************************************************************
758 Like strncpy but always null terminates. Make sure there is room!
759 The variable n should always be one less than the available size.
760 ****************************************************************************/
763 StrnCpy (char *dest, const char *src, size_t n)
773 while (n-- && (*d++ = *src++));
779 skip_multibyte_char (char c)
781 /* bogus if to get rid of unused compiler warning */
789 /*******************************************************************
790 safe string copy into a known length string. maxlength does not
791 include the terminating zero.
792 ********************************************************************/
795 safe_strcpy (char *dest, const char *src, size_t maxlength)
801 DEBUG_X (0, ("ERROR: NULL dest in safe_strcpy\n"));
815 DEBUG_X (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
816 (int) (len - maxlength), src));
820 memcpy (dest, src, len);
832 size_t skip = skip_multibyte_char (*s);
837 if (islower ((uschar)(*s)))
847 This implements the X/Open SMB password encryption
848 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
849 encrypted password into p24
853 spa_smb_encrypt (uschar * passwd, uschar * c8, uschar * p24)
855 uschar p14[15], p21[21];
857 memset (p21, '\0', 21);
858 memset (p14, '\0', 14);
859 StrnCpy ((char *) p14, (char *) passwd, 14);
861 strupper ((char *) p14);
864 SMBOWFencrypt (p21, c8, p24);
866 #ifdef DEBUG_PASSWORD
867 DEBUG_X (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
868 dump_data (100, (char *) p21, 16);
869 dump_data (100, (char *) c8, 8);
870 dump_data (100, (char *) p24, 24);
874 /* Routines for Windows NT MD4 Hash functions. */
876 _my_wcslen (int16x * str)
885 * Convert a string into an NT UNICODE string.
886 * Note that regardless of processor type
887 * this must be in intel (little-endian)
892 _my_mbstowcs (int16x * dst, uschar * src, int len)
897 for (i = 0; i < len; i++)
910 * Creates the MD4 Hash of the users password in NT UNICODE.
914 E_md4hash (uschar * passwd, uschar * p16)
919 /* Password cannot be longer than 128 characters */
920 len = strlen ((char *) passwd);
923 /* Password must be converted to NT unicode */
924 _my_mbstowcs (wpwd, passwd, len);
925 wpwd[len] = 0; /* Ensure string is null terminated */
926 /* Calculate length in bytes */
927 len = _my_wcslen (wpwd) * sizeof (int16x);
929 mdfour (p16, US wpwd, len);
932 /* Does both the NT and LM owfs of a user's password */
934 nt_lm_owf_gen (char *pwd, uschar nt_p16[16], uschar p16[16])
938 memset (passwd, '\0', 130);
939 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
941 /* Calculate the MD4 hash (NT compatible) of the password */
942 memset (nt_p16, '\0', 16);
943 E_md4hash (US passwd, nt_p16);
945 #ifdef DEBUG_PASSWORD
946 DEBUG_X (100, ("nt_lm_owf_gen: pwd, nt#\n"));
947 dump_data (120, passwd, strlen (passwd));
948 dump_data (100, (char *) nt_p16, 16);
951 /* Mangle the passwords into Lanman format */
955 /* Calculate the SMB (lanman) hash functions of the password */
957 memset (p16, '\0', 16);
958 E_P16 (US passwd, US p16);
960 #ifdef DEBUG_PASSWORD
961 DEBUG_X (100, ("nt_lm_owf_gen: pwd, lm#\n"));
962 dump_data (120, passwd, strlen (passwd));
963 dump_data (100, (char *) p16, 16);
965 /* clear out local copy of user's password (just being paranoid). */
966 memset (passwd, '\0', sizeof (passwd));
969 /* Does the des encryption from the NT or LM MD4 hash. */
971 SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24])
975 memset (p21, '\0', 21);
977 memcpy (p21, passwd, 16);
978 E_P24 (p21, c8, p24);
981 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
983 NTLMSSPOWFencrypt (uschar passwd[8], uschar * ntlmchalresp, uschar p24[24])
987 memset (p21, '\0', 21);
988 memcpy (p21, passwd, 8);
989 memset (p21 + 8, 0xbd, 8);
991 E_P24 (p21, ntlmchalresp, p24);
992 #ifdef DEBUG_PASSWORD
993 DEBUG_X (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
994 dump_data (100, (char *) p21, 21);
995 dump_data (100, (char *) ntlmchalresp, 8);
996 dump_data (100, (char *) p24, 24);
1001 /* Does the NT MD4 hash then des encryption. */
1004 spa_smb_nt_encrypt (uschar * passwd, uschar * c8, uschar * p24)
1008 memset (p21, '\0', 21);
1010 E_md4hash (passwd, p21);
1011 SMBOWFencrypt (p21, c8, p24);
1013 #ifdef DEBUG_PASSWORD
1014 DEBUG_X (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1015 dump_data (100, (char *) p21, 16);
1016 dump_data (100, (char *) c8, 8);
1017 dump_data (100, (char *) p24, 24);
1021 static uint32x A, B, C, D;
1024 F (uint32x X, uint32x Y, uint32x Z)
1026 return (X & Y) | ((~X) & Z);
1030 G (uint32x X, uint32x Y, uint32x Z)
1032 return (X & Y) | (X & Z) | (Y & Z);
1036 H (uint32x X, uint32x Y, uint32x Z)
1042 lshift_a (uint32x x, int s)
1045 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1048 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1049 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1050 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1052 /* this applies md4 to 64 byte chunks */
1054 spa_mdfour64 (uint32x * M)
1057 uint32x AA, BB, CC, DD;
1060 for (j = 0; j < 16; j++)
1068 ROUND1 (A, B, C, D, 0, 3);
1069 ROUND1 (D, A, B, C, 1, 7);
1070 ROUND1 (C, D, A, B, 2, 11);
1071 ROUND1 (B, C, D, A, 3, 19);
1072 ROUND1 (A, B, C, D, 4, 3);
1073 ROUND1 (D, A, B, C, 5, 7);
1074 ROUND1 (C, D, A, B, 6, 11);
1075 ROUND1 (B, C, D, A, 7, 19);
1076 ROUND1 (A, B, C, D, 8, 3);
1077 ROUND1 (D, A, B, C, 9, 7);
1078 ROUND1 (C, D, A, B, 10, 11);
1079 ROUND1 (B, C, D, A, 11, 19);
1080 ROUND1 (A, B, C, D, 12, 3);
1081 ROUND1 (D, A, B, C, 13, 7);
1082 ROUND1 (C, D, A, B, 14, 11);
1083 ROUND1 (B, C, D, A, 15, 19);
1085 ROUND2 (A, B, C, D, 0, 3);
1086 ROUND2 (D, A, B, C, 4, 5);
1087 ROUND2 (C, D, A, B, 8, 9);
1088 ROUND2 (B, C, D, A, 12, 13);
1089 ROUND2 (A, B, C, D, 1, 3);
1090 ROUND2 (D, A, B, C, 5, 5);
1091 ROUND2 (C, D, A, B, 9, 9);
1092 ROUND2 (B, C, D, A, 13, 13);
1093 ROUND2 (A, B, C, D, 2, 3);
1094 ROUND2 (D, A, B, C, 6, 5);
1095 ROUND2 (C, D, A, B, 10, 9);
1096 ROUND2 (B, C, D, A, 14, 13);
1097 ROUND2 (A, B, C, D, 3, 3);
1098 ROUND2 (D, A, B, C, 7, 5);
1099 ROUND2 (C, D, A, B, 11, 9);
1100 ROUND2 (B, C, D, A, 15, 13);
1102 ROUND3 (A, B, C, D, 0, 3);
1103 ROUND3 (D, A, B, C, 8, 9);
1104 ROUND3 (C, D, A, B, 4, 11);
1105 ROUND3 (B, C, D, A, 12, 15);
1106 ROUND3 (A, B, C, D, 2, 3);
1107 ROUND3 (D, A, B, C, 10, 9);
1108 ROUND3 (C, D, A, B, 6, 11);
1109 ROUND3 (B, C, D, A, 14, 15);
1110 ROUND3 (A, B, C, D, 1, 3);
1111 ROUND3 (D, A, B, C, 9, 9);
1112 ROUND3 (C, D, A, B, 5, 11);
1113 ROUND3 (B, C, D, A, 13, 15);
1114 ROUND3 (A, B, C, D, 3, 3);
1115 ROUND3 (D, A, B, C, 11, 9);
1116 ROUND3 (C, D, A, B, 7, 11);
1117 ROUND3 (B, C, D, A, 15, 15);
1129 for (j = 0; j < 16; j++)
1134 copy64 (uint32x * M, uschar *in)
1138 for (i = 0; i < 16; i++)
1139 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1140 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1144 copy4 (uschar *out, uint32x x)
1147 out[1] = (x >> 8) & 0xFF;
1148 out[2] = (x >> 16) & 0xFF;
1149 out[3] = (x >> 24) & 0xFF;
1152 /* produce a md4 message digest from data of length n bytes */
1154 mdfour (uschar *out, uschar *in, int n)
1174 for (i = 0; i < 128; i++)
1176 memcpy (buf, in, n);
1181 copy4 (buf + 56, b);
1187 copy4 (buf + 120, b);
1190 copy64 (M, buf + 64);
1194 for (i = 0; i < 128; i++)
1201 copy4 (out + 12, D);
1206 char versionString[] = "libntlm version 0.21";
1208 /* Utility routines that handle NTLM auth structures. */
1210 /* The [IS]VAL macros are to take care of byte order for non-Intel
1211 * Machines -- I think this file is OK, but it hasn't been tested.
1212 * The other files (the ones stolen from Samba) should be OK.
1216 /* I am not crazy about these macros -- they seem to have gotten
1217 * a bit complex. A new scheme for handling string/buffer fields
1218 * in the structures probably needs to be designed
1221 #define spa_bytes_add(ptr, header, buf, count) \
1223 if (buf != NULL && count) \
1225 SSVAL(&ptr->header.len,0,count); \
1226 SSVAL(&ptr->header.maxlen,0,count); \
1227 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1228 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1229 ptr->bufIndex += count; \
1234 ptr->header.maxlen = 0; \
1235 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1239 #define spa_string_add(ptr, header, string) \
1243 if (p) len = strlen(p); \
1244 spa_bytes_add(ptr, header, (US p), len); \
1247 #define spa_unicode_add_string(ptr, header, string) \
1255 b = strToUnicode(p); \
1257 spa_bytes_add(ptr, header, b, len*2); \
1261 #define GetUnicodeString(structPtr, header) \
1262 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1263 #define GetString(structPtr, header) \
1264 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1268 #define DumpBuffer(fp, structPtr, header) \
1269 dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1273 dumpRaw (FILE * fp, uschar *buf, size_t len)
1277 for (i = 0; i < len; ++i)
1278 fprintf (fp, "%02x ", buf[i]);
1286 unicodeToString (char *p, size_t len)
1289 static char buf[1024];
1291 assert (len + 1 < sizeof buf);
1293 for (i = 0; i < len; ++i)
1304 strToUnicode (char *p)
1306 static uschar buf[1024];
1307 size_t l = strlen (p);
1310 assert (l * 2 < sizeof buf);
1322 toString (char *p, size_t len)
1324 static uschar buf[1024];
1326 assert (len + 1 < sizeof buf);
1328 memcpy (buf, p, len);
1336 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1338 fprintf (fp, "NTLM Request:\n");
1339 fprintf (fp, " Ident = %s\n", request->ident);
1340 fprintf (fp, " mType = %d\n", IVAL (&request->msgType, 0));
1341 fprintf (fp, " Flags = %08x\n", IVAL (&request->flags, 0));
1342 fprintf (fp, " User = %s\n", GetString (request, user));
1343 fprintf (fp, " Domain = %s\n", GetString (request, domain));
1347 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1349 fprintf (fp, "NTLM Challenge:\n");
1350 fprintf (fp, " Ident = %s\n", challenge->ident);
1351 fprintf (fp, " mType = %d\n", IVAL (&challenge->msgType, 0));
1352 fprintf (fp, " Domain = %s\n", GetUnicodeString (challenge, uDomain));
1353 fprintf (fp, " Flags = %08x\n", IVAL (&challenge->flags, 0));
1354 fprintf (fp, " Challenge = ");
1355 dumpRaw (fp, challenge->challengeData, 8);
1359 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1361 fprintf (fp, "NTLM Response:\n");
1362 fprintf (fp, " Ident = %s\n", response->ident);
1363 fprintf (fp, " mType = %d\n", IVAL (&response->msgType, 0));
1364 fprintf (fp, " LmResp = ");
1365 DumpBuffer (fp, response, lmResponse);
1366 fprintf (fp, " NTResp = ");
1367 DumpBuffer (fp, response, ntResponse);
1368 fprintf (fp, " Domain = %s\n", GetUnicodeString (response, uDomain));
1369 fprintf (fp, " User = %s\n", GetUnicodeString (response, uUser));
1370 fprintf (fp, " Wks = %s\n", GetUnicodeString (response, uWks));
1371 fprintf (fp, " sKey = ");
1372 DumpBuffer (fp, response, sessionKey);
1373 fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0));
1378 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1380 char *u = strdup (user);
1381 char *p = strchr (u, '@');
1390 request->bufIndex = 0;
1391 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1392 SIVAL (&request->msgType, 0, 1);
1393 SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */
1394 spa_string_add (request, user, u);
1395 spa_string_add (request, domain, domain);
1402 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1406 int p = (int)getpid();
1407 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1409 request = request; /* Added by PH to stop compilers whinging */
1411 /* Ensure challenge data is cleared, in case it isn't all used. This
1412 patch added by PH on suggestion of Russell King */
1414 memset(challenge, 0, sizeof(SPAAuthChallenge));
1416 challenge->bufIndex = 0;
1417 memcpy (challenge->ident, "NTLMSSP\0", 8);
1418 SIVAL (&challenge->msgType, 0, 2);
1419 SIVAL (&challenge->flags, 0, 0x00008201);
1420 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1421 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1422 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1424 /* generate eight pseudo random bytes (method ripped from host.c) */
1427 chalstr[i] = (uschar)(random_seed >> 16) % 256;
1428 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1431 memcpy(challenge->challengeData,chalstr,8);
1437 /* This is the original source of this function, preserved here for reference.
1438 The new version below was re-organized by PH following a patch and some further
1439 suggestions from Mark Lyda to fix the problem that is described at the head of
1440 this module. At the same time, I removed the untidiness in the code below that
1441 involves the "d" and "domain" variables. */
1445 spa_build_auth_response (SPAAuthChallenge * challenge,
1446 SPAAuthResponse * response, char *user,
1449 uint8x lmRespData[24];
1450 uint8x ntRespData[24];
1451 char *d = strdup (GetUnicodeString (challenge, uDomain));
1453 char *u = strdup (user);
1454 char *p = strchr (u, '@');
1462 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1463 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1465 response->bufIndex = 0;
1466 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1467 SIVAL (&response->msgType, 0, 3);
1469 spa_bytes_add (response, lmResponse, lmRespData, 24);
1470 spa_bytes_add (response, ntResponse, ntRespData, 24);
1471 spa_unicode_add_string (response, uDomain, domain);
1472 spa_unicode_add_string (response, uUser, u);
1473 spa_unicode_add_string (response, uWks, u);
1474 spa_string_add (response, sessionKey, NULL);
1476 response->flags = challenge->flags;
1484 /* This is the re-organized version (see comments above) */
1487 spa_build_auth_response (SPAAuthChallenge * challenge,
1488 SPAAuthResponse * response, char *user,
1491 uint8x lmRespData[24];
1492 uint8x ntRespData[24];
1493 uint32x cf = IVAL(&challenge->flags, 0);
1494 char *u = strdup (user);
1495 char *p = strchr (u, '@');
1505 else domain = d = strdup((cf & 0x1)?
1506 (const char *)GetUnicodeString(challenge, uDomain) :
1507 (const char *)GetString(challenge, uDomain));
1509 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1510 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1512 response->bufIndex = 0;
1513 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1514 SIVAL (&response->msgType, 0, 3);
1516 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1517 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1519 if (cf & 0x1) { /* Unicode Text */
1520 spa_unicode_add_string (response, uDomain, domain);
1521 spa_unicode_add_string (response, uUser, u);
1522 spa_unicode_add_string (response, uWks, u);
1523 } else { /* OEM Text */
1524 spa_string_add (response, uDomain, domain);
1525 spa_string_add (response, uUser, u);
1526 spa_string_add (response, uWks, u);
1529 spa_string_add (response, sessionKey, NULL);
1530 response->flags = challenge->flags;
1532 if (d != NULL) free (d);