Indentation fixes, untabify and related whitespace-cleanup. No code changed.
[platform/upstream/curl.git] / lib / http_ntlm.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2009, 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 http://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  * $Id$
22  ***************************************************************************/
23 #include "setup.h"
24
25 /* NTLM details:
26
27    http://davenport.sourceforge.net/ntlm.html
28    http://www.innovation.ch/java/ntlm.html
29
30    Another implementation:
31    http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
32
33 */
34
35 #ifndef CURL_DISABLE_HTTP
36 #ifdef USE_NTLM
37
38 #define DEBUG_ME 0
39
40 /* -- WIN32 approved -- */
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdarg.h>
44 #include <stdlib.h>
45 #include <ctype.h>
46
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50
51 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
52 #include <netdb.h>
53 #endif
54
55 #include "urldata.h"
56 #include "easyif.h"  /* for Curl_convert_... prototypes */
57 #include "sendf.h"
58 #include "rawstr.h"
59 #include "curl_base64.h"
60 #include "http_ntlm.h"
61 #include "url.h"
62 #include "memory.h"
63
64 #define _MPRINTF_REPLACE /* use our functions only */
65 #include <curl/mprintf.h>
66
67 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
68 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
69
70 #ifdef USE_SSLEAY
71 #include "ssluse.h"
72 #    ifdef USE_OPENSSL
73 #      include <openssl/des.h>
74 #      include <openssl/md4.h>
75 #      include <openssl/md5.h>
76 #      include <openssl/ssl.h>
77 #      include <openssl/rand.h>
78 #    else
79 #      include <des.h>
80 #      include <md4.h>
81 #      include <md5.h>
82 #      include <ssl.h>
83 #      include <rand.h>
84 #    endif
85
86 #if OPENSSL_VERSION_NUMBER < 0x00907001L
87 #define DES_key_schedule des_key_schedule
88 #define DES_cblock des_cblock
89 #define DES_set_odd_parity des_set_odd_parity
90 #define DES_set_key des_set_key
91 #define DES_ecb_encrypt des_ecb_encrypt
92
93 /* This is how things were done in the old days */
94 #define DESKEY(x) x
95 #define DESKEYARG(x) x
96 #else
97 /* Modern version */
98 #define DESKEYARG(x) *x
99 #define DESKEY(x) &x
100 #endif
101
102 #elif defined(USE_GNUTLS)
103
104 #include "gtls.h"
105 #include <gcrypt.h>
106
107 #define MD5_DIGEST_LENGTH 16
108 #define MD4_DIGEST_LENGTH 16
109
110 #elif defined(USE_WINDOWS_SSPI)
111
112 #include "curl_sspi.h"
113
114 #else
115 #    error "Can't compile NTLM support without a crypto library."
116 #endif
117
118 /* The last #include file should be: */
119 #include "memdebug.h"
120
121 /* Define this to make the type-3 message include the NT response message */
122 #define USE_NTRESPONSES 1
123
124 /* Define this to make the type-3 message include the NTLM2Session response
125    message, requires USE_NTRESPONSES. */
126 #define USE_NTLM2SESSION 1
127
128 #ifndef USE_WINDOWS_SSPI
129 /* this function converts from the little endian format used in the incoming
130    package to whatever endian format we're using natively */
131 static unsigned int readint_le(unsigned char *buf) /* must point to a
132                                                       4 bytes buffer*/
133 {
134   return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
135     ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
136 }
137 #endif
138
139 #if DEBUG_ME
140 # define DEBUG_OUT(x) x
141 static void print_flags(FILE *handle, unsigned long flags)
142 {
143   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
144     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
145   if(flags & NTLMFLAG_NEGOTIATE_OEM)
146     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
147   if(flags & NTLMFLAG_REQUEST_TARGET)
148     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
149   if(flags & (1<<3))
150     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
151   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
152     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
153   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
154     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
155   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
156     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
157   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
158     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
159   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
160     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
161   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
162     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
163   if(flags & (1<<10))
164     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
165   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
166     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
167   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
168     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
169   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
170     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
171   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
172     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
173   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
174     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
175   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
176     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
177   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
178     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
179   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
180     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
181   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
182     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
183   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
184     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
185   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
186     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
187   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
188     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
189   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
190     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
191   if(flags & (1<<24))
192     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
193   if(flags & (1<<25))
194     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
195   if(flags & (1<<26))
196     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
197   if(flags & (1<<27))
198     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
199   if(flags & (1<<28))
200     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
201   if(flags & NTLMFLAG_NEGOTIATE_128)
202     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
203   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
204     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
205   if(flags & NTLMFLAG_NEGOTIATE_56)
206     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
207 }
208
209 static void print_hex(FILE *handle, const char *buf, size_t len)
210 {
211   const char *p = buf;
212   fprintf(stderr, "0x");
213   while(len-- > 0)
214     fprintf(stderr, "%02.2x", (unsigned int)*p++);
215 }
216 #else
217 # define DEBUG_OUT(x)
218 #endif
219
220 /*
221   (*) = A "security buffer" is a triplet consisting of two shorts and one
222   long:
223
224   1. a 'short' containing the length of the buffer in bytes
225   2. a 'short' containing the allocated space for the buffer in bytes
226   3. a 'long' containing the offset to the start of the buffer from the
227      beginning of the NTLM message, in bytes.
228 */
229
230
231 CURLntlm Curl_input_ntlm(struct connectdata *conn,
232                          bool proxy,   /* if proxy or not */
233                          const char *header) /* rest of the www-authenticate:
234                                                 header */
235 {
236   /* point to the correct struct with this */
237   struct ntlmdata *ntlm;
238 #ifndef USE_WINDOWS_SSPI
239   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
240 #endif
241
242   ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
243
244   /* skip initial whitespaces */
245   while(*header && ISSPACE(*header))
246     header++;
247
248   if(checkprefix("NTLM", header)) {
249     header += strlen("NTLM");
250
251     while(*header && ISSPACE(*header))
252       header++;
253
254     if(*header) {
255       /* We got a type-2 message here:
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 (optional)  8 bytes (two consecutive longs)
265          (40)    Target Information  (optional) security buffer(*)
266          32 (48) start of data block
267       */
268       size_t size;
269       unsigned char *buffer;
270       size = Curl_base64_decode(header, &buffer);
271       if(!buffer)
272         return CURLNTLM_BAD;
273
274       ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
275
276 #ifdef USE_WINDOWS_SSPI
277       ntlm->type_2 = malloc(size+1);
278       if(ntlm->type_2 == NULL) {
279         free(buffer);
280         return CURLE_OUT_OF_MEMORY;
281       }
282       ntlm->n_type_2 = size;
283       memcpy(ntlm->type_2, buffer, size);
284 #else
285       ntlm->flags = 0;
286
287       if((size < 32) ||
288          (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
289          (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
290         /* This was not a good enough type-2 message */
291         free(buffer);
292         return CURLNTLM_BAD;
293       }
294
295       ntlm->flags = readint_le(&buffer[20]);
296       memcpy(ntlm->nonce, &buffer[24], 8);
297
298       DEBUG_OUT({
299         fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
300         print_flags(stderr, ntlm->flags);
301         fprintf(stderr, "\n                  nonce=");
302         print_hex(stderr, (char *)ntlm->nonce, 8);
303         fprintf(stderr, "\n****\n");
304         fprintf(stderr, "**** Header %s\n ", header);
305       });
306
307       free(buffer);
308 #endif
309     }
310     else {
311       if(ntlm->state >= NTLMSTATE_TYPE1)
312         return CURLNTLM_BAD;
313
314       ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
315     }
316   }
317   return CURLNTLM_FINE;
318 }
319
320 #ifndef USE_WINDOWS_SSPI
321
322 #ifdef USE_SSLEAY
323 /*
324  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
325  * key schedule ks is also set.
326  */
327 static void setup_des_key(const unsigned char *key_56,
328                           DES_key_schedule DESKEYARG(ks))
329 {
330   DES_cblock key;
331
332   key[0] = key_56[0];
333   key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
334   key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
335   key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
336   key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
337   key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
338   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
339   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
340
341   DES_set_odd_parity(&key);
342   DES_set_key(&key, ks);
343 }
344 #elif defined(USE_GNUTLS)
345
346 /*
347  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
348  */
349 static void setup_des_key(const unsigned char *key_56,
350                           gcry_cipher_hd_t *des)
351 {
352   char key[8];
353
354   key[0] = key_56[0];
355   key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
356   key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
357   key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
358   key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
359   key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
360   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
361   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
362
363   gcry_cipher_setkey(*des, key, 8);
364 }
365 #endif
366
367  /*
368   * takes a 21 byte array and treats it as 3 56-bit DES keys. The
369   * 8 byte plaintext is encrypted with each key and the resulting 24
370   * bytes are stored in the results array.
371   */
372 static void lm_resp(const unsigned char *keys,
373                     const unsigned char *plaintext,
374                     unsigned char *results)
375 {
376 #ifdef USE_SSLEAY
377   DES_key_schedule ks;
378
379   setup_des_key(keys, DESKEY(ks));
380   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
381                   DESKEY(ks), DES_ENCRYPT);
382
383   setup_des_key(keys+7, DESKEY(ks));
384   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
385                   DESKEY(ks), DES_ENCRYPT);
386
387   setup_des_key(keys+14, DESKEY(ks));
388   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
389                   DESKEY(ks), DES_ENCRYPT);
390 #elif USE_GNUTLS
391   gcry_cipher_hd_t des;
392
393   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
394   setup_des_key(keys, &des);
395   gcry_cipher_encrypt(des, results, 8, plaintext, 8);
396   gcry_cipher_close(des);
397
398   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
399   setup_des_key(keys+7, &des);
400   gcry_cipher_encrypt(des, results+8, 8, plaintext, 8);
401   gcry_cipher_close(des);
402
403   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
404   setup_des_key(keys+14, &des);
405   gcry_cipher_encrypt(des, results+16, 8, plaintext, 8);
406   gcry_cipher_close(des);
407 #endif
408 }
409
410
411 /*
412  * Set up lanmanager hashed password
413  */
414 static void mk_lm_hash(struct SessionHandle *data,
415                        const char *password,
416                        unsigned char *lmbuffer /* 21 bytes */)
417 {
418   unsigned char pw[14];
419   static const unsigned char magic[] = {
420     0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
421   };
422   size_t len = CURLMIN(strlen(password), 14);
423
424   Curl_strntoupper((char *)pw, password, len);
425   memset(&pw[len], 0, 14-len);
426
427 #ifdef CURL_DOES_CONVERSIONS
428   /*
429    * The LanManager hashed password needs to be created using the
430    * password in the network encoding not the host encoding.
431    */
432   if(data)
433     Curl_convert_to_network(data, (char *)pw, 14);
434 #else
435   (void)data;
436 #endif
437
438   {
439     /* Create LanManager hashed password. */
440
441 #ifdef USE_SSLEAY
442     DES_key_schedule ks;
443
444     setup_des_key(pw, DESKEY(ks));
445     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
446                     DESKEY(ks), DES_ENCRYPT);
447
448     setup_des_key(pw+7, DESKEY(ks));
449     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
450                     DESKEY(ks), DES_ENCRYPT);
451 #elif USE_GNUTLS
452     gcry_cipher_hd_t des;
453
454     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
455     setup_des_key(pw, &des);
456     gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
457     gcry_cipher_close(des);
458
459     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
460     setup_des_key(pw+7, &des);
461     gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8);
462     gcry_cipher_close(des);
463 #endif
464
465     memset(lmbuffer + 16, 0, 21 - 16);
466   }
467   }
468
469 #if USE_NTRESPONSES
470 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
471                                size_t srclen)
472 {
473   size_t i;
474   for (i=0; i<srclen; i++) {
475     dest[2*i]   = (unsigned char)src[i];
476     dest[2*i+1] =   '\0';
477   }
478 }
479
480 /*
481  * Set up nt hashed passwords
482  */
483 static CURLcode mk_nt_hash(struct SessionHandle *data,
484                            const char *password,
485                            unsigned char *ntbuffer /* 21 bytes */)
486 {
487   size_t len = strlen(password);
488   unsigned char *pw = malloc(len*2);
489   if(!pw)
490     return CURLE_OUT_OF_MEMORY;
491
492   ascii_to_unicode_le(pw, password, len);
493
494 #ifdef CURL_DOES_CONVERSIONS
495   /*
496    * The NT hashed password needs to be created using the
497    * password in the network encoding not the host encoding.
498    */
499   if(data)
500     Curl_convert_to_network(data, (char *)pw, len*2);
501 #else
502   (void)data;
503 #endif
504
505   {
506     /* Create NT hashed password. */
507 #ifdef USE_SSLEAY
508     MD4_CTX MD4pw;
509     MD4_Init(&MD4pw);
510     MD4_Update(&MD4pw, pw, 2*len);
511     MD4_Final(ntbuffer, &MD4pw);
512 #elif USE_GNUTLS
513     gcry_md_hd_t MD4pw;
514     gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
515     gcry_md_write(MD4pw, pw, 2*len);
516     memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
517     gcry_md_close(MD4pw);
518 #endif
519
520     memset(ntbuffer + 16, 0, 21 - 16);
521   }
522
523   free(pw);
524   return CURLE_OK;
525 }
526 #endif
527
528
529 #endif
530
531 #ifdef USE_WINDOWS_SSPI
532
533 static void
534 ntlm_sspi_cleanup(struct ntlmdata *ntlm)
535 {
536   if(ntlm->type_2) {
537     free(ntlm->type_2);
538     ntlm->type_2 = NULL;
539   }
540   if(ntlm->has_handles) {
541     s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
542     s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
543     ntlm->has_handles = 0;
544   }
545   if(ntlm->p_identity) {
546     if(ntlm->identity.User) free(ntlm->identity.User);
547     if(ntlm->identity.Password) free(ntlm->identity.Password);
548     if(ntlm->identity.Domain) free(ntlm->identity.Domain);
549     ntlm->p_identity = NULL;
550   }
551 }
552
553 #endif
554
555 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
556 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
557   (((x) >>16)&0xff), (((x)>>24) & 0xff)
558
559 #define HOSTNAME_MAX 1024
560
561 /* this is for creating ntlm header output */
562 CURLcode Curl_output_ntlm(struct connectdata *conn,
563                           bool proxy)
564 {
565   const char *domain=""; /* empty */
566   char host [HOSTNAME_MAX+ 1] = ""; /* empty */
567 #ifndef USE_WINDOWS_SSPI
568   size_t domlen = strlen(domain);
569   size_t hostlen = strlen(host);
570   size_t hostoff; /* host name offset */
571   size_t domoff;  /* domain name offset */
572 #endif
573   size_t size;
574   char *base64=NULL;
575   unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
576                                   long */
577
578   /* point to the address of the pointer that holds the string to sent to the
579      server, which is for a plain host or for a HTTP proxy */
580   char **allocuserpwd;
581
582   /* point to the name and password for this */
583   const char *userp;
584   const char *passwdp;
585   /* point to the correct struct with this */
586   struct ntlmdata *ntlm;
587   struct auth *authp;
588
589   DEBUGASSERT(conn);
590   DEBUGASSERT(conn->data);
591
592   if(proxy) {
593     allocuserpwd = &conn->allocptr.proxyuserpwd;
594     userp = conn->proxyuser;
595     passwdp = conn->proxypasswd;
596     ntlm = &conn->proxyntlm;
597     authp = &conn->data->state.authproxy;
598   }
599   else {
600     allocuserpwd = &conn->allocptr.userpwd;
601     userp = conn->user;
602     passwdp = conn->passwd;
603     ntlm = &conn->ntlm;
604     authp = &conn->data->state.authhost;
605   }
606   authp->done = FALSE;
607
608   /* not set means empty */
609   if(!userp)
610     userp="";
611
612   if(!passwdp)
613     passwdp="";
614
615 #ifdef USE_WINDOWS_SSPI
616   if (s_hSecDll == NULL) {
617     /* not thread safe and leaks - use curl_global_init() to avoid */
618     CURLcode err = Curl_sspi_global_init();
619     if (s_hSecDll == NULL)
620       return err;
621   }
622 #endif
623
624   switch(ntlm->state) {
625   case NTLMSTATE_TYPE1:
626   default: /* for the weird cases we (re)start here */
627 #ifdef USE_WINDOWS_SSPI
628   {
629     SecBuffer buf;
630     SecBufferDesc desc;
631     SECURITY_STATUS status;
632     ULONG attrs;
633     const char *user;
634     int domlen;
635     TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
636
637     ntlm_sspi_cleanup(ntlm);
638
639     user = strchr(userp, '\\');
640     if(!user)
641       user = strchr(userp, '/');
642
643     if(user) {
644       domain = userp;
645       domlen = user - userp;
646       user++;
647     }
648     else {
649       user = userp;
650       domain = "";
651       domlen = 0;
652     }
653
654     if(user && *user) {
655       /* note: initialize all of this before doing the mallocs so that
656        * it can be cleaned up later without leaking memory.
657        */
658       ntlm->p_identity = &ntlm->identity;
659       memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
660       if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
661         return CURLE_OUT_OF_MEMORY;
662       ntlm->identity.UserLength = strlen(user);
663       if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
664         return CURLE_OUT_OF_MEMORY;
665       ntlm->identity.PasswordLength = strlen(passwdp);
666       if((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
667         return CURLE_OUT_OF_MEMORY;
668       strncpy((char *)ntlm->identity.Domain, domain, domlen);
669       ntlm->identity.Domain[domlen] = '\0';
670       ntlm->identity.DomainLength = domlen;
671       ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
672     }
673     else {
674       ntlm->p_identity = NULL;
675     }
676
677     if(s_pSecFn->AcquireCredentialsHandleA(
678           NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
679           NULL, NULL, &ntlm->handle, &tsDummy
680           ) != SEC_E_OK) {
681       return CURLE_OUT_OF_MEMORY;
682     }
683
684     desc.ulVersion = SECBUFFER_VERSION;
685     desc.cBuffers  = 1;
686     desc.pBuffers  = &buf;
687     buf.cbBuffer   = sizeof(ntlmbuf);
688     buf.BufferType = SECBUFFER_TOKEN;
689     buf.pvBuffer   = ntlmbuf;
690
691     status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
692                                                  (char *) host,
693                                                  ISC_REQ_CONFIDENTIALITY |
694                                                  ISC_REQ_REPLAY_DETECT |
695                                                  ISC_REQ_CONNECTION,
696                                                  0, SECURITY_NETWORK_DREP,
697                                                  NULL, 0,
698                                                  &ntlm->c_handle, &desc,
699                                                  &attrs, &tsDummy);
700
701     if(status == SEC_I_COMPLETE_AND_CONTINUE ||
702         status == SEC_I_CONTINUE_NEEDED) {
703       s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
704     }
705     else if(status != SEC_E_OK) {
706       s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
707       return CURLE_RECV_ERROR;
708     }
709
710     ntlm->has_handles = 1;
711     size = buf.cbBuffer;
712   }
713 #else
714     hostoff = 0;
715     domoff = hostoff + hostlen; /* This is 0: remember that host and domain
716                                    are empty */
717
718     /* Create and send a type-1 message:
719
720     Index Description          Content
721     0     NTLMSSP Signature    Null-terminated ASCII "NTLMSSP"
722                                (0x4e544c4d53535000)
723     8     NTLM Message Type    long (0x01000000)
724     12    Flags                long
725     16    Supplied Domain      security buffer(*)
726     24    Supplied Workstation security buffer(*)
727     32    start of data block
728
729     */
730 #if USE_NTLM2SESSION
731 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
732 #else
733 #define NTLM2FLAG 0
734 #endif
735     snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
736              "\x01%c%c%c" /* 32-bit type = 1 */
737              "%c%c%c%c"   /* 32-bit NTLM flag field */
738              "%c%c"  /* domain length */
739              "%c%c"  /* domain allocated space */
740              "%c%c"  /* domain name offset */
741              "%c%c"  /* 2 zeroes */
742              "%c%c"  /* host length */
743              "%c%c"  /* host allocated space */
744              "%c%c"  /* host name offset */
745              "%c%c"  /* 2 zeroes */
746              "%s"   /* host name */
747              "%s",  /* domain string */
748              0,     /* trailing zero */
749              0,0,0, /* part of type-1 long */
750
751              LONGQUARTET(
752                NTLMFLAG_NEGOTIATE_OEM|
753                NTLMFLAG_REQUEST_TARGET|
754                NTLMFLAG_NEGOTIATE_NTLM_KEY|
755                NTLM2FLAG|
756                NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
757                ),
758              SHORTPAIR(domlen),
759              SHORTPAIR(domlen),
760              SHORTPAIR(domoff),
761              0,0,
762              SHORTPAIR(hostlen),
763              SHORTPAIR(hostlen),
764              SHORTPAIR(hostoff),
765              0,0,
766              host /* this is empty */, domain /* this is empty */);
767
768     /* initial packet length */
769     size = 32 + hostlen + domlen;
770 #endif
771
772     DEBUG_OUT({
773       fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
774               LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
775                           NTLMFLAG_REQUEST_TARGET|
776                           NTLMFLAG_NEGOTIATE_NTLM_KEY|
777                           NTLM2FLAG|
778                           NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
779               NTLMFLAG_NEGOTIATE_OEM|
780               NTLMFLAG_REQUEST_TARGET|
781               NTLMFLAG_NEGOTIATE_NTLM_KEY|
782               NTLM2FLAG|
783               NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
784       print_flags(stderr,
785                   NTLMFLAG_NEGOTIATE_OEM|
786                   NTLMFLAG_REQUEST_TARGET|
787                   NTLMFLAG_NEGOTIATE_NTLM_KEY|
788                   NTLM2FLAG|
789                   NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
790       fprintf(stderr, "\n****\n");
791     });
792
793     /* now size is the size of the base64 encoded package size */
794     size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
795
796     if(size >0 ) {
797       Curl_safefree(*allocuserpwd);
798       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
799                               proxy?"Proxy-":"",
800                               base64);
801       DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
802       free(base64);
803     }
804     else
805       return CURLE_OUT_OF_MEMORY; /* FIX TODO */
806
807     break;
808
809   case NTLMSTATE_TYPE2:
810     /* We received the type-2 message already, create a type-3 message:
811
812     Index   Description            Content
813     0       NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
814                                    (0x4e544c4d53535000)
815     8       NTLM Message Type      long (0x03000000)
816     12      LM/LMv2 Response       security buffer(*)
817     20      NTLM/NTLMv2 Response   security buffer(*)
818     28      Domain Name            security buffer(*)
819     36      User Name              security buffer(*)
820     44      Workstation Name       security buffer(*)
821     (52)    Session Key (optional) security buffer(*)
822     (60)    Flags (optional)       long
823     52 (64) start of data block
824
825     */
826
827   {
828 #ifdef USE_WINDOWS_SSPI
829     SecBuffer type_2, type_3;
830     SecBufferDesc type_2_desc, type_3_desc;
831     SECURITY_STATUS status;
832     ULONG attrs;
833     TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
834
835     type_2_desc.ulVersion  = type_3_desc.ulVersion  = SECBUFFER_VERSION;
836     type_2_desc.cBuffers   = type_3_desc.cBuffers   = 1;
837     type_2_desc.pBuffers   = &type_2;
838     type_3_desc.pBuffers   = &type_3;
839
840     type_2.BufferType = SECBUFFER_TOKEN;
841     type_2.pvBuffer   = ntlm->type_2;
842     type_2.cbBuffer   = ntlm->n_type_2;
843     type_3.BufferType = SECBUFFER_TOKEN;
844     type_3.pvBuffer   = ntlmbuf;
845     type_3.cbBuffer   = sizeof(ntlmbuf);
846
847     status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle,
848                                        (char *) host,
849                                        ISC_REQ_CONFIDENTIALITY |
850                                        ISC_REQ_REPLAY_DETECT |
851                                        ISC_REQ_CONNECTION,
852                                        0, SECURITY_NETWORK_DREP, &type_2_desc,
853                                        0, &ntlm->c_handle, &type_3_desc,
854                                        &attrs, &tsDummy);
855
856     if(status != SEC_E_OK)
857       return CURLE_RECV_ERROR;
858
859     size = type_3.cbBuffer;
860
861     ntlm_sspi_cleanup(ntlm);
862
863 #else
864     int lmrespoff;
865     unsigned char lmresp[24]; /* fixed-size */
866 #if USE_NTRESPONSES
867     int ntrespoff;
868     unsigned char ntresp[24]; /* fixed-size */
869 #endif
870     size_t useroff;
871     const char *user;
872     size_t userlen;
873
874     user = strchr(userp, '\\');
875     if(!user)
876       user = strchr(userp, '/');
877
878     if(user) {
879       domain = userp;
880       domlen = (user - domain);
881       user++;
882     }
883     else
884       user = userp;
885     userlen = strlen(user);
886
887     if(gethostname(host, HOSTNAME_MAX)) {
888       infof(conn->data, "gethostname() failed, continuing without!");
889       hostlen = 0;
890     }
891     else {
892       /* If the workstation if configured with a full DNS name (i.e.
893        * workstation.somewhere.net) gethostname() returns the fully qualified
894        * name, which NTLM doesn't like.
895        */
896       char *dot = strchr(host, '.');
897       if(dot)
898         *dot = '\0';
899       hostlen = strlen(host);
900     }
901
902 #if USE_NTLM2SESSION
903     /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
904     if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
905       unsigned char ntbuffer[0x18];
906       unsigned char tmp[0x18];
907       unsigned char md5sum[MD5_DIGEST_LENGTH];
908       unsigned char entropy[8];
909
910       /* Need to create 8 bytes random data */
911 #ifdef USE_SSLEAY
912       MD5_CTX MD5pw;
913       Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
914       RAND_bytes(entropy,8);
915 #elif USE_GNUTLS
916       gcry_md_hd_t MD5pw;
917       Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
918       gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
919 #endif
920
921       /* 8 bytes random data as challenge in lmresp */
922       memcpy(lmresp,entropy,8);
923       /* Pad with zeros */
924       memset(lmresp+8,0,0x10);
925
926       /* Fill tmp with challenge(nonce?) + entropy */
927       memcpy(tmp,&ntlm->nonce[0],8);
928       memcpy(tmp+8,entropy,8);
929
930 #ifdef USE_SSLEAY
931       MD5_Init(&MD5pw);
932       MD5_Update(&MD5pw, tmp, 16);
933       MD5_Final(md5sum, &MD5pw);
934 #elif USE_GNUTLS
935       gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
936       gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
937       memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
938       gcry_md_close(MD5pw);
939 #endif
940
941       /* We shall only use the first 8 bytes of md5sum,
942          but the des code in lm_resp only encrypt the first 8 bytes */
943       if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
944         return CURLE_OUT_OF_MEMORY;
945       lm_resp(ntbuffer, md5sum, ntresp);
946
947       /* End of NTLM2 Session code */
948     }
949     else {
950 #endif
951
952 #if USE_NTRESPONSES
953       unsigned char ntbuffer[0x18];
954 #endif
955       unsigned char lmbuffer[0x18];
956
957 #if USE_NTRESPONSES
958       if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
959         return CURLE_OUT_OF_MEMORY;
960       lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
961 #endif
962
963       mk_lm_hash(conn->data, passwdp, lmbuffer);
964       lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
965       /* A safer but less compatible alternative is:
966        *   lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
967        * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
968 #if USE_NTLM2SESSION
969     }
970 #endif
971
972     lmrespoff = 64; /* size of the message header */
973 #if USE_NTRESPONSES
974     ntrespoff = lmrespoff + 0x18;
975     domoff = ntrespoff + 0x18;
976 #else
977     domoff = lmrespoff + 0x18;
978 #endif
979     useroff = domoff + domlen;
980     hostoff = useroff + userlen;
981
982     /*
983      * In the case the server sets the flag NTLMFLAG_NEGOTIATE_UNICODE, we
984      * need to filter it off because libcurl doesn't UNICODE encode the
985      * strings it packs into the NTLM authenticate packet.
986      */
987     ntlm->flags &= ~NTLMFLAG_NEGOTIATE_UNICODE;
988
989     /* Create the big type-3 message binary blob */
990     size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
991                     NTLMSSP_SIGNATURE "%c"
992                     "\x03%c%c%c" /* type-3, 32 bits */
993
994                     "%c%c" /* LanManager length */
995                     "%c%c" /* LanManager allocated space */
996                     "%c%c" /* LanManager offset */
997                     "%c%c" /* 2 zeroes */
998
999                     "%c%c" /* NT-response length */
1000                     "%c%c" /* NT-response allocated space */
1001                     "%c%c" /* NT-response offset */
1002                     "%c%c" /* 2 zeroes */
1003
1004                     "%c%c"  /* domain length */
1005                     "%c%c"  /* domain allocated space */
1006                     "%c%c"  /* domain name offset */
1007                     "%c%c"  /* 2 zeroes */
1008
1009                     "%c%c"  /* user length */
1010                     "%c%c"  /* user allocated space */
1011                     "%c%c"  /* user offset */
1012                     "%c%c"  /* 2 zeroes */
1013
1014                     "%c%c"  /* host length */
1015                     "%c%c"  /* host allocated space */
1016                     "%c%c"  /* host offset */
1017                     "%c%c"  /* 2 zeroes */
1018
1019                     "%c%c"  /* session key length (unknown purpose) */
1020                     "%c%c"  /* session key allocated space (unknown purpose) */
1021                     "%c%c"  /* session key offset (unknown purpose) */
1022                     "%c%c"  /* 2 zeroes */
1023
1024                     "%c%c%c%c" /* flags */
1025
1026                     /* domain string */
1027                     /* user string */
1028                     /* host string */
1029                     /* LanManager response */
1030                     /* NT response */
1031                     ,
1032                     0, /* zero termination */
1033                     0,0,0, /* type-3 long, the 24 upper bits */
1034
1035                     SHORTPAIR(0x18),  /* LanManager response length, twice */
1036                     SHORTPAIR(0x18),
1037                     SHORTPAIR(lmrespoff),
1038                     0x0, 0x0,
1039
1040 #if USE_NTRESPONSES
1041                     SHORTPAIR(0x18),  /* NT-response length, twice */
1042                     SHORTPAIR(0x18),
1043                     SHORTPAIR(ntrespoff),
1044                     0x0, 0x0,
1045 #else
1046                     0x0, 0x0,
1047                     0x0, 0x0,
1048                     0x0, 0x0,
1049                     0x0, 0x0,
1050 #endif
1051                     SHORTPAIR(domlen),
1052                     SHORTPAIR(domlen),
1053                     SHORTPAIR(domoff),
1054                     0x0, 0x0,
1055
1056                     SHORTPAIR(userlen),
1057                     SHORTPAIR(userlen),
1058                     SHORTPAIR(useroff),
1059                     0x0, 0x0,
1060
1061                     SHORTPAIR(hostlen),
1062                     SHORTPAIR(hostlen),
1063                     SHORTPAIR(hostoff),
1064                     0x0, 0x0,
1065
1066                     0x0, 0x0,
1067                     0x0, 0x0,
1068                     0x0, 0x0,
1069                     0x0, 0x0,
1070
1071                     LONGQUARTET(ntlm->flags));
1072     DEBUGASSERT(size==64);
1073
1074     DEBUGASSERT(size == (size_t)lmrespoff);
1075     /* We append the binary hashes */
1076     if(size < (sizeof(ntlmbuf) - 0x18)) {
1077       memcpy(&ntlmbuf[size], lmresp, 0x18);
1078       size += 0x18;
1079     }
1080
1081     DEBUG_OUT({
1082         fprintf(stderr, "**** TYPE3 header lmresp=");
1083         print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
1084     });
1085
1086 #if USE_NTRESPONSES
1087     if(size < (sizeof(ntlmbuf) - 0x18)) {
1088       DEBUGASSERT(size == (size_t)ntrespoff);
1089       memcpy(&ntlmbuf[size], ntresp, 0x18);
1090       size += 0x18;
1091     }
1092
1093     DEBUG_OUT({
1094         fprintf(stderr, "\n                  ntresp=");
1095         print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
1096     });
1097
1098 #endif
1099
1100     DEBUG_OUT({
1101         fprintf(stderr, "\n                  flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
1102                 LONGQUARTET(ntlm->flags), ntlm->flags);
1103         print_flags(stderr, ntlm->flags);
1104         fprintf(stderr, "\n****\n");
1105     });
1106
1107
1108     /* Make sure that the domain, user and host strings fit in the target
1109        buffer before we copy them there. */
1110     if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
1111       failf(conn->data, "user + domain + host name too big");
1112       return CURLE_OUT_OF_MEMORY;
1113     }
1114
1115     DEBUGASSERT(size == domoff);
1116     memcpy(&ntlmbuf[size], domain, domlen);
1117     size += domlen;
1118
1119     DEBUGASSERT(size == useroff);
1120     memcpy(&ntlmbuf[size], user, userlen);
1121     size += userlen;
1122
1123     DEBUGASSERT(size == hostoff);
1124     memcpy(&ntlmbuf[size], host, hostlen);
1125     size += hostlen;
1126
1127 #ifdef CURL_DOES_CONVERSIONS
1128     /* convert domain, user, and host to ASCII but leave the rest as-is */
1129     if(CURLE_OK != Curl_convert_to_network(conn->data,
1130                                            (char *)&ntlmbuf[domoff],
1131                                            size-domoff)) {
1132       return CURLE_CONV_FAILED;
1133     }
1134 #endif /* CURL_DOES_CONVERSIONS */
1135
1136 #endif
1137
1138     /* convert the binary blob into base64 */
1139     size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
1140
1141     if(size >0 ) {
1142       Curl_safefree(*allocuserpwd);
1143       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
1144                               proxy?"Proxy-":"",
1145                               base64);
1146       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
1147       free(base64);
1148     }
1149     else
1150       return CURLE_OUT_OF_MEMORY; /* FIX TODO */
1151
1152     ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
1153     authp->done = TRUE;
1154   }
1155   break;
1156
1157   case NTLMSTATE_TYPE3:
1158     /* connection is already authenticated,
1159      * don't send a header in future requests */
1160     if(*allocuserpwd) {
1161       free(*allocuserpwd);
1162       *allocuserpwd=NULL;
1163     }
1164     authp->done = TRUE;
1165     break;
1166   }
1167
1168   return CURLE_OK;
1169 }
1170
1171
1172 void
1173 Curl_ntlm_cleanup(struct connectdata *conn)
1174 {
1175 #ifdef USE_WINDOWS_SSPI
1176   ntlm_sspi_cleanup(&conn->ntlm);
1177   ntlm_sspi_cleanup(&conn->proxyntlm);
1178 #else
1179   (void)conn;
1180 #endif
1181 }
1182
1183
1184 #endif /* USE_NTLM */
1185 #endif /* !CURL_DISABLE_HTTP */