Imported Upstream version 7.48.0
[platform/upstream/curl.git] / lib / curl_ntlm_msgs.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
26
27 /*
28  * NTLM details:
29  *
30  * http://davenport.sourceforge.net/ntlm.html
31  * http://www.innovation.ch/java/ntlm.html
32  */
33
34 #define DEBUG_ME 0
35
36 #include "urldata.h"
37 #include "non-ascii.h"
38 #include "sendf.h"
39 #include "curl_base64.h"
40 #include "curl_ntlm_core.h"
41 #include "curl_gethostname.h"
42 #include "curl_multibyte.h"
43 #include "warnless.h"
44
45 #include "vtls/vtls.h"
46
47 #ifdef USE_NSS
48 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
49 #endif
50
51 #define BUILDING_CURL_NTLM_MSGS_C
52 #include "curl_ntlm_msgs.h"
53 #include "curl_sasl.h"
54 #include "curl_endian.h"
55 #include "curl_printf.h"
56
57 /* The last #include files should be: */
58 #include "curl_memory.h"
59 #include "memdebug.h"
60
61 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
62 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
63
64 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
65 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
66   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
67
68 #if DEBUG_ME
69 # define DEBUG_OUT(x) x
70 static void ntlm_print_flags(FILE *handle, unsigned long flags)
71 {
72   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
73     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
74   if(flags & NTLMFLAG_NEGOTIATE_OEM)
75     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
76   if(flags & NTLMFLAG_REQUEST_TARGET)
77     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
78   if(flags & (1<<3))
79     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
80   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
81     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
82   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
83     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
84   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
85     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
86   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
87     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
88   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
89     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
90   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
91     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
92   if(flags & (1<<10))
93     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
94   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
95     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
96   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
97     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
98   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
99     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
100   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
101     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
102   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
103     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
104   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
105     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
106   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
107     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
108   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
109     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
110   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
111     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
112   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
113     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
114   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
115     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
116   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
117     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
118   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
119     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
120   if(flags & (1<<24))
121     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
122   if(flags & (1<<25))
123     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
124   if(flags & (1<<26))
125     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
126   if(flags & (1<<27))
127     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
128   if(flags & (1<<28))
129     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
130   if(flags & NTLMFLAG_NEGOTIATE_128)
131     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
132   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
133     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
134   if(flags & NTLMFLAG_NEGOTIATE_56)
135     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
136 }
137
138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
139 {
140   const char *p = buf;
141   (void)handle;
142   fprintf(stderr, "0x");
143   while(len-- > 0)
144     fprintf(stderr, "%02.2x", (unsigned int)*p++);
145 }
146 #else
147 # define DEBUG_OUT(x) Curl_nop_stmt
148 #endif
149
150 /*
151  * ntlm_decode_type2_target()
152  *
153  * This is used to decode the "target info" in the NTLM type-2 message
154  * received.
155  *
156  * Parameters:
157  *
158  * data      [in]     - The session handle.
159  * buffer    [in]     - The decoded type-2 message.
160  * size      [in]     - The input buffer size, at least 32 bytes.
161  * ntlm      [in/out] - The NTLM data struct being used and modified.
162  *
163  * Returns CURLE_OK on success.
164  */
165 static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
166                                          unsigned char *buffer,
167                                          size_t size,
168                                          struct ntlmdata *ntlm)
169 {
170   unsigned short target_info_len = 0;
171   unsigned int target_info_offset = 0;
172
173 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
174   (void) data;
175 #endif
176
177   if(size >= 48) {
178     target_info_len = Curl_read16_le(&buffer[40]);
179     target_info_offset = Curl_read32_le(&buffer[44]);
180     if(target_info_len > 0) {
181       if(((target_info_offset + target_info_len) > size) ||
182          (target_info_offset < 48)) {
183         infof(data, "NTLM handshake failure (bad type-2 message). "
184                     "Target Info Offset Len is set incorrect by the peer\n");
185         return CURLE_BAD_CONTENT_ENCODING;
186       }
187
188       ntlm->target_info = malloc(target_info_len);
189       if(!ntlm->target_info)
190         return CURLE_OUT_OF_MEMORY;
191
192       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
193     }
194   }
195
196   ntlm->target_info_len = target_info_len;
197
198   return CURLE_OK;
199 }
200
201 /*
202   NTLM message structure notes:
203
204   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
205
206   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
207
208   A 'security buffer' represents a triplet used to point to a buffer,
209   consisting of two shorts and one long:
210
211     1. A 'short' containing the length of the buffer content in bytes.
212     2. A 'short' containing the allocated space for the buffer in bytes.
213     3. A 'long' containing the offset to the start of the buffer in bytes,
214        from the beginning of the NTLM message.
215 */
216
217 /*
218  * Curl_sasl_decode_ntlm_type2_message()
219  *
220  * This is used to decode an already encoded NTLM type-2 message. The message
221  * is first decoded from a base64 string into a raw NTLM message and checked
222  * for validity before the appropriate data for creating a type-3 message is
223  * written to the given NTLM data structure.
224  *
225  * Parameters:
226  *
227  * data     [in]     - The session handle.
228  * type2msg [in]     - The base64 encoded type-2 message.
229  * ntlm     [in/out] - The NTLM data struct being used and modified.
230  *
231  * Returns CURLE_OK on success.
232  */
233 CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
234                                              const char *type2msg,
235                                              struct ntlmdata *ntlm)
236 {
237   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
238
239   /* NTLM type-2 message structure:
240
241           Index  Description            Content
242             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
243                                         (0x4e544c4d53535000)
244             8    NTLM Message Type      long (0x02000000)
245            12    Target Name            security buffer
246            20    Flags                  long
247            24    Challenge              8 bytes
248           (32)   Context                8 bytes (two consecutive longs) (*)
249           (40)   Target Information     security buffer (*)
250           (48)   OS Version Structure   8 bytes (*)
251   32 (48) (56)   Start of data block    (*)
252                                         (*) -> Optional
253   */
254
255   CURLcode result = CURLE_OK;
256   unsigned char *type2 = NULL;
257   size_t type2_len = 0;
258
259 #if defined(USE_NSS)
260   /* Make sure the crypto backend is initialized */
261   result = Curl_nss_force_init(data);
262   if(result)
263     return result;
264 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
265   (void)data;
266 #endif
267
268   /* Decode the base-64 encoded type-2 message */
269   if(strlen(type2msg) && *type2msg != '=') {
270     result = Curl_base64_decode(type2msg, &type2, &type2_len);
271     if(result)
272       return result;
273   }
274
275   /* Ensure we have a valid type-2 message */
276   if(!type2) {
277     infof(data, "NTLM handshake failure (empty type-2 message)\n");
278     return CURLE_BAD_CONTENT_ENCODING;
279   }
280
281   ntlm->flags = 0;
282
283   if((type2_len < 32) ||
284      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
285      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
286     /* This was not a good enough type-2 message */
287     free(type2);
288     infof(data, "NTLM handshake failure (bad type-2 message)\n");
289     return CURLE_BAD_CONTENT_ENCODING;
290   }
291
292   ntlm->flags = Curl_read32_le(&type2[20]);
293   memcpy(ntlm->nonce, &type2[24], 8);
294
295   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
296     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
297     if(result) {
298       free(type2);
299       infof(data, "NTLM handshake failure (bad type-2 message)\n");
300       return result;
301     }
302   }
303
304   DEBUG_OUT({
305     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
306     ntlm_print_flags(stderr, ntlm->flags);
307     fprintf(stderr, "\n                  nonce=");
308     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
309     fprintf(stderr, "\n****\n");
310     fprintf(stderr, "**** Header %s\n ", header);
311   });
312
313   free(type2);
314
315   return result;
316 }
317
318 /* copy the source to the destination and fill in zeroes in every
319    other destination byte! */
320 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
321 {
322   size_t i;
323   for(i = 0; i < length; i++) {
324     dest[2 * i] = (unsigned char)src[i];
325     dest[2 * i + 1] = '\0';
326   }
327 }
328
329 /*
330  * Curl_sasl_create_ntlm_type1_message()
331  *
332  * This is used to generate an already encoded NTLM type-1 message ready for
333  * sending to the recipient using the appropriate compile time crypto API.
334  *
335  * Parameters:
336  *
337  * userp   [in]     - The user name in the format User or Domain\User.
338  * passdwp [in]     - The user's password.
339  * ntlm    [in/out] - The NTLM data struct being used and modified.
340  * outptr  [in/out] - The address where a pointer to newly allocated memory
341  *                    holding the result will be stored upon completion.
342  * outlen  [out]    - The length of the output message.
343  *
344  * Returns CURLE_OK on success.
345  */
346 CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
347                                              const char *passwdp,
348                                              struct ntlmdata *ntlm,
349                                              char **outptr, size_t *outlen)
350 {
351   /* NTLM type-1 message structure:
352
353        Index  Description            Content
354          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
355                                      (0x4e544c4d53535000)
356          8    NTLM Message Type      long (0x01000000)
357         12    Flags                  long
358        (16)   Supplied Domain        security buffer (*)
359        (24)   Supplied Workstation   security buffer (*)
360        (32)   OS Version Structure   8 bytes (*)
361   (32) (40)   Start of data block    (*)
362                                      (*) -> Optional
363   */
364
365   size_t size;
366
367   unsigned char ntlmbuf[NTLM_BUFSIZE];
368   const char *host = "";              /* empty */
369   const char *domain = "";            /* empty */
370   size_t hostlen = 0;
371   size_t domlen = 0;
372   size_t hostoff = 0;
373   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
374                                          domain are empty */
375   (void)userp;
376   (void)passwdp;
377
378   /* Clean up any former leftovers and initialise to defaults */
379   Curl_sasl_ntlm_cleanup(ntlm);
380
381 #if USE_NTRESPONSES && USE_NTLM2SESSION
382 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
383 #else
384 #define NTLM2FLAG 0
385 #endif
386   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
387            NTLMSSP_SIGNATURE "%c"
388            "\x01%c%c%c" /* 32-bit type = 1 */
389            "%c%c%c%c"   /* 32-bit NTLM flag field */
390            "%c%c"       /* domain length */
391            "%c%c"       /* domain allocated space */
392            "%c%c"       /* domain name offset */
393            "%c%c"       /* 2 zeroes */
394            "%c%c"       /* host length */
395            "%c%c"       /* host allocated space */
396            "%c%c"       /* host name offset */
397            "%c%c"       /* 2 zeroes */
398            "%s"         /* host name */
399            "%s",        /* domain string */
400            0,           /* trailing zero */
401            0, 0, 0,     /* part of type-1 long */
402
403            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
404                        NTLMFLAG_REQUEST_TARGET |
405                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
406                        NTLM2FLAG |
407                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
408            SHORTPAIR(domlen),
409            SHORTPAIR(domlen),
410            SHORTPAIR(domoff),
411            0, 0,
412            SHORTPAIR(hostlen),
413            SHORTPAIR(hostlen),
414            SHORTPAIR(hostoff),
415            0, 0,
416            host,  /* this is empty */
417            domain /* this is empty */);
418
419   /* Initial packet length */
420   size = 32 + hostlen + domlen;
421
422   DEBUG_OUT({
423     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
424             "0x%08.8x ",
425             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
426                         NTLMFLAG_REQUEST_TARGET |
427                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
428                         NTLM2FLAG |
429                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
430             NTLMFLAG_NEGOTIATE_OEM |
431             NTLMFLAG_REQUEST_TARGET |
432             NTLMFLAG_NEGOTIATE_NTLM_KEY |
433             NTLM2FLAG |
434             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
435     ntlm_print_flags(stderr,
436                      NTLMFLAG_NEGOTIATE_OEM |
437                      NTLMFLAG_REQUEST_TARGET |
438                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
439                      NTLM2FLAG |
440                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
441     fprintf(stderr, "\n****\n");
442   });
443
444   /* Return with binary blob encoded into base64 */
445   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
446 }
447
448 /*
449  * Curl_sasl_create_ntlm_type3_message()
450  *
451  * This is used to generate an already encoded NTLM type-3 message ready for
452  * sending to the recipient using the appropriate compile time crypto API.
453  *
454  * Parameters:
455  *
456  * data    [in]     - The session handle.
457  * userp   [in]     - The user name in the format User or Domain\User.
458  * passdwp [in]     - The user's password.
459  * ntlm    [in/out] - The NTLM data struct being used and modified.
460  * outptr  [in/out] - The address where a pointer to newly allocated memory
461  *                    holding the result will be stored upon completion.
462  * outlen  [out]    - The length of the output message.
463  *
464  * Returns CURLE_OK on success.
465  */
466 CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
467                                              const char *userp,
468                                              const char *passwdp,
469                                              struct ntlmdata *ntlm,
470                                              char **outptr, size_t *outlen)
471
472 {
473   /* NTLM type-3 message structure:
474
475           Index  Description            Content
476             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
477                                         (0x4e544c4d53535000)
478             8    NTLM Message Type      long (0x03000000)
479            12    LM/LMv2 Response       security buffer
480            20    NTLM/NTLMv2 Response   security buffer
481            28    Target Name            security buffer
482            36    User Name              security buffer
483            44    Workstation Name       security buffer
484           (52)   Session Key            security buffer (*)
485           (60)   Flags                  long (*)
486           (64)   OS Version Structure   8 bytes (*)
487   52 (64) (72)   Start of data block
488                                           (*) -> Optional
489   */
490
491   CURLcode result = CURLE_OK;
492   size_t size;
493   unsigned char ntlmbuf[NTLM_BUFSIZE];
494   int lmrespoff;
495   unsigned char lmresp[24]; /* fixed-size */
496 #if USE_NTRESPONSES
497   int ntrespoff;
498   unsigned int ntresplen = 24;
499   unsigned char ntresp[24]; /* fixed-size */
500   unsigned char *ptr_ntresp = &ntresp[0];
501   unsigned char *ntlmv2resp = NULL;
502 #endif
503   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
504   char host[HOSTNAME_MAX + 1] = "";
505   const char *user;
506   const char *domain = "";
507   size_t hostoff = 0;
508   size_t useroff = 0;
509   size_t domoff = 0;
510   size_t hostlen = 0;
511   size_t userlen = 0;
512   size_t domlen = 0;
513
514   user = strchr(userp, '\\');
515   if(!user)
516     user = strchr(userp, '/');
517
518   if(user) {
519     domain = userp;
520     domlen = (user - domain);
521     user++;
522   }
523   else
524     user = userp;
525
526   if(user)
527     userlen = strlen(user);
528
529   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
530      qualified domain name */
531   if(Curl_gethostname(host, sizeof(host))) {
532     infof(data, "gethostname() failed, continuing without!\n");
533     hostlen = 0;
534   }
535   else {
536     hostlen = strlen(host);
537   }
538
539 #if USE_NTRESPONSES && USE_NTLM_V2
540   if(ntlm->target_info_len) {
541     unsigned char ntbuffer[0x18];
542     unsigned int entropy[2];
543     unsigned char ntlmv2hash[0x18];
544
545     entropy[0] = Curl_rand(data);
546     entropy[1] = Curl_rand(data);
547
548     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
549     if(result)
550       return result;
551
552     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
553                                            ntbuffer, ntlmv2hash);
554     if(result)
555       return result;
556
557     /* LMv2 response */
558     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
559                                          (unsigned char *)&entropy[0],
560                                          &ntlm->nonce[0], lmresp);
561     if(result)
562       return result;
563
564     /* NTLMv2 response */
565     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
566                                            (unsigned char *)&entropy[0],
567                                            ntlm, &ntlmv2resp, &ntresplen);
568     if(result)
569       return result;
570
571     ptr_ntresp = ntlmv2resp;
572   }
573   else
574 #endif
575
576 #if USE_NTRESPONSES && USE_NTLM2SESSION
577   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
578   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
579     unsigned char ntbuffer[0x18];
580     unsigned char tmp[0x18];
581     unsigned char md5sum[MD5_DIGEST_LENGTH];
582     unsigned int entropy[2];
583
584     /* Need to create 8 bytes random data */
585     entropy[0] = Curl_rand(data);
586     entropy[1] = Curl_rand(data);
587
588     /* 8 bytes random data as challenge in lmresp */
589     memcpy(lmresp, entropy, 8);
590
591     /* Pad with zeros */
592     memset(lmresp + 8, 0, 0x10);
593
594     /* Fill tmp with challenge(nonce?) + entropy */
595     memcpy(tmp, &ntlm->nonce[0], 8);
596     memcpy(tmp + 8, entropy, 8);
597
598     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
599     if(!result)
600       /* We shall only use the first 8 bytes of md5sum, but the des code in
601          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
602       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
603     if(result)
604       return result;
605
606     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
607
608     /* End of NTLM2 Session code */
609
610   }
611   else
612 #endif
613   {
614
615 #if USE_NTRESPONSES
616     unsigned char ntbuffer[0x18];
617 #endif
618     unsigned char lmbuffer[0x18];
619
620 #if USE_NTRESPONSES
621     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
622     if(result)
623       return result;
624
625     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
626 #endif
627
628     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
629     if(result)
630       return result;
631
632     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
633
634     /* A safer but less compatible alternative is:
635      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
636      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
637   }
638
639   if(unicode) {
640     domlen = domlen * 2;
641     userlen = userlen * 2;
642     hostlen = hostlen * 2;
643   }
644
645   lmrespoff = 64; /* size of the message header */
646 #if USE_NTRESPONSES
647   ntrespoff = lmrespoff + 0x18;
648   domoff = ntrespoff + ntresplen;
649 #else
650   domoff = lmrespoff + 0x18;
651 #endif
652   useroff = domoff + domlen;
653   hostoff = useroff + userlen;
654
655   /* Create the big type-3 message binary blob */
656   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
657                   NTLMSSP_SIGNATURE "%c"
658                   "\x03%c%c%c"  /* 32-bit type = 3 */
659
660                   "%c%c"  /* LanManager length */
661                   "%c%c"  /* LanManager allocated space */
662                   "%c%c"  /* LanManager offset */
663                   "%c%c"  /* 2 zeroes */
664
665                   "%c%c"  /* NT-response length */
666                   "%c%c"  /* NT-response allocated space */
667                   "%c%c"  /* NT-response offset */
668                   "%c%c"  /* 2 zeroes */
669
670                   "%c%c"  /* domain length */
671                   "%c%c"  /* domain allocated space */
672                   "%c%c"  /* domain name offset */
673                   "%c%c"  /* 2 zeroes */
674
675                   "%c%c"  /* user length */
676                   "%c%c"  /* user allocated space */
677                   "%c%c"  /* user offset */
678                   "%c%c"  /* 2 zeroes */
679
680                   "%c%c"  /* host length */
681                   "%c%c"  /* host allocated space */
682                   "%c%c"  /* host offset */
683                   "%c%c"  /* 2 zeroes */
684
685                   "%c%c"  /* session key length (unknown purpose) */
686                   "%c%c"  /* session key allocated space (unknown purpose) */
687                   "%c%c"  /* session key offset (unknown purpose) */
688                   "%c%c"  /* 2 zeroes */
689
690                   "%c%c%c%c",  /* flags */
691
692                   /* domain string */
693                   /* user string */
694                   /* host string */
695                   /* LanManager response */
696                   /* NT response */
697
698                   0,                /* zero termination */
699                   0, 0, 0,          /* type-3 long, the 24 upper bits */
700
701                   SHORTPAIR(0x18),  /* LanManager response length, twice */
702                   SHORTPAIR(0x18),
703                   SHORTPAIR(lmrespoff),
704                   0x0, 0x0,
705
706 #if USE_NTRESPONSES
707                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
708                   SHORTPAIR(ntresplen),
709                   SHORTPAIR(ntrespoff),
710                   0x0, 0x0,
711 #else
712                   0x0, 0x0,
713                   0x0, 0x0,
714                   0x0, 0x0,
715                   0x0, 0x0,
716 #endif
717                   SHORTPAIR(domlen),
718                   SHORTPAIR(domlen),
719                   SHORTPAIR(domoff),
720                   0x0, 0x0,
721
722                   SHORTPAIR(userlen),
723                   SHORTPAIR(userlen),
724                   SHORTPAIR(useroff),
725                   0x0, 0x0,
726
727                   SHORTPAIR(hostlen),
728                   SHORTPAIR(hostlen),
729                   SHORTPAIR(hostoff),
730                   0x0, 0x0,
731
732                   0x0, 0x0,
733                   0x0, 0x0,
734                   0x0, 0x0,
735                   0x0, 0x0,
736
737                   LONGQUARTET(ntlm->flags));
738
739   DEBUGASSERT(size == 64);
740   DEBUGASSERT(size == (size_t)lmrespoff);
741
742   /* We append the binary hashes */
743   if(size < (NTLM_BUFSIZE - 0x18)) {
744     memcpy(&ntlmbuf[size], lmresp, 0x18);
745     size += 0x18;
746   }
747
748   DEBUG_OUT({
749     fprintf(stderr, "**** TYPE3 header lmresp=");
750     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
751   });
752
753 #if USE_NTRESPONSES
754   if(size < (NTLM_BUFSIZE - ntresplen)) {
755     DEBUGASSERT(size == (size_t)ntrespoff);
756     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
757     size += ntresplen;
758   }
759
760   DEBUG_OUT({
761     fprintf(stderr, "\n   ntresp=");
762     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
763   });
764
765   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
766
767 #endif
768
769   DEBUG_OUT({
770     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
771             LONGQUARTET(ntlm->flags), ntlm->flags);
772     ntlm_print_flags(stderr, ntlm->flags);
773     fprintf(stderr, "\n****\n");
774   });
775
776   /* Make sure that the domain, user and host strings fit in the
777      buffer before we copy them there. */
778   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
779     failf(data, "user + domain + host name too big");
780     return CURLE_OUT_OF_MEMORY;
781   }
782
783   DEBUGASSERT(size == domoff);
784   if(unicode)
785     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
786   else
787     memcpy(&ntlmbuf[size], domain, domlen);
788
789   size += domlen;
790
791   DEBUGASSERT(size == useroff);
792   if(unicode)
793     unicodecpy(&ntlmbuf[size], user, userlen / 2);
794   else
795     memcpy(&ntlmbuf[size], user, userlen);
796
797   size += userlen;
798
799   DEBUGASSERT(size == hostoff);
800   if(unicode)
801     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
802   else
803     memcpy(&ntlmbuf[size], host, hostlen);
804
805   size += hostlen;
806
807   /* Convert domain, user, and host to ASCII but leave the rest as-is */
808   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
809                                    size - domoff);
810   if(result)
811     return CURLE_CONV_FAILED;
812
813   /* Return with binary blob encoded into base64 */
814   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
815
816   Curl_sasl_ntlm_cleanup(ntlm);
817
818   return result;
819 }
820
821 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */