1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
22 ***************************************************************************/
27 http://davenport.sourceforge.net/ntlm.html
28 http://www.innovation.ch/java/ntlm.html
30 Another implementation:
31 http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
35 #ifndef CURL_DISABLE_HTTP
40 /* -- WIN32 approved -- */
51 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
56 #include "easyif.h" /* for Curl_convert_... prototypes */
59 #include "curl_base64.h"
60 #include "http_ntlm.h"
64 #define _MPRINTF_REPLACE /* use our functions only */
65 #include <curl/mprintf.h>
67 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
68 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
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>
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
93 /* This is how things were done in the old days */
95 #define DESKEYARG(x) x
98 #define DESKEYARG(x) *x
102 #elif defined(USE_GNUTLS)
107 #define MD5_DIGEST_LENGTH 16
108 #define MD4_DIGEST_LENGTH 16
110 #elif defined(USE_WINDOWS_SSPI)
112 #include "curl_sspi.h"
115 # error "Can't compile NTLM support without a crypto library."
118 /* The last #include file should be: */
119 #include "memdebug.h"
121 /* Define this to make the type-3 message include the NT response message */
122 #define USE_NTRESPONSES 1
124 /* Define this to make the type-3 message include the NTLM2Session response
125 message, requires USE_NTRESPONSES. */
126 #define USE_NTLM2SESSION 1
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
134 return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
135 ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
140 # define DEBUG_OUT(x) x
141 static void print_flags(FILE *handle, unsigned long flags)
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 ");
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 ");
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 ");
192 fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
194 fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
196 fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
198 fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
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 ");
209 static void print_hex(FILE *handle, const char *buf, size_t len)
212 fprintf(stderr, "0x");
214 fprintf(stderr, "%02.2x", (unsigned int)*p++);
217 # define DEBUG_OUT(x)
221 (*) = A "security buffer" is a triplet consisting of two shorts and one
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.
231 CURLntlm Curl_input_ntlm(struct connectdata *conn,
232 bool proxy, /* if proxy or not */
233 const char *header) /* rest of the www-authenticate:
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 };
242 ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
244 /* skip initial whitespaces */
245 while(*header && ISSPACE(*header))
248 if(checkprefix("NTLM", header)) {
249 header += strlen("NTLM");
251 while(*header && ISSPACE(*header))
255 /* We got a type-2 message here:
257 Index Description Content
258 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
260 8 NTLM Message Type long (0x02000000)
261 12 Target Name security buffer(*)
264 (32) Context (optional) 8 bytes (two consecutive longs)
265 (40) Target Information (optional) security buffer(*)
266 32 (48) start of data block
269 unsigned char *buffer;
270 size = Curl_base64_decode(header, &buffer);
274 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
276 #ifdef USE_WINDOWS_SSPI
277 ntlm->type_2 = malloc(size+1);
278 if(ntlm->type_2 == NULL) {
280 return CURLE_OUT_OF_MEMORY;
282 ntlm->n_type_2 = size;
283 memcpy(ntlm->type_2, buffer, size);
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 */
295 ntlm->flags = readint_le(&buffer[20]);
296 memcpy(ntlm->nonce, &buffer[24], 8);
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);
311 if(ntlm->state >= NTLMSTATE_TYPE1)
314 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
317 return CURLNTLM_FINE;
320 #ifndef USE_WINDOWS_SSPI
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.
327 static void setup_des_key(const unsigned char *key_56,
328 DES_key_schedule DESKEYARG(ks))
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);
341 DES_set_odd_parity(&key);
342 DES_set_key(&key, ks);
344 #elif defined(USE_GNUTLS)
347 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
349 static void setup_des_key(const unsigned char *key_56,
350 gcry_cipher_hd_t *des)
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);
363 gcry_cipher_setkey(*des, key, 8);
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.
372 static void lm_resp(const unsigned char *keys,
373 const unsigned char *plaintext,
374 unsigned char *results)
379 setup_des_key(keys, DESKEY(ks));
380 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
381 DESKEY(ks), DES_ENCRYPT);
383 setup_des_key(keys+7, DESKEY(ks));
384 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
385 DESKEY(ks), DES_ENCRYPT);
387 setup_des_key(keys+14, DESKEY(ks));
388 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
389 DESKEY(ks), DES_ENCRYPT);
391 gcry_cipher_hd_t des;
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);
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);
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);
412 * Set up lanmanager hashed password
414 static void mk_lm_hash(struct SessionHandle *data,
415 const char *password,
416 unsigned char *lmbuffer /* 21 bytes */)
418 unsigned char pw[14];
419 static const unsigned char magic[] = {
420 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
422 size_t len = CURLMIN(strlen(password), 14);
424 Curl_strntoupper((char *)pw, password, len);
425 memset(&pw[len], 0, 14-len);
427 #ifdef CURL_DOES_CONVERSIONS
429 * The LanManager hashed password needs to be created using the
430 * password in the network encoding not the host encoding.
433 Curl_convert_to_network(data, (char *)pw, 14);
439 /* Create LanManager hashed password. */
444 setup_des_key(pw, DESKEY(ks));
445 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
446 DESKEY(ks), DES_ENCRYPT);
448 setup_des_key(pw+7, DESKEY(ks));
449 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
450 DESKEY(ks), DES_ENCRYPT);
452 gcry_cipher_hd_t des;
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);
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);
465 memset(lmbuffer + 16, 0, 21 - 16);
470 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
474 for (i=0; i<srclen; i++) {
475 dest[2*i] = (unsigned char)src[i];
481 * Set up nt hashed passwords
483 static CURLcode mk_nt_hash(struct SessionHandle *data,
484 const char *password,
485 unsigned char *ntbuffer /* 21 bytes */)
487 size_t len = strlen(password);
488 unsigned char *pw = malloc(len*2);
490 return CURLE_OUT_OF_MEMORY;
492 ascii_to_unicode_le(pw, password, len);
494 #ifdef CURL_DOES_CONVERSIONS
496 * The NT hashed password needs to be created using the
497 * password in the network encoding not the host encoding.
500 Curl_convert_to_network(data, (char *)pw, len*2);
506 /* Create NT hashed password. */
510 MD4_Update(&MD4pw, pw, 2*len);
511 MD4_Final(ntbuffer, &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);
520 memset(ntbuffer + 16, 0, 21 - 16);
531 #ifdef USE_WINDOWS_SSPI
534 ntlm_sspi_cleanup(struct ntlmdata *ntlm)
540 if(ntlm->has_handles) {
541 s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
542 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
543 ntlm->has_handles = 0;
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;
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)
559 #define HOSTNAME_MAX 1024
561 /* this is for creating ntlm header output */
562 CURLcode Curl_output_ntlm(struct connectdata *conn,
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 */
575 unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
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 */
582 /* point to the name and password for this */
585 /* point to the correct struct with this */
586 struct ntlmdata *ntlm;
590 DEBUGASSERT(conn->data);
593 allocuserpwd = &conn->allocptr.proxyuserpwd;
594 userp = conn->proxyuser;
595 passwdp = conn->proxypasswd;
596 ntlm = &conn->proxyntlm;
597 authp = &conn->data->state.authproxy;
600 allocuserpwd = &conn->allocptr.userpwd;
602 passwdp = conn->passwd;
604 authp = &conn->data->state.authhost;
608 /* not set means empty */
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)
624 switch(ntlm->state) {
625 case NTLMSTATE_TYPE1:
626 default: /* for the weird cases we (re)start here */
627 #ifdef USE_WINDOWS_SSPI
631 SECURITY_STATUS status;
635 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
637 ntlm_sspi_cleanup(ntlm);
639 user = strchr(userp, '\\');
641 user = strchr(userp, '/');
645 domlen = user - userp;
655 /* note: initialize all of this before doing the mallocs so that
656 * it can be cleaned up later without leaking memory.
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;
674 ntlm->p_identity = NULL;
677 if(s_pSecFn->AcquireCredentialsHandleA(
678 NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
679 NULL, NULL, &ntlm->handle, &tsDummy
681 return CURLE_OUT_OF_MEMORY;
684 desc.ulVersion = SECBUFFER_VERSION;
686 desc.pBuffers = &buf;
687 buf.cbBuffer = sizeof(ntlmbuf);
688 buf.BufferType = SECBUFFER_TOKEN;
689 buf.pvBuffer = ntlmbuf;
691 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
693 ISC_REQ_CONFIDENTIALITY |
694 ISC_REQ_REPLAY_DETECT |
696 0, SECURITY_NETWORK_DREP,
698 &ntlm->c_handle, &desc,
701 if(status == SEC_I_COMPLETE_AND_CONTINUE ||
702 status == SEC_I_CONTINUE_NEEDED) {
703 s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
705 else if(status != SEC_E_OK) {
706 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
707 return CURLE_RECV_ERROR;
710 ntlm->has_handles = 1;
715 domoff = hostoff + hostlen; /* This is 0: remember that host and domain
718 /* Create and send a type-1 message:
720 Index Description Content
721 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
723 8 NTLM Message Type long (0x01000000)
725 16 Supplied Domain security buffer(*)
726 24 Supplied Workstation security buffer(*)
727 32 start of data block
731 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
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 */
747 "%s", /* domain string */
748 0, /* trailing zero */
749 0,0,0, /* part of type-1 long */
752 NTLMFLAG_NEGOTIATE_OEM|
753 NTLMFLAG_REQUEST_TARGET|
754 NTLMFLAG_NEGOTIATE_NTLM_KEY|
756 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
766 host /* this is empty */, domain /* this is empty */);
768 /* initial packet length */
769 size = 32 + hostlen + domlen;
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|
778 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
779 NTLMFLAG_NEGOTIATE_OEM|
780 NTLMFLAG_REQUEST_TARGET|
781 NTLMFLAG_NEGOTIATE_NTLM_KEY|
783 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
785 NTLMFLAG_NEGOTIATE_OEM|
786 NTLMFLAG_REQUEST_TARGET|
787 NTLMFLAG_NEGOTIATE_NTLM_KEY|
789 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
790 fprintf(stderr, "\n****\n");
793 /* now size is the size of the base64 encoded package size */
794 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
797 Curl_safefree(*allocuserpwd);
798 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
801 DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
805 return CURLE_OUT_OF_MEMORY; /* FIX TODO */
809 case NTLMSTATE_TYPE2:
810 /* We received the type-2 message already, create a type-3 message:
812 Index Description Content
813 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
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
828 #ifdef USE_WINDOWS_SSPI
829 SecBuffer type_2, type_3;
830 SecBufferDesc type_2_desc, type_3_desc;
831 SECURITY_STATUS status;
833 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
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;
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);
847 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle,
849 ISC_REQ_CONFIDENTIALITY |
850 ISC_REQ_REPLAY_DETECT |
852 0, SECURITY_NETWORK_DREP, &type_2_desc,
853 0, &ntlm->c_handle, &type_3_desc,
856 if(status != SEC_E_OK)
857 return CURLE_RECV_ERROR;
859 size = type_3.cbBuffer;
861 ntlm_sspi_cleanup(ntlm);
865 unsigned char lmresp[24]; /* fixed-size */
868 unsigned char ntresp[24]; /* fixed-size */
874 user = strchr(userp, '\\');
876 user = strchr(userp, '/');
880 domlen = (user - domain);
885 userlen = strlen(user);
887 if(gethostname(host, HOSTNAME_MAX)) {
888 infof(conn->data, "gethostname() failed, continuing without!");
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.
896 char *dot = strchr(host, '.');
899 hostlen = strlen(host);
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];
910 /* Need to create 8 bytes random data */
913 Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
914 RAND_bytes(entropy,8);
917 Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
918 gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
921 /* 8 bytes random data as challenge in lmresp */
922 memcpy(lmresp,entropy,8);
924 memset(lmresp+8,0,0x10);
926 /* Fill tmp with challenge(nonce?) + entropy */
927 memcpy(tmp,&ntlm->nonce[0],8);
928 memcpy(tmp+8,entropy,8);
932 MD5_Update(&MD5pw, tmp, 16);
933 MD5_Final(md5sum, &MD5pw);
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);
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);
947 /* End of NTLM2 Session code */
953 unsigned char ntbuffer[0x18];
955 unsigned char lmbuffer[0x18];
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);
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 */
972 lmrespoff = 64; /* size of the message header */
974 ntrespoff = lmrespoff + 0x18;
975 domoff = ntrespoff + 0x18;
977 domoff = lmrespoff + 0x18;
979 useroff = domoff + domlen;
980 hostoff = useroff + userlen;
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.
987 ntlm->flags &= ~NTLMFLAG_NEGOTIATE_UNICODE;
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 */
994 "%c%c" /* LanManager length */
995 "%c%c" /* LanManager allocated space */
996 "%c%c" /* LanManager offset */
997 "%c%c" /* 2 zeroes */
999 "%c%c" /* NT-response length */
1000 "%c%c" /* NT-response allocated space */
1001 "%c%c" /* NT-response offset */
1002 "%c%c" /* 2 zeroes */
1004 "%c%c" /* domain length */
1005 "%c%c" /* domain allocated space */
1006 "%c%c" /* domain name offset */
1007 "%c%c" /* 2 zeroes */
1009 "%c%c" /* user length */
1010 "%c%c" /* user allocated space */
1011 "%c%c" /* user offset */
1012 "%c%c" /* 2 zeroes */
1014 "%c%c" /* host length */
1015 "%c%c" /* host allocated space */
1016 "%c%c" /* host offset */
1017 "%c%c" /* 2 zeroes */
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 */
1024 "%c%c%c%c" /* flags */
1029 /* LanManager response */
1032 0, /* zero termination */
1033 0,0,0, /* type-3 long, the 24 upper bits */
1035 SHORTPAIR(0x18), /* LanManager response length, twice */
1037 SHORTPAIR(lmrespoff),
1041 SHORTPAIR(0x18), /* NT-response length, twice */
1043 SHORTPAIR(ntrespoff),
1071 LONGQUARTET(ntlm->flags));
1072 DEBUGASSERT(size==64);
1074 DEBUGASSERT(size == (size_t)lmrespoff);
1075 /* We append the binary hashes */
1076 if(size < (sizeof(ntlmbuf) - 0x18)) {
1077 memcpy(&ntlmbuf[size], lmresp, 0x18);
1082 fprintf(stderr, "**** TYPE3 header lmresp=");
1083 print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
1087 if(size < (sizeof(ntlmbuf) - 0x18)) {
1088 DEBUGASSERT(size == (size_t)ntrespoff);
1089 memcpy(&ntlmbuf[size], ntresp, 0x18);
1094 fprintf(stderr, "\n ntresp=");
1095 print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
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");
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;
1115 DEBUGASSERT(size == domoff);
1116 memcpy(&ntlmbuf[size], domain, domlen);
1119 DEBUGASSERT(size == useroff);
1120 memcpy(&ntlmbuf[size], user, userlen);
1123 DEBUGASSERT(size == hostoff);
1124 memcpy(&ntlmbuf[size], host, hostlen);
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],
1132 return CURLE_CONV_FAILED;
1134 #endif /* CURL_DOES_CONVERSIONS */
1138 /* convert the binary blob into base64 */
1139 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
1142 Curl_safefree(*allocuserpwd);
1143 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
1146 DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
1150 return CURLE_OUT_OF_MEMORY; /* FIX TODO */
1152 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
1157 case NTLMSTATE_TYPE3:
1158 /* connection is already authenticated,
1159 * don't send a header in future requests */
1161 free(*allocuserpwd);
1173 Curl_ntlm_cleanup(struct connectdata *conn)
1175 #ifdef USE_WINDOWS_SSPI
1176 ntlm_sspi_cleanup(&conn->ntlm);
1177 ntlm_sspi_cleanup(&conn->proxyntlm);
1184 #endif /* USE_NTLM */
1185 #endif /* !CURL_DISABLE_HTTP */