schannel.c (92835B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * Copyright (C) Marc Hoersken, <info@marc-hoersken.de> 10 * Copyright (C) Mark Salisbury, <mark.salisbury@hp.com> 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.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 * SPDX-License-Identifier: curl 24 * 25 ***************************************************************************/ 26 27 /* 28 * Source file for all Schannel-specific code for the TLS/SSL layer. No code 29 * but vtls.c should ever call or use these functions. 30 */ 31 32 #include "../curl_setup.h" 33 34 #ifdef USE_SCHANNEL 35 36 #ifndef USE_WINDOWS_SSPI 37 # error "cannot compile SCHANNEL support without SSPI." 38 #endif 39 40 #include "schannel.h" 41 #include "schannel_int.h" 42 #include "vtls.h" 43 #include "vtls_int.h" 44 #include "vtls_scache.h" 45 #include "../sendf.h" 46 #include "../connect.h" /* for the connect timeout */ 47 #include "../strdup.h" 48 #include "../strerror.h" 49 #include "../select.h" /* for the socket readiness */ 50 #include "../curlx/inet_pton.h" /* for IP addr SNI check */ 51 #include "../curlx/multibyte.h" 52 #include "../curlx/warnless.h" 53 #include "x509asn1.h" 54 #include "../curl_printf.h" 55 #include "../multiif.h" 56 #include "../system_win32.h" 57 #include "../curlx/version_win32.h" 58 #include "../rand.h" 59 #include "../curlx/strparse.h" 60 61 /* The last #include file should be: */ 62 #include "../curl_memory.h" 63 #include "../memdebug.h" 64 65 /* Some verbose debug messages are wrapped by SCH_DEV() instead of DEBUGF() 66 * and only shown if CURL_SCHANNEL_DEV_DEBUG was defined at build time. These 67 * messages are extra verbose and intended for curl developers debugging 68 * Schannel recv decryption. 69 */ 70 #ifdef CURL_SCHANNEL_DEV_DEBUG 71 #define SCH_DEV(x) x 72 #else 73 #define SCH_DEV(x) do { } while(0) 74 #endif 75 76 #ifndef BCRYPT_CHAIN_MODE_CCM 77 #define BCRYPT_CHAIN_MODE_CCM L"ChainingModeCCM" 78 #endif 79 80 #ifndef BCRYPT_CHAIN_MODE_GCM 81 #define BCRYPT_CHAIN_MODE_GCM L"ChainingModeGCM" 82 #endif 83 84 #ifndef BCRYPT_AES_ALGORITHM 85 #define BCRYPT_AES_ALGORITHM L"AES" 86 #endif 87 88 #ifndef BCRYPT_SHA256_ALGORITHM 89 #define BCRYPT_SHA256_ALGORITHM L"SHA256" 90 #endif 91 92 #ifndef BCRYPT_SHA384_ALGORITHM 93 #define BCRYPT_SHA384_ALGORITHM L"SHA384" 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_TLS1_0_CLIENT 105 #define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT 106 #endif 107 108 #ifndef SP_PROT_TLS1_1_CLIENT 109 #define SP_PROT_TLS1_1_CLIENT 0x00000200 110 #endif 111 112 #ifndef SP_PROT_TLS1_2_CLIENT 113 #define SP_PROT_TLS1_2_CLIENT 0x00000800 114 #endif 115 116 #ifndef SP_PROT_TLS1_3_CLIENT 117 #define SP_PROT_TLS1_3_CLIENT 0x00002000 118 #endif 119 120 #ifndef SCH_USE_STRONG_CRYPTO 121 #define SCH_USE_STRONG_CRYPTO 0x00400000 122 #endif 123 124 #ifndef SECBUFFER_ALERT 125 #define SECBUFFER_ALERT 17 126 #endif 127 128 /* Both schannel buffer sizes must be > 0 */ 129 #define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 130 #define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 131 132 #define CERT_THUMBPRINT_STR_LEN 40 133 #define CERT_THUMBPRINT_DATA_LEN 20 134 135 /* Uncomment to force verbose output 136 * #define infof(x, y, ...) printf(y, __VA_ARGS__) 137 * #define failf(x, y, ...) printf(y, __VA_ARGS__) 138 */ 139 140 #ifndef CALG_SHA_256 141 #define CALG_SHA_256 0x0000800c 142 #endif 143 144 /* Work around typo in CeGCC (as of 0.59.1) w32api headers */ 145 #if defined(__MINGW32CE__) && \ 146 !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH) 147 #define ALG_CLASS_DHASH ALG_CLASS_HASH 148 #endif 149 150 #ifndef PKCS12_NO_PERSIST_KEY 151 #define PKCS12_NO_PERSIST_KEY 0x00008000 152 #endif 153 154 #ifndef CERT_FIND_HAS_PRIVATE_KEY 155 #define CERT_FIND_HAS_PRIVATE_KEY (21 << CERT_COMPARE_SHIFT) 156 #endif 157 158 /* ALPN requires version 8.1 of the Windows SDK, which was 159 shipped with Visual Studio 2013, aka _MSC_VER 1800: 160 https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx 161 Or mingw-w64 9.0 or upper. 162 */ 163 #if (defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 9) || \ 164 (defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)) 165 #define HAS_ALPN_SCHANNEL 166 static bool s_win_has_alpn; 167 #endif 168 169 static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf, 170 struct Curl_easy *data, 171 const char *pinnedpubkey); 172 173 static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, 174 void *BufDataPtr, unsigned long BufByteSize) 175 { 176 buffer->cbBuffer = BufByteSize; 177 buffer->BufferType = BufType; 178 buffer->pvBuffer = BufDataPtr; 179 } 180 181 static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, 182 unsigned long NumArrElem) 183 { 184 desc->ulVersion = SECBUFFER_VERSION; 185 desc->pBuffers = BufArr; 186 desc->cBuffers = NumArrElem; 187 } 188 189 static CURLcode 190 schannel_set_ssl_version_min_max(DWORD *enabled_protocols, 191 struct Curl_cfilter *cf, 192 struct Curl_easy *data) 193 { 194 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 195 long ssl_version = conn_config->version; 196 long ssl_version_max = (long)conn_config->version_max; 197 long i = ssl_version; 198 199 switch(ssl_version_max) { 200 case CURL_SSLVERSION_MAX_NONE: 201 case CURL_SSLVERSION_MAX_DEFAULT: 202 203 /* Windows Server 2022 and newer (including Windows 11) support TLS 1.3 204 built-in. Previous builds of Windows 10 had broken TLS 1.3 205 implementations that could be enabled via registry. 206 */ 207 if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT, 208 VERSION_GREATER_THAN_EQUAL)) { 209 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3; 210 } 211 else /* Windows 10 and older */ 212 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; 213 214 break; 215 } 216 217 for(; i <= (ssl_version_max >> 16); ++i) { 218 switch(i) { 219 case CURL_SSLVERSION_TLSv1_0: 220 (*enabled_protocols) |= SP_PROT_TLS1_0_CLIENT; 221 break; 222 case CURL_SSLVERSION_TLSv1_1: 223 (*enabled_protocols) |= SP_PROT_TLS1_1_CLIENT; 224 break; 225 case CURL_SSLVERSION_TLSv1_2: 226 (*enabled_protocols) |= SP_PROT_TLS1_2_CLIENT; 227 break; 228 case CURL_SSLVERSION_TLSv1_3: 229 230 /* Windows Server 2022 and newer */ 231 if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT, 232 VERSION_GREATER_THAN_EQUAL)) { 233 (*enabled_protocols) |= SP_PROT_TLS1_3_CLIENT; 234 break; 235 } 236 else { /* Windows 10 and older */ 237 failf(data, "schannel: TLS 1.3 not supported on Windows prior to 11"); 238 return CURLE_SSL_CONNECT_ERROR; 239 } 240 } 241 } 242 return CURLE_OK; 243 } 244 245 #define CIPHEROPTION(x) {#x, x} 246 247 struct algo { 248 const char *name; 249 int id; 250 }; 251 252 static const struct algo algs[]= { 253 CIPHEROPTION(CALG_MD2), 254 CIPHEROPTION(CALG_MD4), 255 CIPHEROPTION(CALG_MD5), 256 CIPHEROPTION(CALG_SHA), 257 CIPHEROPTION(CALG_SHA1), 258 CIPHEROPTION(CALG_MAC), 259 CIPHEROPTION(CALG_RSA_SIGN), 260 CIPHEROPTION(CALG_DSS_SIGN), 261 /* ifdefs for the options that are defined conditionally in wincrypt.h */ 262 #ifdef CALG_NO_SIGN 263 CIPHEROPTION(CALG_NO_SIGN), 264 #endif 265 CIPHEROPTION(CALG_RSA_KEYX), 266 CIPHEROPTION(CALG_DES), 267 #ifdef CALG_3DES_112 268 CIPHEROPTION(CALG_3DES_112), 269 #endif 270 CIPHEROPTION(CALG_3DES), 271 CIPHEROPTION(CALG_DESX), 272 CIPHEROPTION(CALG_RC2), 273 CIPHEROPTION(CALG_RC4), 274 CIPHEROPTION(CALG_SEAL), 275 #ifdef CALG_DH_SF 276 CIPHEROPTION(CALG_DH_SF), 277 #endif 278 CIPHEROPTION(CALG_DH_EPHEM), 279 #ifdef CALG_AGREEDKEY_ANY 280 CIPHEROPTION(CALG_AGREEDKEY_ANY), 281 #endif 282 #ifdef CALG_HUGHES_MD5 283 CIPHEROPTION(CALG_HUGHES_MD5), 284 #endif 285 CIPHEROPTION(CALG_SKIPJACK), 286 #ifdef CALG_TEK 287 CIPHEROPTION(CALG_TEK), 288 #endif 289 CIPHEROPTION(CALG_CYLINK_MEK), 290 CIPHEROPTION(CALG_SSL3_SHAMD5), 291 #ifdef CALG_SSL3_MASTER 292 CIPHEROPTION(CALG_SSL3_MASTER), 293 #endif 294 #ifdef CALG_SCHANNEL_MASTER_HASH 295 CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH), 296 #endif 297 #ifdef CALG_SCHANNEL_MAC_KEY 298 CIPHEROPTION(CALG_SCHANNEL_MAC_KEY), 299 #endif 300 #ifdef CALG_SCHANNEL_ENC_KEY 301 CIPHEROPTION(CALG_SCHANNEL_ENC_KEY), 302 #endif 303 #ifdef CALG_PCT1_MASTER 304 CIPHEROPTION(CALG_PCT1_MASTER), 305 #endif 306 #ifdef CALG_SSL2_MASTER 307 CIPHEROPTION(CALG_SSL2_MASTER), 308 #endif 309 #ifdef CALG_TLS1_MASTER 310 CIPHEROPTION(CALG_TLS1_MASTER), 311 #endif 312 #ifdef CALG_RC5 313 CIPHEROPTION(CALG_RC5), 314 #endif 315 #ifdef CALG_HMAC 316 CIPHEROPTION(CALG_HMAC), 317 #endif 318 #ifdef CALG_TLS1PRF 319 CIPHEROPTION(CALG_TLS1PRF), 320 #endif 321 #ifdef CALG_HASH_REPLACE_OWF 322 CIPHEROPTION(CALG_HASH_REPLACE_OWF), 323 #endif 324 #ifdef CALG_AES_128 325 CIPHEROPTION(CALG_AES_128), 326 #endif 327 #ifdef CALG_AES_192 328 CIPHEROPTION(CALG_AES_192), 329 #endif 330 #ifdef CALG_AES_256 331 CIPHEROPTION(CALG_AES_256), 332 #endif 333 #ifdef CALG_AES 334 CIPHEROPTION(CALG_AES), 335 #endif 336 #ifdef CALG_SHA_256 337 CIPHEROPTION(CALG_SHA_256), 338 #endif 339 #ifdef CALG_SHA_384 340 CIPHEROPTION(CALG_SHA_384), 341 #endif 342 #ifdef CALG_SHA_512 343 CIPHEROPTION(CALG_SHA_512), 344 #endif 345 #ifdef CALG_ECDH 346 CIPHEROPTION(CALG_ECDH), 347 #endif 348 #ifdef CALG_ECMQV 349 CIPHEROPTION(CALG_ECMQV), 350 #endif 351 #ifdef CALG_ECDSA 352 CIPHEROPTION(CALG_ECDSA), 353 #endif 354 #ifdef CALG_ECDH_EPHEM 355 CIPHEROPTION(CALG_ECDH_EPHEM), 356 #endif 357 {NULL, 0}, 358 }; 359 360 static int 361 get_alg_id_by_name(const char *name) 362 { 363 const char *nameEnd = strchr(name, ':'); 364 size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name); 365 int i; 366 367 for(i = 0; algs[i].name; i++) { 368 if((n == strlen(algs[i].name) && !strncmp(algs[i].name, name, n))) 369 return algs[i].id; 370 } 371 return 0; /* not found */ 372 } 373 374 #define NUM_CIPHERS 47 /* There are 47 options listed above */ 375 376 static CURLcode 377 set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, 378 ALG_ID *algIds) 379 { 380 const char *startCur = ciphers; 381 int algCount = 0; 382 while(startCur && (0 != *startCur) && (algCount < NUM_CIPHERS)) { 383 curl_off_t alg; 384 if(curlx_str_number(&startCur, &alg, INT_MAX) || !alg) 385 alg = get_alg_id_by_name(startCur); 386 387 if(alg) 388 algIds[algCount++] = (ALG_ID)alg; 389 else if(!strncmp(startCur, "USE_STRONG_CRYPTO", 390 sizeof("USE_STRONG_CRYPTO") - 1) || 391 !strncmp(startCur, "SCH_USE_STRONG_CRYPTO", 392 sizeof("SCH_USE_STRONG_CRYPTO") - 1)) 393 schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO; 394 else 395 return CURLE_SSL_CIPHER; 396 startCur = strchr(startCur, ':'); 397 if(startCur) 398 startCur++; 399 } 400 schannel_cred->palgSupportedAlgs = algIds; 401 schannel_cred->cSupportedAlgs = (DWORD)algCount; 402 return CURLE_OK; 403 } 404 405 #ifdef HAS_CLIENT_CERT_PATH 406 407 /* Function allocates memory for store_path only if CURLE_OK is returned */ 408 static CURLcode 409 get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, 410 TCHAR **thumbprint) 411 { 412 TCHAR *sep; 413 TCHAR *store_path_start; 414 size_t store_name_len; 415 416 sep = _tcschr(path, TEXT('\\')); 417 if(!sep) 418 return CURLE_SSL_CERTPROBLEM; 419 420 store_name_len = sep - path; 421 422 if(_tcsncmp(path, TEXT("CurrentUser"), store_name_len) == 0) 423 *store_name = CERT_SYSTEM_STORE_CURRENT_USER; 424 else if(_tcsncmp(path, TEXT("LocalMachine"), store_name_len) == 0) 425 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE; 426 else if(_tcsncmp(path, TEXT("CurrentService"), store_name_len) == 0) 427 *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE; 428 else if(_tcsncmp(path, TEXT("Services"), store_name_len) == 0) 429 *store_name = CERT_SYSTEM_STORE_SERVICES; 430 else if(_tcsncmp(path, TEXT("Users"), store_name_len) == 0) 431 *store_name = CERT_SYSTEM_STORE_USERS; 432 else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"), 433 store_name_len) == 0) 434 *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; 435 else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"), 436 store_name_len) == 0) 437 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; 438 else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"), 439 store_name_len) == 0) 440 *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; 441 else 442 return CURLE_SSL_CERTPROBLEM; 443 444 store_path_start = sep + 1; 445 446 sep = _tcschr(store_path_start, TEXT('\\')); 447 if(!sep) 448 return CURLE_SSL_CERTPROBLEM; 449 450 *thumbprint = sep + 1; 451 if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) 452 return CURLE_SSL_CERTPROBLEM; 453 454 *sep = TEXT('\0'); 455 *store_path = _tcsdup(store_path_start); 456 *sep = TEXT('\\'); 457 if(!*store_path) 458 return CURLE_OUT_OF_MEMORY; 459 460 return CURLE_OK; 461 } 462 #endif 463 464 static CURLcode 465 schannel_acquire_credential_handle(struct Curl_cfilter *cf, 466 struct Curl_easy *data) 467 { 468 struct ssl_connect_data *connssl = cf->ctx; 469 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 470 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 471 472 #ifdef HAS_CLIENT_CERT_PATH 473 PCCERT_CONTEXT client_certs[1] = { NULL }; 474 HCERTSTORE client_cert_store = NULL; 475 #endif 476 SECURITY_STATUS sspi_status = SEC_E_OK; 477 CURLcode result; 478 479 /* setup Schannel API options */ 480 DWORD flags = 0; 481 DWORD enabled_protocols = 0; 482 483 struct schannel_ssl_backend_data *backend = 484 (struct schannel_ssl_backend_data *)(connssl->backend); 485 486 DEBUGASSERT(backend); 487 488 if(conn_config->verifypeer) { 489 #ifdef HAS_MANUAL_VERIFY_API 490 if(backend->use_manual_cred_validation) 491 flags = SCH_CRED_MANUAL_CRED_VALIDATION; 492 else 493 #endif 494 flags = SCH_CRED_AUTO_CRED_VALIDATION; 495 496 if(ssl_config->no_revoke) { 497 flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 498 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 499 500 DEBUGF(infof(data, "schannel: disabled server certificate revocation " 501 "checks")); 502 } 503 else if(ssl_config->revoke_best_effort) { 504 flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 505 SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; 506 507 DEBUGF(infof(data, "schannel: ignore revocation offline errors")); 508 } 509 else { 510 flags |= SCH_CRED_REVOCATION_CHECK_CHAIN; 511 512 DEBUGF(infof(data, 513 "schannel: checking server certificate revocation")); 514 } 515 } 516 else { 517 flags = SCH_CRED_MANUAL_CRED_VALIDATION | 518 SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 519 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 520 DEBUGF(infof(data, 521 "schannel: disabled server cert revocation checks")); 522 } 523 524 if(!conn_config->verifyhost) { 525 flags |= SCH_CRED_NO_SERVERNAME_CHECK; 526 DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " 527 "comparing the supplied target name with the subject " 528 "names in server certificates.")); 529 } 530 531 if(!ssl_config->auto_client_cert) { 532 flags &= ~(DWORD)SCH_CRED_USE_DEFAULT_CREDS; 533 flags |= SCH_CRED_NO_DEFAULT_CREDS; 534 infof(data, "schannel: disabled automatic use of client certificate"); 535 } 536 else 537 infof(data, "schannel: enabled automatic use of client certificate"); 538 539 switch(conn_config->version) { 540 case CURL_SSLVERSION_DEFAULT: 541 case CURL_SSLVERSION_TLSv1: 542 case CURL_SSLVERSION_TLSv1_0: 543 case CURL_SSLVERSION_TLSv1_1: 544 case CURL_SSLVERSION_TLSv1_2: 545 case CURL_SSLVERSION_TLSv1_3: 546 { 547 result = schannel_set_ssl_version_min_max(&enabled_protocols, cf, data); 548 if(result != CURLE_OK) 549 return result; 550 break; 551 } 552 case CURL_SSLVERSION_SSLv3: 553 case CURL_SSLVERSION_SSLv2: 554 failf(data, "SSL versions not supported"); 555 return CURLE_NOT_BUILT_IN; 556 default: 557 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 558 return CURLE_SSL_CONNECT_ERROR; 559 } 560 561 #ifdef HAS_CLIENT_CERT_PATH 562 /* client certificate */ 563 if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { 564 DWORD cert_store_name = 0; 565 TCHAR *cert_store_path = NULL; 566 TCHAR *cert_thumbprint_str = NULL; 567 CRYPT_HASH_BLOB cert_thumbprint; 568 BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; 569 HCERTSTORE cert_store = NULL; 570 FILE *fInCert = NULL; 571 void *certdata = NULL; 572 size_t certsize = 0; 573 bool blob = data->set.ssl.primary.cert_blob != NULL; 574 TCHAR *cert_path = NULL; 575 if(blob) { 576 certdata = data->set.ssl.primary.cert_blob->data; 577 certsize = data->set.ssl.primary.cert_blob->len; 578 } 579 else { 580 cert_path = curlx_convert_UTF8_to_tchar( 581 data->set.ssl.primary.clientcert); 582 if(!cert_path) 583 return CURLE_OUT_OF_MEMORY; 584 585 result = get_cert_location(cert_path, &cert_store_name, 586 &cert_store_path, &cert_thumbprint_str); 587 588 if(result && (data->set.ssl.primary.clientcert[0]!='\0')) 589 fInCert = fopen(data->set.ssl.primary.clientcert, "rb"); 590 591 if(result && !fInCert) { 592 failf(data, "schannel: Failed to get certificate location" 593 " or file for %s", 594 data->set.ssl.primary.clientcert); 595 curlx_unicodefree(cert_path); 596 return result; 597 } 598 } 599 600 if((fInCert || blob) && (data->set.ssl.cert_type) && 601 (!curl_strequal(data->set.ssl.cert_type, "P12"))) { 602 failf(data, "schannel: certificate format compatibility error " 603 " for %s", 604 blob ? "(memory blob)" : data->set.ssl.primary.clientcert); 605 curlx_unicodefree(cert_path); 606 return CURLE_SSL_CERTPROBLEM; 607 } 608 609 if(fInCert || blob) { 610 /* Reading a .P12 or .pfx file, like the example at bottom of 611 https://social.msdn.microsoft.com/Forums/windowsdesktop/ 612 en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 613 */ 614 CRYPT_DATA_BLOB datablob; 615 WCHAR* pszPassword; 616 size_t pwd_len = 0; 617 int str_w_len = 0; 618 int cert_find_flags; 619 const char *cert_showfilename_error = blob ? 620 "(memory blob)" : data->set.ssl.primary.clientcert; 621 curlx_unicodefree(cert_path); 622 if(fInCert) { 623 long cert_tell = 0; 624 bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0; 625 if(continue_reading) 626 cert_tell = ftell(fInCert); 627 if(cert_tell < 0) 628 continue_reading = FALSE; 629 else 630 certsize = (size_t)cert_tell; 631 if(continue_reading) 632 continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; 633 if(continue_reading) 634 certdata = malloc(certsize + 1); 635 if((!certdata) || 636 ((int) fread(certdata, certsize, 1, fInCert) != 1)) 637 continue_reading = FALSE; 638 fclose(fInCert); 639 if(!continue_reading) { 640 failf(data, "schannel: Failed to read cert file %s", 641 data->set.ssl.primary.clientcert); 642 free(certdata); 643 return CURLE_SSL_CERTPROBLEM; 644 } 645 } 646 647 /* Convert key-pair data to the in-memory certificate store */ 648 datablob.pbData = (BYTE*)certdata; 649 datablob.cbData = (DWORD)certsize; 650 651 if(data->set.ssl.key_passwd) 652 pwd_len = strlen(data->set.ssl.key_passwd); 653 pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1)); 654 if(pszPassword) { 655 if(pwd_len > 0) 656 str_w_len = MultiByteToWideChar(CP_UTF8, 657 MB_ERR_INVALID_CHARS, 658 data->set.ssl.key_passwd, 659 (int)pwd_len, 660 pszPassword, (int)(pwd_len + 1)); 661 662 if((str_w_len >= 0) && (str_w_len <= (int)pwd_len)) 663 pszPassword[str_w_len] = 0; 664 else 665 pszPassword[0] = 0; 666 667 if(Curl_isVistaOrGreater) 668 cert_store = PFXImportCertStore(&datablob, pszPassword, 669 PKCS12_NO_PERSIST_KEY); 670 else 671 cert_store = PFXImportCertStore(&datablob, pszPassword, 0); 672 673 free(pszPassword); 674 } 675 if(!blob) 676 free(certdata); 677 if(!cert_store) { 678 DWORD errorcode = GetLastError(); 679 if(errorcode == ERROR_INVALID_PASSWORD) 680 failf(data, "schannel: Failed to import cert file %s, " 681 "password is bad", 682 cert_showfilename_error); 683 else 684 failf(data, "schannel: Failed to import cert file %s, " 685 "last error is 0x%lx", 686 cert_showfilename_error, errorcode); 687 return CURLE_SSL_CERTPROBLEM; 688 } 689 690 /* CERT_FIND_HAS_PRIVATE_KEY is only available in Windows 8 / Server 691 2012, (NT v6.2). For earlier versions we use CURL_FIND_ANY. */ 692 if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT, 693 VERSION_GREATER_THAN_EQUAL)) 694 cert_find_flags = CERT_FIND_HAS_PRIVATE_KEY; 695 else 696 cert_find_flags = CERT_FIND_ANY; 697 698 client_certs[0] = CertFindCertificateInStore( 699 cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 700 cert_find_flags, NULL, NULL); 701 702 if(!client_certs[0]) { 703 failf(data, "schannel: Failed to get certificate from file %s" 704 ", last error is 0x%lx", 705 cert_showfilename_error, GetLastError()); 706 CertCloseStore(cert_store, 0); 707 return CURLE_SSL_CERTPROBLEM; 708 } 709 } 710 else { 711 cert_store = 712 CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, 713 (HCRYPTPROV)NULL, 714 CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, 715 cert_store_path); 716 if(!cert_store) { 717 char *path_utf8 = 718 curlx_convert_tchar_to_UTF8(cert_store_path); 719 failf(data, "schannel: Failed to open cert store %lx %s, " 720 "last error is 0x%lx", 721 cert_store_name, 722 (path_utf8 ? path_utf8 : "(unknown)"), 723 GetLastError()); 724 free(cert_store_path); 725 curlx_unicodefree(path_utf8); 726 curlx_unicodefree(cert_path); 727 return CURLE_SSL_CERTPROBLEM; 728 } 729 free(cert_store_path); 730 731 cert_thumbprint.pbData = cert_thumbprint_data; 732 cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; 733 734 if(!CryptStringToBinary(cert_thumbprint_str, 735 CERT_THUMBPRINT_STR_LEN, 736 CRYPT_STRING_HEX, 737 cert_thumbprint_data, 738 &cert_thumbprint.cbData, 739 NULL, NULL)) { 740 curlx_unicodefree(cert_path); 741 CertCloseStore(cert_store, 0); 742 return CURLE_SSL_CERTPROBLEM; 743 } 744 745 client_certs[0] = CertFindCertificateInStore( 746 cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 747 CERT_FIND_HASH, &cert_thumbprint, NULL); 748 749 curlx_unicodefree(cert_path); 750 751 if(!client_certs[0]) { 752 /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ 753 CertCloseStore(cert_store, 0); 754 return CURLE_SSL_CERTPROBLEM; 755 } 756 } 757 client_cert_store = cert_store; 758 } 759 #else 760 if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { 761 failf(data, "schannel: client cert support not built in"); 762 return CURLE_NOT_BUILT_IN; 763 } 764 #endif 765 766 /* allocate memory for the reusable credential handle */ 767 backend->cred = (struct Curl_schannel_cred *) 768 calloc(1, sizeof(struct Curl_schannel_cred)); 769 if(!backend->cred) { 770 failf(data, "schannel: unable to allocate memory"); 771 772 #ifdef HAS_CLIENT_CERT_PATH 773 if(client_certs[0]) 774 CertFreeCertificateContext(client_certs[0]); 775 if(client_cert_store) 776 CertCloseStore(client_cert_store, 0); 777 #endif 778 779 return CURLE_OUT_OF_MEMORY; 780 } 781 backend->cred->refcount = 1; 782 783 #ifdef HAS_CLIENT_CERT_PATH 784 /* Since we did not persist the key, we need to extend the store's 785 * lifetime until the end of the connection 786 */ 787 backend->cred->client_cert_store = client_cert_store; 788 #endif 789 790 /* We support TLS 1.3 starting in Windows 10 version 1809 (OS build 17763) as 791 long as the user did not set a legacy algorithm list 792 (CURLOPT_SSL_CIPHER_LIST). */ 793 if(!conn_config->cipher_list && 794 curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT, 795 VERSION_GREATER_THAN_EQUAL)) { 796 797 SCH_CREDENTIALS credentials = { 0 }; 798 TLS_PARAMETERS tls_parameters = { 0 }; 799 CRYPTO_SETTINGS crypto_settings[1] = { { 0 } }; 800 801 tls_parameters.pDisabledCrypto = crypto_settings; 802 803 /* The number of blocked suites */ 804 tls_parameters.cDisabledCrypto = (DWORD)0; 805 credentials.pTlsParameters = &tls_parameters; 806 credentials.cTlsParameters = 1; 807 808 credentials.dwVersion = SCH_CREDENTIALS_VERSION; 809 credentials.dwFlags = flags | SCH_USE_STRONG_CRYPTO; 810 811 credentials.pTlsParameters->grbitDisabledProtocols = 812 (DWORD)~enabled_protocols; 813 814 #ifdef HAS_CLIENT_CERT_PATH 815 if(client_certs[0]) { 816 credentials.cCreds = 1; 817 credentials.paCred = client_certs; 818 } 819 #endif 820 821 sspi_status = 822 Curl_pSecFn->AcquireCredentialsHandle(NULL, 823 (TCHAR *)CURL_UNCONST(UNISP_NAME), 824 SECPKG_CRED_OUTBOUND, NULL, 825 &credentials, NULL, NULL, 826 &backend->cred->cred_handle, 827 &backend->cred->time_stamp); 828 } 829 else { 830 /* Pre-Windows 10 1809 or the user set a legacy algorithm list. 831 Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ 832 ALG_ID algIds[NUM_CIPHERS]; 833 char *ciphers = conn_config->cipher_list; 834 SCHANNEL_CRED schannel_cred = { 0 }; 835 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; 836 schannel_cred.dwFlags = flags; 837 schannel_cred.grbitEnabledProtocols = enabled_protocols; 838 839 if(ciphers) { 840 if((enabled_protocols & SP_PROT_TLS1_3_CLIENT)) { 841 infof(data, "schannel: WARNING: This version of Schannel " 842 "negotiates a less-secure TLS version than TLS 1.3 because the " 843 "user set an algorithm cipher list."); 844 } 845 result = set_ssl_ciphers(&schannel_cred, ciphers, algIds); 846 if(CURLE_OK != result) { 847 failf(data, "schannel: Failed setting algorithm cipher list"); 848 return result; 849 } 850 } 851 else { 852 schannel_cred.dwFlags = flags | SCH_USE_STRONG_CRYPTO; 853 } 854 855 #ifdef HAS_CLIENT_CERT_PATH 856 if(client_certs[0]) { 857 schannel_cred.cCreds = 1; 858 schannel_cred.paCred = client_certs; 859 } 860 #endif 861 862 sspi_status = 863 Curl_pSecFn->AcquireCredentialsHandle(NULL, 864 (TCHAR *)CURL_UNCONST(UNISP_NAME), 865 SECPKG_CRED_OUTBOUND, NULL, 866 &schannel_cred, NULL, NULL, 867 &backend->cred->cred_handle, 868 &backend->cred->time_stamp); 869 } 870 871 #ifdef HAS_CLIENT_CERT_PATH 872 if(client_certs[0]) 873 CertFreeCertificateContext(client_certs[0]); 874 #endif 875 876 if(sspi_status != SEC_E_OK) { 877 char buffer[STRERROR_LEN]; 878 failf(data, "schannel: AcquireCredentialsHandle failed: %s", 879 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 880 Curl_safefree(backend->cred); 881 switch(sspi_status) { 882 case SEC_E_INSUFFICIENT_MEMORY: 883 return CURLE_OUT_OF_MEMORY; 884 case SEC_E_NO_CREDENTIALS: 885 case SEC_E_SECPKG_NOT_FOUND: 886 case SEC_E_NOT_OWNER: 887 case SEC_E_UNKNOWN_CREDENTIALS: 888 case SEC_E_INTERNAL_ERROR: 889 default: 890 return CURLE_SSL_CONNECT_ERROR; 891 } 892 } 893 894 return CURLE_OK; 895 } 896 897 static CURLcode 898 schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 899 { 900 size_t written = 0; 901 struct ssl_connect_data *connssl = cf->ctx; 902 struct schannel_ssl_backend_data *backend = 903 (struct schannel_ssl_backend_data *)connssl->backend; 904 #ifndef UNDER_CE 905 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 906 #endif 907 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 908 SecBuffer outbuf; 909 SecBufferDesc outbuf_desc; 910 SecBuffer inbuf; 911 SecBufferDesc inbuf_desc; 912 #ifdef HAS_ALPN_SCHANNEL 913 unsigned char alpn_buffer[128]; 914 #endif 915 SECURITY_STATUS sspi_status = SEC_E_OK; 916 CURLcode result; 917 918 DEBUGASSERT(backend); 919 DEBUGF(infof(data, 920 "schannel: SSL/TLS connection with %s port %d (step 1/3)", 921 connssl->peer.hostname, connssl->peer.port)); 922 923 if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT, 924 VERSION_LESS_THAN_EQUAL)) { 925 /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and 926 algorithms that may not be supported by all servers. */ 927 infof(data, "schannel: Windows version is old and may not be able to " 928 "connect to some servers due to lack of SNI, algorithms, etc."); 929 } 930 931 #ifdef HAS_ALPN_SCHANNEL 932 backend->use_alpn = connssl->alpn && s_win_has_alpn; 933 #else 934 backend->use_alpn = FALSE; 935 #endif 936 937 #ifdef UNDER_CE 938 #ifdef HAS_MANUAL_VERIFY_API 939 /* certificate validation on Windows CE does not seem to work right; we will 940 * do it following a more manual process. */ 941 backend->use_manual_cred_validation = TRUE; 942 #else 943 #error "compiler too old to support Windows CE requisite manual cert verify" 944 #endif 945 #else 946 #ifdef HAS_MANUAL_VERIFY_API 947 if(conn_config->CAfile || conn_config->ca_info_blob) { 948 if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT, 949 VERSION_GREATER_THAN_EQUAL)) { 950 backend->use_manual_cred_validation = TRUE; 951 } 952 else { 953 failf(data, "schannel: this version of Windows is too old to support " 954 "certificate verification via CA bundle file."); 955 return CURLE_SSL_CACERT_BADFILE; 956 } 957 } 958 else 959 backend->use_manual_cred_validation = FALSE; 960 #else 961 if(conn_config->CAfile || conn_config->ca_info_blob) { 962 failf(data, "schannel: CA cert support not built in"); 963 return CURLE_NOT_BUILT_IN; 964 } 965 #endif 966 #endif 967 968 backend->cred = NULL; 969 970 /* check for an existing reusable credential handle */ 971 if(ssl_config->primary.cache_session) { 972 struct Curl_schannel_cred *old_cred; 973 Curl_ssl_scache_lock(data); 974 old_cred = Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key); 975 if(old_cred) { 976 backend->cred = old_cred; 977 DEBUGF(infof(data, "schannel: reusing existing credential handle")); 978 979 /* increment the reference counter of the credential/session handle */ 980 backend->cred->refcount++; 981 DEBUGF(infof(data, 982 "schannel: incremented credential handle refcount = %d", 983 backend->cred->refcount)); 984 } 985 Curl_ssl_scache_unlock(data); 986 } 987 988 if(!backend->cred) { 989 char *snihost; 990 result = schannel_acquire_credential_handle(cf, data); 991 if(result || !backend->cred) 992 return result; 993 /* schannel_acquire_credential_handle() sets backend->cred accordingly or 994 it returns error otherwise. */ 995 996 /* A hostname associated with the credential is needed by 997 InitializeSecurityContext for SNI and other reasons. */ 998 snihost = connssl->peer.sni ? connssl->peer.sni : connssl->peer.hostname; 999 backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost); 1000 if(!backend->cred->sni_hostname) 1001 return CURLE_OUT_OF_MEMORY; 1002 } 1003 1004 /* Warn if SNI is disabled due to use of an IP address */ 1005 if(connssl->peer.type != CURL_SSL_PEER_DNS) { 1006 infof(data, "schannel: using IP address, SNI is not supported by OS."); 1007 } 1008 1009 #ifdef HAS_ALPN_SCHANNEL 1010 if(backend->use_alpn) { 1011 int cur = 0; 1012 int list_start_index = 0; 1013 unsigned int *extension_len = NULL; 1014 unsigned short* list_len = NULL; 1015 struct alpn_proto_buf proto; 1016 1017 /* The first four bytes will be an unsigned int indicating number 1018 of bytes of data in the rest of the buffer. */ 1019 extension_len = (unsigned int *)(void *)(&alpn_buffer[cur]); 1020 cur += (int)sizeof(unsigned int); 1021 1022 /* The next four bytes are an indicator that this buffer will contain 1023 ALPN data, as opposed to NPN, for example. */ 1024 *(unsigned int *)(void *)&alpn_buffer[cur] = 1025 SecApplicationProtocolNegotiationExt_ALPN; 1026 cur += (int)sizeof(unsigned int); 1027 1028 /* The next two bytes will be an unsigned short indicating the number 1029 of bytes used to list the preferred protocols. */ 1030 list_len = (unsigned short*)(void *)(&alpn_buffer[cur]); 1031 cur += (int)sizeof(unsigned short); 1032 1033 list_start_index = cur; 1034 1035 result = Curl_alpn_to_proto_buf(&proto, connssl->alpn); 1036 if(result) { 1037 failf(data, "Error setting ALPN"); 1038 return CURLE_SSL_CONNECT_ERROR; 1039 } 1040 memcpy(&alpn_buffer[cur], proto.data, proto.len); 1041 cur += proto.len; 1042 1043 *list_len = curlx_uitous(cur - list_start_index); 1044 *extension_len = (unsigned int)(*list_len + 1045 sizeof(unsigned int) + sizeof(unsigned short)); 1046 1047 InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); 1048 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 1049 1050 Curl_alpn_to_proto_str(&proto, connssl->alpn); 1051 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 1052 } 1053 else { 1054 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 1055 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 1056 } 1057 #else /* HAS_ALPN_SCHANNEL */ 1058 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 1059 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 1060 #endif 1061 1062 /* setup output buffer */ 1063 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 1064 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 1065 1066 /* security request flags */ 1067 backend->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | 1068 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | 1069 ISC_REQ_STREAM; 1070 1071 if(!ssl_config->auto_client_cert) { 1072 backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; 1073 } 1074 1075 /* allocate memory for the security context handle */ 1076 backend->ctxt = (struct Curl_schannel_ctxt *) 1077 calloc(1, sizeof(struct Curl_schannel_ctxt)); 1078 if(!backend->ctxt) { 1079 failf(data, "schannel: unable to allocate memory"); 1080 return CURLE_OUT_OF_MEMORY; 1081 } 1082 1083 /* Schannel InitializeSecurityContext: 1084 https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx 1085 1086 At the moment we do not pass inbuf unless we are using ALPN since we only 1087 use it for that, and WINE (for which we currently disable ALPN) is giving 1088 us problems with inbuf regardless. https://github.com/curl/curl/issues/983 1089 */ 1090 sspi_status = Curl_pSecFn->InitializeSecurityContext( 1091 &backend->cred->cred_handle, NULL, backend->cred->sni_hostname, 1092 backend->req_flags, 0, 0, 1093 (backend->use_alpn ? &inbuf_desc : NULL), 1094 0, &backend->ctxt->ctxt_handle, 1095 &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp); 1096 1097 if(sspi_status != SEC_I_CONTINUE_NEEDED) { 1098 char buffer[STRERROR_LEN]; 1099 Curl_safefree(backend->ctxt); 1100 switch(sspi_status) { 1101 case SEC_E_INSUFFICIENT_MEMORY: 1102 failf(data, "schannel: initial InitializeSecurityContext failed: %s", 1103 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1104 return CURLE_OUT_OF_MEMORY; 1105 case SEC_E_WRONG_PRINCIPAL: 1106 failf(data, "schannel: SNI or certificate check failed: %s", 1107 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1108 return CURLE_PEER_FAILED_VERIFICATION; 1109 /* 1110 case SEC_E_INVALID_HANDLE: 1111 case SEC_E_INVALID_TOKEN: 1112 case SEC_E_LOGON_DENIED: 1113 case SEC_E_TARGET_UNKNOWN: 1114 case SEC_E_NO_AUTHENTICATING_AUTHORITY: 1115 case SEC_E_INTERNAL_ERROR: 1116 case SEC_E_NO_CREDENTIALS: 1117 case SEC_E_UNSUPPORTED_FUNCTION: 1118 case SEC_E_APPLICATION_PROTOCOL_MISMATCH: 1119 */ 1120 default: 1121 failf(data, "schannel: initial InitializeSecurityContext failed: %s", 1122 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1123 return CURLE_SSL_CONNECT_ERROR; 1124 } 1125 } 1126 1127 DEBUGF(infof(data, "schannel: sending initial handshake data: " 1128 "sending %lu bytes.", outbuf.cbBuffer)); 1129 1130 /* send initial handshake data which is now stored in output buffer */ 1131 result = Curl_conn_cf_send(cf->next, data, 1132 outbuf.pvBuffer, outbuf.cbBuffer, FALSE, 1133 &written); 1134 Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 1135 if((result != CURLE_OK) || (outbuf.cbBuffer != written)) { 1136 failf(data, "schannel: failed to send initial handshake data: " 1137 "sent %zu of %lu bytes", written, outbuf.cbBuffer); 1138 return CURLE_SSL_CONNECT_ERROR; 1139 } 1140 1141 DEBUGF(infof(data, "schannel: sent initial handshake data: " 1142 "sent %zu bytes", written)); 1143 1144 backend->recv_unrecoverable_err = CURLE_OK; 1145 backend->recv_sspi_close_notify = FALSE; 1146 backend->recv_connection_closed = FALSE; 1147 backend->recv_renegotiating = FALSE; 1148 backend->encdata_is_incomplete = FALSE; 1149 1150 /* continue to second handshake step */ 1151 connssl->connecting_state = ssl_connect_2; 1152 1153 return CURLE_OK; 1154 } 1155 1156 static CURLcode 1157 schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) 1158 { 1159 struct ssl_connect_data *connssl = cf->ctx; 1160 struct schannel_ssl_backend_data *backend = 1161 (struct schannel_ssl_backend_data *)connssl->backend; 1162 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 1163 int i; 1164 size_t nread = 0, written = 0; 1165 unsigned char *reallocated_buffer; 1166 SecBuffer outbuf[3]; 1167 SecBufferDesc outbuf_desc; 1168 SecBuffer inbuf[2]; 1169 SecBufferDesc inbuf_desc; 1170 SECURITY_STATUS sspi_status = SEC_E_OK; 1171 CURLcode result; 1172 bool doread; 1173 const char *pubkey_ptr; 1174 1175 DEBUGASSERT(backend); 1176 1177 doread = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ? FALSE : TRUE; 1178 connssl->io_need = CURL_SSL_IO_NEED_NONE; 1179 1180 DEBUGF(infof(data, 1181 "schannel: SSL/TLS connection with %s port %d (step 2/3)", 1182 connssl->peer.hostname, connssl->peer.port)); 1183 1184 if(!backend->cred || !backend->ctxt) 1185 return CURLE_SSL_CONNECT_ERROR; 1186 1187 /* buffer to store previously received and decrypted data */ 1188 if(!backend->decdata_buffer) { 1189 backend->decdata_offset = 0; 1190 backend->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 1191 backend->decdata_buffer = malloc(backend->decdata_length); 1192 if(!backend->decdata_buffer) { 1193 failf(data, "schannel: unable to allocate memory"); 1194 return CURLE_OUT_OF_MEMORY; 1195 } 1196 } 1197 1198 /* buffer to store previously received and encrypted data */ 1199 if(!backend->encdata_buffer) { 1200 backend->encdata_is_incomplete = FALSE; 1201 backend->encdata_offset = 0; 1202 backend->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 1203 backend->encdata_buffer = malloc(backend->encdata_length); 1204 if(!backend->encdata_buffer) { 1205 failf(data, "schannel: unable to allocate memory"); 1206 return CURLE_OUT_OF_MEMORY; 1207 } 1208 } 1209 1210 /* if we need a bigger buffer to read a full message, increase buffer now */ 1211 if(backend->encdata_length - backend->encdata_offset < 1212 CURL_SCHANNEL_BUFFER_FREE_SIZE) { 1213 /* increase internal encrypted data buffer */ 1214 size_t reallocated_length = backend->encdata_offset + 1215 CURL_SCHANNEL_BUFFER_FREE_SIZE; 1216 reallocated_buffer = realloc(backend->encdata_buffer, 1217 reallocated_length); 1218 1219 if(!reallocated_buffer) { 1220 failf(data, "schannel: unable to re-allocate memory"); 1221 return CURLE_OUT_OF_MEMORY; 1222 } 1223 else { 1224 backend->encdata_buffer = reallocated_buffer; 1225 backend->encdata_length = reallocated_length; 1226 } 1227 } 1228 1229 for(;;) { 1230 if(doread) { 1231 /* read encrypted handshake data from socket */ 1232 result = Curl_conn_cf_recv(cf->next, data, 1233 (char *) (backend->encdata_buffer + 1234 backend->encdata_offset), 1235 backend->encdata_length - 1236 backend->encdata_offset, 1237 &nread); 1238 if(result == CURLE_AGAIN) { 1239 connssl->io_need = CURL_SSL_IO_NEED_RECV; 1240 DEBUGF(infof(data, "schannel: failed to receive handshake, " 1241 "need more data")); 1242 return CURLE_OK; 1243 } 1244 else if((result != CURLE_OK) || (nread == 0)) { 1245 failf(data, "schannel: failed to receive handshake, " 1246 "SSL/TLS connection failed"); 1247 return CURLE_SSL_CONNECT_ERROR; 1248 } 1249 1250 /* increase encrypted data buffer offset */ 1251 backend->encdata_offset += nread; 1252 backend->encdata_is_incomplete = FALSE; 1253 SCH_DEV(infof(data, "schannel: encrypted data got %zu", nread)); 1254 } 1255 1256 SCH_DEV(infof(data, 1257 "schannel: encrypted data buffer: offset %zu length %zu", 1258 backend->encdata_offset, backend->encdata_length)); 1259 1260 /* setup input buffers */ 1261 InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(backend->encdata_offset), 1262 curlx_uztoul(backend->encdata_offset)); 1263 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 1264 InitSecBufferDesc(&inbuf_desc, inbuf, 2); 1265 1266 /* setup output buffers */ 1267 InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); 1268 InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); 1269 InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); 1270 InitSecBufferDesc(&outbuf_desc, outbuf, 3); 1271 1272 if(!inbuf[0].pvBuffer) { 1273 failf(data, "schannel: unable to allocate memory"); 1274 return CURLE_OUT_OF_MEMORY; 1275 } 1276 1277 /* copy received handshake data into input buffer */ 1278 memcpy(inbuf[0].pvBuffer, backend->encdata_buffer, 1279 backend->encdata_offset); 1280 1281 sspi_status = Curl_pSecFn->InitializeSecurityContext( 1282 &backend->cred->cred_handle, &backend->ctxt->ctxt_handle, 1283 backend->cred->sni_hostname, backend->req_flags, 1284 0, 0, &inbuf_desc, 0, NULL, 1285 &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp); 1286 1287 /* free buffer for received handshake data */ 1288 Curl_safefree(inbuf[0].pvBuffer); 1289 1290 /* check if the handshake was incomplete */ 1291 if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 1292 backend->encdata_is_incomplete = TRUE; 1293 connssl->io_need = CURL_SSL_IO_NEED_RECV; 1294 DEBUGF(infof(data, 1295 "schannel: received incomplete message, need more data")); 1296 return CURLE_OK; 1297 } 1298 1299 /* If the server has requested a client certificate, attempt to continue 1300 the handshake without one. This will allow connections to servers which 1301 request a client certificate but do not require it. */ 1302 if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && 1303 !(backend->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { 1304 backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; 1305 connssl->io_need = CURL_SSL_IO_NEED_SEND; 1306 DEBUGF(infof(data, 1307 "schannel: a client certificate has been requested")); 1308 return CURLE_OK; 1309 } 1310 1311 /* check if the handshake needs to be continued */ 1312 if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { 1313 for(i = 0; i < 3; i++) { 1314 /* search for handshake tokens that need to be send */ 1315 if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { 1316 DEBUGF(infof(data, "schannel: sending next handshake data: " 1317 "sending %lu bytes.", outbuf[i].cbBuffer)); 1318 1319 /* send handshake token to server */ 1320 result = Curl_conn_cf_send(cf->next, data, 1321 outbuf[i].pvBuffer, outbuf[i].cbBuffer, 1322 FALSE, &written); 1323 if((result != CURLE_OK) || 1324 (outbuf[i].cbBuffer != written)) { 1325 failf(data, "schannel: failed to send next handshake data: " 1326 "sent %zu of %lu bytes", written, outbuf[i].cbBuffer); 1327 return CURLE_SSL_CONNECT_ERROR; 1328 } 1329 } 1330 1331 /* free obsolete buffer */ 1332 if(outbuf[i].pvBuffer) { 1333 Curl_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); 1334 } 1335 } 1336 } 1337 else { 1338 char buffer[STRERROR_LEN]; 1339 switch(sspi_status) { 1340 case SEC_E_INSUFFICIENT_MEMORY: 1341 failf(data, "schannel: next InitializeSecurityContext failed: %s", 1342 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1343 return CURLE_OUT_OF_MEMORY; 1344 case SEC_E_WRONG_PRINCIPAL: 1345 failf(data, "schannel: SNI or certificate check failed: %s", 1346 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1347 return CURLE_PEER_FAILED_VERIFICATION; 1348 case SEC_E_UNTRUSTED_ROOT: 1349 failf(data, "schannel: %s", 1350 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1351 return CURLE_PEER_FAILED_VERIFICATION; 1352 /* 1353 case SEC_E_INVALID_HANDLE: 1354 case SEC_E_INVALID_TOKEN: 1355 case SEC_E_LOGON_DENIED: 1356 case SEC_E_TARGET_UNKNOWN: 1357 case SEC_E_NO_AUTHENTICATING_AUTHORITY: 1358 case SEC_E_INTERNAL_ERROR: 1359 case SEC_E_NO_CREDENTIALS: 1360 case SEC_E_UNSUPPORTED_FUNCTION: 1361 case SEC_E_APPLICATION_PROTOCOL_MISMATCH: 1362 */ 1363 default: 1364 failf(data, "schannel: next InitializeSecurityContext failed: %s", 1365 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 1366 return CURLE_SSL_CONNECT_ERROR; 1367 } 1368 } 1369 1370 /* check if there was additional remaining encrypted data */ 1371 if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { 1372 SCH_DEV(infof(data, "schannel: encrypted data length: %lu", 1373 inbuf[1].cbBuffer)); 1374 /* 1375 There are two cases where we could be getting extra data here: 1376 1) If we are renegotiating a connection and the handshake is already 1377 complete (from the server perspective), it can encrypted app data 1378 (not handshake data) in an extra buffer at this point. 1379 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a 1380 connection and this extra data is part of the handshake. 1381 We should process the data immediately; waiting for the socket to 1382 be ready may fail since the server is done sending handshake data. 1383 */ 1384 /* check if the remaining data is less than the total amount 1385 and therefore begins after the already processed data */ 1386 if(backend->encdata_offset > inbuf[1].cbBuffer) { 1387 memmove(backend->encdata_buffer, 1388 (backend->encdata_buffer + backend->encdata_offset) - 1389 inbuf[1].cbBuffer, inbuf[1].cbBuffer); 1390 backend->encdata_offset = inbuf[1].cbBuffer; 1391 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 1392 doread = FALSE; 1393 continue; 1394 } 1395 } 1396 } 1397 else { 1398 backend->encdata_offset = 0; 1399 } 1400 break; 1401 } 1402 1403 /* check if the handshake needs to be continued */ 1404 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 1405 connssl->io_need = CURL_SSL_IO_NEED_RECV; 1406 return CURLE_OK; 1407 } 1408 1409 /* check if the handshake is complete */ 1410 if(sspi_status == SEC_E_OK) { 1411 connssl->connecting_state = ssl_connect_3; 1412 DEBUGF(infof(data, "schannel: SSL/TLS handshake complete")); 1413 } 1414 1415 #ifndef CURL_DISABLE_PROXY 1416 pubkey_ptr = Curl_ssl_cf_is_proxy(cf) ? 1417 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : 1418 data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 1419 #else 1420 pubkey_ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 1421 #endif 1422 if(pubkey_ptr) { 1423 result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr); 1424 if(result) { 1425 failf(data, "SSL: public key does not match pinned public key"); 1426 return result; 1427 } 1428 } 1429 1430 #ifdef HAS_MANUAL_VERIFY_API 1431 if(conn_config->verifypeer && backend->use_manual_cred_validation) { 1432 /* Certificate verification also verifies the hostname if verifyhost */ 1433 return Curl_verify_certificate(cf, data); 1434 } 1435 #endif 1436 1437 /* Verify the hostname manually when certificate verification is disabled, 1438 because in that case Schannel will not verify it. */ 1439 if(!conn_config->verifypeer && conn_config->verifyhost) 1440 return Curl_verify_host(cf, data); 1441 1442 return CURLE_OK; 1443 } 1444 1445 static bool 1446 valid_cert_encoding(const CERT_CONTEXT *cert_context) 1447 { 1448 return (cert_context != NULL) && 1449 ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && 1450 (cert_context->pbCertEncoded != NULL) && 1451 (cert_context->cbCertEncoded > 0); 1452 } 1453 1454 typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, 1455 bool reverse_order, void *arg); 1456 1457 static void 1458 traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, 1459 void *arg) 1460 { 1461 const CERT_CONTEXT *current_context = NULL; 1462 bool should_continue = TRUE; 1463 bool first = TRUE; 1464 bool reverse_order = FALSE; 1465 while(should_continue && 1466 (current_context = CertEnumCertificatesInStore( 1467 context->hCertStore, 1468 current_context)) != NULL) { 1469 /* Windows 11 22H2 OS Build 22621.674 or higher enumerates certificates in 1470 leaf-to-root order while all previous versions of Windows enumerate 1471 certificates in root-to-leaf order. Determine the order of enumeration 1472 by comparing SECPKG_ATTR_REMOTE_CERT_CONTEXT's pbCertContext with the 1473 first certificate's pbCertContext. */ 1474 if(first && context->pbCertEncoded != current_context->pbCertEncoded) 1475 reverse_order = TRUE; 1476 should_continue = func(current_context, reverse_order, arg); 1477 first = FALSE; 1478 } 1479 1480 if(current_context) 1481 CertFreeCertificateContext(current_context); 1482 } 1483 1484 static bool 1485 cert_counter_callback(const CERT_CONTEXT *ccert_context, bool reverse_order, 1486 void *certs_count) 1487 { 1488 (void)reverse_order; /* unused */ 1489 if(valid_cert_encoding(ccert_context)) 1490 (*(int *)certs_count)++; 1491 return TRUE; 1492 } 1493 1494 struct Adder_args 1495 { 1496 struct Curl_easy *data; 1497 CURLcode result; 1498 int idx; 1499 int certs_count; 1500 }; 1501 1502 static bool 1503 add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, bool reverse_order, 1504 void *raw_arg) 1505 { 1506 struct Adder_args *args = (struct Adder_args*)raw_arg; 1507 args->result = CURLE_OK; 1508 if(valid_cert_encoding(ccert_context)) { 1509 const char *beg = (const char *) ccert_context->pbCertEncoded; 1510 const char *end = beg + ccert_context->cbCertEncoded; 1511 int insert_index = reverse_order ? (args->certs_count - 1) - args->idx : 1512 args->idx; 1513 args->result = Curl_extract_certinfo(args->data, insert_index, 1514 beg, end); 1515 args->idx++; 1516 } 1517 return args->result == CURLE_OK; 1518 } 1519 1520 static void schannel_session_free(void *sessionid) 1521 { 1522 /* this is expected to be called under sessionid lock */ 1523 struct Curl_schannel_cred *cred = sessionid; 1524 1525 if(cred) { 1526 cred->refcount--; 1527 if(cred->refcount == 0) { 1528 Curl_pSecFn->FreeCredentialsHandle(&cred->cred_handle); 1529 curlx_unicodefree(cred->sni_hostname); 1530 #ifdef HAS_CLIENT_CERT_PATH 1531 if(cred->client_cert_store) { 1532 CertCloseStore(cred->client_cert_store, 0); 1533 cred->client_cert_store = NULL; 1534 } 1535 #endif 1536 Curl_safefree(cred); 1537 } 1538 } 1539 } 1540 1541 static CURLcode 1542 schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) 1543 { 1544 struct ssl_connect_data *connssl = cf->ctx; 1545 struct schannel_ssl_backend_data *backend = 1546 (struct schannel_ssl_backend_data *)connssl->backend; 1547 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 1548 CURLcode result = CURLE_OK; 1549 SECURITY_STATUS sspi_status = SEC_E_OK; 1550 CERT_CONTEXT *ccert_context = NULL; 1551 #ifdef HAS_ALPN_SCHANNEL 1552 SecPkgContext_ApplicationProtocol alpn_result; 1553 #endif 1554 1555 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 1556 DEBUGASSERT(backend); 1557 1558 DEBUGF(infof(data, 1559 "schannel: SSL/TLS connection with %s port %d (step 3/3)", 1560 connssl->peer.hostname, connssl->peer.port)); 1561 1562 if(!backend->cred) 1563 return CURLE_SSL_CONNECT_ERROR; 1564 1565 /* check if the required context attributes are met */ 1566 if(backend->ret_flags != backend->req_flags) { 1567 if(!(backend->ret_flags & ISC_RET_SEQUENCE_DETECT)) 1568 failf(data, "schannel: failed to setup sequence detection"); 1569 if(!(backend->ret_flags & ISC_RET_REPLAY_DETECT)) 1570 failf(data, "schannel: failed to setup replay detection"); 1571 if(!(backend->ret_flags & ISC_RET_CONFIDENTIALITY)) 1572 failf(data, "schannel: failed to setup confidentiality"); 1573 if(!(backend->ret_flags & ISC_RET_ALLOCATED_MEMORY)) 1574 failf(data, "schannel: failed to setup memory allocation"); 1575 if(!(backend->ret_flags & ISC_RET_STREAM)) 1576 failf(data, "schannel: failed to setup stream orientation"); 1577 return CURLE_SSL_CONNECT_ERROR; 1578 } 1579 1580 #ifdef HAS_ALPN_SCHANNEL 1581 if(backend->use_alpn) { 1582 sspi_status = 1583 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, 1584 SECPKG_ATTR_APPLICATION_PROTOCOL, 1585 &alpn_result); 1586 1587 if(sspi_status != SEC_E_OK) { 1588 failf(data, "schannel: failed to retrieve ALPN result"); 1589 return CURLE_SSL_CONNECT_ERROR; 1590 } 1591 1592 if(alpn_result.ProtoNegoStatus == 1593 SecApplicationProtocolNegotiationStatus_Success) { 1594 unsigned char prev_alpn = cf->conn->alpn; 1595 1596 Curl_alpn_set_negotiated(cf, data, connssl, alpn_result.ProtocolId, 1597 alpn_result.ProtocolIdSize); 1598 if(backend->recv_renegotiating) { 1599 if(prev_alpn != cf->conn->alpn && 1600 prev_alpn != CURL_HTTP_VERSION_NONE) { 1601 /* Renegotiation selected a different protocol now, we cannot 1602 * deal with this */ 1603 failf(data, "schannel: server selected an ALPN protocol too late"); 1604 return CURLE_SSL_CONNECT_ERROR; 1605 } 1606 } 1607 } 1608 else { 1609 if(!backend->recv_renegotiating) 1610 Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0); 1611 } 1612 } 1613 #endif 1614 1615 /* save the current session data for possible reuse */ 1616 if(ssl_config->primary.cache_session) { 1617 Curl_ssl_scache_lock(data); 1618 /* Up ref count since call takes ownership */ 1619 backend->cred->refcount++; 1620 result = Curl_ssl_scache_add_obj(cf, data, connssl->peer.scache_key, 1621 backend->cred, schannel_session_free); 1622 Curl_ssl_scache_unlock(data); 1623 if(result) 1624 return result; 1625 } 1626 1627 if(data->set.ssl.certinfo) { 1628 int certs_count = 0; 1629 sspi_status = 1630 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, 1631 SECPKG_ATTR_REMOTE_CERT_CONTEXT, 1632 &ccert_context); 1633 1634 if((sspi_status != SEC_E_OK) || !ccert_context) { 1635 failf(data, "schannel: failed to retrieve remote cert context"); 1636 return CURLE_PEER_FAILED_VERIFICATION; 1637 } 1638 1639 traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); 1640 1641 result = Curl_ssl_init_certinfo(data, certs_count); 1642 if(!result) { 1643 struct Adder_args args; 1644 args.data = data; 1645 args.idx = 0; 1646 args.certs_count = certs_count; 1647 args.result = CURLE_OK; 1648 traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); 1649 result = args.result; 1650 } 1651 CertFreeCertificateContext(ccert_context); 1652 if(result) 1653 return result; 1654 } 1655 1656 connssl->connecting_state = ssl_connect_done; 1657 1658 return CURLE_OK; 1659 } 1660 1661 static CURLcode schannel_connect(struct Curl_cfilter *cf, 1662 struct Curl_easy *data, 1663 bool *done) 1664 { 1665 struct ssl_connect_data *connssl = cf->ctx; 1666 CURLcode result; 1667 1668 /* check if the connection has already been established */ 1669 if(ssl_connection_complete == connssl->state) { 1670 *done = TRUE; 1671 return CURLE_OK; 1672 } 1673 1674 *done = FALSE; 1675 1676 if(ssl_connect_1 == connssl->connecting_state) { 1677 result = schannel_connect_step1(cf, data); 1678 if(result) 1679 return result; 1680 } 1681 1682 if(ssl_connect_2 == connssl->connecting_state) { 1683 result = schannel_connect_step2(cf, data); 1684 if(result) 1685 return result; 1686 } 1687 1688 if(ssl_connect_3 == connssl->connecting_state) { 1689 result = schannel_connect_step3(cf, data); 1690 if(result) 1691 return result; 1692 } 1693 1694 if(ssl_connect_done == connssl->connecting_state) { 1695 connssl->state = ssl_connection_complete; 1696 1697 #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS 1698 /* When SSPI is used in combination with Schannel 1699 * we need the Schannel context to create the Schannel 1700 * binding to pass the IIS extended protection checks. 1701 * Available on Windows 7 or later. 1702 */ 1703 { 1704 struct schannel_ssl_backend_data *backend = 1705 (struct schannel_ssl_backend_data *)connssl->backend; 1706 DEBUGASSERT(backend); 1707 cf->conn->sslContext = &backend->ctxt->ctxt_handle; 1708 } 1709 #endif 1710 1711 *done = TRUE; 1712 } 1713 1714 return CURLE_OK; 1715 } 1716 1717 static CURLcode 1718 schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, 1719 const void *buf, size_t len, size_t *pnwritten) 1720 { 1721 size_t data_len = 0; 1722 unsigned char *ptr = NULL; 1723 struct ssl_connect_data *connssl = cf->ctx; 1724 SecBuffer outbuf[4]; 1725 SecBufferDesc outbuf_desc; 1726 SECURITY_STATUS sspi_status = SEC_E_OK; 1727 CURLcode result = CURLE_OK; 1728 struct schannel_ssl_backend_data *backend = 1729 (struct schannel_ssl_backend_data *)connssl->backend; 1730 1731 DEBUGASSERT(backend); 1732 *pnwritten = 0; 1733 1734 /* check if the maximum stream sizes were queried */ 1735 if(backend->stream_sizes.cbMaximumMessage == 0) { 1736 sspi_status = Curl_pSecFn->QueryContextAttributes( 1737 &backend->ctxt->ctxt_handle, 1738 SECPKG_ATTR_STREAM_SIZES, 1739 &backend->stream_sizes); 1740 if(sspi_status != SEC_E_OK) { 1741 return CURLE_SEND_ERROR; 1742 } 1743 } 1744 1745 /* check if the buffer is longer than the maximum message length */ 1746 if(len > backend->stream_sizes.cbMaximumMessage) { 1747 len = backend->stream_sizes.cbMaximumMessage; 1748 } 1749 1750 /* calculate the complete message length and allocate a buffer for it */ 1751 data_len = backend->stream_sizes.cbHeader + len + 1752 backend->stream_sizes.cbTrailer; 1753 ptr = (unsigned char *) malloc(data_len); 1754 if(!ptr) { 1755 return CURLE_OUT_OF_MEMORY; 1756 } 1757 1758 /* setup output buffers (header, data, trailer, empty) */ 1759 InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, 1760 ptr, backend->stream_sizes.cbHeader); 1761 InitSecBuffer(&outbuf[1], SECBUFFER_DATA, 1762 ptr + backend->stream_sizes.cbHeader, curlx_uztoul(len)); 1763 InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, 1764 ptr + backend->stream_sizes.cbHeader + len, 1765 backend->stream_sizes.cbTrailer); 1766 InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); 1767 InitSecBufferDesc(&outbuf_desc, outbuf, 4); 1768 1769 /* copy data into output buffer */ 1770 memcpy(outbuf[1].pvBuffer, buf, len); 1771 1772 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ 1773 sspi_status = Curl_pSecFn->EncryptMessage(&backend->ctxt->ctxt_handle, 0, 1774 &outbuf_desc, 0); 1775 1776 /* check if the message was encrypted */ 1777 if(sspi_status == SEC_E_OK) { 1778 1779 /* send the encrypted message including header, data and trailer */ 1780 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; 1781 1782 /* 1783 it is important to send the full message which includes the header, 1784 encrypted payload, and trailer. Until the client receives all the 1785 data a coherent message has not been delivered and the client 1786 cannot read any of it. 1787 1788 If we wanted to buffer the unwritten encrypted bytes, we would 1789 tell the client that all data it has requested to be sent has been 1790 sent. The unwritten encrypted bytes would be the first bytes to 1791 send on the next invocation. 1792 Here's the catch with this - if we tell the client that all the 1793 bytes have been sent, will the client call this method again to 1794 send the buffered data? Looking at who calls this function, it 1795 seems the answer is NO. 1796 */ 1797 1798 /* send entire message or fail */ 1799 while(len > *pnwritten) { 1800 size_t this_write = 0; 1801 int what; 1802 timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE); 1803 if(timeout_ms < 0) { 1804 /* we already got the timeout */ 1805 failf(data, "schannel: timed out sending data " 1806 "(bytes sent: %zu)", *pnwritten); 1807 result = CURLE_OPERATION_TIMEDOUT; 1808 break; 1809 } 1810 else if(!timeout_ms) 1811 timeout_ms = TIMEDIFF_T_MAX; 1812 what = SOCKET_WRITABLE(Curl_conn_cf_get_socket(cf, data), timeout_ms); 1813 if(what < 0) { 1814 /* fatal error */ 1815 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1816 result = CURLE_SEND_ERROR; 1817 break; 1818 } 1819 else if(0 == what) { 1820 failf(data, "schannel: timed out sending data " 1821 "(bytes sent: %zu)", *pnwritten); 1822 result = CURLE_OPERATION_TIMEDOUT; 1823 break; 1824 } 1825 /* socket is writable */ 1826 1827 result = Curl_conn_cf_send(cf->next, data, 1828 ptr + *pnwritten, len - *pnwritten, 1829 FALSE, &this_write); 1830 if(result == CURLE_AGAIN) 1831 continue; 1832 else if(result != CURLE_OK) { 1833 break; 1834 } 1835 1836 *pnwritten += this_write; 1837 } 1838 } 1839 else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { 1840 result = CURLE_OUT_OF_MEMORY; 1841 } 1842 else{ 1843 result = CURLE_SEND_ERROR; 1844 } 1845 1846 Curl_safefree(ptr); 1847 1848 if(len == *pnwritten) 1849 /* Encrypted message including header, data and trailer entirely sent. 1850 The return value is the number of unencrypted bytes that were sent. */ 1851 *pnwritten = outbuf[1].cbBuffer; 1852 1853 return result; 1854 } 1855 1856 static CURLcode 1857 schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, 1858 char *buf, size_t len, size_t *pnread) 1859 { 1860 size_t size = 0; 1861 size_t nread = 0; 1862 struct ssl_connect_data *connssl = cf->ctx; 1863 unsigned char *reallocated_buffer; 1864 size_t reallocated_length; 1865 bool done = FALSE; 1866 SecBuffer inbuf[4]; 1867 SecBufferDesc inbuf_desc; 1868 SECURITY_STATUS sspi_status = SEC_E_OK; 1869 /* we want the length of the encrypted buffer to be at least large enough 1870 that it can hold all the bytes requested and some TLS record overhead. */ 1871 size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; 1872 struct schannel_ssl_backend_data *backend = 1873 (struct schannel_ssl_backend_data *)connssl->backend; 1874 CURLcode result = CURLE_OK; 1875 1876 DEBUGASSERT(backend); 1877 *pnread = 0; 1878 1879 /**************************************************************************** 1880 * Do not return or set backend->recv_unrecoverable_err unless in the 1881 * cleanup. The pattern for return error is set *err, optional infof, goto 1882 * cleanup. 1883 * 1884 * Some verbose debug messages are wrapped by SCH_DEV() instead of DEBUGF() 1885 * and only shown if CURL_SCHANNEL_DEV_DEBUG was defined at build time. These 1886 * messages are extra verbose and intended for curl developers debugging 1887 * Schannel recv decryption. 1888 * 1889 * Our priority is to always return as much decrypted data to the caller as 1890 * possible, even if an error occurs. The state of the decrypted buffer must 1891 * always be valid. Transfer of decrypted data to the caller's buffer is 1892 * handled in the cleanup. 1893 */ 1894 1895 SCH_DEV(infof(data, "schannel: client wants to read %zu bytes", len)); 1896 1897 if(len && len <= backend->decdata_offset) { 1898 SCH_DEV(infof(data, 1899 "schannel: enough decrypted data is already available")); 1900 goto cleanup; 1901 } 1902 else if(backend->recv_unrecoverable_err) { 1903 result = backend->recv_unrecoverable_err; 1904 infof(data, "schannel: an unrecoverable error occurred in a prior call"); 1905 goto cleanup; 1906 } 1907 else if(backend->recv_sspi_close_notify) { 1908 /* once a server has indicated shutdown there is no more encrypted data */ 1909 infof(data, "schannel: server indicated shutdown in a prior call"); 1910 goto cleanup; 1911 } 1912 /* it is debatable what to return when !len. Regardless we cannot return 1913 immediately because there may be data to decrypt (in the case we want to 1914 decrypt all encrypted cached data) so handle !len later in cleanup. 1915 */ 1916 else if(len && !backend->recv_connection_closed) { 1917 /* increase enc buffer in order to fit the requested amount of data */ 1918 size = backend->encdata_length - backend->encdata_offset; 1919 if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || 1920 backend->encdata_length < min_encdata_length) { 1921 reallocated_length = backend->encdata_offset + 1922 CURL_SCHANNEL_BUFFER_FREE_SIZE; 1923 if(reallocated_length < min_encdata_length) { 1924 reallocated_length = min_encdata_length; 1925 } 1926 reallocated_buffer = realloc(backend->encdata_buffer, 1927 reallocated_length); 1928 if(!reallocated_buffer) { 1929 result = CURLE_OUT_OF_MEMORY; 1930 failf(data, "schannel: unable to re-allocate memory"); 1931 goto cleanup; 1932 } 1933 1934 backend->encdata_buffer = reallocated_buffer; 1935 backend->encdata_length = reallocated_length; 1936 size = backend->encdata_length - backend->encdata_offset; 1937 SCH_DEV(infof(data, "schannel: encdata_buffer resized %zu", 1938 backend->encdata_length)); 1939 } 1940 1941 SCH_DEV(infof(data, 1942 "schannel: encrypted data buffer: offset %zu length %zu", 1943 backend->encdata_offset, backend->encdata_length)); 1944 1945 /* read encrypted data from socket */ 1946 result = Curl_conn_cf_recv(cf->next, data, 1947 (char *)(backend->encdata_buffer + 1948 backend->encdata_offset), 1949 size, &nread); 1950 if(result) { 1951 if(result == CURLE_AGAIN) 1952 SCH_DEV(infof(data, "schannel: recv returned CURLE_AGAIN")); 1953 else if(result == CURLE_RECV_ERROR) 1954 infof(data, "schannel: recv returned CURLE_RECV_ERROR"); 1955 else 1956 infof(data, "schannel: recv returned error %d", result); 1957 } 1958 else if(nread == 0) { 1959 backend->recv_connection_closed = TRUE; 1960 DEBUGF(infof(data, "schannel: server closed the connection")); 1961 } 1962 else { 1963 backend->encdata_offset += nread; 1964 backend->encdata_is_incomplete = FALSE; 1965 SCH_DEV(infof(data, "schannel: encrypted data got %zu", nread)); 1966 } 1967 } 1968 1969 SCH_DEV(infof(data, "schannel: encrypted data buffer: offset %zu length %zu", 1970 backend->encdata_offset, backend->encdata_length)); 1971 1972 /* decrypt loop */ 1973 while(backend->encdata_offset > 0 && sspi_status == SEC_E_OK && 1974 (!len || backend->decdata_offset < len || 1975 backend->recv_connection_closed)) { 1976 /* prepare data buffer for DecryptMessage call */ 1977 InitSecBuffer(&inbuf[0], SECBUFFER_DATA, backend->encdata_buffer, 1978 curlx_uztoul(backend->encdata_offset)); 1979 1980 /* we need 3 more empty input buffers for possible output */ 1981 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 1982 InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); 1983 InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); 1984 InitSecBufferDesc(&inbuf_desc, inbuf, 4); 1985 1986 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx 1987 */ 1988 sspi_status = Curl_pSecFn->DecryptMessage(&backend->ctxt->ctxt_handle, 1989 &inbuf_desc, 0, NULL); 1990 1991 /* check if everything went fine (server may want to renegotiate 1992 or shutdown the connection context) */ 1993 if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || 1994 sspi_status == SEC_I_CONTEXT_EXPIRED) { 1995 /* check for successfully decrypted data, even before actual 1996 renegotiation or shutdown of the connection context */ 1997 if(inbuf[1].BufferType == SECBUFFER_DATA) { 1998 SCH_DEV(infof(data, "schannel: decrypted data length: %lu", 1999 inbuf[1].cbBuffer)); 2000 2001 /* increase buffer in order to fit the received amount of data */ 2002 size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? 2003 inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; 2004 if(backend->decdata_length - backend->decdata_offset < size || 2005 backend->decdata_length < len) { 2006 /* increase internal decrypted data buffer */ 2007 reallocated_length = backend->decdata_offset + size; 2008 /* make sure that the requested amount of data fits */ 2009 if(reallocated_length < len) { 2010 reallocated_length = len; 2011 } 2012 reallocated_buffer = realloc(backend->decdata_buffer, 2013 reallocated_length); 2014 if(!reallocated_buffer) { 2015 result = CURLE_OUT_OF_MEMORY; 2016 failf(data, "schannel: unable to re-allocate memory"); 2017 goto cleanup; 2018 } 2019 backend->decdata_buffer = reallocated_buffer; 2020 backend->decdata_length = reallocated_length; 2021 } 2022 2023 /* copy decrypted data to internal buffer */ 2024 size = inbuf[1].cbBuffer; 2025 if(size) { 2026 memcpy(backend->decdata_buffer + backend->decdata_offset, 2027 inbuf[1].pvBuffer, size); 2028 backend->decdata_offset += size; 2029 } 2030 2031 SCH_DEV(infof(data, "schannel: decrypted data added: %zu", size)); 2032 SCH_DEV(infof(data, 2033 "schannel: decrypted cached: offset %zu length %zu", 2034 backend->decdata_offset, backend->decdata_length)); 2035 } 2036 2037 /* check for remaining encrypted data */ 2038 if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { 2039 SCH_DEV(infof(data, "schannel: encrypted data length: %lu", 2040 inbuf[3].cbBuffer)); 2041 2042 /* check if the remaining data is less than the total amount 2043 * and therefore begins after the already processed data 2044 */ 2045 if(backend->encdata_offset > inbuf[3].cbBuffer) { 2046 /* move remaining encrypted data forward to the beginning of 2047 buffer */ 2048 memmove(backend->encdata_buffer, 2049 (backend->encdata_buffer + backend->encdata_offset) - 2050 inbuf[3].cbBuffer, inbuf[3].cbBuffer); 2051 backend->encdata_offset = inbuf[3].cbBuffer; 2052 } 2053 2054 SCH_DEV(infof(data, 2055 "schannel: encrypted cached: offset %zu length %zu", 2056 backend->encdata_offset, backend->encdata_length)); 2057 } 2058 else { 2059 /* reset encrypted buffer offset, because there is no data remaining */ 2060 backend->encdata_offset = 0; 2061 } 2062 2063 /* check if server wants to renegotiate the connection context */ 2064 if(sspi_status == SEC_I_RENEGOTIATE) { 2065 infof(data, "schannel: remote party requests renegotiation"); 2066 if(result && result != CURLE_AGAIN) { 2067 infof(data, "schannel: cannot renegotiate, an error is pending"); 2068 goto cleanup; 2069 } 2070 2071 /* begin renegotiation */ 2072 infof(data, "schannel: renegotiating SSL/TLS connection"); 2073 connssl->state = ssl_connection_negotiating; 2074 connssl->connecting_state = ssl_connect_2; 2075 connssl->io_need = CURL_SSL_IO_NEED_SEND; 2076 backend->recv_renegotiating = TRUE; 2077 result = schannel_connect(cf, data, &done); 2078 backend->recv_renegotiating = FALSE; 2079 if(result) { 2080 infof(data, "schannel: renegotiation failed"); 2081 goto cleanup; 2082 } 2083 /* now retry receiving data */ 2084 sspi_status = SEC_E_OK; 2085 infof(data, "schannel: SSL/TLS connection renegotiated"); 2086 continue; 2087 } 2088 /* check if the server closed the connection */ 2089 else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { 2090 /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not 2091 returned so we have to work around that in cleanup. */ 2092 backend->recv_sspi_close_notify = TRUE; 2093 if(!backend->recv_connection_closed) 2094 backend->recv_connection_closed = TRUE; 2095 /* We received the close notify just fine, any error we got 2096 * from the lower filters afterwards (e.g. the socket), is not 2097 * an error on the TLS data stream. That one ended here. */ 2098 if(result == CURLE_RECV_ERROR) 2099 result = CURLE_OK; 2100 infof(data, 2101 "schannel: server close notification received (close_notify)"); 2102 goto cleanup; 2103 } 2104 } 2105 else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 2106 backend->encdata_is_incomplete = TRUE; 2107 if(!result) 2108 result = CURLE_AGAIN; 2109 SCH_DEV(infof(data, "schannel: failed to decrypt data, need more data")); 2110 goto cleanup; 2111 } 2112 else { 2113 #ifndef CURL_DISABLE_VERBOSE_STRINGS 2114 char buffer[STRERROR_LEN]; 2115 failf(data, "schannel: failed to read data from server: %s", 2116 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 2117 #endif 2118 result = CURLE_RECV_ERROR; 2119 goto cleanup; 2120 } 2121 } 2122 2123 SCH_DEV(infof(data, "schannel: encrypted data buffer: offset %zu length %zu", 2124 backend->encdata_offset, backend->encdata_length)); 2125 2126 SCH_DEV(infof(data, "schannel: decrypted data buffer: offset %zu length %zu", 2127 backend->decdata_offset, backend->decdata_length)); 2128 2129 cleanup: 2130 /* Warning- there is no guarantee the encdata state is valid at this point */ 2131 SCH_DEV(infof(data, "schannel: schannel_recv cleanup")); 2132 2133 /* Error if the connection has closed without a close_notify. 2134 2135 The behavior here is a matter of debate. We do not want to be vulnerable 2136 to a truncation attack however there is some browser precedent for 2137 ignoring the close_notify for compatibility reasons. 2138 */ 2139 if(len && !backend->decdata_offset && backend->recv_connection_closed && 2140 !backend->recv_sspi_close_notify) { 2141 result = CURLE_RECV_ERROR; 2142 failf(data, "schannel: server closed abruptly (missing close_notify)"); 2143 } 2144 2145 /* Any error other than CURLE_AGAIN is an unrecoverable error. */ 2146 if(result && result != CURLE_AGAIN) 2147 backend->recv_unrecoverable_err = result; 2148 2149 size = len < backend->decdata_offset ? len : backend->decdata_offset; 2150 if(size) { 2151 memcpy(buf, backend->decdata_buffer, size); 2152 memmove(backend->decdata_buffer, backend->decdata_buffer + size, 2153 backend->decdata_offset - size); 2154 backend->decdata_offset -= size; 2155 SCH_DEV(infof(data, "schannel: decrypted data returned %zu", size)); 2156 SCH_DEV(infof(data, 2157 "schannel: decrypted data buffer: offset %zu length %zu", 2158 backend->decdata_offset, backend->decdata_length)); 2159 *pnread = size; 2160 return CURLE_OK; 2161 } 2162 2163 if(!result && !backend->recv_connection_closed) 2164 result = CURLE_AGAIN; 2165 2166 /* it is debatable what to return when !len. We could return whatever error 2167 we got from decryption but instead we override here so the return is 2168 consistent. 2169 */ 2170 if(!len) 2171 return CURLE_OK; 2172 2173 return result; 2174 } 2175 2176 static bool schannel_data_pending(struct Curl_cfilter *cf, 2177 const struct Curl_easy *data) 2178 { 2179 const struct ssl_connect_data *connssl = cf->ctx; 2180 struct schannel_ssl_backend_data *backend = 2181 (struct schannel_ssl_backend_data *)connssl->backend; 2182 2183 (void)data; 2184 DEBUGASSERT(backend); 2185 2186 if(backend->ctxt) /* SSL/TLS is in use */ 2187 return backend->decdata_offset > 0 || 2188 (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) || 2189 backend->recv_connection_closed || 2190 backend->recv_sspi_close_notify || 2191 backend->recv_unrecoverable_err; 2192 else 2193 return FALSE; 2194 } 2195 2196 /* shut down the SSL connection and clean up related memory. 2197 this function can be called multiple times on the same connection including 2198 if the SSL connection failed (eg connection made but failed handshake). */ 2199 static CURLcode schannel_shutdown(struct Curl_cfilter *cf, 2200 struct Curl_easy *data, 2201 bool send_shutdown, bool *done) 2202 { 2203 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx 2204 * Shutting Down an Schannel Connection 2205 */ 2206 struct ssl_connect_data *connssl = cf->ctx; 2207 struct schannel_ssl_backend_data *backend = 2208 (struct schannel_ssl_backend_data *)connssl->backend; 2209 CURLcode result = CURLE_OK; 2210 2211 if(cf->shutdown) { 2212 *done = TRUE; 2213 return CURLE_OK; 2214 } 2215 2216 DEBUGASSERT(data); 2217 DEBUGASSERT(backend); 2218 2219 /* Not supported in schannel */ 2220 (void)send_shutdown; 2221 2222 *done = FALSE; 2223 if(backend->ctxt) { 2224 infof(data, "schannel: shutting down SSL/TLS connection with %s port %d", 2225 connssl->peer.hostname, connssl->peer.port); 2226 } 2227 2228 if(!backend->ctxt || cf->shutdown) { 2229 *done = TRUE; 2230 goto out; 2231 } 2232 2233 if(backend->cred && backend->ctxt && !backend->sent_shutdown) { 2234 SecBufferDesc BuffDesc; 2235 SecBuffer Buffer; 2236 SECURITY_STATUS sspi_status; 2237 SecBuffer outbuf; 2238 SecBufferDesc outbuf_desc; 2239 DWORD dwshut = SCHANNEL_SHUTDOWN; 2240 2241 InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); 2242 InitSecBufferDesc(&BuffDesc, &Buffer, 1); 2243 2244 sspi_status = Curl_pSecFn->ApplyControlToken(&backend->ctxt->ctxt_handle, 2245 &BuffDesc); 2246 2247 if(sspi_status != SEC_E_OK) { 2248 char buffer[STRERROR_LEN]; 2249 failf(data, "schannel: ApplyControlToken failure: %s", 2250 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 2251 result = CURLE_SEND_ERROR; 2252 goto out; 2253 } 2254 2255 /* setup output buffer */ 2256 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 2257 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 2258 2259 sspi_status = Curl_pSecFn->InitializeSecurityContext( 2260 &backend->cred->cred_handle, 2261 &backend->ctxt->ctxt_handle, 2262 backend->cred->sni_hostname, 2263 backend->req_flags, 2264 0, 2265 0, 2266 NULL, 2267 0, 2268 &backend->ctxt->ctxt_handle, 2269 &outbuf_desc, 2270 &backend->ret_flags, 2271 &backend->ctxt->time_stamp); 2272 2273 if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { 2274 /* send close message which is in output buffer */ 2275 size_t written; 2276 2277 result = Curl_conn_cf_send(cf->next, data, 2278 outbuf.pvBuffer, outbuf.cbBuffer, 2279 FALSE, &written); 2280 Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 2281 if(!result) { 2282 if(written < outbuf.cbBuffer) { 2283 failf(data, "schannel: failed to send close msg: %s" 2284 " (bytes written: %zu)", curl_easy_strerror(result), written); 2285 result = CURLE_SEND_ERROR; 2286 goto out; 2287 } 2288 backend->sent_shutdown = TRUE; 2289 *done = TRUE; 2290 } 2291 else if(result == CURLE_AGAIN) { 2292 connssl->io_need = CURL_SSL_IO_NEED_SEND; 2293 result = CURLE_OK; 2294 goto out; 2295 } 2296 else { 2297 if(!backend->recv_connection_closed) { 2298 failf(data, "schannel: error sending close msg: %d", result); 2299 result = CURLE_SEND_ERROR; 2300 goto out; 2301 } 2302 /* Looks like server already closed the connection. 2303 * An error to send our close notify is not a failure. */ 2304 *done = TRUE; 2305 result = CURLE_OK; 2306 } 2307 } 2308 } 2309 2310 /* If the connection seems open and we have not seen the close notify 2311 * from the server yet, try to receive it. */ 2312 if(backend->cred && backend->ctxt && 2313 !backend->recv_sspi_close_notify && !backend->recv_connection_closed) { 2314 char buffer[1024]; 2315 size_t nread; 2316 2317 result = schannel_recv(cf, data, buffer, sizeof(buffer), &nread); 2318 if(result == CURLE_AGAIN) { 2319 connssl->io_need = CURL_SSL_IO_NEED_RECV; 2320 } 2321 else if(result) { 2322 CURL_TRC_CF(data, cf, "SSL shutdown, error %d", result); 2323 result = CURLE_RECV_ERROR; 2324 } 2325 else if(nread == 0) { 2326 /* We got the close notify alert and are done. */ 2327 backend->recv_connection_closed = TRUE; 2328 *done = TRUE; 2329 } 2330 else { 2331 /* still data coming in? */ 2332 } 2333 } 2334 2335 out: 2336 cf->shutdown = (result || *done); 2337 return result; 2338 } 2339 2340 static void schannel_close(struct Curl_cfilter *cf, struct Curl_easy *data) 2341 { 2342 struct ssl_connect_data *connssl = cf->ctx; 2343 struct schannel_ssl_backend_data *backend = 2344 (struct schannel_ssl_backend_data *)connssl->backend; 2345 2346 DEBUGASSERT(data); 2347 DEBUGASSERT(backend); 2348 2349 /* free SSPI Schannel API security context handle */ 2350 if(backend->ctxt) { 2351 DEBUGF(infof(data, "schannel: clear security context handle")); 2352 Curl_pSecFn->DeleteSecurityContext(&backend->ctxt->ctxt_handle); 2353 Curl_safefree(backend->ctxt); 2354 } 2355 2356 /* free SSPI Schannel API credential handle */ 2357 if(backend->cred) { 2358 Curl_ssl_scache_lock(data); 2359 schannel_session_free(backend->cred); 2360 Curl_ssl_scache_unlock(data); 2361 backend->cred = NULL; 2362 } 2363 2364 /* free internal buffer for received encrypted data */ 2365 if(backend->encdata_buffer) { 2366 Curl_safefree(backend->encdata_buffer); 2367 backend->encdata_length = 0; 2368 backend->encdata_offset = 0; 2369 backend->encdata_is_incomplete = FALSE; 2370 } 2371 2372 /* free internal buffer for received decrypted data */ 2373 if(backend->decdata_buffer) { 2374 Curl_safefree(backend->decdata_buffer); 2375 backend->decdata_length = 0; 2376 backend->decdata_offset = 0; 2377 } 2378 } 2379 2380 static int schannel_init(void) 2381 { 2382 #if defined(HAS_ALPN_SCHANNEL) && !defined(UNDER_CE) 2383 bool wine = FALSE; 2384 bool wine_has_alpn = FALSE; 2385 2386 #ifndef CURL_WINDOWS_UWP 2387 typedef const char *(APIENTRY *WINE_GET_VERSION_FN)(void); 2388 /* GetModuleHandle() not available for UWP. 2389 Assume no WINE because WINE has no UWP support. */ 2390 WINE_GET_VERSION_FN p_wine_get_version = 2391 CURLX_FUNCTION_CAST(WINE_GET_VERSION_FN, 2392 (GetProcAddress(GetModuleHandleA("ntdll"), 2393 "wine_get_version"))); 2394 wine = !!p_wine_get_version; 2395 if(wine) { 2396 const char *wine_version = p_wine_get_version(); /* e.g. "6.0.2" */ 2397 /* Assume ALPN support with WINE 6.0 or upper */ 2398 wine_has_alpn = wine_version && atoi(wine_version) >= 6; 2399 } 2400 #endif 2401 if(wine) 2402 s_win_has_alpn = wine_has_alpn; 2403 else { 2404 /* ALPN is supported on Windows 8.1 / Server 2012 R2 and above. */ 2405 s_win_has_alpn = curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT, 2406 VERSION_GREATER_THAN_EQUAL); 2407 } 2408 #endif /* HAS_ALPN_SCHANNEL && !UNDER_CE */ 2409 2410 return Curl_sspi_global_init() == CURLE_OK ? 1 : 0; 2411 } 2412 2413 static void schannel_cleanup(void) 2414 { 2415 Curl_sspi_global_cleanup(); 2416 } 2417 2418 static size_t schannel_version(char *buffer, size_t size) 2419 { 2420 return msnprintf(buffer, size, "Schannel"); 2421 } 2422 2423 static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM, 2424 unsigned char *entropy, size_t length) 2425 { 2426 (void)data; 2427 2428 return Curl_win32_random(entropy, length); 2429 } 2430 2431 static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf, 2432 struct Curl_easy *data, 2433 const char *pinnedpubkey) 2434 { 2435 struct ssl_connect_data *connssl = cf->ctx; 2436 struct schannel_ssl_backend_data *backend = 2437 (struct schannel_ssl_backend_data *)connssl->backend; 2438 CERT_CONTEXT *pCertContextServer = NULL; 2439 2440 /* Result is returned to caller */ 2441 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 2442 2443 DEBUGASSERT(backend); 2444 2445 /* if a path was not specified, do not pin */ 2446 if(!pinnedpubkey) 2447 return CURLE_OK; 2448 2449 do { 2450 SECURITY_STATUS sspi_status; 2451 const char *x509_der; 2452 DWORD x509_der_len; 2453 struct Curl_X509certificate x509_parsed; 2454 struct Curl_asn1Element *pubkey; 2455 2456 sspi_status = 2457 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, 2458 SECPKG_ATTR_REMOTE_CERT_CONTEXT, 2459 &pCertContextServer); 2460 2461 if((sspi_status != SEC_E_OK) || !pCertContextServer) { 2462 char buffer[STRERROR_LEN]; 2463 failf(data, "schannel: Failed to read remote certificate context: %s", 2464 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); 2465 break; /* failed */ 2466 } 2467 2468 2469 if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && 2470 (pCertContextServer->cbCertEncoded > 0))) 2471 break; 2472 2473 x509_der = (const char *)pCertContextServer->pbCertEncoded; 2474 x509_der_len = pCertContextServer->cbCertEncoded; 2475 memset(&x509_parsed, 0, sizeof(x509_parsed)); 2476 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) 2477 break; 2478 2479 pubkey = &x509_parsed.subjectPublicKeyInfo; 2480 if(!pubkey->header || pubkey->end <= pubkey->header) { 2481 failf(data, "SSL: failed retrieving public key from server certificate"); 2482 break; 2483 } 2484 2485 result = Curl_pin_peer_pubkey(data, 2486 pinnedpubkey, 2487 (const unsigned char *)pubkey->header, 2488 (size_t)(pubkey->end - pubkey->header)); 2489 if(result) { 2490 failf(data, "SSL: public key does not match pinned public key"); 2491 } 2492 } while(0); 2493 2494 if(pCertContextServer) 2495 CertFreeCertificateContext(pCertContextServer); 2496 2497 return result; 2498 } 2499 2500 static void schannel_checksum(const unsigned char *input, 2501 size_t inputlen, 2502 unsigned char *checksum, 2503 size_t checksumlen, 2504 DWORD provType, 2505 const unsigned int algId) 2506 { 2507 #ifdef CURL_WINDOWS_UWP 2508 (void)input; 2509 (void)inputlen; 2510 (void)provType; 2511 (void)algId; 2512 memset(checksum, 0, checksumlen); 2513 #else 2514 HCRYPTPROV hProv = 0; 2515 HCRYPTHASH hHash = 0; 2516 DWORD cbHashSize = 0; 2517 DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize); 2518 DWORD dwChecksumLen = (DWORD)checksumlen; 2519 2520 /* since this can fail in multiple ways, zero memory first so we never 2521 * return old data 2522 */ 2523 memset(checksum, 0, checksumlen); 2524 2525 if(!CryptAcquireContext(&hProv, NULL, NULL, provType, 2526 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) 2527 return; /* failed */ 2528 2529 do { 2530 if(!CryptCreateHash(hProv, algId, 0, 0, &hHash)) 2531 break; /* failed */ 2532 2533 #ifdef __MINGW32CE__ 2534 /* workaround for CeGCC, should be (const BYTE*) */ 2535 if(!CryptHashData(hHash, (BYTE*)CURL_UNCONST(input), (DWORD)inputlen, 0)) 2536 #else 2537 if(!CryptHashData(hHash, input, (DWORD)inputlen, 0)) 2538 #endif 2539 break; /* failed */ 2540 2541 /* get hash size */ 2542 if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, 2543 &dwHashSizeLen, 0)) 2544 break; /* failed */ 2545 2546 /* check hash size */ 2547 if(checksumlen < cbHashSize) 2548 break; /* failed */ 2549 2550 if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0)) 2551 break; /* failed */ 2552 } while(0); 2553 2554 if(hHash) 2555 CryptDestroyHash(hHash); 2556 2557 if(hProv) 2558 CryptReleaseContext(hProv, 0); 2559 #endif 2560 } 2561 2562 static CURLcode schannel_sha256sum(const unsigned char *input, 2563 size_t inputlen, 2564 unsigned char *sha256sum, 2565 size_t sha256len) 2566 { 2567 schannel_checksum(input, inputlen, sha256sum, sha256len, 2568 PROV_RSA_AES, CALG_SHA_256); 2569 return CURLE_OK; 2570 } 2571 2572 static void *schannel_get_internals(struct ssl_connect_data *connssl, 2573 CURLINFO info UNUSED_PARAM) 2574 { 2575 struct schannel_ssl_backend_data *backend = 2576 (struct schannel_ssl_backend_data *)connssl->backend; 2577 (void)info; 2578 DEBUGASSERT(backend); 2579 return &backend->ctxt->ctxt_handle; 2580 } 2581 2582 HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, 2583 const struct Curl_easy *data) 2584 { 2585 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 2586 struct Curl_multi *multi = data->multi; 2587 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 2588 struct schannel_cert_share *share; 2589 const struct ssl_general_config *cfg = &data->set.general_ssl; 2590 timediff_t timeout_ms; 2591 timediff_t elapsed_ms; 2592 struct curltime now; 2593 unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH]; 2594 2595 DEBUGASSERT(multi); 2596 2597 if(!multi) { 2598 return NULL; 2599 } 2600 2601 share = Curl_hash_pick(&multi->proto_hash, 2602 CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), 2603 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); 2604 if(!share || !share->cert_store) { 2605 return NULL; 2606 } 2607 2608 /* zero ca_cache_timeout completely disables caching */ 2609 if(!cfg->ca_cache_timeout) { 2610 return NULL; 2611 } 2612 2613 /* check for cache timeout by using the cached_x509_store_expired timediff 2614 calculation pattern from openssl.c. 2615 negative timeout means retain forever. */ 2616 timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; 2617 if(timeout_ms >= 0) { 2618 now = curlx_now(); 2619 elapsed_ms = curlx_timediff(now, share->time); 2620 if(elapsed_ms >= timeout_ms) { 2621 return NULL; 2622 } 2623 } 2624 2625 if(ca_info_blob) { 2626 if(share->CAinfo_blob_size != ca_info_blob->len) { 2627 return NULL; 2628 } 2629 schannel_sha256sum((const unsigned char *)ca_info_blob->data, 2630 ca_info_blob->len, 2631 info_blob_digest, 2632 CURL_SHA256_DIGEST_LENGTH); 2633 if(memcmp(share->CAinfo_blob_digest, info_blob_digest, 2634 CURL_SHA256_DIGEST_LENGTH)) { 2635 return NULL; 2636 } 2637 } 2638 else { 2639 if(!conn_config->CAfile || !share->CAfile || 2640 strcmp(share->CAfile, conn_config->CAfile)) { 2641 return NULL; 2642 } 2643 } 2644 2645 return share->cert_store; 2646 } 2647 2648 static void schannel_cert_share_free(void *key, size_t key_len, void *p) 2649 { 2650 struct schannel_cert_share *share = p; 2651 DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1)); 2652 DEBUGASSERT(!memcmp(MPROTO_SCHANNEL_CERT_SHARE_KEY, key, key_len)); 2653 (void)key; 2654 (void)key_len; 2655 if(share->cert_store) { 2656 CertCloseStore(share->cert_store, 0); 2657 } 2658 free(share->CAfile); 2659 free(share); 2660 } 2661 2662 bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, 2663 const struct Curl_easy *data, 2664 HCERTSTORE cert_store) 2665 { 2666 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 2667 struct Curl_multi *multi = data->multi; 2668 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 2669 struct schannel_cert_share *share; 2670 size_t CAinfo_blob_size = 0; 2671 char *CAfile = NULL; 2672 2673 DEBUGASSERT(multi); 2674 2675 if(!multi) { 2676 return FALSE; 2677 } 2678 2679 share = Curl_hash_pick(&multi->proto_hash, 2680 CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), 2681 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); 2682 if(!share) { 2683 share = calloc(1, sizeof(*share)); 2684 if(!share) { 2685 return FALSE; 2686 } 2687 if(!Curl_hash_add2(&multi->proto_hash, 2688 CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), 2689 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1, 2690 share, schannel_cert_share_free)) { 2691 free(share); 2692 return FALSE; 2693 } 2694 } 2695 2696 if(ca_info_blob) { 2697 schannel_sha256sum((const unsigned char *)ca_info_blob->data, 2698 ca_info_blob->len, 2699 share->CAinfo_blob_digest, 2700 CURL_SHA256_DIGEST_LENGTH); 2701 CAinfo_blob_size = ca_info_blob->len; 2702 } 2703 else { 2704 if(conn_config->CAfile) { 2705 CAfile = strdup(conn_config->CAfile); 2706 if(!CAfile) { 2707 return FALSE; 2708 } 2709 } 2710 } 2711 2712 /* free old cache data */ 2713 if(share->cert_store) { 2714 CertCloseStore(share->cert_store, 0); 2715 } 2716 free(share->CAfile); 2717 2718 share->time = curlx_now(); 2719 share->cert_store = cert_store; 2720 share->CAinfo_blob_size = CAinfo_blob_size; 2721 share->CAfile = CAfile; 2722 return TRUE; 2723 } 2724 2725 const struct Curl_ssl Curl_ssl_schannel = { 2726 { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ 2727 2728 SSLSUPP_CERTINFO | 2729 #ifdef HAS_MANUAL_VERIFY_API 2730 SSLSUPP_CAINFO_BLOB | 2731 #endif 2732 #ifndef CURL_WINDOWS_UWP 2733 SSLSUPP_PINNEDPUBKEY | 2734 #endif 2735 SSLSUPP_CA_CACHE | 2736 SSLSUPP_HTTPS_PROXY | 2737 SSLSUPP_CIPHER_LIST, 2738 2739 sizeof(struct schannel_ssl_backend_data), 2740 2741 schannel_init, /* init */ 2742 schannel_cleanup, /* cleanup */ 2743 schannel_version, /* version */ 2744 schannel_shutdown, /* shutdown */ 2745 schannel_data_pending, /* data_pending */ 2746 schannel_random, /* random */ 2747 NULL, /* cert_status_request */ 2748 schannel_connect, /* connect */ 2749 Curl_ssl_adjust_pollset, /* adjust_pollset */ 2750 schannel_get_internals, /* get_internals */ 2751 schannel_close, /* close_one */ 2752 NULL, /* close_all */ 2753 NULL, /* set_engine */ 2754 NULL, /* set_engine_default */ 2755 NULL, /* engines_list */ 2756 schannel_sha256sum, /* sha256sum */ 2757 schannel_recv, /* recv decrypted data */ 2758 schannel_send, /* send data to encrypt */ 2759 NULL, /* get_channel_binding */ 2760 }; 2761 2762 #endif /* USE_SCHANNEL */