From ec2f7e568ea18a22ab57326fffe78ef2aa6884f5 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 18 Oct 2013 16:09:12 +0100 Subject: [PATCH] Extend SSL_CONF Extend SSL_CONF to return command value types. Add certificate and key options. Update documentation. --- apps/s_cb.c | 6 ++ doc/ssl/SSL_CONF_CTX_set_flags.pod | 4 + doc/ssl/SSL_CONF_cmd.pod | 70 ++++++++++++++ ssl/ssl.h | 8 ++ 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 b1102ceed6..083956916c 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -1685,6 +1685,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 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 on B. Its purpose is to simplify application configuration of B or B 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 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 names for command lines (i.e. when the @@ -80,6 +88,21 @@ Sets the cipher suite list to B. Note: syntax checking of B is currently not performed unless a B or B structure is associated with B. +=item B<-cert> + +Attempts to use the file B as the certificate for the appropriate +context. It currently uses SSL_CTX_use_cerificate_chain_file if an B +structure is set or SSL_use_certifcate_file with filetype PEM if an B +structure is set. This option is only supported if certificate operations +are permitted. + +=item B<-key> + +Attempts to use the file B 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. Note: syntax checking of B is currently not performed unless an B or B structure is associated with B. +=item B + +Attempts to use the file B as the certificate for the appropriate +context. It currently uses SSL_CTX_use_cerificate_chain_file if an B +structure is set or SSL_use_certifcate_file with filetype PEM if an B +structure is set. This option is only supported if certificate operations +are permitted. + +=item B + +Attempts to use the file B 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 file. + =item B 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 + +The B string is unrecognised, this return value can be use to flag +syntax errors. + +=item B + +The value is a string without any specific structure. + +=item B + +The value is a file name. + +=item B + +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 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 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, diff --git a/ssl/ssl.h b/ssl/ssl.h index a41518414a..c2587120a5 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -802,6 +802,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. */ @@ -2483,6 +2489,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); @@ -2493,6 +2500,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 a2b8d4975d..4b083019aa 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -221,7 +221,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) @@ -232,7 +232,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) @@ -243,7 +243,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) @@ -255,7 +255,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)) @@ -315,7 +315,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) @@ -325,7 +325,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[] = { @@ -343,7 +343,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[] = { @@ -365,55 +365,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; @@ -422,27 +459,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) @@ -504,6 +551,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; @@ -523,6 +582,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) -- 2.34.1