quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

schannel.c (92835B)


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