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