00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "setup.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef CURL_DISABLE_HTTP
00036 #ifdef USE_NTLM
00037
00038 #define DEBUG_ME 0
00039
00040
00041 #include <stdio.h>
00042 #include <string.h>
00043 #include <stdarg.h>
00044 #include <stdlib.h>
00045 #include <ctype.h>
00046
00047 #ifdef HAVE_UNISTD_H
00048 #include <unistd.h>
00049 #endif
00050
00051 #include "urldata.h"
00052 #include "easyif.h"
00053 #include "sendf.h"
00054 #include "strequal.h"
00055 #include "base64.h"
00056 #include "http_ntlm.h"
00057 #include "url.h"
00058 #include "memory.h"
00059 #include "ssluse.h"
00060
00061 #define _MPRINTF_REPLACE
00062 #include <curl/mprintf.h>
00063
00064
00065 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
00066
00067 #ifndef USE_WINDOWS_SSPI
00068
00069 #include <openssl/des.h>
00070 #include <openssl/md4.h>
00071 #include <openssl/md5.h>
00072 #include <openssl/ssl.h>
00073 #include <openssl/rand.h>
00074
00075 #if OPENSSL_VERSION_NUMBER < 0x00907001L
00076 #define DES_key_schedule des_key_schedule
00077 #define DES_cblock des_cblock
00078 #define DES_set_odd_parity des_set_odd_parity
00079 #define DES_set_key des_set_key
00080 #define DES_ecb_encrypt des_ecb_encrypt
00081
00082
00083 #define DESKEY(x) x
00084 #define DESKEYARG(x) x
00085 #else
00086
00087 #define DESKEYARG(x) *x
00088 #define DESKEY(x) &x
00089 #endif
00090
00091 #else
00092
00093 #include <rpc.h>
00094
00095
00096 static HMODULE s_hSecDll = NULL;
00097
00098 static PSecurityFunctionTable s_pSecFn = NULL;
00099
00100 #endif
00101
00102
00103 #include "memdebug.h"
00104
00105
00106 #define USE_NTRESPONSES 1
00107
00108
00109
00110 #define USE_NTLM2SESSION 1
00111
00112 #ifndef USE_WINDOWS_SSPI
00113
00114
00115 static unsigned int readint_le(unsigned char *buf)
00116
00117 {
00118 return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
00119 ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
00120 }
00121 #endif
00122
00123 #if DEBUG_ME
00124 # define DEBUG_OUT(x) x
00125 static void print_flags(FILE *handle, unsigned long flags)
00126 {
00127 if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
00128 fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
00129 if(flags & NTLMFLAG_NEGOTIATE_OEM)
00130 fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
00131 if(flags & NTLMFLAG_REQUEST_TARGET)
00132 fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
00133 if(flags & (1<<3))
00134 fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
00135 if(flags & NTLMFLAG_NEGOTIATE_SIGN)
00136 fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
00137 if(flags & NTLMFLAG_NEGOTIATE_SEAL)
00138 fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
00139 if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
00140 fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
00141 if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
00142 fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
00143 if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
00144 fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
00145 if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
00146 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
00147 if(flags & (1<<10))
00148 fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
00149 if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
00150 fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
00151 if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
00152 fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
00153 if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
00154 fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
00155 if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
00156 fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
00157 if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
00158 fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
00159 if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
00160 fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
00161 if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
00162 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
00163 if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
00164 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
00165 if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
00166 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
00167 if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
00168 fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
00169 if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
00170 fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
00171 if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
00172 fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
00173 if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
00174 fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
00175 if(flags & (1<<24))
00176 fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
00177 if(flags & (1<<25))
00178 fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
00179 if(flags & (1<<26))
00180 fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
00181 if(flags & (1<<27))
00182 fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
00183 if(flags & (1<<28))
00184 fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
00185 if(flags & NTLMFLAG_NEGOTIATE_128)
00186 fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
00187 if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
00188 fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
00189 if(flags & NTLMFLAG_NEGOTIATE_56)
00190 fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
00191 }
00192
00193 static void print_hex(FILE *handle, const char *buf, size_t len)
00194 {
00195 const char *p = buf;
00196 fprintf(stderr, "0x");
00197 while (len-- > 0)
00198 fprintf(stderr, "%02.2x", (unsigned int)*p++);
00199 }
00200 #else
00201 # define DEBUG_OUT(x)
00202 #endif
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 CURLntlm Curl_input_ntlm(struct connectdata *conn,
00216 bool proxy,
00217 char *header)
00218
00219 {
00220
00221 struct ntlmdata *ntlm;
00222 #ifndef USE_WINDOWS_SSPI
00223 static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
00224 #endif
00225
00226 ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
00227
00228
00229 while(*header && ISSPACE(*header))
00230 header++;
00231
00232 if(checkprefix("NTLM", header)) {
00233 header += strlen("NTLM");
00234
00235 while(*header && ISSPACE(*header))
00236 header++;
00237
00238 if(*header) {
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 size_t size;
00253 unsigned char *buffer;
00254 size = Curl_base64_decode(header, &buffer);
00255 if(!buffer)
00256 return CURLNTLM_BAD;
00257
00258 ntlm->state = NTLMSTATE_TYPE2;
00259
00260 #ifdef USE_WINDOWS_SSPI
00261 ntlm->type_2 = malloc(size+1);
00262 if (ntlm->type_2 == NULL) {
00263 free(buffer);
00264 return CURLE_OUT_OF_MEMORY;
00265 }
00266 ntlm->n_type_2 = size;
00267 memcpy(ntlm->type_2, buffer, size);
00268 #else
00269 ntlm->flags = 0;
00270
00271 if((size < 32) ||
00272 (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
00273 (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
00274
00275 free(buffer);
00276 return CURLNTLM_BAD;
00277 }
00278
00279 ntlm->flags = readint_le(&buffer[20]);
00280 memcpy(ntlm->nonce, &buffer[24], 8);
00281
00282 DEBUG_OUT({
00283 fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
00284 print_flags(stderr, ntlm->flags);
00285 fprintf(stderr, "\n nonce=");
00286 print_hex(stderr, (char *)ntlm->nonce, 8);
00287 fprintf(stderr, "\n****\n");
00288 fprintf(stderr, "**** Header %s\n ", header);
00289 });
00290
00291 free(buffer);
00292 #endif
00293 }
00294 else {
00295 if(ntlm->state >= NTLMSTATE_TYPE1)
00296 return CURLNTLM_BAD;
00297
00298 ntlm->state = NTLMSTATE_TYPE1;
00299 }
00300 }
00301 return CURLNTLM_FINE;
00302 }
00303
00304 #ifndef USE_WINDOWS_SSPI
00305
00306
00307
00308
00309
00310 static void setup_des_key(unsigned char *key_56,
00311 DES_key_schedule DESKEYARG(ks))
00312 {
00313 DES_cblock key;
00314
00315 key[0] = key_56[0];
00316 key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
00317 key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
00318 key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
00319 key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
00320 key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
00321 key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
00322 key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
00323
00324 DES_set_odd_parity(&key);
00325 DES_set_key(&key, ks);
00326 }
00327
00328
00329
00330
00331
00332
00333 static void lm_resp(unsigned char *keys,
00334 unsigned char *plaintext,
00335 unsigned char *results)
00336 {
00337 DES_key_schedule ks;
00338
00339 setup_des_key(keys, DESKEY(ks));
00340 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
00341 DESKEY(ks), DES_ENCRYPT);
00342
00343 setup_des_key(keys+7, DESKEY(ks));
00344 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
00345 DESKEY(ks), DES_ENCRYPT);
00346
00347 setup_des_key(keys+14, DESKEY(ks));
00348 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
00349 DESKEY(ks), DES_ENCRYPT);
00350 }
00351
00352
00353
00354
00355
00356 static void mk_lm_hash(struct SessionHandle *data,
00357 char *password,
00358 unsigned char *lmbuffer )
00359 {
00360 unsigned char pw[14];
00361 static const unsigned char magic[] = {
00362 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
00363 };
00364 unsigned int i;
00365 size_t len = strlen(password);
00366
00367 if (len > 14)
00368 len = 14;
00369
00370 for (i=0; i<len; i++)
00371 pw[i] = (unsigned char)toupper(password[i]);
00372
00373 for (; i<14; i++)
00374 pw[i] = 0;
00375
00376 #ifdef CURL_DOES_CONVERSIONS
00377
00378
00379
00380
00381 if(data)
00382 Curl_convert_to_network(data, (char *)pw, 14);
00383 #else
00384 (void)data;
00385 #endif
00386
00387 {
00388
00389
00390 DES_key_schedule ks;
00391
00392 setup_des_key(pw, DESKEY(ks));
00393 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
00394 DESKEY(ks), DES_ENCRYPT);
00395
00396 setup_des_key(pw+7, DESKEY(ks));
00397 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
00398 DESKEY(ks), DES_ENCRYPT);
00399
00400 memset(lmbuffer + 16, 0, 21 - 16);
00401 }
00402 }
00403
00404 #if USE_NTRESPONSES
00405 static void utf8_to_unicode_le(unsigned char *dest, const char *src,
00406 size_t srclen)
00407 {
00408 size_t i;
00409 for (i=0; i<srclen; i++) {
00410 dest[2*i] = (unsigned char)src[i];
00411 dest[2*i+1] = '\0';
00412 }
00413 }
00414
00415
00416
00417
00418 static CURLcode mk_nt_hash(struct SessionHandle *data,
00419 char *password,
00420 unsigned char *ntbuffer )
00421 {
00422 size_t len = strlen(password);
00423 unsigned char *pw = malloc(len*2);
00424 if (!pw)
00425 return CURLE_OUT_OF_MEMORY;
00426
00427 utf8_to_unicode_le(pw, password, len);
00428
00429 #ifdef CURL_DOES_CONVERSIONS
00430
00431
00432
00433
00434 if(data)
00435 Curl_convert_to_network(data, (char *)pw, len*2);
00436 #else
00437 (void)data;
00438 #endif
00439
00440 {
00441
00442 MD4_CTX MD4;
00443
00444 MD4_Init(&MD4);
00445 MD4_Update(&MD4, pw, 2*len);
00446 MD4_Final(ntbuffer, &MD4);
00447
00448 memset(ntbuffer + 16, 0, 21 - 16);
00449 }
00450
00451 free(pw);
00452 return CURLE_OK;
00453 }
00454 #endif
00455
00456
00457 #endif
00458
00459 #ifdef USE_WINDOWS_SSPI
00460
00461 static void
00462 ntlm_sspi_cleanup(struct ntlmdata *ntlm)
00463 {
00464 if (ntlm->type_2) {
00465 free(ntlm->type_2);
00466 ntlm->type_2 = NULL;
00467 }
00468 if (ntlm->has_handles) {
00469 s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
00470 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
00471 ntlm->has_handles = 0;
00472 }
00473 if (ntlm->p_identity) {
00474 if (ntlm->identity.User) free(ntlm->identity.User);
00475 if (ntlm->identity.Password) free(ntlm->identity.Password);
00476 if (ntlm->identity.Domain) free(ntlm->identity.Domain);
00477 ntlm->p_identity = NULL;
00478 }
00479 }
00480
00481 #endif
00482
00483 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
00484 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
00485 (((x) >>16)&0xff), (((x)>>24) & 0xff)
00486
00487 #define HOSTNAME_MAX 1024
00488
00489
00490 CURLcode Curl_output_ntlm(struct connectdata *conn,
00491 bool proxy)
00492 {
00493 const char *domain="";
00494 char host [HOSTNAME_MAX+ 1] = "";
00495 #ifndef USE_WINDOWS_SSPI
00496 size_t domlen = strlen(domain);
00497 size_t hostlen = strlen(host);
00498 size_t hostoff;
00499 size_t domoff;
00500 #endif
00501 size_t size;
00502 char *base64=NULL;
00503 unsigned char ntlmbuf[1024];
00504
00505
00506
00507
00508 char **allocuserpwd;
00509
00510
00511 char *userp;
00512 char *passwdp;
00513
00514 struct ntlmdata *ntlm;
00515 struct auth *authp;
00516
00517 DEBUGASSERT(conn);
00518 DEBUGASSERT(conn->data);
00519
00520 if(proxy) {
00521 allocuserpwd = &conn->allocptr.proxyuserpwd;
00522 userp = conn->proxyuser;
00523 passwdp = conn->proxypasswd;
00524 ntlm = &conn->proxyntlm;
00525 authp = &conn->data->state.authproxy;
00526 }
00527 else {
00528 allocuserpwd = &conn->allocptr.userpwd;
00529 userp = conn->user;
00530 passwdp = conn->passwd;
00531 ntlm = &conn->ntlm;
00532 authp = &conn->data->state.authhost;
00533 }
00534 authp->done = FALSE;
00535
00536
00537 if(!userp)
00538 userp=(char *)"";
00539
00540 if(!passwdp)
00541 passwdp=(char *)"";
00542
00543 #ifdef USE_WINDOWS_SSPI
00544
00545 if (s_hSecDll == NULL) {
00546
00547
00548
00549
00550
00551 OSVERSIONINFO osver;
00552 osver.dwOSVersionInfoSize = sizeof(osver);
00553 GetVersionEx(&osver);
00554 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT
00555 && osver.dwMajorVersion == 4)
00556 s_hSecDll = LoadLibrary("security.dll");
00557 else
00558 s_hSecDll = LoadLibrary("secur32.dll");
00559 if (s_hSecDll != NULL) {
00560 INIT_SECURITY_INTERFACE pInitSecurityInterface;
00561 pInitSecurityInterface =
00562 (INIT_SECURITY_INTERFACE)GetProcAddress(s_hSecDll,
00563 "InitSecurityInterfaceA");
00564 if (pInitSecurityInterface != NULL)
00565 s_pSecFn = pInitSecurityInterface();
00566 }
00567 }
00568 if (s_pSecFn == NULL)
00569 return CURLE_RECV_ERROR;
00570 #endif
00571
00572 switch(ntlm->state) {
00573 case NTLMSTATE_TYPE1:
00574 default:
00575 #ifdef USE_WINDOWS_SSPI
00576 {
00577 SecBuffer buf;
00578 SecBufferDesc desc;
00579 SECURITY_STATUS status;
00580 ULONG attrs;
00581 const char *user;
00582 int domlen;
00583 TimeStamp tsDummy;
00584
00585 ntlm_sspi_cleanup(ntlm);
00586
00587 user = strchr(userp, '\\');
00588 if (!user)
00589 user = strchr(userp, '/');
00590
00591 if (user) {
00592 domain = userp;
00593 domlen = user - userp;
00594 user++;
00595 }
00596 else {
00597 user = userp;
00598 domain = "";
00599 domlen = 0;
00600 }
00601
00602 if (user && *user) {
00603
00604
00605
00606 ntlm->p_identity = &ntlm->identity;
00607 memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
00608 if ((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
00609 return CURLE_OUT_OF_MEMORY;
00610 ntlm->identity.UserLength = strlen(user);
00611 if ((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
00612 return CURLE_OUT_OF_MEMORY;
00613 ntlm->identity.PasswordLength = strlen(passwdp);
00614 if ((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
00615 return CURLE_OUT_OF_MEMORY;
00616 strncpy((char *)ntlm->identity.Domain, domain, domlen);
00617 ntlm->identity.Domain[domlen] = '\0';
00618 ntlm->identity.DomainLength = domlen;
00619 ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
00620 }
00621 else {
00622 ntlm->p_identity = NULL;
00623 }
00624
00625 if (s_pSecFn->AcquireCredentialsHandle(
00626 NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
00627 NULL, NULL, &ntlm->handle, &tsDummy
00628 ) != SEC_E_OK) {
00629 return CURLE_OUT_OF_MEMORY;
00630 }
00631
00632 desc.ulVersion = SECBUFFER_VERSION;
00633 desc.cBuffers = 1;
00634 desc.pBuffers = &buf;
00635 buf.cbBuffer = sizeof(ntlmbuf);
00636 buf.BufferType = SECBUFFER_TOKEN;
00637 buf.pvBuffer = ntlmbuf;
00638
00639 status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
00640 (char *) host,
00641 ISC_REQ_CONFIDENTIALITY |
00642 ISC_REQ_REPLAY_DETECT |
00643 ISC_REQ_CONNECTION,
00644 0, SECURITY_NETWORK_DREP,
00645 NULL, 0,
00646 &ntlm->c_handle, &desc,
00647 &attrs, &tsDummy);
00648
00649 if (status == SEC_I_COMPLETE_AND_CONTINUE ||
00650 status == SEC_I_CONTINUE_NEEDED) {
00651 s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
00652 }
00653 else if (status != SEC_E_OK) {
00654 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
00655 return CURLE_RECV_ERROR;
00656 }
00657
00658 ntlm->has_handles = 1;
00659 size = buf.cbBuffer;
00660 }
00661 #else
00662 hostoff = 0;
00663 domoff = hostoff + hostlen;
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 #if USE_NTLM2SESSION
00679 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
00680 #else
00681 #define NTLM2FLAG 0
00682 #endif
00683 snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
00684 "\x01%c%c%c"
00685 "%c%c%c%c"
00686 "%c%c"
00687 "%c%c"
00688 "%c%c"
00689 "%c%c"
00690 "%c%c"
00691 "%c%c"
00692 "%c%c"
00693 "%c%c"
00694 "%s"
00695 "%s",
00696 0,
00697 0,0,0,
00698
00699 LONGQUARTET(
00700 NTLMFLAG_NEGOTIATE_OEM|
00701 NTLMFLAG_REQUEST_TARGET|
00702 NTLMFLAG_NEGOTIATE_NTLM_KEY|
00703 NTLM2FLAG|
00704 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
00705 ),
00706 SHORTPAIR(domlen),
00707 SHORTPAIR(domlen),
00708 SHORTPAIR(domoff),
00709 0,0,
00710 SHORTPAIR(hostlen),
00711 SHORTPAIR(hostlen),
00712 SHORTPAIR(hostoff),
00713 0,0,
00714 host , domain );
00715
00716
00717 size = 32 + hostlen + domlen;
00718 #endif
00719
00720 DEBUG_OUT({
00721 fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
00722 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
00723 NTLMFLAG_REQUEST_TARGET|
00724 NTLMFLAG_NEGOTIATE_NTLM_KEY|
00725 NTLM2FLAG|
00726 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
00727 NTLMFLAG_NEGOTIATE_OEM|
00728 NTLMFLAG_REQUEST_TARGET|
00729 NTLMFLAG_NEGOTIATE_NTLM_KEY|
00730 NTLM2FLAG|
00731 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
00732 print_flags(stderr,
00733 NTLMFLAG_NEGOTIATE_OEM|
00734 NTLMFLAG_REQUEST_TARGET|
00735 NTLMFLAG_NEGOTIATE_NTLM_KEY|
00736 NTLM2FLAG|
00737 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
00738 fprintf(stderr, "\n****\n");
00739 });
00740
00741
00742 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
00743
00744 if(size >0 ) {
00745 Curl_safefree(*allocuserpwd);
00746 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
00747 proxy?"Proxy-":"",
00748 base64);
00749 DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
00750 free(base64);
00751 }
00752 else
00753 return CURLE_OUT_OF_MEMORY;
00754
00755 break;
00756
00757 case NTLMSTATE_TYPE2:
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 {
00776 #ifdef USE_WINDOWS_SSPI
00777 SecBuffer type_2, type_3;
00778 SecBufferDesc type_2_desc, type_3_desc;
00779 SECURITY_STATUS status;
00780 ULONG attrs;
00781 TimeStamp tsDummy;
00782
00783 type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
00784 type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
00785 type_2_desc.pBuffers = &type_2;
00786 type_3_desc.pBuffers = &type_3;
00787
00788 type_2.BufferType = SECBUFFER_TOKEN;
00789 type_2.pvBuffer = ntlm->type_2;
00790 type_2.cbBuffer = ntlm->n_type_2;
00791 type_3.BufferType = SECBUFFER_TOKEN;
00792 type_3.pvBuffer = ntlmbuf;
00793 type_3.cbBuffer = sizeof(ntlmbuf);
00794
00795 status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, &ntlm->c_handle,
00796 (char *) host,
00797 ISC_REQ_CONFIDENTIALITY |
00798 ISC_REQ_REPLAY_DETECT |
00799 ISC_REQ_CONNECTION,
00800 0, SECURITY_NETWORK_DREP, &type_2_desc,
00801 0, &ntlm->c_handle, &type_3_desc,
00802 &attrs, &tsDummy);
00803
00804 if (status != SEC_E_OK)
00805 return CURLE_RECV_ERROR;
00806
00807 size = type_3.cbBuffer;
00808
00809 ntlm_sspi_cleanup(ntlm);
00810
00811 #else
00812 int lmrespoff;
00813 unsigned char lmresp[24];
00814 #if USE_NTRESPONSES
00815 int ntrespoff;
00816 unsigned char ntresp[24];
00817 #endif
00818 size_t useroff;
00819 const char *user;
00820 size_t userlen;
00821
00822 user = strchr(userp, '\\');
00823 if(!user)
00824 user = strchr(userp, '/');
00825
00826 if (user) {
00827 domain = userp;
00828 domlen = (user - domain);
00829 user++;
00830 }
00831 else
00832 user = userp;
00833 userlen = strlen(user);
00834
00835 if (gethostname(host, HOSTNAME_MAX)) {
00836 infof(conn->data, "gethostname() failed, continuing without!");
00837 hostlen = 0;
00838 }
00839 else {
00840
00841
00842
00843
00844 char *dot = strchr(host, '.');
00845 if (dot)
00846 *dot = '\0';
00847 hostlen = strlen(host);
00848 }
00849
00850 #if USE_NTLM2SESSION
00851
00852 if (ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
00853 unsigned char ntbuffer[0x18];
00854 unsigned char tmp[0x18];
00855 unsigned char md5sum[MD5_DIGEST_LENGTH];
00856 MD5_CTX MD5;
00857 unsigned char random[8];
00858
00859
00860 Curl_ossl_seed(conn->data);
00861 RAND_bytes(random,8);
00862
00863
00864 memcpy(lmresp,random,8);
00865
00866 memset(lmresp+8,0,0x10);
00867
00868
00869 memcpy(tmp,&ntlm->nonce[0],8);
00870 memcpy(tmp+8,random,8);
00871
00872 MD5_Init(&MD5);
00873 MD5_Update(&MD5, tmp, 16);
00874 MD5_Final(md5sum, &MD5);
00875
00876
00877 if (mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
00878 return CURLE_OUT_OF_MEMORY;
00879 lm_resp(ntbuffer, md5sum, ntresp);
00880
00881
00882 }
00883 else {
00884 #endif
00885
00886 #if USE_NTRESPONSES
00887 unsigned char ntbuffer[0x18];
00888 #endif
00889 unsigned char lmbuffer[0x18];
00890
00891 #if USE_NTRESPONSES
00892 if (mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
00893 return CURLE_OUT_OF_MEMORY;
00894 lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
00895 #endif
00896
00897 mk_lm_hash(conn->data, passwdp, lmbuffer);
00898 lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
00899
00900
00901
00902 #if USE_NTLM2SESSION
00903 }
00904 #endif
00905
00906 lmrespoff = 64;
00907 #if USE_NTRESPONSES
00908 ntrespoff = lmrespoff + 0x18;
00909 domoff = ntrespoff + 0x18;
00910 #else
00911 domoff = lmrespoff + 0x18;
00912 #endif
00913 useroff = domoff + domlen;
00914 hostoff = useroff + userlen;
00915
00916
00917 size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
00918 NTLMSSP_SIGNATURE "%c"
00919 "\x03%c%c%c"
00920
00921 "%c%c"
00922 "%c%c"
00923 "%c%c"
00924 "%c%c"
00925
00926 "%c%c"
00927 "%c%c"
00928 "%c%c"
00929 "%c%c"
00930
00931 "%c%c"
00932 "%c%c"
00933 "%c%c"
00934 "%c%c"
00935
00936 "%c%c"
00937 "%c%c"
00938 "%c%c"
00939 "%c%c"
00940
00941 "%c%c"
00942 "%c%c"
00943 "%c%c"
00944 "%c%c"
00945
00946 "%c%c"
00947 "%c%c"
00948 "%c%c"
00949 "%c%c"
00950
00951 "%c%c%c%c"
00952
00953
00954
00955
00956
00957
00958 ,
00959 0,
00960 0,0,0,
00961
00962 SHORTPAIR(0x18),
00963 SHORTPAIR(0x18),
00964 SHORTPAIR(lmrespoff),
00965 0x0, 0x0,
00966
00967 #if USE_NTRESPONSES
00968 SHORTPAIR(0x18),
00969 SHORTPAIR(0x18),
00970 SHORTPAIR(ntrespoff),
00971 0x0, 0x0,
00972 #else
00973 0x0, 0x0,
00974 0x0, 0x0,
00975 0x0, 0x0,
00976 0x0, 0x0,
00977 #endif
00978 SHORTPAIR(domlen),
00979 SHORTPAIR(domlen),
00980 SHORTPAIR(domoff),
00981 0x0, 0x0,
00982
00983 SHORTPAIR(userlen),
00984 SHORTPAIR(userlen),
00985 SHORTPAIR(useroff),
00986 0x0, 0x0,
00987
00988 SHORTPAIR(hostlen),
00989 SHORTPAIR(hostlen),
00990 SHORTPAIR(hostoff),
00991 0x0, 0x0,
00992
00993 0x0, 0x0,
00994 0x0, 0x0,
00995 0x0, 0x0,
00996 0x0, 0x0,
00997
00998 LONGQUARTET(ntlm->flags));
00999 DEBUGASSERT(size==64);
01000
01001 DEBUGASSERT(size == (size_t)lmrespoff);
01002
01003 if(size < (sizeof(ntlmbuf) - 0x18)) {
01004 memcpy(&ntlmbuf[size], lmresp, 0x18);
01005 size += 0x18;
01006 }
01007
01008 DEBUG_OUT({
01009 fprintf(stderr, "**** TYPE3 header lmresp=");
01010 print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
01011 });
01012
01013 #if USE_NTRESPONSES
01014 if(size < (sizeof(ntlmbuf) - 0x18)) {
01015 DEBUGASSERT(size == (size_t)ntrespoff);
01016 memcpy(&ntlmbuf[size], ntresp, 0x18);
01017 size += 0x18;
01018 }
01019
01020 DEBUG_OUT({
01021 fprintf(stderr, "\n ntresp=");
01022 print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
01023 });
01024
01025 #endif
01026
01027 DEBUG_OUT({
01028 fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
01029 LONGQUARTET(ntlm->flags), ntlm->flags);
01030 print_flags(stderr, ntlm->flags);
01031 fprintf(stderr, "\n****\n");
01032 });
01033
01034
01035
01036
01037 if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
01038 failf(conn->data, "user + domain + host name too big");
01039 return CURLE_OUT_OF_MEMORY;
01040 }
01041
01042 DEBUGASSERT(size == domoff);
01043 memcpy(&ntlmbuf[size], domain, domlen);
01044 size += domlen;
01045
01046 DEBUGASSERT(size == useroff);
01047 memcpy(&ntlmbuf[size], user, userlen);
01048 size += userlen;
01049
01050 DEBUGASSERT(size == hostoff);
01051 memcpy(&ntlmbuf[size], host, hostlen);
01052 size += hostlen;
01053
01054 #ifdef CURL_DOES_CONVERSIONS
01055
01056 if(CURLE_OK != Curl_convert_to_network(conn->data,
01057 (char *)&ntlmbuf[domoff],
01058 size-domoff)) {
01059 return CURLE_CONV_FAILED;
01060 }
01061 #endif
01062
01063 #endif
01064
01065
01066 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
01067
01068 if(size >0 ) {
01069 Curl_safefree(*allocuserpwd);
01070 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
01071 proxy?"Proxy-":"",
01072 base64);
01073 DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
01074 free(base64);
01075 }
01076 else
01077 return CURLE_OUT_OF_MEMORY;
01078
01079 ntlm->state = NTLMSTATE_TYPE3;
01080 authp->done = TRUE;
01081 }
01082 break;
01083
01084 case NTLMSTATE_TYPE3:
01085
01086
01087 if(*allocuserpwd) {
01088 free(*allocuserpwd);
01089 *allocuserpwd=NULL;
01090 }
01091 authp->done = TRUE;
01092 break;
01093 }
01094
01095 return CURLE_OK;
01096 }
01097
01098
01099 void
01100 Curl_ntlm_cleanup(struct connectdata *conn)
01101 {
01102 #ifdef USE_WINDOWS_SSPI
01103 ntlm_sspi_cleanup(&conn->ntlm);
01104 ntlm_sspi_cleanup(&conn->proxyntlm);
01105 if (s_hSecDll != NULL) {
01106 FreeLibrary(s_hSecDll);
01107 s_hSecDll = NULL;
01108 s_pSecFn = NULL;
01109 }
01110 #else
01111 (void)conn;
01112 #endif
01113 }
01114
01115 #endif
01116 #endif