xref: /aosp_15_r20/external/curl/lib/vtls/vtls.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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