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 - 2017, 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 /* 32 * Based upon the PolarSSL implementation in polarssl.c and polarssl.h: 33 * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan (at) gmail.com> 34 * 35 * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: 36 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel (at) haxx.se>, et al. 37 * 38 * Thanks for code and inspiration! 39 */ 40 41 #include "curl_setup.h" 42 43 #ifdef USE_SCHANNEL 44 45 #ifndef USE_WINDOWS_SSPI 46 # error "Can't compile SCHANNEL support without SSPI." 47 #endif 48 49 #include <schnlsp.h> 50 #include <schannel.h> 51 #include "curl_sspi.h" 52 #include "schannel.h" 53 #include "vtls.h" 54 #include "sendf.h" 55 #include "connect.h" /* for the connect timeout */ 56 #include "strerror.h" 57 #include "select.h" /* for the socket readyness */ 58 #include "inet_pton.h" /* for IP addr SNI check */ 59 #include "curl_multibyte.h" 60 #include "warnless.h" 61 #include "x509asn1.h" 62 #include "curl_printf.h" 63 #include "system_win32.h" 64 #include "hostcheck.h" 65 66 /* The last #include file should be: */ 67 #include "curl_memory.h" 68 #include "memdebug.h" 69 70 /* ALPN requires version 8.1 of the Windows SDK, which was 71 shipped with Visual Studio 2013, aka _MSC_VER 1800: 72 73 https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx 74 */ 75 #if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_) 76 # define HAS_ALPN 1 77 #endif 78 79 #ifndef UNISP_NAME_A 80 #define UNISP_NAME_A "Microsoft Unified Security Protocol Provider" 81 #endif 82 83 #ifndef UNISP_NAME_W 84 #define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider" 85 #endif 86 87 #ifndef UNISP_NAME 88 #ifdef UNICODE 89 #define UNISP_NAME UNISP_NAME_W 90 #else 91 #define UNISP_NAME UNISP_NAME_A 92 #endif 93 #endif 94 95 #ifndef SP_PROT_SSL2_CLIENT 96 #define SP_PROT_SSL2_CLIENT 0x00000008 97 #endif 98 99 #ifndef SP_PROT_SSL3_CLIENT 100 #define SP_PROT_SSL3_CLIENT 0x00000008 101 #endif 102 103 #ifndef SP_PROT_TLS1_CLIENT 104 #define SP_PROT_TLS1_CLIENT 0x00000080 105 #endif 106 107 #ifndef SP_PROT_TLS1_0_CLIENT 108 #define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT 109 #endif 110 111 #ifndef SP_PROT_TLS1_1_CLIENT 112 #define SP_PROT_TLS1_1_CLIENT 0x00000200 113 #endif 114 115 #ifndef SP_PROT_TLS1_2_CLIENT 116 #define SP_PROT_TLS1_2_CLIENT 0x00000800 117 #endif 118 119 #ifndef SECBUFFER_ALERT 120 #define SECBUFFER_ALERT 17 121 #endif 122 123 /* Both schannel buffer sizes must be > 0 */ 124 #define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 125 #define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 126 127 /* Uncomment to force verbose output 128 * #define infof(x, y, ...) printf(y, __VA_ARGS__) 129 * #define failf(x, y, ...) printf(y, __VA_ARGS__) 130 */ 131 132 /* Structs to store Schannel handles */ 133 struct curl_schannel_cred { 134 CredHandle cred_handle; 135 TimeStamp time_stamp; 136 int refcount; 137 }; 138 139 struct curl_schannel_ctxt { 140 CtxtHandle ctxt_handle; 141 TimeStamp time_stamp; 142 }; 143 144 struct ssl_backend_data { 145 struct curl_schannel_cred *cred; 146 struct curl_schannel_ctxt *ctxt; 147 SecPkgContext_StreamSizes stream_sizes; 148 size_t encdata_length, decdata_length; 149 size_t encdata_offset, decdata_offset; 150 unsigned char *encdata_buffer, *decdata_buffer; 151 /* encdata_is_incomplete: if encdata contains only a partial record that 152 can't be decrypted without another Curl_read_plain (that is, status is 153 SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes 154 more bytes into encdata then set this back to false. */ 155 bool encdata_is_incomplete; 156 unsigned long req_flags, ret_flags; 157 CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ 158 bool recv_sspi_close_notify; /* true if connection closed by close_notify */ 159 bool recv_connection_closed; /* true if connection closed, regardless how */ 160 bool use_alpn; /* true if ALPN is used for this connection */ 161 }; 162 163 #define BACKEND connssl->backend 164 165 static Curl_recv schannel_recv; 166 static Curl_send schannel_send; 167 168 #ifdef _WIN32_WCE 169 static CURLcode verify_certificate(struct connectdata *conn, int sockindex); 170 #endif 171 172 static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, 173 void *BufDataPtr, unsigned long BufByteSize) 174 { 175 buffer->cbBuffer = BufByteSize; 176 buffer->BufferType = BufType; 177 buffer->pvBuffer = BufDataPtr; 178 } 179 180 static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, 181 unsigned long NumArrElem) 182 { 183 desc->ulVersion = SECBUFFER_VERSION; 184 desc->pBuffers = BufArr; 185 desc->cBuffers = NumArrElem; 186 } 187 188 static CURLcode 189 set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) 190 { 191 struct Curl_easy *data = conn->data; 192 long ssl_version = SSL_CONN_CONFIG(version); 193 long ssl_version_max = SSL_CONN_CONFIG(version_max); 194 long i = ssl_version; 195 196 switch(ssl_version_max) { 197 case CURL_SSLVERSION_MAX_NONE: 198 ssl_version_max = ssl_version << 16; 199 break; 200 case CURL_SSLVERSION_MAX_DEFAULT: 201 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; 202 break; 203 } 204 for(; i <= (ssl_version_max >> 16); ++i) { 205 switch(i) { 206 case CURL_SSLVERSION_TLSv1_0: 207 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; 208 break; 209 case CURL_SSLVERSION_TLSv1_1: 210 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; 211 break; 212 case CURL_SSLVERSION_TLSv1_2: 213 schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; 214 break; 215 case CURL_SSLVERSION_TLSv1_3: 216 failf(data, "Schannel: TLS 1.3 is not yet supported"); 217 return CURLE_SSL_CONNECT_ERROR; 218 } 219 } 220 return CURLE_OK; 221 } 222 223 static CURLcode 224 schannel_connect_step1(struct connectdata *conn, int sockindex) 225 { 226 ssize_t written = -1; 227 struct Curl_easy *data = conn->data; 228 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 229 SecBuffer outbuf; 230 SecBufferDesc outbuf_desc; 231 SecBuffer inbuf; 232 SecBufferDesc inbuf_desc; 233 #ifdef HAS_ALPN 234 unsigned char alpn_buffer[128]; 235 #endif 236 SCHANNEL_CRED schannel_cred; 237 SECURITY_STATUS sspi_status = SEC_E_OK; 238 struct curl_schannel_cred *old_cred = NULL; 239 struct in_addr addr; 240 #ifdef ENABLE_IPV6 241 struct in6_addr addr6; 242 #endif 243 TCHAR *host_name; 244 CURLcode result; 245 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 246 conn->host.name; 247 248 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", 249 hostname, conn->remote_port); 250 251 if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, 252 VERSION_LESS_THAN_EQUAL)) { 253 /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and 254 algorithms that may not be supported by all servers. */ 255 infof(data, "schannel: WinSSL version is old and may not be able to " 256 "connect to some servers due to lack of SNI, algorithms, etc.\n"); 257 } 258 259 #ifdef HAS_ALPN 260 /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. 261 Also it doesn't seem to be supported for Wine, see curl bug #983. */ 262 BACKEND->use_alpn = conn->bits.tls_enable_alpn && 263 !GetProcAddress(GetModuleHandleA("ntdll"), 264 "wine_get_version") && 265 Curl_verify_windows_version(6, 3, PLATFORM_WINNT, 266 VERSION_GREATER_THAN_EQUAL); 267 #else 268 BACKEND->use_alpn = false; 269 #endif 270 271 BACKEND->cred = NULL; 272 273 /* check for an existing re-usable credential handle */ 274 if(SSL_SET_OPTION(primary.sessionid)) { 275 Curl_ssl_sessionid_lock(conn); 276 if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { 277 BACKEND->cred = old_cred; 278 infof(data, "schannel: re-using existing credential handle\n"); 279 280 /* increment the reference counter of the credential/session handle */ 281 BACKEND->cred->refcount++; 282 infof(data, "schannel: incremented credential handle refcount = %d\n", 283 BACKEND->cred->refcount); 284 } 285 Curl_ssl_sessionid_unlock(conn); 286 } 287 288 if(!BACKEND->cred) { 289 /* setup Schannel API options */ 290 memset(&schannel_cred, 0, sizeof(schannel_cred)); 291 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; 292 293 if(conn->ssl_config.verifypeer) { 294 #ifdef _WIN32_WCE 295 /* certificate validation on CE doesn't seem to work right; we'll 296 do it following a more manual process. */ 297 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | 298 SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 299 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 300 #else 301 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; 302 /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */ 303 if(data->set.ssl.no_revoke) 304 schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 305 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 306 else 307 schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; 308 #endif 309 if(data->set.ssl.no_revoke) 310 infof(data, "schannel: disabled server certificate revocation " 311 "checks\n"); 312 else 313 infof(data, "schannel: checking server certificate revocation\n"); 314 } 315 else { 316 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | 317 SCH_CRED_IGNORE_NO_REVOCATION_CHECK | 318 SCH_CRED_IGNORE_REVOCATION_OFFLINE; 319 infof(data, "schannel: disabled server certificate revocation checks\n"); 320 } 321 322 if(!conn->ssl_config.verifyhost) { 323 schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; 324 infof(data, "schannel: verifyhost setting prevents Schannel from " 325 "comparing the supplied target name with the subject " 326 "names in server certificates.\n"); 327 } 328 329 switch(conn->ssl_config.version) { 330 case CURL_SSLVERSION_DEFAULT: 331 case CURL_SSLVERSION_TLSv1: 332 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | 333 SP_PROT_TLS1_1_CLIENT | 334 SP_PROT_TLS1_2_CLIENT; 335 break; 336 case CURL_SSLVERSION_TLSv1_0: 337 case CURL_SSLVERSION_TLSv1_1: 338 case CURL_SSLVERSION_TLSv1_2: 339 case CURL_SSLVERSION_TLSv1_3: 340 { 341 result = set_ssl_version_min_max(&schannel_cred, conn); 342 if(result != CURLE_OK) 343 return result; 344 break; 345 } 346 case CURL_SSLVERSION_SSLv3: 347 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; 348 break; 349 case CURL_SSLVERSION_SSLv2: 350 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; 351 break; 352 default: 353 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 354 return CURLE_SSL_CONNECT_ERROR; 355 } 356 357 /* allocate memory for the re-usable credential handle */ 358 BACKEND->cred = (struct curl_schannel_cred *) 359 malloc(sizeof(struct curl_schannel_cred)); 360 if(!BACKEND->cred) { 361 failf(data, "schannel: unable to allocate memory"); 362 return CURLE_OUT_OF_MEMORY; 363 } 364 memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred)); 365 BACKEND->cred->refcount = 1; 366 367 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx 368 */ 369 sspi_status = 370 s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, 371 SECPKG_CRED_OUTBOUND, NULL, 372 &schannel_cred, NULL, NULL, 373 &BACKEND->cred->cred_handle, 374 &BACKEND->cred->time_stamp); 375 376 if(sspi_status != SEC_E_OK) { 377 if(sspi_status == SEC_E_WRONG_PRINCIPAL) 378 failf(data, "schannel: SNI or certificate check failed: %s", 379 Curl_sspi_strerror(conn, sspi_status)); 380 else 381 failf(data, "schannel: AcquireCredentialsHandle failed: %s", 382 Curl_sspi_strerror(conn, sspi_status)); 383 Curl_safefree(BACKEND->cred); 384 return CURLE_SSL_CONNECT_ERROR; 385 } 386 } 387 388 /* Warn if SNI is disabled due to use of an IP address */ 389 if(Curl_inet_pton(AF_INET, hostname, &addr) 390 #ifdef ENABLE_IPV6 391 || Curl_inet_pton(AF_INET6, hostname, &addr6) 392 #endif 393 ) { 394 infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); 395 } 396 397 #ifdef HAS_ALPN 398 if(BACKEND->use_alpn) { 399 int cur = 0; 400 int list_start_index = 0; 401 unsigned int *extension_len = NULL; 402 unsigned short* list_len = NULL; 403 404 /* The first four bytes will be an unsigned int indicating number 405 of bytes of data in the rest of the the buffer. */ 406 extension_len = (unsigned int *)(&alpn_buffer[cur]); 407 cur += sizeof(unsigned int); 408 409 /* The next four bytes are an indicator that this buffer will contain 410 ALPN data, as opposed to NPN, for example. */ 411 *(unsigned int *)&alpn_buffer[cur] = 412 SecApplicationProtocolNegotiationExt_ALPN; 413 cur += sizeof(unsigned int); 414 415 /* The next two bytes will be an unsigned short indicating the number 416 of bytes used to list the preferred protocols. */ 417 list_len = (unsigned short*)(&alpn_buffer[cur]); 418 cur += sizeof(unsigned short); 419 420 list_start_index = cur; 421 422 #ifdef USE_NGHTTP2 423 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { 424 memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); 425 cur += NGHTTP2_PROTO_ALPN_LEN; 426 infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); 427 } 428 #endif 429 430 alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH; 431 memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); 432 cur += ALPN_HTTP_1_1_LENGTH; 433 infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1); 434 435 *list_len = curlx_uitous(cur - list_start_index); 436 *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); 437 438 InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); 439 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 440 } 441 else 442 { 443 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 444 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 445 } 446 #else /* HAS_ALPN */ 447 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); 448 InitSecBufferDesc(&inbuf_desc, &inbuf, 1); 449 #endif 450 451 /* setup output buffer */ 452 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 453 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 454 455 /* setup request flags */ 456 BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | 457 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | 458 ISC_REQ_STREAM; 459 460 /* allocate memory for the security context handle */ 461 BACKEND->ctxt = (struct curl_schannel_ctxt *) 462 malloc(sizeof(struct curl_schannel_ctxt)); 463 if(!BACKEND->ctxt) { 464 failf(data, "schannel: unable to allocate memory"); 465 return CURLE_OUT_OF_MEMORY; 466 } 467 memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt)); 468 469 host_name = Curl_convert_UTF8_to_tchar(hostname); 470 if(!host_name) 471 return CURLE_OUT_OF_MEMORY; 472 473 /* Schannel InitializeSecurityContext: 474 https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx 475 476 At the moment we don't pass inbuf unless we're using ALPN since we only 477 use it for that, and Wine (for which we currently disable ALPN) is giving 478 us problems with inbuf regardless. https://github.com/curl/curl/issues/983 479 */ 480 sspi_status = s_pSecFn->InitializeSecurityContext( 481 &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0, 482 (BACKEND->use_alpn ? &inbuf_desc : NULL), 483 0, &BACKEND->ctxt->ctxt_handle, 484 &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); 485 486 Curl_unicodefree(host_name); 487 488 if(sspi_status != SEC_I_CONTINUE_NEEDED) { 489 if(sspi_status == SEC_E_WRONG_PRINCIPAL) 490 failf(data, "schannel: SNI or certificate check failed: %s", 491 Curl_sspi_strerror(conn, sspi_status)); 492 else 493 failf(data, "schannel: initial InitializeSecurityContext failed: %s", 494 Curl_sspi_strerror(conn, sspi_status)); 495 Curl_safefree(BACKEND->ctxt); 496 return CURLE_SSL_CONNECT_ERROR; 497 } 498 499 infof(data, "schannel: sending initial handshake data: " 500 "sending %lu bytes...\n", outbuf.cbBuffer); 501 502 /* send initial handshake data which is now stored in output buffer */ 503 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, 504 outbuf.cbBuffer, &written); 505 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 506 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { 507 failf(data, "schannel: failed to send initial handshake data: " 508 "sent %zd of %lu bytes", written, outbuf.cbBuffer); 509 return CURLE_SSL_CONNECT_ERROR; 510 } 511 512 infof(data, "schannel: sent initial handshake data: " 513 "sent %zd bytes\n", written); 514 515 BACKEND->recv_unrecoverable_err = CURLE_OK; 516 BACKEND->recv_sspi_close_notify = false; 517 BACKEND->recv_connection_closed = false; 518 BACKEND->encdata_is_incomplete = false; 519 520 /* continue to second handshake step */ 521 connssl->connecting_state = ssl_connect_2; 522 523 return CURLE_OK; 524 } 525 526 static CURLcode 527 schannel_connect_step2(struct connectdata *conn, int sockindex) 528 { 529 int i; 530 ssize_t nread = -1, written = -1; 531 struct Curl_easy *data = conn->data; 532 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 533 unsigned char *reallocated_buffer; 534 size_t reallocated_length; 535 SecBuffer outbuf[3]; 536 SecBufferDesc outbuf_desc; 537 SecBuffer inbuf[2]; 538 SecBufferDesc inbuf_desc; 539 SECURITY_STATUS sspi_status = SEC_E_OK; 540 TCHAR *host_name; 541 CURLcode result; 542 bool doread; 543 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 544 conn->host.name; 545 546 doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; 547 548 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", 549 hostname, conn->remote_port); 550 551 if(!BACKEND->cred || !BACKEND->ctxt) 552 return CURLE_SSL_CONNECT_ERROR; 553 554 /* buffer to store previously received and decrypted data */ 555 if(BACKEND->decdata_buffer == NULL) { 556 BACKEND->decdata_offset = 0; 557 BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 558 BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); 559 if(BACKEND->decdata_buffer == NULL) { 560 failf(data, "schannel: unable to allocate memory"); 561 return CURLE_OUT_OF_MEMORY; 562 } 563 } 564 565 /* buffer to store previously received and encrypted data */ 566 if(BACKEND->encdata_buffer == NULL) { 567 BACKEND->encdata_is_incomplete = false; 568 BACKEND->encdata_offset = 0; 569 BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; 570 BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); 571 if(BACKEND->encdata_buffer == NULL) { 572 failf(data, "schannel: unable to allocate memory"); 573 return CURLE_OUT_OF_MEMORY; 574 } 575 } 576 577 /* if we need a bigger buffer to read a full message, increase buffer now */ 578 if(BACKEND->encdata_length - BACKEND->encdata_offset < 579 CURL_SCHANNEL_BUFFER_FREE_SIZE) { 580 /* increase internal encrypted data buffer */ 581 reallocated_length = BACKEND->encdata_offset + 582 CURL_SCHANNEL_BUFFER_FREE_SIZE; 583 reallocated_buffer = realloc(BACKEND->encdata_buffer, 584 reallocated_length); 585 586 if(reallocated_buffer == NULL) { 587 failf(data, "schannel: unable to re-allocate memory"); 588 return CURLE_OUT_OF_MEMORY; 589 } 590 else { 591 BACKEND->encdata_buffer = reallocated_buffer; 592 BACKEND->encdata_length = reallocated_length; 593 } 594 } 595 596 for(;;) { 597 if(doread) { 598 /* read encrypted handshake data from socket */ 599 result = Curl_read_plain(conn->sock[sockindex], 600 (char *) (BACKEND->encdata_buffer + 601 BACKEND->encdata_offset), 602 BACKEND->encdata_length - 603 BACKEND->encdata_offset, 604 &nread); 605 if(result == CURLE_AGAIN) { 606 if(connssl->connecting_state != ssl_connect_2_writing) 607 connssl->connecting_state = ssl_connect_2_reading; 608 infof(data, "schannel: failed to receive handshake, " 609 "need more data\n"); 610 return CURLE_OK; 611 } 612 else if((result != CURLE_OK) || (nread == 0)) { 613 failf(data, "schannel: failed to receive handshake, " 614 "SSL/TLS connection failed"); 615 return CURLE_SSL_CONNECT_ERROR; 616 } 617 618 /* increase encrypted data buffer offset */ 619 BACKEND->encdata_offset += nread; 620 BACKEND->encdata_is_incomplete = false; 621 infof(data, "schannel: encrypted data got %zd\n", nread); 622 } 623 624 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 625 BACKEND->encdata_offset, BACKEND->encdata_length); 626 627 /* setup input buffers */ 628 InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), 629 curlx_uztoul(BACKEND->encdata_offset)); 630 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 631 InitSecBufferDesc(&inbuf_desc, inbuf, 2); 632 633 /* setup output buffers */ 634 InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); 635 InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); 636 InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); 637 InitSecBufferDesc(&outbuf_desc, outbuf, 3); 638 639 if(inbuf[0].pvBuffer == NULL) { 640 failf(data, "schannel: unable to allocate memory"); 641 return CURLE_OUT_OF_MEMORY; 642 } 643 644 /* copy received handshake data into input buffer */ 645 memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer, 646 BACKEND->encdata_offset); 647 648 host_name = Curl_convert_UTF8_to_tchar(hostname); 649 if(!host_name) 650 return CURLE_OUT_OF_MEMORY; 651 652 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx 653 */ 654 sspi_status = s_pSecFn->InitializeSecurityContext( 655 &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle, 656 host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, 657 &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); 658 659 Curl_unicodefree(host_name); 660 661 /* free buffer for received handshake data */ 662 Curl_safefree(inbuf[0].pvBuffer); 663 664 /* check if the handshake was incomplete */ 665 if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 666 BACKEND->encdata_is_incomplete = true; 667 connssl->connecting_state = ssl_connect_2_reading; 668 infof(data, "schannel: received incomplete message, need more data\n"); 669 return CURLE_OK; 670 } 671 672 /* If the server has requested a client certificate, attempt to continue 673 the handshake without one. This will allow connections to servers which 674 request a client certificate but do not require it. */ 675 if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && 676 !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { 677 BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; 678 connssl->connecting_state = ssl_connect_2_writing; 679 infof(data, "schannel: a client certificate has been requested\n"); 680 return CURLE_OK; 681 } 682 683 /* check if the handshake needs to be continued */ 684 if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { 685 for(i = 0; i < 3; i++) { 686 /* search for handshake tokens that need to be send */ 687 if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { 688 infof(data, "schannel: sending next handshake data: " 689 "sending %lu bytes...\n", outbuf[i].cbBuffer); 690 691 /* send handshake token to server */ 692 result = Curl_write_plain(conn, conn->sock[sockindex], 693 outbuf[i].pvBuffer, outbuf[i].cbBuffer, 694 &written); 695 if((result != CURLE_OK) || 696 (outbuf[i].cbBuffer != (size_t) written)) { 697 failf(data, "schannel: failed to send next handshake data: " 698 "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); 699 return CURLE_SSL_CONNECT_ERROR; 700 } 701 } 702 703 /* free obsolete buffer */ 704 if(outbuf[i].pvBuffer != NULL) { 705 s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); 706 } 707 } 708 } 709 else { 710 if(sspi_status == SEC_E_WRONG_PRINCIPAL) 711 failf(data, "schannel: SNI or certificate check failed: %s", 712 Curl_sspi_strerror(conn, sspi_status)); 713 else 714 failf(data, "schannel: next InitializeSecurityContext failed: %s", 715 Curl_sspi_strerror(conn, sspi_status)); 716 return sspi_status == SEC_E_UNTRUSTED_ROOT ? 717 CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR; 718 } 719 720 /* check if there was additional remaining encrypted data */ 721 if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { 722 infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); 723 /* 724 There are two cases where we could be getting extra data here: 725 1) If we're renegotiating a connection and the handshake is already 726 complete (from the server perspective), it can encrypted app data 727 (not handshake data) in an extra buffer at this point. 728 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a 729 connection and this extra data is part of the handshake. 730 We should process the data immediately; waiting for the socket to 731 be ready may fail since the server is done sending handshake data. 732 */ 733 /* check if the remaining data is less than the total amount 734 and therefore begins after the already processed data */ 735 if(BACKEND->encdata_offset > inbuf[1].cbBuffer) { 736 memmove(BACKEND->encdata_buffer, 737 (BACKEND->encdata_buffer + BACKEND->encdata_offset) - 738 inbuf[1].cbBuffer, inbuf[1].cbBuffer); 739 BACKEND->encdata_offset = inbuf[1].cbBuffer; 740 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 741 doread = FALSE; 742 continue; 743 } 744 } 745 } 746 else { 747 BACKEND->encdata_offset = 0; 748 } 749 break; 750 } 751 752 /* check if the handshake needs to be continued */ 753 if(sspi_status == SEC_I_CONTINUE_NEEDED) { 754 connssl->connecting_state = ssl_connect_2_reading; 755 return CURLE_OK; 756 } 757 758 /* check if the handshake is complete */ 759 if(sspi_status == SEC_E_OK) { 760 connssl->connecting_state = ssl_connect_3; 761 infof(data, "schannel: SSL/TLS handshake complete\n"); 762 } 763 764 #ifdef _WIN32_WCE 765 /* Windows CE doesn't do any server certificate validation. 766 We have to do it manually. */ 767 if(conn->ssl_config.verifypeer) 768 return verify_certificate(conn, sockindex); 769 #endif 770 771 return CURLE_OK; 772 } 773 774 static CURLcode 775 schannel_connect_step3(struct connectdata *conn, int sockindex) 776 { 777 CURLcode result = CURLE_OK; 778 struct Curl_easy *data = conn->data; 779 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 780 SECURITY_STATUS sspi_status = SEC_E_OK; 781 CERT_CONTEXT *ccert_context = NULL; 782 #ifndef CURL_DISABLE_VERBOSE_STRINGS 783 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 784 conn->host.name; 785 #endif 786 #ifdef HAS_ALPN 787 SecPkgContext_ApplicationProtocol alpn_result; 788 #endif 789 790 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 791 792 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", 793 hostname, conn->remote_port); 794 795 if(!BACKEND->cred) 796 return CURLE_SSL_CONNECT_ERROR; 797 798 /* check if the required context attributes are met */ 799 if(BACKEND->ret_flags != BACKEND->req_flags) { 800 if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT)) 801 failf(data, "schannel: failed to setup sequence detection"); 802 if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT)) 803 failf(data, "schannel: failed to setup replay detection"); 804 if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY)) 805 failf(data, "schannel: failed to setup confidentiality"); 806 if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY)) 807 failf(data, "schannel: failed to setup memory allocation"); 808 if(!(BACKEND->ret_flags & ISC_RET_STREAM)) 809 failf(data, "schannel: failed to setup stream orientation"); 810 return CURLE_SSL_CONNECT_ERROR; 811 } 812 813 #ifdef HAS_ALPN 814 if(BACKEND->use_alpn) { 815 sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 816 SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result); 817 818 if(sspi_status != SEC_E_OK) { 819 failf(data, "schannel: failed to retrieve ALPN result"); 820 return CURLE_SSL_CONNECT_ERROR; 821 } 822 823 if(alpn_result.ProtoNegoStatus == 824 SecApplicationProtocolNegotiationStatus_Success) { 825 826 infof(data, "schannel: ALPN, server accepted to use %.*s\n", 827 alpn_result.ProtocolIdSize, alpn_result.ProtocolId); 828 829 #ifdef USE_NGHTTP2 830 if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && 831 !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, 832 NGHTTP2_PROTO_VERSION_ID_LEN)) { 833 conn->negnpn = CURL_HTTP_VERSION_2; 834 } 835 else 836 #endif 837 if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH && 838 !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId, 839 ALPN_HTTP_1_1_LENGTH)) { 840 conn->negnpn = CURL_HTTP_VERSION_1_1; 841 } 842 } 843 else 844 infof(data, "ALPN, server did not agree to a protocol\n"); 845 } 846 #endif 847 848 /* save the current session data for possible re-use */ 849 if(SSL_SET_OPTION(primary.sessionid)) { 850 bool incache; 851 struct curl_schannel_cred *old_cred = NULL; 852 853 Curl_ssl_sessionid_lock(conn); 854 incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, 855 sockindex)); 856 if(incache) { 857 if(old_cred != BACKEND->cred) { 858 infof(data, "schannel: old credential handle is stale, removing\n"); 859 /* we're not taking old_cred ownership here, no refcount++ is needed */ 860 Curl_ssl_delsessionid(conn, (void *)old_cred); 861 incache = FALSE; 862 } 863 } 864 if(!incache) { 865 result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred, 866 sizeof(struct curl_schannel_cred), 867 sockindex); 868 if(result) { 869 Curl_ssl_sessionid_unlock(conn); 870 failf(data, "schannel: failed to store credential handle"); 871 return result; 872 } 873 else { 874 /* this cred session is now also referenced by sessionid cache */ 875 BACKEND->cred->refcount++; 876 infof(data, "schannel: stored credential handle in session cache\n"); 877 } 878 } 879 Curl_ssl_sessionid_unlock(conn); 880 } 881 882 if(data->set.ssl.certinfo) { 883 sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 884 SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); 885 886 if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { 887 failf(data, "schannel: failed to retrieve remote cert context"); 888 return CURLE_SSL_CONNECT_ERROR; 889 } 890 891 result = Curl_ssl_init_certinfo(data, 1); 892 if(!result) { 893 if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && 894 (ccert_context->cbCertEncoded > 0)) { 895 896 const char *beg = (const char *) ccert_context->pbCertEncoded; 897 const char *end = beg + ccert_context->cbCertEncoded; 898 result = Curl_extract_certinfo(conn, 0, beg, end); 899 } 900 } 901 CertFreeCertificateContext(ccert_context); 902 if(result) 903 return result; 904 } 905 906 connssl->connecting_state = ssl_connect_done; 907 908 return CURLE_OK; 909 } 910 911 static CURLcode 912 schannel_connect_common(struct connectdata *conn, int sockindex, 913 bool nonblocking, bool *done) 914 { 915 CURLcode result; 916 struct Curl_easy *data = conn->data; 917 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 918 curl_socket_t sockfd = conn->sock[sockindex]; 919 time_t timeout_ms; 920 int what; 921 922 /* check if the connection has already been established */ 923 if(ssl_connection_complete == connssl->state) { 924 *done = TRUE; 925 return CURLE_OK; 926 } 927 928 if(ssl_connect_1 == connssl->connecting_state) { 929 /* check out how much more time we're allowed */ 930 timeout_ms = Curl_timeleft(data, NULL, TRUE); 931 932 if(timeout_ms < 0) { 933 /* no need to continue if time already is up */ 934 failf(data, "SSL/TLS connection timeout"); 935 return CURLE_OPERATION_TIMEDOUT; 936 } 937 938 result = schannel_connect_step1(conn, sockindex); 939 if(result) 940 return result; 941 } 942 943 while(ssl_connect_2 == connssl->connecting_state || 944 ssl_connect_2_reading == connssl->connecting_state || 945 ssl_connect_2_writing == connssl->connecting_state) { 946 947 /* check out how much more time we're allowed */ 948 timeout_ms = Curl_timeleft(data, NULL, TRUE); 949 950 if(timeout_ms < 0) { 951 /* no need to continue if time already is up */ 952 failf(data, "SSL/TLS connection timeout"); 953 return CURLE_OPERATION_TIMEDOUT; 954 } 955 956 /* if ssl is expecting something, check if it's available. */ 957 if(connssl->connecting_state == ssl_connect_2_reading 958 || connssl->connecting_state == ssl_connect_2_writing) { 959 960 curl_socket_t writefd = ssl_connect_2_writing == 961 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; 962 curl_socket_t readfd = ssl_connect_2_reading == 963 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; 964 965 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 966 nonblocking ? 0 : timeout_ms); 967 if(what < 0) { 968 /* fatal error */ 969 failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO); 970 return CURLE_SSL_CONNECT_ERROR; 971 } 972 else if(0 == what) { 973 if(nonblocking) { 974 *done = FALSE; 975 return CURLE_OK; 976 } 977 else { 978 /* timeout */ 979 failf(data, "SSL/TLS connection timeout"); 980 return CURLE_OPERATION_TIMEDOUT; 981 } 982 } 983 /* socket is readable or writable */ 984 } 985 986 /* Run transaction, and return to the caller if it failed or if 987 * this connection is part of a multi handle and this loop would 988 * execute again. This permits the owner of a multi handle to 989 * abort a connection attempt before step2 has completed while 990 * ensuring that a client using select() or epoll() will always 991 * have a valid fdset to wait on. 992 */ 993 result = schannel_connect_step2(conn, sockindex); 994 if(result || (nonblocking && 995 (ssl_connect_2 == connssl->connecting_state || 996 ssl_connect_2_reading == connssl->connecting_state || 997 ssl_connect_2_writing == connssl->connecting_state))) 998 return result; 999 1000 } /* repeat step2 until all transactions are done. */ 1001 1002 if(ssl_connect_3 == connssl->connecting_state) { 1003 result = schannel_connect_step3(conn, sockindex); 1004 if(result) 1005 return result; 1006 } 1007 1008 if(ssl_connect_done == connssl->connecting_state) { 1009 connssl->state = ssl_connection_complete; 1010 conn->recv[sockindex] = schannel_recv; 1011 conn->send[sockindex] = schannel_send; 1012 *done = TRUE; 1013 } 1014 else 1015 *done = FALSE; 1016 1017 /* reset our connection state machine */ 1018 connssl->connecting_state = ssl_connect_1; 1019 1020 return CURLE_OK; 1021 } 1022 1023 static ssize_t 1024 schannel_send(struct connectdata *conn, int sockindex, 1025 const void *buf, size_t len, CURLcode *err) 1026 { 1027 ssize_t written = -1; 1028 size_t data_len = 0; 1029 unsigned char *data = NULL; 1030 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1031 SecBuffer outbuf[4]; 1032 SecBufferDesc outbuf_desc; 1033 SECURITY_STATUS sspi_status = SEC_E_OK; 1034 CURLcode result; 1035 1036 /* check if the maximum stream sizes were queried */ 1037 if(BACKEND->stream_sizes.cbMaximumMessage == 0) { 1038 sspi_status = s_pSecFn->QueryContextAttributes( 1039 &BACKEND->ctxt->ctxt_handle, 1040 SECPKG_ATTR_STREAM_SIZES, 1041 &BACKEND->stream_sizes); 1042 if(sspi_status != SEC_E_OK) { 1043 *err = CURLE_SEND_ERROR; 1044 return -1; 1045 } 1046 } 1047 1048 /* check if the buffer is longer than the maximum message length */ 1049 if(len > BACKEND->stream_sizes.cbMaximumMessage) { 1050 len = BACKEND->stream_sizes.cbMaximumMessage; 1051 } 1052 1053 /* calculate the complete message length and allocate a buffer for it */ 1054 data_len = BACKEND->stream_sizes.cbHeader + len + 1055 BACKEND->stream_sizes.cbTrailer; 1056 data = (unsigned char *) malloc(data_len); 1057 if(data == NULL) { 1058 *err = CURLE_OUT_OF_MEMORY; 1059 return -1; 1060 } 1061 1062 /* setup output buffers (header, data, trailer, empty) */ 1063 InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, 1064 data, BACKEND->stream_sizes.cbHeader); 1065 InitSecBuffer(&outbuf[1], SECBUFFER_DATA, 1066 data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); 1067 InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, 1068 data + BACKEND->stream_sizes.cbHeader + len, 1069 BACKEND->stream_sizes.cbTrailer); 1070 InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); 1071 InitSecBufferDesc(&outbuf_desc, outbuf, 4); 1072 1073 /* copy data into output buffer */ 1074 memcpy(outbuf[1].pvBuffer, buf, len); 1075 1076 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ 1077 sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0, 1078 &outbuf_desc, 0); 1079 1080 /* check if the message was encrypted */ 1081 if(sspi_status == SEC_E_OK) { 1082 written = 0; 1083 1084 /* send the encrypted message including header, data and trailer */ 1085 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; 1086 1087 /* 1088 It's important to send the full message which includes the header, 1089 encrypted payload, and trailer. Until the client receives all the 1090 data a coherent message has not been delivered and the client 1091 can't read any of it. 1092 1093 If we wanted to buffer the unwritten encrypted bytes, we would 1094 tell the client that all data it has requested to be sent has been 1095 sent. The unwritten encrypted bytes would be the first bytes to 1096 send on the next invocation. 1097 Here's the catch with this - if we tell the client that all the 1098 bytes have been sent, will the client call this method again to 1099 send the buffered data? Looking at who calls this function, it 1100 seems the answer is NO. 1101 */ 1102 1103 /* send entire message or fail */ 1104 while(len > (size_t)written) { 1105 ssize_t this_write; 1106 time_t timeleft; 1107 int what; 1108 1109 this_write = 0; 1110 1111 timeleft = Curl_timeleft(conn->data, NULL, FALSE); 1112 if(timeleft < 0) { 1113 /* we already got the timeout */ 1114 failf(conn->data, "schannel: timed out sending data " 1115 "(bytes sent: %zd)", written); 1116 *err = CURLE_OPERATION_TIMEDOUT; 1117 written = -1; 1118 break; 1119 } 1120 1121 what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft); 1122 if(what < 0) { 1123 /* fatal error */ 1124 failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1125 *err = CURLE_SEND_ERROR; 1126 written = -1; 1127 break; 1128 } 1129 else if(0 == what) { 1130 failf(conn->data, "schannel: timed out sending data " 1131 "(bytes sent: %zd)", written); 1132 *err = CURLE_OPERATION_TIMEDOUT; 1133 written = -1; 1134 break; 1135 } 1136 /* socket is writable */ 1137 1138 result = Curl_write_plain(conn, conn->sock[sockindex], data + written, 1139 len - written, &this_write); 1140 if(result == CURLE_AGAIN) 1141 continue; 1142 else if(result != CURLE_OK) { 1143 *err = result; 1144 written = -1; 1145 break; 1146 } 1147 1148 written += this_write; 1149 } 1150 } 1151 else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { 1152 *err = CURLE_OUT_OF_MEMORY; 1153 } 1154 else{ 1155 *err = CURLE_SEND_ERROR; 1156 } 1157 1158 Curl_safefree(data); 1159 1160 if(len == (size_t)written) 1161 /* Encrypted message including header, data and trailer entirely sent. 1162 The return value is the number of unencrypted bytes that were sent. */ 1163 written = outbuf[1].cbBuffer; 1164 1165 return written; 1166 } 1167 1168 static ssize_t 1169 schannel_recv(struct connectdata *conn, int sockindex, 1170 char *buf, size_t len, CURLcode *err) 1171 { 1172 size_t size = 0; 1173 ssize_t nread = -1; 1174 struct Curl_easy *data = conn->data; 1175 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1176 unsigned char *reallocated_buffer; 1177 size_t reallocated_length; 1178 bool done = FALSE; 1179 SecBuffer inbuf[4]; 1180 SecBufferDesc inbuf_desc; 1181 SECURITY_STATUS sspi_status = SEC_E_OK; 1182 /* we want the length of the encrypted buffer to be at least large enough 1183 that it can hold all the bytes requested and some TLS record overhead. */ 1184 size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; 1185 1186 /**************************************************************************** 1187 * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup. 1188 * The pattern for return error is set *err, optional infof, goto cleanup. 1189 * 1190 * Our priority is to always return as much decrypted data to the caller as 1191 * possible, even if an error occurs. The state of the decrypted buffer must 1192 * always be valid. Transfer of decrypted data to the caller's buffer is 1193 * handled in the cleanup. 1194 */ 1195 1196 infof(data, "schannel: client wants to read %zu bytes\n", len); 1197 *err = CURLE_OK; 1198 1199 if(len && len <= BACKEND->decdata_offset) { 1200 infof(data, "schannel: enough decrypted data is already available\n"); 1201 goto cleanup; 1202 } 1203 else if(BACKEND->recv_unrecoverable_err) { 1204 *err = BACKEND->recv_unrecoverable_err; 1205 infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); 1206 goto cleanup; 1207 } 1208 else if(BACKEND->recv_sspi_close_notify) { 1209 /* once a server has indicated shutdown there is no more encrypted data */ 1210 infof(data, "schannel: server indicated shutdown in a prior call\n"); 1211 goto cleanup; 1212 } 1213 else if(!len) { 1214 /* It's debatable what to return when !len. Regardless we can't return 1215 immediately because there may be data to decrypt (in the case we want to 1216 decrypt all encrypted cached data) so handle !len later in cleanup. 1217 */ 1218 ; /* do nothing */ 1219 } 1220 else if(!BACKEND->recv_connection_closed) { 1221 /* increase enc buffer in order to fit the requested amount of data */ 1222 size = BACKEND->encdata_length - BACKEND->encdata_offset; 1223 if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || 1224 BACKEND->encdata_length < min_encdata_length) { 1225 reallocated_length = BACKEND->encdata_offset + 1226 CURL_SCHANNEL_BUFFER_FREE_SIZE; 1227 if(reallocated_length < min_encdata_length) { 1228 reallocated_length = min_encdata_length; 1229 } 1230 reallocated_buffer = realloc(BACKEND->encdata_buffer, 1231 reallocated_length); 1232 if(reallocated_buffer == NULL) { 1233 *err = CURLE_OUT_OF_MEMORY; 1234 failf(data, "schannel: unable to re-allocate memory"); 1235 goto cleanup; 1236 } 1237 1238 BACKEND->encdata_buffer = reallocated_buffer; 1239 BACKEND->encdata_length = reallocated_length; 1240 size = BACKEND->encdata_length - BACKEND->encdata_offset; 1241 infof(data, "schannel: encdata_buffer resized %zu\n", 1242 BACKEND->encdata_length); 1243 } 1244 1245 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 1246 BACKEND->encdata_offset, BACKEND->encdata_length); 1247 1248 /* read encrypted data from socket */ 1249 *err = Curl_read_plain(conn->sock[sockindex], 1250 (char *)(BACKEND->encdata_buffer + 1251 BACKEND->encdata_offset), 1252 size, &nread); 1253 if(*err) { 1254 nread = -1; 1255 if(*err == CURLE_AGAIN) 1256 infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n"); 1257 else if(*err == CURLE_RECV_ERROR) 1258 infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); 1259 else 1260 infof(data, "schannel: Curl_read_plain returned error %d\n", *err); 1261 } 1262 else if(nread == 0) { 1263 BACKEND->recv_connection_closed = true; 1264 infof(data, "schannel: server closed the connection\n"); 1265 } 1266 else if(nread > 0) { 1267 BACKEND->encdata_offset += (size_t)nread; 1268 BACKEND->encdata_is_incomplete = false; 1269 infof(data, "schannel: encrypted data got %zd\n", nread); 1270 } 1271 } 1272 1273 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 1274 BACKEND->encdata_offset, BACKEND->encdata_length); 1275 1276 /* decrypt loop */ 1277 while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && 1278 (!len || BACKEND->decdata_offset < len || 1279 BACKEND->recv_connection_closed)) { 1280 /* prepare data buffer for DecryptMessage call */ 1281 InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer, 1282 curlx_uztoul(BACKEND->encdata_offset)); 1283 1284 /* we need 3 more empty input buffers for possible output */ 1285 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); 1286 InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); 1287 InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); 1288 InitSecBufferDesc(&inbuf_desc, inbuf, 4); 1289 1290 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx 1291 */ 1292 sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle, 1293 &inbuf_desc, 0, NULL); 1294 1295 /* check if everything went fine (server may want to renegotiate 1296 or shutdown the connection context) */ 1297 if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || 1298 sspi_status == SEC_I_CONTEXT_EXPIRED) { 1299 /* check for successfully decrypted data, even before actual 1300 renegotiation or shutdown of the connection context */ 1301 if(inbuf[1].BufferType == SECBUFFER_DATA) { 1302 infof(data, "schannel: decrypted data length: %lu\n", 1303 inbuf[1].cbBuffer); 1304 1305 /* increase buffer in order to fit the received amount of data */ 1306 size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? 1307 inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; 1308 if(BACKEND->decdata_length - BACKEND->decdata_offset < size || 1309 BACKEND->decdata_length < len) { 1310 /* increase internal decrypted data buffer */ 1311 reallocated_length = BACKEND->decdata_offset + size; 1312 /* make sure that the requested amount of data fits */ 1313 if(reallocated_length < len) { 1314 reallocated_length = len; 1315 } 1316 reallocated_buffer = realloc(BACKEND->decdata_buffer, 1317 reallocated_length); 1318 if(reallocated_buffer == NULL) { 1319 *err = CURLE_OUT_OF_MEMORY; 1320 failf(data, "schannel: unable to re-allocate memory"); 1321 goto cleanup; 1322 } 1323 BACKEND->decdata_buffer = reallocated_buffer; 1324 BACKEND->decdata_length = reallocated_length; 1325 } 1326 1327 /* copy decrypted data to internal buffer */ 1328 size = inbuf[1].cbBuffer; 1329 if(size) { 1330 memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset, 1331 inbuf[1].pvBuffer, size); 1332 BACKEND->decdata_offset += size; 1333 } 1334 1335 infof(data, "schannel: decrypted data added: %zu\n", size); 1336 infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", 1337 BACKEND->decdata_offset, BACKEND->decdata_length); 1338 } 1339 1340 /* check for remaining encrypted data */ 1341 if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { 1342 infof(data, "schannel: encrypted data length: %lu\n", 1343 inbuf[3].cbBuffer); 1344 1345 /* check if the remaining data is less than the total amount 1346 * and therefore begins after the already processed data 1347 */ 1348 if(BACKEND->encdata_offset > inbuf[3].cbBuffer) { 1349 /* move remaining encrypted data forward to the beginning of 1350 buffer */ 1351 memmove(BACKEND->encdata_buffer, 1352 (BACKEND->encdata_buffer + BACKEND->encdata_offset) - 1353 inbuf[3].cbBuffer, inbuf[3].cbBuffer); 1354 BACKEND->encdata_offset = inbuf[3].cbBuffer; 1355 } 1356 1357 infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", 1358 BACKEND->encdata_offset, BACKEND->encdata_length); 1359 } 1360 else { 1361 /* reset encrypted buffer offset, because there is no data remaining */ 1362 BACKEND->encdata_offset = 0; 1363 } 1364 1365 /* check if server wants to renegotiate the connection context */ 1366 if(sspi_status == SEC_I_RENEGOTIATE) { 1367 infof(data, "schannel: remote party requests renegotiation\n"); 1368 if(*err && *err != CURLE_AGAIN) { 1369 infof(data, "schannel: can't renogotiate, an error is pending\n"); 1370 goto cleanup; 1371 } 1372 if(BACKEND->encdata_offset) { 1373 *err = CURLE_RECV_ERROR; 1374 infof(data, "schannel: can't renogotiate, " 1375 "encrypted data available\n"); 1376 goto cleanup; 1377 } 1378 /* begin renegotiation */ 1379 infof(data, "schannel: renegotiating SSL/TLS connection\n"); 1380 connssl->state = ssl_connection_negotiating; 1381 connssl->connecting_state = ssl_connect_2_writing; 1382 *err = schannel_connect_common(conn, sockindex, FALSE, &done); 1383 if(*err) { 1384 infof(data, "schannel: renegotiation failed\n"); 1385 goto cleanup; 1386 } 1387 /* now retry receiving data */ 1388 sspi_status = SEC_E_OK; 1389 infof(data, "schannel: SSL/TLS connection renegotiated\n"); 1390 continue; 1391 } 1392 /* check if the server closed the connection */ 1393 else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { 1394 /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not 1395 returned so we have to work around that in cleanup. */ 1396 BACKEND->recv_sspi_close_notify = true; 1397 if(!BACKEND->recv_connection_closed) { 1398 BACKEND->recv_connection_closed = true; 1399 infof(data, "schannel: server closed the connection\n"); 1400 } 1401 goto cleanup; 1402 } 1403 } 1404 else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { 1405 BACKEND->encdata_is_incomplete = true; 1406 if(!*err) 1407 *err = CURLE_AGAIN; 1408 infof(data, "schannel: failed to decrypt data, need more data\n"); 1409 goto cleanup; 1410 } 1411 else { 1412 *err = CURLE_RECV_ERROR; 1413 infof(data, "schannel: failed to read data from server: %s\n", 1414 Curl_sspi_strerror(conn, sspi_status)); 1415 goto cleanup; 1416 } 1417 } 1418 1419 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 1420 BACKEND->encdata_offset, BACKEND->encdata_length); 1421 1422 infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", 1423 BACKEND->decdata_offset, BACKEND->decdata_length); 1424 1425 cleanup: 1426 /* Warning- there is no guarantee the encdata state is valid at this point */ 1427 infof(data, "schannel: schannel_recv cleanup\n"); 1428 1429 /* Error if the connection has closed without a close_notify. 1430 Behavior here is a matter of debate. We don't want to be vulnerable to a 1431 truncation attack however there's some browser precedent for ignoring the 1432 close_notify for compatibility reasons. 1433 Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't 1434 return close_notify. In that case if the connection was closed we assume it 1435 was graceful (close_notify) since there doesn't seem to be a way to tell. 1436 */ 1437 if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed && 1438 !BACKEND->recv_sspi_close_notify) { 1439 bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, 1440 VERSION_EQUAL); 1441 1442 if(isWin2k && sspi_status == SEC_E_OK) 1443 BACKEND->recv_sspi_close_notify = true; 1444 else { 1445 *err = CURLE_RECV_ERROR; 1446 infof(data, "schannel: server closed abruptly (missing close_notify)\n"); 1447 } 1448 } 1449 1450 /* Any error other than CURLE_AGAIN is an unrecoverable error. */ 1451 if(*err && *err != CURLE_AGAIN) 1452 BACKEND->recv_unrecoverable_err = *err; 1453 1454 size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset; 1455 if(size) { 1456 memcpy(buf, BACKEND->decdata_buffer, size); 1457 memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, 1458 BACKEND->decdata_offset - size); 1459 BACKEND->decdata_offset -= size; 1460 1461 infof(data, "schannel: decrypted data returned %zu\n", size); 1462 infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", 1463 BACKEND->decdata_offset, BACKEND->decdata_length); 1464 *err = CURLE_OK; 1465 return (ssize_t)size; 1466 } 1467 1468 if(!*err && !BACKEND->recv_connection_closed) 1469 *err = CURLE_AGAIN; 1470 1471 /* It's debatable what to return when !len. We could return whatever error we 1472 got from decryption but instead we override here so the return is consistent. 1473 */ 1474 if(!len) 1475 *err = CURLE_OK; 1476 1477 return *err ? -1 : 0; 1478 } 1479 1480 static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, 1481 int sockindex, bool *done) 1482 { 1483 return schannel_connect_common(conn, sockindex, TRUE, done); 1484 } 1485 1486 static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) 1487 { 1488 CURLcode result; 1489 bool done = FALSE; 1490 1491 result = schannel_connect_common(conn, sockindex, FALSE, &done); 1492 if(result) 1493 return result; 1494 1495 DEBUGASSERT(done); 1496 1497 return CURLE_OK; 1498 } 1499 1500 static bool Curl_schannel_data_pending(const struct connectdata *conn, 1501 int sockindex) 1502 { 1503 const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1504 1505 if(connssl->use) /* SSL/TLS is in use */ 1506 return (BACKEND->decdata_offset > 0 || 1507 (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete)); 1508 else 1509 return FALSE; 1510 } 1511 1512 static void Curl_schannel_close(struct connectdata *conn, int sockindex) 1513 { 1514 if(conn->ssl[sockindex].use) 1515 /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ 1516 Curl_ssl_shutdown(conn, sockindex); 1517 } 1518 1519 static void Curl_schannel_session_free(void *ptr) 1520 { 1521 /* this is expected to be called under sessionid lock */ 1522 struct curl_schannel_cred *cred = ptr; 1523 1524 cred->refcount--; 1525 if(cred->refcount == 0) { 1526 s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); 1527 Curl_safefree(cred); 1528 } 1529 } 1530 1531 static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) 1532 { 1533 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx 1534 * Shutting Down an Schannel Connection 1535 */ 1536 struct Curl_easy *data = conn->data; 1537 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1538 char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : 1539 conn->host.name; 1540 1541 infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", 1542 hostname, conn->remote_port); 1543 1544 if(BACKEND->cred && BACKEND->ctxt) { 1545 SecBufferDesc BuffDesc; 1546 SecBuffer Buffer; 1547 SECURITY_STATUS sspi_status; 1548 SecBuffer outbuf; 1549 SecBufferDesc outbuf_desc; 1550 CURLcode result; 1551 TCHAR *host_name; 1552 DWORD dwshut = SCHANNEL_SHUTDOWN; 1553 1554 InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); 1555 InitSecBufferDesc(&BuffDesc, &Buffer, 1); 1556 1557 sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, 1558 &BuffDesc); 1559 1560 if(sspi_status != SEC_E_OK) 1561 failf(data, "schannel: ApplyControlToken failure: %s", 1562 Curl_sspi_strerror(conn, sspi_status)); 1563 1564 host_name = Curl_convert_UTF8_to_tchar(hostname); 1565 if(!host_name) 1566 return CURLE_OUT_OF_MEMORY; 1567 1568 /* setup output buffer */ 1569 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); 1570 InitSecBufferDesc(&outbuf_desc, &outbuf, 1); 1571 1572 sspi_status = s_pSecFn->InitializeSecurityContext( 1573 &BACKEND->cred->cred_handle, 1574 &BACKEND->ctxt->ctxt_handle, 1575 host_name, 1576 BACKEND->req_flags, 1577 0, 1578 0, 1579 NULL, 1580 0, 1581 &BACKEND->ctxt->ctxt_handle, 1582 &outbuf_desc, 1583 &BACKEND->ret_flags, 1584 &BACKEND->ctxt->time_stamp); 1585 1586 Curl_unicodefree(host_name); 1587 1588 if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { 1589 /* send close message which is in output buffer */ 1590 ssize_t written; 1591 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, 1592 outbuf.cbBuffer, &written); 1593 1594 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); 1595 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { 1596 infof(data, "schannel: failed to send close msg: %s" 1597 " (bytes written: %zd)\n", curl_easy_strerror(result), written); 1598 } 1599 } 1600 } 1601 1602 /* free SSPI Schannel API security context handle */ 1603 if(BACKEND->ctxt) { 1604 infof(data, "schannel: clear security context handle\n"); 1605 s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); 1606 Curl_safefree(BACKEND->ctxt); 1607 } 1608 1609 /* free SSPI Schannel API credential handle */ 1610 if(BACKEND->cred) { 1611 Curl_ssl_sessionid_lock(conn); 1612 Curl_schannel_session_free(BACKEND->cred); 1613 Curl_ssl_sessionid_unlock(conn); 1614 BACKEND->cred = NULL; 1615 } 1616 1617 /* free internal buffer for received encrypted data */ 1618 if(BACKEND->encdata_buffer != NULL) { 1619 Curl_safefree(BACKEND->encdata_buffer); 1620 BACKEND->encdata_length = 0; 1621 BACKEND->encdata_offset = 0; 1622 BACKEND->encdata_is_incomplete = false; 1623 } 1624 1625 /* free internal buffer for received decrypted data */ 1626 if(BACKEND->decdata_buffer != NULL) { 1627 Curl_safefree(BACKEND->decdata_buffer); 1628 BACKEND->decdata_length = 0; 1629 BACKEND->decdata_offset = 0; 1630 } 1631 1632 return CURLE_OK; 1633 } 1634 1635 static int Curl_schannel_init(void) 1636 { 1637 return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); 1638 } 1639 1640 static void Curl_schannel_cleanup(void) 1641 { 1642 Curl_sspi_global_cleanup(); 1643 } 1644 1645 static size_t Curl_schannel_version(char *buffer, size_t size) 1646 { 1647 size = snprintf(buffer, size, "WinSSL"); 1648 1649 return size; 1650 } 1651 1652 static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, 1653 unsigned char *entropy, size_t length) 1654 { 1655 HCRYPTPROV hCryptProv = 0; 1656 1657 (void)data; 1658 1659 if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 1660 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) 1661 return CURLE_FAILED_INIT; 1662 1663 if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { 1664 CryptReleaseContext(hCryptProv, 0UL); 1665 return CURLE_FAILED_INIT; 1666 } 1667 1668 CryptReleaseContext(hCryptProv, 0UL); 1669 return CURLE_OK; 1670 } 1671 1672 #ifdef _WIN32_WCE 1673 static CURLcode verify_certificate(struct connectdata *conn, int sockindex) 1674 { 1675 SECURITY_STATUS status; 1676 struct Curl_easy *data = conn->data; 1677 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1678 CURLcode result = CURLE_OK; 1679 CERT_CONTEXT *pCertContextServer = NULL; 1680 const CERT_CHAIN_CONTEXT *pChainContext = NULL; 1681 const char * const conn_hostname = SSL_IS_PROXY() ? 1682 conn->http_proxy.host.name : 1683 conn->host.name; 1684 1685 status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, 1686 SECPKG_ATTR_REMOTE_CERT_CONTEXT, 1687 &pCertContextServer); 1688 1689 if((status != SEC_E_OK) || (pCertContextServer == NULL)) { 1690 failf(data, "schannel: Failed to read remote certificate context: %s", 1691 Curl_sspi_strerror(conn, status)); 1692 result = CURLE_PEER_FAILED_VERIFICATION; 1693 } 1694 1695 if(result == CURLE_OK) { 1696 CERT_CHAIN_PARA ChainPara; 1697 memset(&ChainPara, 0, sizeof(ChainPara)); 1698 ChainPara.cbSize = sizeof(ChainPara); 1699 1700 if(!CertGetCertificateChain(NULL, 1701 pCertContextServer, 1702 NULL, 1703 pCertContextServer->hCertStore, 1704 &ChainPara, 1705 (data->set.ssl.no_revoke ? 0 : 1706 CERT_CHAIN_REVOCATION_CHECK_CHAIN), 1707 NULL, 1708 &pChainContext)) { 1709 failf(data, "schannel: CertGetCertificateChain failed: %s", 1710 Curl_sspi_strerror(conn, GetLastError())); 1711 pChainContext = NULL; 1712 result = CURLE_PEER_FAILED_VERIFICATION; 1713 } 1714 1715 if(result == CURLE_OK) { 1716 CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; 1717 DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED); 1718 dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; 1719 if(dwTrustErrorMask) { 1720 if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED) 1721 failf(data, "schannel: CertGetCertificateChain trust error" 1722 " CERT_TRUST_IS_REVOKED"); 1723 else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) 1724 failf(data, "schannel: CertGetCertificateChain trust error" 1725 " CERT_TRUST_IS_PARTIAL_CHAIN"); 1726 else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) 1727 failf(data, "schannel: CertGetCertificateChain trust error" 1728 " CERT_TRUST_IS_UNTRUSTED_ROOT"); 1729 else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) 1730 failf(data, "schannel: CertGetCertificateChain trust error" 1731 " CERT_TRUST_IS_NOT_TIME_VALID"); 1732 else 1733 failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", 1734 dwTrustErrorMask); 1735 result = CURLE_PEER_FAILED_VERIFICATION; 1736 } 1737 } 1738 } 1739 1740 if(result == CURLE_OK) { 1741 if(conn->ssl_config.verifyhost) { 1742 TCHAR cert_hostname_buff[256]; 1743 DWORD len; 1744 1745 /* TODO: Fix this for certificates with multiple alternative names. 1746 Right now we're only asking for the first preferred alternative name. 1747 Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG 1748 (if WinCE supports that?) and run this section in a loop for each. 1749 https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx 1750 curl: (51) schannel: CertGetNameString() certificate hostname 1751 (.google.com) did not match connection (google.com) 1752 */ 1753 len = CertGetNameString(pCertContextServer, 1754 CERT_NAME_DNS_TYPE, 1755 CERT_NAME_DISABLE_IE4_UTF8_FLAG, 1756 NULL, 1757 cert_hostname_buff, 1758 256); 1759 if(len > 0) { 1760 const char *cert_hostname; 1761 1762 /* Comparing the cert name and the connection hostname encoded as UTF-8 1763 * is acceptable since both values are assumed to use ASCII 1764 * (or some equivalent) encoding 1765 */ 1766 cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff); 1767 if(!cert_hostname) { 1768 result = CURLE_OUT_OF_MEMORY; 1769 } 1770 else{ 1771 int match_result; 1772 1773 match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name); 1774 if(match_result == CURL_HOST_MATCH) { 1775 infof(data, 1776 "schannel: connection hostname (%s) validated " 1777 "against certificate name (%s)\n", 1778 conn->host.name, 1779 cert_hostname); 1780 result = CURLE_OK; 1781 } 1782 else{ 1783 failf(data, 1784 "schannel: connection hostname (%s) " 1785 "does not match certificate name (%s)", 1786 conn->host.name, 1787 cert_hostname); 1788 result = CURLE_PEER_FAILED_VERIFICATION; 1789 } 1790 Curl_unicodefree(cert_hostname); 1791 } 1792 } 1793 else { 1794 failf(data, 1795 "schannel: CertGetNameString did not provide any " 1796 "certificate name information"); 1797 result = CURLE_PEER_FAILED_VERIFICATION; 1798 } 1799 } 1800 } 1801 1802 if(pChainContext) 1803 CertFreeCertificateChain(pChainContext); 1804 1805 if(pCertContextServer) 1806 CertFreeCertificateContext(pCertContextServer); 1807 1808 return result; 1809 } 1810 #endif /* _WIN32_WCE */ 1811 1812 static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, 1813 CURLINFO info UNUSED_PARAM) 1814 { 1815 (void)info; 1816 return &BACKEND->ctxt->ctxt_handle; 1817 } 1818 1819 const struct Curl_ssl Curl_ssl_schannel = { 1820 { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ 1821 1822 0, /* have_ca_path */ 1823 1, /* have_certinfo */ 1824 0, /* have_pinnedpubkey */ 1825 0, /* have_ssl_ctx */ 1826 0, /* support_https_proxy */ 1827 1828 sizeof(struct ssl_backend_data), 1829 1830 Curl_schannel_init, /* init */ 1831 Curl_schannel_cleanup, /* cleanup */ 1832 Curl_schannel_version, /* version */ 1833 Curl_none_check_cxn, /* check_cxn */ 1834 Curl_schannel_shutdown, /* shutdown */ 1835 Curl_schannel_data_pending, /* data_pending */ 1836 Curl_schannel_random, /* random */ 1837 Curl_none_cert_status_request, /* cert_status_request */ 1838 Curl_schannel_connect, /* connect */ 1839 Curl_schannel_connect_nonblocking, /* connect_nonblocking */ 1840 Curl_schannel_get_internals, /* get_internals */ 1841 Curl_schannel_close, /* close_one */ 1842 Curl_none_close_all, /* close_all */ 1843 Curl_schannel_session_free, /* session_free */ 1844 Curl_none_set_engine, /* set_engine */ 1845 Curl_none_set_engine_default, /* set_engine_default */ 1846 Curl_none_engines_list, /* engines_list */ 1847 Curl_none_false_start, /* false_start */ 1848 Curl_none_md5sum, /* md5sum */ 1849 NULL /* sha256sum */ 1850 }; 1851 1852 #endif /* USE_SCHANNEL */ 1853