• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * https://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 #include "rand.h"
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 "vauth/vauth.h"
53 #include "vauth/ntlm.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
ntlm_print_flags(FILE * handle,unsigned long flags)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 
ntlm_print_hex(FILE * handle,const char * buf,size_t len)138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
139 {
140   const char *p = buf;
141 
142   (void) handle;
143 
144   fprintf(stderr, "0x");
145   while(len-- > 0)
146     fprintf(stderr, "%02.2x", (unsigned int)*p++);
147 }
148 #else
149 # define DEBUG_OUT(x) Curl_nop_stmt
150 #endif
151 
152 /*
153  * ntlm_decode_type2_target()
154  *
155  * This is used to decode the "target info" in the NTLM type-2 message
156  * received.
157  *
158  * Parameters:
159  *
160  * data      [in]     - The session handle.
161  * buffer    [in]     - The decoded type-2 message.
162  * size      [in]     - The input buffer size, at least 32 bytes.
163  * ntlm      [in/out] - The NTLM data struct being used and modified.
164  *
165  * Returns CURLE_OK on success.
166  */
ntlm_decode_type2_target(struct Curl_easy * data,unsigned char * buffer,size_t size,struct ntlmdata * ntlm)167 static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
168                                          unsigned char *buffer,
169                                          size_t size,
170                                          struct ntlmdata *ntlm)
171 {
172   unsigned short target_info_len = 0;
173   unsigned int target_info_offset = 0;
174 
175 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
176   (void) data;
177 #endif
178 
179   if(size >= 48) {
180     target_info_len = Curl_read16_le(&buffer[40]);
181     target_info_offset = Curl_read32_le(&buffer[44]);
182     if(target_info_len > 0) {
183       if(((target_info_offset + target_info_len) > size) ||
184          (target_info_offset < 48)) {
185         infof(data, "NTLM handshake failure (bad type-2 message). "
186                     "Target Info Offset Len is set incorrect by the peer\n");
187         return CURLE_BAD_CONTENT_ENCODING;
188       }
189 
190       ntlm->target_info = malloc(target_info_len);
191       if(!ntlm->target_info)
192         return CURLE_OUT_OF_MEMORY;
193 
194       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
195     }
196   }
197 
198   ntlm->target_info_len = target_info_len;
199 
200   return CURLE_OK;
201 }
202 
203 /*
204   NTLM message structure notes:
205 
206   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
207 
208   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
209 
210   A 'security buffer' represents a triplet used to point to a buffer,
211   consisting of two shorts and one long:
212 
213     1. A 'short' containing the length of the buffer content in bytes.
214     2. A 'short' containing the allocated space for the buffer in bytes.
215     3. A 'long' containing the offset to the start of the buffer in bytes,
216        from the beginning of the NTLM message.
217 */
218 
219 /*
220  * Curl_auth_is_ntlm_supported()
221  *
222  * This is used to evaluate if NTLM is supported.
223  *
224  * Parameters: None
225  *
226  * Returns TRUE as NTLM as handled by libcurl.
227  */
Curl_auth_is_ntlm_supported(void)228 bool Curl_auth_is_ntlm_supported(void)
229 {
230   return TRUE;
231 }
232 
233 /*
234  * Curl_auth_decode_ntlm_type2_message()
235  *
236  * This is used to decode an already encoded NTLM type-2 message. The message
237  * is first decoded from a base64 string into a raw NTLM message and checked
238  * for validity before the appropriate data for creating a type-3 message is
239  * written to the given NTLM data structure.
240  *
241  * Parameters:
242  *
243  * data     [in]     - The session handle.
244  * type2msg [in]     - The base64 encoded type-2 message.
245  * ntlm     [in/out] - The NTLM data struct being used and modified.
246  *
247  * Returns CURLE_OK on success.
248  */
Curl_auth_decode_ntlm_type2_message(struct Curl_easy * data,const char * type2msg,struct ntlmdata * ntlm)249 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
250                                              const char *type2msg,
251                                              struct ntlmdata *ntlm)
252 {
253   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
254 
255   /* NTLM type-2 message structure:
256 
257           Index  Description            Content
258             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
259                                         (0x4e544c4d53535000)
260             8    NTLM Message Type      long (0x02000000)
261            12    Target Name            security buffer
262            20    Flags                  long
263            24    Challenge              8 bytes
264           (32)   Context                8 bytes (two consecutive longs) (*)
265           (40)   Target Information     security buffer (*)
266           (48)   OS Version Structure   8 bytes (*)
267   32 (48) (56)   Start of data block    (*)
268                                         (*) -> Optional
269   */
270 
271   CURLcode result = CURLE_OK;
272   unsigned char *type2 = NULL;
273   size_t type2_len = 0;
274 
275 #if defined(USE_NSS)
276   /* Make sure the crypto backend is initialized */
277   result = Curl_nss_force_init(data);
278   if(result)
279     return result;
280 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
281   (void)data;
282 #endif
283 
284   /* Decode the base-64 encoded type-2 message */
285   if(strlen(type2msg) && *type2msg != '=') {
286     result = Curl_base64_decode(type2msg, &type2, &type2_len);
287     if(result)
288       return result;
289   }
290 
291   /* Ensure we have a valid type-2 message */
292   if(!type2) {
293     infof(data, "NTLM handshake failure (empty type-2 message)\n");
294     return CURLE_BAD_CONTENT_ENCODING;
295   }
296 
297   ntlm->flags = 0;
298 
299   if((type2_len < 32) ||
300      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
301      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
302     /* This was not a good enough type-2 message */
303     free(type2);
304     infof(data, "NTLM handshake failure (bad type-2 message)\n");
305     return CURLE_BAD_CONTENT_ENCODING;
306   }
307 
308   ntlm->flags = Curl_read32_le(&type2[20]);
309   memcpy(ntlm->nonce, &type2[24], 8);
310 
311   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
312     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
313     if(result) {
314       free(type2);
315       infof(data, "NTLM handshake failure (bad type-2 message)\n");
316       return result;
317     }
318   }
319 
320   DEBUG_OUT({
321     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
322     ntlm_print_flags(stderr, ntlm->flags);
323     fprintf(stderr, "\n                  nonce=");
324     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
325     fprintf(stderr, "\n****\n");
326     fprintf(stderr, "**** Header %s\n ", header);
327   });
328 
329   free(type2);
330 
331   return result;
332 }
333 
334 /* copy the source to the destination and fill in zeroes in every
335    other destination byte! */
unicodecpy(unsigned char * dest,const char * src,size_t length)336 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
337 {
338   size_t i;
339   for(i = 0; i < length; i++) {
340     dest[2 * i] = (unsigned char)src[i];
341     dest[2 * i + 1] = '\0';
342   }
343 }
344 
345 /*
346  * Curl_auth_create_ntlm_type1_message()
347  *
348  * This is used to generate an already encoded NTLM type-1 message ready for
349  * sending to the recipient using the appropriate compile time crypto API.
350  *
351  * Parameters:
352  *
353  * userp   [in]     - The user name in the format User or Domain\User.
354  * passdwp [in]     - The user's password.
355  * ntlm    [in/out] - The NTLM data struct being used and modified.
356  * outptr  [in/out] - The address where a pointer to newly allocated memory
357  *                    holding the result will be stored upon completion.
358  * outlen  [out]    - The length of the output message.
359  *
360  * Returns CURLE_OK on success.
361  */
Curl_auth_create_ntlm_type1_message(const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)362 CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
363                                              const char *passwdp,
364                                              struct ntlmdata *ntlm,
365                                              char **outptr, size_t *outlen)
366 {
367   /* NTLM type-1 message structure:
368 
369        Index  Description            Content
370          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
371                                      (0x4e544c4d53535000)
372          8    NTLM Message Type      long (0x01000000)
373         12    Flags                  long
374        (16)   Supplied Domain        security buffer (*)
375        (24)   Supplied Workstation   security buffer (*)
376        (32)   OS Version Structure   8 bytes (*)
377   (32) (40)   Start of data block    (*)
378                                      (*) -> Optional
379   */
380 
381   size_t size;
382 
383   unsigned char ntlmbuf[NTLM_BUFSIZE];
384   const char *host = "";              /* empty */
385   const char *domain = "";            /* empty */
386   size_t hostlen = 0;
387   size_t domlen = 0;
388   size_t hostoff = 0;
389   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
390                                          domain are empty */
391   (void)userp;
392   (void)passwdp;
393 
394   /* Clean up any former leftovers and initialise to defaults */
395   Curl_auth_ntlm_cleanup(ntlm);
396 
397 #if USE_NTRESPONSES && USE_NTLM2SESSION
398 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
399 #else
400 #define NTLM2FLAG 0
401 #endif
402   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
403            NTLMSSP_SIGNATURE "%c"
404            "\x01%c%c%c" /* 32-bit type = 1 */
405            "%c%c%c%c"   /* 32-bit NTLM flag field */
406            "%c%c"       /* domain length */
407            "%c%c"       /* domain allocated space */
408            "%c%c"       /* domain name offset */
409            "%c%c"       /* 2 zeroes */
410            "%c%c"       /* host length */
411            "%c%c"       /* host allocated space */
412            "%c%c"       /* host name offset */
413            "%c%c"       /* 2 zeroes */
414            "%s"         /* host name */
415            "%s",        /* domain string */
416            0,           /* trailing zero */
417            0, 0, 0,     /* part of type-1 long */
418 
419            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
420                        NTLMFLAG_REQUEST_TARGET |
421                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
422                        NTLM2FLAG |
423                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
424            SHORTPAIR(domlen),
425            SHORTPAIR(domlen),
426            SHORTPAIR(domoff),
427            0, 0,
428            SHORTPAIR(hostlen),
429            SHORTPAIR(hostlen),
430            SHORTPAIR(hostoff),
431            0, 0,
432            host,  /* this is empty */
433            domain /* this is empty */);
434 
435   /* Initial packet length */
436   size = 32 + hostlen + domlen;
437 
438   DEBUG_OUT({
439     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
440             "0x%08.8x ",
441             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
442                         NTLMFLAG_REQUEST_TARGET |
443                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
444                         NTLM2FLAG |
445                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
446             NTLMFLAG_NEGOTIATE_OEM |
447             NTLMFLAG_REQUEST_TARGET |
448             NTLMFLAG_NEGOTIATE_NTLM_KEY |
449             NTLM2FLAG |
450             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
451     ntlm_print_flags(stderr,
452                      NTLMFLAG_NEGOTIATE_OEM |
453                      NTLMFLAG_REQUEST_TARGET |
454                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
455                      NTLM2FLAG |
456                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
457     fprintf(stderr, "\n****\n");
458   });
459 
460   /* Return with binary blob encoded into base64 */
461   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
462 }
463 
464 /*
465  * Curl_auth_create_ntlm_type3_message()
466  *
467  * This is used to generate an already encoded NTLM type-3 message ready for
468  * sending to the recipient using the appropriate compile time crypto API.
469  *
470  * Parameters:
471  *
472  * data    [in]     - The session handle.
473  * userp   [in]     - The user name in the format User or Domain\User.
474  * passdwp [in]     - The user's password.
475  * ntlm    [in/out] - The NTLM data struct being used and modified.
476  * outptr  [in/out] - The address where a pointer to newly allocated memory
477  *                    holding the result will be stored upon completion.
478  * outlen  [out]    - The length of the output message.
479  *
480  * Returns CURLE_OK on success.
481  */
Curl_auth_create_ntlm_type3_message(struct Curl_easy * data,const char * userp,const char * passwdp,struct ntlmdata * ntlm,char ** outptr,size_t * outlen)482 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
483                                              const char *userp,
484                                              const char *passwdp,
485                                              struct ntlmdata *ntlm,
486                                              char **outptr, size_t *outlen)
487 
488 {
489   /* NTLM type-3 message structure:
490 
491           Index  Description            Content
492             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
493                                         (0x4e544c4d53535000)
494             8    NTLM Message Type      long (0x03000000)
495            12    LM/LMv2 Response       security buffer
496            20    NTLM/NTLMv2 Response   security buffer
497            28    Target Name            security buffer
498            36    User Name              security buffer
499            44    Workstation Name       security buffer
500           (52)   Session Key            security buffer (*)
501           (60)   Flags                  long (*)
502           (64)   OS Version Structure   8 bytes (*)
503   52 (64) (72)   Start of data block
504                                           (*) -> Optional
505   */
506 
507   CURLcode result = CURLE_OK;
508   size_t size;
509   unsigned char ntlmbuf[NTLM_BUFSIZE];
510   int lmrespoff;
511   unsigned char lmresp[24]; /* fixed-size */
512 #if USE_NTRESPONSES
513   int ntrespoff;
514   unsigned int ntresplen = 24;
515   unsigned char ntresp[24]; /* fixed-size */
516   unsigned char *ptr_ntresp = &ntresp[0];
517   unsigned char *ntlmv2resp = NULL;
518 #endif
519   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
520   char host[HOSTNAME_MAX + 1] = "";
521   const char *user;
522   const char *domain = "";
523   size_t hostoff = 0;
524   size_t useroff = 0;
525   size_t domoff = 0;
526   size_t hostlen = 0;
527   size_t userlen = 0;
528   size_t domlen = 0;
529 
530   user = strchr(userp, '\\');
531   if(!user)
532     user = strchr(userp, '/');
533 
534   if(user) {
535     domain = userp;
536     domlen = (user - domain);
537     user++;
538   }
539   else
540     user = userp;
541 
542   if(user)
543     userlen = strlen(user);
544 
545   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
546      qualified domain name */
547   if(Curl_gethostname(host, sizeof(host))) {
548     infof(data, "gethostname() failed, continuing without!\n");
549     hostlen = 0;
550   }
551   else {
552     hostlen = strlen(host);
553   }
554 
555 #if USE_NTRESPONSES && USE_NTLM_V2
556   if(ntlm->target_info_len) {
557     unsigned char ntbuffer[0x18];
558     unsigned int entropy[2];
559     unsigned char ntlmv2hash[0x18];
560 
561     result = Curl_rand(data, &entropy[0], 2);
562     if(result)
563       return result;
564 
565     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
566     if(result)
567       return result;
568 
569     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
570                                            ntbuffer, ntlmv2hash);
571     if(result)
572       return result;
573 
574     /* LMv2 response */
575     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
576                                          (unsigned char *)&entropy[0],
577                                          &ntlm->nonce[0], lmresp);
578     if(result)
579       return result;
580 
581     /* NTLMv2 response */
582     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
583                                            (unsigned char *)&entropy[0],
584                                            ntlm, &ntlmv2resp, &ntresplen);
585     if(result)
586       return result;
587 
588     ptr_ntresp = ntlmv2resp;
589   }
590   else
591 #endif
592 
593 #if USE_NTRESPONSES && USE_NTLM2SESSION
594   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
595   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
596     unsigned char ntbuffer[0x18];
597     unsigned char tmp[0x18];
598     unsigned char md5sum[MD5_DIGEST_LENGTH];
599     unsigned int entropy[2];
600 
601     /* Need to create 8 bytes random data */
602     result = Curl_rand(data, &entropy[0], 2);
603     if(result)
604       return result;
605 
606     /* 8 bytes random data as challenge in lmresp */
607     memcpy(lmresp, entropy, 8);
608 
609     /* Pad with zeros */
610     memset(lmresp + 8, 0, 0x10);
611 
612     /* Fill tmp with challenge(nonce?) + entropy */
613     memcpy(tmp, &ntlm->nonce[0], 8);
614     memcpy(tmp + 8, entropy, 8);
615 
616     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
617     if(!result)
618       /* We shall only use the first 8 bytes of md5sum, but the des code in
619          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
620       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
621     if(result)
622       return result;
623 
624     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
625 
626     /* End of NTLM2 Session code */
627 
628   }
629   else
630 #endif
631   {
632 
633 #if USE_NTRESPONSES
634     unsigned char ntbuffer[0x18];
635 #endif
636     unsigned char lmbuffer[0x18];
637 
638 #if USE_NTRESPONSES
639     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
640     if(result)
641       return result;
642 
643     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
644 #endif
645 
646     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
647     if(result)
648       return result;
649 
650     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
651 
652     /* A safer but less compatible alternative is:
653      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
654      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
655   }
656 
657   if(unicode) {
658     domlen = domlen * 2;
659     userlen = userlen * 2;
660     hostlen = hostlen * 2;
661   }
662 
663   lmrespoff = 64; /* size of the message header */
664 #if USE_NTRESPONSES
665   ntrespoff = lmrespoff + 0x18;
666   domoff = ntrespoff + ntresplen;
667 #else
668   domoff = lmrespoff + 0x18;
669 #endif
670   useroff = domoff + domlen;
671   hostoff = useroff + userlen;
672 
673   /* Create the big type-3 message binary blob */
674   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
675                   NTLMSSP_SIGNATURE "%c"
676                   "\x03%c%c%c"  /* 32-bit type = 3 */
677 
678                   "%c%c"  /* LanManager length */
679                   "%c%c"  /* LanManager allocated space */
680                   "%c%c"  /* LanManager offset */
681                   "%c%c"  /* 2 zeroes */
682 
683                   "%c%c"  /* NT-response length */
684                   "%c%c"  /* NT-response allocated space */
685                   "%c%c"  /* NT-response offset */
686                   "%c%c"  /* 2 zeroes */
687 
688                   "%c%c"  /* domain length */
689                   "%c%c"  /* domain allocated space */
690                   "%c%c"  /* domain name offset */
691                   "%c%c"  /* 2 zeroes */
692 
693                   "%c%c"  /* user length */
694                   "%c%c"  /* user allocated space */
695                   "%c%c"  /* user offset */
696                   "%c%c"  /* 2 zeroes */
697 
698                   "%c%c"  /* host length */
699                   "%c%c"  /* host allocated space */
700                   "%c%c"  /* host offset */
701                   "%c%c"  /* 2 zeroes */
702 
703                   "%c%c"  /* session key length (unknown purpose) */
704                   "%c%c"  /* session key allocated space (unknown purpose) */
705                   "%c%c"  /* session key offset (unknown purpose) */
706                   "%c%c"  /* 2 zeroes */
707 
708                   "%c%c%c%c",  /* flags */
709 
710                   /* domain string */
711                   /* user string */
712                   /* host string */
713                   /* LanManager response */
714                   /* NT response */
715 
716                   0,                /* zero termination */
717                   0, 0, 0,          /* type-3 long, the 24 upper bits */
718 
719                   SHORTPAIR(0x18),  /* LanManager response length, twice */
720                   SHORTPAIR(0x18),
721                   SHORTPAIR(lmrespoff),
722                   0x0, 0x0,
723 
724 #if USE_NTRESPONSES
725                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
726                   SHORTPAIR(ntresplen),
727                   SHORTPAIR(ntrespoff),
728                   0x0, 0x0,
729 #else
730                   0x0, 0x0,
731                   0x0, 0x0,
732                   0x0, 0x0,
733                   0x0, 0x0,
734 #endif
735                   SHORTPAIR(domlen),
736                   SHORTPAIR(domlen),
737                   SHORTPAIR(domoff),
738                   0x0, 0x0,
739 
740                   SHORTPAIR(userlen),
741                   SHORTPAIR(userlen),
742                   SHORTPAIR(useroff),
743                   0x0, 0x0,
744 
745                   SHORTPAIR(hostlen),
746                   SHORTPAIR(hostlen),
747                   SHORTPAIR(hostoff),
748                   0x0, 0x0,
749 
750                   0x0, 0x0,
751                   0x0, 0x0,
752                   0x0, 0x0,
753                   0x0, 0x0,
754 
755                   LONGQUARTET(ntlm->flags));
756 
757   DEBUGASSERT(size == 64);
758   DEBUGASSERT(size == (size_t)lmrespoff);
759 
760   /* We append the binary hashes */
761   if(size < (NTLM_BUFSIZE - 0x18)) {
762     memcpy(&ntlmbuf[size], lmresp, 0x18);
763     size += 0x18;
764   }
765 
766   DEBUG_OUT({
767     fprintf(stderr, "**** TYPE3 header lmresp=");
768     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
769   });
770 
771 #if USE_NTRESPONSES
772   if(size < (NTLM_BUFSIZE - ntresplen)) {
773     DEBUGASSERT(size == (size_t)ntrespoff);
774     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
775     size += ntresplen;
776   }
777 
778   DEBUG_OUT({
779     fprintf(stderr, "\n   ntresp=");
780     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
781   });
782 
783   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
784 
785 #endif
786 
787   DEBUG_OUT({
788     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
789             LONGQUARTET(ntlm->flags), ntlm->flags);
790     ntlm_print_flags(stderr, ntlm->flags);
791     fprintf(stderr, "\n****\n");
792   });
793 
794   /* Make sure that the domain, user and host strings fit in the
795      buffer before we copy them there. */
796   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
797     failf(data, "user + domain + host name too big");
798     return CURLE_OUT_OF_MEMORY;
799   }
800 
801   DEBUGASSERT(size == domoff);
802   if(unicode)
803     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
804   else
805     memcpy(&ntlmbuf[size], domain, domlen);
806 
807   size += domlen;
808 
809   DEBUGASSERT(size == useroff);
810   if(unicode)
811     unicodecpy(&ntlmbuf[size], user, userlen / 2);
812   else
813     memcpy(&ntlmbuf[size], user, userlen);
814 
815   size += userlen;
816 
817   DEBUGASSERT(size == hostoff);
818   if(unicode)
819     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
820   else
821     memcpy(&ntlmbuf[size], host, hostlen);
822 
823   size += hostlen;
824 
825   /* Convert domain, user, and host to ASCII but leave the rest as-is */
826   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
827                                    size - domoff);
828   if(result)
829     return CURLE_CONV_FAILED;
830 
831   /* Return with binary blob encoded into base64 */
832   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
833 
834   Curl_auth_ntlm_cleanup(ntlm);
835 
836   return result;
837 }
838 
839 /*
840 * Curl_auth_ntlm_cleanup()
841 *
842 * This is used to clean up the NTLM specific data.
843 *
844 * Parameters:
845 *
846 * ntlm    [in/out] - The NTLM data struct being cleaned up.
847 *
848 */
Curl_auth_ntlm_cleanup(struct ntlmdata * ntlm)849 void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
850 {
851   /* Free the target info */
852   Curl_safefree(ntlm->target_info);
853 
854   /* Reset any variables */
855   ntlm->target_info_len = 0;
856 }
857 
858 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */
859