Package: perdition Version: 2.1-2 Severity: wishlist Perdition 2.1 can not use or offer cipher suites with forward secrecy. Please include attached patch in the package or in the upstream mercurial.
The patch originates from Daniel Kahn Gillmor and was posted to the perdition mailing list in spring. I extended the patch to also support EC-DHE ciphers. It applies cleanly on 1.19rc5 as well as 2.1-2. Maybe the used EC curve should be made configurable. Regards Matthias
--- perdition-1.19~rc5.orig/perdition/options.c +++ perdition-1.19~rc5/perdition/options.c @@ -464,6 +464,8 @@ int options(int argc, char **argv, flag_ TAG_SSL_CA_ACCEPT_SELF_SIGNED, NULL, NULL}, {"ssl_cert_file", '\0', POPT_ARG_STRING, NULL, TAG_SSL_CERT_FILE, NULL, NULL}, + {"ssl_dh_params_file", '\0', POPT_ARG_STRING, NULL, + TAG_SSL_DH_PARAMS_FILE, NULL, NULL}, {"ssl_cert_accept_expired", '\0', POPT_ARG_NONE, NULL, TAG_SSL_CERT_ACCEPT_EXPIRED, NULL, NULL}, {"ssl_cert_accept_not_yet_valid", '\0', POPT_ARG_NONE, NULL, @@ -594,6 +596,7 @@ int options(int argc, char **argv, flag_ opt_i(&(opt.ssl_ca_accept_self_signed), DEFAULT_SSL_CA_ACCEPT_SELF_SIGNED, &i, 0, OPT_NOT_SET); opt_p(&(opt.ssl_cert_file), DEFAULT_SSL_CERT_FILE, &i, 0, OPT_NOT_SET); + opt_p(&(opt.ssl_dh_params_file), DEFAULT_SSL_DH_PARAMS_FILE, &i, 0, OPT_NOT_SET); opt_i(&(opt.ssl_cert_accept_expired), DEFAULT_SSL_CERT_ACCEPT_EXPIRED, &i, 0, OPT_NOT_SET); opt_i(&(opt.ssl_cert_accept_not_yet_valid), @@ -920,6 +923,14 @@ int options(int argc, char **argv, flag_ NO_SSL_OPT("ssl_cert_file"); #endif /* WITH_SSL_SUPPORT */ break; + case TAG_SSL_DH_PARAMS_FILE: +#ifdef WITH_SSL_SUPPORT + opt_p(&(opt.ssl_dh_params_file), optarg, &(opt.ssl_mask), + MASK_SSL_DH_PARAMS_FILE, f); +#else /* WITH_SSL_SUPPORT */ + NO_SSL_OPT("ssl_dh_params_file"); +#endif /* WITH_SSL_SUPPORT */ + break; case TAG_SSL_CERT_ACCEPT_EXPIRED: #ifdef WITH_SSL_SUPPORT opt_i(&(opt.ssl_cert_accept_expired), 1, &(opt.ssl_mask), @@ -1755,6 +1766,7 @@ void usage(int exit_status){ OPT_STR(RECOMMENDED_SSL_CA_FILE), OPT_STR(DEFAULT_SSL_CA_PATH), OPT_STR(DEFAULT_SSL_CERT_FILE), + OPT_STR(DEFAULT_SSL_DH_PARAMS_FILE), DEFAULT_SSL_CERT_VERIFY_DEPTH, OPT_STR(DEFAULT_SSL_KEY_FILE), OPT_STR(DEFAULT_SSL_LISTEN_CIPHERS), --- perdition-1.19~rc5.orig/perdition/options.h +++ perdition-1.19~rc5/perdition/options.h @@ -167,6 +167,7 @@ #define DEFAULT_SSL_CA_ACCEPT_SELF_SIGNED 0 #define DEFAULT_SSL_CERT_FILE PERDITION_SYSCONFDIR \ "/perdition.crt.pem" +#define DEFAULT_SSL_DH_PARAMS_FILE NULL #define DEFAULT_SSL_CERT_ACCEPT_EXPIRED 0 #define DEFAULT_SSL_CERT_ACCEPT_SELF_SIGNED 0 #define DEFAULT_SSL_CERT_ACCEPT_NOT_YET_VALID 0 @@ -236,6 +237,7 @@ typedef struct { char *ssl_ca_path; int ssl_ca_accept_self_signed; char *ssl_cert_file; + char *ssl_dh_params_file; int ssl_cert_accept_self_signed; int ssl_cert_accept_expired; int ssl_cert_accept_not_yet_valid; @@ -317,6 +319,7 @@ typedef struct { #define MASK_SSL_NO_CN_VERIFY (flag_t) 0x00004000 #define MASK_SSL_PASSPHRASE_FD (flag_t) 0x00008000 #define MASK_SSL_PASSPHRASE_FILE (flag_t) 0x00010000 +#define MASK_SSL_DH_PARAMS_FILE (flag_t) 0x00020000 #endif /* WITH_SSL_SUPPORT */ /* @@ -355,6 +358,7 @@ typedef struct { #define TAG_MANAGESIEVE_CAPABILITY (int) 155 #define TAG_POP_CAPABILITY (int) 156 #define TAG_TCP_KEEPALIVE (int) 157 +#define TAG_SSL_DH_PARAMS_FILE (int) 158 /*Flag values for options()*/ #define OPT_ERR (flag_t) 0x1 /*Print error to stderr, enable help*/ --- perdition-1.19~rc5.orig/perdition/ssl.c +++ perdition-1.19~rc5/perdition/ssl.c @@ -166,6 +166,11 @@ __perdition_ssl_passwd_cb(char *buf, int * concatenation of the various PEM-encoded CA Certificate * files, usually in certificate chain order. * Overrides ca_pat and ca_file + * dh_params_file: Diffie-Hellman parameters to use as a server + * May be NULL if not a server, if the DH params are + * appended to the cert file, or if EDH ciphersuites are + * not desired. Should be the path to a PEM file that + * contains DH PARAMETERS * ciphers: cipher list to use as per ciphers(1). * May be NULL in which case openssl's default is used. * flag: PERDITION_SSL_CLIENT or PERDITION_SSL_SERVER @@ -488,9 +493,14 @@ static long __perdition_verify_result(lo SSL_CTX *perdition_ssl_ctx(const char *ca_file, const char *ca_path, const char *cert, const char *privkey, - const char *ca_chain_file, const char *ciphers, flag_t flag) + const char *ca_chain_file, const char *dh_params_file, + const char *ciphers, flag_t flag) { SSL_CTX *ssl_ctx, *out = NULL; + const char *dhfile = NULL; + FILE* dhfp = NULL; + DH* dh = NULL; + EC_KEY* ecdh = NULL; const char *use_ca_file = NULL; const char *use_ca_path = NULL; struct passwd_cb_data pw_data; @@ -533,6 +543,65 @@ SSL_CTX *perdition_ssl_ctx(const char *c } /* + * Load the Diffie-Hellman parameters: + */ + if (flag & PERDITION_SSL_SERVER && + (dh_params_file || cert)) { + dhfile = (dh_params_file ? dh_params_file : cert); + dhfp = fopen(dhfile, "r"); + if (dhfp == NULL) { + if (dh_params_file) { + VANESSA_LOGGER_ERR_UNSAFE + ("Error opening Diffie-Hellman parameters file \"%s\"", dhfile); + SSL_CTX_free(ssl_ctx); + return NULL; + } else { + VANESSA_LOGGER_DEBUG_UNSAFE("could not open cert file for reading DH params \"%s\"", dhfile); + } + } else { + dh = PEM_read_DHparams(dhfp, NULL, NULL, NULL); + fclose(dhfp); + if (dh == NULL) { + if (dh_params_file) { + PERDITION_DEBUG_SSL_ERR("PEM_read_DHparams"); + VANESSA_LOGGER_ERR_UNSAFE + ("Error reading Diffie-Hellman parameters from file \"%s\"", dhfile); + SSL_CTX_free(ssl_ctx); + return NULL; + } else { + VANESSA_LOGGER_ERR_UNSAFE("could not read DH params from cert file \"%s\"", dhfile); + } + } else { + if (1 != SSL_CTX_set_tmp_dh(ssl_ctx, dh)) { + PERDITION_DEBUG_SSL_ERR("SSL_CTX_set_tmp_dh"); + VANESSA_LOGGER_ERR_UNSAFE + ("Error loading Diffie-Hellman parameters: \"%s\"", dhfile); + } else { + VANESSA_LOGGER_INFO_UNSAFE + ("Loaded Diffie-Hellman parameters: \"%s\"", dhfile); + } + DH_free(dh); + } + } + } + + + /* + * Load the EC Diffie-Hellman parameters: + */ + if (flag & PERDITION_SSL_SERVER) { + EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); + if (!ecdh) { + VANESSA_LOGGER_ERR("Error generating ECDH parameters"); + } else { + if (!SSL_CTX_set_tmp_ecdh (ssl_ctx, ecdh)) { + VANESSA_LOGGER_ERR("Error setting ECDH parameters"); + } + EC_KEY_free (ecdh); + } + } + + /* * Set the available ciphers */ if(ciphers && SSL_CTX_set_cipher_list(ssl_ctx, ciphers) < 0) { @@ -1154,7 +1223,7 @@ perdition_ssl_client_connection(io_t * i io_t *new_io; ssl_ctx = perdition_ssl_ctx(ca_file, ca_path, NULL, NULL, NULL, - ciphers, PERDITION_SSL_CLIENT); + NULL, ciphers, PERDITION_SSL_CLIENT); if (!ssl_ctx) { PERDITION_DEBUG_SSL_ERR("perdition_ssl_ctx"); io_destroy(io); --- perdition-1.19~rc5.orig/perdition/perdition.8 +++ perdition-1.19~rc5/perdition/perdition.8 @@ -571,6 +571,12 @@ Should be in PEM format. .br (default "/etc/perdition/perdition.crt.pem") .TP +.B \-\-ssl_dh_params_file FILENAME: +Diffie-Hellman parameters to use when offering EDH ciphersuites to clients. +Should be in PEM format. +.br +(default: look for DH parameters in ssl_cert_file) +.TP .B \-\-ssl_cert_accept_self_signed: Accept self-signed certificates. Used for SSL or TLS outgoing connections. --- perdition-1.19~rc5.orig/perdition/ssl.h +++ perdition-1.19~rc5/perdition/ssl.h @@ -62,6 +62,11 @@ * the root CA certificate. Such a file is simply the * concatenation of the various PEM-encoded CA Certificate * files, usually in certificate chain order. + * dh_params_file: Diffie-Hellman parameters to use as a server + * May be NULL if not a server, if the DH params are + * appended to the cert file, or if EDH ciphersuites are + * not desired. Should be the path to a PEM file that + * contains DH PARAMETERS * ciphers: cipher list to use as per ciphers(1). * May be NULL in which case openssl's default is used. * flag: PERDITION_SSL_CLIENT or PERDITION_SSL_SERVER @@ -79,7 +84,8 @@ SSL_CTX *perdition_ssl_ctx(const char *ca_file, const char *ca_path, const char *cert, const char *privkey, - const char *ca_chain_file, const char *ciphers, flag_t flag); + const char *ca_chain_file, const char *dh_params_file, + const char *ciphers, flag_t flag); /********************************************************************** --- perdition-1.19~rc5.orig/perdition/perdition.c +++ perdition-1.19~rc5/perdition/perdition.c @@ -509,8 +509,8 @@ int main (int argc, char **argv, char ** if(opt.ssl_mode & SSL_LISTEN_MASK) { ssl_ctx = perdition_ssl_ctx(opt.ssl_ca_file, opt.ssl_ca_path, opt.ssl_cert_file, opt.ssl_key_file, - opt.ssl_ca_chain_file, opt.ssl_listen_ciphers, - PERDITION_SSL_SERVER); + opt.ssl_ca_chain_file, opt.ssl_dh_params_file, + opt.ssl_listen_ciphers, PERDITION_SSL_SERVER); if(!ssl_ctx) { PERDITION_DEBUG_SSL_ERR("perdition_ssl_ctx"); VANESSA_LOGGER_ERR("Fatal error establishing SSL context for listening"); --- perdition-1.19~rc5.orig/etc/perdition/perdition.conf +++ perdition-1.19~rc5/etc/perdition/perdition.conf @@ -358,6 +358,11 @@ # (default "/etc/perdition/perdition.crt.pem") #ssl_cert_file /etc/perdition/perdition.crt.pem +# ssl_dh_params_file FILENAME: +# Diffie-Hellman parameters to use when offering EDH ciphersuites to clients. +# (default is to look for the DH params in the ssl_cert_file) +#ssl_dh_params_file /etc/perdition/perdition.crt.pem + # ssl_cert_accept_self_signed: # Accept self-signed certificates. #ssl_cert_accept_self_signed