Extend SSL_CONF
authorDr. Stephen Henson <steve@openssl.org>
Fri, 18 Oct 2013 15:09:12 +0000 (16:09 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 20 Oct 2013 21:07:36 +0000 (22:07 +0100)
Extend SSL_CONF to return command value types.

Add certificate and key options.

Update documentation.

apps/s_cb.c
doc/ssl/SSL_CONF_CTX_set_flags.pod
doc/ssl/SSL_CONF_cmd.pod
ssl/ssl.h
ssl/ssl_conf.c

index b1102ce..0839569 100644 (file)
@@ -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;
        }
 
index cc3d20e..ab87efc 100644 (file)
@@ -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
index 5952072..c57bf80 100644 (file)
@@ -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)>,
index a415184..c258712 100644 (file)
--- 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,
index a2b8d49..4b08301 100644 (file)
@@ -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)