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