Commit 044f8ca8 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Extend SSL_CONF

Extend SSL_CONF to return command value types.

Add certificate and key options.

Update documentation.
(cherry picked from commit ec2f7e56)
parent 45ee08d9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1677,6 +1677,12 @@ int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx,
			}
		}
#endif
	if (!SSL_CONF_CTX_finish(cctx))
		{
		BIO_puts(err, "Error finishing context\n");
		ERR_print_errors(err);
		return 0;
		}
	return 1;
	}

+4 −0
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@ least one of these flags must be set.
recognise options intended for use in SSL/TLS clients or servers. One or
both of these flags must be set.

=item SSL_CONF_CERTIFICATE

recognise certificate and private key options.

=item SSL_CONF_FLAG_SHOW_ERRORS

indicate errors relating to unrecognised options or missing arguments in
+70 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ SSL_CONF_cmd - send configuration command
 #include <openssl/ssl.h>

 int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
 int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
 int SSL_CONF_finish(SSL_CONF_CTX *cctx);

=head1 DESCRIPTION

@@ -17,6 +19,12 @@ optional parameter B<value> on B<ctx>. Its purpose is to simplify application
configuration of B<SSL_CTX> or B<SSL> structures by providing a common
framework for command line options or configuration files.

SSL_CONF_cmd_value_type() returns the type of value that B<cmd> refers to.

The function SSL_CONF_finish() must be called after all configuration
operations have been completed. It is used to finalise any operations
or to process defaults.

=head1 SUPPORTED COMMAND LINE COMMANDS

Currently supported B<cmd> names for command lines (i.e. when the
@@ -80,6 +88,21 @@ Sets the cipher suite list to B<value>. Note: syntax checking of B<value> is
currently not performed unless a B<SSL> or B<SSL_CTX> structure is 
associated with B<cctx>.

=item B<-cert>

Attempts to use the file B<value> as the certificate for the appropriate
context. It currently uses SSL_CTX_use_cerificate_chain_file if an B<SSL_CTX>
structure is set or SSL_use_certifcate_file with filetype PEM if an B<SSL>
structure is set. This option is only supported if certificate operations
are permitted.

=item B<-key>

Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
are permitted. Note: if no B<-key> option is set then a private key is
not loaded: it does not currently use the B<-cert> file.

=item B<-no_ssl2>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>

Disables protocol support for SSLv2, SSLv3, TLS 1.0, TLS 1.1 or TLS 1.2 
@@ -147,6 +170,21 @@ Sets the cipher suite list to B<value>. Note: syntax checking of B<value> is
currently not performed unless an B<SSL> or B<SSL_CTX> structure is 
associated with B<cctx>.

=item B<Certificate>

Attempts to use the file B<value> as the certificate for the appropriate
context. It currently uses SSL_CTX_use_cerificate_chain_file if an B<SSL_CTX>
structure is set or SSL_use_certifcate_file with filetype PEM if an B<SSL>
structure is set. This option is only supported if certificate operations
are permitted.

=item B<PrivateKey>

Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
are permitted. Note: if no B<-key> option is set then a private key is
not loaded: it does not currently use the B<Certificate> file.

=item B<SignatureAlgorithms>

This sets the supported signature algorithms for TLS v1.2. For clients this
@@ -246,6 +284,30 @@ Set by default.

=back

=head1 SUPPORTED COMMAND TYPES

The function SSL_CONF_cmd_value_type() currently returns one of the following
types:

=over 4

=item B<SSL_CONF_TYPE_UNKNOWN>

The B<cmd> string is unrecognised, this return value can be use to flag
syntax errors.

=item B<SSL_CONF_TYPE_STRING>

The value is a string without any specific structure.

=item B<SSL_CONF_TYPE_FILE>

The value is a file name.

=item B<SSL_CONF_TYPE_DIR>

The value is a directory name.

=head1 NOTES

The order of operations is significant. This can be used to set either defaults
@@ -284,6 +346,12 @@ can be checked instead. If -3 is returned a required argument is missing
and an error is indicated. If 0 is returned some other error occurred and
this can be reported back to the user.

The function SSL_CONF_cmd_value_type() can be used by applications to 
check for the existence of a command or to perform additional syntax
checking or translation of the command value. For example if the return
value is B<SSL_CONF_TYPE_FILE> an application could translate a relative
pathname to an absolute pathname.

=head1 EXAMPLES

Set supported signature algorithms:
@@ -327,6 +395,8 @@ error occurred attempting to perform the operation: for example due to an
error in the syntax of B<value> in this case the error queue may provide
additional information.

SSL_CONF_finish() returns 1 for success and 0 for failure.

=head1 SEE ALSO

L<SSL_CONF_CTX_new(3)|SSL_CONF_CTX_new(3)>,
+8 −0
Original line number Diff line number Diff line
@@ -763,6 +763,12 @@ struct ssl_session_st
#define SSL_CONF_FLAG_CLIENT		0x4
#define SSL_CONF_FLAG_SERVER		0x8
#define SSL_CONF_FLAG_SHOW_ERRORS	0x10
#define SSL_CONF_FLAG_CERTIFICATE	0x20
/* Configuration value types */
#define SSL_CONF_TYPE_UNKNOWN		0x0
#define SSL_CONF_TYPE_STRING		0x1
#define SSL_CONF_TYPE_FILE		0x2
#define SSL_CONF_TYPE_DIR		0x3

/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
 * they cannot be used to clear bits. */
@@ -2431,6 +2437,7 @@ int SSL_cache_hit(SSL *s);
int SSL_is_server(SSL *s);

SSL_CONF_CTX *SSL_CONF_CTX_new(void);
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags);
@@ -2441,6 +2448,7 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);

int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);

#ifndef OPENSSL_NO_SSL_TRACE
void SSL_trace(int write_p, int version, int content_type,
+105 −41
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ static int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd)
	}

/* Set supported signature algorithms */
static int cmd_sigalgs(SSL_CONF_CTX *cctx, const char *value)
static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv;
	if (cctx->ssl)
@@ -233,7 +233,7 @@ static int cmd_sigalgs(SSL_CONF_CTX *cctx, const char *value)
	return rv > 0;
	}
/* Set supported client signature algorithms */
static int cmd_client_sigalgs(SSL_CONF_CTX *cctx, const char *value)
static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv;
	if (cctx->ssl)
@@ -244,7 +244,7 @@ static int cmd_client_sigalgs(SSL_CONF_CTX *cctx, const char *value)
	return rv > 0;
	}

static int cmd_curves(SSL_CONF_CTX *cctx, const char *value)
static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv;
	if (cctx->ssl)
@@ -256,7 +256,7 @@ static int cmd_curves(SSL_CONF_CTX *cctx, const char *value)
	}
#ifndef OPENSSL_NO_ECDH
/* ECDH temporary parameters */
static int cmd_ecdhparam(SSL_CONF_CTX *cctx, const char *value)
static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
	{
	int onoff = -1, rv = 1;
	if (!(cctx->flags & SSL_CONF_FLAG_SERVER))
@@ -316,7 +316,7 @@ static int cmd_ecdhparam(SSL_CONF_CTX *cctx, const char *value)
	return rv > 0;
	}
#endif
static int cmd_cipher_list(SSL_CONF_CTX *cctx, const char *value)
static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv = 1;
	if (cctx->ctx)
@@ -326,7 +326,7 @@ static int cmd_cipher_list(SSL_CONF_CTX *cctx, const char *value)
	return rv > 0;
	}

static int cmd_protocol(SSL_CONF_CTX *cctx, const char *value)
static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
	{
	static const ssl_flag_tbl ssl_protocol_list[] =
		{
@@ -344,7 +344,7 @@ static int cmd_protocol(SSL_CONF_CTX *cctx, const char *value)
	return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
	}

static int cmd_options(SSL_CONF_CTX *cctx, const char *value)
static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
	{
	static const ssl_flag_tbl ssl_option_list[] =
		{
@@ -366,56 +366,93 @@ static int cmd_options(SSL_CONF_CTX *cctx, const char *value)
	return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
	}

static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv = 1;
	if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
		return -2;
	if (cctx->ctx)
		rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
	if (cctx->ssl)
		rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM);
	return rv > 0;
	}

static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value)
	{
	int rv = 1;
	if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
		return -2;
	if (cctx->ctx)
		rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM);
	if (cctx->ssl)
		rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM);
	return rv > 0;
	}

typedef struct
	{
	int (*cmd)(SSL_CONF_CTX *cctx, const char *value);
	const char *str_file;
	const char *str_cmdline;
	unsigned int value_type;
	} ssl_conf_cmd_tbl;

/* Table of supported patameters */
/* Table of supported parameters */

#define SSL_CONF_CMD(name, cmdopt, type) \
	{cmd_##name, #name, cmdopt, type}

#define SSL_CONF_CMD_STRING(name, cmdopt) \
	SSL_CONF_CMD(name, cmdopt, SSL_CONF_TYPE_STRING)

static ssl_conf_cmd_tbl ssl_conf_cmds[] = {
	{cmd_sigalgs,		"SignatureAlgorithms", "sigalgs"},
	{cmd_client_sigalgs,	"ClientSignatureAlgorithms", "client_sigalgs"},
	{cmd_curves,		"Curves", "curves"},
	SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs"),
	SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs"),
	SSL_CONF_CMD_STRING(Curves, "curves"),
#ifndef OPENSSL_NO_ECDH
	{cmd_ecdhparam,		"ECDHParameters", "named_curve"},
	SSL_CONF_CMD_STRING(ECDHParameters, "named_curve"),
#endif
	{cmd_cipher_list,	"CipherString", "cipher"},
	{cmd_protocol,		"Protocol", NULL},
	{cmd_options,		"Options", NULL},
	SSL_CONF_CMD_STRING(CipherString, "cipher"),
	SSL_CONF_CMD_STRING(Protocol, NULL),
	SSL_CONF_CMD_STRING(Options, NULL),
	SSL_CONF_CMD(Certificate, "cert", SSL_CONF_TYPE_FILE),
	SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_TYPE_FILE)
};

int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
	{
	ssl_conf_cmd_tbl *t, *runcmd = NULL;
	size_t i;
	if (cmd == NULL)
static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
	{
		SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
	if (!pcmd || !*pcmd)
		return 0;
		}
	/* If a prefix is set, check and skip */
	if (cctx->prefix)
		{
		if (strlen(cmd) <= cctx->prefixlen)
			return -2;
		if (strlen(*pcmd) <= cctx->prefixlen)
			return 0;
		if (cctx->flags & SSL_CONF_FLAG_CMDLINE &&
			strncmp(cmd, cctx->prefix, cctx->prefixlen))
			return -2;
			strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
			return 0;
		if (cctx->flags & SSL_CONF_FLAG_FILE &&
			strncasecmp(cmd, cctx->prefix, cctx->prefixlen))
			return -2;
		cmd += cctx->prefixlen;
			strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
			return 0;
		*pcmd += cctx->prefixlen;
		}
	else if (cctx->flags & SSL_CONF_FLAG_CMDLINE)
		{
		if (*cmd != '-' || !cmd[1])
			return -2;
		cmd++;
		if (**pcmd != '-' || !*pcmd[1])
			return 0;
		*pcmd += 1;
		}
	return 1;
	}

static ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, const char *cmd)
	{
	ssl_conf_cmd_tbl *t;
	size_t i;
	if (cmd == NULL)
		return NULL;

	/* Look for matching parameter name in table */
	for (i = 0, t = ssl_conf_cmds;
		i < sizeof(ssl_conf_cmds)/sizeof(ssl_conf_cmd_tbl); i++, t++)
@@ -423,27 +460,37 @@ int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
		if (cctx->flags & SSL_CONF_FLAG_CMDLINE)
			{
			if (t->str_cmdline && !strcmp(t->str_cmdline, cmd))
				{
				runcmd = t;
				break;
				}
				return t;
			}
		if (cctx->flags & SSL_CONF_FLAG_FILE)
			{
			if (t->str_file && !strcasecmp(t->str_file, cmd))
				{
				runcmd = t;
				break;
				return t;
			}
		}
	return NULL;
	}

int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
	{
	ssl_conf_cmd_tbl *runcmd;
	if (cmd == NULL)
		{
		SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
		return 0;
		}

	if (!ssl_conf_cmd_skip_prefix(cctx, &cmd))
		return -2;

	runcmd = ssl_conf_cmd_lookup(cctx, cmd);

	if (runcmd)
		{
		int rv;
		if (value == NULL)
			return -3;
		rv = t->cmd(cctx, value);
		rv = runcmd->cmd(cctx, value);
		if (rv > 0)
			return 2;
		if (rv == -2)
@@ -505,6 +552,18 @@ int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
	return rv;
	}

int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
	{
	if (ssl_conf_cmd_skip_prefix(cctx, &cmd))
		{
		ssl_conf_cmd_tbl *runcmd;
		runcmd = ssl_conf_cmd_lookup(cctx, cmd);
		if (runcmd)
			return runcmd->value_type;
		}
	return SSL_CONF_TYPE_UNKNOWN;
	}

SSL_CONF_CTX *SSL_CONF_CTX_new(void)
	{
	SSL_CONF_CTX *ret;
@@ -524,6 +583,11 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void)
	return ret;
	}

int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
	{
	return 1;
	}

void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
	{
	if (cctx)