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