X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=ssl%2Fssl_conf.c;h=5478840deae9947b73631ad500057ac398965993;hb=3c66a669dfc7b3792f7af0758ea26fe8502ce70c;hp=31ae9250fb0be8641579aaf1b5365c39f8fe2237;hpb=f14a4a861d2d221ed565a75441a218f85b8db530;p=openssl.git diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 31ae9250fb..5478840dea 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -1,5 +1,5 @@ -/*! \file ssl/ssl_conf.c - * \brief SSL configuration functions +/* + * ! \file ssl/ssl_conf.c \brief SSL configuration functions */ /* ==================================================================== * Copyright (c) 2012 The OpenSSL Project. All rights reserved. @@ -9,7 +9,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -56,29 +56,32 @@ */ #ifdef REF_CHECK -# include +# include #endif #include #include "ssl_locl.h" #include #include +#ifndef OPENSSL_NO_DH +# include +#endif -/* structure holding name tables. This is used for pemitted elements in - * lists such as TLSv1 and single command line switches such as no_tls1 +/* + * structure holding name tables. This is used for pemitted elements in lists + * such as TLSv1 and single command line switches such as no_tls1 */ -typedef struct - { - const char *name; - int namelen; - unsigned int name_flags; - unsigned long option_value; - } ssl_flag_tbl; +typedef struct { + const char *name; + int namelen; + unsigned int name_flags; + unsigned long option_value; +} ssl_flag_tbl; /* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */ -#define SSL_TFLAG_INV 0x1 +#define SSL_TFLAG_INV 0x1 /* Flags refers to cert_flags not options */ -#define SSL_TFLAG_CERT 0x2 +#define SSL_TFLAG_CERT 0x2 /* Option can only be used for clients */ #define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT /* Option can only be used for servers */ @@ -86,513 +89,595 @@ typedef struct #define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER) #define SSL_FLAG_TBL(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag} #define SSL_FLAG_TBL_SRV(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag} #define SSL_FLAG_TBL_CLI(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag} #define SSL_FLAG_TBL_INV(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag} #define SSL_FLAG_TBL_SRV_INV(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag} #define SSL_FLAG_TBL_CERT(str, flag) \ - {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} -/* Opaque structure containing SSL configuration context. +/* + * Opaque structure containing SSL configuration context. */ -struct ssl_conf_ctx_st - { - /* Various flags indicating (among other things) which options we - * will recognise. - */ - unsigned int flags; - /* Prefix and length of commands */ - char *prefix; - size_t prefixlen; - /* SSL_CTX or SSL structure to perform operations on */ - SSL_CTX *ctx; - SSL *ssl; - /* Pointer to SSL or SSL_CTX options field or NULL if none */ - unsigned long *poptions; - /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ - unsigned int *pcert_flags; - /* Current flag table being worked on */ - const ssl_flag_tbl *tbl; - /* Size of table */ - size_t ntbl; - }; +struct ssl_conf_ctx_st { + /* + * Various flags indicating (among other things) which options we will + * recognise. + */ + unsigned int flags; + /* Prefix and length of commands */ + char *prefix; + size_t prefixlen; + /* SSL_CTX or SSL structure to perform operations on */ + SSL_CTX *ctx; + SSL *ssl; + /* Pointer to SSL or SSL_CTX options field or NULL if none */ + unsigned long *poptions; + /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ + unsigned int *pcert_flags; + /* Current flag table being worked on */ + const ssl_flag_tbl *tbl; + /* Size of table */ + size_t ntbl; +}; static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl, - const char *name, int namelen, int onoff) - { - /* If name not relevant for context skip */ - if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH)) - return 0; - if (namelen == -1) - { - if (strcmp(tbl->name, name)) - return 0; - } - else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen)) - return 0; - if (cctx->poptions) - { - if (tbl->name_flags & SSL_TFLAG_INV) - onoff ^= 1; - if (tbl->name_flags & SSL_TFLAG_CERT) - { - if (onoff) - *cctx->pcert_flags |= tbl->option_value; - else - *cctx->pcert_flags &= ~tbl->option_value; - } - else - { - if (onoff) - *cctx->poptions |= tbl->option_value; - else - *cctx->poptions &= ~tbl->option_value; - } - } - return 1; - } + const char *name, int namelen, int onoff) +{ + /* If name not relevant for context skip */ + if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH)) + return 0; + if (namelen == -1) { + if (strcmp(tbl->name, name)) + return 0; + } else if (tbl->namelen != namelen + || strncasecmp(tbl->name, name, namelen)) + return 0; + if (cctx->poptions) { + if (tbl->name_flags & SSL_TFLAG_INV) + onoff ^= 1; + if (tbl->name_flags & SSL_TFLAG_CERT) { + if (onoff) + *cctx->pcert_flags |= tbl->option_value; + else + *cctx->pcert_flags &= ~tbl->option_value; + } else { + if (onoff) + *cctx->poptions |= tbl->option_value; + else + *cctx->poptions &= ~tbl->option_value; + } + } + return 1; +} static int ssl_set_option_list(const char *elem, int len, void *usr) - { - SSL_CONF_CTX *cctx = usr; - size_t i; - const ssl_flag_tbl *tbl; - int onoff = 1; - /* len == -1 indicates not being called in list context, just for - * single command line switches, so don't allow +, -. - */ - if (len != -1) - { - if (*elem == '+') - { - elem++; - len--; - onoff = 1; - } - else if (*elem == '-') - { - elem++; - len--; - onoff = 0; - } - } - for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) - { - if (ssl_match_option(cctx, tbl, elem, len, onoff)) - return 1; - } - return 0; - } +{ + SSL_CONF_CTX *cctx = usr; + size_t i; + const ssl_flag_tbl *tbl; + int onoff = 1; + /* + * len == -1 indicates not being called in list context, just for single + * command line switches, so don't allow +, -. + */ + if (elem == NULL) + return 0; + if (len != -1) { + if (*elem == '+') { + elem++; + len--; + onoff = 1; + } else if (*elem == '-') { + elem++; + len--; + onoff = 0; + } + } + for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) { + if (ssl_match_option(cctx, tbl, elem, len, onoff)) + return 1; + } + return 0; +} /* Single command line switches with no argument e.g. -no_ssl3 */ static int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd) - { - static const ssl_flag_tbl ssl_option_single[] = - { - SSL_FLAG_TBL("no_ssl2", SSL_OP_NO_SSLv2), - SSL_FLAG_TBL("no_ssl3", SSL_OP_NO_SSLv3), - SSL_FLAG_TBL("no_tls1", SSL_OP_NO_TLSv1), - SSL_FLAG_TBL("no_tls1_1", SSL_OP_NO_TLSv1_1), - SSL_FLAG_TBL("no_tls1_2", SSL_OP_NO_TLSv1_2), - SSL_FLAG_TBL("no_tls1_2", SSL_OP_NO_TLSv1_2), - SSL_FLAG_TBL("bugs", SSL_OP_ALL), - SSL_FLAG_TBL("no_comp", SSL_OP_NO_COMPRESSION), - SSL_FLAG_TBL_SRV("ecdh_single", SSL_OP_SINGLE_ECDH_USE), +{ + static const ssl_flag_tbl ssl_option_single[] = { + SSL_FLAG_TBL("no_ssl2", SSL_OP_NO_SSLv2), + SSL_FLAG_TBL("no_ssl3", SSL_OP_NO_SSLv3), + SSL_FLAG_TBL("no_tls1", SSL_OP_NO_TLSv1), + SSL_FLAG_TBL("no_tls1_1", SSL_OP_NO_TLSv1_1), + SSL_FLAG_TBL("no_tls1_2", SSL_OP_NO_TLSv1_2), + SSL_FLAG_TBL("bugs", SSL_OP_ALL), + SSL_FLAG_TBL("no_comp", SSL_OP_NO_COMPRESSION), + SSL_FLAG_TBL_SRV("ecdh_single", SSL_OP_SINGLE_ECDH_USE), #ifndef OPENSSL_NO_TLSEXT - SSL_FLAG_TBL("no_ticket", SSL_OP_NO_TICKET), + SSL_FLAG_TBL("no_ticket", SSL_OP_NO_TICKET), #endif - SSL_FLAG_TBL_SRV("serverpref", SSL_OP_CIPHER_SERVER_PREFERENCE), - SSL_FLAG_TBL("legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), - SSL_FLAG_TBL_SRV("legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT), - SSL_FLAG_TBL_SRV_INV("no_legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT), - SSL_FLAG_TBL_CERT("strict", SSL_CERT_FLAG_TLS_STRICT), + SSL_FLAG_TBL_SRV("serverpref", SSL_OP_CIPHER_SERVER_PREFERENCE), + SSL_FLAG_TBL("legacy_renegotiation", + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), + SSL_FLAG_TBL_SRV("legacy_server_connect", + SSL_OP_LEGACY_SERVER_CONNECT), + SSL_FLAG_TBL_SRV("no_resumption_on_reneg", + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + SSL_FLAG_TBL_SRV_INV("no_legacy_server_connect", + SSL_OP_LEGACY_SERVER_CONNECT), + SSL_FLAG_TBL_CERT("strict", SSL_CERT_FLAG_TLS_STRICT), #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL - SSL_FLAG_TBL_CERT("debug_broken_protocol", SSL_CERT_FLAG_BROKEN_PROTOCOL), + SSL_FLAG_TBL_CERT("debug_broken_protocol", + SSL_CERT_FLAG_BROKEN_PROTOCOL), #endif - }; - cctx->tbl = ssl_option_single; - cctx->ntbl = sizeof(ssl_option_single)/sizeof(ssl_flag_tbl); - return ssl_set_option_list(cmd, -1, cctx); - } + }; + cctx->tbl = ssl_option_single; + cctx->ntbl = sizeof(ssl_option_single) / sizeof(ssl_flag_tbl); + return ssl_set_option_list(cmd, -1, cctx); +} /* Set supported signature algorithms */ -static int cmd_sigalgs(SSL_CONF_CTX *cctx, const char *value) - { - int rv; - if (cctx->ssl) - rv = SSL_set1_sigalgs_list(cctx->ssl, value); - /* NB: ctx == NULL performs syntax checking only */ - else - rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value); - return rv > 0; - } +static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + /* Set supported client signature algorithms */ -static int cmd_client_sigalgs(SSL_CONF_CTX *cctx, const char *value) - { - int rv; - if (cctx->ssl) - rv = SSL_set1_client_sigalgs_list(cctx->ssl, value); - /* NB: ctx == NULL performs syntax checking only */ - else - rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value); - return rv > 0; - } - -static int cmd_curves(SSL_CONF_CTX *cctx, const char *value) - { - int rv; - if (cctx->ssl) - rv = SSL_set1_curves_list(cctx->ssl, value); - /* NB: ctx == NULL performs syntax checking only */ - else - rv = SSL_CTX_set1_curves_list(cctx->ctx, value); - return rv > 0; - } +static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, + const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_client_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + +static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_curves_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_curves_list(cctx->ctx, value); + return rv > 0; +} + #ifndef OPENSSL_NO_ECDH /* ECDH temporary parameters */ -static int cmd_ecdhparam(SSL_CONF_CTX *cctx, const char *value) - { - int onoff = -1, rv = 1; - if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) - return -2; - if (cctx->flags & SSL_CONF_FLAG_FILE) - { - if (*value == '+') - { - onoff = 1; - value++; - } - if (*value == '-') - { - onoff = 0; - value++; - } - if (!strcasecmp(value, "automatic")) - { - if (onoff == -1) - onoff = 1; - } - else if (onoff != -1) - return 0; - } - else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) - { - if (!strcmp(value, "auto")) - onoff = 1; - } - - if (onoff != -1) - { - if (cctx->ctx) - rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff); - else if (cctx->ssl) - rv = SSL_set_ecdh_auto(cctx->ssl, onoff); - } - else - { - EC_KEY *ecdh; - int nid; - nid = EC_curve_nist2nid(value); - if (nid == NID_undef) - nid = OBJ_sn2nid(value); - if (nid == 0) - return 0; - ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) - return 0; - if (cctx->ctx) - rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); - else if (cctx->ssl) - rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); - EC_KEY_free(ecdh); - } - - return rv > 0; - } +static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int onoff = -1, rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) + return -2; + if (cctx->flags & SSL_CONF_FLAG_FILE) { + if (*value == '+') { + onoff = 1; + value++; + } + if (*value == '-') { + onoff = 0; + value++; + } + if (!strcasecmp(value, "automatic")) { + if (onoff == -1) + onoff = 1; + } else if (onoff != -1) + return 0; + } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (!strcmp(value, "auto")) + onoff = 1; + } + + if (onoff != -1) { + if (cctx->ctx) + rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff); + else if (cctx->ssl) + rv = SSL_set_ecdh_auto(cctx->ssl, onoff); + } else { + EC_KEY *ecdh; + int nid; + nid = EC_curve_nist2nid(value); + if (nid == NID_undef) + nid = OBJ_sn2nid(value); + if (nid == 0) + return 0; + ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) + return 0; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); + else if (cctx->ssl) + rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); + EC_KEY_free(ecdh); + } + + return rv > 0; +} +#endif +static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (cctx->ctx) + rv = SSL_CTX_set_cipher_list(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_set_cipher_list(cctx->ssl, value); + return rv > 0; +} + +static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_protocol_list[] = { + SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK), + SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2), + SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3), + SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1), + SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1), + SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2) + }; + if (!(cctx->flags & SSL_CONF_FLAG_FILE)) + return -2; + cctx->tbl = ssl_protocol_list; + cctx->ntbl = sizeof(ssl_protocol_list) / sizeof(ssl_flag_tbl); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_option_list[] = { + SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET), + SSL_FLAG_TBL_INV("EmptyFragments", + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS), + SSL_FLAG_TBL("Bugs", SSL_OP_ALL), + SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION), + SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE), + SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation", + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE), + SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE), + SSL_FLAG_TBL("UnsafeLegacyRenegotiation", + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), + }; + if (!(cctx->flags & SSL_CONF_FLAG_FILE)) + return -2; + if (value == NULL) + return -3; + cctx->tbl = ssl_option_list; + cctx->ntbl = sizeof(ssl_option_list) / sizeof(ssl_flag_tbl); + 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; +} + +static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) + return -2; + if (cctx->ctx) + rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value); + return rv > 0; +} + +#ifndef OPENSSL_NO_DH +static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 0; + DH *dh = NULL; + BIO *in = NULL; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (cctx->ctx || cctx->ssl) { + in = BIO_new(BIO_s_file_internal()); + if (!in) + goto end; + if (BIO_read_filename(in, value) <= 0) + goto end; + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (!dh) + goto end; + } else + return 1; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh); + if (cctx->ssl) + rv = SSL_set_tmp_dh(cctx->ssl, dh); + end: + if (dh) + DH_free(dh); + if (in) + BIO_free(in); + return rv > 0; +} #endif -static int cmd_cipher_list(SSL_CONF_CTX *cctx, const char *value) - { - int rv = 1; - if (cctx->ctx) - rv = SSL_CTX_set_cipher_list(cctx->ctx, value); - if (cctx->ssl) - rv = SSL_set_cipher_list(cctx->ssl, value); - return rv > 0; - } - -static int cmd_protocol(SSL_CONF_CTX *cctx, const char *value) - { - static const ssl_flag_tbl ssl_protocol_list[] = - { - SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK), - SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2), - SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3), - SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1), - SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1), - SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2) - }; - if (!(cctx->flags & SSL_CONF_FLAG_FILE)) - return -2; - cctx->tbl = ssl_protocol_list; - cctx->ntbl = sizeof(ssl_protocol_list)/sizeof(ssl_flag_tbl); - return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); - } - -static int cmd_options(SSL_CONF_CTX *cctx, const char *value) - { - static const ssl_flag_tbl ssl_option_list[] = - { - SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET), - SSL_FLAG_TBL_INV("EmptyFragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS), - SSL_FLAG_TBL("Bugs", SSL_OP_ALL), - SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION), - SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE), - SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE), - SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE), - SSL_FLAG_TBL("UnsafeLegacyRenegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), - }; - if (!(cctx->flags & SSL_CONF_FLAG_FILE)) - return -2; - if (value == NULL) - return -3; - cctx->tbl = ssl_option_list; - cctx->ntbl = sizeof(ssl_option_list)/sizeof(ssl_flag_tbl); - return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); - } - -typedef struct - { - int (*cmd)(SSL_CONF_CTX *cctx, const char *value); - const char *str_file; - const char *str_cmdline; - } ssl_conf_cmd_tbl; - -/* Table of supported patameters */ - -static ssl_conf_cmd_tbl ssl_conf_cmds[] = { - {cmd_sigalgs, "SignatureAlgorithms", "sigalgs"}, - {cmd_client_sigalgs, "ClientSignatureAlgorithms", "client_sigalgs"}, - {cmd_curves, "Curves", "curves"}, +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 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 const ssl_conf_cmd_tbl ssl_conf_cmds[] = { + 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 + 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), + SSL_CONF_CMD(ServerInfoFile, NULL, SSL_CONF_TYPE_FILE), +#ifndef OPENSSL_NO_DH + SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_TYPE_FILE) #endif - {cmd_cipher_list, "CipherString", "cipher"}, - {cmd_protocol, "Protocol", NULL}, - {cmd_options, "Options", NULL}, }; +static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) +{ + if (!pcmd || !*pcmd) + return 0; + /* If a prefix is set, check and skip */ + if (cctx->prefix) { + if (strlen(*pcmd) <= cctx->prefixlen) + return 0; + if (cctx->flags & SSL_CONF_FLAG_CMDLINE && + strncmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + if (cctx->flags & SSL_CONF_FLAG_FILE && + strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + *pcmd += cctx->prefixlen; + } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (**pcmd != '-' || !(*pcmd)[1]) + return 0; + *pcmd += 1; + } + return 1; +} + +static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, + const char *cmd) +{ + const 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++) { + if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (t->str_cmdline && !strcmp(t->str_cmdline, cmd)) + return t; + } + if (cctx->flags & SSL_CONF_FLAG_FILE) { + if (t->str_file && !strcasecmp(t->str_file, cmd)) + return t; + } + } + return NULL; +} + 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) - { - SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME); - return 0; - } - /* If a prefix is set, check and skip */ - if (cctx->prefix) - { - if (strlen(cmd) <= cctx->prefixlen) - return -2; - if (cctx->flags & SSL_CONF_FLAG_CMDLINE && - strncmp(cmd, cctx->prefix, cctx->prefixlen)) - return -2; - if (cctx->flags & SSL_CONF_FLAG_FILE && - strncasecmp(cmd, cctx->prefix, cctx->prefixlen)) - return -2; - cmd += cctx->prefixlen; - } - else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) - { - if (*cmd != '-' || !cmd[1]) - return -2; - cmd++; - } - - /* 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++) - { - if (cctx->flags & SSL_CONF_FLAG_CMDLINE) - { - if (t->str_cmdline && !strcmp(t->str_cmdline, cmd)) - { - runcmd = t; - break; - } - } - if (cctx->flags & SSL_CONF_FLAG_FILE) - { - if (t->str_file && !strcasecmp(t->str_file, cmd)) - { - runcmd = t; - break; - } - } - } - - if (runcmd) - { - int rv; - if (value == NULL) - return -3; - rv = t->cmd(cctx, value); - if (rv > 0) - return 2; - if (rv == -2) - return -2; - if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) - { - SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE); - ERR_add_error_data(4, "cmd=", cmd, ", value=", value); - } - return 0; - } - - if (cctx->flags & SSL_CONF_FLAG_CMDLINE) - { - if (ctrl_str_option(cctx, cmd)) - return 1; - } - - if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) - { - SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME); - ERR_add_error_data(2, "cmd=", cmd); - } - - return -2; - } +{ + const 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 = runcmd->cmd(cctx, value); + if (rv > 0) + return 2; + if (rv == -2) + return -2; + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE); + ERR_add_error_data(4, "cmd=", cmd, ", value=", value); + } + return 0; + } + + if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (ctrl_str_option(cctx, cmd)) + return 1; + } + + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME); + ERR_add_error_data(2, "cmd=", cmd); + } + + return -2; +} int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv) - { - int rv; - const char *arg = NULL, *argn; - if (pargc && *pargc == 0) - return 0; - if (!pargc || *pargc > 0) - arg = **pargv; - if (arg == NULL) - return 0; - if (!pargc || *pargc > 1) - argn = (*pargv)[1]; - else - argn = NULL; - cctx->flags &= ~SSL_CONF_FLAG_FILE; - cctx->flags |= SSL_CONF_FLAG_CMDLINE; - rv = SSL_CONF_cmd(cctx, arg, argn); - if (rv > 0) - { - /* Success: update pargc, pargv */ - (*pargv) += rv; - if (pargc) - (*pargc) -= rv; - return rv; - } - /* Unknown swicth: indicate no arguments processed */ - if (rv == -2) - return 0; - /* Some error occurred processing command, return fatal error */ - if (rv == 0) - return -1; - return rv; - } +{ + int rv; + const char *arg = NULL, *argn; + if (pargc && *pargc == 0) + return 0; + if (!pargc || *pargc > 0) + arg = **pargv; + if (arg == NULL) + return 0; + if (!pargc || *pargc > 1) + argn = (*pargv)[1]; + else + argn = NULL; + cctx->flags &= ~SSL_CONF_FLAG_FILE; + cctx->flags |= SSL_CONF_FLAG_CMDLINE; + rv = SSL_CONF_cmd(cctx, arg, argn); + if (rv > 0) { + /* Success: update pargc, pargv */ + (*pargv) += rv; + if (pargc) + (*pargc) -= rv; + return rv; + } + /* Unknown switch: indicate no arguments processed */ + if (rv == -2) + return 0; + /* Some error occurred processing command, return fatal error */ + if (rv == 0) + return -1; + return rv; +} + +int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) +{ + if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) { + const 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; - ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX)); - if (ret) - { - ret->flags = 0; - ret->prefix = NULL; - ret->prefixlen = 0; - ret->ssl = NULL; - ret->ctx = NULL; - ret->poptions = NULL; - ret->pcert_flags = NULL; - ret->tbl = NULL; - ret->ntbl = 0; - } - return ret; - } +{ + SSL_CONF_CTX *ret; + ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX)); + if (ret) { + ret->flags = 0; + ret->prefix = NULL; + ret->prefixlen = 0; + ret->ssl = NULL; + ret->ctx = NULL; + ret->poptions = NULL; + ret->pcert_flags = NULL; + ret->tbl = NULL; + ret->ntbl = 0; + } + return ret; +} + +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) +{ + return 1; +} void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) - { - if (cctx) - { - if (cctx->prefix) - OPENSSL_free(cctx->prefix); - OPENSSL_free(cctx); - } - } +{ + if (cctx) { + if (cctx->prefix) + OPENSSL_free(cctx->prefix); + OPENSSL_free(cctx); + } +} unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) - { - cctx->flags |= flags; - return cctx->flags; - } +{ + cctx->flags |= flags; + return cctx->flags; +} unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags) - { - cctx->flags &= ~flags; - return cctx->flags; - } +{ + cctx->flags &= ~flags; + return cctx->flags; +} int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre) - { - char *tmp = NULL; - if (pre) - { - tmp = BUF_strdup(pre); - if (tmp == NULL) - return 0; - } - if (cctx->prefix) - OPENSSL_free(cctx->prefix); - cctx->prefix = tmp; - if (tmp) - cctx->prefixlen = strlen(tmp); - else - cctx->prefixlen = 0; - return 1; - } +{ + char *tmp = NULL; + if (pre) { + tmp = BUF_strdup(pre); + if (tmp == NULL) + return 0; + } + if (cctx->prefix) + OPENSSL_free(cctx->prefix); + cctx->prefix = tmp; + if (tmp) + cctx->prefixlen = strlen(tmp); + else + cctx->prefixlen = 0; + return 1; +} void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) - { - cctx->ssl = ssl; - cctx->ctx = NULL; - if (ssl) - { - cctx->poptions = &ssl->options; - cctx->pcert_flags = &ssl->cert->cert_flags; - } - else - { - cctx->poptions = NULL; - cctx->pcert_flags = NULL; - } - } +{ + cctx->ssl = ssl; + cctx->ctx = NULL; + if (ssl) { + cctx->poptions = &ssl->options; + cctx->pcert_flags = &ssl->cert->cert_flags; + } else { + cctx->poptions = NULL; + cctx->pcert_flags = NULL; + } +} void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) - { - cctx->ctx = ctx; - cctx->ssl = NULL; - if (ctx) - { - cctx->poptions = &ctx->options; - cctx->pcert_flags = &ctx->cert->cert_flags; - } - else - { - cctx->poptions = NULL; - cctx->pcert_flags = NULL; - } - } +{ + cctx->ctx = ctx; + cctx->ssl = NULL; + if (ctx) { + cctx->poptions = &ctx->options; + cctx->pcert_flags = &ctx->cert->cert_flags; + } else { + cctx->poptions = NULL; + cctx->pcert_flags = NULL; + } +}