Home | History | Annotate | Download | only in vtls
      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