From 1d936b865caaf00f3949cc52de2fb1f059ae6ac6 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 25 Jun 2024 16:42:01 -0400 Subject: [PATCH 1/2] conf: implement VerifyCAPath/VerifyCAFile commands --- rustls-libssl/src/conf.rs | 60 +++++++++++++++++++++- rustls-libssl/tests/config.c | 98 ++++++++++++++++++++++++++++++------ 2 files changed, 142 insertions(+), 16 deletions(-) diff --git a/rustls-libssl/src/conf.rs b/rustls-libssl/src/conf.rs index f86c433..99cbbb7 100644 --- a/rustls-libssl/src/conf.rs +++ b/rustls-libssl/src/conf.rs @@ -220,6 +220,48 @@ impl SslConfigCtx { } } + fn verify_ca_path(&mut self, path: Option<&str>) -> Result { + let path = match path { + Some(path) => path, + None => return Ok(ActionResult::ValueRequired), + }; + + match &self.state { + State::Validating => Ok(ActionResult::Applied), + State::ApplyingToCtx(ctx) => { + ctx.get_mut().default_cert_dir = Some(path.into()); + Ok(ActionResult::Applied) + } + State::ApplyingToSsl(_) => { + // NYI: would require setting a constructed `RootCertStore` on the `Ssl` instance. + Err(Error::not_supported( + "VerifyCAPath with SSL structure not supported", + )) + } + } + } + + fn verify_ca_file(&mut self, path: Option<&str>) -> Result { + let path = match path { + Some(path) => path, + None => return Ok(ActionResult::ValueRequired), + }; + + match &self.state { + State::Validating => Ok(ActionResult::Applied), + State::ApplyingToCtx(ctx) => { + ctx.get_mut().default_cert_file = Some(path.into()); + Ok(ActionResult::Applied) + } + State::ApplyingToSsl(_) => { + // NYI: would require setting a constructed `RootCertStore` on the `Ssl` instance. + Err(Error::not_supported( + "VerifyCAFile with SSL structure not supported", + )) + } + } + } + fn parse_protocol_version(proto: Option<&str>) -> Option { Some(match proto { Some("None") => 0, @@ -274,8 +316,8 @@ pub(super) enum ValueType { String = 0x1, /// The option value is a filename. File = 0x2, - // The option value is a directory name. - //Dir = 0x3, + /// The option value is a directory name. + Dir = 0x3, // The option value is not used. //None = 0x4, } @@ -460,4 +502,18 @@ const SUPPORTED_COMMANDS: &[Command] = &[ value_type: ValueType::File, action: SslConfigCtx::private_key, }, + Command { + name_file: Some("VerifyCAPath"), + name_cmdline: Some("verifyCApath"), + flags: Flags(Flags::CERTIFICATE), + value_type: ValueType::Dir, + action: SslConfigCtx::verify_ca_path, + }, + Command { + name_file: Some("VerifyCAFile"), + name_cmdline: Some("verifyCAfile"), + flags: Flags(Flags::CERTIFICATE), + value_type: ValueType::File, + action: SslConfigCtx::verify_ca_file, + }, ]; diff --git a/rustls-libssl/tests/config.c b/rustls-libssl/tests/config.c index 637d64a..913ad74 100644 --- a/rustls-libssl/tests/config.c +++ b/rustls-libssl/tests/config.c @@ -14,20 +14,38 @@ static const int conf_flags[] = {SSL_CONF_FLAG_SERVER, SSL_CONF_FLAG_CLIENT, #define NUM_FLAGS (sizeof(conf_flags) / sizeof(conf_flags[0])) -static const char *supported_cmds[] = { - "-min_protocol", CUSTOM_PREFIX "min_protocol", - "MinProtocol", CUSTOM_PREFIX "MinProtocol", - - "-max_protocol", CUSTOM_PREFIX "max_protocol", - "MaxProtocol", CUSTOM_PREFIX "MaxProtocol", - - "VerifyMode", CUSTOM_PREFIX "VerifyMode", - - "-cert", CUSTOM_PREFIX "cert", - "Certificate", CUSTOM_PREFIX "Certificate", - - "-key", CUSTOM_PREFIX "key", - "PrivateKey", CUSTOM_PREFIX "PrivateKey"}; +static const char *supported_cmds[] = {"-min_protocol", + CUSTOM_PREFIX "min_protocol", + "MinProtocol", + CUSTOM_PREFIX "MinProtocol", + + "-max_protocol", + CUSTOM_PREFIX "max_protocol", + "MaxProtocol", + CUSTOM_PREFIX "MaxProtocol", + + "VerifyMode", + CUSTOM_PREFIX "VerifyMode", + + "-cert", + CUSTOM_PREFIX "cert", + "Certificate", + CUSTOM_PREFIX "Certificate", + + "-key", + CUSTOM_PREFIX "key", + "PrivateKey", + CUSTOM_PREFIX "PrivateKey" + + "-verifyCApath", + CUSTOM_PREFIX "verifyCApath", + "VerifyCAPath", + CUSTOM_PREFIX "VerifyCAPath", + + "-verifyCAfile", + CUSTOM_PREFIX "verifyCAfile", + "VerifyCAFile", + CUSTOM_PREFIX "VerifyCAFile"}; #define NUM_SUPPORTED_CMDS (sizeof(supported_cmds) / sizeof(supported_cmds[0])) @@ -283,6 +301,55 @@ void test_certificate_and_private_key(void) { SSL_CTX_free(ctx); } +void set_verify_ca(SSL_CONF_CTX *cctx) { + // Note: we don't test invalid values here - our implementation diverges + // slightly due to later processing of the cert file/dir. + printf("\t\tcmd VerifyCAPath NULL returns %d\n", + SSL_CONF_cmd(cctx, "VerifyCAPath", NULL)); + printf("\t\tcmd VerifyCAPath 'test-ca/rsa' returns %d\n", + SSL_CONF_cmd(cctx, "VerifyCAPath", "test-ca/rsa")); + + printf("\t\tcmd VerifyCAFile NULL returns %d\n", + SSL_CONF_cmd(cctx, "VerifyCAFile", NULL)); + printf("\t\tcmd VerifyCAFile 'test-ca/rsa/ca.cert' returns %d\n", + SSL_CONF_cmd(cctx, "VerifyCAFile", "test-ca/rsa/ca.cert")); +} + +void test_verify_ca_path_file(void) { + SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); + assert(cctx != NULL); + + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); + + printf("\tPre-ctx (not certificate flag):\n"); + set_verify_ca(cctx); + + printf("\tPre-ctx (certificate flag):\n"); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); + set_verify_ca(cctx); + SSL_CONF_CTX_clear_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); + + SSL_CTX *ctx = SSL_CTX_new(TLS_method()); + assert(ctx != NULL); + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + + printf("\tWith ctx (not certificate flag):\n"); + set_verify_ca(cctx); + + printf("\tWith ctx (certificate flag):\n"); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); + set_verify_ca(cctx); + SSL_CONF_CTX_clear_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); + + // Note: we do not test with `SSL_CONF_set_ssl()` here - we lack + // support for the `Certificate` command updating an `SSL` + // struct at this time. + + assert(SSL_CONF_CTX_finish(cctx)); + SSL_CONF_CTX_free(cctx); + SSL_CTX_free(ctx); +} + int main(void) { printf("Supported commands:\n"); printf("no base flags, default prefix:\n"); @@ -311,4 +378,7 @@ int main(void) { printf("Certificate/PrivateKey:\n"); test_certificate_and_private_key(); + + printf("VerifyCAPath/VerifyCAFile:\n"); + test_verify_ca_path_file(); } From 34217a258ba46ef5ac28791f42b876dc4f15d6cc Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Sun, 23 Jun 2024 15:45:34 -0400 Subject: [PATCH 2/2] conf: add a TODO for some future commands Most of these will require implementing more logic elsewhere before we can add a supported command. --- rustls-libssl/src/conf.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rustls-libssl/src/conf.rs b/rustls-libssl/src/conf.rs index 99cbbb7..1df44d0 100644 --- a/rustls-libssl/src/conf.rs +++ b/rustls-libssl/src/conf.rs @@ -516,4 +516,13 @@ const SUPPORTED_COMMANDS: &[Command] = &[ value_type: ValueType::File, action: SslConfigCtx::verify_ca_file, }, + // Some commands that would be reasonable to implement in the future: + // - ClientCAFile/ClientCAPath + // - Options + // - SessionTicket/-no_ticket + // - CANames (?) + // - Groups/-groups + // - SignatureAlgorithms/-sigalgs + // - RequestCAFile + // - Ciphersuites/-ciphersuites ];