From fbc607a48b1fb4ae65c9f2691c44453f02aef2b8 Mon Sep 17 00:00:00 2001 From: "Gunnar \"Nick\" Bluth" Date: Thu, 8 Jan 2026 03:17:17 +0100 Subject: [PATCH] Allow configuration of TLS cipher suites. Configuration of specific cipher suites may be required for compliance or to use preferred ciphers for security. Cipher suites are applied to the entire process and cannot be configured on a per-connection basis, except that for object store clients (e.g. S3) verification can be disabled. --- doc/xml/release/2020s/2026/2.58.0.xml | 12 +++ src/build/config/config.yaml | 10 ++ src/build/help/help.xml | 29 ++++++ src/common/io/tls/common.c | 48 +++++++++ src/common/io/tls/common.h | 3 + src/config/config.auto.h | 6 +- src/config/load.c | 8 ++ src/config/parse.auto.c.inc | 138 ++++++++++++++++++++++++++ test/define.yaml | 1 + test/src/module/command/helpTest.c | 2 + test/src/module/common/ioTlsTest.c | 58 +++++++++++ test/src/module/config/loadTest.c | 19 +++- 12 files changed, 332 insertions(+), 2 deletions(-) diff --git a/doc/xml/release/2020s/2026/2.58.0.xml b/doc/xml/release/2020s/2026/2.58.0.xml index 789d6d363..7a9dc1105 100644 --- a/doc/xml/release/2020s/2026/2.58.0.xml +++ b/doc/xml/release/2020s/2026/2.58.0.xml @@ -57,6 +57,18 @@

Support for Azure managed identities.

+ + + + + + + + + +

Allow configuration of TLS cipher suites.

+
+ diff --git a/src/build/config/config.yaml b/src/build/config/config.yaml index 703c9c35d..857c725d8 100644 --- a/src/build/config/config.yaml +++ b/src/build/config/config.yaml @@ -952,6 +952,16 @@ option: command: buffer-size depend: tcp-keep-alive-count + # TLS allowed ciphers + tls-cipher-12: + section: global + type: string + required: false + command: buffer-size + + tls-cipher-13: + inherit: tls-cipher-12 + # Logging options #--------------------------------------------------------------------------------------------------------------------------------- log-level-console: diff --git a/src/build/help/help.xml b/src/build/help/help.xml index a4186e28a..3cb00596b 100644 --- a/src/build/help/help.xml +++ b/src/build/help/help.xml @@ -430,6 +430,35 @@ 30 + + + Allowed TLSv1.2 cipher suites. + + +

All TLS connections between the client and server are encrypted. By default, connections to objects stores (e.g. S3) are also encrypted.

+ + The absolute minimum security level for any transport connection is TLSv1.2. + +

The accepted cipher suites can be adjusted if need arises. The example is reasonable choice unless you have specific security requirements. If unset (the default), the default of the underlying OpenSSL library applies.

+
+ + HIGH:MEDIUM:+3DES:!aNULL +
+ + + Allowed TLSv1.3 cipher suites. + + +

All TLS connections between the client and server are encrypted. By default, connections to objects stores (e.g. S3) are also encrypted.

+ + The absolute minimum security level for any transport connection is TLSv1.2. + +

The accepted cipher suites can be adjusted if need arises. If unset (the default), the default of the underlying OpenSSL library applies.

+
+ + TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 +
+ diff --git a/src/common/io/tls/common.c b/src/common/io/tls/common.c index 7770ab259..d1806b418 100644 --- a/src/common/io/tls/common.c +++ b/src/common/io/tls/common.c @@ -14,6 +14,17 @@ TLS Common #include "common/user.h" #include "storage/posix/storage.h" +/*********************************************************************************************************************************** +Local variables +***********************************************************************************************************************************/ +static struct TlsCommonLocal +{ + MemContext *memContext; // Mem context for TLS common + + String *tlsCipher12; // Allowed ciphers for TLSv1.2 + String *tlsCipher13; // Allowed ciphers for TLSv1.3 +} tlsCommonLocal; + /**********************************************************************************************************************************/ FN_EXTERN Buffer * tlsAsn1ToBuf(const ASN1_STRING *const nameAsn1) @@ -172,6 +183,35 @@ tlsCertKeyLoad(SSL_CTX *const context, const String *const certFile, const Strin FUNCTION_TEST_RETURN_VOID(); } +/**********************************************************************************************************************************/ +FN_EXTERN void +tlsInit(const String *const tlsCipher12, const String *const tlsCipher13) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(STRING, tlsCipher12); + FUNCTION_TEST_PARAM(STRING, tlsCipher13); + FUNCTION_TEST_END(); + + // Free old mem context (if any) + if (tlsCommonLocal.memContext != NULL) + memContextFree(tlsCommonLocal.memContext); + + // Initialize mem context + MEM_CONTEXT_BEGIN(memContextTop()) + { + MEM_CONTEXT_NEW_BEGIN(TlsCommon, .childQty = MEM_CONTEXT_QTY_MAX) + { + tlsCommonLocal.memContext = MEM_CONTEXT_NEW(); + tlsCommonLocal.tlsCipher12 = strDup(tlsCipher12); + tlsCommonLocal.tlsCipher13 = strDup(tlsCipher13); + } + MEM_CONTEXT_NEW_END(); + } + MEM_CONTEXT_END(); + + FUNCTION_TEST_RETURN_VOID(); +} + /**********************************************************************************************************************************/ FN_EXTERN SSL_CTX * tlsContext(const bool verifyPeer) @@ -200,6 +240,14 @@ tlsContext(const bool verifyPeer) { // Set minimum TLS version to 1.2 cryptoError(SSL_CTX_set_min_proto_version(result, TLS1_2_VERSION) != 1, "unable to set minumum TLS version to 1.2"); + + // Set allowed ciphers for TLSv1.2 when configured + if (tlsCommonLocal.tlsCipher12 != NULL) + cryptoError(SSL_CTX_set_cipher_list(result, strZ(tlsCommonLocal.tlsCipher12)) != 1, "unable to set TLSv1.2 ciphers"); + + // Set allowed ciphers for TLSv1.3 when configured + if (tlsCommonLocal.tlsCipher13 != NULL) + cryptoError(SSL_CTX_set_ciphersuites(result, strZ(tlsCommonLocal.tlsCipher13)) != 1, "unable to set TLSv1.3 ciphers"); } FUNCTION_TEST_RETURN_TYPE_P(SSL_CTX, result); diff --git a/src/common/io/tls/common.h b/src/common/io/tls/common.h index 63c6f33f3..09762a223 100644 --- a/src/common/io/tls/common.h +++ b/src/common/io/tls/common.h @@ -11,6 +11,9 @@ TLS Common /*********************************************************************************************************************************** Functions ***********************************************************************************************************************************/ +// Initialize TLS with allowed ciphers +FN_EXTERN void tlsInit(const String *tlsCipher12, const String *tlsCipher13); + // Convert an ASN1 string used in certificates to a Buffer FN_EXTERN Buffer *tlsAsn1ToBuf(const ASN1_STRING *nameAsn1); diff --git a/src/config/config.auto.h b/src/config/config.auto.h index 49deabe33..6a7c3f181 100644 --- a/src/config/config.auto.h +++ b/src/config/config.auto.h @@ -132,6 +132,8 @@ Option constants #define CFGOPT_TCP_KEEP_ALIVE_COUNT "tcp-keep-alive-count" #define CFGOPT_TCP_KEEP_ALIVE_IDLE "tcp-keep-alive-idle" #define CFGOPT_TCP_KEEP_ALIVE_INTERVAL "tcp-keep-alive-interval" +#define CFGOPT_TLS_CIPHER_12 "tls-cipher-12" +#define CFGOPT_TLS_CIPHER_13 "tls-cipher-13" #define CFGOPT_TLS_SERVER_ADDRESS "tls-server-address" #define CFGOPT_TLS_SERVER_AUTH "tls-server-auth" #define CFGOPT_TLS_SERVER_CA_FILE "tls-server-ca-file" @@ -142,7 +144,7 @@ Option constants #define CFGOPT_VERBOSE "verbose" #define CFGOPT_VERSION "version" -#define CFG_OPTION_TOTAL 190 +#define CFG_OPTION_TOTAL 192 /*********************************************************************************************************************************** Option value constants @@ -585,6 +587,8 @@ typedef enum cfgOptTcpKeepAliveCount, cfgOptTcpKeepAliveIdle, cfgOptTcpKeepAliveInterval, + cfgOptTlsCipher12, + cfgOptTlsCipher13, cfgOptTlsServerAddress, cfgOptTlsServerAuth, cfgOptTlsServerCaFile, diff --git a/src/config/load.c b/src/config/load.c index 52a152b76..f8d0176ed 100644 --- a/src/config/load.c +++ b/src/config/load.c @@ -14,6 +14,7 @@ Configuration Load #include "common/debug.h" #include "common/io/io.h" #include "common/io/socket/common.h" +#include "common/io/tls/common.h" #include "common/log.h" #include "common/memContext.h" #include "config/config.intern.h" @@ -492,6 +493,13 @@ cfgLoad(const unsigned int argListSize, const char *argList[]) cfgOptionTest(cfgOptTcpKeepAliveInterval) ? cfgOptionInt(cfgOptTcpKeepAliveInterval) : 0); } + // Initialize TLS settings + if (cfgOptionValid(cfgOptTlsCipher12)) + { + ASSERT(cfgOptionValid(cfgOptTlsCipher13)); + tlsInit(cfgOptionStrNull(cfgOptTlsCipher12), cfgOptionStrNull(cfgOptTlsCipher13)); + } + // Set IO buffer size (use the default for help to lower memory usage) if (cfgOptionValid(cfgOptBufferSize) && !cfgCommandHelp()) ioBufferSizeSet(cfgOptionUInt(cfgOptBufferSize)); diff --git a/src/config/parse.auto.c.inc b/src/config/parse.auto.c.inc index b486988c1..0ff01c5e0 100644 --- a/src/config/parse.auto.c.inc +++ b/src/config/parse.auto.c.inc @@ -11138,6 +11138,142 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ), // opt/tcp-keep-alive-interval ), // opt/tcp-keep-alive-interval // ----------------------------------------------------------------------------------------------------------------------------- + PARSE_RULE_OPTION // opt/tls-cipher-12 + ( // opt/tls-cipher-12 + PARSE_RULE_OPTION_NAME("tls-cipher-12"), // opt/tls-cipher-12 + PARSE_RULE_OPTION_TYPE(String), // opt/tls-cipher-12 + PARSE_RULE_OPTION_RESET(true), // opt/tls-cipher-12 + PARSE_RULE_OPTION_REQUIRED(false), // opt/tls-cipher-12 + PARSE_RULE_OPTION_SECTION(Global), // opt/tls-cipher-12 + // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/tls-cipher-12 + ( // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Annotate) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Check) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Expire) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Info) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Manifest) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Server) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ServerPing) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaDelete) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-12 + ), // opt/tls-cipher-12 + // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/tls-cipher-12 + ( // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-12 + ), // opt/tls-cipher-12 + // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/tls-cipher-12 + ( // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-12 + ), // opt/tls-cipher-12 + // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND_ROLE_REMOTE_VALID_LIST // opt/tls-cipher-12 + ( // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Annotate) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Check) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Expire) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Info) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Manifest) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaDelete) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/tls-cipher-12 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-12 + ), // opt/tls-cipher-12 + ), // opt/tls-cipher-12 + // ----------------------------------------------------------------------------------------------------------------------------- + PARSE_RULE_OPTION // opt/tls-cipher-13 + ( // opt/tls-cipher-13 + PARSE_RULE_OPTION_NAME("tls-cipher-13"), // opt/tls-cipher-13 + PARSE_RULE_OPTION_TYPE(String), // opt/tls-cipher-13 + PARSE_RULE_OPTION_RESET(true), // opt/tls-cipher-13 + PARSE_RULE_OPTION_REQUIRED(false), // opt/tls-cipher-13 + PARSE_RULE_OPTION_SECTION(Global), // opt/tls-cipher-13 + // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/tls-cipher-13 + ( // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Annotate) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Check) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Expire) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Info) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Manifest) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Server) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ServerPing) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaDelete) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-13 + ), // opt/tls-cipher-13 + // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/tls-cipher-13 + ( // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-13 + ), // opt/tls-cipher-13 + // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/tls-cipher-13 + ( // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-13 + ), // opt/tls-cipher-13 + // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND_ROLE_REMOTE_VALID_LIST // opt/tls-cipher-13 + ( // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Annotate) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Backup) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Check) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Expire) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Info) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Manifest) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Restore) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaDelete) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/tls-cipher-13 + PARSE_RULE_OPTION_COMMAND(Verify) // opt/tls-cipher-13 + ), // opt/tls-cipher-13 + ), // opt/tls-cipher-13 + // ----------------------------------------------------------------------------------------------------------------------------- PARSE_RULE_OPTION // opt/tls-server-address ( // opt/tls-server-address PARSE_RULE_OPTION_NAME("tls-server-address"), // opt/tls-server-address @@ -11741,6 +11877,8 @@ static const uint8_t optionResolveOrder[] = cfgOptTcpKeepAliveCount, // opt-resolve-order cfgOptTcpKeepAliveIdle, // opt-resolve-order cfgOptTcpKeepAliveInterval, // opt-resolve-order + cfgOptTlsCipher12, // opt-resolve-order + cfgOptTlsCipher13, // opt-resolve-order cfgOptTlsServerAddress, // opt-resolve-order cfgOptTlsServerAuth, // opt-resolve-order cfgOptTlsServerCaFile, // opt-resolve-order diff --git a/test/define.yaml b/test/define.yaml index 6cdcb1f6e..6dcbed3bf 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -530,6 +530,7 @@ unit: include: - common/io/socket/common + - common/io/tls/common # ---------------------------------------------------------------------------------------------------------------------------- - name: exec diff --git a/test/src/module/command/helpTest.c b/test/src/module/command/helpTest.c index decdd2336..8d4d0434f 100644 --- a/test/src/module/command/helpTest.c +++ b/test/src/module/command/helpTest.c @@ -278,6 +278,8 @@ testRun(void) " --tcp-keep-alive-count keep-alive count\n" " --tcp-keep-alive-idle keep-alive idle time\n" " --tcp-keep-alive-interval keep-alive interval time\n" + " --tls-cipher-12 allowed TLSv1.2 cipher suites\n" + " --tls-cipher-13 allowed TLSv1.3 cipher suites\n" "\n" "Log Options:\n" "\n" diff --git a/test/src/module/common/ioTlsTest.c b/test/src/module/common/ioTlsTest.c index 252847b5e..2a3f68404 100644 --- a/test/src/module/common/ioTlsTest.c +++ b/test/src/module/common/ioTlsTest.c @@ -917,6 +917,64 @@ testRun(void) } HRN_FORK_END(); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("fail on mismatch between allowed TLS cipher suites"); + + HRN_FORK_BEGIN() + { + const unsigned int testPort = hrnServerPortNext(); + + HRN_FORK_CHILD_BEGIN(.prefix = "test server", .timeout = 5000) + { + TEST_RESULT_VOID(tlsInit(STRDEF("eNULL"), STRDEF("TLS_AES_256_GCM_SHA384")), "disallow TLS 1.2"); + + // Start server to test various certificate errors + TEST_ERROR_MULTI( + hrnServerRunP( + HRN_FORK_CHILD_READ(), hrnServerProtocolTls, testPort, .certificate = STRDEF(HRN_SERVER_CERT), + .key = STRDEF(HRN_SERVER_KEY), .address = STRDEF("::1")), + ServiceError, + // TLS >= 3 + "TLS error [1:167772353] no shared cipher", + // TLS < 3 + "TLS error [1:337678529] no shared cipher"); + } + HRN_FORK_CHILD_END(); + + HRN_FORK_PARENT_BEGIN(.prefix = "test client", .timeout = 1000) + { + IoWrite *const tls = hrnServerScriptBegin(HRN_FORK_PARENT_WRITE(0)); + + // ----------------------------------------------------------------------------------------------------------------- + TEST_TITLE("cipher suite mismatch"); + + hrnServerScriptAccept(tls); + hrnServerScriptClose(tls); + + TEST_RESULT_VOID(tlsInit(STRDEF("COMPLEMENTOFALL"), STRDEF("TLS_AES_128_GCM_SHA256")), "disallow TLS 1.3"); + + TEST_ERROR_MULTI( + ioClientOpen( + tlsClientNewP( + sckClientNew(STRDEF("::1"), testPort, 5000, 5000), STRDEF("::1"), 0, 0, true, + .caFile = STRDEF(HRN_SERVER_CA))), + ServiceError, + // TLS >= 3 + "TLS error [1:167773200] sslv3 alert handshake failure", + // TLS < 3 + "TLS error [1:336151568] sslv3 alert handshake failure", + // TLS >= 3 Fedora/Alpine + "TLS error [1:167773200] ssl/tls alert handshake failure"); + + // ----------------------------------------------------------------------------------------------------------------- + hrnServerScriptEnd(tls); + } + HRN_FORK_PARENT_END(); + } + HRN_FORK_END(); + + TEST_RESULT_VOID(tlsInit(NULL, NULL), "init null tls ciphers"); + // Server on IPv6 // ------------------------------------------------------------------------------------------------------------------------- HRN_FORK_BEGIN() diff --git a/test/src/module/config/loadTest.c b/test/src/module/config/loadTest.c index c864100b9..109e71aed 100644 --- a/test/src/module/config/loadTest.c +++ b/test/src/module/config/loadTest.c @@ -731,12 +731,29 @@ testRun(void) if (testBegin("cfgLoad()")) { // ------------------------------------------------------------------------------------------------------------------------- - TEST_TITLE("dry-run valid, --no-dry-run"); + TEST_TITLE("TLS cipher suites"); StringList *argList = strLstNew(); strLstAddZ(argList, PROJECT_BIN); hrnCfgArgRawZ(argList, cfgOptStanza, "db"); hrnCfgArgRawZ(argList, cfgOptLockPath, HRN_PATH "/lock"); + hrnCfgArgRawZ(argList, cfgOptTlsCipher12, "HIGH:MEDIUM:+3DES:!aNULL"); + hrnCfgArgRawZ(argList, cfgOptTlsCipher13, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"); + strLstAddZ(argList, CFGCMD_EXPIRE); + + TEST_RESULT_VOID(cfgLoad(strLstSize(argList), strLstPtr(argList)), "load config"); + TEST_RESULT_STR_Z(tlsCommonLocal.tlsCipher12, "HIGH:MEDIUM:+3DES:!aNULL", "check tls1.2 cipher suites"); + TEST_RESULT_STR_Z( + tlsCommonLocal.tlsCipher13, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256", "check tls1.3 cipher suites"); + cmdLockReleaseP(); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("dry-run valid, --no-dry-run"); + + argList = strLstNew(); + strLstAddZ(argList, PROJECT_BIN); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); + hrnCfgArgRawZ(argList, cfgOptLockPath, HRN_PATH "/lock"); hrnCfgArgRawZ(argList, cfgOptLogLevelStderr, CFGOPTVAL_ARCHIVE_MODE_OFF_Z); strLstAddZ(argList, CFGCMD_EXPIRE);