From c1725bda3c9e6dc57cceedb2e867982ec2d4a509 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 12 Dec 2015 07:50:48 -0600 Subject: [PATCH] ssl: allow cipher list to be overridden (closes #67) --- doc/reference.conf | 3 +++ include/s_conf.h | 1 + include/sslproc.h | 4 ++-- libratbox/include/commio-ssl.h | 2 +- libratbox/include/rb_commio.h | 2 +- libratbox/src/gnutls.c | 4 +++- libratbox/src/mbedtls.c | 4 +++- libratbox/src/nossl.c | 2 +- libratbox/src/openssl.c | 8 +++++++- src/ircd.c | 2 +- src/newconf.c | 1 + src/s_conf.c | 7 +++---- src/sslproc.c | 22 ++++++++++++---------- ssld/ssld.c | 8 ++++++-- 14 files changed, 45 insertions(+), 25 deletions(-) diff --git a/doc/reference.conf b/doc/reference.conf index 6ac16171..6c3806e4 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -151,6 +151,9 @@ serverinfo { /* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 1024 */ ssl_dh_params = "etc/dh.pem"; + /* ssl_cipher_list: A list of ciphers, dependent on your TLS backend */ + #ssl_cipher_list = "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL"; + /* ssld_count: number of ssld processes you want to start, if you * have a really busy server, using N-1 where N is the number of * cpu/cpu cores you have might be useful. A number greater than one diff --git a/include/s_conf.h b/include/s_conf.h index 42df6ef0..9d7c7703 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -289,6 +289,7 @@ struct server_info char *ssl_ca_cert; char *ssl_cert; char *ssl_dh_params; + char *ssl_cipher_list; int ssld_count; }; diff --git a/include/sslproc.h b/include/sslproc.h index 6e7a3544..838bff75 100644 --- a/include/sslproc.h +++ b/include/sslproc.h @@ -28,11 +28,11 @@ struct _ssl_ctl; typedef struct _ssl_ctl ssl_ctl_t; void init_ssld(void); -int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params); +int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list); ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); void start_zlib_session(void *data); -void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params); +void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list); void ssld_decrement_clicount(ssl_ctl_t *ctl); int get_ssld_count(void); diff --git a/libratbox/include/commio-ssl.h b/libratbox/include/commio-ssl.h index 19e65c29..6e2bd69f 100644 --- a/libratbox/include/commio-ssl.h +++ b/libratbox/include/commio-ssl.h @@ -25,7 +25,7 @@ #ifndef _COMMIO_SSL_H #define _COMMIO_SSL_H -int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile); +int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list); int rb_init_ssl(void); int rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept); diff --git a/libratbox/include/rb_commio.h b/libratbox/include/rb_commio.h index fb83dd54..92e75950 100644 --- a/libratbox/include/rb_commio.h +++ b/libratbox/include/rb_commio.h @@ -134,7 +134,7 @@ ssize_t rb_writev(rb_fde_t *, struct rb_iovec *vector, int count); ssize_t rb_read(rb_fde_t *, void *buf, int count); int rb_pipe(rb_fde_t **, rb_fde_t **, const char *desc); -int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile); +int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list); int rb_ssl_listen(rb_fde_t *, int backlog, int defer_accept); int rb_listen(rb_fde_t *, int backlog, int defer_accept); diff --git a/libratbox/src/gnutls.c b/libratbox/src/gnutls.c index a2d4c3bf..492e52ee 100644 --- a/libratbox/src/gnutls.c +++ b/libratbox/src/gnutls.c @@ -327,7 +327,7 @@ rb_load_file_into_datum_t(const char *file) } int -rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) +rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { int ret; gnutls_datum_t *d_cert, *d_key; @@ -402,6 +402,8 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) else rb_lib_log("rb_setup_ssl_server: Unable to setup DH parameters"); } + + /* XXX integrate gnutls_priority_init() */ return 1; } diff --git a/libratbox/src/mbedtls.c b/libratbox/src/mbedtls.c index e819d983..6feab1bd 100644 --- a/libratbox/src/mbedtls.c +++ b/libratbox/src/mbedtls.c @@ -321,7 +321,7 @@ rb_init_ssl(void) } int -rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) +rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { int ret; @@ -374,6 +374,8 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) return 0; } + /* XXX support cipher lists when added to mbedtls */ + return 1; } diff --git a/libratbox/src/nossl.c b/libratbox/src/nossl.c index 91bdf8b0..6164bbe7 100644 --- a/libratbox/src/nossl.c +++ b/libratbox/src/nossl.c @@ -34,7 +34,7 @@ #include int -rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) +rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { errno = ENOSYS; return 0; diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index fbdeefdf..ab3e3400 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -397,7 +397,7 @@ rb_init_ssl(void) int -rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) +rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { DH *dh; unsigned long err; @@ -455,6 +455,12 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) dhfile, get_ssl_error(err)); } } + + if (cipher_list != NULL) + { + SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list); + } + return 1; } diff --git a/src/ircd.c b/src/ircd.c index 923180fc..9a82ae42 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -709,7 +709,7 @@ main(int argc, char *argv[]) if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL) { /* just do the rb_setup_ssl_server to validate the config */ - if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params)) + if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list)) { ilog(L_MAIN, "WARNING: Unable to setup SSL."); ssl_ok = 0; diff --git a/src/newconf.c b/src/newconf.c index 47cf6a23..a3e12272 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2252,6 +2252,7 @@ static struct ConfEntry conf_serverinfo_table[] = { "ssl_ca_cert", CF_QSTRING, NULL, 0, &ServerInfo.ssl_ca_cert }, { "ssl_cert", CF_QSTRING, NULL, 0, &ServerInfo.ssl_cert }, { "ssl_dh_params", CF_QSTRING, NULL, 0, &ServerInfo.ssl_dh_params }, + { "ssl_cipher_list", CF_QSTRING, NULL, 0, &ServerInfo.ssl_cipher_list }, { "ssld_count", CF_INT, NULL, 0, &ServerInfo.ssld_count }, { "default_max_clients",CF_INT, NULL, 0, &ServerInfo.default_max_clients }, diff --git a/src/s_conf.c b/src/s_conf.c index 96559c13..66960a3f 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -870,21 +870,20 @@ validate_conf(void) if(ServerInfo.ssld_count < 1) ServerInfo.ssld_count = 1; - if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params)) + if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list)) { ilog(L_MAIN, "WARNING: Unable to setup SSL."); ssl_ok = 0; } else { ssl_ok = 1; - send_new_ssl_certs(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params); + send_new_ssl_certs(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list); } if(ServerInfo.ssld_count > get_ssld_count()) { int start = ServerInfo.ssld_count - get_ssld_count(); /* start up additional ssld if needed */ - start_ssldaemon(start, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params); - + start_ssldaemon(start, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list); } /* General conf */ diff --git a/src/sslproc.c b/src/sslproc.c index 31d24fcf..0dc5a6e2 100644 --- a/src/sslproc.c +++ b/src/sslproc.c @@ -70,7 +70,8 @@ struct _ssl_ctl }; static void send_new_ssl_certs_one(ssl_ctl_t * ctl, const char *ssl_cert, - const char *ssl_private_key, const char *ssl_dh_params); + const char *ssl_private_key, const char *ssl_dh_params, + const char *ssl_cipher_list); static void send_init_prng(ssl_ctl_t * ctl, prng_seed_t seedtype, const char *path); static void send_certfp_method(ssl_ctl_t *ctl, int method); @@ -176,7 +177,7 @@ ssl_dead(ssl_ctl_t * ctl) rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */ ilog(L_MAIN, "ssld helper died - attempting to restart"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "ssld helper died - attempting to restart"); - start_ssldaemon(1, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params); + start_ssldaemon(1, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list); } static void @@ -204,12 +205,12 @@ restart_ssld_event(void *unused) int start = ServerInfo.ssld_count - get_ssld_count(); ilog(L_MAIN, "Attempting to restart ssld processes"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Attempt to restart ssld processes"); - start_ssldaemon(start, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params); + start_ssldaemon(start, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list); } } int -start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params) +start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list) { rb_fde_t *F1, *F2; rb_fde_t *P1, *P2; @@ -313,7 +314,8 @@ start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, co if(ssl_cert != NULL && ssl_private_key != NULL) send_new_ssl_certs_one(ctl, ssl_cert, ssl_private_key, - ssl_dh_params != NULL ? ssl_dh_params : ""); + ssl_dh_params != NULL ? ssl_dh_params : "", + ssl_cipher_list != NULL ? ssl_cipher_list : ""); } ssl_read_ctl(ctl->F, ctl); ssl_do_pipe(P2, ctl); @@ -613,7 +615,7 @@ ssl_cmd_write_queue(ssl_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, static void -send_new_ssl_certs_one(ssl_ctl_t * ctl, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params) +send_new_ssl_certs_one(ssl_ctl_t * ctl, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list) { size_t len; @@ -628,8 +630,8 @@ send_new_ssl_certs_one(ssl_ctl_t * ctl, const char *ssl_cert, const char *ssl_pr len, sizeof(tmpbuf)); return; } - len = rb_snprintf(tmpbuf, sizeof(tmpbuf), "K%c%s%c%s%c%s%c", nul, ssl_cert, nul, - ssl_private_key, nul, ssl_dh_params, nul); + len = rb_snprintf(tmpbuf, sizeof(tmpbuf), "K%c%s%c%s%c%s%c%s%c", nul, ssl_cert, nul, + ssl_private_key, nul, ssl_dh_params, nul, ssl_cipher_list, nul); ssl_cmd_write_queue(ctl, NULL, 0, tmpbuf, len); } @@ -672,7 +674,7 @@ send_certfp_method(ssl_ctl_t *ctl, int method) } void -send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params) +send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list) { rb_dlink_node *ptr; if(ssl_cert == NULL || ssl_private_key == NULL || ssl_dh_params == NULL) @@ -683,7 +685,7 @@ send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char RB_DLINK_FOREACH(ptr, ssl_daemons.head) { ssl_ctl_t *ctl = ptr->data; - send_new_ssl_certs_one(ctl, ssl_cert, ssl_private_key, ssl_dh_params); + send_new_ssl_certs_one(ctl, ssl_cert, ssl_private_key, ssl_dh_params, ssl_cipher_list); } } diff --git a/ssld/ssld.c b/ssld/ssld.c index e18ee77a..ee76be87 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -910,7 +910,7 @@ static void ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf) { char *buf; - char *cert, *key, *dhparam; + char *cert, *key, *dhparam, *cipher_list; buf = (char *) &ctl_buf->buf[2]; cert = buf; @@ -920,8 +920,12 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf) dhparam = buf; if(strlen(dhparam) == 0) dhparam = NULL; + buf += strlen(dhparam) + 1; + cipher_list = buf; + if(strlen(cipher_list) == 0) + cipher_list = NULL; - if(!rb_setup_ssl_server(cert, key, dhparam)) + if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list)) { const char *invalid = "I"; mod_cmd_write_queue(ctl, invalid, strlen(invalid));