diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2013-10-18 16:09:12 +0100 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2013-11-02 13:41:19 +0000 |
commit | 044f8ca87d0cb3c4c8eded86f793a47108614f1f (patch) | |
tree | 9eaf1a84090d09977aefc57fcd27fc4df3061a98 | |
parent | 45ee08d99b24c76cdcfdd4e6eeeed55b7a25641f (diff) |
Extend SSL_CONF
Extend SSL_CONF to return command value types.
Add certificate and key options.
Update documentation.
(cherry picked from commit ec2f7e568ea18a22ab57326fffe78ef2aa6884f5)
-rw-r--r-- | apps/s_cb.c | 6 | ||||
-rw-r--r-- | doc/ssl/SSL_CONF_CTX_set_flags.pod | 4 | ||||
-rw-r--r-- | doc/ssl/SSL_CONF_cmd.pod | 70 | ||||
-rw-r--r-- | ssl/ssl.h | 8 | ||||
-rw-r--r-- | ssl/ssl_conf.c | 146 |
5 files changed, 193 insertions, 41 deletions
diff --git a/apps/s_cb.c b/apps/s_cb.c index 69a50a4599..22506a6805 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -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; } diff --git a/doc/ssl/SSL_CONF_CTX_set_flags.pod b/doc/ssl/SSL_CONF_CTX_set_flags.pod index cc3d20e7ec..ab87efcc22 100644 --- a/doc/ssl/SSL_CONF_CTX_set_flags.pod +++ b/doc/ssl/SSL_CONF_CTX_set_flags.pod @@ -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 diff --git a/doc/ssl/SSL_CONF_cmd.pod b/doc/ssl/SSL_CONF_cmd.pod index 5952072f9e..c57bf80109 100644 --- a/doc/ssl/SSL_CONF_cmd.pod +++ b/doc/ssl/SSL_CONF_cmd.pod @@ -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)>, @@ -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, diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 7f3487737f..b5a3cccefd 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -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,55 +366,92 @@ 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) +static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) { - ssl_conf_cmd_tbl *t, *runcmd = NULL; - size_t i; - if (cmd == NULL) - { - 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; @@ -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) |