1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker /* This file is for implementing all "generic" SSL functions that all libcurl
26*6236dae4SAndroid Build Coastguard Worker internals should use. It is then responsible for calling the proper
27*6236dae4SAndroid Build Coastguard Worker "backend" function.
28*6236dae4SAndroid Build Coastguard Worker
29*6236dae4SAndroid Build Coastguard Worker SSL-functions in libcurl should call functions in this source file, and not
30*6236dae4SAndroid Build Coastguard Worker to any specific SSL-layer.
31*6236dae4SAndroid Build Coastguard Worker
32*6236dae4SAndroid Build Coastguard Worker Curl_ssl_ - prefix for generic ones
33*6236dae4SAndroid Build Coastguard Worker
34*6236dae4SAndroid Build Coastguard Worker Note that this source code uses the functions of the configured SSL
35*6236dae4SAndroid Build Coastguard Worker backend via the global Curl_ssl instance.
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker "SSL/TLS Strong Encryption: An Introduction"
38*6236dae4SAndroid Build Coastguard Worker https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
39*6236dae4SAndroid Build Coastguard Worker */
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
42*6236dae4SAndroid Build Coastguard Worker
43*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_TYPES_H
44*6236dae4SAndroid Build Coastguard Worker #include <sys/types.h>
45*6236dae4SAndroid Build Coastguard Worker #endif
46*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_STAT_H
47*6236dae4SAndroid Build Coastguard Worker #include <sys/stat.h>
48*6236dae4SAndroid Build Coastguard Worker #endif
49*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
50*6236dae4SAndroid Build Coastguard Worker #include <fcntl.h>
51*6236dae4SAndroid Build Coastguard Worker #endif
52*6236dae4SAndroid Build Coastguard Worker
53*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
54*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
55*6236dae4SAndroid Build Coastguard Worker
56*6236dae4SAndroid Build Coastguard Worker #include "vtls.h" /* generic SSL protos etc */
57*6236dae4SAndroid Build Coastguard Worker #include "vtls_int.h"
58*6236dae4SAndroid Build Coastguard Worker
59*6236dae4SAndroid Build Coastguard Worker #include "openssl.h" /* OpenSSL versions */
60*6236dae4SAndroid Build Coastguard Worker #include "gtls.h" /* GnuTLS versions */
61*6236dae4SAndroid Build Coastguard Worker #include "wolfssl.h" /* wolfSSL versions */
62*6236dae4SAndroid Build Coastguard Worker #include "schannel.h" /* Schannel SSPI version */
63*6236dae4SAndroid Build Coastguard Worker #include "sectransp.h" /* Secure Transport (Darwin) version */
64*6236dae4SAndroid Build Coastguard Worker #include "mbedtls.h" /* mbedTLS versions */
65*6236dae4SAndroid Build Coastguard Worker #include "bearssl.h" /* BearSSL versions */
66*6236dae4SAndroid Build Coastguard Worker #include "rustls.h" /* Rustls versions */
67*6236dae4SAndroid Build Coastguard Worker
68*6236dae4SAndroid Build Coastguard Worker #include "slist.h"
69*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
70*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
71*6236dae4SAndroid Build Coastguard Worker #include "url.h"
72*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
73*6236dae4SAndroid Build Coastguard Worker #include "share.h"
74*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
75*6236dae4SAndroid Build Coastguard Worker #include "timeval.h"
76*6236dae4SAndroid Build Coastguard Worker #include "curl_md5.h"
77*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
78*6236dae4SAndroid Build Coastguard Worker #include "curl_base64.h"
79*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
80*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
81*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
82*6236dae4SAndroid Build Coastguard Worker #include "select.h"
83*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
84*6236dae4SAndroid Build Coastguard Worker #include "rand.h"
85*6236dae4SAndroid Build Coastguard Worker
86*6236dae4SAndroid Build Coastguard Worker /* The last #include files should be: */
87*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
88*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
89*6236dae4SAndroid Build Coastguard Worker
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker /* convenience macro to check if this handle is using a shared SSL session */
92*6236dae4SAndroid Build Coastguard Worker #define SSLSESSION_SHARED(data) (data->share && \
93*6236dae4SAndroid Build Coastguard Worker (data->share->specifier & \
94*6236dae4SAndroid Build Coastguard Worker (1<<CURL_LOCK_DATA_SSL_SESSION)))
95*6236dae4SAndroid Build Coastguard Worker
96*6236dae4SAndroid Build Coastguard Worker #define CLONE_STRING(var) \
97*6236dae4SAndroid Build Coastguard Worker do { \
98*6236dae4SAndroid Build Coastguard Worker if(source->var) { \
99*6236dae4SAndroid Build Coastguard Worker dest->var = strdup(source->var); \
100*6236dae4SAndroid Build Coastguard Worker if(!dest->var) \
101*6236dae4SAndroid Build Coastguard Worker return FALSE; \
102*6236dae4SAndroid Build Coastguard Worker } \
103*6236dae4SAndroid Build Coastguard Worker else \
104*6236dae4SAndroid Build Coastguard Worker dest->var = NULL; \
105*6236dae4SAndroid Build Coastguard Worker } while(0)
106*6236dae4SAndroid Build Coastguard Worker
107*6236dae4SAndroid Build Coastguard Worker #define CLONE_BLOB(var) \
108*6236dae4SAndroid Build Coastguard Worker do { \
109*6236dae4SAndroid Build Coastguard Worker if(blobdup(&dest->var, source->var)) \
110*6236dae4SAndroid Build Coastguard Worker return FALSE; \
111*6236dae4SAndroid Build Coastguard Worker } while(0)
112*6236dae4SAndroid Build Coastguard Worker
blobdup(struct curl_blob ** dest,struct curl_blob * src)113*6236dae4SAndroid Build Coastguard Worker static CURLcode blobdup(struct curl_blob **dest,
114*6236dae4SAndroid Build Coastguard Worker struct curl_blob *src)
115*6236dae4SAndroid Build Coastguard Worker {
116*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(dest);
117*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!*dest);
118*6236dae4SAndroid Build Coastguard Worker if(src) {
119*6236dae4SAndroid Build Coastguard Worker /* only if there is data to dupe! */
120*6236dae4SAndroid Build Coastguard Worker struct curl_blob *d;
121*6236dae4SAndroid Build Coastguard Worker d = malloc(sizeof(struct curl_blob) + src->len);
122*6236dae4SAndroid Build Coastguard Worker if(!d)
123*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
124*6236dae4SAndroid Build Coastguard Worker d->len = src->len;
125*6236dae4SAndroid Build Coastguard Worker /* Always duplicate because the connection may survive longer than the
126*6236dae4SAndroid Build Coastguard Worker handle that passed in the blob. */
127*6236dae4SAndroid Build Coastguard Worker d->flags = CURL_BLOB_COPY;
128*6236dae4SAndroid Build Coastguard Worker d->data = (void *)((char *)d + sizeof(struct curl_blob));
129*6236dae4SAndroid Build Coastguard Worker memcpy(d->data, src->data, src->len);
130*6236dae4SAndroid Build Coastguard Worker *dest = d;
131*6236dae4SAndroid Build Coastguard Worker }
132*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
133*6236dae4SAndroid Build Coastguard Worker }
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker /* returns TRUE if the blobs are identical */
blobcmp(struct curl_blob * first,struct curl_blob * second)136*6236dae4SAndroid Build Coastguard Worker static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
137*6236dae4SAndroid Build Coastguard Worker {
138*6236dae4SAndroid Build Coastguard Worker if(!first && !second) /* both are NULL */
139*6236dae4SAndroid Build Coastguard Worker return TRUE;
140*6236dae4SAndroid Build Coastguard Worker if(!first || !second) /* one is NULL */
141*6236dae4SAndroid Build Coastguard Worker return FALSE;
142*6236dae4SAndroid Build Coastguard Worker if(first->len != second->len) /* different sizes */
143*6236dae4SAndroid Build Coastguard Worker return FALSE;
144*6236dae4SAndroid Build Coastguard Worker return !memcmp(first->data, second->data, first->len); /* same data */
145*6236dae4SAndroid Build Coastguard Worker }
146*6236dae4SAndroid Build Coastguard Worker
147*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
148*6236dae4SAndroid Build Coastguard Worker static const struct alpn_spec ALPN_SPEC_H11 = {
149*6236dae4SAndroid Build Coastguard Worker { ALPN_HTTP_1_1 }, 1
150*6236dae4SAndroid Build Coastguard Worker };
151*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP2
152*6236dae4SAndroid Build Coastguard Worker static const struct alpn_spec ALPN_SPEC_H2 = {
153*6236dae4SAndroid Build Coastguard Worker { ALPN_H2 }, 1
154*6236dae4SAndroid Build Coastguard Worker };
155*6236dae4SAndroid Build Coastguard Worker static const struct alpn_spec ALPN_SPEC_H2_H11 = {
156*6236dae4SAndroid Build Coastguard Worker { ALPN_H2, ALPN_HTTP_1_1 }, 2
157*6236dae4SAndroid Build Coastguard Worker };
158*6236dae4SAndroid Build Coastguard Worker #endif
159*6236dae4SAndroid Build Coastguard Worker
alpn_get_spec(int httpwant,bool use_alpn)160*6236dae4SAndroid Build Coastguard Worker static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
161*6236dae4SAndroid Build Coastguard Worker {
162*6236dae4SAndroid Build Coastguard Worker if(!use_alpn)
163*6236dae4SAndroid Build Coastguard Worker return NULL;
164*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP2
165*6236dae4SAndroid Build Coastguard Worker if(httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
166*6236dae4SAndroid Build Coastguard Worker return &ALPN_SPEC_H2;
167*6236dae4SAndroid Build Coastguard Worker if(httpwant >= CURL_HTTP_VERSION_2)
168*6236dae4SAndroid Build Coastguard Worker return &ALPN_SPEC_H2_H11;
169*6236dae4SAndroid Build Coastguard Worker #else
170*6236dae4SAndroid Build Coastguard Worker (void)httpwant;
171*6236dae4SAndroid Build Coastguard Worker #endif
172*6236dae4SAndroid Build Coastguard Worker /* Use the ALPN protocol "http/1.1" for HTTP/1.x.
173*6236dae4SAndroid Build Coastguard Worker Avoid "http/1.0" because some servers do not support it. */
174*6236dae4SAndroid Build Coastguard Worker return &ALPN_SPEC_H11;
175*6236dae4SAndroid Build Coastguard Worker }
176*6236dae4SAndroid Build Coastguard Worker #endif /* USE_SSL */
177*6236dae4SAndroid Build Coastguard Worker
178*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_easy_config_init(struct Curl_easy * data)179*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_easy_config_init(struct Curl_easy *data)
180*6236dae4SAndroid Build Coastguard Worker {
181*6236dae4SAndroid Build Coastguard Worker /*
182*6236dae4SAndroid Build Coastguard Worker * libcurl 7.10 introduced SSL verification *by default*! This needs to be
183*6236dae4SAndroid Build Coastguard Worker * switched off unless wanted.
184*6236dae4SAndroid Build Coastguard Worker */
185*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.verifypeer = TRUE;
186*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.verifyhost = TRUE;
187*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.cache_session = TRUE; /* caching by default */
188*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
189*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl = data->set.ssl;
190*6236dae4SAndroid Build Coastguard Worker #endif
191*6236dae4SAndroid Build Coastguard Worker }
192*6236dae4SAndroid Build Coastguard Worker
193*6236dae4SAndroid Build Coastguard Worker static bool
match_ssl_primary_config(struct Curl_easy * data,struct ssl_primary_config * c1,struct ssl_primary_config * c2)194*6236dae4SAndroid Build Coastguard Worker match_ssl_primary_config(struct Curl_easy *data,
195*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *c1,
196*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *c2)
197*6236dae4SAndroid Build Coastguard Worker {
198*6236dae4SAndroid Build Coastguard Worker (void)data;
199*6236dae4SAndroid Build Coastguard Worker if((c1->version == c2->version) &&
200*6236dae4SAndroid Build Coastguard Worker (c1->version_max == c2->version_max) &&
201*6236dae4SAndroid Build Coastguard Worker (c1->ssl_options == c2->ssl_options) &&
202*6236dae4SAndroid Build Coastguard Worker (c1->verifypeer == c2->verifypeer) &&
203*6236dae4SAndroid Build Coastguard Worker (c1->verifyhost == c2->verifyhost) &&
204*6236dae4SAndroid Build Coastguard Worker (c1->verifystatus == c2->verifystatus) &&
205*6236dae4SAndroid Build Coastguard Worker blobcmp(c1->cert_blob, c2->cert_blob) &&
206*6236dae4SAndroid Build Coastguard Worker blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
207*6236dae4SAndroid Build Coastguard Worker blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
208*6236dae4SAndroid Build Coastguard Worker Curl_safecmp(c1->CApath, c2->CApath) &&
209*6236dae4SAndroid Build Coastguard Worker Curl_safecmp(c1->CAfile, c2->CAfile) &&
210*6236dae4SAndroid Build Coastguard Worker Curl_safecmp(c1->issuercert, c2->issuercert) &&
211*6236dae4SAndroid Build Coastguard Worker Curl_safecmp(c1->clientcert, c2->clientcert) &&
212*6236dae4SAndroid Build Coastguard Worker #ifdef USE_TLS_SRP
213*6236dae4SAndroid Build Coastguard Worker !Curl_timestrcmp(c1->username, c2->username) &&
214*6236dae4SAndroid Build Coastguard Worker !Curl_timestrcmp(c1->password, c2->password) &&
215*6236dae4SAndroid Build Coastguard Worker #endif
216*6236dae4SAndroid Build Coastguard Worker strcasecompare(c1->cipher_list, c2->cipher_list) &&
217*6236dae4SAndroid Build Coastguard Worker strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
218*6236dae4SAndroid Build Coastguard Worker strcasecompare(c1->curves, c2->curves) &&
219*6236dae4SAndroid Build Coastguard Worker strcasecompare(c1->CRLfile, c2->CRLfile) &&
220*6236dae4SAndroid Build Coastguard Worker strcasecompare(c1->pinned_key, c2->pinned_key))
221*6236dae4SAndroid Build Coastguard Worker return TRUE;
222*6236dae4SAndroid Build Coastguard Worker
223*6236dae4SAndroid Build Coastguard Worker return FALSE;
224*6236dae4SAndroid Build Coastguard Worker }
225*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_conn_config_match(struct Curl_easy * data,struct connectdata * candidate,bool proxy)226*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_conn_config_match(struct Curl_easy *data,
227*6236dae4SAndroid Build Coastguard Worker struct connectdata *candidate,
228*6236dae4SAndroid Build Coastguard Worker bool proxy)
229*6236dae4SAndroid Build Coastguard Worker {
230*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
231*6236dae4SAndroid Build Coastguard Worker if(proxy)
232*6236dae4SAndroid Build Coastguard Worker return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
233*6236dae4SAndroid Build Coastguard Worker &candidate->proxy_ssl_config);
234*6236dae4SAndroid Build Coastguard Worker #else
235*6236dae4SAndroid Build Coastguard Worker (void)proxy;
236*6236dae4SAndroid Build Coastguard Worker #endif
237*6236dae4SAndroid Build Coastguard Worker return match_ssl_primary_config(data, &data->set.ssl.primary,
238*6236dae4SAndroid Build Coastguard Worker &candidate->ssl_config);
239*6236dae4SAndroid Build Coastguard Worker }
240*6236dae4SAndroid Build Coastguard Worker
clone_ssl_primary_config(struct ssl_primary_config * source,struct ssl_primary_config * dest)241*6236dae4SAndroid Build Coastguard Worker static bool clone_ssl_primary_config(struct ssl_primary_config *source,
242*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *dest)
243*6236dae4SAndroid Build Coastguard Worker {
244*6236dae4SAndroid Build Coastguard Worker dest->version = source->version;
245*6236dae4SAndroid Build Coastguard Worker dest->version_max = source->version_max;
246*6236dae4SAndroid Build Coastguard Worker dest->verifypeer = source->verifypeer;
247*6236dae4SAndroid Build Coastguard Worker dest->verifyhost = source->verifyhost;
248*6236dae4SAndroid Build Coastguard Worker dest->verifystatus = source->verifystatus;
249*6236dae4SAndroid Build Coastguard Worker dest->cache_session = source->cache_session;
250*6236dae4SAndroid Build Coastguard Worker dest->ssl_options = source->ssl_options;
251*6236dae4SAndroid Build Coastguard Worker
252*6236dae4SAndroid Build Coastguard Worker CLONE_BLOB(cert_blob);
253*6236dae4SAndroid Build Coastguard Worker CLONE_BLOB(ca_info_blob);
254*6236dae4SAndroid Build Coastguard Worker CLONE_BLOB(issuercert_blob);
255*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(CApath);
256*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(CAfile);
257*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(issuercert);
258*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(clientcert);
259*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(cipher_list);
260*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(cipher_list13);
261*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(pinned_key);
262*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(curves);
263*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(CRLfile);
264*6236dae4SAndroid Build Coastguard Worker #ifdef USE_TLS_SRP
265*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(username);
266*6236dae4SAndroid Build Coastguard Worker CLONE_STRING(password);
267*6236dae4SAndroid Build Coastguard Worker #endif
268*6236dae4SAndroid Build Coastguard Worker
269*6236dae4SAndroid Build Coastguard Worker return TRUE;
270*6236dae4SAndroid Build Coastguard Worker }
271*6236dae4SAndroid Build Coastguard Worker
free_primary_ssl_config(struct ssl_primary_config * sslc)272*6236dae4SAndroid Build Coastguard Worker static void free_primary_ssl_config(struct ssl_primary_config *sslc)
273*6236dae4SAndroid Build Coastguard Worker {
274*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->CApath);
275*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->CAfile);
276*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->issuercert);
277*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->clientcert);
278*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->cipher_list);
279*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->cipher_list13);
280*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->pinned_key);
281*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->cert_blob);
282*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->ca_info_blob);
283*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->issuercert_blob);
284*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->curves);
285*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->CRLfile);
286*6236dae4SAndroid Build Coastguard Worker #ifdef USE_TLS_SRP
287*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->username);
288*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sslc->password);
289*6236dae4SAndroid Build Coastguard Worker #endif
290*6236dae4SAndroid Build Coastguard Worker }
291*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_easy_config_complete(struct Curl_easy * data)292*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
293*6236dae4SAndroid Build Coastguard Worker {
294*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
295*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
296*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
297*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
298*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
299*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.cipher_list =
300*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_CIPHER_LIST];
301*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.cipher_list13 =
302*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_CIPHER13_LIST];
303*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.pinned_key =
304*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_PINNEDPUBLICKEY];
305*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
306*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
307*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
308*6236dae4SAndroid Build Coastguard Worker #ifdef USE_TLS_SRP
309*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
310*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
311*6236dae4SAndroid Build Coastguard Worker #endif
312*6236dae4SAndroid Build Coastguard Worker data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
313*6236dae4SAndroid Build Coastguard Worker data->set.ssl.key = data->set.str[STRING_KEY];
314*6236dae4SAndroid Build Coastguard Worker data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
315*6236dae4SAndroid Build Coastguard Worker data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
316*6236dae4SAndroid Build Coastguard Worker data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
317*6236dae4SAndroid Build Coastguard Worker data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
318*6236dae4SAndroid Build Coastguard Worker
319*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
320*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
321*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
322*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.cipher_list =
323*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
324*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.cipher_list13 =
325*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
326*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.pinned_key =
327*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
328*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
329*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.ca_info_blob =
330*6236dae4SAndroid Build Coastguard Worker data->set.blobs[BLOB_CAINFO_PROXY];
331*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.issuercert =
332*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_ISSUERCERT_PROXY];
333*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.issuercert_blob =
334*6236dae4SAndroid Build Coastguard Worker data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
335*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.CRLfile =
336*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_CRLFILE_PROXY];
337*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
338*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
339*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
340*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
341*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
342*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
343*6236dae4SAndroid Build Coastguard Worker #ifdef USE_TLS_SRP
344*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.username =
345*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
346*6236dae4SAndroid Build Coastguard Worker data->set.proxy_ssl.primary.password =
347*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
348*6236dae4SAndroid Build Coastguard Worker #endif
349*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_PROXY */
350*6236dae4SAndroid Build Coastguard Worker
351*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
352*6236dae4SAndroid Build Coastguard Worker }
353*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_conn_config_init(struct Curl_easy * data,struct connectdata * conn)354*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
355*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn)
356*6236dae4SAndroid Build Coastguard Worker {
357*6236dae4SAndroid Build Coastguard Worker /* Clone "primary" SSL configurations from the esay handle to
358*6236dae4SAndroid Build Coastguard Worker * the connection. They are used for connection cache matching and
359*6236dae4SAndroid Build Coastguard Worker * probably outlive the easy handle */
360*6236dae4SAndroid Build Coastguard Worker if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config))
361*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
362*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
363*6236dae4SAndroid Build Coastguard Worker if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary,
364*6236dae4SAndroid Build Coastguard Worker &conn->proxy_ssl_config))
365*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
366*6236dae4SAndroid Build Coastguard Worker #endif
367*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
368*6236dae4SAndroid Build Coastguard Worker }
369*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_conn_config_cleanup(struct connectdata * conn)370*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_conn_config_cleanup(struct connectdata *conn)
371*6236dae4SAndroid Build Coastguard Worker {
372*6236dae4SAndroid Build Coastguard Worker free_primary_ssl_config(&conn->ssl_config);
373*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
374*6236dae4SAndroid Build Coastguard Worker free_primary_ssl_config(&conn->proxy_ssl_config);
375*6236dae4SAndroid Build Coastguard Worker #endif
376*6236dae4SAndroid Build Coastguard Worker }
377*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_conn_config_update(struct Curl_easy * data,bool for_proxy)378*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy)
379*6236dae4SAndroid Build Coastguard Worker {
380*6236dae4SAndroid Build Coastguard Worker /* May be called on an easy that has no connection yet */
381*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
382*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *src, *dest;
383*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
384*6236dae4SAndroid Build Coastguard Worker src = for_proxy ? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
385*6236dae4SAndroid Build Coastguard Worker dest = for_proxy ? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
386*6236dae4SAndroid Build Coastguard Worker #else
387*6236dae4SAndroid Build Coastguard Worker (void)for_proxy;
388*6236dae4SAndroid Build Coastguard Worker src = &data->set.ssl.primary;
389*6236dae4SAndroid Build Coastguard Worker dest = &data->conn->ssl_config;
390*6236dae4SAndroid Build Coastguard Worker #endif
391*6236dae4SAndroid Build Coastguard Worker dest->verifyhost = src->verifyhost;
392*6236dae4SAndroid Build Coastguard Worker dest->verifypeer = src->verifypeer;
393*6236dae4SAndroid Build Coastguard Worker dest->verifystatus = src->verifystatus;
394*6236dae4SAndroid Build Coastguard Worker }
395*6236dae4SAndroid Build Coastguard Worker }
396*6236dae4SAndroid Build Coastguard Worker
397*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
398*6236dae4SAndroid Build Coastguard Worker static int multissl_setup(const struct Curl_ssl *backend);
399*6236dae4SAndroid Build Coastguard Worker #endif
400*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_backend(void)401*6236dae4SAndroid Build Coastguard Worker curl_sslbackend Curl_ssl_backend(void)
402*6236dae4SAndroid Build Coastguard Worker {
403*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
404*6236dae4SAndroid Build Coastguard Worker multissl_setup(NULL);
405*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->info.id;
406*6236dae4SAndroid Build Coastguard Worker #else
407*6236dae4SAndroid Build Coastguard Worker return CURLSSLBACKEND_NONE;
408*6236dae4SAndroid Build Coastguard Worker #endif
409*6236dae4SAndroid Build Coastguard Worker }
410*6236dae4SAndroid Build Coastguard Worker
411*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker /* "global" init done? */
414*6236dae4SAndroid Build Coastguard Worker static bool init_ssl = FALSE;
415*6236dae4SAndroid Build Coastguard Worker
416*6236dae4SAndroid Build Coastguard Worker /**
417*6236dae4SAndroid Build Coastguard Worker * Global SSL init
418*6236dae4SAndroid Build Coastguard Worker *
419*6236dae4SAndroid Build Coastguard Worker * @retval 0 error initializing SSL
420*6236dae4SAndroid Build Coastguard Worker * @retval 1 SSL initialized successfully
421*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_init(void)422*6236dae4SAndroid Build Coastguard Worker int Curl_ssl_init(void)
423*6236dae4SAndroid Build Coastguard Worker {
424*6236dae4SAndroid Build Coastguard Worker /* make sure this is only done once */
425*6236dae4SAndroid Build Coastguard Worker if(init_ssl)
426*6236dae4SAndroid Build Coastguard Worker return 1;
427*6236dae4SAndroid Build Coastguard Worker init_ssl = TRUE; /* never again */
428*6236dae4SAndroid Build Coastguard Worker
429*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->init();
430*6236dae4SAndroid Build Coastguard Worker }
431*6236dae4SAndroid Build Coastguard Worker
ssl_prefs_check(struct Curl_easy * data)432*6236dae4SAndroid Build Coastguard Worker static bool ssl_prefs_check(struct Curl_easy *data)
433*6236dae4SAndroid Build Coastguard Worker {
434*6236dae4SAndroid Build Coastguard Worker /* check for CURLOPT_SSLVERSION invalid parameter value */
435*6236dae4SAndroid Build Coastguard Worker const unsigned char sslver = data->set.ssl.primary.version;
436*6236dae4SAndroid Build Coastguard Worker if(sslver >= CURL_SSLVERSION_LAST) {
437*6236dae4SAndroid Build Coastguard Worker failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
438*6236dae4SAndroid Build Coastguard Worker return FALSE;
439*6236dae4SAndroid Build Coastguard Worker }
440*6236dae4SAndroid Build Coastguard Worker
441*6236dae4SAndroid Build Coastguard Worker switch(data->set.ssl.primary.version_max) {
442*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_MAX_NONE:
443*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_MAX_DEFAULT:
444*6236dae4SAndroid Build Coastguard Worker break;
445*6236dae4SAndroid Build Coastguard Worker
446*6236dae4SAndroid Build Coastguard Worker default:
447*6236dae4SAndroid Build Coastguard Worker if((data->set.ssl.primary.version_max >> 16) < sslver) {
448*6236dae4SAndroid Build Coastguard Worker failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION");
449*6236dae4SAndroid Build Coastguard Worker return FALSE;
450*6236dae4SAndroid Build Coastguard Worker }
451*6236dae4SAndroid Build Coastguard Worker }
452*6236dae4SAndroid Build Coastguard Worker
453*6236dae4SAndroid Build Coastguard Worker return TRUE;
454*6236dae4SAndroid Build Coastguard Worker }
455*6236dae4SAndroid Build Coastguard Worker
cf_ctx_new(struct Curl_easy * data,const struct alpn_spec * alpn)456*6236dae4SAndroid Build Coastguard Worker static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
457*6236dae4SAndroid Build Coastguard Worker const struct alpn_spec *alpn)
458*6236dae4SAndroid Build Coastguard Worker {
459*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *ctx;
460*6236dae4SAndroid Build Coastguard Worker
461*6236dae4SAndroid Build Coastguard Worker (void)data;
462*6236dae4SAndroid Build Coastguard Worker ctx = calloc(1, sizeof(*ctx));
463*6236dae4SAndroid Build Coastguard Worker if(!ctx)
464*6236dae4SAndroid Build Coastguard Worker return NULL;
465*6236dae4SAndroid Build Coastguard Worker
466*6236dae4SAndroid Build Coastguard Worker ctx->alpn = alpn;
467*6236dae4SAndroid Build Coastguard Worker Curl_bufq_init2(&ctx->earlydata, CURL_SSL_EARLY_MAX, 1, BUFQ_OPT_NO_SPARES);
468*6236dae4SAndroid Build Coastguard Worker ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data);
469*6236dae4SAndroid Build Coastguard Worker if(!ctx->backend) {
470*6236dae4SAndroid Build Coastguard Worker free(ctx);
471*6236dae4SAndroid Build Coastguard Worker return NULL;
472*6236dae4SAndroid Build Coastguard Worker }
473*6236dae4SAndroid Build Coastguard Worker return ctx;
474*6236dae4SAndroid Build Coastguard Worker }
475*6236dae4SAndroid Build Coastguard Worker
cf_ctx_free(struct ssl_connect_data * ctx)476*6236dae4SAndroid Build Coastguard Worker static void cf_ctx_free(struct ssl_connect_data *ctx)
477*6236dae4SAndroid Build Coastguard Worker {
478*6236dae4SAndroid Build Coastguard Worker if(ctx) {
479*6236dae4SAndroid Build Coastguard Worker Curl_safefree(ctx->alpn_negotiated);
480*6236dae4SAndroid Build Coastguard Worker Curl_bufq_free(&ctx->earlydata);
481*6236dae4SAndroid Build Coastguard Worker free(ctx->backend);
482*6236dae4SAndroid Build Coastguard Worker free(ctx);
483*6236dae4SAndroid Build Coastguard Worker }
484*6236dae4SAndroid Build Coastguard Worker }
485*6236dae4SAndroid Build Coastguard Worker
ssl_connect(struct Curl_cfilter * cf,struct Curl_easy * data)486*6236dae4SAndroid Build Coastguard Worker static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
487*6236dae4SAndroid Build Coastguard Worker {
488*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
489*6236dae4SAndroid Build Coastguard Worker CURLcode result;
490*6236dae4SAndroid Build Coastguard Worker
491*6236dae4SAndroid Build Coastguard Worker if(!ssl_prefs_check(data))
492*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
493*6236dae4SAndroid Build Coastguard Worker
494*6236dae4SAndroid Build Coastguard Worker /* mark this is being ssl-enabled from here on. */
495*6236dae4SAndroid Build Coastguard Worker connssl->state = ssl_connection_negotiating;
496*6236dae4SAndroid Build Coastguard Worker
497*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl->connect_blocking(cf, data);
498*6236dae4SAndroid Build Coastguard Worker
499*6236dae4SAndroid Build Coastguard Worker if(!result) {
500*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->state == ssl_connection_complete);
501*6236dae4SAndroid Build Coastguard Worker }
502*6236dae4SAndroid Build Coastguard Worker
503*6236dae4SAndroid Build Coastguard Worker return result;
504*6236dae4SAndroid Build Coastguard Worker }
505*6236dae4SAndroid Build Coastguard Worker
506*6236dae4SAndroid Build Coastguard Worker static CURLcode
ssl_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)507*6236dae4SAndroid Build Coastguard Worker ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
508*6236dae4SAndroid Build Coastguard Worker bool *done)
509*6236dae4SAndroid Build Coastguard Worker {
510*6236dae4SAndroid Build Coastguard Worker if(!ssl_prefs_check(data))
511*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
512*6236dae4SAndroid Build Coastguard Worker
513*6236dae4SAndroid Build Coastguard Worker /* mark this is being ssl requested from here on. */
514*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->connect_nonblocking(cf, data, done);
515*6236dae4SAndroid Build Coastguard Worker }
516*6236dae4SAndroid Build Coastguard Worker
517*6236dae4SAndroid Build Coastguard Worker /*
518*6236dae4SAndroid Build Coastguard Worker * Lock shared SSL session data
519*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_sessionid_lock(struct Curl_easy * data)520*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_sessionid_lock(struct Curl_easy *data)
521*6236dae4SAndroid Build Coastguard Worker {
522*6236dae4SAndroid Build Coastguard Worker if(SSLSESSION_SHARED(data))
523*6236dae4SAndroid Build Coastguard Worker Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
524*6236dae4SAndroid Build Coastguard Worker }
525*6236dae4SAndroid Build Coastguard Worker
526*6236dae4SAndroid Build Coastguard Worker /*
527*6236dae4SAndroid Build Coastguard Worker * Unlock shared SSL session data
528*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_sessionid_unlock(struct Curl_easy * data)529*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
530*6236dae4SAndroid Build Coastguard Worker {
531*6236dae4SAndroid Build Coastguard Worker if(SSLSESSION_SHARED(data))
532*6236dae4SAndroid Build Coastguard Worker Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
533*6236dae4SAndroid Build Coastguard Worker }
534*6236dae4SAndroid Build Coastguard Worker
535*6236dae4SAndroid Build Coastguard Worker /*
536*6236dae4SAndroid Build Coastguard Worker * Check if there is a session ID for the given connection in the cache, and if
537*6236dae4SAndroid Build Coastguard Worker * there is one suitable, it is provided. Returns TRUE when no entry matched.
538*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_getsessionid(struct Curl_cfilter * cf,struct Curl_easy * data,const struct ssl_peer * peer,void ** ssl_sessionid,size_t * idsize,char ** palpn)539*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
540*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
541*6236dae4SAndroid Build Coastguard Worker const struct ssl_peer *peer,
542*6236dae4SAndroid Build Coastguard Worker void **ssl_sessionid,
543*6236dae4SAndroid Build Coastguard Worker size_t *idsize, /* set 0 if unknown */
544*6236dae4SAndroid Build Coastguard Worker char **palpn)
545*6236dae4SAndroid Build Coastguard Worker {
546*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
547*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
548*6236dae4SAndroid Build Coastguard Worker struct Curl_ssl_session *check;
549*6236dae4SAndroid Build Coastguard Worker size_t i;
550*6236dae4SAndroid Build Coastguard Worker long *general_age;
551*6236dae4SAndroid Build Coastguard Worker bool no_match = TRUE;
552*6236dae4SAndroid Build Coastguard Worker
553*6236dae4SAndroid Build Coastguard Worker *ssl_sessionid = NULL;
554*6236dae4SAndroid Build Coastguard Worker if(palpn)
555*6236dae4SAndroid Build Coastguard Worker *palpn = NULL;
556*6236dae4SAndroid Build Coastguard Worker if(!ssl_config)
557*6236dae4SAndroid Build Coastguard Worker return TRUE;
558*6236dae4SAndroid Build Coastguard Worker
559*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ssl_config->primary.cache_session);
560*6236dae4SAndroid Build Coastguard Worker
561*6236dae4SAndroid Build Coastguard Worker if(!ssl_config->primary.cache_session || !data->state.session)
562*6236dae4SAndroid Build Coastguard Worker /* session ID reuse is disabled or the session cache has not been
563*6236dae4SAndroid Build Coastguard Worker setup */
564*6236dae4SAndroid Build Coastguard Worker return TRUE;
565*6236dae4SAndroid Build Coastguard Worker
566*6236dae4SAndroid Build Coastguard Worker /* Lock if shared */
567*6236dae4SAndroid Build Coastguard Worker if(SSLSESSION_SHARED(data))
568*6236dae4SAndroid Build Coastguard Worker general_age = &data->share->sessionage;
569*6236dae4SAndroid Build Coastguard Worker else
570*6236dae4SAndroid Build Coastguard Worker general_age = &data->state.sessionage;
571*6236dae4SAndroid Build Coastguard Worker
572*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
573*6236dae4SAndroid Build Coastguard Worker check = &data->state.session[i];
574*6236dae4SAndroid Build Coastguard Worker if(!check->sessionid)
575*6236dae4SAndroid Build Coastguard Worker /* not session ID means blank entry */
576*6236dae4SAndroid Build Coastguard Worker continue;
577*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(peer->hostname, check->name) &&
578*6236dae4SAndroid Build Coastguard Worker ((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
579*6236dae4SAndroid Build Coastguard Worker (cf->conn->bits.conn_to_host && check->conn_to_host &&
580*6236dae4SAndroid Build Coastguard Worker strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
581*6236dae4SAndroid Build Coastguard Worker ((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
582*6236dae4SAndroid Build Coastguard Worker (cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
583*6236dae4SAndroid Build Coastguard Worker cf->conn->conn_to_port == check->conn_to_port)) &&
584*6236dae4SAndroid Build Coastguard Worker (peer->port == check->remote_port) &&
585*6236dae4SAndroid Build Coastguard Worker (peer->transport == check->transport) &&
586*6236dae4SAndroid Build Coastguard Worker strcasecompare(cf->conn->handler->scheme, check->scheme) &&
587*6236dae4SAndroid Build Coastguard Worker match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
588*6236dae4SAndroid Build Coastguard Worker /* yes, we have a session ID! */
589*6236dae4SAndroid Build Coastguard Worker (*general_age)++; /* increase general age */
590*6236dae4SAndroid Build Coastguard Worker check->age = *general_age; /* set this as used in this age */
591*6236dae4SAndroid Build Coastguard Worker *ssl_sessionid = check->sessionid;
592*6236dae4SAndroid Build Coastguard Worker if(idsize)
593*6236dae4SAndroid Build Coastguard Worker *idsize = check->idsize;
594*6236dae4SAndroid Build Coastguard Worker if(palpn)
595*6236dae4SAndroid Build Coastguard Worker *palpn = check->alpn;
596*6236dae4SAndroid Build Coastguard Worker no_match = FALSE;
597*6236dae4SAndroid Build Coastguard Worker break;
598*6236dae4SAndroid Build Coastguard Worker }
599*6236dae4SAndroid Build Coastguard Worker }
600*6236dae4SAndroid Build Coastguard Worker
601*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "%s cached session ID for %s://%s:%d",
602*6236dae4SAndroid Build Coastguard Worker no_match ? "No" : "Found",
603*6236dae4SAndroid Build Coastguard Worker cf->conn->handler->scheme, peer->hostname, peer->port);
604*6236dae4SAndroid Build Coastguard Worker return no_match;
605*6236dae4SAndroid Build Coastguard Worker }
606*6236dae4SAndroid Build Coastguard Worker
607*6236dae4SAndroid Build Coastguard Worker /*
608*6236dae4SAndroid Build Coastguard Worker * Kill a single session ID entry in the cache.
609*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_kill_session(struct Curl_ssl_session * session)610*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_kill_session(struct Curl_ssl_session *session)
611*6236dae4SAndroid Build Coastguard Worker {
612*6236dae4SAndroid Build Coastguard Worker if(session->sessionid) {
613*6236dae4SAndroid Build Coastguard Worker /* defensive check */
614*6236dae4SAndroid Build Coastguard Worker
615*6236dae4SAndroid Build Coastguard Worker /* free the ID the SSL-layer specific way */
616*6236dae4SAndroid Build Coastguard Worker session->sessionid_free(session->sessionid, session->idsize);
617*6236dae4SAndroid Build Coastguard Worker
618*6236dae4SAndroid Build Coastguard Worker session->sessionid = NULL;
619*6236dae4SAndroid Build Coastguard Worker session->sessionid_free = NULL;
620*6236dae4SAndroid Build Coastguard Worker session->age = 0; /* fresh */
621*6236dae4SAndroid Build Coastguard Worker
622*6236dae4SAndroid Build Coastguard Worker free_primary_ssl_config(&session->ssl_config);
623*6236dae4SAndroid Build Coastguard Worker
624*6236dae4SAndroid Build Coastguard Worker Curl_safefree(session->name);
625*6236dae4SAndroid Build Coastguard Worker Curl_safefree(session->conn_to_host);
626*6236dae4SAndroid Build Coastguard Worker Curl_safefree(session->alpn);
627*6236dae4SAndroid Build Coastguard Worker }
628*6236dae4SAndroid Build Coastguard Worker }
629*6236dae4SAndroid Build Coastguard Worker
630*6236dae4SAndroid Build Coastguard Worker /*
631*6236dae4SAndroid Build Coastguard Worker * Delete the given session ID from the cache.
632*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_delsessionid(struct Curl_easy * data,void * ssl_sessionid)633*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
634*6236dae4SAndroid Build Coastguard Worker {
635*6236dae4SAndroid Build Coastguard Worker size_t i;
636*6236dae4SAndroid Build Coastguard Worker
637*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
638*6236dae4SAndroid Build Coastguard Worker struct Curl_ssl_session *check = &data->state.session[i];
639*6236dae4SAndroid Build Coastguard Worker
640*6236dae4SAndroid Build Coastguard Worker if(check->sessionid == ssl_sessionid) {
641*6236dae4SAndroid Build Coastguard Worker Curl_ssl_kill_session(check);
642*6236dae4SAndroid Build Coastguard Worker break;
643*6236dae4SAndroid Build Coastguard Worker }
644*6236dae4SAndroid Build Coastguard Worker }
645*6236dae4SAndroid Build Coastguard Worker }
646*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_set_sessionid(struct Curl_cfilter * cf,struct Curl_easy * data,const struct ssl_peer * peer,const char * alpn,void * ssl_sessionid,size_t idsize,Curl_ssl_sessionid_dtor * sessionid_free_cb)647*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf,
648*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
649*6236dae4SAndroid Build Coastguard Worker const struct ssl_peer *peer,
650*6236dae4SAndroid Build Coastguard Worker const char *alpn,
651*6236dae4SAndroid Build Coastguard Worker void *ssl_sessionid,
652*6236dae4SAndroid Build Coastguard Worker size_t idsize,
653*6236dae4SAndroid Build Coastguard Worker Curl_ssl_sessionid_dtor *sessionid_free_cb)
654*6236dae4SAndroid Build Coastguard Worker {
655*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
656*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
657*6236dae4SAndroid Build Coastguard Worker size_t i;
658*6236dae4SAndroid Build Coastguard Worker struct Curl_ssl_session *store;
659*6236dae4SAndroid Build Coastguard Worker long oldest_age;
660*6236dae4SAndroid Build Coastguard Worker char *clone_host = NULL;
661*6236dae4SAndroid Build Coastguard Worker char *clone_conn_to_host = NULL;
662*6236dae4SAndroid Build Coastguard Worker char *clone_alpn = NULL;
663*6236dae4SAndroid Build Coastguard Worker int conn_to_port;
664*6236dae4SAndroid Build Coastguard Worker long *general_age;
665*6236dae4SAndroid Build Coastguard Worker void *old_sessionid;
666*6236dae4SAndroid Build Coastguard Worker size_t old_size;
667*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OUT_OF_MEMORY;
668*6236dae4SAndroid Build Coastguard Worker
669*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ssl_sessionid);
670*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(sessionid_free_cb);
671*6236dae4SAndroid Build Coastguard Worker
672*6236dae4SAndroid Build Coastguard Worker if(!data->state.session) {
673*6236dae4SAndroid Build Coastguard Worker sessionid_free_cb(ssl_sessionid, idsize);
674*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
675*6236dae4SAndroid Build Coastguard Worker }
676*6236dae4SAndroid Build Coastguard Worker
677*6236dae4SAndroid Build Coastguard Worker if(!Curl_ssl_getsessionid(cf, data, peer, &old_sessionid, &old_size, NULL)) {
678*6236dae4SAndroid Build Coastguard Worker if((old_size == idsize) &&
679*6236dae4SAndroid Build Coastguard Worker ((old_sessionid == ssl_sessionid) ||
680*6236dae4SAndroid Build Coastguard Worker (idsize && !memcmp(old_sessionid, ssl_sessionid, idsize)))) {
681*6236dae4SAndroid Build Coastguard Worker /* the very same */
682*6236dae4SAndroid Build Coastguard Worker sessionid_free_cb(ssl_sessionid, idsize);
683*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
684*6236dae4SAndroid Build Coastguard Worker }
685*6236dae4SAndroid Build Coastguard Worker Curl_ssl_delsessionid(data, old_sessionid);
686*6236dae4SAndroid Build Coastguard Worker }
687*6236dae4SAndroid Build Coastguard Worker
688*6236dae4SAndroid Build Coastguard Worker store = &data->state.session[0];
689*6236dae4SAndroid Build Coastguard Worker oldest_age = data->state.session[0].age; /* zero if unused */
690*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ssl_config->primary.cache_session);
691*6236dae4SAndroid Build Coastguard Worker (void)ssl_config;
692*6236dae4SAndroid Build Coastguard Worker
693*6236dae4SAndroid Build Coastguard Worker clone_host = strdup(peer->hostname);
694*6236dae4SAndroid Build Coastguard Worker if(!clone_host)
695*6236dae4SAndroid Build Coastguard Worker goto out;
696*6236dae4SAndroid Build Coastguard Worker
697*6236dae4SAndroid Build Coastguard Worker if(cf->conn->bits.conn_to_host) {
698*6236dae4SAndroid Build Coastguard Worker clone_conn_to_host = strdup(cf->conn->conn_to_host.name);
699*6236dae4SAndroid Build Coastguard Worker if(!clone_conn_to_host)
700*6236dae4SAndroid Build Coastguard Worker goto out;
701*6236dae4SAndroid Build Coastguard Worker }
702*6236dae4SAndroid Build Coastguard Worker
703*6236dae4SAndroid Build Coastguard Worker clone_alpn = alpn ? strdup(alpn) : NULL;
704*6236dae4SAndroid Build Coastguard Worker if(alpn && !clone_alpn)
705*6236dae4SAndroid Build Coastguard Worker goto out;
706*6236dae4SAndroid Build Coastguard Worker
707*6236dae4SAndroid Build Coastguard Worker if(cf->conn->bits.conn_to_port)
708*6236dae4SAndroid Build Coastguard Worker conn_to_port = cf->conn->conn_to_port;
709*6236dae4SAndroid Build Coastguard Worker else
710*6236dae4SAndroid Build Coastguard Worker conn_to_port = -1;
711*6236dae4SAndroid Build Coastguard Worker
712*6236dae4SAndroid Build Coastguard Worker /* Now we should add the session ID and the hostname to the cache, (remove
713*6236dae4SAndroid Build Coastguard Worker the oldest if necessary) */
714*6236dae4SAndroid Build Coastguard Worker
715*6236dae4SAndroid Build Coastguard Worker /* If using shared SSL session, lock! */
716*6236dae4SAndroid Build Coastguard Worker if(SSLSESSION_SHARED(data)) {
717*6236dae4SAndroid Build Coastguard Worker general_age = &data->share->sessionage;
718*6236dae4SAndroid Build Coastguard Worker }
719*6236dae4SAndroid Build Coastguard Worker else {
720*6236dae4SAndroid Build Coastguard Worker general_age = &data->state.sessionage;
721*6236dae4SAndroid Build Coastguard Worker }
722*6236dae4SAndroid Build Coastguard Worker
723*6236dae4SAndroid Build Coastguard Worker /* find an empty slot for us, or find the oldest */
724*6236dae4SAndroid Build Coastguard Worker for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
725*6236dae4SAndroid Build Coastguard Worker data->state.session[i].sessionid; i++) {
726*6236dae4SAndroid Build Coastguard Worker if(data->state.session[i].age < oldest_age) {
727*6236dae4SAndroid Build Coastguard Worker oldest_age = data->state.session[i].age;
728*6236dae4SAndroid Build Coastguard Worker store = &data->state.session[i];
729*6236dae4SAndroid Build Coastguard Worker }
730*6236dae4SAndroid Build Coastguard Worker }
731*6236dae4SAndroid Build Coastguard Worker if(i == data->set.general_ssl.max_ssl_sessions)
732*6236dae4SAndroid Build Coastguard Worker /* cache is full, we must "kill" the oldest entry! */
733*6236dae4SAndroid Build Coastguard Worker Curl_ssl_kill_session(store);
734*6236dae4SAndroid Build Coastguard Worker else
735*6236dae4SAndroid Build Coastguard Worker store = &data->state.session[i]; /* use this slot */
736*6236dae4SAndroid Build Coastguard Worker
737*6236dae4SAndroid Build Coastguard Worker /* now init the session struct wisely */
738*6236dae4SAndroid Build Coastguard Worker if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
739*6236dae4SAndroid Build Coastguard Worker free_primary_ssl_config(&store->ssl_config);
740*6236dae4SAndroid Build Coastguard Worker store->sessionid = NULL; /* let caller free sessionid */
741*6236dae4SAndroid Build Coastguard Worker goto out;
742*6236dae4SAndroid Build Coastguard Worker }
743*6236dae4SAndroid Build Coastguard Worker store->sessionid = ssl_sessionid;
744*6236dae4SAndroid Build Coastguard Worker store->idsize = idsize;
745*6236dae4SAndroid Build Coastguard Worker store->sessionid_free = sessionid_free_cb;
746*6236dae4SAndroid Build Coastguard Worker store->age = *general_age; /* set current age */
747*6236dae4SAndroid Build Coastguard Worker /* free it if there is one already present */
748*6236dae4SAndroid Build Coastguard Worker free(store->name);
749*6236dae4SAndroid Build Coastguard Worker free(store->conn_to_host);
750*6236dae4SAndroid Build Coastguard Worker store->name = clone_host; /* clone hostname */
751*6236dae4SAndroid Build Coastguard Worker clone_host = NULL;
752*6236dae4SAndroid Build Coastguard Worker store->conn_to_host = clone_conn_to_host; /* clone connect to hostname */
753*6236dae4SAndroid Build Coastguard Worker clone_conn_to_host = NULL;
754*6236dae4SAndroid Build Coastguard Worker store->conn_to_port = conn_to_port; /* connect to port number */
755*6236dae4SAndroid Build Coastguard Worker store->alpn = clone_alpn;
756*6236dae4SAndroid Build Coastguard Worker clone_alpn = NULL;
757*6236dae4SAndroid Build Coastguard Worker /* port number */
758*6236dae4SAndroid Build Coastguard Worker store->remote_port = peer->port;
759*6236dae4SAndroid Build Coastguard Worker store->scheme = cf->conn->handler->scheme;
760*6236dae4SAndroid Build Coastguard Worker store->transport = peer->transport;
761*6236dae4SAndroid Build Coastguard Worker
762*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
763*6236dae4SAndroid Build Coastguard Worker
764*6236dae4SAndroid Build Coastguard Worker out:
765*6236dae4SAndroid Build Coastguard Worker free(clone_host);
766*6236dae4SAndroid Build Coastguard Worker free(clone_conn_to_host);
767*6236dae4SAndroid Build Coastguard Worker free(clone_alpn);
768*6236dae4SAndroid Build Coastguard Worker if(result) {
769*6236dae4SAndroid Build Coastguard Worker failf(data, "Failed to add Session ID to cache for %s://%s:%d [%s]",
770*6236dae4SAndroid Build Coastguard Worker store->scheme, store->name, store->remote_port,
771*6236dae4SAndroid Build Coastguard Worker Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
772*6236dae4SAndroid Build Coastguard Worker sessionid_free_cb(ssl_sessionid, idsize);
773*6236dae4SAndroid Build Coastguard Worker return result;
774*6236dae4SAndroid Build Coastguard Worker }
775*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "Added Session ID to cache for %s://%s:%d [%s]",
776*6236dae4SAndroid Build Coastguard Worker store->scheme, store->name, store->remote_port,
777*6236dae4SAndroid Build Coastguard Worker Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
778*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
779*6236dae4SAndroid Build Coastguard Worker }
780*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_get_channel_binding(struct Curl_easy * data,int sockindex,struct dynbuf * binding)781*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex,
782*6236dae4SAndroid Build Coastguard Worker struct dynbuf *binding)
783*6236dae4SAndroid Build Coastguard Worker {
784*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl->get_channel_binding)
785*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->get_channel_binding(data, sockindex, binding);
786*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
787*6236dae4SAndroid Build Coastguard Worker }
788*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_close_all(struct Curl_easy * data)789*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_close_all(struct Curl_easy *data)
790*6236dae4SAndroid Build Coastguard Worker {
791*6236dae4SAndroid Build Coastguard Worker /* kill the session ID cache if not shared */
792*6236dae4SAndroid Build Coastguard Worker if(data->state.session && !SSLSESSION_SHARED(data)) {
793*6236dae4SAndroid Build Coastguard Worker size_t i;
794*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
795*6236dae4SAndroid Build Coastguard Worker /* the single-killer function handles empty table slots */
796*6236dae4SAndroid Build Coastguard Worker Curl_ssl_kill_session(&data->state.session[i]);
797*6236dae4SAndroid Build Coastguard Worker
798*6236dae4SAndroid Build Coastguard Worker /* free the cache data */
799*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.session);
800*6236dae4SAndroid Build Coastguard Worker }
801*6236dae4SAndroid Build Coastguard Worker
802*6236dae4SAndroid Build Coastguard Worker Curl_ssl->close_all(data);
803*6236dae4SAndroid Build Coastguard Worker }
804*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_adjust_pollset(struct Curl_cfilter * cf,struct Curl_easy * data,struct easy_pollset * ps)805*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
806*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *ps)
807*6236dae4SAndroid Build Coastguard Worker {
808*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
809*6236dae4SAndroid Build Coastguard Worker
810*6236dae4SAndroid Build Coastguard Worker if(connssl->io_need) {
811*6236dae4SAndroid Build Coastguard Worker curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
812*6236dae4SAndroid Build Coastguard Worker if(sock != CURL_SOCKET_BAD) {
813*6236dae4SAndroid Build Coastguard Worker if(connssl->io_need & CURL_SSL_IO_NEED_SEND) {
814*6236dae4SAndroid Build Coastguard Worker Curl_pollset_set_out_only(data, ps, sock);
815*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "adjust_pollset, POLLOUT fd=%" FMT_SOCKET_T,
816*6236dae4SAndroid Build Coastguard Worker sock);
817*6236dae4SAndroid Build Coastguard Worker }
818*6236dae4SAndroid Build Coastguard Worker else {
819*6236dae4SAndroid Build Coastguard Worker Curl_pollset_set_in_only(data, ps, sock);
820*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "adjust_pollset, POLLIN fd=%" FMT_SOCKET_T,
821*6236dae4SAndroid Build Coastguard Worker sock);
822*6236dae4SAndroid Build Coastguard Worker }
823*6236dae4SAndroid Build Coastguard Worker }
824*6236dae4SAndroid Build Coastguard Worker }
825*6236dae4SAndroid Build Coastguard Worker }
826*6236dae4SAndroid Build Coastguard Worker
827*6236dae4SAndroid Build Coastguard Worker /* Selects an SSL crypto engine
828*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_set_engine(struct Curl_easy * data,const char * engine)829*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
830*6236dae4SAndroid Build Coastguard Worker {
831*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->set_engine(data, engine);
832*6236dae4SAndroid Build Coastguard Worker }
833*6236dae4SAndroid Build Coastguard Worker
834*6236dae4SAndroid Build Coastguard Worker /* Selects the default SSL crypto engine
835*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_set_engine_default(struct Curl_easy * data)836*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
837*6236dae4SAndroid Build Coastguard Worker {
838*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->set_engine_default(data);
839*6236dae4SAndroid Build Coastguard Worker }
840*6236dae4SAndroid Build Coastguard Worker
841*6236dae4SAndroid Build Coastguard Worker /* Return list of OpenSSL crypto engine names. */
Curl_ssl_engines_list(struct Curl_easy * data)842*6236dae4SAndroid Build Coastguard Worker struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
843*6236dae4SAndroid Build Coastguard Worker {
844*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->engines_list(data);
845*6236dae4SAndroid Build Coastguard Worker }
846*6236dae4SAndroid Build Coastguard Worker
847*6236dae4SAndroid Build Coastguard Worker /*
848*6236dae4SAndroid Build Coastguard Worker * This sets up a session ID cache to the specified size. Make sure this code
849*6236dae4SAndroid Build Coastguard Worker * is agnostic to what underlying SSL technology we use.
850*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_initsessions(struct Curl_easy * data,size_t amount)851*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
852*6236dae4SAndroid Build Coastguard Worker {
853*6236dae4SAndroid Build Coastguard Worker struct Curl_ssl_session *session;
854*6236dae4SAndroid Build Coastguard Worker
855*6236dae4SAndroid Build Coastguard Worker if(data->state.session)
856*6236dae4SAndroid Build Coastguard Worker /* this is just a precaution to prevent multiple inits */
857*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
858*6236dae4SAndroid Build Coastguard Worker
859*6236dae4SAndroid Build Coastguard Worker session = calloc(amount, sizeof(struct Curl_ssl_session));
860*6236dae4SAndroid Build Coastguard Worker if(!session)
861*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
862*6236dae4SAndroid Build Coastguard Worker
863*6236dae4SAndroid Build Coastguard Worker /* store the info in the SSL section */
864*6236dae4SAndroid Build Coastguard Worker data->set.general_ssl.max_ssl_sessions = amount;
865*6236dae4SAndroid Build Coastguard Worker data->state.session = session;
866*6236dae4SAndroid Build Coastguard Worker data->state.sessionage = 1; /* this is brand new */
867*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
868*6236dae4SAndroid Build Coastguard Worker }
869*6236dae4SAndroid Build Coastguard Worker
870*6236dae4SAndroid Build Coastguard Worker static size_t multissl_version(char *buffer, size_t size);
871*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_version(char * buffer,size_t size)872*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_version(char *buffer, size_t size)
873*6236dae4SAndroid Build Coastguard Worker {
874*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_WITH_MULTI_SSL
875*6236dae4SAndroid Build Coastguard Worker (void)multissl_version(buffer, size);
876*6236dae4SAndroid Build Coastguard Worker #else
877*6236dae4SAndroid Build Coastguard Worker (void)Curl_ssl->version(buffer, size);
878*6236dae4SAndroid Build Coastguard Worker #endif
879*6236dae4SAndroid Build Coastguard Worker }
880*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_free_certinfo(struct Curl_easy * data)881*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_free_certinfo(struct Curl_easy *data)
882*6236dae4SAndroid Build Coastguard Worker {
883*6236dae4SAndroid Build Coastguard Worker struct curl_certinfo *ci = &data->info.certs;
884*6236dae4SAndroid Build Coastguard Worker
885*6236dae4SAndroid Build Coastguard Worker if(ci->num_of_certs) {
886*6236dae4SAndroid Build Coastguard Worker /* free all individual lists used */
887*6236dae4SAndroid Build Coastguard Worker int i;
888*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < ci->num_of_certs; i++) {
889*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(ci->certinfo[i]);
890*6236dae4SAndroid Build Coastguard Worker ci->certinfo[i] = NULL;
891*6236dae4SAndroid Build Coastguard Worker }
892*6236dae4SAndroid Build Coastguard Worker
893*6236dae4SAndroid Build Coastguard Worker free(ci->certinfo); /* free the actual array too */
894*6236dae4SAndroid Build Coastguard Worker ci->certinfo = NULL;
895*6236dae4SAndroid Build Coastguard Worker ci->num_of_certs = 0;
896*6236dae4SAndroid Build Coastguard Worker }
897*6236dae4SAndroid Build Coastguard Worker }
898*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_init_certinfo(struct Curl_easy * data,int num)899*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
900*6236dae4SAndroid Build Coastguard Worker {
901*6236dae4SAndroid Build Coastguard Worker struct curl_certinfo *ci = &data->info.certs;
902*6236dae4SAndroid Build Coastguard Worker struct curl_slist **table;
903*6236dae4SAndroid Build Coastguard Worker
904*6236dae4SAndroid Build Coastguard Worker /* Free any previous certificate information structures */
905*6236dae4SAndroid Build Coastguard Worker Curl_ssl_free_certinfo(data);
906*6236dae4SAndroid Build Coastguard Worker
907*6236dae4SAndroid Build Coastguard Worker /* Allocate the required certificate information structures */
908*6236dae4SAndroid Build Coastguard Worker table = calloc((size_t) num, sizeof(struct curl_slist *));
909*6236dae4SAndroid Build Coastguard Worker if(!table)
910*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
911*6236dae4SAndroid Build Coastguard Worker
912*6236dae4SAndroid Build Coastguard Worker ci->num_of_certs = num;
913*6236dae4SAndroid Build Coastguard Worker ci->certinfo = table;
914*6236dae4SAndroid Build Coastguard Worker
915*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
916*6236dae4SAndroid Build Coastguard Worker }
917*6236dae4SAndroid Build Coastguard Worker
918*6236dae4SAndroid Build Coastguard Worker /*
919*6236dae4SAndroid Build Coastguard Worker * 'value' is NOT a null-terminated string
920*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_push_certinfo_len(struct Curl_easy * data,int certnum,const char * label,const char * value,size_t valuelen)921*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
922*6236dae4SAndroid Build Coastguard Worker int certnum,
923*6236dae4SAndroid Build Coastguard Worker const char *label,
924*6236dae4SAndroid Build Coastguard Worker const char *value,
925*6236dae4SAndroid Build Coastguard Worker size_t valuelen)
926*6236dae4SAndroid Build Coastguard Worker {
927*6236dae4SAndroid Build Coastguard Worker struct curl_certinfo *ci = &data->info.certs;
928*6236dae4SAndroid Build Coastguard Worker struct curl_slist *nl;
929*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
930*6236dae4SAndroid Build Coastguard Worker struct dynbuf build;
931*6236dae4SAndroid Build Coastguard Worker
932*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(certnum < ci->num_of_certs);
933*6236dae4SAndroid Build Coastguard Worker
934*6236dae4SAndroid Build Coastguard Worker Curl_dyn_init(&build, CURL_X509_STR_MAX);
935*6236dae4SAndroid Build Coastguard Worker
936*6236dae4SAndroid Build Coastguard Worker if(Curl_dyn_add(&build, label) ||
937*6236dae4SAndroid Build Coastguard Worker Curl_dyn_addn(&build, ":", 1) ||
938*6236dae4SAndroid Build Coastguard Worker Curl_dyn_addn(&build, value, valuelen))
939*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
940*6236dae4SAndroid Build Coastguard Worker
941*6236dae4SAndroid Build Coastguard Worker nl = Curl_slist_append_nodup(ci->certinfo[certnum],
942*6236dae4SAndroid Build Coastguard Worker Curl_dyn_ptr(&build));
943*6236dae4SAndroid Build Coastguard Worker if(!nl) {
944*6236dae4SAndroid Build Coastguard Worker Curl_dyn_free(&build);
945*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(ci->certinfo[certnum]);
946*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
947*6236dae4SAndroid Build Coastguard Worker }
948*6236dae4SAndroid Build Coastguard Worker
949*6236dae4SAndroid Build Coastguard Worker ci->certinfo[certnum] = nl;
950*6236dae4SAndroid Build Coastguard Worker return result;
951*6236dae4SAndroid Build Coastguard Worker }
952*6236dae4SAndroid Build Coastguard Worker
953*6236dae4SAndroid Build Coastguard Worker /* get 32 bits of random */
Curl_ssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)954*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_random(struct Curl_easy *data,
955*6236dae4SAndroid Build Coastguard Worker unsigned char *entropy,
956*6236dae4SAndroid Build Coastguard Worker size_t length)
957*6236dae4SAndroid Build Coastguard Worker {
958*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(length == sizeof(int));
959*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl->random)
960*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->random(data, entropy, length);
961*6236dae4SAndroid Build Coastguard Worker else
962*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
963*6236dae4SAndroid Build Coastguard Worker }
964*6236dae4SAndroid Build Coastguard Worker
965*6236dae4SAndroid Build Coastguard Worker /*
966*6236dae4SAndroid Build Coastguard Worker * Public key pem to der conversion
967*6236dae4SAndroid Build Coastguard Worker */
968*6236dae4SAndroid Build Coastguard Worker
pubkey_pem_to_der(const char * pem,unsigned char ** der,size_t * der_len)969*6236dae4SAndroid Build Coastguard Worker static CURLcode pubkey_pem_to_der(const char *pem,
970*6236dae4SAndroid Build Coastguard Worker unsigned char **der, size_t *der_len)
971*6236dae4SAndroid Build Coastguard Worker {
972*6236dae4SAndroid Build Coastguard Worker char *begin_pos, *end_pos;
973*6236dae4SAndroid Build Coastguard Worker size_t pem_count, pem_len;
974*6236dae4SAndroid Build Coastguard Worker CURLcode result;
975*6236dae4SAndroid Build Coastguard Worker struct dynbuf pbuf;
976*6236dae4SAndroid Build Coastguard Worker
977*6236dae4SAndroid Build Coastguard Worker /* if no pem, exit. */
978*6236dae4SAndroid Build Coastguard Worker if(!pem)
979*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
980*6236dae4SAndroid Build Coastguard Worker
981*6236dae4SAndroid Build Coastguard Worker Curl_dyn_init(&pbuf, MAX_PINNED_PUBKEY_SIZE);
982*6236dae4SAndroid Build Coastguard Worker
983*6236dae4SAndroid Build Coastguard Worker begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----");
984*6236dae4SAndroid Build Coastguard Worker if(!begin_pos)
985*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
986*6236dae4SAndroid Build Coastguard Worker
987*6236dae4SAndroid Build Coastguard Worker pem_count = begin_pos - pem;
988*6236dae4SAndroid Build Coastguard Worker /* Invalid if not at beginning AND not directly following \n */
989*6236dae4SAndroid Build Coastguard Worker if(0 != pem_count && '\n' != pem[pem_count - 1])
990*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
991*6236dae4SAndroid Build Coastguard Worker
992*6236dae4SAndroid Build Coastguard Worker /* 26 is length of "-----BEGIN PUBLIC KEY-----" */
993*6236dae4SAndroid Build Coastguard Worker pem_count += 26;
994*6236dae4SAndroid Build Coastguard Worker
995*6236dae4SAndroid Build Coastguard Worker /* Invalid if not directly following \n */
996*6236dae4SAndroid Build Coastguard Worker end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----");
997*6236dae4SAndroid Build Coastguard Worker if(!end_pos)
998*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
999*6236dae4SAndroid Build Coastguard Worker
1000*6236dae4SAndroid Build Coastguard Worker pem_len = end_pos - pem;
1001*6236dae4SAndroid Build Coastguard Worker
1002*6236dae4SAndroid Build Coastguard Worker /*
1003*6236dae4SAndroid Build Coastguard Worker * Here we loop through the pem array one character at a time between the
1004*6236dae4SAndroid Build Coastguard Worker * correct indices, and place each character that is not '\n' or '\r'
1005*6236dae4SAndroid Build Coastguard Worker * into the stripped_pem array, which should represent the raw base64 string
1006*6236dae4SAndroid Build Coastguard Worker */
1007*6236dae4SAndroid Build Coastguard Worker while(pem_count < pem_len) {
1008*6236dae4SAndroid Build Coastguard Worker if('\n' != pem[pem_count] && '\r' != pem[pem_count]) {
1009*6236dae4SAndroid Build Coastguard Worker result = Curl_dyn_addn(&pbuf, &pem[pem_count], 1);
1010*6236dae4SAndroid Build Coastguard Worker if(result)
1011*6236dae4SAndroid Build Coastguard Worker return result;
1012*6236dae4SAndroid Build Coastguard Worker }
1013*6236dae4SAndroid Build Coastguard Worker ++pem_count;
1014*6236dae4SAndroid Build Coastguard Worker }
1015*6236dae4SAndroid Build Coastguard Worker
1016*6236dae4SAndroid Build Coastguard Worker result = Curl_base64_decode(Curl_dyn_ptr(&pbuf), der, der_len);
1017*6236dae4SAndroid Build Coastguard Worker
1018*6236dae4SAndroid Build Coastguard Worker Curl_dyn_free(&pbuf);
1019*6236dae4SAndroid Build Coastguard Worker
1020*6236dae4SAndroid Build Coastguard Worker return result;
1021*6236dae4SAndroid Build Coastguard Worker }
1022*6236dae4SAndroid Build Coastguard Worker
1023*6236dae4SAndroid Build Coastguard Worker /*
1024*6236dae4SAndroid Build Coastguard Worker * Generic pinned public key check.
1025*6236dae4SAndroid Build Coastguard Worker */
1026*6236dae4SAndroid Build Coastguard Worker
Curl_pin_peer_pubkey(struct Curl_easy * data,const char * pinnedpubkey,const unsigned char * pubkey,size_t pubkeylen)1027*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
1028*6236dae4SAndroid Build Coastguard Worker const char *pinnedpubkey,
1029*6236dae4SAndroid Build Coastguard Worker const unsigned char *pubkey, size_t pubkeylen)
1030*6236dae4SAndroid Build Coastguard Worker {
1031*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1032*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_VERBOSE_STRINGS
1033*6236dae4SAndroid Build Coastguard Worker (void)data;
1034*6236dae4SAndroid Build Coastguard Worker #endif
1035*6236dae4SAndroid Build Coastguard Worker
1036*6236dae4SAndroid Build Coastguard Worker /* if a path was not specified, do not pin */
1037*6236dae4SAndroid Build Coastguard Worker if(!pinnedpubkey)
1038*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1039*6236dae4SAndroid Build Coastguard Worker if(!pubkey || !pubkeylen)
1040*6236dae4SAndroid Build Coastguard Worker return result;
1041*6236dae4SAndroid Build Coastguard Worker
1042*6236dae4SAndroid Build Coastguard Worker /* only do this if pinnedpubkey starts with "sha256//", length 8 */
1043*6236dae4SAndroid Build Coastguard Worker if(!strncmp(pinnedpubkey, "sha256//", 8)) {
1044*6236dae4SAndroid Build Coastguard Worker CURLcode encode;
1045*6236dae4SAndroid Build Coastguard Worker size_t encodedlen = 0;
1046*6236dae4SAndroid Build Coastguard Worker char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos;
1047*6236dae4SAndroid Build Coastguard Worker unsigned char *sha256sumdigest;
1048*6236dae4SAndroid Build Coastguard Worker
1049*6236dae4SAndroid Build Coastguard Worker if(!Curl_ssl->sha256sum) {
1050*6236dae4SAndroid Build Coastguard Worker /* without sha256 support, this cannot match */
1051*6236dae4SAndroid Build Coastguard Worker return result;
1052*6236dae4SAndroid Build Coastguard Worker }
1053*6236dae4SAndroid Build Coastguard Worker
1054*6236dae4SAndroid Build Coastguard Worker /* compute sha256sum of public key */
1055*6236dae4SAndroid Build Coastguard Worker sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
1056*6236dae4SAndroid Build Coastguard Worker if(!sha256sumdigest)
1057*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1058*6236dae4SAndroid Build Coastguard Worker encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
1059*6236dae4SAndroid Build Coastguard Worker sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
1060*6236dae4SAndroid Build Coastguard Worker
1061*6236dae4SAndroid Build Coastguard Worker if(!encode)
1062*6236dae4SAndroid Build Coastguard Worker encode = Curl_base64_encode((char *)sha256sumdigest,
1063*6236dae4SAndroid Build Coastguard Worker CURL_SHA256_DIGEST_LENGTH, &encoded,
1064*6236dae4SAndroid Build Coastguard Worker &encodedlen);
1065*6236dae4SAndroid Build Coastguard Worker Curl_safefree(sha256sumdigest);
1066*6236dae4SAndroid Build Coastguard Worker
1067*6236dae4SAndroid Build Coastguard Worker if(encode)
1068*6236dae4SAndroid Build Coastguard Worker return encode;
1069*6236dae4SAndroid Build Coastguard Worker
1070*6236dae4SAndroid Build Coastguard Worker infof(data, " public key hash: sha256//%s", encoded);
1071*6236dae4SAndroid Build Coastguard Worker
1072*6236dae4SAndroid Build Coastguard Worker /* it starts with sha256//, copy so we can modify it */
1073*6236dae4SAndroid Build Coastguard Worker pinkeycopy = strdup(pinnedpubkey);
1074*6236dae4SAndroid Build Coastguard Worker if(!pinkeycopy) {
1075*6236dae4SAndroid Build Coastguard Worker Curl_safefree(encoded);
1076*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1077*6236dae4SAndroid Build Coastguard Worker }
1078*6236dae4SAndroid Build Coastguard Worker /* point begin_pos to the copy, and start extracting keys */
1079*6236dae4SAndroid Build Coastguard Worker begin_pos = pinkeycopy;
1080*6236dae4SAndroid Build Coastguard Worker do {
1081*6236dae4SAndroid Build Coastguard Worker end_pos = strstr(begin_pos, ";sha256//");
1082*6236dae4SAndroid Build Coastguard Worker /*
1083*6236dae4SAndroid Build Coastguard Worker * if there is an end_pos, null terminate,
1084*6236dae4SAndroid Build Coastguard Worker * otherwise it will go to the end of the original string
1085*6236dae4SAndroid Build Coastguard Worker */
1086*6236dae4SAndroid Build Coastguard Worker if(end_pos)
1087*6236dae4SAndroid Build Coastguard Worker end_pos[0] = '\0';
1088*6236dae4SAndroid Build Coastguard Worker
1089*6236dae4SAndroid Build Coastguard Worker /* compare base64 sha256 digests, 8 is the length of "sha256//" */
1090*6236dae4SAndroid Build Coastguard Worker if(encodedlen == strlen(begin_pos + 8) &&
1091*6236dae4SAndroid Build Coastguard Worker !memcmp(encoded, begin_pos + 8, encodedlen)) {
1092*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
1093*6236dae4SAndroid Build Coastguard Worker break;
1094*6236dae4SAndroid Build Coastguard Worker }
1095*6236dae4SAndroid Build Coastguard Worker
1096*6236dae4SAndroid Build Coastguard Worker /*
1097*6236dae4SAndroid Build Coastguard Worker * change back the null-terminator we changed earlier,
1098*6236dae4SAndroid Build Coastguard Worker * and look for next begin
1099*6236dae4SAndroid Build Coastguard Worker */
1100*6236dae4SAndroid Build Coastguard Worker if(end_pos) {
1101*6236dae4SAndroid Build Coastguard Worker end_pos[0] = ';';
1102*6236dae4SAndroid Build Coastguard Worker begin_pos = strstr(end_pos, "sha256//");
1103*6236dae4SAndroid Build Coastguard Worker }
1104*6236dae4SAndroid Build Coastguard Worker } while(end_pos && begin_pos);
1105*6236dae4SAndroid Build Coastguard Worker Curl_safefree(encoded);
1106*6236dae4SAndroid Build Coastguard Worker Curl_safefree(pinkeycopy);
1107*6236dae4SAndroid Build Coastguard Worker }
1108*6236dae4SAndroid Build Coastguard Worker else {
1109*6236dae4SAndroid Build Coastguard Worker long filesize;
1110*6236dae4SAndroid Build Coastguard Worker size_t size, pem_len;
1111*6236dae4SAndroid Build Coastguard Worker CURLcode pem_read;
1112*6236dae4SAndroid Build Coastguard Worker struct dynbuf buf;
1113*6236dae4SAndroid Build Coastguard Worker char unsigned *pem_ptr = NULL;
1114*6236dae4SAndroid Build Coastguard Worker size_t left;
1115*6236dae4SAndroid Build Coastguard Worker FILE *fp = fopen(pinnedpubkey, "rb");
1116*6236dae4SAndroid Build Coastguard Worker if(!fp)
1117*6236dae4SAndroid Build Coastguard Worker return result;
1118*6236dae4SAndroid Build Coastguard Worker
1119*6236dae4SAndroid Build Coastguard Worker Curl_dyn_init(&buf, MAX_PINNED_PUBKEY_SIZE);
1120*6236dae4SAndroid Build Coastguard Worker
1121*6236dae4SAndroid Build Coastguard Worker /* Determine the file's size */
1122*6236dae4SAndroid Build Coastguard Worker if(fseek(fp, 0, SEEK_END))
1123*6236dae4SAndroid Build Coastguard Worker goto end;
1124*6236dae4SAndroid Build Coastguard Worker filesize = ftell(fp);
1125*6236dae4SAndroid Build Coastguard Worker if(fseek(fp, 0, SEEK_SET))
1126*6236dae4SAndroid Build Coastguard Worker goto end;
1127*6236dae4SAndroid Build Coastguard Worker if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE)
1128*6236dae4SAndroid Build Coastguard Worker goto end;
1129*6236dae4SAndroid Build Coastguard Worker
1130*6236dae4SAndroid Build Coastguard Worker /*
1131*6236dae4SAndroid Build Coastguard Worker * if the size of our certificate is bigger than the file
1132*6236dae4SAndroid Build Coastguard Worker * size then it cannot match
1133*6236dae4SAndroid Build Coastguard Worker */
1134*6236dae4SAndroid Build Coastguard Worker size = curlx_sotouz((curl_off_t) filesize);
1135*6236dae4SAndroid Build Coastguard Worker if(pubkeylen > size)
1136*6236dae4SAndroid Build Coastguard Worker goto end;
1137*6236dae4SAndroid Build Coastguard Worker
1138*6236dae4SAndroid Build Coastguard Worker /*
1139*6236dae4SAndroid Build Coastguard Worker * Read the file into the dynbuf
1140*6236dae4SAndroid Build Coastguard Worker */
1141*6236dae4SAndroid Build Coastguard Worker left = size;
1142*6236dae4SAndroid Build Coastguard Worker do {
1143*6236dae4SAndroid Build Coastguard Worker char buffer[1024];
1144*6236dae4SAndroid Build Coastguard Worker size_t want = left > sizeof(buffer) ? sizeof(buffer) : left;
1145*6236dae4SAndroid Build Coastguard Worker if(want != fread(buffer, 1, want, fp))
1146*6236dae4SAndroid Build Coastguard Worker goto end;
1147*6236dae4SAndroid Build Coastguard Worker if(Curl_dyn_addn(&buf, buffer, want))
1148*6236dae4SAndroid Build Coastguard Worker goto end;
1149*6236dae4SAndroid Build Coastguard Worker left -= want;
1150*6236dae4SAndroid Build Coastguard Worker } while(left);
1151*6236dae4SAndroid Build Coastguard Worker
1152*6236dae4SAndroid Build Coastguard Worker /* If the sizes are the same, it cannot be base64 encoded, must be der */
1153*6236dae4SAndroid Build Coastguard Worker if(pubkeylen == size) {
1154*6236dae4SAndroid Build Coastguard Worker if(!memcmp(pubkey, Curl_dyn_ptr(&buf), pubkeylen))
1155*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
1156*6236dae4SAndroid Build Coastguard Worker goto end;
1157*6236dae4SAndroid Build Coastguard Worker }
1158*6236dae4SAndroid Build Coastguard Worker
1159*6236dae4SAndroid Build Coastguard Worker /*
1160*6236dae4SAndroid Build Coastguard Worker * Otherwise we will assume it is PEM and try to decode it
1161*6236dae4SAndroid Build Coastguard Worker * after placing null terminator
1162*6236dae4SAndroid Build Coastguard Worker */
1163*6236dae4SAndroid Build Coastguard Worker pem_read = pubkey_pem_to_der(Curl_dyn_ptr(&buf), &pem_ptr, &pem_len);
1164*6236dae4SAndroid Build Coastguard Worker /* if it was not read successfully, exit */
1165*6236dae4SAndroid Build Coastguard Worker if(pem_read)
1166*6236dae4SAndroid Build Coastguard Worker goto end;
1167*6236dae4SAndroid Build Coastguard Worker
1168*6236dae4SAndroid Build Coastguard Worker /*
1169*6236dae4SAndroid Build Coastguard Worker * if the size of our certificate does not match the size of
1170*6236dae4SAndroid Build Coastguard Worker * the decoded file, they cannot be the same, otherwise compare
1171*6236dae4SAndroid Build Coastguard Worker */
1172*6236dae4SAndroid Build Coastguard Worker if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen))
1173*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
1174*6236dae4SAndroid Build Coastguard Worker end:
1175*6236dae4SAndroid Build Coastguard Worker Curl_dyn_free(&buf);
1176*6236dae4SAndroid Build Coastguard Worker Curl_safefree(pem_ptr);
1177*6236dae4SAndroid Build Coastguard Worker fclose(fp);
1178*6236dae4SAndroid Build Coastguard Worker }
1179*6236dae4SAndroid Build Coastguard Worker
1180*6236dae4SAndroid Build Coastguard Worker return result;
1181*6236dae4SAndroid Build Coastguard Worker }
1182*6236dae4SAndroid Build Coastguard Worker
1183*6236dae4SAndroid Build Coastguard Worker /*
1184*6236dae4SAndroid Build Coastguard Worker * Check whether the SSL backend supports the status_request extension.
1185*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_cert_status_request(void)1186*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_cert_status_request(void)
1187*6236dae4SAndroid Build Coastguard Worker {
1188*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->cert_status_request();
1189*6236dae4SAndroid Build Coastguard Worker }
1190*6236dae4SAndroid Build Coastguard Worker
1191*6236dae4SAndroid Build Coastguard Worker /*
1192*6236dae4SAndroid Build Coastguard Worker * Check whether the SSL backend supports false start.
1193*6236dae4SAndroid Build Coastguard Worker */
Curl_ssl_false_start(struct Curl_easy * data)1194*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_false_start(struct Curl_easy *data)
1195*6236dae4SAndroid Build Coastguard Worker {
1196*6236dae4SAndroid Build Coastguard Worker (void)data;
1197*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->false_start();
1198*6236dae4SAndroid Build Coastguard Worker }
1199*6236dae4SAndroid Build Coastguard Worker
1200*6236dae4SAndroid Build Coastguard Worker /*
1201*6236dae4SAndroid Build Coastguard Worker * Default implementations for unsupported functions.
1202*6236dae4SAndroid Build Coastguard Worker */
1203*6236dae4SAndroid Build Coastguard Worker
Curl_none_init(void)1204*6236dae4SAndroid Build Coastguard Worker int Curl_none_init(void)
1205*6236dae4SAndroid Build Coastguard Worker {
1206*6236dae4SAndroid Build Coastguard Worker return 1;
1207*6236dae4SAndroid Build Coastguard Worker }
1208*6236dae4SAndroid Build Coastguard Worker
Curl_none_cleanup(void)1209*6236dae4SAndroid Build Coastguard Worker void Curl_none_cleanup(void)
1210*6236dae4SAndroid Build Coastguard Worker { }
1211*6236dae4SAndroid Build Coastguard Worker
Curl_none_shutdown(struct Curl_cfilter * cf UNUSED_PARAM,struct Curl_easy * data UNUSED_PARAM,bool send_shutdown UNUSED_PARAM,bool * done)1212*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_none_shutdown(struct Curl_cfilter *cf UNUSED_PARAM,
1213*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data UNUSED_PARAM,
1214*6236dae4SAndroid Build Coastguard Worker bool send_shutdown UNUSED_PARAM,
1215*6236dae4SAndroid Build Coastguard Worker bool *done)
1216*6236dae4SAndroid Build Coastguard Worker {
1217*6236dae4SAndroid Build Coastguard Worker (void)data;
1218*6236dae4SAndroid Build Coastguard Worker (void)cf;
1219*6236dae4SAndroid Build Coastguard Worker (void)send_shutdown;
1220*6236dae4SAndroid Build Coastguard Worker /* Every SSL backend should have a shutdown implementation. Until we
1221*6236dae4SAndroid Build Coastguard Worker * have implemented that, we put this fake in place. */
1222*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1223*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1224*6236dae4SAndroid Build Coastguard Worker }
1225*6236dae4SAndroid Build Coastguard Worker
Curl_none_check_cxn(struct Curl_cfilter * cf,struct Curl_easy * data)1226*6236dae4SAndroid Build Coastguard Worker int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data)
1227*6236dae4SAndroid Build Coastguard Worker {
1228*6236dae4SAndroid Build Coastguard Worker (void)cf;
1229*6236dae4SAndroid Build Coastguard Worker (void)data;
1230*6236dae4SAndroid Build Coastguard Worker return -1;
1231*6236dae4SAndroid Build Coastguard Worker }
1232*6236dae4SAndroid Build Coastguard Worker
Curl_none_close_all(struct Curl_easy * data UNUSED_PARAM)1233*6236dae4SAndroid Build Coastguard Worker void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
1234*6236dae4SAndroid Build Coastguard Worker {
1235*6236dae4SAndroid Build Coastguard Worker (void)data;
1236*6236dae4SAndroid Build Coastguard Worker }
1237*6236dae4SAndroid Build Coastguard Worker
Curl_none_session_free(void * ptr UNUSED_PARAM)1238*6236dae4SAndroid Build Coastguard Worker void Curl_none_session_free(void *ptr UNUSED_PARAM)
1239*6236dae4SAndroid Build Coastguard Worker {
1240*6236dae4SAndroid Build Coastguard Worker (void)ptr;
1241*6236dae4SAndroid Build Coastguard Worker }
1242*6236dae4SAndroid Build Coastguard Worker
Curl_none_data_pending(struct Curl_cfilter * cf UNUSED_PARAM,const struct Curl_easy * data UNUSED_PARAM)1243*6236dae4SAndroid Build Coastguard Worker bool Curl_none_data_pending(struct Curl_cfilter *cf UNUSED_PARAM,
1244*6236dae4SAndroid Build Coastguard Worker const struct Curl_easy *data UNUSED_PARAM)
1245*6236dae4SAndroid Build Coastguard Worker {
1246*6236dae4SAndroid Build Coastguard Worker (void)cf;
1247*6236dae4SAndroid Build Coastguard Worker (void)data;
1248*6236dae4SAndroid Build Coastguard Worker return 0;
1249*6236dae4SAndroid Build Coastguard Worker }
1250*6236dae4SAndroid Build Coastguard Worker
Curl_none_cert_status_request(void)1251*6236dae4SAndroid Build Coastguard Worker bool Curl_none_cert_status_request(void)
1252*6236dae4SAndroid Build Coastguard Worker {
1253*6236dae4SAndroid Build Coastguard Worker return FALSE;
1254*6236dae4SAndroid Build Coastguard Worker }
1255*6236dae4SAndroid Build Coastguard Worker
Curl_none_set_engine(struct Curl_easy * data UNUSED_PARAM,const char * engine UNUSED_PARAM)1256*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
1257*6236dae4SAndroid Build Coastguard Worker const char *engine UNUSED_PARAM)
1258*6236dae4SAndroid Build Coastguard Worker {
1259*6236dae4SAndroid Build Coastguard Worker (void)data;
1260*6236dae4SAndroid Build Coastguard Worker (void)engine;
1261*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
1262*6236dae4SAndroid Build Coastguard Worker }
1263*6236dae4SAndroid Build Coastguard Worker
Curl_none_set_engine_default(struct Curl_easy * data UNUSED_PARAM)1264*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
1265*6236dae4SAndroid Build Coastguard Worker {
1266*6236dae4SAndroid Build Coastguard Worker (void)data;
1267*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
1268*6236dae4SAndroid Build Coastguard Worker }
1269*6236dae4SAndroid Build Coastguard Worker
Curl_none_engines_list(struct Curl_easy * data UNUSED_PARAM)1270*6236dae4SAndroid Build Coastguard Worker struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
1271*6236dae4SAndroid Build Coastguard Worker {
1272*6236dae4SAndroid Build Coastguard Worker (void)data;
1273*6236dae4SAndroid Build Coastguard Worker return (struct curl_slist *)NULL;
1274*6236dae4SAndroid Build Coastguard Worker }
1275*6236dae4SAndroid Build Coastguard Worker
Curl_none_false_start(void)1276*6236dae4SAndroid Build Coastguard Worker bool Curl_none_false_start(void)
1277*6236dae4SAndroid Build Coastguard Worker {
1278*6236dae4SAndroid Build Coastguard Worker return FALSE;
1279*6236dae4SAndroid Build Coastguard Worker }
1280*6236dae4SAndroid Build Coastguard Worker
multissl_init(void)1281*6236dae4SAndroid Build Coastguard Worker static int multissl_init(void)
1282*6236dae4SAndroid Build Coastguard Worker {
1283*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1284*6236dae4SAndroid Build Coastguard Worker return 1;
1285*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->init();
1286*6236dae4SAndroid Build Coastguard Worker }
1287*6236dae4SAndroid Build Coastguard Worker
multissl_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1288*6236dae4SAndroid Build Coastguard Worker static CURLcode multissl_connect(struct Curl_cfilter *cf,
1289*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
1290*6236dae4SAndroid Build Coastguard Worker {
1291*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1292*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1293*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->connect_blocking(cf, data);
1294*6236dae4SAndroid Build Coastguard Worker }
1295*6236dae4SAndroid Build Coastguard Worker
multissl_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1296*6236dae4SAndroid Build Coastguard Worker static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
1297*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1298*6236dae4SAndroid Build Coastguard Worker bool *done)
1299*6236dae4SAndroid Build Coastguard Worker {
1300*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1301*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1302*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->connect_nonblocking(cf, data, done);
1303*6236dae4SAndroid Build Coastguard Worker }
1304*6236dae4SAndroid Build Coastguard Worker
multissl_adjust_pollset(struct Curl_cfilter * cf,struct Curl_easy * data,struct easy_pollset * ps)1305*6236dae4SAndroid Build Coastguard Worker static void multissl_adjust_pollset(struct Curl_cfilter *cf,
1306*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1307*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *ps)
1308*6236dae4SAndroid Build Coastguard Worker {
1309*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1310*6236dae4SAndroid Build Coastguard Worker return;
1311*6236dae4SAndroid Build Coastguard Worker Curl_ssl->adjust_pollset(cf, data, ps);
1312*6236dae4SAndroid Build Coastguard Worker }
1313*6236dae4SAndroid Build Coastguard Worker
multissl_get_internals(struct ssl_connect_data * connssl,CURLINFO info)1314*6236dae4SAndroid Build Coastguard Worker static void *multissl_get_internals(struct ssl_connect_data *connssl,
1315*6236dae4SAndroid Build Coastguard Worker CURLINFO info)
1316*6236dae4SAndroid Build Coastguard Worker {
1317*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1318*6236dae4SAndroid Build Coastguard Worker return NULL;
1319*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->get_internals(connssl, info);
1320*6236dae4SAndroid Build Coastguard Worker }
1321*6236dae4SAndroid Build Coastguard Worker
multissl_close(struct Curl_cfilter * cf,struct Curl_easy * data)1322*6236dae4SAndroid Build Coastguard Worker static void multissl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1323*6236dae4SAndroid Build Coastguard Worker {
1324*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1325*6236dae4SAndroid Build Coastguard Worker return;
1326*6236dae4SAndroid Build Coastguard Worker Curl_ssl->close(cf, data);
1327*6236dae4SAndroid Build Coastguard Worker }
1328*6236dae4SAndroid Build Coastguard Worker
multissl_recv_plain(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t len,CURLcode * code)1329*6236dae4SAndroid Build Coastguard Worker static ssize_t multissl_recv_plain(struct Curl_cfilter *cf,
1330*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1331*6236dae4SAndroid Build Coastguard Worker char *buf, size_t len, CURLcode *code)
1332*6236dae4SAndroid Build Coastguard Worker {
1333*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1334*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1335*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->recv_plain(cf, data, buf, len, code);
1336*6236dae4SAndroid Build Coastguard Worker }
1337*6236dae4SAndroid Build Coastguard Worker
multissl_send_plain(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * code)1338*6236dae4SAndroid Build Coastguard Worker static ssize_t multissl_send_plain(struct Curl_cfilter *cf,
1339*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1340*6236dae4SAndroid Build Coastguard Worker const void *mem, size_t len,
1341*6236dae4SAndroid Build Coastguard Worker CURLcode *code)
1342*6236dae4SAndroid Build Coastguard Worker {
1343*6236dae4SAndroid Build Coastguard Worker if(multissl_setup(NULL))
1344*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1345*6236dae4SAndroid Build Coastguard Worker return Curl_ssl->send_plain(cf, data, mem, len, code);
1346*6236dae4SAndroid Build Coastguard Worker }
1347*6236dae4SAndroid Build Coastguard Worker
1348*6236dae4SAndroid Build Coastguard Worker static const struct Curl_ssl Curl_ssl_multi = {
1349*6236dae4SAndroid Build Coastguard Worker { CURLSSLBACKEND_NONE, "multi" }, /* info */
1350*6236dae4SAndroid Build Coastguard Worker 0, /* supports nothing */
1351*6236dae4SAndroid Build Coastguard Worker (size_t)-1, /* something insanely large to be on the safe side */
1352*6236dae4SAndroid Build Coastguard Worker
1353*6236dae4SAndroid Build Coastguard Worker multissl_init, /* init */
1354*6236dae4SAndroid Build Coastguard Worker Curl_none_cleanup, /* cleanup */
1355*6236dae4SAndroid Build Coastguard Worker multissl_version, /* version */
1356*6236dae4SAndroid Build Coastguard Worker Curl_none_check_cxn, /* check_cxn */
1357*6236dae4SAndroid Build Coastguard Worker Curl_none_shutdown, /* shutdown */
1358*6236dae4SAndroid Build Coastguard Worker Curl_none_data_pending, /* data_pending */
1359*6236dae4SAndroid Build Coastguard Worker NULL, /* random */
1360*6236dae4SAndroid Build Coastguard Worker Curl_none_cert_status_request, /* cert_status_request */
1361*6236dae4SAndroid Build Coastguard Worker multissl_connect, /* connect */
1362*6236dae4SAndroid Build Coastguard Worker multissl_connect_nonblocking, /* connect_nonblocking */
1363*6236dae4SAndroid Build Coastguard Worker multissl_adjust_pollset, /* adjust_pollset */
1364*6236dae4SAndroid Build Coastguard Worker multissl_get_internals, /* get_internals */
1365*6236dae4SAndroid Build Coastguard Worker multissl_close, /* close_one */
1366*6236dae4SAndroid Build Coastguard Worker Curl_none_close_all, /* close_all */
1367*6236dae4SAndroid Build Coastguard Worker Curl_none_set_engine, /* set_engine */
1368*6236dae4SAndroid Build Coastguard Worker Curl_none_set_engine_default, /* set_engine_default */
1369*6236dae4SAndroid Build Coastguard Worker Curl_none_engines_list, /* engines_list */
1370*6236dae4SAndroid Build Coastguard Worker Curl_none_false_start, /* false_start */
1371*6236dae4SAndroid Build Coastguard Worker NULL, /* sha256sum */
1372*6236dae4SAndroid Build Coastguard Worker NULL, /* associate_connection */
1373*6236dae4SAndroid Build Coastguard Worker NULL, /* disassociate_connection */
1374*6236dae4SAndroid Build Coastguard Worker multissl_recv_plain, /* recv decrypted data */
1375*6236dae4SAndroid Build Coastguard Worker multissl_send_plain, /* send data to encrypt */
1376*6236dae4SAndroid Build Coastguard Worker NULL, /* get_channel_binding */
1377*6236dae4SAndroid Build Coastguard Worker };
1378*6236dae4SAndroid Build Coastguard Worker
1379*6236dae4SAndroid Build Coastguard Worker const struct Curl_ssl *Curl_ssl =
1380*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_WITH_MULTI_SSL)
1381*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_multi;
1382*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_WOLFSSL)
1383*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_wolfssl;
1384*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_GNUTLS)
1385*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_gnutls;
1386*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_MBEDTLS)
1387*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_mbedtls;
1388*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_RUSTLS)
1389*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_rustls;
1390*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_OPENSSL)
1391*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_openssl;
1392*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_SECTRANSP)
1393*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_sectransp;
1394*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_SCHANNEL)
1395*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_schannel;
1396*6236dae4SAndroid Build Coastguard Worker #elif defined(USE_BEARSSL)
1397*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_bearssl;
1398*6236dae4SAndroid Build Coastguard Worker #else
1399*6236dae4SAndroid Build Coastguard Worker #error "Missing struct Curl_ssl for selected SSL backend"
1400*6236dae4SAndroid Build Coastguard Worker #endif
1401*6236dae4SAndroid Build Coastguard Worker
1402*6236dae4SAndroid Build Coastguard Worker static const struct Curl_ssl *available_backends[] = {
1403*6236dae4SAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
1404*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_wolfssl,
1405*6236dae4SAndroid Build Coastguard Worker #endif
1406*6236dae4SAndroid Build Coastguard Worker #if defined(USE_GNUTLS)
1407*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_gnutls,
1408*6236dae4SAndroid Build Coastguard Worker #endif
1409*6236dae4SAndroid Build Coastguard Worker #if defined(USE_MBEDTLS)
1410*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_mbedtls,
1411*6236dae4SAndroid Build Coastguard Worker #endif
1412*6236dae4SAndroid Build Coastguard Worker #if defined(USE_OPENSSL)
1413*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_openssl,
1414*6236dae4SAndroid Build Coastguard Worker #endif
1415*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SECTRANSP)
1416*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_sectransp,
1417*6236dae4SAndroid Build Coastguard Worker #endif
1418*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SCHANNEL)
1419*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_schannel,
1420*6236dae4SAndroid Build Coastguard Worker #endif
1421*6236dae4SAndroid Build Coastguard Worker #if defined(USE_BEARSSL)
1422*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_bearssl,
1423*6236dae4SAndroid Build Coastguard Worker #endif
1424*6236dae4SAndroid Build Coastguard Worker #if defined(USE_RUSTLS)
1425*6236dae4SAndroid Build Coastguard Worker &Curl_ssl_rustls,
1426*6236dae4SAndroid Build Coastguard Worker #endif
1427*6236dae4SAndroid Build Coastguard Worker NULL
1428*6236dae4SAndroid Build Coastguard Worker };
1429*6236dae4SAndroid Build Coastguard Worker
1430*6236dae4SAndroid Build Coastguard Worker /* Global cleanup */
Curl_ssl_cleanup(void)1431*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_cleanup(void)
1432*6236dae4SAndroid Build Coastguard Worker {
1433*6236dae4SAndroid Build Coastguard Worker if(init_ssl) {
1434*6236dae4SAndroid Build Coastguard Worker /* only cleanup if we did a previous init */
1435*6236dae4SAndroid Build Coastguard Worker Curl_ssl->cleanup();
1436*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_WITH_MULTI_SSL)
1437*6236dae4SAndroid Build Coastguard Worker Curl_ssl = &Curl_ssl_multi;
1438*6236dae4SAndroid Build Coastguard Worker #endif
1439*6236dae4SAndroid Build Coastguard Worker init_ssl = FALSE;
1440*6236dae4SAndroid Build Coastguard Worker }
1441*6236dae4SAndroid Build Coastguard Worker }
1442*6236dae4SAndroid Build Coastguard Worker
multissl_version(char * buffer,size_t size)1443*6236dae4SAndroid Build Coastguard Worker static size_t multissl_version(char *buffer, size_t size)
1444*6236dae4SAndroid Build Coastguard Worker {
1445*6236dae4SAndroid Build Coastguard Worker static const struct Curl_ssl *selected;
1446*6236dae4SAndroid Build Coastguard Worker static char backends[200];
1447*6236dae4SAndroid Build Coastguard Worker static size_t backends_len;
1448*6236dae4SAndroid Build Coastguard Worker const struct Curl_ssl *current;
1449*6236dae4SAndroid Build Coastguard Worker
1450*6236dae4SAndroid Build Coastguard Worker current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
1451*6236dae4SAndroid Build Coastguard Worker
1452*6236dae4SAndroid Build Coastguard Worker if(current != selected) {
1453*6236dae4SAndroid Build Coastguard Worker char *p = backends;
1454*6236dae4SAndroid Build Coastguard Worker char *end = backends + sizeof(backends);
1455*6236dae4SAndroid Build Coastguard Worker int i;
1456*6236dae4SAndroid Build Coastguard Worker
1457*6236dae4SAndroid Build Coastguard Worker selected = current;
1458*6236dae4SAndroid Build Coastguard Worker
1459*6236dae4SAndroid Build Coastguard Worker backends[0] = '\0';
1460*6236dae4SAndroid Build Coastguard Worker
1461*6236dae4SAndroid Build Coastguard Worker for(i = 0; available_backends[i]; ++i) {
1462*6236dae4SAndroid Build Coastguard Worker char vb[200];
1463*6236dae4SAndroid Build Coastguard Worker bool paren = (selected != available_backends[i]);
1464*6236dae4SAndroid Build Coastguard Worker
1465*6236dae4SAndroid Build Coastguard Worker if(available_backends[i]->version(vb, sizeof(vb))) {
1466*6236dae4SAndroid Build Coastguard Worker p += msnprintf(p, end - p, "%s%s%s%s", (p != backends ? " " : ""),
1467*6236dae4SAndroid Build Coastguard Worker (paren ? "(" : ""), vb, (paren ? ")" : ""));
1468*6236dae4SAndroid Build Coastguard Worker }
1469*6236dae4SAndroid Build Coastguard Worker }
1470*6236dae4SAndroid Build Coastguard Worker
1471*6236dae4SAndroid Build Coastguard Worker backends_len = p - backends;
1472*6236dae4SAndroid Build Coastguard Worker }
1473*6236dae4SAndroid Build Coastguard Worker
1474*6236dae4SAndroid Build Coastguard Worker if(size) {
1475*6236dae4SAndroid Build Coastguard Worker if(backends_len < size)
1476*6236dae4SAndroid Build Coastguard Worker strcpy(buffer, backends);
1477*6236dae4SAndroid Build Coastguard Worker else
1478*6236dae4SAndroid Build Coastguard Worker *buffer = 0; /* did not fit */
1479*6236dae4SAndroid Build Coastguard Worker }
1480*6236dae4SAndroid Build Coastguard Worker return 0;
1481*6236dae4SAndroid Build Coastguard Worker }
1482*6236dae4SAndroid Build Coastguard Worker
multissl_setup(const struct Curl_ssl * backend)1483*6236dae4SAndroid Build Coastguard Worker static int multissl_setup(const struct Curl_ssl *backend)
1484*6236dae4SAndroid Build Coastguard Worker {
1485*6236dae4SAndroid Build Coastguard Worker const char *env;
1486*6236dae4SAndroid Build Coastguard Worker char *env_tmp;
1487*6236dae4SAndroid Build Coastguard Worker
1488*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl != &Curl_ssl_multi)
1489*6236dae4SAndroid Build Coastguard Worker return 1;
1490*6236dae4SAndroid Build Coastguard Worker
1491*6236dae4SAndroid Build Coastguard Worker if(backend) {
1492*6236dae4SAndroid Build Coastguard Worker Curl_ssl = backend;
1493*6236dae4SAndroid Build Coastguard Worker return 0;
1494*6236dae4SAndroid Build Coastguard Worker }
1495*6236dae4SAndroid Build Coastguard Worker
1496*6236dae4SAndroid Build Coastguard Worker if(!available_backends[0])
1497*6236dae4SAndroid Build Coastguard Worker return 1;
1498*6236dae4SAndroid Build Coastguard Worker
1499*6236dae4SAndroid Build Coastguard Worker env = env_tmp = curl_getenv("CURL_SSL_BACKEND");
1500*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DEFAULT_SSL_BACKEND
1501*6236dae4SAndroid Build Coastguard Worker if(!env)
1502*6236dae4SAndroid Build Coastguard Worker env = CURL_DEFAULT_SSL_BACKEND;
1503*6236dae4SAndroid Build Coastguard Worker #endif
1504*6236dae4SAndroid Build Coastguard Worker if(env) {
1505*6236dae4SAndroid Build Coastguard Worker int i;
1506*6236dae4SAndroid Build Coastguard Worker for(i = 0; available_backends[i]; i++) {
1507*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(env, available_backends[i]->info.name)) {
1508*6236dae4SAndroid Build Coastguard Worker Curl_ssl = available_backends[i];
1509*6236dae4SAndroid Build Coastguard Worker free(env_tmp);
1510*6236dae4SAndroid Build Coastguard Worker return 0;
1511*6236dae4SAndroid Build Coastguard Worker }
1512*6236dae4SAndroid Build Coastguard Worker }
1513*6236dae4SAndroid Build Coastguard Worker }
1514*6236dae4SAndroid Build Coastguard Worker
1515*6236dae4SAndroid Build Coastguard Worker /* Fall back to first available backend */
1516*6236dae4SAndroid Build Coastguard Worker Curl_ssl = available_backends[0];
1517*6236dae4SAndroid Build Coastguard Worker free(env_tmp);
1518*6236dae4SAndroid Build Coastguard Worker return 0;
1519*6236dae4SAndroid Build Coastguard Worker }
1520*6236dae4SAndroid Build Coastguard Worker
1521*6236dae4SAndroid Build Coastguard Worker /* This function is used to select the SSL backend to use. It is called by
1522*6236dae4SAndroid Build Coastguard Worker curl_global_sslset (easy.c) which uses the global init lock. */
Curl_init_sslset_nolock(curl_sslbackend id,const char * name,const curl_ssl_backend *** avail)1523*6236dae4SAndroid Build Coastguard Worker CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
1524*6236dae4SAndroid Build Coastguard Worker const curl_ssl_backend ***avail)
1525*6236dae4SAndroid Build Coastguard Worker {
1526*6236dae4SAndroid Build Coastguard Worker int i;
1527*6236dae4SAndroid Build Coastguard Worker
1528*6236dae4SAndroid Build Coastguard Worker if(avail)
1529*6236dae4SAndroid Build Coastguard Worker *avail = (const curl_ssl_backend **)&available_backends;
1530*6236dae4SAndroid Build Coastguard Worker
1531*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl != &Curl_ssl_multi)
1532*6236dae4SAndroid Build Coastguard Worker return id == Curl_ssl->info.id ||
1533*6236dae4SAndroid Build Coastguard Worker (name && strcasecompare(name, Curl_ssl->info.name)) ?
1534*6236dae4SAndroid Build Coastguard Worker CURLSSLSET_OK :
1535*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_WITH_MULTI_SSL)
1536*6236dae4SAndroid Build Coastguard Worker CURLSSLSET_TOO_LATE;
1537*6236dae4SAndroid Build Coastguard Worker #else
1538*6236dae4SAndroid Build Coastguard Worker CURLSSLSET_UNKNOWN_BACKEND;
1539*6236dae4SAndroid Build Coastguard Worker #endif
1540*6236dae4SAndroid Build Coastguard Worker
1541*6236dae4SAndroid Build Coastguard Worker for(i = 0; available_backends[i]; i++) {
1542*6236dae4SAndroid Build Coastguard Worker if(available_backends[i]->info.id == id ||
1543*6236dae4SAndroid Build Coastguard Worker (name && strcasecompare(available_backends[i]->info.name, name))) {
1544*6236dae4SAndroid Build Coastguard Worker multissl_setup(available_backends[i]);
1545*6236dae4SAndroid Build Coastguard Worker return CURLSSLSET_OK;
1546*6236dae4SAndroid Build Coastguard Worker }
1547*6236dae4SAndroid Build Coastguard Worker }
1548*6236dae4SAndroid Build Coastguard Worker
1549*6236dae4SAndroid Build Coastguard Worker return CURLSSLSET_UNKNOWN_BACKEND;
1550*6236dae4SAndroid Build Coastguard Worker }
1551*6236dae4SAndroid Build Coastguard Worker
1552*6236dae4SAndroid Build Coastguard Worker #else /* USE_SSL */
Curl_init_sslset_nolock(curl_sslbackend id,const char * name,const curl_ssl_backend *** avail)1553*6236dae4SAndroid Build Coastguard Worker CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
1554*6236dae4SAndroid Build Coastguard Worker const curl_ssl_backend ***avail)
1555*6236dae4SAndroid Build Coastguard Worker {
1556*6236dae4SAndroid Build Coastguard Worker (void)id;
1557*6236dae4SAndroid Build Coastguard Worker (void)name;
1558*6236dae4SAndroid Build Coastguard Worker (void)avail;
1559*6236dae4SAndroid Build Coastguard Worker return CURLSSLSET_NO_BACKENDS;
1560*6236dae4SAndroid Build Coastguard Worker }
1561*6236dae4SAndroid Build Coastguard Worker
1562*6236dae4SAndroid Build Coastguard Worker #endif /* !USE_SSL */
1563*6236dae4SAndroid Build Coastguard Worker
1564*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
1565*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_peer_cleanup(struct ssl_peer * peer)1566*6236dae4SAndroid Build Coastguard Worker void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
1567*6236dae4SAndroid Build Coastguard Worker {
1568*6236dae4SAndroid Build Coastguard Worker if(peer->dispname != peer->hostname)
1569*6236dae4SAndroid Build Coastguard Worker free(peer->dispname);
1570*6236dae4SAndroid Build Coastguard Worker free(peer->sni);
1571*6236dae4SAndroid Build Coastguard Worker free(peer->hostname);
1572*6236dae4SAndroid Build Coastguard Worker peer->hostname = peer->sni = peer->dispname = NULL;
1573*6236dae4SAndroid Build Coastguard Worker peer->type = CURL_SSL_PEER_DNS;
1574*6236dae4SAndroid Build Coastguard Worker }
1575*6236dae4SAndroid Build Coastguard Worker
cf_close(struct Curl_cfilter * cf,struct Curl_easy * data)1576*6236dae4SAndroid Build Coastguard Worker static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1577*6236dae4SAndroid Build Coastguard Worker {
1578*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1579*6236dae4SAndroid Build Coastguard Worker if(connssl) {
1580*6236dae4SAndroid Build Coastguard Worker Curl_ssl->close(cf, data);
1581*6236dae4SAndroid Build Coastguard Worker connssl->state = ssl_connection_none;
1582*6236dae4SAndroid Build Coastguard Worker Curl_ssl_peer_cleanup(&connssl->peer);
1583*6236dae4SAndroid Build Coastguard Worker }
1584*6236dae4SAndroid Build Coastguard Worker cf->connected = FALSE;
1585*6236dae4SAndroid Build Coastguard Worker }
1586*6236dae4SAndroid Build Coastguard Worker
get_peer_type(const char * hostname)1587*6236dae4SAndroid Build Coastguard Worker static ssl_peer_type get_peer_type(const char *hostname)
1588*6236dae4SAndroid Build Coastguard Worker {
1589*6236dae4SAndroid Build Coastguard Worker if(hostname && hostname[0]) {
1590*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1591*6236dae4SAndroid Build Coastguard Worker struct in6_addr addr;
1592*6236dae4SAndroid Build Coastguard Worker #else
1593*6236dae4SAndroid Build Coastguard Worker struct in_addr addr;
1594*6236dae4SAndroid Build Coastguard Worker #endif
1595*6236dae4SAndroid Build Coastguard Worker if(Curl_inet_pton(AF_INET, hostname, &addr))
1596*6236dae4SAndroid Build Coastguard Worker return CURL_SSL_PEER_IPV4;
1597*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1598*6236dae4SAndroid Build Coastguard Worker else if(Curl_inet_pton(AF_INET6, hostname, &addr)) {
1599*6236dae4SAndroid Build Coastguard Worker return CURL_SSL_PEER_IPV6;
1600*6236dae4SAndroid Build Coastguard Worker }
1601*6236dae4SAndroid Build Coastguard Worker #endif
1602*6236dae4SAndroid Build Coastguard Worker }
1603*6236dae4SAndroid Build Coastguard Worker return CURL_SSL_PEER_DNS;
1604*6236dae4SAndroid Build Coastguard Worker }
1605*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_peer_init(struct ssl_peer * peer,struct Curl_cfilter * cf,int transport)1606*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf,
1607*6236dae4SAndroid Build Coastguard Worker int transport)
1608*6236dae4SAndroid Build Coastguard Worker {
1609*6236dae4SAndroid Build Coastguard Worker const char *ehostname, *edispname;
1610*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OUT_OF_MEMORY;
1611*6236dae4SAndroid Build Coastguard Worker
1612*6236dae4SAndroid Build Coastguard Worker /* We expect a clean struct, e.g. called only ONCE */
1613*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(peer);
1614*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!peer->hostname);
1615*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!peer->dispname);
1616*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!peer->sni);
1617*6236dae4SAndroid Build Coastguard Worker /* We need the hostname for SNI negotiation. Once handshaked, this remains
1618*6236dae4SAndroid Build Coastguard Worker * the SNI hostname for the TLS connection. When the connection is reused,
1619*6236dae4SAndroid Build Coastguard Worker * the settings in cf->conn might change. We keep a copy of the hostname we
1620*6236dae4SAndroid Build Coastguard Worker * use for SNI.
1621*6236dae4SAndroid Build Coastguard Worker */
1622*6236dae4SAndroid Build Coastguard Worker peer->transport = transport;
1623*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1624*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl_cf_is_proxy(cf)) {
1625*6236dae4SAndroid Build Coastguard Worker ehostname = cf->conn->http_proxy.host.name;
1626*6236dae4SAndroid Build Coastguard Worker edispname = cf->conn->http_proxy.host.dispname;
1627*6236dae4SAndroid Build Coastguard Worker peer->port = cf->conn->http_proxy.port;
1628*6236dae4SAndroid Build Coastguard Worker }
1629*6236dae4SAndroid Build Coastguard Worker else
1630*6236dae4SAndroid Build Coastguard Worker #endif
1631*6236dae4SAndroid Build Coastguard Worker {
1632*6236dae4SAndroid Build Coastguard Worker ehostname = cf->conn->host.name;
1633*6236dae4SAndroid Build Coastguard Worker edispname = cf->conn->host.dispname;
1634*6236dae4SAndroid Build Coastguard Worker peer->port = cf->conn->remote_port;
1635*6236dae4SAndroid Build Coastguard Worker }
1636*6236dae4SAndroid Build Coastguard Worker
1637*6236dae4SAndroid Build Coastguard Worker /* hostname MUST exist and not be empty */
1638*6236dae4SAndroid Build Coastguard Worker if(!ehostname || !ehostname[0]) {
1639*6236dae4SAndroid Build Coastguard Worker result = CURLE_FAILED_INIT;
1640*6236dae4SAndroid Build Coastguard Worker goto out;
1641*6236dae4SAndroid Build Coastguard Worker }
1642*6236dae4SAndroid Build Coastguard Worker
1643*6236dae4SAndroid Build Coastguard Worker peer->hostname = strdup(ehostname);
1644*6236dae4SAndroid Build Coastguard Worker if(!peer->hostname)
1645*6236dae4SAndroid Build Coastguard Worker goto out;
1646*6236dae4SAndroid Build Coastguard Worker if(!edispname || !strcmp(ehostname, edispname))
1647*6236dae4SAndroid Build Coastguard Worker peer->dispname = peer->hostname;
1648*6236dae4SAndroid Build Coastguard Worker else {
1649*6236dae4SAndroid Build Coastguard Worker peer->dispname = strdup(edispname);
1650*6236dae4SAndroid Build Coastguard Worker if(!peer->dispname)
1651*6236dae4SAndroid Build Coastguard Worker goto out;
1652*6236dae4SAndroid Build Coastguard Worker }
1653*6236dae4SAndroid Build Coastguard Worker peer->type = get_peer_type(peer->hostname);
1654*6236dae4SAndroid Build Coastguard Worker if(peer->type == CURL_SSL_PEER_DNS) {
1655*6236dae4SAndroid Build Coastguard Worker /* not an IP address, normalize according to RCC 6066 ch. 3,
1656*6236dae4SAndroid Build Coastguard Worker * max len of SNI is 2^16-1, no trailing dot */
1657*6236dae4SAndroid Build Coastguard Worker size_t len = strlen(peer->hostname);
1658*6236dae4SAndroid Build Coastguard Worker if(len && (peer->hostname[len-1] == '.'))
1659*6236dae4SAndroid Build Coastguard Worker len--;
1660*6236dae4SAndroid Build Coastguard Worker if(len < USHRT_MAX) {
1661*6236dae4SAndroid Build Coastguard Worker peer->sni = calloc(1, len + 1);
1662*6236dae4SAndroid Build Coastguard Worker if(!peer->sni)
1663*6236dae4SAndroid Build Coastguard Worker goto out;
1664*6236dae4SAndroid Build Coastguard Worker Curl_strntolower(peer->sni, peer->hostname, len);
1665*6236dae4SAndroid Build Coastguard Worker peer->sni[len] = 0;
1666*6236dae4SAndroid Build Coastguard Worker }
1667*6236dae4SAndroid Build Coastguard Worker }
1668*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
1669*6236dae4SAndroid Build Coastguard Worker
1670*6236dae4SAndroid Build Coastguard Worker out:
1671*6236dae4SAndroid Build Coastguard Worker if(result)
1672*6236dae4SAndroid Build Coastguard Worker Curl_ssl_peer_cleanup(peer);
1673*6236dae4SAndroid Build Coastguard Worker return result;
1674*6236dae4SAndroid Build Coastguard Worker }
1675*6236dae4SAndroid Build Coastguard Worker
ssl_cf_destroy(struct Curl_cfilter * cf,struct Curl_easy * data)1676*6236dae4SAndroid Build Coastguard Worker static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
1677*6236dae4SAndroid Build Coastguard Worker {
1678*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1679*6236dae4SAndroid Build Coastguard Worker
1680*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1681*6236dae4SAndroid Build Coastguard Worker cf_close(cf, data);
1682*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1683*6236dae4SAndroid Build Coastguard Worker cf_ctx_free(cf->ctx);
1684*6236dae4SAndroid Build Coastguard Worker cf->ctx = NULL;
1685*6236dae4SAndroid Build Coastguard Worker }
1686*6236dae4SAndroid Build Coastguard Worker
ssl_cf_close(struct Curl_cfilter * cf,struct Curl_easy * data)1687*6236dae4SAndroid Build Coastguard Worker static void ssl_cf_close(struct Curl_cfilter *cf,
1688*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
1689*6236dae4SAndroid Build Coastguard Worker {
1690*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1691*6236dae4SAndroid Build Coastguard Worker
1692*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1693*6236dae4SAndroid Build Coastguard Worker cf_close(cf, data);
1694*6236dae4SAndroid Build Coastguard Worker if(cf->next)
1695*6236dae4SAndroid Build Coastguard Worker cf->next->cft->do_close(cf->next, data);
1696*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1697*6236dae4SAndroid Build Coastguard Worker }
1698*6236dae4SAndroid Build Coastguard Worker
ssl_cf_connect(struct Curl_cfilter * cf,struct Curl_easy * data,bool blocking,bool * done)1699*6236dae4SAndroid Build Coastguard Worker static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
1700*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1701*6236dae4SAndroid Build Coastguard Worker bool blocking, bool *done)
1702*6236dae4SAndroid Build Coastguard Worker {
1703*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1704*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1705*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1706*6236dae4SAndroid Build Coastguard Worker
1707*6236dae4SAndroid Build Coastguard Worker if(cf->connected) {
1708*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1709*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1710*6236dae4SAndroid Build Coastguard Worker }
1711*6236dae4SAndroid Build Coastguard Worker
1712*6236dae4SAndroid Build Coastguard Worker if(!cf->next) {
1713*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1714*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1715*6236dae4SAndroid Build Coastguard Worker }
1716*6236dae4SAndroid Build Coastguard Worker
1717*6236dae4SAndroid Build Coastguard Worker if(!cf->next->connected) {
1718*6236dae4SAndroid Build Coastguard Worker result = cf->next->cft->do_connect(cf->next, data, blocking, done);
1719*6236dae4SAndroid Build Coastguard Worker if(result || !*done)
1720*6236dae4SAndroid Build Coastguard Worker return result;
1721*6236dae4SAndroid Build Coastguard Worker }
1722*6236dae4SAndroid Build Coastguard Worker
1723*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1724*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "cf_connect()");
1725*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
1726*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn == cf->conn);
1727*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl);
1728*6236dae4SAndroid Build Coastguard Worker
1729*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1730*6236dae4SAndroid Build Coastguard Worker if(!connssl->peer.hostname) {
1731*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl_peer_init(&connssl->peer, cf, TRNSPRT_TCP);
1732*6236dae4SAndroid Build Coastguard Worker if(result)
1733*6236dae4SAndroid Build Coastguard Worker goto out;
1734*6236dae4SAndroid Build Coastguard Worker }
1735*6236dae4SAndroid Build Coastguard Worker
1736*6236dae4SAndroid Build Coastguard Worker if(blocking) {
1737*6236dae4SAndroid Build Coastguard Worker result = ssl_connect(cf, data);
1738*6236dae4SAndroid Build Coastguard Worker *done = (result == CURLE_OK);
1739*6236dae4SAndroid Build Coastguard Worker }
1740*6236dae4SAndroid Build Coastguard Worker else {
1741*6236dae4SAndroid Build Coastguard Worker result = ssl_connect_nonblocking(cf, data, done);
1742*6236dae4SAndroid Build Coastguard Worker }
1743*6236dae4SAndroid Build Coastguard Worker
1744*6236dae4SAndroid Build Coastguard Worker if(!result && *done) {
1745*6236dae4SAndroid Build Coastguard Worker cf->connected = TRUE;
1746*6236dae4SAndroid Build Coastguard Worker connssl->handshake_done = Curl_now();
1747*6236dae4SAndroid Build Coastguard Worker /* Connection can be deferred when sending early data */
1748*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->state == ssl_connection_complete ||
1749*6236dae4SAndroid Build Coastguard Worker connssl->state == ssl_connection_deferred);
1750*6236dae4SAndroid Build Coastguard Worker }
1751*6236dae4SAndroid Build Coastguard Worker out:
1752*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
1753*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1754*6236dae4SAndroid Build Coastguard Worker return result;
1755*6236dae4SAndroid Build Coastguard Worker }
1756*6236dae4SAndroid Build Coastguard Worker
ssl_cf_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1757*6236dae4SAndroid Build Coastguard Worker static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
1758*6236dae4SAndroid Build Coastguard Worker const struct Curl_easy *data)
1759*6236dae4SAndroid Build Coastguard Worker {
1760*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1761*6236dae4SAndroid Build Coastguard Worker bool result;
1762*6236dae4SAndroid Build Coastguard Worker
1763*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1764*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl->data_pending(cf, data))
1765*6236dae4SAndroid Build Coastguard Worker result = TRUE;
1766*6236dae4SAndroid Build Coastguard Worker else
1767*6236dae4SAndroid Build Coastguard Worker result = cf->next->cft->has_data_pending(cf->next, data);
1768*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1769*6236dae4SAndroid Build Coastguard Worker return result;
1770*6236dae4SAndroid Build Coastguard Worker }
1771*6236dae4SAndroid Build Coastguard Worker
ssl_cf_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t len,bool eos,CURLcode * err)1772*6236dae4SAndroid Build Coastguard Worker static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
1773*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data, const void *buf, size_t len,
1774*6236dae4SAndroid Build Coastguard Worker bool eos, CURLcode *err)
1775*6236dae4SAndroid Build Coastguard Worker {
1776*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1777*6236dae4SAndroid Build Coastguard Worker ssize_t nwritten = 0;
1778*6236dae4SAndroid Build Coastguard Worker
1779*6236dae4SAndroid Build Coastguard Worker (void)eos;
1780*6236dae4SAndroid Build Coastguard Worker /* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
1781*6236dae4SAndroid Build Coastguard Worker *err = CURLE_OK;
1782*6236dae4SAndroid Build Coastguard Worker if(len > 0) {
1783*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1784*6236dae4SAndroid Build Coastguard Worker nwritten = Curl_ssl->send_plain(cf, data, buf, len, err);
1785*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1786*6236dae4SAndroid Build Coastguard Worker }
1787*6236dae4SAndroid Build Coastguard Worker return nwritten;
1788*6236dae4SAndroid Build Coastguard Worker }
1789*6236dae4SAndroid Build Coastguard Worker
ssl_cf_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t len,CURLcode * err)1790*6236dae4SAndroid Build Coastguard Worker static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
1791*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data, char *buf, size_t len,
1792*6236dae4SAndroid Build Coastguard Worker CURLcode *err)
1793*6236dae4SAndroid Build Coastguard Worker {
1794*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1795*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
1796*6236dae4SAndroid Build Coastguard Worker
1797*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1798*6236dae4SAndroid Build Coastguard Worker *err = CURLE_OK;
1799*6236dae4SAndroid Build Coastguard Worker nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
1800*6236dae4SAndroid Build Coastguard Worker if(nread > 0) {
1801*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((size_t)nread <= len);
1802*6236dae4SAndroid Build Coastguard Worker }
1803*6236dae4SAndroid Build Coastguard Worker else if(nread == 0) {
1804*6236dae4SAndroid Build Coastguard Worker /* eof */
1805*6236dae4SAndroid Build Coastguard Worker *err = CURLE_OK;
1806*6236dae4SAndroid Build Coastguard Worker }
1807*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
1808*6236dae4SAndroid Build Coastguard Worker nread, *err);
1809*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1810*6236dae4SAndroid Build Coastguard Worker return nread;
1811*6236dae4SAndroid Build Coastguard Worker }
1812*6236dae4SAndroid Build Coastguard Worker
ssl_cf_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1813*6236dae4SAndroid Build Coastguard Worker static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
1814*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1815*6236dae4SAndroid Build Coastguard Worker bool *done)
1816*6236dae4SAndroid Build Coastguard Worker {
1817*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1818*6236dae4SAndroid Build Coastguard Worker
1819*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1820*6236dae4SAndroid Build Coastguard Worker if(!cf->shutdown) {
1821*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1822*6236dae4SAndroid Build Coastguard Worker
1823*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1824*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl->shut_down(cf, data, TRUE, done);
1825*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "cf_shutdown -> %d, done=%d", result, *done);
1826*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1827*6236dae4SAndroid Build Coastguard Worker cf->shutdown = (result || *done);
1828*6236dae4SAndroid Build Coastguard Worker }
1829*6236dae4SAndroid Build Coastguard Worker return result;
1830*6236dae4SAndroid Build Coastguard Worker }
1831*6236dae4SAndroid Build Coastguard Worker
ssl_cf_adjust_pollset(struct Curl_cfilter * cf,struct Curl_easy * data,struct easy_pollset * ps)1832*6236dae4SAndroid Build Coastguard Worker static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
1833*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1834*6236dae4SAndroid Build Coastguard Worker struct easy_pollset *ps)
1835*6236dae4SAndroid Build Coastguard Worker {
1836*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1837*6236dae4SAndroid Build Coastguard Worker
1838*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1839*6236dae4SAndroid Build Coastguard Worker Curl_ssl->adjust_pollset(cf, data, ps);
1840*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1841*6236dae4SAndroid Build Coastguard Worker }
1842*6236dae4SAndroid Build Coastguard Worker
ssl_cf_cntrl(struct Curl_cfilter * cf,struct Curl_easy * data,int event,int arg1,void * arg2)1843*6236dae4SAndroid Build Coastguard Worker static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
1844*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1845*6236dae4SAndroid Build Coastguard Worker int event, int arg1, void *arg2)
1846*6236dae4SAndroid Build Coastguard Worker {
1847*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1848*6236dae4SAndroid Build Coastguard Worker
1849*6236dae4SAndroid Build Coastguard Worker (void)arg1;
1850*6236dae4SAndroid Build Coastguard Worker (void)arg2;
1851*6236dae4SAndroid Build Coastguard Worker switch(event) {
1852*6236dae4SAndroid Build Coastguard Worker case CF_CTRL_DATA_ATTACH:
1853*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl->attach_data) {
1854*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1855*6236dae4SAndroid Build Coastguard Worker Curl_ssl->attach_data(cf, data);
1856*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1857*6236dae4SAndroid Build Coastguard Worker }
1858*6236dae4SAndroid Build Coastguard Worker break;
1859*6236dae4SAndroid Build Coastguard Worker case CF_CTRL_DATA_DETACH:
1860*6236dae4SAndroid Build Coastguard Worker if(Curl_ssl->detach_data) {
1861*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1862*6236dae4SAndroid Build Coastguard Worker Curl_ssl->detach_data(cf, data);
1863*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1864*6236dae4SAndroid Build Coastguard Worker }
1865*6236dae4SAndroid Build Coastguard Worker break;
1866*6236dae4SAndroid Build Coastguard Worker default:
1867*6236dae4SAndroid Build Coastguard Worker break;
1868*6236dae4SAndroid Build Coastguard Worker }
1869*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1870*6236dae4SAndroid Build Coastguard Worker }
1871*6236dae4SAndroid Build Coastguard Worker
ssl_cf_query(struct Curl_cfilter * cf,struct Curl_easy * data,int query,int * pres1,void * pres2)1872*6236dae4SAndroid Build Coastguard Worker static CURLcode ssl_cf_query(struct Curl_cfilter *cf,
1873*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1874*6236dae4SAndroid Build Coastguard Worker int query, int *pres1, void *pres2)
1875*6236dae4SAndroid Build Coastguard Worker {
1876*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1877*6236dae4SAndroid Build Coastguard Worker
1878*6236dae4SAndroid Build Coastguard Worker switch(query) {
1879*6236dae4SAndroid Build Coastguard Worker case CF_QUERY_TIMER_APPCONNECT: {
1880*6236dae4SAndroid Build Coastguard Worker struct curltime *when = pres2;
1881*6236dae4SAndroid Build Coastguard Worker if(cf->connected && !Curl_ssl_cf_is_proxy(cf))
1882*6236dae4SAndroid Build Coastguard Worker *when = connssl->handshake_done;
1883*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1884*6236dae4SAndroid Build Coastguard Worker }
1885*6236dae4SAndroid Build Coastguard Worker default:
1886*6236dae4SAndroid Build Coastguard Worker break;
1887*6236dae4SAndroid Build Coastguard Worker }
1888*6236dae4SAndroid Build Coastguard Worker return cf->next ?
1889*6236dae4SAndroid Build Coastguard Worker cf->next->cft->query(cf->next, data, query, pres1, pres2) :
1890*6236dae4SAndroid Build Coastguard Worker CURLE_UNKNOWN_OPTION;
1891*6236dae4SAndroid Build Coastguard Worker }
1892*6236dae4SAndroid Build Coastguard Worker
cf_ssl_is_alive(struct Curl_cfilter * cf,struct Curl_easy * data,bool * input_pending)1893*6236dae4SAndroid Build Coastguard Worker static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data,
1894*6236dae4SAndroid Build Coastguard Worker bool *input_pending)
1895*6236dae4SAndroid Build Coastguard Worker {
1896*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
1897*6236dae4SAndroid Build Coastguard Worker int result;
1898*6236dae4SAndroid Build Coastguard Worker /*
1899*6236dae4SAndroid Build Coastguard Worker * This function tries to determine connection status.
1900*6236dae4SAndroid Build Coastguard Worker *
1901*6236dae4SAndroid Build Coastguard Worker * Return codes:
1902*6236dae4SAndroid Build Coastguard Worker * 1 means the connection is still in place
1903*6236dae4SAndroid Build Coastguard Worker * 0 means the connection has been closed
1904*6236dae4SAndroid Build Coastguard Worker * -1 means the connection status is unknown
1905*6236dae4SAndroid Build Coastguard Worker */
1906*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
1907*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl->check_cxn(cf, data);
1908*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
1909*6236dae4SAndroid Build Coastguard Worker if(result > 0) {
1910*6236dae4SAndroid Build Coastguard Worker *input_pending = TRUE;
1911*6236dae4SAndroid Build Coastguard Worker return TRUE;
1912*6236dae4SAndroid Build Coastguard Worker }
1913*6236dae4SAndroid Build Coastguard Worker if(result == 0) {
1914*6236dae4SAndroid Build Coastguard Worker *input_pending = FALSE;
1915*6236dae4SAndroid Build Coastguard Worker return FALSE;
1916*6236dae4SAndroid Build Coastguard Worker }
1917*6236dae4SAndroid Build Coastguard Worker /* ssl backend does not know */
1918*6236dae4SAndroid Build Coastguard Worker return cf->next ?
1919*6236dae4SAndroid Build Coastguard Worker cf->next->cft->is_alive(cf->next, data, input_pending) :
1920*6236dae4SAndroid Build Coastguard Worker FALSE; /* pessimistic in absence of data */
1921*6236dae4SAndroid Build Coastguard Worker }
1922*6236dae4SAndroid Build Coastguard Worker
1923*6236dae4SAndroid Build Coastguard Worker struct Curl_cftype Curl_cft_ssl = {
1924*6236dae4SAndroid Build Coastguard Worker "SSL",
1925*6236dae4SAndroid Build Coastguard Worker CF_TYPE_SSL,
1926*6236dae4SAndroid Build Coastguard Worker CURL_LOG_LVL_NONE,
1927*6236dae4SAndroid Build Coastguard Worker ssl_cf_destroy,
1928*6236dae4SAndroid Build Coastguard Worker ssl_cf_connect,
1929*6236dae4SAndroid Build Coastguard Worker ssl_cf_close,
1930*6236dae4SAndroid Build Coastguard Worker ssl_cf_shutdown,
1931*6236dae4SAndroid Build Coastguard Worker Curl_cf_def_get_host,
1932*6236dae4SAndroid Build Coastguard Worker ssl_cf_adjust_pollset,
1933*6236dae4SAndroid Build Coastguard Worker ssl_cf_data_pending,
1934*6236dae4SAndroid Build Coastguard Worker ssl_cf_send,
1935*6236dae4SAndroid Build Coastguard Worker ssl_cf_recv,
1936*6236dae4SAndroid Build Coastguard Worker ssl_cf_cntrl,
1937*6236dae4SAndroid Build Coastguard Worker cf_ssl_is_alive,
1938*6236dae4SAndroid Build Coastguard Worker Curl_cf_def_conn_keep_alive,
1939*6236dae4SAndroid Build Coastguard Worker ssl_cf_query,
1940*6236dae4SAndroid Build Coastguard Worker };
1941*6236dae4SAndroid Build Coastguard Worker
1942*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1943*6236dae4SAndroid Build Coastguard Worker
1944*6236dae4SAndroid Build Coastguard Worker struct Curl_cftype Curl_cft_ssl_proxy = {
1945*6236dae4SAndroid Build Coastguard Worker "SSL-PROXY",
1946*6236dae4SAndroid Build Coastguard Worker CF_TYPE_SSL|CF_TYPE_PROXY,
1947*6236dae4SAndroid Build Coastguard Worker CURL_LOG_LVL_NONE,
1948*6236dae4SAndroid Build Coastguard Worker ssl_cf_destroy,
1949*6236dae4SAndroid Build Coastguard Worker ssl_cf_connect,
1950*6236dae4SAndroid Build Coastguard Worker ssl_cf_close,
1951*6236dae4SAndroid Build Coastguard Worker ssl_cf_shutdown,
1952*6236dae4SAndroid Build Coastguard Worker Curl_cf_def_get_host,
1953*6236dae4SAndroid Build Coastguard Worker ssl_cf_adjust_pollset,
1954*6236dae4SAndroid Build Coastguard Worker ssl_cf_data_pending,
1955*6236dae4SAndroid Build Coastguard Worker ssl_cf_send,
1956*6236dae4SAndroid Build Coastguard Worker ssl_cf_recv,
1957*6236dae4SAndroid Build Coastguard Worker ssl_cf_cntrl,
1958*6236dae4SAndroid Build Coastguard Worker cf_ssl_is_alive,
1959*6236dae4SAndroid Build Coastguard Worker Curl_cf_def_conn_keep_alive,
1960*6236dae4SAndroid Build Coastguard Worker Curl_cf_def_query,
1961*6236dae4SAndroid Build Coastguard Worker };
1962*6236dae4SAndroid Build Coastguard Worker
1963*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_PROXY */
1964*6236dae4SAndroid Build Coastguard Worker
cf_ssl_create(struct Curl_cfilter ** pcf,struct Curl_easy * data,struct connectdata * conn)1965*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
1966*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1967*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn)
1968*6236dae4SAndroid Build Coastguard Worker {
1969*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf = NULL;
1970*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *ctx;
1971*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1972*6236dae4SAndroid Build Coastguard Worker
1973*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
1974*6236dae4SAndroid Build Coastguard Worker
1975*6236dae4SAndroid Build Coastguard Worker ctx = cf_ctx_new(data, alpn_get_spec(data->state.httpwant,
1976*6236dae4SAndroid Build Coastguard Worker conn->bits.tls_enable_alpn));
1977*6236dae4SAndroid Build Coastguard Worker if(!ctx) {
1978*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
1979*6236dae4SAndroid Build Coastguard Worker goto out;
1980*6236dae4SAndroid Build Coastguard Worker }
1981*6236dae4SAndroid Build Coastguard Worker
1982*6236dae4SAndroid Build Coastguard Worker result = Curl_cf_create(&cf, &Curl_cft_ssl, ctx);
1983*6236dae4SAndroid Build Coastguard Worker
1984*6236dae4SAndroid Build Coastguard Worker out:
1985*6236dae4SAndroid Build Coastguard Worker if(result)
1986*6236dae4SAndroid Build Coastguard Worker cf_ctx_free(ctx);
1987*6236dae4SAndroid Build Coastguard Worker *pcf = result ? NULL : cf;
1988*6236dae4SAndroid Build Coastguard Worker return result;
1989*6236dae4SAndroid Build Coastguard Worker }
1990*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_cfilter_add(struct Curl_easy * data,struct connectdata * conn,int sockindex)1991*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
1992*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn,
1993*6236dae4SAndroid Build Coastguard Worker int sockindex)
1994*6236dae4SAndroid Build Coastguard Worker {
1995*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf;
1996*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1997*6236dae4SAndroid Build Coastguard Worker
1998*6236dae4SAndroid Build Coastguard Worker result = cf_ssl_create(&cf, data, conn);
1999*6236dae4SAndroid Build Coastguard Worker if(!result)
2000*6236dae4SAndroid Build Coastguard Worker Curl_conn_cf_add(data, conn, sockindex, cf);
2001*6236dae4SAndroid Build Coastguard Worker return result;
2002*6236dae4SAndroid Build Coastguard Worker }
2003*6236dae4SAndroid Build Coastguard Worker
Curl_cf_ssl_insert_after(struct Curl_cfilter * cf_at,struct Curl_easy * data)2004*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
2005*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
2006*6236dae4SAndroid Build Coastguard Worker {
2007*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf;
2008*6236dae4SAndroid Build Coastguard Worker CURLcode result;
2009*6236dae4SAndroid Build Coastguard Worker
2010*6236dae4SAndroid Build Coastguard Worker result = cf_ssl_create(&cf, data, cf_at->conn);
2011*6236dae4SAndroid Build Coastguard Worker if(!result)
2012*6236dae4SAndroid Build Coastguard Worker Curl_conn_cf_insert_after(cf_at, cf);
2013*6236dae4SAndroid Build Coastguard Worker return result;
2014*6236dae4SAndroid Build Coastguard Worker }
2015*6236dae4SAndroid Build Coastguard Worker
2016*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2017*6236dae4SAndroid Build Coastguard Worker
cf_ssl_proxy_create(struct Curl_cfilter ** pcf,struct Curl_easy * data,struct connectdata * conn)2018*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
2019*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2020*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn)
2021*6236dae4SAndroid Build Coastguard Worker {
2022*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf = NULL;
2023*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *ctx;
2024*6236dae4SAndroid Build Coastguard Worker CURLcode result;
2025*6236dae4SAndroid Build Coastguard Worker bool use_alpn = conn->bits.tls_enable_alpn;
2026*6236dae4SAndroid Build Coastguard Worker int httpwant = CURL_HTTP_VERSION_1_1;
2027*6236dae4SAndroid Build Coastguard Worker
2028*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP2
2029*6236dae4SAndroid Build Coastguard Worker if(conn->http_proxy.proxytype == CURLPROXY_HTTPS2) {
2030*6236dae4SAndroid Build Coastguard Worker use_alpn = TRUE;
2031*6236dae4SAndroid Build Coastguard Worker httpwant = CURL_HTTP_VERSION_2;
2032*6236dae4SAndroid Build Coastguard Worker }
2033*6236dae4SAndroid Build Coastguard Worker #endif
2034*6236dae4SAndroid Build Coastguard Worker
2035*6236dae4SAndroid Build Coastguard Worker ctx = cf_ctx_new(data, alpn_get_spec(httpwant, use_alpn));
2036*6236dae4SAndroid Build Coastguard Worker if(!ctx) {
2037*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
2038*6236dae4SAndroid Build Coastguard Worker goto out;
2039*6236dae4SAndroid Build Coastguard Worker }
2040*6236dae4SAndroid Build Coastguard Worker result = Curl_cf_create(&cf, &Curl_cft_ssl_proxy, ctx);
2041*6236dae4SAndroid Build Coastguard Worker
2042*6236dae4SAndroid Build Coastguard Worker out:
2043*6236dae4SAndroid Build Coastguard Worker if(result)
2044*6236dae4SAndroid Build Coastguard Worker cf_ctx_free(ctx);
2045*6236dae4SAndroid Build Coastguard Worker *pcf = result ? NULL : cf;
2046*6236dae4SAndroid Build Coastguard Worker return result;
2047*6236dae4SAndroid Build Coastguard Worker }
2048*6236dae4SAndroid Build Coastguard Worker
Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter * cf_at,struct Curl_easy * data)2049*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
2050*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
2051*6236dae4SAndroid Build Coastguard Worker {
2052*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf;
2053*6236dae4SAndroid Build Coastguard Worker CURLcode result;
2054*6236dae4SAndroid Build Coastguard Worker
2055*6236dae4SAndroid Build Coastguard Worker result = cf_ssl_proxy_create(&cf, data, cf_at->conn);
2056*6236dae4SAndroid Build Coastguard Worker if(!result)
2057*6236dae4SAndroid Build Coastguard Worker Curl_conn_cf_insert_after(cf_at, cf);
2058*6236dae4SAndroid Build Coastguard Worker return result;
2059*6236dae4SAndroid Build Coastguard Worker }
2060*6236dae4SAndroid Build Coastguard Worker
2061*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_PROXY */
2062*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_supports(struct Curl_easy * data,unsigned int ssl_option)2063*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_supports(struct Curl_easy *data, unsigned int ssl_option)
2064*6236dae4SAndroid Build Coastguard Worker {
2065*6236dae4SAndroid Build Coastguard Worker (void)data;
2066*6236dae4SAndroid Build Coastguard Worker return (Curl_ssl->supports & ssl_option);
2067*6236dae4SAndroid Build Coastguard Worker }
2068*6236dae4SAndroid Build Coastguard Worker
get_ssl_filter(struct Curl_cfilter * cf)2069*6236dae4SAndroid Build Coastguard Worker static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf)
2070*6236dae4SAndroid Build Coastguard Worker {
2071*6236dae4SAndroid Build Coastguard Worker for(; cf; cf = cf->next) {
2072*6236dae4SAndroid Build Coastguard Worker if(cf->cft == &Curl_cft_ssl)
2073*6236dae4SAndroid Build Coastguard Worker return cf;
2074*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2075*6236dae4SAndroid Build Coastguard Worker if(cf->cft == &Curl_cft_ssl_proxy)
2076*6236dae4SAndroid Build Coastguard Worker return cf;
2077*6236dae4SAndroid Build Coastguard Worker #endif
2078*6236dae4SAndroid Build Coastguard Worker }
2079*6236dae4SAndroid Build Coastguard Worker return NULL;
2080*6236dae4SAndroid Build Coastguard Worker }
2081*6236dae4SAndroid Build Coastguard Worker
2082*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_get_internals(struct Curl_easy * data,int sockindex,CURLINFO info,int n)2083*6236dae4SAndroid Build Coastguard Worker void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
2084*6236dae4SAndroid Build Coastguard Worker CURLINFO info, int n)
2085*6236dae4SAndroid Build Coastguard Worker {
2086*6236dae4SAndroid Build Coastguard Worker void *result = NULL;
2087*6236dae4SAndroid Build Coastguard Worker (void)n;
2088*6236dae4SAndroid Build Coastguard Worker if(data->conn) {
2089*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf;
2090*6236dae4SAndroid Build Coastguard Worker /* get first SSL filter in chain, if any is present */
2091*6236dae4SAndroid Build Coastguard Worker cf = get_ssl_filter(data->conn->cfilter[sockindex]);
2092*6236dae4SAndroid Build Coastguard Worker if(cf) {
2093*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
2094*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
2095*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl->get_internals(cf->ctx, info);
2096*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
2097*6236dae4SAndroid Build Coastguard Worker }
2098*6236dae4SAndroid Build Coastguard Worker }
2099*6236dae4SAndroid Build Coastguard Worker return result;
2100*6236dae4SAndroid Build Coastguard Worker }
2101*6236dae4SAndroid Build Coastguard Worker
vtls_shutdown_blocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)2102*6236dae4SAndroid Build Coastguard Worker static CURLcode vtls_shutdown_blocking(struct Curl_cfilter *cf,
2103*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2104*6236dae4SAndroid Build Coastguard Worker bool send_shutdown, bool *done)
2105*6236dae4SAndroid Build Coastguard Worker {
2106*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
2107*6236dae4SAndroid Build Coastguard Worker struct cf_call_data save;
2108*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2109*6236dae4SAndroid Build Coastguard Worker timediff_t timeout_ms;
2110*6236dae4SAndroid Build Coastguard Worker int what, loop = 10;
2111*6236dae4SAndroid Build Coastguard Worker
2112*6236dae4SAndroid Build Coastguard Worker if(cf->shutdown) {
2113*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
2114*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2115*6236dae4SAndroid Build Coastguard Worker }
2116*6236dae4SAndroid Build Coastguard Worker CF_DATA_SAVE(save, cf, data);
2117*6236dae4SAndroid Build Coastguard Worker
2118*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
2119*6236dae4SAndroid Build Coastguard Worker while(!result && !*done && loop--) {
2120*6236dae4SAndroid Build Coastguard Worker timeout_ms = Curl_shutdown_timeleft(cf->conn, cf->sockindex, NULL);
2121*6236dae4SAndroid Build Coastguard Worker
2122*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0) {
2123*6236dae4SAndroid Build Coastguard Worker /* no need to continue if time is already up */
2124*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL shutdown timeout");
2125*6236dae4SAndroid Build Coastguard Worker return CURLE_OPERATION_TIMEDOUT;
2126*6236dae4SAndroid Build Coastguard Worker }
2127*6236dae4SAndroid Build Coastguard Worker
2128*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl->shut_down(cf, data, send_shutdown, done);
2129*6236dae4SAndroid Build Coastguard Worker if(result ||*done)
2130*6236dae4SAndroid Build Coastguard Worker goto out;
2131*6236dae4SAndroid Build Coastguard Worker
2132*6236dae4SAndroid Build Coastguard Worker if(connssl->io_need) {
2133*6236dae4SAndroid Build Coastguard Worker what = Curl_conn_cf_poll(cf, data, timeout_ms);
2134*6236dae4SAndroid Build Coastguard Worker if(what < 0) {
2135*6236dae4SAndroid Build Coastguard Worker /* fatal error */
2136*6236dae4SAndroid Build Coastguard Worker failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
2137*6236dae4SAndroid Build Coastguard Worker result = CURLE_RECV_ERROR;
2138*6236dae4SAndroid Build Coastguard Worker goto out;
2139*6236dae4SAndroid Build Coastguard Worker }
2140*6236dae4SAndroid Build Coastguard Worker else if(0 == what) {
2141*6236dae4SAndroid Build Coastguard Worker /* timeout */
2142*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL shutdown timeout");
2143*6236dae4SAndroid Build Coastguard Worker result = CURLE_OPERATION_TIMEDOUT;
2144*6236dae4SAndroid Build Coastguard Worker goto out;
2145*6236dae4SAndroid Build Coastguard Worker }
2146*6236dae4SAndroid Build Coastguard Worker /* socket is readable or writable */
2147*6236dae4SAndroid Build Coastguard Worker }
2148*6236dae4SAndroid Build Coastguard Worker }
2149*6236dae4SAndroid Build Coastguard Worker out:
2150*6236dae4SAndroid Build Coastguard Worker CF_DATA_RESTORE(cf, save);
2151*6236dae4SAndroid Build Coastguard Worker cf->shutdown = (result || *done);
2152*6236dae4SAndroid Build Coastguard Worker return result;
2153*6236dae4SAndroid Build Coastguard Worker }
2154*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_cfilter_remove(struct Curl_easy * data,int sockindex,bool send_shutdown)2155*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
2156*6236dae4SAndroid Build Coastguard Worker int sockindex, bool send_shutdown)
2157*6236dae4SAndroid Build Coastguard Worker {
2158*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf, *head;
2159*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2160*6236dae4SAndroid Build Coastguard Worker
2161*6236dae4SAndroid Build Coastguard Worker head = data->conn ? data->conn->cfilter[sockindex] : NULL;
2162*6236dae4SAndroid Build Coastguard Worker for(cf = head; cf; cf = cf->next) {
2163*6236dae4SAndroid Build Coastguard Worker if(cf->cft == &Curl_cft_ssl) {
2164*6236dae4SAndroid Build Coastguard Worker bool done;
2165*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "shutdown and remove SSL, start");
2166*6236dae4SAndroid Build Coastguard Worker Curl_shutdown_start(data, sockindex, NULL);
2167*6236dae4SAndroid Build Coastguard Worker result = vtls_shutdown_blocking(cf, data, send_shutdown, &done);
2168*6236dae4SAndroid Build Coastguard Worker Curl_shutdown_clear(data, sockindex);
2169*6236dae4SAndroid Build Coastguard Worker if(!result && !done) /* blocking failed? */
2170*6236dae4SAndroid Build Coastguard Worker result = CURLE_SSL_SHUTDOWN_FAILED;
2171*6236dae4SAndroid Build Coastguard Worker Curl_conn_cf_discard_sub(head, cf, data, FALSE);
2172*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "shutdown and remove SSL, done -> %d", result);
2173*6236dae4SAndroid Build Coastguard Worker break;
2174*6236dae4SAndroid Build Coastguard Worker }
2175*6236dae4SAndroid Build Coastguard Worker }
2176*6236dae4SAndroid Build Coastguard Worker return result;
2177*6236dae4SAndroid Build Coastguard Worker }
2178*6236dae4SAndroid Build Coastguard Worker
Curl_ssl_cf_is_proxy(struct Curl_cfilter * cf)2179*6236dae4SAndroid Build Coastguard Worker bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
2180*6236dae4SAndroid Build Coastguard Worker {
2181*6236dae4SAndroid Build Coastguard Worker return (cf->cft->flags & CF_TYPE_SSL) && (cf->cft->flags & CF_TYPE_PROXY);
2182*6236dae4SAndroid Build Coastguard Worker }
2183*6236dae4SAndroid Build Coastguard Worker
2184*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *
Curl_ssl_cf_get_config(struct Curl_cfilter * cf,struct Curl_easy * data)2185*6236dae4SAndroid Build Coastguard Worker Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
2186*6236dae4SAndroid Build Coastguard Worker {
2187*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_PROXY
2188*6236dae4SAndroid Build Coastguard Worker (void)cf;
2189*6236dae4SAndroid Build Coastguard Worker return &data->set.ssl;
2190*6236dae4SAndroid Build Coastguard Worker #else
2191*6236dae4SAndroid Build Coastguard Worker return Curl_ssl_cf_is_proxy(cf) ? &data->set.proxy_ssl : &data->set.ssl;
2192*6236dae4SAndroid Build Coastguard Worker #endif
2193*6236dae4SAndroid Build Coastguard Worker }
2194*6236dae4SAndroid Build Coastguard Worker
2195*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *
Curl_ssl_cf_get_primary_config(struct Curl_cfilter * cf)2196*6236dae4SAndroid Build Coastguard Worker Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
2197*6236dae4SAndroid Build Coastguard Worker {
2198*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_PROXY
2199*6236dae4SAndroid Build Coastguard Worker return &cf->conn->ssl_config;
2200*6236dae4SAndroid Build Coastguard Worker #else
2201*6236dae4SAndroid Build Coastguard Worker return Curl_ssl_cf_is_proxy(cf) ?
2202*6236dae4SAndroid Build Coastguard Worker &cf->conn->proxy_ssl_config : &cf->conn->ssl_config;
2203*6236dae4SAndroid Build Coastguard Worker #endif
2204*6236dae4SAndroid Build Coastguard Worker }
2205*6236dae4SAndroid Build Coastguard Worker
Curl_alpn_to_proto_buf(struct alpn_proto_buf * buf,const struct alpn_spec * spec)2206*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
2207*6236dae4SAndroid Build Coastguard Worker const struct alpn_spec *spec)
2208*6236dae4SAndroid Build Coastguard Worker {
2209*6236dae4SAndroid Build Coastguard Worker size_t i, len;
2210*6236dae4SAndroid Build Coastguard Worker int off = 0;
2211*6236dae4SAndroid Build Coastguard Worker unsigned char blen;
2212*6236dae4SAndroid Build Coastguard Worker
2213*6236dae4SAndroid Build Coastguard Worker memset(buf, 0, sizeof(*buf));
2214*6236dae4SAndroid Build Coastguard Worker for(i = 0; spec && i < spec->count; ++i) {
2215*6236dae4SAndroid Build Coastguard Worker len = strlen(spec->entries[i]);
2216*6236dae4SAndroid Build Coastguard Worker if(len >= ALPN_NAME_MAX)
2217*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
2218*6236dae4SAndroid Build Coastguard Worker blen = (unsigned char)len;
2219*6236dae4SAndroid Build Coastguard Worker if(off + blen + 1 >= (int)sizeof(buf->data))
2220*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
2221*6236dae4SAndroid Build Coastguard Worker buf->data[off++] = blen;
2222*6236dae4SAndroid Build Coastguard Worker memcpy(buf->data + off, spec->entries[i], blen);
2223*6236dae4SAndroid Build Coastguard Worker off += blen;
2224*6236dae4SAndroid Build Coastguard Worker }
2225*6236dae4SAndroid Build Coastguard Worker buf->len = off;
2226*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2227*6236dae4SAndroid Build Coastguard Worker }
2228*6236dae4SAndroid Build Coastguard Worker
Curl_alpn_to_proto_str(struct alpn_proto_buf * buf,const struct alpn_spec * spec)2229*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
2230*6236dae4SAndroid Build Coastguard Worker const struct alpn_spec *spec)
2231*6236dae4SAndroid Build Coastguard Worker {
2232*6236dae4SAndroid Build Coastguard Worker size_t i, len;
2233*6236dae4SAndroid Build Coastguard Worker size_t off = 0;
2234*6236dae4SAndroid Build Coastguard Worker
2235*6236dae4SAndroid Build Coastguard Worker memset(buf, 0, sizeof(*buf));
2236*6236dae4SAndroid Build Coastguard Worker for(i = 0; spec && i < spec->count; ++i) {
2237*6236dae4SAndroid Build Coastguard Worker len = strlen(spec->entries[i]);
2238*6236dae4SAndroid Build Coastguard Worker if(len >= ALPN_NAME_MAX)
2239*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
2240*6236dae4SAndroid Build Coastguard Worker if(off + len + 2 >= sizeof(buf->data))
2241*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
2242*6236dae4SAndroid Build Coastguard Worker if(off)
2243*6236dae4SAndroid Build Coastguard Worker buf->data[off++] = ',';
2244*6236dae4SAndroid Build Coastguard Worker memcpy(buf->data + off, spec->entries[i], len);
2245*6236dae4SAndroid Build Coastguard Worker off += len;
2246*6236dae4SAndroid Build Coastguard Worker }
2247*6236dae4SAndroid Build Coastguard Worker buf->data[off] = '\0';
2248*6236dae4SAndroid Build Coastguard Worker buf->len = (int)off;
2249*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2250*6236dae4SAndroid Build Coastguard Worker }
2251*6236dae4SAndroid Build Coastguard Worker
Curl_alpn_contains_proto(const struct alpn_spec * spec,const char * proto)2252*6236dae4SAndroid Build Coastguard Worker bool Curl_alpn_contains_proto(const struct alpn_spec *spec,
2253*6236dae4SAndroid Build Coastguard Worker const char *proto)
2254*6236dae4SAndroid Build Coastguard Worker {
2255*6236dae4SAndroid Build Coastguard Worker size_t i, plen = proto ? strlen(proto) : 0;
2256*6236dae4SAndroid Build Coastguard Worker for(i = 0; spec && plen && i < spec->count; ++i) {
2257*6236dae4SAndroid Build Coastguard Worker size_t slen = strlen(spec->entries[i]);
2258*6236dae4SAndroid Build Coastguard Worker if((slen == plen) && !memcmp(proto, spec->entries[i], plen))
2259*6236dae4SAndroid Build Coastguard Worker return TRUE;
2260*6236dae4SAndroid Build Coastguard Worker }
2261*6236dae4SAndroid Build Coastguard Worker return FALSE;
2262*6236dae4SAndroid Build Coastguard Worker }
2263*6236dae4SAndroid Build Coastguard Worker
Curl_alpn_set_negotiated(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_connect_data * connssl,const unsigned char * proto,size_t proto_len)2264*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
2265*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2266*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl,
2267*6236dae4SAndroid Build Coastguard Worker const unsigned char *proto,
2268*6236dae4SAndroid Build Coastguard Worker size_t proto_len)
2269*6236dae4SAndroid Build Coastguard Worker {
2270*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2271*6236dae4SAndroid Build Coastguard Worker unsigned char *palpn =
2272*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2273*6236dae4SAndroid Build Coastguard Worker (cf->conn->bits.tunnel_proxy && Curl_ssl_cf_is_proxy(cf)) ?
2274*6236dae4SAndroid Build Coastguard Worker &cf->conn->proxy_alpn : &cf->conn->alpn
2275*6236dae4SAndroid Build Coastguard Worker #else
2276*6236dae4SAndroid Build Coastguard Worker &cf->conn->alpn
2277*6236dae4SAndroid Build Coastguard Worker #endif
2278*6236dae4SAndroid Build Coastguard Worker ;
2279*6236dae4SAndroid Build Coastguard Worker
2280*6236dae4SAndroid Build Coastguard Worker if(connssl->alpn_negotiated) {
2281*6236dae4SAndroid Build Coastguard Worker /* When we ask for a specific ALPN protocol, we need the confirmation
2282*6236dae4SAndroid Build Coastguard Worker * of it by the server, as we have installed protocol handler and
2283*6236dae4SAndroid Build Coastguard Worker * connection filter chain for exactly this protocol. */
2284*6236dae4SAndroid Build Coastguard Worker if(!proto_len) {
2285*6236dae4SAndroid Build Coastguard Worker failf(data, "ALPN: asked for '%s' from previous session, "
2286*6236dae4SAndroid Build Coastguard Worker "but server did not confirm it. Refusing to continue.",
2287*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated);
2288*6236dae4SAndroid Build Coastguard Worker result = CURLE_SSL_CONNECT_ERROR;
2289*6236dae4SAndroid Build Coastguard Worker goto out;
2290*6236dae4SAndroid Build Coastguard Worker }
2291*6236dae4SAndroid Build Coastguard Worker else if((strlen(connssl->alpn_negotiated) != proto_len) ||
2292*6236dae4SAndroid Build Coastguard Worker memcmp(connssl->alpn_negotiated, proto, proto_len)) {
2293*6236dae4SAndroid Build Coastguard Worker failf(data, "ALPN: asked for '%s' from previous session, but server "
2294*6236dae4SAndroid Build Coastguard Worker "selected '%.*s'. Refusing to continue.",
2295*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated, (int)proto_len, proto);
2296*6236dae4SAndroid Build Coastguard Worker result = CURLE_SSL_CONNECT_ERROR;
2297*6236dae4SAndroid Build Coastguard Worker goto out;
2298*6236dae4SAndroid Build Coastguard Worker }
2299*6236dae4SAndroid Build Coastguard Worker /* ALPN is exactly what we asked for, done. */
2300*6236dae4SAndroid Build Coastguard Worker infof(data, "ALPN: server confirmed to use '%s'",
2301*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated);
2302*6236dae4SAndroid Build Coastguard Worker goto out;
2303*6236dae4SAndroid Build Coastguard Worker }
2304*6236dae4SAndroid Build Coastguard Worker
2305*6236dae4SAndroid Build Coastguard Worker if(proto && proto_len) {
2306*6236dae4SAndroid Build Coastguard Worker if(memchr(proto, '\0', proto_len)) {
2307*6236dae4SAndroid Build Coastguard Worker failf(data, "ALPN: server selected protocol contains NUL. "
2308*6236dae4SAndroid Build Coastguard Worker "Refusing to continue.");
2309*6236dae4SAndroid Build Coastguard Worker result = CURLE_SSL_CONNECT_ERROR;
2310*6236dae4SAndroid Build Coastguard Worker goto out;
2311*6236dae4SAndroid Build Coastguard Worker }
2312*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated = malloc(proto_len + 1);
2313*6236dae4SAndroid Build Coastguard Worker if(!connssl->alpn_negotiated)
2314*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
2315*6236dae4SAndroid Build Coastguard Worker memcpy(connssl->alpn_negotiated, proto, proto_len);
2316*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated[proto_len] = 0;
2317*6236dae4SAndroid Build Coastguard Worker }
2318*6236dae4SAndroid Build Coastguard Worker
2319*6236dae4SAndroid Build Coastguard Worker if(proto && proto_len) {
2320*6236dae4SAndroid Build Coastguard Worker if(proto_len == ALPN_HTTP_1_1_LENGTH &&
2321*6236dae4SAndroid Build Coastguard Worker !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
2322*6236dae4SAndroid Build Coastguard Worker *palpn = CURL_HTTP_VERSION_1_1;
2323*6236dae4SAndroid Build Coastguard Worker }
2324*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP2
2325*6236dae4SAndroid Build Coastguard Worker else if(proto_len == ALPN_H2_LENGTH &&
2326*6236dae4SAndroid Build Coastguard Worker !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
2327*6236dae4SAndroid Build Coastguard Worker *palpn = CURL_HTTP_VERSION_2;
2328*6236dae4SAndroid Build Coastguard Worker }
2329*6236dae4SAndroid Build Coastguard Worker #endif
2330*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP3
2331*6236dae4SAndroid Build Coastguard Worker else if(proto_len == ALPN_H3_LENGTH &&
2332*6236dae4SAndroid Build Coastguard Worker !memcmp(ALPN_H3, proto, ALPN_H3_LENGTH)) {
2333*6236dae4SAndroid Build Coastguard Worker *palpn = CURL_HTTP_VERSION_3;
2334*6236dae4SAndroid Build Coastguard Worker }
2335*6236dae4SAndroid Build Coastguard Worker #endif
2336*6236dae4SAndroid Build Coastguard Worker else {
2337*6236dae4SAndroid Build Coastguard Worker *palpn = CURL_HTTP_VERSION_NONE;
2338*6236dae4SAndroid Build Coastguard Worker failf(data, "unsupported ALPN protocol: '%.*s'", (int)proto_len, proto);
2339*6236dae4SAndroid Build Coastguard Worker /* TODO: do we want to fail this? Previous code just ignored it and
2340*6236dae4SAndroid Build Coastguard Worker * some vtls backends even ignore the return code of this function. */
2341*6236dae4SAndroid Build Coastguard Worker /* return CURLE_NOT_BUILT_IN; */
2342*6236dae4SAndroid Build Coastguard Worker goto out;
2343*6236dae4SAndroid Build Coastguard Worker }
2344*6236dae4SAndroid Build Coastguard Worker
2345*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_deferred)
2346*6236dae4SAndroid Build Coastguard Worker infof(data, VTLS_INFOF_ALPN_DEFERRED, (int)proto_len, proto);
2347*6236dae4SAndroid Build Coastguard Worker else
2348*6236dae4SAndroid Build Coastguard Worker infof(data, VTLS_INFOF_ALPN_ACCEPTED, (int)proto_len, proto);
2349*6236dae4SAndroid Build Coastguard Worker }
2350*6236dae4SAndroid Build Coastguard Worker else {
2351*6236dae4SAndroid Build Coastguard Worker *palpn = CURL_HTTP_VERSION_NONE;
2352*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_deferred)
2353*6236dae4SAndroid Build Coastguard Worker infof(data, VTLS_INFOF_NO_ALPN_DEFERRED);
2354*6236dae4SAndroid Build Coastguard Worker else
2355*6236dae4SAndroid Build Coastguard Worker infof(data, VTLS_INFOF_NO_ALPN);
2356*6236dae4SAndroid Build Coastguard Worker }
2357*6236dae4SAndroid Build Coastguard Worker
2358*6236dae4SAndroid Build Coastguard Worker out:
2359*6236dae4SAndroid Build Coastguard Worker return result;
2360*6236dae4SAndroid Build Coastguard Worker }
2361*6236dae4SAndroid Build Coastguard Worker
2362*6236dae4SAndroid Build Coastguard Worker #endif /* USE_SSL */
2363