diff options
Diffstat (limited to 'ssl/ssl_conf.c')
-rw-r--r-- | ssl/ssl_conf.c | 178 |
1 files changed, 138 insertions, 40 deletions
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 698280288e9d..946d20be527c 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2012-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,6 +7,8 @@ * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" + #include <stdio.h> #include "ssl_local.h" #include <openssl/conf.h> @@ -14,6 +16,7 @@ #include <openssl/decoder.h> #include <openssl/core_dispatch.h> #include "internal/nelem.h" +#include "internal/ssl_unwrap.h" /* * structure holding name tables. This is used for permitted elements in lists @@ -86,7 +89,9 @@ struct ssl_conf_ctx_st { /* Pointer to SSL or SSL_CTX options field or NULL if none */ uint64_t *poptions; /* Certificate filenames for each type */ - char *cert_filename[SSL_PKEY_NUM]; + char **cert_filename; + /* Number of elements in the cert_filename array */ + size_t num_cert_filename; /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ uint32_t *pcert_flags; /* Pointer to SSL or SSL_CTX verify_mode or NULL if none */ @@ -241,7 +246,7 @@ static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) return 1; /* ECDHParameters accepts a single group name */ - if (strstr(value, ":") != NULL) + if (strchr(value, ':') != NULL) return 0; if (cctx->ctx) @@ -337,7 +342,7 @@ static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound) if (cctx->ctx != NULL) method_version = cctx->ctx->method->version; else if (cctx->ssl != NULL) - method_version = cctx->ssl->ctx->method->version; + method_version = cctx->ssl->defltmeth->version; else return 0; if ((new_version = protocol_from_string(value)) < 0) @@ -391,12 +396,18 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC), SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION), SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX), + SSL_FLAG_TBL("PreferNoDHEKEX", SSL_OP_PREFER_NO_DHE_KEX), SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA), SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT), SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY), SSL_FLAG_TBL_INV("ExtendedMasterSecret", SSL_OP_NO_EXTENDED_MASTER_SECRET), SSL_FLAG_TBL_INV("CANames", SSL_OP_DISABLE_TLSEXT_CA_NAMES), - SSL_FLAG_TBL("KTLS", SSL_OP_ENABLE_KTLS) + SSL_FLAG_TBL("KTLS", SSL_OP_ENABLE_KTLS), + SSL_FLAG_TBL_CERT("StrictCertCheck", SSL_CERT_FLAG_TLS_STRICT), + SSL_FLAG_TBL_INV("TxCertificateCompression", SSL_OP_NO_TX_CERTIFICATE_COMPRESSION), + SSL_FLAG_TBL_INV("RxCertificateCompression", SSL_OP_NO_RX_CERTIFICATE_COMPRESSION), + SSL_FLAG_TBL("KTLSTxZerocopySendfile", SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE), + SSL_FLAG_TBL("IgnoreUnexpectedEOF", SSL_OP_IGNORE_UNEXPECTED_EOF), }; if (value == NULL) return -3; @@ -430,20 +441,33 @@ static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) { int rv = 1; CERT *c = NULL; - if (cctx->ctx) { + if (cctx->ctx != NULL) { rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); c = cctx->ctx->cert; } - if (cctx->ssl) { - rv = SSL_use_certificate_chain_file(cctx->ssl, value); - c = cctx->ssl->cert; + if (cctx->ssl != NULL) { + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); + + if (sc != NULL) { + rv = SSL_use_certificate_chain_file(cctx->ssl, value); + c = sc->cert; + } else { + rv = 0; + } } - if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { - char **pfilename = &cctx->cert_filename[c->key - c->pkeys]; - OPENSSL_free(*pfilename); - *pfilename = OPENSSL_strdup(value); - if (*pfilename == NULL) + if (rv > 0 && c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { + size_t fileidx = c->key - c->pkeys; + + if (fileidx >= cctx->num_cert_filename) { rv = 0; + } else { + char **pfilename = &cctx->cert_filename[c->key - c->pkeys]; + + OPENSSL_free(*pfilename); + *pfilename = OPENSSL_strdup(value); + if (*pfilename == NULL) + rv = 0; + } } return rv > 0; @@ -483,7 +507,12 @@ static int do_store(SSL_CONF_CTX *cctx, cert = cctx->ctx->cert; ctx = cctx->ctx; } else if (cctx->ssl != NULL) { - cert = cctx->ssl->cert; + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); + + if (sc == NULL) + return 0; + + cert = sc->cert; ctx = cctx->ssl->ctx; } else { return 1; @@ -631,21 +660,47 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) return rv > 0; } +/* + * |value| input is "<number[,number]>" + * where the first number is the padding block size for + * application data, and the optional second is the + * padding block size for handshake messages + */ static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value) { int rv = 0; - int block_size = atoi(value); + unsigned long block_padding = 0, hs_padding = 0; + char *commap = NULL, *copy = NULL; + char *endptr = NULL; + + copy = OPENSSL_strdup(value); + if (copy == NULL) + goto out; + commap = strstr(copy, ","); + if (commap != NULL) { + *commap = '\0'; + if (*(commap + 1) == '\0') + goto out; + if (!OPENSSL_strtoul(commap + 1, &endptr, 0, &hs_padding)) + goto out; + } + if (!OPENSSL_strtoul(copy, &endptr, 0, &block_padding)) + goto out; + if (commap == NULL) + hs_padding = block_padding; /* - * All we care about is a non-negative value, + * All we care about are non-negative values, * the setters check the range */ - if (block_size >= 0) { - if (cctx->ctx) - rv = SSL_CTX_set_block_padding(cctx->ctx, block_size); - if (cctx->ssl) - rv = SSL_set_block_padding(cctx->ssl, block_size); - } + if (cctx->ctx) + rv = SSL_CTX_set_block_padding_ex(cctx->ctx, (size_t)block_padding, + (size_t)hs_padding); + if (cctx->ssl) + rv = SSL_set_block_padding_ex(cctx->ssl, (size_t)block_padding, + (size_t)hs_padding); +out: + OPENSSL_free(copy); return rv; } @@ -694,6 +749,10 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_CMD_SWITCH("bugs", 0), SSL_CONF_CMD_SWITCH("no_comp", 0), SSL_CONF_CMD_SWITCH("comp", 0), + SSL_CONF_CMD_SWITCH("no_tx_cert_comp", 0), + SSL_CONF_CMD_SWITCH("tx_cert_comp", 0), + SSL_CONF_CMD_SWITCH("no_rx_cert_comp", 0), + SSL_CONF_CMD_SWITCH("rx_cert_comp", 0), SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("no_ticket", 0), SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER), @@ -704,12 +763,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_CLIENT), SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0), + SSL_CONF_CMD_SWITCH("prefer_no_dhe_kex", 0), SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("strict", 0), SSL_CONF_CMD_SWITCH("no_middlebox", 0), SSL_CONF_CMD_SWITCH("anti_replay", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("no_etm", 0), + SSL_CONF_CMD_SWITCH("no_ems", 0), SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0), SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0), SSL_CONF_CMD_STRING(Curves, "curves", 0), @@ -773,6 +834,10 @@ static const ssl_switch_tbl ssl_cmd_switches[] = { {SSL_OP_ALL, 0}, /* bugs */ {SSL_OP_NO_COMPRESSION, 0}, /* no_comp */ {SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */ + {SSL_OP_NO_TX_CERTIFICATE_COMPRESSION, 0}, /* no_tx_cert_comp */ + {SSL_OP_NO_TX_CERTIFICATE_COMPRESSION, SSL_TFLAG_INV}, /* tx_cert_comp */ + {SSL_OP_NO_RX_CERTIFICATE_COMPRESSION, 0}, /* no_rx_cert_comp */ + {SSL_OP_NO_RX_CERTIFICATE_COMPRESSION, SSL_TFLAG_INV}, /* rx_cert_comp */ {SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */ {SSL_OP_NO_TICKET, 0}, /* no_ticket */ {SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */ @@ -790,6 +855,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = { {SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV}, /* allow_no_dhe_kex */ {SSL_OP_ALLOW_NO_DHE_KEX, 0}, + /* prefer_no_dhe_kex */ + {SSL_OP_PREFER_NO_DHE_KEX, 0}, /* chacha reprioritization */ {SSL_OP_PRIORITIZE_CHACHA, 0}, {SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */ @@ -801,6 +868,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = { {SSL_OP_NO_ANTI_REPLAY, 0}, /* no Encrypt-then-Mac */ {SSL_OP_NO_ENCRYPT_THEN_MAC, 0}, + /* no Extended master secret */ + {SSL_OP_NO_EXTENDED_MASTER_SECRET, 0}, }; static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) @@ -827,7 +896,7 @@ static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) } /* Determine if a command is allowed according to cctx flags */ -static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t) +static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl *t) { unsigned int tfl = t->flags; unsigned int cfl = cctx->flags; @@ -865,7 +934,7 @@ static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, return NULL; } -static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd) +static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl *cmd) { /* Find index of command in table */ size_t idx = cmd - ssl_conf_cmds; @@ -981,17 +1050,23 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) /* See if any certificates are missing private keys */ size_t i; CERT *c = NULL; - if (cctx->ctx) + + if (cctx->ctx != NULL) { c = cctx->ctx->cert; - else if (cctx->ssl) - c = cctx->ssl->cert; - if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { - for (i = 0; i < SSL_PKEY_NUM; i++) { + } else if (cctx->ssl != NULL) { + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); + + if (sc != NULL) + c = sc->cert; + } + if (c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { + for (i = 0; i < cctx->num_cert_filename; i++) { const char *p = cctx->cert_filename[i]; + /* * If missing private key try to load one from certificate file */ - if (p && !c->pkeys[i].privatekey) { + if (p != NULL && c->pkeys[i].privatekey == NULL) { if (!cmd_PrivateKey(cctx, p)) return 0; } @@ -1009,12 +1084,21 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) return 1; } +static void free_cert_filename(SSL_CONF_CTX *cctx) +{ + size_t i; + + for (i = 0; i < cctx->num_cert_filename; i++) + OPENSSL_free(cctx->cert_filename[i]); + OPENSSL_free(cctx->cert_filename); + cctx->cert_filename = NULL; + cctx->num_cert_filename = 0; +} + void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) { if (cctx) { - size_t i; - for (i = 0; i < SSL_PKEY_NUM; i++) - OPENSSL_free(cctx->cert_filename[i]); + free_cert_filename(cctx); OPENSSL_free(cctx->prefix); sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free); OPENSSL_free(cctx); @@ -1054,12 +1138,21 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) { cctx->ssl = ssl; cctx->ctx = NULL; - if (ssl) { - cctx->poptions = &ssl->options; - cctx->min_version = &ssl->min_proto_version; - cctx->max_version = &ssl->max_proto_version; - cctx->pcert_flags = &ssl->cert->cert_flags; - cctx->pvfy_flags = &ssl->verify_mode; + free_cert_filename(cctx); + if (ssl != NULL) { + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl); + + if (sc == NULL) + return; + cctx->poptions = &sc->options; + cctx->min_version = &sc->min_proto_version; + cctx->max_version = &sc->max_proto_version; + cctx->pcert_flags = &sc->cert->cert_flags; + cctx->pvfy_flags = &sc->verify_mode; + cctx->cert_filename = OPENSSL_zalloc(sc->ssl_pkey_num + * sizeof(*cctx->cert_filename)); + if (cctx->cert_filename != NULL) + cctx->num_cert_filename = sc->ssl_pkey_num; } else { cctx->poptions = NULL; cctx->min_version = NULL; @@ -1073,12 +1166,17 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) { cctx->ctx = ctx; cctx->ssl = NULL; + free_cert_filename(cctx); if (ctx) { cctx->poptions = &ctx->options; cctx->min_version = &ctx->min_proto_version; cctx->max_version = &ctx->max_proto_version; cctx->pcert_flags = &ctx->cert->cert_flags; cctx->pvfy_flags = &ctx->verify_mode; + cctx->cert_filename = OPENSSL_zalloc((SSL_PKEY_NUM + ctx->sigalg_list_len) + * sizeof(*cctx->cert_filename)); + if (cctx->cert_filename != NULL) + cctx->num_cert_filename = SSL_PKEY_NUM + ctx->sigalg_list_len; } else { cctx->poptions = NULL; cctx->min_version = NULL; |