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