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