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