Skip to content

Commit

Permalink
conf: implement Options SessionTicket/-SessionTicket cmd
Browse files Browse the repository at this point in the history
  • Loading branch information
cpu committed Jun 27, 2024
1 parent a8ebfc5 commit 0f68342
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 1 deletion.
54 changes: 53 additions & 1 deletion rustls-libssl/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,44 @@ impl SslConfigCtx {
Ok(ActionResult::NotApplied)
}

fn options(&mut self, opts: Option<&str>) -> Result<ActionResult, Error> {
let opts = match opts {
Some(path) => path,
None => return Ok(ActionResult::ValueRequired),
};

for part in opts.split(',').map(|part| part.trim()) {
let flag = match part.starts_with('-') {
true => OptionFlag::Disable,
false => OptionFlag::Enable,
};
match part {
"SessionTicket" | "-SessionTicket" => self.session_ticket_option(flag)?,
_ => {}
}
}

Ok(ActionResult::Applied)
}

fn session_ticket_option(&mut self, flag: OptionFlag) -> Result<(), Error> {
if !self.flags.is_server() {
return Err(Error::bad_data(
"SessionTicket is only supported for servers",
));
}
let opts = match &self.state {
State::ApplyingToCtx(ctx) => &mut ctx.get_mut().raw_options,
State::ApplyingToSsl(ssl) => &mut ssl.get_mut().raw_options,
State::Validating => return Ok(()),
};
match flag {
OptionFlag::Disable => *opts |= crate::SSL_OP_NO_TICKET,
OptionFlag::Enable => *opts &= !crate::SSL_OP_NO_TICKET,
}
Ok(())
}

fn parse_protocol_version(proto: Option<&str>) -> Option<u16> {
Some(match proto {
Some("None") => 0,
Expand Down Expand Up @@ -481,6 +519,14 @@ impl From<Flags> for c_uint {
}
}

/// Representation of whether an "Options" value flag should be enabled or disabled.
enum OptionFlag {
/// The option flag value begins with '-' indicating it should be disabled.
Disable,
/// The option flag does not begin with '-' indicating it should be enabled.
Enable,
}

/// All the [`Command`]s that are supported by [`SslConfigCtx`].
const SUPPORTED_COMMANDS: &[Command] = &[
Command {
Expand Down Expand Up @@ -539,10 +585,16 @@ const SUPPORTED_COMMANDS: &[Command] = &[
value_type: ValueType::None,
action: SslConfigCtx::no_tickets,
},
Command {
name_file: Some("Options"),
name_cmdline: None,
flags: Flags(Flags::ANY),
value_type: ValueType::String,
action: SslConfigCtx::options,
},
// Some commands that would be reasonable to implement in the future:
// - ClientCAFile/ClientCAPath
// - Options
// - SessionTicket
// - CANames (?)
// - Groups/-groups
// - SignatureAlgorithms/-sigalgs
Expand Down
90 changes: 90 additions & 0 deletions rustls-libssl/tests/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

#include <assert.h>
#include <stdint.h>
#include <stdio.h>

#include <openssl/ssl.h>
Expand Down Expand Up @@ -403,6 +404,92 @@ void test_no_ticket(void) {
SSL_free(ssl);
}

void set_options_values(SSL_CONF_CTX *cctx, SSL_CTX *ctx, SSL *ssl,
uint64_t opts, const char *values) {
// Put the CTX and SSL_CTX into a known options state beforehand.
if (ctx != NULL) {
SSL_CTX_clear_options(ctx, UINT64_MAX);
SSL_CTX_set_options(ctx, opts);
printf("\t\tSSL_CTX_get_options before: 0x%lx\n", SSL_CTX_get_options(ctx));
}
if (ssl != NULL) {
SSL_clear_options(ssl, UINT64_MAX);
SSL_set_options(ssl, opts);
printf("\t\tSSL_get_options before: 0x%lx\n", SSL_get_options(ssl));
}

// Apply the Options command
printf("\t\tSSL_CONF_cmd Options %s == %d\n",
values == NULL ? "NULL" : values,
SSL_CONF_cmd(cctx, "Options", values));

if (ctx != NULL) {
printf("\t\tSSL_CTX_get_options after: 0x%lx\n", SSL_CTX_get_options(ctx));
}
if (ssl != NULL) {
printf("\t\tSSL_get_options after: 0x%lx\n", SSL_get_options(ssl));
}
}

void test_options_session_ticket_variations(SSL_CONF_CTX *cctx, SSL_CTX *ctx,
SSL *ssl) {
// Try NULL
set_options_values(cctx, ctx, ssl, 0, NULL);
// NOTE: we don't try invalid/unknown values because Rustls will ignore them
// without error
// while OpenSSL will erorr.

// Test enabling the option when it has not been disabled, and when it has
// been disabled
set_options_values(cctx, ctx, ssl, 0, "SessionTicket");
set_options_values(cctx, ctx, ssl, SSL_OP_NO_TICKET, "SessionTicket");

// Test disabling the option when it has been enabled, and when it has not
// been enabled
set_options_values(cctx, ctx, ssl, SSL_OP_NO_TICKET, "-SessionTicket");
set_options_values(cctx, ctx, ssl, 0, "-SessionTicket");

// Test enabling and disabling the option in the same command for both initial
// states
set_options_values(cctx, ctx, ssl, 0, "SessionTicket,-SessionTicket");
set_options_values(cctx, ctx, ssl, SSL_OP_NO_TICKET,
"SessionTicket,-SessionTicket");
set_options_values(cctx, ctx, ssl, SSL_OP_NO_TICKET,
"-SessionTicket,SessionTicket");
set_options_values(cctx, ctx, ssl, 0, "-SessionTicket,SessionTicket");
}

void test_options_session_ticket(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, no server flag:\n");
test_options_session_ticket_variations(cctx, NULL, NULL);

printf("\tPre-ctx, with server flag: \n");
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
test_options_session_ticket_variations(cctx, NULL, NULL);

SSL_CTX *ctx = SSL_CTX_new(TLS_method());
assert(ctx != NULL);
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
printf("\tWith ctx\n");
test_options_session_ticket_variations(cctx, ctx, NULL);

SSL *ssl = SSL_new(ctx);
assert(ssl != NULL);
SSL_CONF_CTX_set_ssl(cctx, ssl);
printf("\tWith ssl\n");
test_options_session_ticket_variations(cctx, NULL, ssl);

assert(SSL_CONF_CTX_finish(cctx));
SSL_CONF_CTX_free(cctx);
SSL_CTX_free(ctx);
SSL_free(ssl);
}

int main(void) {
printf("Supported commands:\n");
printf("no base flags, default prefix:\n");
Expand Down Expand Up @@ -437,4 +524,7 @@ int main(void) {

printf("no_ticket\n");
test_no_ticket();

printf("Options SessionTicket\n");
test_options_session_ticket();
}

0 comments on commit 0f68342

Please sign in to comment.