1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2012 - 2016, Marc Hoersken, <info (at) marc-hoersken.de> 9 * Copyright (C) 2012, Mark Salisbury, <mark.salisbury (at) hp.com> 10 * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel (at) haxx.se>, et al. 11 * 12 * This software is licensed as described in the file COPYING, which 13 * you should have received as part of this distribution. The terms 14 * are also available at https://curl.haxx.se/docs/copyright.html. 15 * 16 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 * copies of the Software, and permit persons to whom the Software is 18 * furnished to do so, under the terms of the COPYING file. 19 * 20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 * KIND, either express or implied. 22 * 23 ***************************************************************************/ 24 25 /* 26 * Source file for all Schannel-specific code for the TLS/SSL layer. No code 27 * but vtls.c should ever call or use these functions. 28 */ 29 30 /* 31 * Based upon the PolarSSL implementation in polarssl.c and polarssl.h: 32 * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan (at) gmail.com> 33 * 34 * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: 35 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel (at) haxx.se>, et al. 36 * 37 * Thanks for code and inspiration! 38 */ 39 40 #include "curl_setup.h" 41 42 #ifdef USE_SCHANNEL 43 44 #define EXPOSE_SCHANNEL_INTERNAL_STRUCTS 45 46 #ifndef USE_WINDOWS_SSPI 47 # error "Can't compile SCHANNEL support without SSPI." 48 #endif 49 50 #include "schannel.h" 51 #include "vtls.h" 52 #include "sendf.h" 53 #include "connect.h" /* for the connect timeout */ 54 #include "strerror.h" 55 #include "select.h" /* for the socket readyness */ 56 #include "inet_pton.h" /* for IP addr SNI check */ 57 #include "curl_multibyte.h" 58 #include "warnless.h" 59 #include "x509asn1.h" 60 #include "curl_printf.h" 61 #include "system_win32.h" 62 63 /* The last #include file should be: */ 64 #include "curl_memory.h" 65 #include "memdebug.h" 66 67 /* ALPN requires version 8.1 of the Windows SDK, which was 68 shipped with Visual Studio 2013, aka _MSC_VER 1800: 69 70 https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx 71 */ 72 #if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_) 73 # define HAS_ALPN 1 74 #endif 75 76 #ifndef UNISP_NAME_A 77 #define UNISP_NAME_A "Microsoft Unified Security Protocol Provider" 78 #endif 79 80 #ifndef UNISP_NAME_W 81 #define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider" 82 #endif 83 84 #ifndef UNISP_NAME 85 #ifdef UNICODE 86 #define UNISP_NAME UNISP_NAME_W 87 #else 88 #define UNISP_NAME UNISP_NAME_A 89 #endif 90 #endif 91 92 #if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) 93 #define HAS_CLIENT_CERT_PATH 94 #endif 95 96 #ifdef HAS_CLIENT_CERT_PATH 97 #ifdef UNICODE 98 #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W 99 #else 100 #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A 101 #endif 102 #endif 103 104 #ifndef SP_PROT_SSL2_CLIENT 105 #define SP_PROT_SSL2_CLIENT 0x00000008 106 #endif 107 108 #ifndef SP_PROT_SSL3_CLIENT 109 #define SP_PROT_SSL3_CLIENT 0x00000008 110 #endif 111 112 #ifndef SP_PROT_TLS1_CLIENT 113 #define SP_PROT_TLS1_CLIENT 0x00000080 114 #endif 115 116 #ifndef SP_PROT_TLS1_0_CLIENT 117 #define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT 118 #endif 119 120 #ifndef SP_PROT_TLS1_1_CLIENT 121 #define SP_PROT_TLS1_1_CLIENT 0x00000200 122 #endif 123 124 #ifndef SP_PROT_TLS1_2_CLIENT 125 #define SP_PROT_TLS1_2_CLIENT 0x00000800 126 #endif 127 128 #ifndef SECBUFFER_ALERT 129 #define SECBUFFER_ALERT 17 130 #endif 131 132 /* Both schannel buffer sizes must be > 0 */ 133 #define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 134 #define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 135 136 #define CERT_THUMBPRINT_STR_LEN 40 137 #define CERT_THUMBPRINT_DATA_LEN 20 138 139 /* Uncomment to force verbose output 140 * #define infof(x, y, ...) printf(y, __VA_ARGS__) 141 * #define failf(x, y, ...) printf(y, __VA_ARGS__) 142 */ 143 144 #ifndef CALG_SHA_256 145 # define CALG_SHA_256 0x0000800c 146 #endif 147 148 #define BACKEND connssl->backend 149 150 static Curl_recv schannel_recv; 151 static Curl_send schannel_send; 152 153 static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, 154 const char *pinnedpubkey); 155 156 static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, 157 void *BufDataPtr, unsigned long BufByteSize) 158 { 159 buffer->cbBuffer = BufByteSize; 160 buffer->BufferType = BufType; 161 buffer->pvBuffer = BufDataPtr; 162 } 163 164 static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, 165 unsigned long NumArrElem) 166 { 167 desc->ulVersion = SECBUFFER_VERSION; 168 desc->pBuffers = BufArr; 169 desc->cBuffers = NumArrElem; 170 } 171 172 static CURLcode 173 set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) 174 { 175 struct Curl_easy *data = conn->data; 176 long ssl_version = SSL_CONN_CONFIG(version); 177 long ssl_version_max = SSL_CONN_CONFIG(version_max); 178 long i = ssl_version; 179 180 switch(ssl_version_max) { 181 case CURL_SSLVERSION_MAX_NONE: 182 case CURL_SSLVERSION_MAX_DEFAULT: 183 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; 184 break; 185 } 186 for(; i <= (ssl_version_max >> 16); ++i) { 187 switch(i) { 188 case CURL_SSLVERSION_TLSv1_0: 189 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; 190 break; 191 case CURL_SSLVERSION_TLSv1_1: 192 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; 193 break; 194 case CURL_SSLVERSION_TLSv1_2: 195 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; 196 break; 197 case CURL_SSLVERSION_TLSv1_3: 198 failf(data, "schannel: TLS 1.3 is not yet supported"); 199 return CURLE_SSL_CONNECT_ERROR; 200 } 201 } 202 return CURLE_OK; 203 } 204 205 /*longest is 26, buffer is slightly bigger*/ 206 #define LONGEST_ALG_ID 32 207 #define CIPHEROPTION(X) \ 208 if(strcmp(#X, tmp) == 0) \ 209 return X 210 211 static int 212 get_alg_id_by_name(char *name) 213 { 214 char tmp[LONGEST_ALG_ID] = { 0 }; 215 char *nameEnd = strchr(name, ':'); 216 size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \ 217 min(strlen(name), LONGEST_ALG_ID - 1); 218 strncpy(tmp, name, n); 219 tmp[n] = 0; 220 CIPHEROPTION(CALG_MD2); 221 CIPHEROPTION(CALG_MD4); 222 CIPHEROPTION(CALG_MD5); 223 CIPHEROPTION(CALG_SHA); 224 CIPHEROPTION(CALG_SHA1); 225 CIPHEROPTION(CALG_MAC); 226 CIPHEROPTION(CALG_RSA_SIGN); 227 CIPHEROPTION(CALG_DSS_SIGN); 228 /*ifdefs for the options that are defined conditionally in wincrypt.h*/ 229 #ifdef CALG_NO_SIGN 230 CIPHEROPTION(CALG_NO_SIGN); 231 #endif 232 CIPHEROPTION(CALG_RSA_KEYX); 233 CIPHEROPTION(CALG_DES); 234 #ifdef CALG_3DES_112 235 CIPHEROPTION(CALG_3DES_112); 236 #endif 237 CIPHEROPTION(CALG_3DES); 238 CIPHEROPTION(CALG_DESX); 239 CIPHEROPTION(CALG_RC2); 240 CIPHEROPTION(CALG_RC4); 241 CIPHEROPTION(CALG_SEAL); 242 #ifdef CALG_DH_SF 243 CIPHEROPTION(CALG_DH_SF); 244 #endif 245 CIPHEROPTION(CALG_DH_EPHEM); 246 #ifdef CALG_AGREEDKEY_ANY 247 CIPHEROPTION(CALG_AGREEDKEY_ANY); 248 #endif 249 #ifdef CALG_HUGHES_MD5 250 CIPHEROPTION(CALG_HUGHES_MD5); 251 #endif 252 CIPHEROPTION(CALG_SKIPJACK); 253 #ifdef CALG_TEK 254 CIPHEROPTION(CALG_TEK); 255 #endif 256 CIPHEROPTION(CALG_CYLINK_MEK); 257 CIPHEROPTION(CALG_SSL3_SHAMD5); 258 #ifdef CALG_SSL3_MASTER 259 CIPHEROPTION(CALG_SSL3_MASTER); 260 #endif 261 #ifdef CALG_SCHANNEL_MASTER_HASH 262 CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH); 263 #endif 264 #ifdef CALG_SCHANNEL_MAC_KEY 265 CIPHEROPTION(CALG_SCHANNEL_MAC_KEY); 266 #endif 267 #ifdef CALG_SCHANNEL_ENC_KEY 268 CIPHEROPTION(CALG_SCHANNEL_ENC_KEY); 269 #endif 270 #ifdef CALG_PCT1_MASTER 271 CIPHEROPTION(CALG_PCT1_MASTER); 272 #endif 273 #ifdef CALG_SSL2_MASTER 274 CIPHEROPTION(CALG_SSL2_MASTER); 275 #endif 276 #ifdef CALG_TLS1_MASTER 277 CIPHEROPTION(CALG_TLS1_MASTER); 278 #endif 279 #ifdef CALG_RC5 280 CIPHEROPTION(CALG_RC5); 281 #endif 282 #ifdef CALG_HMAC 283 CIPHEROPTION(CALG_HMAC); 284 #endif 285 #if !defined(__W32API_MAJOR_VERSION) || \ 286 !defined(__W32API_MINOR_VERSION) || \ 287 defined(__MINGW64_VERSION_MAJOR) || \ 288 (__W32API_MAJOR_VERSION > 5) || \ 289 ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0)) 290 /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0, 291 see https://osdn.net/projects/mingw/ticket/38391 */ 292 CIPHEROPTION(CALG_TLS1PRF); 293 #endif 294 #ifdef CALG_HASH_REPLACE_OWF 295 CIPHEROPTION(CALG_HASH_REPLACE_OWF); 296 #endif 297 #ifdef CALG_AES_128 298 CIPHEROPTION(CALG_AES_128); 299 #endif 300 #ifdef CALG_AES_192 301 CIPHEROPTION(CALG_AES_192); 302 #endif 303 #ifdef CALG_AES_256 304 CIPHEROPTION(CALG_AES_256); 305 #endif 306 #ifdef CALG_AES 307 CIPHEROPTION(CALG_AES); 308 #endif 309 #ifdef CALG_SHA_256 310 CIPHEROPTION(CALG_SHA_256); 311 #endif 312 #ifdef CALG_SHA_384 313 CIPHEROPTION(CALG_SHA_384); 314 #endif 315 #ifdef CALG_SHA_512 316 CIPHEROPTION(CALG_SHA_512); 317 #endif 318 #ifdef CALG_ECDH 319 CIPHEROPTION(CALG_ECDH); 320 #endif 321 #ifdef CALG_ECMQV 322 CIPHEROPTION(CALG_ECMQV); 323 #endif 324 #ifdef CALG_ECDSA 325 CIPHEROPTION(CALG_ECDSA); 326 #endif 327 #ifdef CALG_ECDH_EPHEM 328 CIPHEROPTION(CALG_ECDH_EPHEM); 329 #endif 330 return 0; 331 } 332 333 static CURLcode 334 set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) 335 { 336 char *startCur = ciphers; 337 int algCount = 0; 338 static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ 339 while(startCur && (0 != *startCur) && (algCount < 45)) { 340 long alg = strtol(startCur, 0, 0); 341 if(!alg) 342 alg = get_alg_id_by_name(startCur); 343 if(alg) 344 algIds[algCount++] = alg; 345 else 346 return CURLE_SSL_CIPHER; 347 startCur = strchr(startCur, ':'); 348 if(startCur) 349 startCur++; 350 } 351 schannel_cred->palgSupportedAlgs = algIds; 352 schannel_cred->cSupportedAlgs = algCount; 353 return CURLE_OK; 354 } 355 356 #ifdef HAS_CLIENT_CERT_PATH 357 static CURLcode 358 get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, 359 TCHAR **thumbprint) 360 { 361 TCHAR *sep; 362 TCHAR *store_path_start; 363 size_t store_name_len; 364 365 sep = _tcschr(path, TEXT('\\')); 366 if(sep == NULL) 367 return CURLE_SSL_CERTPROBLEM; 368 369 store_name_len = sep - path; 370 371 if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0) 372 *store_name = CERT_SYSTEM_STORE_CURRENT_USER; 373 else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0) 374 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE; 375 else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0) 376 *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE; 377 else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0) 378 *store_name = CERT_SYSTEM_STORE_SERVICES; 379 else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0) 380 *store_name = CERT_SYSTEM_STORE_USERS; 381 else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"), 382 store_name_len) == 0) 383 *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; 384 else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"), 385 store_name_len) == 0) 386 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; 387 else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"), 388 store_name_len) == 0) 389 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; 390 else 391 return CURLE_SSL_CERTPROBLEM; 392 393 store_path_start = sep + 1; 394 395 sep = _tcschr(store_path_start, TEXT('\\')); 396 if(sep == NULL) 397 return CURLE_SSL_CERTPROBLEM; 398 399 *sep = TEXT('\0'); 400 *store_path = _tcsdup(store_path_start); 401 *sep = TEXT('\\'); 402 if(*store_path == NULL) 403 return CURLE_OUT_OF_MEMORY; 404 405 *thumbprint = sep + 1; 406 if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) 407 return CURLE_SSL_CERTPROBLEM; 408 409 return CURLE_OK; 410 } 411 #endif 412 413 static CURLcode 414 schannel_connect_step1(struct connectdata *conn, int sockindex) 415 { 416 ssize_t written = -1; 417 struct Curl_easy *data = conn->data; 418 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 419 SecBuffer outbuf; 420 SecBufferDesc outbuf_desc; 421 SecBuffer inbuf; 422 SecBufferDesc inbuf_desc; 423 #ifdef HAS_ALPN 424 unsigned char alpn_buffer[128]; 425 #endif 426 SCHANNEL_CRED schannel_cred; 427 PCCERT_CONTEXT client_certs[1] = { NULL }; 428 SECURITY_STATUS sspi_status = SEC_E_OK; 429 struct curl_schannel_cred *old_cred = NULL; 430 struct in_addr addr; 431 #ifdef ENABLE_IPV6 432 struct in6_addr addr6; 433 #endif 434 TCHAR *host_name; 435 CURLcode result; 436 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 437 conn->host.name; 438 439 DEBUGF(infof(data, 440 "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", 441 hostname, conn->remote_port)); 442 443 if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, 444 VERSION_LESS_THAN_EQUAL)) { 445 /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and 446 algorithms that may not be supported by all servers. */ 447 infof(data, "schannel: Windows version is old and may not be able to " 448 "connect to some servers due to lack of SNI, algorithms, etc.\n"); 449 } 450 451 #ifdef HAS_ALPN 452 /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. 453 Also it doesn't seem to be supported for Wine, see curl bug #983. */ 454 BACKEND->use_alpn = conn->bits.tls_enable_alpn && 455 !GetProcAddress(GetModuleHandleA("ntdll"), 456 "wine_get_version") && 457 Curl_verify_windows_version(6, 3, PLATFORM_WINNT, 458 VERSION_GREATER_THAN_EQUAL); 459 #else 460 BACKEND->use_alpn = false; 461 #endif 462 463 #ifdef _WIN32_WCE 464 #ifdef HAS_MANUAL_VERIFY_API 465 /* certificate validation on CE doesn't seem to work right; we'll 466 * do it following a more manual process. */ 467 BACKEND->use_manual_cred_validation = true; 468 #else 469 #error "compiler too old to support requisite manual cert verify for Win CE" 470 #endif 471 #else 472 #ifdef HAS_MANUAL_VERIFY_API 473 if(SSL_CONN_CONFIG(CAfile)) { 474 if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, 475 VERSION_GREATER_THAN_EQUAL)) { 476 BACKEND->use_manual_cred_validation = true; 477 } 478 else { 479 failf(data, "schannel: this version of Windows is too old to support " 480 "certificate verification via CA bundle file."); 481 return CURLE_SSL_CACERT_BADFILE; 482 } 483 } 484 else 485 BACKEND->use_manual_cred_validation = false; 486 #else 487 if(SSL_CONN_CONFIG(CAfile)) { 488 failf(data, "schannel: CA cert support not built in"); 489 return CURLE_NOT_BUILT_IN; 490 } 491 #endif 492 #endif 493 494 BACKEND->cred = NULL; 495 496 /* check for an existing re-usable credential handle */ 497 if(SSL_SET_OPTION(primary.sessionid)) { 498 Curl_ssl_sessionid_lock(conn); 499 if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { 500 BACKEND->cred = old_cred; 501 DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); 502 503 /* increment the reference counter of the credential/session handle */ 504 BACKEND->cred->refcount++; 505 DEBUGF(infof(data, 506 "schannel: incremented credential handle refcount = %d\n", 507 BACKEND->cred->refcount)); 508 } 509 Curl_ssl_sessionid_unlock(conn); 510 } 511 512 if(!BACKEND->cred) { 513 /* setup Schannel API options */ 514 memset(&schannel_cred, 0, sizeof(schannel_cred)); 515 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; 516 517 if(conn->ssl_config.verifypeer) { 518 #ifdef HAS_MANUAL_VERIFY_API 519 if(BACKEND->use_manual_cred_validation) 520 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; 521 else 522 #endif 523 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; 524 525 /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */ 526 if(data->set.ssl.no_revoke) { 527 schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 528 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 529 530 DEBUGF(infof(data, "schannel: disabled server certificate revocation " 531 "checks\n")); 532 } 533 else { 534 schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; 535 DEBUGF(infof(data, 536 "schannel: checking server certificate revocation\n")); 537 } 538 } 539 else { 540 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | 541 SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 542 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 543 DEBUGF(infof(data, 544 "schannel: disabled server cert revocation checks\n")); 545 } 546 547 if(!conn->ssl_config.verifyhost) { 548 schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; 549 DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " 550 "comparing the supplied target name with the subject " 551 "names in server certificates.\n")); 552 } 553 554 switch(conn->ssl_config.version) { 555 case CURL_SSLVERSION_DEFAULT: 556 case CURL_SSLVERSION_TLSv1: 557 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | 558 SP_PROT_TLS1_1_CLIENT | 559 SP_PROT_TLS1_2_CLIENT; 560 break; 561 case CURL_SSLVERSION_TLSv1_0: 562 case CURL_SSLVERSION_TLSv1_1: 563 case CURL_SSLVERSION_TLSv1_2: 564 case CURL_SSLVERSION_TLSv1_3: 565 { 566 result = set_ssl_version_min_max(&schannel_cred, conn); 567 if(result != CURLE_OK) 568 return result; 569 break; 570 } 571 case CURL_SSLVERSION_SSLv3: 572 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; 573 break; 574 case CURL_SSLVERSION_SSLv2: 575 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; 576 break; 577 default: 578 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 579 return CURLE_SSL_CONNECT_ERROR; 580 } 581 582 if(SSL_CONN_CONFIG(cipher_list)) { 583 result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); 584 if(CURLE_OK != result) { 585 failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); 586 return result; 587 } 588 } 589 590 591 #ifdef HAS_CLIENT_CERT_PATH 592 /* client certificate */ 593 if(data->set.ssl.cert) { 594 DWORD cert_store_name; 595 TCHAR *cert_store_path; 596 TCHAR *cert_thumbprint_str; 597 CRYPT_HASH_BLOB cert_thumbprint; 598 BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; 599 HCERTSTORE cert_store; 600 601 TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert); 602 if(!cert_path) 603 return CURLE_OUT_OF_MEMORY; 604 605 result = get_cert_location(cert_path, &cert_store_name, 606 &cert_store_path, &cert_thumbprint_str); 607 if(result != CURLE_OK) { 608 failf(data, "schannel: Failed to get certificate location for %s", 609 cert_path); 610 Curl_unicodefree(cert_path); 611 return result; 612 } 613 614 cert_store = 615 CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, 616 (HCRYPTPROV)NULL, 617 CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, 618 cert_store_path); 619 if(!cert_store) { 620 failf(data, "schannel: Failed to open cert store %x %s, " 621 "last error is %x", 622 cert_store_name, cert_store_path, GetLastError()); 623 free(cert_store_path); 624 Curl_unicodefree(cert_path); 625 return CURLE_SSL_CERTPROBLEM; 626 } 627 free(cert_store_path); 628 629 cert_thumbprint.pbData = cert_thumbprint_data; 630 cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; 631 632 if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN, 633 CRYPT_STRING_HEX, 634 cert_thumbprint_data, &cert_thumbprint.cbData, 635 NULL, NULL)) { 636 Curl_unicodefree(cert_path); 637 return CURLE_SSL_CERTPROBLEM; 638 } 639 640 client_certs[0] = CertFindCertificateInStore( 641 cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 642 CERT_FIND_HASH, &cert_thumbprint, NULL); 643 644 Curl_unicodefree(cert_path); 645 646 if(client_certs[0]) { 647 schannel_cred.cCreds = 1; 648 schannel_cred.paCred = client_certs; 649 } 650 else { 651 /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ 652 return CURLE_SSL_CERTPROBLEM; 653 } 654 655 CertCloseStore(cert_store, 0); 656 } 657 #else 658 if(data->set.ssl.cert) { 659 failf(data, "schannel: client cert support not built in"); 660 return CURLE_NOT_BUILT_IN; 661 } 662 #endif 663 664 /* allocate memory for the re-usable credential handle */ 665 BACKEND->cred = (struct curl_schannel_cred *) 666 calloc(1, sizeof(struct curl_schannel_cred)); 667 if(!BACKEND->cred) { 668 failf(data, "schannel: unable to allocate memory"); 669 670 if(client_certs[0]) 671 CertFreeCertificateContext(client_certs[0]); 672 673 return CURLE_OUT_OF_MEMORY; 674 } 675 BACKEND->cred->refcount = 1; 676 677 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx 678 */ 679 sspi_status = 680 s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, 681 SECPKG_CRED_OUTBOUND, NULL, 682 &schannel_cred, NULL, NULL, 683 &BACKEND->cred->cred_handle, 684 &BACKEND->cred->time_stamp); 685 686 if(client_certs[0]) 687 CertFreeCertificateContext(client_certs[0]); 688 689 if(sspi_status != SEC_E_OK) { 690 char buffer[STRERROR_LEN]; 691 failf(data, "schannel: AcquireCredentialsHandle failed: %s", 692 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 693 Curl_safefree(BACKEND->cred); 694 switch(sspi_status) { 695 case SEC_E_INSUFFICIENT_MEMORY: 696 return CURLE_OUT_OF_MEMORY; 697 case SEC_E_NO_CREDENTIALS: 698 case SEC_E_SECPKG_NOT_FOUND: 699 case SEC_E_NOT_OWNER: 700 case SEC_E_UNKNOWN_CREDENTIALS: 701 case SEC_E_INTERNAL_ERROR: 702 default: 703 return CURLE_SSL_CONNECT_ERROR; 704 } 705 } 706 } 707 708 /* Warn if SNI is disabled due to use of an IP address */ 709 if(Curl_inet_pton(AF_INET, hostname, &addr) 710 #ifdef ENABLE_IPV6 711 || Curl_inet_pton(AF_INET6, hostname, &addr6) 712 #endif 713 ) { 714 infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); 715 } 716 717 #ifdef HAS_ALPN 718 if(BACKEND->use_alpn) { 719 int cur = 0; 720 int list_start_index = 0; 721 unsigned int *extension_len = NULL; 722 unsigned short* list_len = NULL; 723 724 /* The first four bytes will be an unsigned int indicating number 725 of bytes of data in the rest of the the buffer. */ 726 extension_len = (unsigned int *)(&alpn_buffer[cur]); 727 cur += sizeof(unsigned int); 728 729 /* The next four bytes are an indicator that this buffer will contain 730 ALPN data, as opposed to NPN, for example. */ 731 *(unsigned int *)&alpn_buffer[cur] = 732 SecApplicationProtocolNegotiationExt_ALPN; 733 cur += sizeof(unsigned int); 734 735 /* The next two bytes will be an unsigned short indicating the number 736 of bytes used to list the preferred protocols. */ 737 list_len = (unsigned short*)(&alpn_buffer[cur]); 738 cur += sizeof(unsigned short); 739 740 list_start_index = cur; 741 742 #ifdef USE_NGHTTP2 743 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { 744 memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); 745 cur += NGHTTP2_PROTO_ALPN_LEN; 746 infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); 747 } 748 #endif 749 750 alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH; 751 memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); 752 cur += ALPN_HTTP_1_1_LENGTH; 753 infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1); 754 755 *list_len = curlx_uitous(cur - list_start_index); 756 *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); 757 758 InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); 759 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 760 } 761 else { 762 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 763 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 764 } 765 #else /* HAS_ALPN */ 766 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 767 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 768 #endif 769 770 /* setup output buffer */ 771 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 772 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 773 774 /* setup request flags */ 775 BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | 776 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | 777 ISC_REQ_STREAM; 778 779 /* allocate memory for the security context handle */ 780 BACKEND->ctxt = (struct curl_schannel_ctxt *) 781 calloc(1, sizeof(struct curl_schannel_ctxt)); 782 if(!BACKEND->ctxt) { 783 failf(data, "schannel: unable to allocate memory"); 784 return CURLE_OUT_OF_MEMORY; 785 } 786 787 host_name = Curl_convert_UTF8_to_tchar(hostname); 788 if(!host_name) 789 return CURLE_OUT_OF_MEMORY; 790 791 /* Schannel InitializeSecurityContext: 792 https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx 793 794 At the moment we don't pass inbuf unless we're using ALPN since we only 795 use it for that, and Wine (for which we currently disable ALPN) is giving 796 us problems with inbuf regardless. https://github.com/curl/curl/issues/983 797 */ 798 sspi_status = s_pSecFn->InitializeSecurityContext( 799 &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0, 800 (BACKEND->use_alpn ? &inbuf_desc : NULL), 801 0, &BACKEND->ctxt->ctxt_handle, 802 &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); 803 804 Curl_unicodefree(host_name); 805 806 if(sspi_status != SEC_I_CONTINUE_NEEDED) { 807 char buffer[STRERROR_LEN]; 808 Curl_safefree(BACKEND->ctxt); 809 switch(sspi_status) { 810 case SEC_E_INSUFFICIENT_MEMORY: 811 failf(data, "schannel: initial InitializeSecurityContext failed: %s", 812 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 813 return CURLE_OUT_OF_MEMORY; 814 case SEC_E_WRONG_PRINCIPAL: 815 failf(data, "schannel: SNI or certificate check failed: %s", 816 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 817 return CURLE_PEER_FAILED_VERIFICATION; 818 /* 819 case SEC_E_INVALID_HANDLE: 820 case SEC_E_INVALID_TOKEN: 821 case SEC_E_LOGON_DENIED: 822 case SEC_E_TARGET_UNKNOWN: 823 case SEC_E_NO_AUTHENTICATING_AUTHORITY: 824 case SEC_E_INTERNAL_ERROR: 825 case SEC_E_NO_CREDENTIALS: 826 case SEC_E_UNSUPPORTED_FUNCTION: 827 case SEC_E_APPLICATION_PROTOCOL_MISMATCH: 828 */ 829 default: 830 failf(data, "schannel: initial InitializeSecurityContext failed: %s", 831 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 832 return CURLE_SSL_CONNECT_ERROR; 833 } 834 } 835 836 DEBUGF(infof(data, "schannel: sending initial handshake data: " 837 "sending %lu bytes...\n", outbuf.cbBuffer)); 838 839 /* send initial handshake data which is now stored in output buffer */ 840 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, 841 outbuf.cbBuffer, &written); 842 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 843 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { 844 failf(data, "schannel: failed to send initial handshake data: " 845 "sent %zd of %lu bytes", written, outbuf.cbBuffer); 846 return CURLE_SSL_CONNECT_ERROR; 847 } 848 849 DEBUGF(infof(data, "schannel: sent initial handshake data: " 850 "sent %zd bytes\n", written)); 851 852 BACKEND->recv_unrecoverable_err = CURLE_OK; 853 BACKEND->recv_sspi_close_notify = false; 854 BACKEND->recv_connection_closed = false; 855 BACKEND->encdata_is_incomplete = false; 856 857 /* continue to second handshake step */ 858 connssl->connecting_state = ssl_connect_2; 859 860 return CURLE_OK; 861 } 862 863 static CURLcode 864 schannel_connect_step2(struct connectdata *conn, int sockindex) 865 { 866 int i; 867 ssize_t nread = -1, written = -1; 868 struct Curl_easy *data = conn->data; 869 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 870 unsigned char *reallocated_buffer; 871 size_t reallocated_length; 872 SecBuffer outbuf[3]; 873 SecBufferDesc outbuf_desc; 874 SecBuffer inbuf[2]; 875 SecBufferDesc inbuf_desc; 876 SECURITY_STATUS sspi_status = SEC_E_OK; 877 TCHAR *host_name; 878 CURLcode result; 879 bool doread; 880 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 881 conn->host.name; 882 const char *pubkey_ptr; 883 884 doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; 885 886 DEBUGF(infof(data, 887 "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", 888 hostname, conn->remote_port)); 889 890 if(!BACKEND->cred || !BACKEND->ctxt) 891 return CURLE_SSL_CONNECT_ERROR; 892 893 /* buffer to store previously received and decrypted data */ 894 if(BACKEND->decdata_buffer == NULL) { 895 BACKEND->decdata_offset = 0; 896 BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 897 BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); 898 if(BACKEND->decdata_buffer == NULL) { 899 failf(data, "schannel: unable to allocate memory"); 900 return CURLE_OUT_OF_MEMORY; 901 } 902 } 903 904 /* buffer to store previously received and encrypted data */ 905 if(BACKEND->encdata_buffer == NULL) { 906 BACKEND->encdata_is_incomplete = false; 907 BACKEND->encdata_offset = 0; 908 BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 909 BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); 910 if(BACKEND->encdata_buffer == NULL) { 911 failf(data, "schannel: unable to allocate memory"); 912 return CURLE_OUT_OF_MEMORY; 913 } 914 } 915 916 /* if we need a bigger buffer to read a full message, increase buffer now */ 917 if(BACKEND->encdata_length - BACKEND->encdata_offset < 918 CURL_SCHANNEL_BUFFER_FREE_SIZE) { 919 /* increase internal encrypted data buffer */ 920 reallocated_length = BACKEND->encdata_offset + 921 CURL_SCHANNEL_BUFFER_FREE_SIZE; 922 reallocated_buffer = realloc(BACKEND->encdata_buffer, 923 reallocated_length); 924 925 if(reallocated_buffer == NULL) { 926 failf(data, "schannel: unable to re-allocate memory"); 927 return CURLE_OUT_OF_MEMORY; 928 } 929 else { 930 BACKEND->encdata_buffer = reallocated_buffer; 931 BACKEND->encdata_length = reallocated_length; 932 } 933 } 934 935 for(;;) { 936 if(doread) { 937 /* read encrypted handshake data from socket */ 938 result = Curl_read_plain(conn->sock[sockindex], 939 (char *) (BACKEND->encdata_buffer + 940 BACKEND->encdata_offset), 941 BACKEND->encdata_length - 942 BACKEND->encdata_offset, 943 &nread); 944 if(result == CURLE_AGAIN) { 945 if(connssl->connecting_state != ssl_connect_2_writing) 946 connssl->connecting_state = ssl_connect_2_reading; 947 DEBUGF(infof(data, "schannel: failed to receive handshake, " 948 "need more data\n")); 949 return CURLE_OK; 950 } 951 else if((result != CURLE_OK) || (nread == 0)) { 952 failf(data, "schannel: failed to receive handshake, " 953 "SSL/TLS connection failed"); 954 return CURLE_SSL_CONNECT_ERROR; 955 } 956 957 /* increase encrypted data buffer offset */ 958 BACKEND->encdata_offset += nread; 959 BACKEND->encdata_is_incomplete = false; 960 DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); 961 } 962 963 DEBUGF(infof(data, 964 "schannel: encrypted data buffer: offset %zu length %zu\n", 965 BACKEND->encdata_offset, BACKEND->encdata_length)); 966 967 /* setup input buffers */ 968 InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), 969 curlx_uztoul(BACKEND->encdata_offset)); 970 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 971 InitSecBufferDesc(&inbuf_desc, inbuf, 2); 972 973 /* setup output buffers */ 974 InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); 975 InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); 976 InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); 977 InitSecBufferDesc(&outbuf_desc, outbuf, 3); 978 979 if(inbuf[0].pvBuffer == NULL) { 980 failf(data, "schannel: unable to allocate memory"); 981 return CURLE_OUT_OF_MEMORY; 982 } 983 984 /* copy received handshake data into input buffer */ 985 memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer, 986 BACKEND->encdata_offset); 987 988 host_name = Curl_convert_UTF8_to_tchar(hostname); 989 if(!host_name) 990 return CURLE_OUT_OF_MEMORY; 991 992 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx 993 */ 994 sspi_status = s_pSecFn->InitializeSecurityContext( 995 &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle, 996 host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, 997 &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); 998 999 Curl_unicodefree(host_name); 1000 1001 /* free buffer for received handshake data */ 1002 Curl_safefree(inbuf[0].pvBuffer); 1003 1004 /* check if the handshake was incomplete */ 1005 if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 1006 BACKEND->encdata_is_incomplete = true; 1007 connssl->connecting_state = ssl_connect_2_reading; 1008 DEBUGF(infof(data, 1009 "schannel: received incomplete message, need more data\n")); 1010 return CURLE_OK; 1011 } 1012 1013 /* If the server has requested a client certificate, attempt to continue 1014 the handshake without one. This will allow connections to servers which 1015 request a client certificate but do not require it. */ 1016 if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && 1017 !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { 1018 BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; 1019 connssl->connecting_state = ssl_connect_2_writing; 1020 DEBUGF(infof(data, 1021 "schannel: a client certificate has been requested\n")); 1022 return CURLE_OK; 1023 } 1024 1025 /* check if the handshake needs to be continued */ 1026 if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { 1027 for(i = 0; i < 3; i++) { 1028 /* search for handshake tokens that need to be send */ 1029 if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { 1030 DEBUGF(infof(data, "schannel: sending next handshake data: " 1031 "sending %lu bytes...\n", outbuf[i].cbBuffer)); 1032 1033 /* send handshake token to server */ 1034 result = Curl_write_plain(conn, conn->sock[sockindex], 1035 outbuf[i].pvBuffer, outbuf[i].cbBuffer, 1036 &written); 1037 if((result != CURLE_OK) || 1038 (outbuf[i].cbBuffer != (size_t) written)) { 1039 failf(data, "schannel: failed to send next handshake data: " 1040 "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); 1041 return CURLE_SSL_CONNECT_ERROR; 1042 } 1043 } 1044 1045 /* free obsolete buffer */ 1046 if(outbuf[i].pvBuffer != NULL) { 1047 s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); 1048 } 1049 } 1050 } 1051 else { 1052 char buffer[STRERROR_LEN]; 1053 switch(sspi_status) { 1054 case SEC_E_INSUFFICIENT_MEMORY: 1055 failf(data, "schannel: next InitializeSecurityContext failed: %s", 1056 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1057 return CURLE_OUT_OF_MEMORY; 1058 case SEC_E_WRONG_PRINCIPAL: 1059 failf(data, "schannel: SNI or certificate check failed: %s", 1060 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1061 return CURLE_PEER_FAILED_VERIFICATION; 1062 /* 1063 case SEC_E_INVALID_HANDLE: 1064 case SEC_E_INVALID_TOKEN: 1065 case SEC_E_LOGON_DENIED: 1066 case SEC_E_TARGET_UNKNOWN: 1067 case SEC_E_NO_AUTHENTICATING_AUTHORITY: 1068 case SEC_E_INTERNAL_ERROR: 1069 case SEC_E_NO_CREDENTIALS: 1070 case SEC_E_UNSUPPORTED_FUNCTION: 1071 case SEC_E_APPLICATION_PROTOCOL_MISMATCH: 1072 */ 1073 default: 1074 failf(data, "schannel: next InitializeSecurityContext failed: %s", 1075 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1076 return CURLE_SSL_CONNECT_ERROR; 1077 } 1078 } 1079 1080 /* check if there was additional remaining encrypted data */ 1081 if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { 1082 DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", 1083 inbuf[1].cbBuffer)); 1084 /* 1085 There are two cases where we could be getting extra data here: 1086 1) If we're renegotiating a connection and the handshake is already 1087 complete (from the server perspective), it can encrypted app data 1088 (not handshake data) in an extra buffer at this point. 1089 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a 1090 connection and this extra data is part of the handshake. 1091 We should process the data immediately; waiting for the socket to 1092 be ready may fail since the server is done sending handshake data. 1093 */ 1094 /* check if the remaining data is less than the total amount 1095 and therefore begins after the already processed data */ 1096 if(BACKEND->encdata_offset > inbuf[1].cbBuffer) { 1097 memmove(BACKEND->encdata_buffer, 1098 (BACKEND->encdata_buffer + BACKEND->encdata_offset) - 1099 inbuf[1].cbBuffer, inbuf[1].cbBuffer); 1100 BACKEND->encdata_offset = inbuf[1].cbBuffer; 1101 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 1102 doread = FALSE; 1103 continue; 1104 } 1105 } 1106 } 1107 else { 1108 BACKEND->encdata_offset = 0; 1109 } 1110 break; 1111 } 1112 1113 /* check if the handshake needs to be continued */ 1114 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 1115 connssl->connecting_state = ssl_connect_2_reading; 1116 return CURLE_OK; 1117 } 1118 1119 /* check if the handshake is complete */ 1120 if(sspi_status == SEC_E_OK) { 1121 connssl->connecting_state = ssl_connect_3; 1122 DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); 1123 } 1124 1125 pubkey_ptr = SSL_IS_PROXY() ? 1126 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : 1127 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; 1128 if(pubkey_ptr) { 1129 result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr); 1130 if(result) { 1131 failf(data, "SSL: public key does not match pinned public key!"); 1132 return result; 1133 } 1134 } 1135 1136 #ifdef HAS_MANUAL_VERIFY_API 1137 if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) { 1138 return Curl_verify_certificate(conn, sockindex); 1139 } 1140 #endif 1141 1142 return CURLE_OK; 1143 } 1144 1145 static bool 1146 valid_cert_encoding(const CERT_CONTEXT *cert_context) 1147 { 1148 return (cert_context != NULL) && 1149 ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && 1150 (cert_context->pbCertEncoded != NULL) && 1151 (cert_context->cbCertEncoded > 0); 1152 } 1153 1154 typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg); 1155 1156 static void 1157 traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, 1158 void *arg) 1159 { 1160 const CERT_CONTEXT *current_context = NULL; 1161 bool should_continue = true; 1162 while(should_continue && 1163 (current_context = CertEnumCertificatesInStore( 1164 context->hCertStore, 1165 current_context)) != NULL) 1166 should_continue = func(current_context, arg); 1167 1168 if(current_context) 1169 CertFreeCertificateContext(current_context); 1170 } 1171 1172 static bool 1173 cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count) 1174 { 1175 if(valid_cert_encoding(ccert_context)) 1176 (*(int *)certs_count)++; 1177 return true; 1178 } 1179 1180 struct Adder_args 1181 { 1182 struct connectdata *conn; 1183 CURLcode result; 1184 int idx; 1185 }; 1186 1187 static bool 1188 add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg) 1189 { 1190 struct Adder_args *args = (struct Adder_args*)raw_arg; 1191 args->result = CURLE_OK; 1192 if(valid_cert_encoding(ccert_context)) { 1193 const char *beg = (const char *) ccert_context->pbCertEncoded; 1194 const char *end = beg + ccert_context->cbCertEncoded; 1195 args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end); 1196 } 1197 return args->result == CURLE_OK; 1198 } 1199 1200 static CURLcode 1201 schannel_connect_step3(struct connectdata *conn, int sockindex) 1202 { 1203 CURLcode result = CURLE_OK; 1204 struct Curl_easy *data = conn->data; 1205 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1206 SECURITY_STATUS sspi_status = SEC_E_OK; 1207 CERT_CONTEXT *ccert_context = NULL; 1208 #ifdef DEBUGBUILD 1209 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 1210 conn->host.name; 1211 #endif 1212 #ifdef HAS_ALPN 1213 SecPkgContext_ApplicationProtocol alpn_result; 1214 #endif 1215 1216 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 1217 1218 DEBUGF(infof(data, 1219 "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", 1220 hostname, conn->remote_port)); 1221 1222 if(!BACKEND->cred) 1223 return CURLE_SSL_CONNECT_ERROR; 1224 1225 /* check if the required context attributes are met */ 1226 if(BACKEND->ret_flags != BACKEND->req_flags) { 1227 if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT)) 1228 failf(data, "schannel: failed to setup sequence detection"); 1229 if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT)) 1230 failf(data, "schannel: failed to setup replay detection"); 1231 if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY)) 1232 failf(data, "schannel: failed to setup confidentiality"); 1233 if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY)) 1234 failf(data, "schannel: failed to setup memory allocation"); 1235 if(!(BACKEND->ret_flags & ISC_RET_STREAM)) 1236 failf(data, "schannel: failed to setup stream orientation"); 1237 return CURLE_SSL_CONNECT_ERROR; 1238 } 1239 1240 #ifdef HAS_ALPN 1241 if(BACKEND->use_alpn) { 1242 sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 1243 SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result); 1244 1245 if(sspi_status != SEC_E_OK) { 1246 failf(data, "schannel: failed to retrieve ALPN result"); 1247 return CURLE_SSL_CONNECT_ERROR; 1248 } 1249 1250 if(alpn_result.ProtoNegoStatus == 1251 SecApplicationProtocolNegotiationStatus_Success) { 1252 1253 infof(data, "schannel: ALPN, server accepted to use %.*s\n", 1254 alpn_result.ProtocolIdSize, alpn_result.ProtocolId); 1255 1256 #ifdef USE_NGHTTP2 1257 if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && 1258 !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, 1259 NGHTTP2_PROTO_VERSION_ID_LEN)) { 1260 conn->negnpn = CURL_HTTP_VERSION_2; 1261 } 1262 else 1263 #endif 1264 if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH && 1265 !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId, 1266 ALPN_HTTP_1_1_LENGTH)) { 1267 conn->negnpn = CURL_HTTP_VERSION_1_1; 1268 } 1269 } 1270 else 1271 infof(data, "ALPN, server did not agree to a protocol\n"); 1272 } 1273 #endif 1274 1275 /* save the current session data for possible re-use */ 1276 if(SSL_SET_OPTION(primary.sessionid)) { 1277 bool incache; 1278 struct curl_schannel_cred *old_cred = NULL; 1279 1280 Curl_ssl_sessionid_lock(conn); 1281 incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, 1282 sockindex)); 1283 if(incache) { 1284 if(old_cred != BACKEND->cred) { 1285 DEBUGF(infof(data, 1286 "schannel: old credential handle is stale, removing\n")); 1287 /* we're not taking old_cred ownership here, no refcount++ is needed */ 1288 Curl_ssl_delsessionid(conn, (void *)old_cred); 1289 incache = FALSE; 1290 } 1291 } 1292 if(!incache) { 1293 result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred, 1294 sizeof(struct curl_schannel_cred), 1295 sockindex); 1296 if(result) { 1297 Curl_ssl_sessionid_unlock(conn); 1298 failf(data, "schannel: failed to store credential handle"); 1299 return result; 1300 } 1301 else { 1302 /* this cred session is now also referenced by sessionid cache */ 1303 BACKEND->cred->refcount++; 1304 DEBUGF(infof(data, 1305 "schannel: stored credential handle in session cache\n")); 1306 } 1307 } 1308 Curl_ssl_sessionid_unlock(conn); 1309 } 1310 1311 if(data->set.ssl.certinfo) { 1312 int certs_count = 0; 1313 sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 1314 SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); 1315 1316 if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { 1317 failf(data, "schannel: failed to retrieve remote cert context"); 1318 return CURLE_PEER_FAILED_VERIFICATION; 1319 } 1320 1321 traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); 1322 1323 result = Curl_ssl_init_certinfo(data, certs_count); 1324 if(!result) { 1325 struct Adder_args args; 1326 args.conn = conn; 1327 args.idx = 0; 1328 traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); 1329 result = args.result; 1330 } 1331 CertFreeCertificateContext(ccert_context); 1332 if(result) 1333 return result; 1334 } 1335 1336 connssl->connecting_state = ssl_connect_done; 1337 1338 return CURLE_OK; 1339 } 1340 1341 static CURLcode 1342 schannel_connect_common(struct connectdata *conn, int sockindex, 1343 bool nonblocking, bool *done) 1344 { 1345 CURLcode result; 1346 struct Curl_easy *data = conn->data; 1347 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1348 curl_socket_t sockfd = conn->sock[sockindex]; 1349 time_t timeout_ms; 1350 int what; 1351 1352 /* check if the connection has already been established */ 1353 if(ssl_connection_complete == connssl->state) { 1354 *done = TRUE; 1355 return CURLE_OK; 1356 } 1357 1358 if(ssl_connect_1 == connssl->connecting_state) { 1359 /* check out how much more time we're allowed */ 1360 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1361 1362 if(timeout_ms < 0) { 1363 /* no need to continue if time already is up */ 1364 failf(data, "SSL/TLS connection timeout"); 1365 return CURLE_OPERATION_TIMEDOUT; 1366 } 1367 1368 result = schannel_connect_step1(conn, sockindex); 1369 if(result) 1370 return result; 1371 } 1372 1373 while(ssl_connect_2 == connssl->connecting_state || 1374 ssl_connect_2_reading == connssl->connecting_state || 1375 ssl_connect_2_writing == connssl->connecting_state) { 1376 1377 /* check out how much more time we're allowed */ 1378 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1379 1380 if(timeout_ms < 0) { 1381 /* no need to continue if time already is up */ 1382 failf(data, "SSL/TLS connection timeout"); 1383 return CURLE_OPERATION_TIMEDOUT; 1384 } 1385 1386 /* if ssl is expecting something, check if it's available. */ 1387 if(connssl->connecting_state == ssl_connect_2_reading 1388 || connssl->connecting_state == ssl_connect_2_writing) { 1389 1390 curl_socket_t writefd = ssl_connect_2_writing == 1391 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; 1392 curl_socket_t readfd = ssl_connect_2_reading == 1393 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; 1394 1395 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 1396 nonblocking ? 0 : timeout_ms); 1397 if(what < 0) { 1398 /* fatal error */ 1399 failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO); 1400 return CURLE_SSL_CONNECT_ERROR; 1401 } 1402 else if(0 == what) { 1403 if(nonblocking) { 1404 *done = FALSE; 1405 return CURLE_OK; 1406 } 1407 else { 1408 /* timeout */ 1409 failf(data, "SSL/TLS connection timeout"); 1410 return CURLE_OPERATION_TIMEDOUT; 1411 } 1412 } 1413 /* socket is readable or writable */ 1414 } 1415 1416 /* Run transaction, and return to the caller if it failed or if 1417 * this connection is part of a multi handle and this loop would 1418 * execute again. This permits the owner of a multi handle to 1419 * abort a connection attempt before step2 has completed while 1420 * ensuring that a client using select() or epoll() will always 1421 * have a valid fdset to wait on. 1422 */ 1423 result = schannel_connect_step2(conn, sockindex); 1424 if(result || (nonblocking && 1425 (ssl_connect_2 == connssl->connecting_state || 1426 ssl_connect_2_reading == connssl->connecting_state || 1427 ssl_connect_2_writing == connssl->connecting_state))) 1428 return result; 1429 1430 } /* repeat step2 until all transactions are done. */ 1431 1432 if(ssl_connect_3 == connssl->connecting_state) { 1433 result = schannel_connect_step3(conn, sockindex); 1434 if(result) 1435 return result; 1436 } 1437 1438 if(ssl_connect_done == connssl->connecting_state) { 1439 connssl->state = ssl_connection_complete; 1440 conn->recv[sockindex] = schannel_recv; 1441 conn->send[sockindex] = schannel_send; 1442 1443 #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS 1444 /* When SSPI is used in combination with Schannel 1445 * we need the Schannel context to create the Schannel 1446 * binding to pass the IIS extended protection checks. 1447 * Available on Windows 7 or later. 1448 */ 1449 conn->sslContext = &BACKEND->ctxt->ctxt_handle; 1450 #endif 1451 1452 *done = TRUE; 1453 } 1454 else 1455 *done = FALSE; 1456 1457 /* reset our connection state machine */ 1458 connssl->connecting_state = ssl_connect_1; 1459 1460 return CURLE_OK; 1461 } 1462 1463 static ssize_t 1464 schannel_send(struct connectdata *conn, int sockindex, 1465 const void *buf, size_t len, CURLcode *err) 1466 { 1467 ssize_t written = -1; 1468 size_t data_len = 0; 1469 unsigned char *data = NULL; 1470 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1471 SecBuffer outbuf[4]; 1472 SecBufferDesc outbuf_desc; 1473 SECURITY_STATUS sspi_status = SEC_E_OK; 1474 CURLcode result; 1475 1476 /* check if the maximum stream sizes were queried */ 1477 if(BACKEND->stream_sizes.cbMaximumMessage == 0) { 1478 sspi_status = s_pSecFn->QueryContextAttributes( 1479 &BACKEND->ctxt->ctxt_handle, 1480 SECPKG_ATTR_STREAM_SIZES, 1481 &BACKEND->stream_sizes); 1482 if(sspi_status != SEC_E_OK) { 1483 *err = CURLE_SEND_ERROR; 1484 return -1; 1485 } 1486 } 1487 1488 /* check if the buffer is longer than the maximum message length */ 1489 if(len > BACKEND->stream_sizes.cbMaximumMessage) { 1490 len = BACKEND->stream_sizes.cbMaximumMessage; 1491 } 1492 1493 /* calculate the complete message length and allocate a buffer for it */ 1494 data_len = BACKEND->stream_sizes.cbHeader + len + 1495 BACKEND->stream_sizes.cbTrailer; 1496 data = (unsigned char *) malloc(data_len); 1497 if(data == NULL) { 1498 *err = CURLE_OUT_OF_MEMORY; 1499 return -1; 1500 } 1501 1502 /* setup output buffers (header, data, trailer, empty) */ 1503 InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, 1504 data, BACKEND->stream_sizes.cbHeader); 1505 InitSecBuffer(&outbuf[1], SECBUFFER_DATA, 1506 data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); 1507 InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, 1508 data + BACKEND->stream_sizes.cbHeader + len, 1509 BACKEND->stream_sizes.cbTrailer); 1510 InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); 1511 InitSecBufferDesc(&outbuf_desc, outbuf, 4); 1512 1513 /* copy data into output buffer */ 1514 memcpy(outbuf[1].pvBuffer, buf, len); 1515 1516 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ 1517 sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0, 1518 &outbuf_desc, 0); 1519 1520 /* check if the message was encrypted */ 1521 if(sspi_status == SEC_E_OK) { 1522 written = 0; 1523 1524 /* send the encrypted message including header, data and trailer */ 1525 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; 1526 1527 /* 1528 It's important to send the full message which includes the header, 1529 encrypted payload, and trailer. Until the client receives all the 1530 data a coherent message has not been delivered and the client 1531 can't read any of it. 1532 1533 If we wanted to buffer the unwritten encrypted bytes, we would 1534 tell the client that all data it has requested to be sent has been 1535 sent. The unwritten encrypted bytes would be the first bytes to 1536 send on the next invocation. 1537 Here's the catch with this - if we tell the client that all the 1538 bytes have been sent, will the client call this method again to 1539 send the buffered data? Looking at who calls this function, it 1540 seems the answer is NO. 1541 */ 1542 1543 /* send entire message or fail */ 1544 while(len > (size_t)written) { 1545 ssize_t this_write; 1546 time_t timeleft; 1547 int what; 1548 1549 this_write = 0; 1550 1551 timeleft = Curl_timeleft(conn->data, NULL, FALSE); 1552 if(timeleft < 0) { 1553 /* we already got the timeout */ 1554 failf(conn->data, "schannel: timed out sending data " 1555 "(bytes sent: %zd)", written); 1556 *err = CURLE_OPERATION_TIMEDOUT; 1557 written = -1; 1558 break; 1559 } 1560 1561 what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft); 1562 if(what < 0) { 1563 /* fatal error */ 1564 failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1565 *err = CURLE_SEND_ERROR; 1566 written = -1; 1567 break; 1568 } 1569 else if(0 == what) { 1570 failf(conn->data, "schannel: timed out sending data " 1571 "(bytes sent: %zd)", written); 1572 *err = CURLE_OPERATION_TIMEDOUT; 1573 written = -1; 1574 break; 1575 } 1576 /* socket is writable */ 1577 1578 result = Curl_write_plain(conn, conn->sock[sockindex], data + written, 1579 len - written, &this_write); 1580 if(result == CURLE_AGAIN) 1581 continue; 1582 else if(result != CURLE_OK) { 1583 *err = result; 1584 written = -1; 1585 break; 1586 } 1587 1588 written += this_write; 1589 } 1590 } 1591 else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { 1592 *err = CURLE_OUT_OF_MEMORY; 1593 } 1594 else{ 1595 *err = CURLE_SEND_ERROR; 1596 } 1597 1598 Curl_safefree(data); 1599 1600 if(len == (size_t)written) 1601 /* Encrypted message including header, data and trailer entirely sent. 1602 The return value is the number of unencrypted bytes that were sent. */ 1603 written = outbuf[1].cbBuffer; 1604 1605 return written; 1606 } 1607 1608 static ssize_t 1609 schannel_recv(struct connectdata *conn, int sockindex, 1610 char *buf, size_t len, CURLcode *err) 1611 { 1612 size_t size = 0; 1613 ssize_t nread = -1; 1614 struct Curl_easy *data = conn->data; 1615 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1616 unsigned char *reallocated_buffer; 1617 size_t reallocated_length; 1618 bool done = FALSE; 1619 SecBuffer inbuf[4]; 1620 SecBufferDesc inbuf_desc; 1621 SECURITY_STATUS sspi_status = SEC_E_OK; 1622 /* we want the length of the encrypted buffer to be at least large enough 1623 that it can hold all the bytes requested and some TLS record overhead. */ 1624 size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; 1625 1626 /**************************************************************************** 1627 * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup. 1628 * The pattern for return error is set *err, optional infof, goto cleanup. 1629 * 1630 * Our priority is to always return as much decrypted data to the caller as 1631 * possible, even if an error occurs. The state of the decrypted buffer must 1632 * always be valid. Transfer of decrypted data to the caller's buffer is 1633 * handled in the cleanup. 1634 */ 1635 1636 DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); 1637 *err = CURLE_OK; 1638 1639 if(len && len <= BACKEND->decdata_offset) { 1640 infof(data, "schannel: enough decrypted data is already available\n"); 1641 goto cleanup; 1642 } 1643 else if(BACKEND->recv_unrecoverable_err) { 1644 *err = BACKEND->recv_unrecoverable_err; 1645 infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); 1646 goto cleanup; 1647 } 1648 else if(BACKEND->recv_sspi_close_notify) { 1649 /* once a server has indicated shutdown there is no more encrypted data */ 1650 infof(data, "schannel: server indicated shutdown in a prior call\n"); 1651 goto cleanup; 1652 } 1653 else if(!len) { 1654 /* It's debatable what to return when !len. Regardless we can't return 1655 immediately because there may be data to decrypt (in the case we want to 1656 decrypt all encrypted cached data) so handle !len later in cleanup. 1657 */ 1658 ; /* do nothing */ 1659 } 1660 else if(!BACKEND->recv_connection_closed) { 1661 /* increase enc buffer in order to fit the requested amount of data */ 1662 size = BACKEND->encdata_length - BACKEND->encdata_offset; 1663 if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || 1664 BACKEND->encdata_length < min_encdata_length) { 1665 reallocated_length = BACKEND->encdata_offset + 1666 CURL_SCHANNEL_BUFFER_FREE_SIZE; 1667 if(reallocated_length < min_encdata_length) { 1668 reallocated_length = min_encdata_length; 1669 } 1670 reallocated_buffer = realloc(BACKEND->encdata_buffer, 1671 reallocated_length); 1672 if(reallocated_buffer == NULL) { 1673 *err = CURLE_OUT_OF_MEMORY; 1674 failf(data, "schannel: unable to re-allocate memory"); 1675 goto cleanup; 1676 } 1677 1678 BACKEND->encdata_buffer = reallocated_buffer; 1679 BACKEND->encdata_length = reallocated_length; 1680 size = BACKEND->encdata_length - BACKEND->encdata_offset; 1681 DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", 1682 BACKEND->encdata_length)); 1683 } 1684 1685 DEBUGF(infof(data, 1686 "schannel: encrypted data buffer: offset %zu length %zu\n", 1687 BACKEND->encdata_offset, BACKEND->encdata_length)); 1688 1689 /* read encrypted data from socket */ 1690 *err = Curl_read_plain(conn->sock[sockindex], 1691 (char *)(BACKEND->encdata_buffer + 1692 BACKEND->encdata_offset), 1693 size, &nread); 1694 if(*err) { 1695 nread = -1; 1696 if(*err == CURLE_AGAIN) 1697 DEBUGF(infof(data, 1698 "schannel: Curl_read_plain returned CURLE_AGAIN\n")); 1699 else if(*err == CURLE_RECV_ERROR) 1700 infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); 1701 else 1702 infof(data, "schannel: Curl_read_plain returned error %d\n", *err); 1703 } 1704 else if(nread == 0) { 1705 BACKEND->recv_connection_closed = true; 1706 DEBUGF(infof(data, "schannel: server closed the connection\n")); 1707 } 1708 else if(nread > 0) { 1709 BACKEND->encdata_offset += (size_t)nread; 1710 BACKEND->encdata_is_incomplete = false; 1711 DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); 1712 } 1713 } 1714 1715 DEBUGF(infof(data, 1716 "schannel: encrypted data buffer: offset %zu length %zu\n", 1717 BACKEND->encdata_offset, BACKEND->encdata_length)); 1718 1719 /* decrypt loop */ 1720 while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && 1721 (!len || BACKEND->decdata_offset < len || 1722 BACKEND->recv_connection_closed)) { 1723 /* prepare data buffer for DecryptMessage call */ 1724 InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer, 1725 curlx_uztoul(BACKEND->encdata_offset)); 1726 1727 /* we need 3 more empty input buffers for possible output */ 1728 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 1729 InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); 1730 InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); 1731 InitSecBufferDesc(&inbuf_desc, inbuf, 4); 1732 1733 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx 1734 */ 1735 sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle, 1736 &inbuf_desc, 0, NULL); 1737 1738 /* check if everything went fine (server may want to renegotiate 1739 or shutdown the connection context) */ 1740 if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || 1741 sspi_status == SEC_I_CONTEXT_EXPIRED) { 1742 /* check for successfully decrypted data, even before actual 1743 renegotiation or shutdown of the connection context */ 1744 if(inbuf[1].BufferType == SECBUFFER_DATA) { 1745 DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", 1746 inbuf[1].cbBuffer)); 1747 1748 /* increase buffer in order to fit the received amount of data */ 1749 size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? 1750 inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; 1751 if(BACKEND->decdata_length - BACKEND->decdata_offset < size || 1752 BACKEND->decdata_length < len) { 1753 /* increase internal decrypted data buffer */ 1754 reallocated_length = BACKEND->decdata_offset + size; 1755 /* make sure that the requested amount of data fits */ 1756 if(reallocated_length < len) { 1757 reallocated_length = len; 1758 } 1759 reallocated_buffer = realloc(BACKEND->decdata_buffer, 1760 reallocated_length); 1761 if(reallocated_buffer == NULL) { 1762 *err = CURLE_OUT_OF_MEMORY; 1763 failf(data, "schannel: unable to re-allocate memory"); 1764 goto cleanup; 1765 } 1766 BACKEND->decdata_buffer = reallocated_buffer; 1767 BACKEND->decdata_length = reallocated_length; 1768 } 1769 1770 /* copy decrypted data to internal buffer */ 1771 size = inbuf[1].cbBuffer; 1772 if(size) { 1773 memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset, 1774 inbuf[1].pvBuffer, size); 1775 BACKEND->decdata_offset += size; 1776 } 1777 1778 DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); 1779 DEBUGF(infof(data, 1780 "schannel: decrypted cached: offset %zu length %zu\n", 1781 BACKEND->decdata_offset, BACKEND->decdata_length)); 1782 } 1783 1784 /* check for remaining encrypted data */ 1785 if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { 1786 DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", 1787 inbuf[3].cbBuffer)); 1788 1789 /* check if the remaining data is less than the total amount 1790 * and therefore begins after the already processed data 1791 */ 1792 if(BACKEND->encdata_offset > inbuf[3].cbBuffer) { 1793 /* move remaining encrypted data forward to the beginning of 1794 buffer */ 1795 memmove(BACKEND->encdata_buffer, 1796 (BACKEND->encdata_buffer + BACKEND->encdata_offset) - 1797 inbuf[3].cbBuffer, inbuf[3].cbBuffer); 1798 BACKEND->encdata_offset = inbuf[3].cbBuffer; 1799 } 1800 1801 DEBUGF(infof(data, 1802 "schannel: encrypted cached: offset %zu length %zu\n", 1803 BACKEND->encdata_offset, BACKEND->encdata_length)); 1804 } 1805 else { 1806 /* reset encrypted buffer offset, because there is no data remaining */ 1807 BACKEND->encdata_offset = 0; 1808 } 1809 1810 /* check if server wants to renegotiate the connection context */ 1811 if(sspi_status == SEC_I_RENEGOTIATE) { 1812 infof(data, "schannel: remote party requests renegotiation\n"); 1813 if(*err && *err != CURLE_AGAIN) { 1814 infof(data, "schannel: can't renogotiate, an error is pending\n"); 1815 goto cleanup; 1816 } 1817 if(BACKEND->encdata_offset) { 1818 *err = CURLE_RECV_ERROR; 1819 infof(data, "schannel: can't renogotiate, " 1820 "encrypted data available\n"); 1821 goto cleanup; 1822 } 1823 /* begin renegotiation */ 1824 infof(data, "schannel: renegotiating SSL/TLS connection\n"); 1825 connssl->state = ssl_connection_negotiating; 1826 connssl->connecting_state = ssl_connect_2_writing; 1827 *err = schannel_connect_common(conn, sockindex, FALSE, &done); 1828 if(*err) { 1829 infof(data, "schannel: renegotiation failed\n"); 1830 goto cleanup; 1831 } 1832 /* now retry receiving data */ 1833 sspi_status = SEC_E_OK; 1834 infof(data, "schannel: SSL/TLS connection renegotiated\n"); 1835 continue; 1836 } 1837 /* check if the server closed the connection */ 1838 else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { 1839 /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not 1840 returned so we have to work around that in cleanup. */ 1841 BACKEND->recv_sspi_close_notify = true; 1842 if(!BACKEND->recv_connection_closed) { 1843 BACKEND->recv_connection_closed = true; 1844 infof(data, "schannel: server closed the connection\n"); 1845 } 1846 goto cleanup; 1847 } 1848 } 1849 else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 1850 BACKEND->encdata_is_incomplete = true; 1851 if(!*err) 1852 *err = CURLE_AGAIN; 1853 infof(data, "schannel: failed to decrypt data, need more data\n"); 1854 goto cleanup; 1855 } 1856 else { 1857 char buffer[STRERROR_LEN]; 1858 *err = CURLE_RECV_ERROR; 1859 infof(data, "schannel: failed to read data from server: %s\n", 1860 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1861 goto cleanup; 1862 } 1863 } 1864 1865 DEBUGF(infof(data, 1866 "schannel: encrypted data buffer: offset %zu length %zu\n", 1867 BACKEND->encdata_offset, BACKEND->encdata_length)); 1868 1869 DEBUGF(infof(data, 1870 "schannel: decrypted data buffer: offset %zu length %zu\n", 1871 BACKEND->decdata_offset, BACKEND->decdata_length)); 1872 1873 cleanup: 1874 /* Warning- there is no guarantee the encdata state is valid at this point */ 1875 DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); 1876 1877 /* Error if the connection has closed without a close_notify. 1878 Behavior here is a matter of debate. We don't want to be vulnerable to a 1879 truncation attack however there's some browser precedent for ignoring the 1880 close_notify for compatibility reasons. 1881 Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't 1882 return close_notify. In that case if the connection was closed we assume it 1883 was graceful (close_notify) since there doesn't seem to be a way to tell. 1884 */ 1885 if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed && 1886 !BACKEND->recv_sspi_close_notify) { 1887 bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, 1888 VERSION_EQUAL); 1889 1890 if(isWin2k && sspi_status == SEC_E_OK) 1891 BACKEND->recv_sspi_close_notify = true; 1892 else { 1893 *err = CURLE_RECV_ERROR; 1894 infof(data, "schannel: server closed abruptly (missing close_notify)\n"); 1895 } 1896 } 1897 1898 /* Any error other than CURLE_AGAIN is an unrecoverable error. */ 1899 if(*err && *err != CURLE_AGAIN) 1900 BACKEND->recv_unrecoverable_err = *err; 1901 1902 size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset; 1903 if(size) { 1904 memcpy(buf, BACKEND->decdata_buffer, size); 1905 memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, 1906 BACKEND->decdata_offset - size); 1907 BACKEND->decdata_offset -= size; 1908 DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); 1909 DEBUGF(infof(data, 1910 "schannel: decrypted data buffer: offset %zu length %zu\n", 1911 BACKEND->decdata_offset, BACKEND->decdata_length)); 1912 *err = CURLE_OK; 1913 return (ssize_t)size; 1914 } 1915 1916 if(!*err && !BACKEND->recv_connection_closed) 1917 *err = CURLE_AGAIN; 1918 1919 /* It's debatable what to return when !len. We could return whatever error we 1920 got from decryption but instead we override here so the return is consistent. 1921 */ 1922 if(!len) 1923 *err = CURLE_OK; 1924 1925 return *err ? -1 : 0; 1926 } 1927 1928 static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, 1929 int sockindex, bool *done) 1930 { 1931 return schannel_connect_common(conn, sockindex, TRUE, done); 1932 } 1933 1934 static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) 1935 { 1936 CURLcode result; 1937 bool done = FALSE; 1938 1939 result = schannel_connect_common(conn, sockindex, FALSE, &done); 1940 if(result) 1941 return result; 1942 1943 DEBUGASSERT(done); 1944 1945 return CURLE_OK; 1946 } 1947 1948 static bool Curl_schannel_data_pending(const struct connectdata *conn, 1949 int sockindex) 1950 { 1951 const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1952 1953 if(connssl->use) /* SSL/TLS is in use */ 1954 return (BACKEND->decdata_offset > 0 || 1955 (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete)); 1956 else 1957 return FALSE; 1958 } 1959 1960 static void Curl_schannel_close(struct connectdata *conn, int sockindex) 1961 { 1962 if(conn->ssl[sockindex].use) 1963 /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ 1964 Curl_ssl_shutdown(conn, sockindex); 1965 } 1966 1967 static void Curl_schannel_session_free(void *ptr) 1968 { 1969 /* this is expected to be called under sessionid lock */ 1970 struct curl_schannel_cred *cred = ptr; 1971 1972 cred->refcount--; 1973 if(cred->refcount == 0) { 1974 s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); 1975 Curl_safefree(cred); 1976 } 1977 } 1978 1979 static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) 1980 { 1981 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx 1982 * Shutting Down an Schannel Connection 1983 */ 1984 struct Curl_easy *data = conn->data; 1985 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1986 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 1987 conn->host.name; 1988 1989 DEBUGASSERT(data); 1990 1991 infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", 1992 hostname, conn->remote_port); 1993 1994 if(BACKEND->cred && BACKEND->ctxt) { 1995 SecBufferDesc BuffDesc; 1996 SecBuffer Buffer; 1997 SECURITY_STATUS sspi_status; 1998 SecBuffer outbuf; 1999 SecBufferDesc outbuf_desc; 2000 CURLcode result; 2001 TCHAR *host_name; 2002 DWORD dwshut = SCHANNEL_SHUTDOWN; 2003 2004 InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); 2005 InitSecBufferDesc(&BuffDesc, &Buffer, 1); 2006 2007 sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, 2008 &BuffDesc); 2009 2010 if(sspi_status != SEC_E_OK) { 2011 char buffer[STRERROR_LEN]; 2012 failf(data, "schannel: ApplyControlToken failure: %s", 2013 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 2014 } 2015 2016 host_name = Curl_convert_UTF8_to_tchar(hostname); 2017 if(!host_name) 2018 return CURLE_OUT_OF_MEMORY; 2019 2020 /* setup output buffer */ 2021 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 2022 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 2023 2024 sspi_status = s_pSecFn->InitializeSecurityContext( 2025 &BACKEND->cred->cred_handle, 2026 &BACKEND->ctxt->ctxt_handle, 2027 host_name, 2028 BACKEND->req_flags, 2029 0, 2030 0, 2031 NULL, 2032 0, 2033 &BACKEND->ctxt->ctxt_handle, 2034 &outbuf_desc, 2035 &BACKEND->ret_flags, 2036 &BACKEND->ctxt->time_stamp); 2037 2038 Curl_unicodefree(host_name); 2039 2040 if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { 2041 /* send close message which is in output buffer */ 2042 ssize_t written; 2043 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, 2044 outbuf.cbBuffer, &written); 2045 2046 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 2047 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { 2048 infof(data, "schannel: failed to send close msg: %s" 2049 " (bytes written: %zd)\n", curl_easy_strerror(result), written); 2050 } 2051 } 2052 } 2053 2054 /* free SSPI Schannel API security context handle */ 2055 if(BACKEND->ctxt) { 2056 DEBUGF(infof(data, "schannel: clear security context handle\n")); 2057 s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); 2058 Curl_safefree(BACKEND->ctxt); 2059 } 2060 2061 /* free SSPI Schannel API credential handle */ 2062 if(BACKEND->cred) { 2063 /* 2064 * When this function is called from Curl_schannel_close() the connection 2065 * might not have an associated transfer so the check for conn->data is 2066 * necessary. 2067 */ 2068 Curl_ssl_sessionid_lock(conn); 2069 Curl_schannel_session_free(BACKEND->cred); 2070 Curl_ssl_sessionid_unlock(conn); 2071 BACKEND->cred = NULL; 2072 } 2073 2074 /* free internal buffer for received encrypted data */ 2075 if(BACKEND->encdata_buffer != NULL) { 2076 Curl_safefree(BACKEND->encdata_buffer); 2077 BACKEND->encdata_length = 0; 2078 BACKEND->encdata_offset = 0; 2079 BACKEND->encdata_is_incomplete = false; 2080 } 2081 2082 /* free internal buffer for received decrypted data */ 2083 if(BACKEND->decdata_buffer != NULL) { 2084 Curl_safefree(BACKEND->decdata_buffer); 2085 BACKEND->decdata_length = 0; 2086 BACKEND->decdata_offset = 0; 2087 } 2088 2089 return CURLE_OK; 2090 } 2091 2092 static int Curl_schannel_init(void) 2093 { 2094 return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); 2095 } 2096 2097 static void Curl_schannel_cleanup(void) 2098 { 2099 Curl_sspi_global_cleanup(); 2100 } 2101 2102 static size_t Curl_schannel_version(char *buffer, size_t size) 2103 { 2104 size = msnprintf(buffer, size, "Schannel"); 2105 2106 return size; 2107 } 2108 2109 static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, 2110 unsigned char *entropy, size_t length) 2111 { 2112 HCRYPTPROV hCryptProv = 0; 2113 2114 (void)data; 2115 2116 if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 2117 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) 2118 return CURLE_FAILED_INIT; 2119 2120 if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { 2121 CryptReleaseContext(hCryptProv, 0UL); 2122 return CURLE_FAILED_INIT; 2123 } 2124 2125 CryptReleaseContext(hCryptProv, 0UL); 2126 return CURLE_OK; 2127 } 2128 2129 static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, 2130 const char *pinnedpubkey) 2131 { 2132 SECURITY_STATUS sspi_status; 2133 struct Curl_easy *data = conn->data; 2134 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 2135 CERT_CONTEXT *pCertContextServer = NULL; 2136 const char *x509_der; 2137 DWORD x509_der_len; 2138 curl_X509certificate x509_parsed; 2139 curl_asn1Element *pubkey; 2140 2141 /* Result is returned to caller */ 2142 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 2143 2144 /* if a path wasn't specified, don't pin */ 2145 if(!pinnedpubkey) 2146 return CURLE_OK; 2147 2148 do { 2149 sspi_status = 2150 s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 2151 SECPKG_ATTR_REMOTE_CERT_CONTEXT, 2152 &pCertContextServer); 2153 2154 if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { 2155 char buffer[STRERROR_LEN]; 2156 failf(data, "schannel: Failed to read remote certificate context: %s", 2157 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 2158 break; /* failed */ 2159 } 2160 2161 2162 if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && 2163 (pCertContextServer->cbCertEncoded > 0))) 2164 break; 2165 2166 x509_der = (const char *)pCertContextServer->pbCertEncoded; 2167 x509_der_len = pCertContextServer->cbCertEncoded; 2168 memset(&x509_parsed, 0, sizeof(x509_parsed)); 2169 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) 2170 break; 2171 2172 pubkey = &x509_parsed.subjectPublicKeyInfo; 2173 if(!pubkey->header || pubkey->end <= pubkey->header) { 2174 failf(data, "SSL: failed retrieving public key from server certificate"); 2175 break; 2176 } 2177 2178 result = Curl_pin_peer_pubkey(data, 2179 pinnedpubkey, 2180 (const unsigned char *)pubkey->header, 2181 (size_t)(pubkey->end - pubkey->header)); 2182 if(result) { 2183 failf(data, "SSL: public key does not match pinned public key!"); 2184 } 2185 } while(0); 2186 2187 if(pCertContextServer) 2188 CertFreeCertificateContext(pCertContextServer); 2189 2190 return result; 2191 } 2192 2193 static void Curl_schannel_checksum(const unsigned char *input, 2194 size_t inputlen, 2195 unsigned char *checksum, 2196 size_t checksumlen, 2197 DWORD provType, 2198 const unsigned int algId) 2199 { 2200 HCRYPTPROV hProv = 0; 2201 HCRYPTHASH hHash = 0; 2202 DWORD cbHashSize = 0; 2203 DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize); 2204 DWORD dwChecksumLen = (DWORD)checksumlen; 2205 2206 /* since this can fail in multiple ways, zero memory first so we never 2207 * return old data 2208 */ 2209 memset(checksum, 0, checksumlen); 2210 2211 if(!CryptAcquireContext(&hProv, NULL, NULL, provType, 2212 CRYPT_VERIFYCONTEXT)) 2213 return; /* failed */ 2214 2215 do { 2216 if(!CryptCreateHash(hProv, algId, 0, 0, &hHash)) 2217 break; /* failed */ 2218 2219 /* workaround for original MinGW, should be (const BYTE*) */ 2220 if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0)) 2221 break; /* failed */ 2222 2223 /* get hash size */ 2224 if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, 2225 &dwHashSizeLen, 0)) 2226 break; /* failed */ 2227 2228 /* check hash size */ 2229 if(checksumlen < cbHashSize) 2230 break; /* failed */ 2231 2232 if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0)) 2233 break; /* failed */ 2234 } while(0); 2235 2236 if(hHash) 2237 CryptDestroyHash(hHash); 2238 2239 if(hProv) 2240 CryptReleaseContext(hProv, 0); 2241 } 2242 2243 static CURLcode Curl_schannel_md5sum(unsigned char *input, 2244 size_t inputlen, 2245 unsigned char *md5sum, 2246 size_t md5len) 2247 { 2248 Curl_schannel_checksum(input, inputlen, md5sum, md5len, 2249 PROV_RSA_FULL, CALG_MD5); 2250 return CURLE_OK; 2251 } 2252 2253 static CURLcode Curl_schannel_sha256sum(const unsigned char *input, 2254 size_t inputlen, 2255 unsigned char *sha256sum, 2256 size_t sha256len) 2257 { 2258 Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, 2259 PROV_RSA_AES, CALG_SHA_256); 2260 return CURLE_OK; 2261 } 2262 2263 static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, 2264 CURLINFO info UNUSED_PARAM) 2265 { 2266 (void)info; 2267 return &BACKEND->ctxt->ctxt_handle; 2268 } 2269 2270 const struct Curl_ssl Curl_ssl_schannel = { 2271 { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ 2272 2273 SSLSUPP_CERTINFO | 2274 SSLSUPP_PINNEDPUBKEY, 2275 2276 sizeof(struct ssl_backend_data), 2277 2278 Curl_schannel_init, /* init */ 2279 Curl_schannel_cleanup, /* cleanup */ 2280 Curl_schannel_version, /* version */ 2281 Curl_none_check_cxn, /* check_cxn */ 2282 Curl_schannel_shutdown, /* shutdown */ 2283 Curl_schannel_data_pending, /* data_pending */ 2284 Curl_schannel_random, /* random */ 2285 Curl_none_cert_status_request, /* cert_status_request */ 2286 Curl_schannel_connect, /* connect */ 2287 Curl_schannel_connect_nonblocking, /* connect_nonblocking */ 2288 Curl_schannel_get_internals, /* get_internals */ 2289 Curl_schannel_close, /* close_one */ 2290 Curl_none_close_all, /* close_all */ 2291 Curl_schannel_session_free, /* session_free */ 2292 Curl_none_set_engine, /* set_engine */ 2293 Curl_none_set_engine_default, /* set_engine_default */ 2294 Curl_none_engines_list, /* engines_list */ 2295 Curl_none_false_start, /* false_start */ 2296 Curl_schannel_md5sum, /* md5sum */ 2297 Curl_schannel_sha256sum /* sha256sum */ 2298 }; 2299 2300 #endif /* USE_SCHANNEL */ 2301