diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2016-12-21 20:23:43 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2017-01-31 14:36:10 -0500 |
commit | 8960633dc71afefb2f7d7ea1c9a8e435c8df0e36 (patch) | |
tree | 11cb6f1a19ad253386f52b645730985b5cc4fe7a /src | |
parent | bdbea2aea8e95c11e5abc3a2eed76cc204f31b11 (diff) | |
download | lighttpd-git-8960633dc71afefb2f7d7ea1c9a8e435c8df0e36.tar.gz |
[mod_openssl] move openssl config into mod_openssl
move openssl data structures and config parsing into mod_openssl
Diffstat (limited to 'src')
-rw-r--r-- | src/base.h | 55 | ||||
-rw-r--r-- | src/configfile-glue.c | 2 | ||||
-rw-r--r-- | src/configfile.c | 154 | ||||
-rw-r--r-- | src/connections.c | 10 | ||||
-rw-r--r-- | src/mod_openssl.c | 879 | ||||
-rw-r--r-- | src/network.c | 527 | ||||
-rw-r--r-- | src/server.c | 26 |
7 files changed, 879 insertions, 774 deletions
@@ -27,21 +27,6 @@ #include "splaytree.h" #include "etag.h" - -#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H -# define USE_OPENSSL -# include <openssl/opensslconf.h> -# ifndef USE_OPENSSL_KERBEROS -# ifndef OPENSSL_NO_KRB5 -# define OPENSSL_NO_KRB5 -# endif -# endif -# include <openssl/ssl.h> -# if ! defined OPENSSL_NO_TLSEXT && ! defined SSL_CTRL_SET_TLSEXT_HOSTNAME -# define OPENSSL_NO_TLSEXT -# endif -#endif - #ifdef HAVE_FAM_H # include <fam.h> #endif @@ -275,28 +260,10 @@ typedef struct { unsigned short log_request_handling; unsigned short log_response_header; unsigned short log_condition_handling; - unsigned short log_ssl_noise; unsigned short log_timeouts; /* server wide */ - buffer *ssl_pemfile; - buffer *ssl_ca_file; - buffer *ssl_cipher_list; - buffer *ssl_dh_file; - buffer *ssl_ec_curve; - unsigned short ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */ - unsigned short ssl_empty_fragments; /* whether to not set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ - unsigned short ssl_use_sslv2; - unsigned short ssl_use_sslv3; - unsigned short ssl_verifyclient; - unsigned short ssl_verifyclient_enforce; - unsigned short ssl_verifyclient_depth; - buffer *ssl_verifyclient_username; - unsigned short ssl_verifyclient_export_cert; - unsigned short ssl_disable_client_renegotiation; - unsigned short ssl_read_ahead; - unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */ unsigned short defer_accept; unsigned short ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */ @@ -335,13 +302,6 @@ typedef struct { buffer *bsd_accept_filter; #endif -#ifdef USE_OPENSSL - SSL_CTX *ssl_ctx; /* not patched */ - /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ - EVP_PKEY *ssl_pemfile_pkey; - X509 *ssl_pemfile_x509; - STACK_OF(X509_NAME) *ssl_ca_file_cert_names; -#endif } specific_config; /* the order of the items should be the same as they are processed @@ -461,6 +421,7 @@ typedef struct connection { cond_cache_t *cond_cache; buffer *server_name; + buffer *tlsext_server_name; /* error-handler */ int error_handler_saved_status; @@ -470,13 +431,6 @@ typedef struct connection { int (* network_write)(struct server *srv, struct connection *con, chunkqueue *cq, off_t max_bytes); int (* network_read)(struct server *srv, struct connection *con, chunkqueue *cq, off_t max_bytes); -#ifdef USE_OPENSSL - SSL *ssl; -# ifndef OPENSSL_NO_TLSEXT - buffer *tlsext_server_name; -# endif - unsigned int renegotiations; /* count of SSL_CB_HANDSHAKE_START */ -#endif /* etag handling */ etag_flags_t etag_flags; @@ -577,12 +531,9 @@ typedef struct server_socket { int fde_ndx; unsigned short is_ssl; + unsigned short sidx; buffer *srv_token; - -#ifdef USE_OPENSSL - SSL_CTX *ssl_ctx; -#endif } server_socket; typedef struct { @@ -611,8 +562,6 @@ typedef struct server { int con_written; int con_closed; - int ssl_is_init; - int max_fds; /* max possible fds */ int cur_fds; /* currently used fds */ int want_fds; /* waiting fds */ diff --git a/src/configfile-glue.c b/src/configfile-glue.c index b6deabdf..b44da1ef 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -445,10 +445,8 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat default: break; } -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT } else if (!buffer_string_is_empty(con->tlsext_server_name)) { l = con->tlsext_server_name; -#endif } else { l = srv->empty_string; } diff --git a/src/configfile.c b/src/configfile.c index 784df88e..beea7552 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -109,18 +109,18 @@ static int config_insert(server *srv) { { "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */ { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */ { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */ - { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 29 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 29 */ { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 30 */ { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 31 */ { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 32 */ { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 33 */ { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 34 */ - { "debug.log-ssl-noise", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 35 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 35 */ { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 36 */ { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */ { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 38 */ - { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 39 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 39 */ { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 40 */ { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 41 */ @@ -129,8 +129,8 @@ static int config_insert(server *srv) { { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 44 */ { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 45 */ { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */ - { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ - { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 48 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 48 */ { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 49 */ { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 50 */ @@ -139,19 +139,19 @@ static int config_insert(server *srv) { { "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */ { "server.defer-accept", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 54 */ { "server.breakagelog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 55 */ - { "ssl.verifyclient.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 56 */ - { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 57 */ - { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 58 */ - { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 59 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 56 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 57 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 58 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 59 */ - { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 60 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 60 */ { "server.set-v6only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */ - { "ssl.use-sslv3", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 62 */ - { "ssl.dh-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 63 */ - { "ssl.ec-curve", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 64 */ - { "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 65 */ - { "ssl.honor-cipher-order", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 66 */ - { "ssl.empty-fragments", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 67 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 62 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 63 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 64 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 65 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 66 */ + { "unused-slot-moved-to-mod-openssl", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 67 */ { "server.upload-temp-file-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_SERVER }, /* 68 */ { "mimetype.xattr-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 69 */ { "server.listen-backlog", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 70 */ @@ -163,7 +163,6 @@ static int config_insert(server *srv) { { "server.stream-request-body", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 76 */ { "server.stream-response-body", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 77 */ { "server.max-request-field-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_SERVER }, /* 78 */ - { "ssl.read-ahead", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 79 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -219,14 +218,9 @@ static int config_insert(server *srv) { s->document_root = buffer_init(); s->mimetypes = array_init(); s->server_name = buffer_init(); - s->ssl_pemfile = buffer_init(); - s->ssl_ca_file = buffer_init(); s->error_handler = buffer_init(); s->error_handler_404 = buffer_init(); s->server_tag = buffer_init_string(PACKAGE_DESC); - s->ssl_cipher_list = buffer_init(); - s->ssl_dh_file = buffer_init(); - s->ssl_ec_curve = buffer_init(); s->errorfile_prefix = buffer_init(); #if defined(__FreeBSD__) || defined(__NetBSD__) \ || defined(__OpenBSD__) || defined(__DragonFly__) @@ -241,10 +235,6 @@ static int config_insert(server *srv) { s->max_request_size = 0; s->use_xattr = 0; s->ssl_enabled = 0; - s->ssl_honor_cipher_order = 1; - s->ssl_empty_fragments = 0; - s->ssl_use_sslv2 = 0; - s->ssl_use_sslv3 = 0; s->use_ipv6 = (i == 0) ? 0 : srv->config_storage[0]->use_ipv6; s->set_v6only = (i == 0) ? 1 : srv->config_storage[0]->set_v6only; s->defer_accept = (i == 0) ? 0 : srv->config_storage[0]->defer_accept; @@ -261,13 +251,6 @@ static int config_insert(server *srv) { s->global_kbytes_per_second = 0; s->global_bytes_per_second_cnt = 0; s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; - s->ssl_verifyclient = 0; - s->ssl_verifyclient_enforce = 1; - s->ssl_verifyclient_username = buffer_init(); - s->ssl_verifyclient_depth = 9; - s->ssl_verifyclient_export_cert = 0; - s->ssl_disable_client_renegotiation = 1; - s->ssl_read_ahead = (0 == i ? 1 : srv->config_storage[0]->ssl_read_ahead); s->listen_backlog = (0 == i ? 1024 : srv->config_storage[0]->listen_backlog); s->stream_request_body = 0; s->stream_response_body = 0; @@ -295,39 +278,39 @@ static int config_insert(server *srv) { cv[26].destination = &(s->kbytes_per_second); cv[27].destination = &(s->use_xattr); cv[28].destination = s->mimetypes; - cv[29].destination = s->ssl_pemfile; + /*cv[29].destination = s->unused;*/ cv[30].destination = &(s->ssl_enabled); cv[31].destination = &(s->log_file_not_found); cv[32].destination = &(s->log_request_handling); cv[33].destination = &(s->log_response_header); cv[34].destination = &(s->log_request_header); - cv[35].destination = &(s->log_ssl_noise); + /*cv[35].destination = &(s->unused);*/ cv[36].destination = &(s->allow_http11); - cv[39].destination = s->ssl_ca_file; + /*cv[39].destination = s->unused;*/ cv[41].destination = &(s->range_requests); - cv[47].destination = s->ssl_cipher_list; - cv[48].destination = &(s->ssl_use_sslv2); + /*cv[47].destination = s->unused;*/ + /*cv[48].destination = &(s->unused);*/ cv[49].destination = &(s->etag_use_inode); cv[50].destination = &(s->etag_use_mtime); cv[51].destination = &(s->etag_use_size); cv[53].destination = &(s->log_timeouts); cv[54].destination = &(s->defer_accept); - cv[56].destination = &(s->ssl_verifyclient); - cv[57].destination = &(s->ssl_verifyclient_enforce); - cv[58].destination = &(s->ssl_verifyclient_depth); - cv[59].destination = s->ssl_verifyclient_username; + /*cv[56].destination = &(s->unused);*/ + /*cv[57].destination = &(s->unused);*/ + /*cv[58].destination = &(s->unused);*/ + /*cv[59].destination = s->unused;*/ - cv[60].destination = &(s->ssl_verifyclient_export_cert); + /*cv[60].destination = &(s->unused);*/ cv[61].destination = &(s->set_v6only); - cv[62].destination = &(s->ssl_use_sslv3); - cv[63].destination = s->ssl_dh_file; - cv[64].destination = s->ssl_ec_curve; - cv[65].destination = &(s->ssl_disable_client_renegotiation); - cv[66].destination = &(s->ssl_honor_cipher_order); - cv[67].destination = &(s->ssl_empty_fragments); + /*cv[62].destination = &(s->unused);*/ + /*cv[63].destination = s->unused;*/ + /*cv[64].destination = s->unused;*/ + /*cv[65].destination = &(s->unused);*/ + /*cv[66].destination = &(s->unused);*/ + /*cv[67].destination = &(s->unused);*/ cv[70].destination = &(s->listen_backlog); cv[71].destination = s->error_handler_404; #if defined(__FreeBSD__) || defined(__NetBSD__) \ @@ -336,7 +319,6 @@ static int config_insert(server *srv) { #endif cv[76].destination = &(s->stream_request_body); cv[77].destination = &(s->stream_response_body); - cv[79].destination = &(s->ssl_read_ahead); srv->config_storage[i] = s; @@ -351,7 +333,7 @@ static int config_insert(server *srv) { s->stream_response_body |= FDEVENT_STREAM_RESPONSE; } -#ifndef USE_OPENSSL +#if !(defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H) if (s->ssl_enabled) { log_error_write(srv, __FILE__, __LINE__, "s", "ssl support is missing, recompile with --with-openssl"); @@ -549,7 +531,6 @@ int config_setup_connection(server *srv, connection *con) { PATCH(log_request_handling); PATCH(log_condition_handling); PATCH(log_file_not_found); - PATCH(log_ssl_noise); PATCH(log_timeouts); PATCH(range_requests); @@ -558,36 +539,10 @@ int config_setup_connection(server *srv, connection *con) { PATCH(stream_request_body); PATCH(stream_response_body); - PATCH(ssl_enabled); - - PATCH(ssl_pemfile); -#ifdef USE_OPENSSL - PATCH(ssl_pemfile_x509); - PATCH(ssl_pemfile_pkey); -#endif - PATCH(ssl_ca_file); -#ifdef USE_OPENSSL - PATCH(ssl_ca_file_cert_names); -#endif - PATCH(ssl_cipher_list); - PATCH(ssl_dh_file); - PATCH(ssl_ec_curve); - PATCH(ssl_honor_cipher_order); - PATCH(ssl_empty_fragments); - PATCH(ssl_use_sslv2); - PATCH(ssl_use_sslv3); PATCH(etag_use_inode); PATCH(etag_use_mtime); PATCH(etag_use_size); - PATCH(ssl_verifyclient); - PATCH(ssl_verifyclient_enforce); - PATCH(ssl_verifyclient_depth); - PATCH(ssl_verifyclient_username); - PATCH(ssl_verifyclient_export_cert); - PATCH(ssl_disable_client_renegotiation); - PATCH(ssl_read_ahead); - return 0; } @@ -636,33 +591,6 @@ int config_patch_connection(server *srv, connection *con) { PATCH(etag_use_mtime); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) { PATCH(etag_use_size); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) { - PATCH(ssl_pemfile); -#ifdef USE_OPENSSL - PATCH(ssl_pemfile_x509); - PATCH(ssl_pemfile_pkey); -#endif - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { - PATCH(ssl_ca_file); -#ifdef USE_OPENSSL - PATCH(ssl_ca_file_cert_names); -#endif - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) { - PATCH(ssl_honor_cipher_order); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) { - PATCH(ssl_empty_fragments); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) { - PATCH(ssl_use_sslv2); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) { - PATCH(ssl_use_sslv3); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) { - PATCH(ssl_cipher_list); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) { - PATCH(ssl_enabled); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) { - PATCH(ssl_dh_file); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) { - PATCH(ssl_ec_curve); #ifdef HAVE_LSTAT } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) { PATCH(follow_symlink); @@ -687,8 +615,6 @@ int config_patch_connection(server *srv, connection *con) { PATCH(log_condition_handling); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) { PATCH(log_file_not_found); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) { - PATCH(log_ssl_noise); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) { PATCH(log_timeouts); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) { @@ -703,20 +629,6 @@ int config_patch_connection(server *srv, connection *con) { PATCH(global_kbytes_per_second); PATCH(global_bytes_per_second_cnt); con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) { - PATCH(ssl_verifyclient); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) { - PATCH(ssl_verifyclient_enforce); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) { - PATCH(ssl_verifyclient_depth); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) { - PATCH(ssl_verifyclient_username); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { - PATCH(ssl_verifyclient_export_cert); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) { - PATCH(ssl_disable_client_renegotiation); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.read-ahead"))) { - PATCH(ssl_read_ahead); } } } diff --git a/src/connections.c b/src/connections.c index c025761b..ce5fdffb 100644 --- a/src/connections.c +++ b/src/connections.c @@ -545,9 +545,7 @@ connection *connection_init(server *srv) { CLEAN(server_name); CLEAN(dst_addr_buf); -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT CLEAN(tlsext_server_name); -#endif #undef CLEAN con->write_queue = chunkqueue_init(); @@ -611,9 +609,7 @@ void connections_free(server *srv) { CLEAN(server_name); CLEAN(dst_addr_buf); -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT CLEAN(tlsext_server_name); -#endif #undef CLEAN free(con->plugin_ctx); free(con->cond_cache); @@ -662,9 +658,7 @@ int connection_reset(server *srv, connection *con) { CLEAN(parse_request); CLEAN(server_name); -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT CLEAN(tlsext_server_name); -#endif #undef CLEAN #define CLEAN(x) \ @@ -986,6 +980,10 @@ connection *connection_accepted(server *srv, server_socket *srv_socket, sock_add buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr))); con->srv_socket = srv_socket; + config_cond_cache_reset(srv, con); + con->conditional_is_valid[COMP_SERVER_SOCKET] = 1; + con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1; + if (-1 == fdevent_fcntl_set_nb_cloexec_sock(srv->ev, con->fd)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); connection_close(srv, con); diff --git a/src/mod_openssl.c b/src/mod_openssl.c index c4730a3a..34908ccb 100644 --- a/src/mod_openssl.c +++ b/src/mod_openssl.c @@ -13,23 +13,68 @@ #include <openssl/ssl.h> #include <openssl/bn.h> #include <openssl/err.h> +#include <openssl/rand.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif + +#if ! defined OPENSSL_NO_TLSEXT && ! defined SSL_CTRL_SET_TLSEXT_HOSTNAME +#define OPENSSL_NO_TLSEXT +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH +#include <openssl/ecdh.h> +#endif +#endif #include "base.h" #include "log.h" #include "plugin.h" typedef struct { - int dummy; + SSL_CTX *ssl_ctx; /* not patched */ + /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */ + EVP_PKEY *ssl_pemfile_pkey; + X509 *ssl_pemfile_x509; + STACK_OF(X509_NAME) *ssl_ca_file_cert_names; + + unsigned short ssl_verifyclient; + unsigned short ssl_verifyclient_enforce; + unsigned short ssl_verifyclient_depth; + unsigned short ssl_verifyclient_export_cert; + buffer *ssl_verifyclient_username; + + unsigned short ssl_disable_client_renegotiation; + unsigned short ssl_read_ahead; + unsigned short ssl_log_noise; + + /*(used only during startup; not patched)*/ + unsigned short ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */ + unsigned short ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */ + unsigned short ssl_empty_fragments; /* whether to not set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ + unsigned short ssl_use_sslv2; + unsigned short ssl_use_sslv3; + buffer *ssl_pemfile; + buffer *ssl_ca_file; + buffer *ssl_cipher_list; + buffer *ssl_dh_file; + buffer *ssl_ec_curve; } plugin_config; typedef struct { PLUGIN_DATA; plugin_config **config_storage; - plugin_config conf; } plugin_data; +static int ssl_is_init; +/* need assigned p->id for deep access of module handler_ctx for connection + * i.e. handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; */ +static plugin_data *plugin_data_singleton; + typedef struct { SSL *ssl; + connection *con; buffer *tlsext_server_name; unsigned int renegotiations; /* count of SSL_CB_HANDSHAKE_START */ int request_env_patched; @@ -49,6 +94,7 @@ handler_ctx_init (void) static void handler_ctx_free (handler_ctx *hctx) { + if (hctx->ssl) SSL_free(hctx->ssl); buffer_free(hctx->tlsext_server_name); free(hctx); } @@ -56,7 +102,8 @@ handler_ctx_free (handler_ctx *hctx) INIT_FUNC(mod_openssl_init) { - return calloc(1, sizeof(plugin_data)); + plugin_data_singleton = (plugin_data *)calloc(1, sizeof(plugin_data)); + return plugin_data_singleton; } @@ -67,7 +114,7 @@ FREE_FUNC(mod_openssl_free) if (p->config_storage) { for (size_t i = 0; i < srv->config_context->used; ++i) { - specific_config *s = srv->config_storage[i]; + plugin_config *s = p->config_storage[i]; buffer_free(s->ssl_pemfile); buffer_free(s->ssl_ca_file); buffer_free(s->ssl_cipher_list); @@ -89,9 +136,7 @@ FREE_FUNC(mod_openssl_free) free(p->config_storage); } - free(p); - - if (srv->ssl_is_init) { + if (ssl_is_init) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L \ && !defined(LIBRESSL_VERSION_NUMBER) /*(OpenSSL libraries handle thread init and deinit) @@ -108,26 +153,751 @@ FREE_FUNC(mod_openssl_free) #endif } + free(p); + return HANDLER_GO_ON; } +static void +ssl_info_callback (const SSL *ssl, int where, int ret) +{ + UNUSED(ret); + + if (0 != (where & SSL_CB_HANDSHAKE_START)) { + handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); + ++hctx->renegotiations; + } +} + + +#ifndef OPENSSL_NO_TLSEXT +static int mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *hctx); + +static int +network_ssl_servername_callback (SSL *ssl, int *al, server *srv) +{ + const char *servername; + handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl); + connection *con = hctx->con; + UNUSED(al); + + buffer_copy_string(con->uri.scheme, "https"); + + servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (NULL == servername) { +#if 0 + /* this "error" just means the client didn't support it */ + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + "failed to get TLS server name"); +#endif + return SSL_TLSEXT_ERR_NOACK; + } + if (NULL == hctx->tlsext_server_name) { + hctx->tlsext_server_name = buffer_init(); + } + buffer_copy_string(hctx->tlsext_server_name, servername); + buffer_to_lower(hctx->tlsext_server_name); + buffer_copy_buffer(con->tlsext_server_name, hctx->tlsext_server_name); + + /* Sometimes this is still set, confusing COMP_HTTP_HOST */ + buffer_reset(con->uri.authority); + + con->conditional_is_valid[COMP_HTTP_SCHEME] = 1; + con->conditional_is_valid[COMP_HTTP_HOST] = 1; + mod_openssl_patch_connection(srv, con, hctx); + + if (NULL == hctx->conf.ssl_pemfile_x509 + || NULL == hctx->conf.ssl_pemfile_pkey) { + /* x509/pkey available <=> pemfile was set <=> pemfile got patched: + * so this should never happen, unless you nest $SERVER["socket"] */ + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + "no certificate/private key for TLS server name", + hctx->tlsext_server_name); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + /* first set certificate! + * setting private key checks whether certificate matches it */ + if (!SSL_use_certificate(ssl, hctx->conf.ssl_pemfile_x509)) { + log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", + "failed to set certificate for TLS server name", + hctx->tlsext_server_name, + ERR_error_string(ERR_get_error(), NULL)); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + if (!SSL_use_PrivateKey(ssl, hctx->conf.ssl_pemfile_pkey)) { + log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", + "failed to set private key for TLS server name", + hctx->tlsext_server_name, + ERR_error_string(ERR_get_error(), NULL)); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + if (hctx->conf.ssl_verifyclient) { + int mode; + if (NULL == hctx->conf.ssl_ca_file_cert_names) { + log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", + "can't verify client without ssl.ca-file " + "for TLS server name", hctx->tlsext_server_name, + ERR_error_string(ERR_get_error(), NULL)); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + SSL_set_client_CA_list( + ssl, SSL_dup_CA_list(hctx->conf.ssl_ca_file_cert_names)); + /* forcing verification here is really not that useful + * -- a client could just connect without SNI */ + mode = SSL_VERIFY_PEER; + if (hctx->conf.ssl_verifyclient_enforce) { + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } + SSL_set_verify(ssl, mode, NULL); + SSL_set_verify_depth(ssl, hctx->conf.ssl_verifyclient_depth); + } else { + SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); + } + + return SSL_TLSEXT_ERR_OK; +} +#endif + + +static X509 * +x509_load_pem_file (server *srv, const char *file) +{ + BIO *in; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (NULL == in) { + log_error_write(srv, __FILE__, __LINE__, "S", + "SSL: BIO_new(BIO_s_file()) failed"); + goto error; + } + + if (BIO_read_filename(in,file) <= 0) { + log_error_write(srv, __FILE__, __LINE__, "SSS", + "SSL: BIO_read_filename('", file,"') failed"); + goto error; + } + + x = PEM_read_bio_X509(in, NULL, NULL, NULL); + if (NULL == x) { + log_error_write(srv, __FILE__, __LINE__, "SSS", + "SSL: couldn't read X509 certificate from '", file,"'"); + goto error; + } + + BIO_free(in); + return x; + +error: + if (NULL != in) BIO_free(in); + return NULL; +} + + +static EVP_PKEY * +evp_pkey_load_pem_file (server *srv, const char *file) +{ + BIO *in; + EVP_PKEY *x = NULL; + + in = BIO_new(BIO_s_file()); + if (NULL == in) { + log_error_write(srv, __FILE__, __LINE__, "s", + "SSL: BIO_new(BIO_s_file()) failed"); + goto error; + } + + if (BIO_read_filename(in,file) <= 0) { + log_error_write(srv, __FILE__, __LINE__, "SSS", + "SSL: BIO_read_filename('", file,"') failed"); + goto error; + } + + x = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (NULL == x) { + log_error_write(srv, __FILE__, __LINE__, "SSS", + "SSL: couldn't read private key from '", file,"'"); + goto error; + } + + BIO_free(in); + return x; + +error: + if (NULL != in) BIO_free(in); + return NULL; +} + + +static int +network_openssl_load_pemfile (server *srv, plugin_config *s, size_t ndx) +{ + #ifdef OPENSSL_NO_TLSEXT + data_config *dc = (data_config *)srv->config_context->data[ndx]; + if ((ndx > 0 && (COMP_SERVER_SOCKET != dc->comp + || dc->cond != CONFIG_COND_EQ)) || !s->ssl_enabled) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + "ssl.pemfile only works in SSL socket binding context " + "as openssl version does not support TLS extensions"); + return -1; + } + #else + UNUSED(ndx); + #endif + + s->ssl_pemfile_x509 = x509_load_pem_file(srv, s->ssl_pemfile->ptr); + if (NULL == s->ssl_pemfile_x509) return -1; + s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr); + if (NULL == s->ssl_pemfile_pkey) return -1; + + if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) { + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", + "Private key does not match the certificate public key," + " reason:", ERR_error_string(ERR_get_error(), NULL), + s->ssl_pemfile); + return -1; + } + + return 0; +} + + +static int +network_init_ssl (server *srv, void *p_d) +{ + plugin_data *p = p_d; + #if OPENSSL_VERSION_NUMBER >= 0x0090800fL + #ifndef OPENSSL_NO_ECDH + EC_KEY *ecdh; + int nid; + #endif + #endif + + #ifndef OPENSSL_NO_DH + DH *dh; + #endif + BIO *bio; + + /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) + * -----BEGIN DH PARAMETERS----- + * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y + * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 + * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV + * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 + * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR + * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= + * -----END DH PARAMETERS----- + */ + + static const unsigned char dh1024_p[]={ + 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, + 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, + 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, + 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, + 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, + 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, + 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, + 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, + 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, + 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, + 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, + }; + + static const unsigned char dh1024_g[]={ + 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, + 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, + 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, + 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, + 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, + 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, + 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, + 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, + 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, + 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, + 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, + }; + + /* load SSL certificates */ + for (size_t i = 0; i < srv->config_context->used; ++i) { + plugin_config *s = p->config_storage[i]; + #ifndef SSL_OP_NO_COMPRESSION + #define SSL_OP_NO_COMPRESSION 0 + #endif + #ifndef SSL_MODE_RELEASE_BUFFERS /* OpenSSL >= 1.0.0 */ + #define SSL_MODE_RELEASE_BUFFERS 0 + #endif + long ssloptions = SSL_OP_ALL + | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + | SSL_OP_NO_COMPRESSION; + + if (s->ssl_enabled) { + if (buffer_string_is_empty(s->ssl_pemfile)) { + /* PEM file is require */ + log_error_write(srv, __FILE__, __LINE__, "s", + "ssl.pemfile has to be set"); + return -1; + } + } + + if (buffer_string_is_empty(s->ssl_pemfile) + && buffer_string_is_empty(s->ssl_ca_file)) continue; + + if (ssl_is_init == 0) { + #if OPENSSL_VERSION_NUMBER >= 0x10100000L \ + && !defined(LIBRESSL_VERSION_NUMBER) + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS + |OPENSSL_INIT_LOAD_CRYPTO_STRINGS,NULL); + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS + |OPENSSL_INIT_ADD_ALL_DIGESTS + |OPENSSL_INIT_LOAD_CONFIG, NULL); + #else + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + #endif + ssl_is_init = 1; + + if (0 == RAND_status()) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + "not enough entropy in the pool"); + return -1; + } + } + + if (!buffer_string_is_empty(s->ssl_pemfile)) { + #ifdef OPENSSL_NO_TLSEXT + data_config *dc = (data_config *)srv->config_context->data[i]; + if (COMP_HTTP_HOST == dc->comp) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + "can't use ssl.pemfile with $HTTP[\"host\"], " + "openssl version does not support TLS " + "extensions"); + return -1; + } + #endif + if (network_openssl_load_pemfile(srv, s, i)) return -1; + } + + + if (!buffer_string_is_empty(s->ssl_ca_file)) { + s->ssl_ca_file_cert_names = + SSL_load_client_CA_file(s->ssl_ca_file->ptr); + if (NULL == s->ssl_ca_file_cert_names) { + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + ERR_error_string(ERR_get_error(), NULL), + s->ssl_ca_file); + } + } + + if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue; + + if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + /* completely useless identifier; + * required for client cert verification to work with sessions */ + if (0 == SSL_CTX_set_session_id_context( + s->ssl_ctx,(const unsigned char*)CONST_STR_LEN("lighttpd"))){ + log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:", + "failed to set session context", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + if (s->ssl_empty_fragments) { + #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + #else + ssloptions &= ~0x00000800L; /* hardcode constant */ + log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:", + "'insert empty fragments' not supported by the " + "openssl version used to compile lighttpd with"); + #endif + } + + SSL_CTX_set_options(s->ssl_ctx, ssloptions); + SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback); + + if (!s->ssl_use_sslv2 && 0 != SSL_OP_NO_SSLv2) { + /* disable SSLv2 */ + if ((SSL_OP_NO_SSLv2 + & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) + != SSL_OP_NO_SSLv2) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + } + + if (!s->ssl_use_sslv3 && 0 != SSL_OP_NO_SSLv3) { + /* disable SSLv3 */ + if ((SSL_OP_NO_SSLv3 + & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) + != SSL_OP_NO_SSLv3) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + } + + if (!buffer_string_is_empty(s->ssl_cipher_list)) { + /* Disable support for low encryption ciphers */ + if (SSL_CTX_set_cipher_list(s->ssl_ctx,s->ssl_cipher_list->ptr)!=1){ + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + if (s->ssl_honor_cipher_order) { + SSL_CTX_set_options(s->ssl_ctx,SSL_OP_CIPHER_SERVER_PREFERENCE); + } + } + + #ifndef OPENSSL_NO_DH + /* Support for Diffie-Hellman key exchange */ + if (!buffer_string_is_empty(s->ssl_dh_file)) { + /* DH parameters from file */ + bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r"); + if (bio == NULL) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "SSL: Unable to open file", + s->ssl_dh_file->ptr); + return -1; + } + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (dh == NULL) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "SSL: PEM_read_bio_DHparams failed", + s->ssl_dh_file->ptr); + return -1; + } + } else { + BIGNUM *dh_p, *dh_g; + /* Default DH parameters from RFC5114 */ + dh = DH_new(); + if (dh == NULL) { + log_error_write(srv, __FILE__, __LINE__, "s", + "SSL: DH_new () failed"); + return -1; + } + dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL); + dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL); + if ((dh_p == NULL) || (dh_g == NULL)) { + DH_free(dh); + log_error_write(srv, __FILE__, __LINE__, "s", + "SSL: BN_bin2bn () failed"); + return -1; + } + #if OPENSSL_VERSION_NUMBER < 0x10100000L \ + || defined(LIBRESSL_VERSION_NUMBER) + dh->p = dh_p; + dh->g = dh_g; + dh->length = 160; + #else + DH_set0_pqg(dh, dh_p, NULL, dh_g); + DH_set_length(dh, 160); + #endif + } + SSL_CTX_set_tmp_dh(s->ssl_ctx,dh); + SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE); + DH_free(dh); + #else + if (!buffer_string_is_empty(s->ssl_dh_file)) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "SSL: openssl compiled without DH support, " + "can't load parameters from", s->ssl_dh_file->ptr); + } + #endif + + #if OPENSSL_VERSION_NUMBER >= 0x0090800fL + #ifndef OPENSSL_NO_ECDH + /* Support for Elliptic-Curve Diffie-Hellman key exchange */ + if (!buffer_string_is_empty(s->ssl_ec_curve)) { + /* OpenSSL only supports the "named curves" + * from RFC 4492, section 5.1.1. */ + nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr); + if (nid == 0) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "SSL: Unknown curve name", + s->ssl_ec_curve->ptr); + return -1; + } + } else { + /* Default curve */ + nid = OBJ_sn2nid("prime256v1"); + } + ecdh = EC_KEY_new_by_curve_name(nid); + if (ecdh == NULL) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "SSL: Unable to create curve", + s->ssl_ec_curve->ptr); + return -1; + } + SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh); + SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); + #endif + #endif + + /* load all ssl.ca-files specified in the config into each SSL_CTX + * to be prepared for SNI */ + for (size_t j = 0; j < srv->config_context->used; ++j) { + plugin_config *s1 = p->config_storage[j]; + + if (!buffer_string_is_empty(s1->ssl_ca_file)) { + if (1 != SSL_CTX_load_verify_locations( + s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) { + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + ERR_error_string(ERR_get_error(), NULL), + s1->ssl_ca_file); + return -1; + } + } + } + + if (s->ssl_verifyclient) { + int mode; + if (NULL == s->ssl_ca_file_cert_names) { + log_error_write(srv, __FILE__, __LINE__, "s", + "SSL: You specified ssl.verifyclient.activate " + "but no ca_file"); + return -1; + } + SSL_CTX_set_client_CA_list( + s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names)); + mode = SSL_VERIFY_PEER; + if (s->ssl_verifyclient_enforce) { + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } + SSL_CTX_set_verify(s->ssl_ctx, mode, NULL); + SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth); + } + + if (1 != SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509)) { + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + ERR_error_string(ERR_get_error(), NULL), + s->ssl_pemfile); + return -1; + } + + if (1 != SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey)) { + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + ERR_error_string(ERR_get_error(), NULL), + s->ssl_pemfile); + return -1; + } + + if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", + "Private key does not match the certificate public " + "key, reason:", + ERR_error_string(ERR_get_error(), NULL), + s->ssl_pemfile); + return -1; + } + SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead); + SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) + | SSL_MODE_ENABLE_PARTIAL_WRITE + | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + | SSL_MODE_RELEASE_BUFFERS); + + #ifndef OPENSSL_NO_TLSEXT + if (!SSL_CTX_set_tlsext_servername_callback( + s->ssl_ctx, network_ssl_servername_callback) || + !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + "failed to initialize TLS servername callback, " + "openssl library does not support TLS servername " + "extension"); + return -1; + } + #endif + } + + return 0; +} + + SETDEFAULTS_FUNC(mod_openssl_set_defaults) { - UNUSED(srv); - UNUSED(p_d); + plugin_data *p = p_d; + config_values_t cv[] = { + { "debug.log-ssl-noise", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ + { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ + { "ssl.dh-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ + { "ssl.ec-curve", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ + { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */ + { "ssl.honor-cipher-order", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */ + { "ssl.empty-fragments", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ + { "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ + { "ssl.read-ahead", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ + { "ssl.verifyclient.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 11 */ + { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ + { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */ + { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */ + { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */ + { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 16 */ + { "ssl.use-sslv3", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 17 */ + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } + }; + + if (!p) return HANDLER_ERROR; + + p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *)); + + for (size_t i = 0; i < srv->config_context->used; i++) { + data_config const* config = (data_config const*)srv->config_context->data[i]; + plugin_config *s = calloc(1, sizeof(plugin_config)); + + s->ssl_enabled = 0; + s->ssl_pemfile = buffer_init(); + s->ssl_ca_file = buffer_init(); + s->ssl_cipher_list = buffer_init(); + s->ssl_dh_file = buffer_init(); + s->ssl_ec_curve = buffer_init(); + s->ssl_honor_cipher_order = 1; + s->ssl_empty_fragments = 0; + s->ssl_use_sslv2 = 0; + s->ssl_use_sslv3 = 0; + s->ssl_verifyclient = 0; + s->ssl_verifyclient_enforce = 1; + s->ssl_verifyclient_username = buffer_init(); + s->ssl_verifyclient_depth = 9; + s->ssl_verifyclient_export_cert = 0; + s->ssl_disable_client_renegotiation = 1; + s->ssl_read_ahead = (0 == i ? 1 : p->config_storage[0]->ssl_read_ahead); + + cv[0].destination = &(s->ssl_log_noise); + cv[1].destination = &(s->ssl_enabled); + cv[2].destination = s->ssl_pemfile; + cv[3].destination = s->ssl_ca_file; + cv[4].destination = s->ssl_dh_file; + cv[5].destination = s->ssl_ec_curve; + cv[6].destination = s->ssl_cipher_list; + cv[7].destination = &(s->ssl_honor_cipher_order); + cv[8].destination = &(s->ssl_empty_fragments); + cv[9].destination = &(s->ssl_disable_client_renegotiation); + cv[10].destination = &(s->ssl_read_ahead); + cv[11].destination = &(s->ssl_verifyclient); + cv[12].destination = &(s->ssl_verifyclient_enforce); + cv[13].destination = &(s->ssl_verifyclient_depth); + cv[14].destination = s->ssl_verifyclient_username; + cv[15].destination = &(s->ssl_verifyclient_export_cert); + cv[16].destination = &(s->ssl_use_sslv2); + cv[17].destination = &(s->ssl_use_sslv3); + + p->config_storage[i] = s; + + if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { + return HANDLER_ERROR; + } + } + + if (0 != network_init_ssl(srv, p)) return HANDLER_ERROR; + return HANDLER_GO_ON; } #define PATCH(x) \ - p->conf.x = s->x; + hctx->conf.x = s->x; static int -mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *p) +mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *hctx) { - UNUSED(srv); - UNUSED(con); - UNUSED(p); + plugin_config *s = plugin_data_singleton->config_storage[0]; + + /*PATCH(ssl_enabled);*//*(not patched)*/ + /*PATCH(ssl_pemfile);*//*(not patched)*/ + PATCH(ssl_pemfile_x509); + PATCH(ssl_pemfile_pkey); + /*PATCH(ssl_ca_file);*//*(not patched)*/ + PATCH(ssl_ca_file_cert_names); + /*PATCH(ssl_cipher_list);*//*(not patched)*/ + /*PATCH(ssl_dh_file);*//*(not patched)*/ + /*PATCH(ssl_ec_curve);*//*(not patched)*/ + /*PATCH(ssl_honor_cipher_order);*//*(not patched)*/ + /*PATCH(ssl_empty_fragments);*//*(not patched)*/ + /*PATCH(ssl_use_sslv2);*//*(not patched)*/ + /*PATCH(ssl_use_sslv3);*//*(not patched)*/ + + PATCH(ssl_verifyclient); + PATCH(ssl_verifyclient_enforce); + PATCH(ssl_verifyclient_depth); + PATCH(ssl_verifyclient_username); + PATCH(ssl_verifyclient_export_cert); + PATCH(ssl_disable_client_renegotiation); + PATCH(ssl_read_ahead); + + PATCH(ssl_log_noise); + + /* skip the first, the global context */ + for (size_t i = 1; i < srv->config_context->used; ++i) { + data_config *dc = (data_config *)srv->config_context->data[i]; + s = plugin_data_singleton->config_storage[i]; + + /* condition didn't match */ + if (!config_check_cond(srv, con, dc)) continue; + + /* merge config */ + for (size_t j = 0; j < dc->value->used; ++j) { + data_unset *du = dc->value->data[j]; + + if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) { + /*PATCH(ssl_pemfile);*//*(not patched)*/ + PATCH(ssl_pemfile_x509); + PATCH(ssl_pemfile_pkey); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { + /*PATCH(ssl_ca_file);*//*(not patched)*/ + PATCH(ssl_ca_file_cert_names); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) { + PATCH(ssl_verifyclient); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) { + PATCH(ssl_verifyclient_enforce); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) { + PATCH(ssl_verifyclient_depth); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) { + PATCH(ssl_verifyclient_username); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { + PATCH(ssl_verifyclient_export_cert); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) { + PATCH(ssl_disable_client_renegotiation); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.read-ahead"))) { + PATCH(ssl_read_ahead); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) { + PATCH(ssl_log_noise); + #if 0 /*(not patched)*/ + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) { + PATCH(ssl_honor_cipher_order); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) { + PATCH(ssl_empty_fragments); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) { + PATCH(ssl_use_sslv2); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) { + PATCH(ssl_use_sslv3); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) { + PATCH(ssl_cipher_list); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) { + PATCH(ssl_dh_file); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) { + PATCH(ssl_ec_curve); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) { + PATCH(ssl_enabled); + #endif + } + } + } + return 0; } #undef PATCH @@ -215,7 +985,8 @@ connection_write_cq_ssl (server *srv, connection *con, * - IE * - wget * if keep-alive is disabled */ - SSL *ssl = con->ssl; + handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; + SSL *ssl = hctx->ssl; if (con->keep_alive == 0) { SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); @@ -242,8 +1013,8 @@ connection_write_cq_ssl (server *srv, connection *con, ERR_clear_error(); r = SSL_write(ssl, data, data_len); - if (con->renegotiations > 1 - && con->conf.ssl_disable_client_renegotiation) { + if (hctx->renegotiations > 1 + && hctx->conf.ssl_disable_client_renegotiation) { log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection"); return -1; @@ -319,6 +1090,7 @@ static int connection_read_cq_ssl (server *srv, connection *con, chunkqueue *cq, off_t max_bytes) { + handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; int r, ssl_err, len; char *mem = NULL; size_t mem_len = 0; @@ -330,13 +1102,13 @@ connection_read_cq_ssl (server *srv, connection *con, ERR_clear_error(); do { chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, - SSL_pending(con->ssl)); + SSL_pending(hctx->ssl)); #if 0 /* overwrite everything with 0 */ memset(mem, 0, mem_len); #endif - len = SSL_read(con->ssl, mem, mem_len); + len = SSL_read(hctx->ssl, mem, mem_len); if (len > 0) { chunkqueue_use_memory(con->read_queue, len); con->bytes_read += len; @@ -344,17 +1116,18 @@ connection_read_cq_ssl (server *srv, connection *con, chunkqueue_use_memory(con->read_queue, 0); } - if (con->renegotiations > 1 - && con->conf.ssl_disable_client_renegotiation) { + if (hctx->renegotiations > 1 + && hctx->conf.ssl_disable_client_renegotiation) { log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection"); return -1; } - } while (len > 0 &&(con.conf->ssl_read_ahead || SSL_pending(con->ssl) > 0)); + } while (len > 0 + && (hctx->conf.ssl_read_ahead || SSL_pending(hctx->ssl) > 0)); if (len < 0) { int oerrno = errno; - switch ((r = SSL_get_error(con->ssl, len))) { + switch ((r = SSL_get_error(hctx->ssl, len))) { case SSL_ERROR_WANT_WRITE: con->is_writable = -1; case SSL_ERROR_WANT_READ: @@ -416,7 +1189,7 @@ connection_read_cq_ssl (server *srv, connection *con, #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: #endif - if (!con->conf.log_ssl_noise) continue; + if (!hctx->conf.ssl_log_noise) continue; break; default: break; @@ -447,12 +1220,13 @@ CONNECTION_FUNC(mod_openssl_handle_con_accept) if (!srv_sock->is_ssl) return HANDLER_GO_ON; hctx = handler_ctx_init(); + hctx->con = con; con->plugin_ctx[p->id] = hctx; mod_openssl_patch_connection(srv, con, hctx); /* connect fd to SSL */ - con->ssl = SSL_new(srv->config_storage[srv_sock->sidx]->ssl_ctx); - if (NULL == con->ssl) { + hctx->ssl = SSL_new(p->config_storage[srv_sock->sidx]->ssl_ctx); + if (NULL == hctx->ssl) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return HANDLER_ERROR; @@ -460,11 +1234,10 @@ CONNECTION_FUNC(mod_openssl_handle_con_accept) con->network_read = connection_read_cq_ssl; con->network_write = connection_write_cq_ssl; - con->renegotiations = 0; - SSL_set_app_data(con->ssl, con); - SSL_set_accept_state(con->ssl); + SSL_set_app_data(hctx->ssl, hctx); + SSL_set_accept_state(hctx->ssl); - if (1 != (SSL_set_fd(con->ssl, con->fd))) { + if (1 != (SSL_set_fd(hctx->ssl, con->fd))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return HANDLER_ERROR; @@ -480,11 +1253,11 @@ CONNECTION_FUNC(mod_openssl_handle_con_shut_wr) handler_ctx *hctx = con->plugin_ctx[p->id]; if (NULL == hctx) return HANDLER_GO_ON; - if (SSL_is_init_finished(con->ssl)) { + if (SSL_is_init_finished(hctx->ssl)) { int ret, ssl_r; unsigned long err; ERR_clear_error(); - switch ((ret = SSL_shutdown(con->ssl))) { + switch ((ret = SSL_shutdown(hctx->ssl))) { case 1: /* ok */ break; @@ -495,12 +1268,12 @@ CONNECTION_FUNC(mod_openssl_handle_con_shut_wr) * */ ERR_clear_error(); - if (-1 != (ret = SSL_shutdown(con->ssl))) break; + if (-1 != (ret = SSL_shutdown(hctx->ssl))) break; /* fall through */ default: - switch ((ssl_r = SSL_get_error(con->ssl, ret))) { + switch ((ssl_r = SSL_get_error(hctx->ssl, ret))) { case SSL_ERROR_ZERO_RETURN: break; case SSL_ERROR_WANT_WRITE: @@ -551,11 +1324,10 @@ CONNECTION_FUNC(mod_openssl_handle_con_close) { plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; - if (NULL == hctx) return HANDLER_GO_ON; - - if (con->ssl) SSL_free(con->ssl); - con->ssl = NULL; - handler_ctx_free(hctx); + if (NULL != hctx) { + handler_ctx_free(hctx); + con->plugin_ctx[p->id] = NULL; + } UNUSED(srv); return HANDLER_GO_ON; @@ -563,13 +1335,13 @@ CONNECTION_FUNC(mod_openssl_handle_con_close) static void -https_add_ssl_client_entries (server *srv, connection *con) +https_add_ssl_client_entries (server *srv, connection *con, handler_ctx *hctx) { X509 *xs; X509_NAME *xn; int i, nentries; - long vr = SSL_get_verify_result(con->ssl); + long vr = SSL_get_verify_result(hctx->ssl); if (vr != X509_V_OK) { char errstr[256]; ERR_error_string_n(vr, errstr, sizeof(errstr)); @@ -579,7 +1351,7 @@ https_add_ssl_client_entries (server *srv, connection *con) CONST_STR_LEN("SSL_CLIENT_VERIFY"), CONST_BUF_LEN(srv->tmp_buf)); return; - } else if (!(xs = SSL_get_peer_certificate(con->ssl))) { + } else if (!(xs = SSL_get_peer_certificate(hctx->ssl))) { array_set_key_value(con->environment, CONST_STR_LEN("SSL_CLIENT_VERIFY"), CONST_STR_LEN("NONE")); @@ -623,7 +1395,7 @@ https_add_ssl_client_entries (server *srv, connection *con) BN_free(serialBN); } - if (!buffer_string_is_empty(con->conf.ssl_verifyclient_username)) { + if (!buffer_string_is_empty(hctx->conf.ssl_verifyclient_username)) { /* pick one of the exported values as "REMOTE_USER", for example * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" * or @@ -631,7 +1403,7 @@ https_add_ssl_client_entries (server *srv, connection *con) */ data_string *ds = (data_string *) array_get_element(con->environment, - con->conf.ssl_verifyclient_username->ptr); + hctx->conf.ssl_verifyclient_username->ptr); if (ds) { /* same as http_auth.c:http_auth_setenv() */ array_set_key_value(con->environment, CONST_STR_LEN("REMOTE_USER"), @@ -642,7 +1414,7 @@ https_add_ssl_client_entries (server *srv, connection *con) } } - if (con->conf.ssl_verifyclient_export_cert) { + if (hctx->conf.ssl_verifyclient_export_cert) { BIO *bio; if (NULL != (bio = BIO_new(BIO_s_mem()))) { data_string *envds; @@ -670,19 +1442,18 @@ https_add_ssl_client_entries (server *srv, connection *con) static void -http_cgi_ssl_env (connection *con) +http_cgi_ssl_env (server *srv, connection *con, handler_ctx *hctx) { const char *s; const SSL_CIPHER *cipher; + UNUSED(srv); - if (!con->ssl) return; - - s = SSL_get_version(con->ssl); + s = SSL_get_version(hctx->ssl); array_set_key_value(con->environment, CONST_STR_LEN("SSL_PROTOCOL"), s, strlen(s)); - if ((cipher = SSL_get_current_cipher(con->ssl))) { + if ((cipher = SSL_get_current_cipher(hctx->ssl))) { int usekeysize, algkeysize; char buf[LI_ITOSTRING_LENGTH]; s = SSL_CIPHER_get_name(cipher); @@ -710,9 +1481,9 @@ CONNECTION_FUNC(mod_openssl_handle_request_env) if (hctx->request_env_patched) return HANDLER_GO_ON; hctx->request_env_patched = 1; - http_cgi_ssl_env(con); - if (con->conf.ssl_verifyclient) { - https_add_ssl_client_entries(srv, con); + http_cgi_ssl_env(srv, con, hctx); + if (hctx->conf.ssl_verifyclient) { + https_add_ssl_client_entries(srv, con, hctx); } return HANDLER_GO_ON; @@ -730,7 +1501,7 @@ CONNECTION_FUNC(mod_openssl_handle_uri_raw) handler_ctx *hctx = con->plugin_ctx[p->id]; if (NULL == hctx) return HANDLER_GO_ON; - if (con->conf.ssl_verifyclient) { + if (hctx->conf.ssl_verifyclient) { mod_openssl_handle_request_env(srv, con, p); } diff --git a/src/network.c b/src/network.c index 83141690..0e5725c8 100644 --- a/src/network.c +++ b/src/network.c @@ -23,33 +23,6 @@ #include <stdlib.h> #include <assert.h> -#ifdef USE_OPENSSL -# include <openssl/ssl.h> -# include <openssl/err.h> -# include <openssl/rand.h> -# ifndef OPENSSL_NO_DH -# include <openssl/dh.h> -# endif -# include <openssl/bn.h> - -# if OPENSSL_VERSION_NUMBER >= 0x0090800fL -# ifndef OPENSSL_NO_ECDH -# include <openssl/ecdh.h> -# endif -# endif -#endif - -#ifdef USE_OPENSSL -static void ssl_info_callback(const SSL *ssl, int where, int ret) { - UNUSED(ret); - - if (0 != (where & SSL_CB_HANDSHAKE_START)) { - connection *con = SSL_get_app_data(ssl); - ++con->renegotiations; - } -} -#endif - void network_accept_tcp_nagle_disable (const int fd) { @@ -96,89 +69,13 @@ static handler_t network_server_handle_fdevent(server *srv, void *context, int r return HANDLER_GO_ON; } -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT -static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) { - const char *servername; - connection *con = (connection *) SSL_get_app_data(ssl); - UNUSED(al); - - buffer_copy_string(con->uri.scheme, "https"); - - if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { -#if 0 - /* this "error" just means the client didn't support it */ - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "failed to get TLS server name"); -#endif - return SSL_TLSEXT_ERR_NOACK; - } - buffer_copy_string(con->tlsext_server_name, servername); - buffer_to_lower(con->tlsext_server_name); - - /* Sometimes this is still set, confusing COMP_HTTP_HOST */ - buffer_reset(con->uri.authority); - - config_cond_cache_reset(srv, con); - config_setup_connection(srv, con); - - con->conditional_is_valid[COMP_SERVER_SOCKET] = 1; - con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1; - con->conditional_is_valid[COMP_HTTP_SCHEME] = 1; - con->conditional_is_valid[COMP_HTTP_HOST] = 1; - config_patch_connection(srv, con); - - if (NULL == con->conf.ssl_pemfile_x509 || NULL == con->conf.ssl_pemfile_pkey) { - /* x509/pkey available <=> pemfile was set <=> pemfile got patched: so this should never happen, unless you nest $SERVER["socket"] */ - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", - "no certificate/private key for TLS server name", con->tlsext_server_name); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - - /* first set certificate! setting private key checks whether certificate matches it */ - if (!SSL_use_certificate(ssl, con->conf.ssl_pemfile_x509)) { - log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", - "failed to set certificate for TLS server name", con->tlsext_server_name, - ERR_error_string(ERR_get_error(), NULL)); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - - if (!SSL_use_PrivateKey(ssl, con->conf.ssl_pemfile_pkey)) { - log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", - "failed to set private key for TLS server name", con->tlsext_server_name, - ERR_error_string(ERR_get_error(), NULL)); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - - if (con->conf.ssl_verifyclient) { - if (NULL == con->conf.ssl_ca_file_cert_names) { - log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", - "can't verify client without ssl.ca-file for TLS server name", con->tlsext_server_name, - ERR_error_string(ERR_get_error(), NULL)); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - - SSL_set_client_CA_list(ssl, SSL_dup_CA_list(con->conf.ssl_ca_file_cert_names)); - /* forcing verification here is really not that useful - a client could just connect without SNI */ - SSL_set_verify( - ssl, - SSL_VERIFY_PEER | (con->conf.ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), - NULL - ); - SSL_set_verify_depth(ssl, con->conf.ssl_verifyclient_depth); - } else { - SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); - } - - return SSL_TLSEXT_ERR_OK; -} -#endif - -static int network_server_init(server *srv, buffer *host_token, specific_config *s) { +static int network_server_init(server *srv, buffer *host_token, size_t sidx) { int val; socklen_t addr_len; server_socket *srv_socket; unsigned int port = 0; const char *host; + specific_config *s = srv->config_storage[sidx]; buffer *b; int err; @@ -202,6 +99,7 @@ static int network_server_init(server *srv, buffer *host_token, specific_config srv_socket->addr.plain.sa_family = AF_INET; /* default */ srv_socket->fd = -1; srv_socket->fde_ndx = -1; + srv_socket->sidx = sidx; srv_socket->srv_token = buffer_init(); buffer_copy_buffer(srv_socket->srv_token, host_token); @@ -373,9 +271,6 @@ static int network_server_init(server *srv, buffer *host_token, specific_config } if (srv->sockets_disabled) { /* lighttpd -1 (one-shot mode) */ -#ifdef USE_OPENSSL - if (s->ssl_enabled) srv_socket->ssl_ctx = s->ssl_ctx; -#endif goto srv_sockets_append; } @@ -475,18 +370,6 @@ static int network_server_init(server *srv, buffer *host_token, specific_config } if (s->ssl_enabled) { -#ifdef USE_OPENSSL - if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) { - log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); - goto error_free_socket; - } -#else - - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "ssl requested but openssl support is not compiled in"); - - goto error_free_socket; -#endif #ifdef TCP_DEFER_ACCEPT } else if (s->defer_accept) { int v = s->defer_accept; @@ -583,153 +466,11 @@ typedef enum { NETWORK_BACKEND_SENDFILE, } network_backend_t; -#ifdef USE_OPENSSL -static X509* x509_load_pem_file(server *srv, const char *file) { - BIO *in; - X509 *x = NULL; - - in = BIO_new(BIO_s_file()); - if (NULL == in) { - log_error_write(srv, __FILE__, __LINE__, "S", "SSL: BIO_new(BIO_s_file()) failed"); - goto error; - } - - if (BIO_read_filename(in,file) <= 0) { - log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed"); - goto error; - } - x = PEM_read_bio_X509(in, NULL, NULL, NULL); - - if (NULL == x) { - log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read X509 certificate from '", file,"'"); - goto error; - } - - BIO_free(in); - return x; - -error: - if (NULL != in) BIO_free(in); - return NULL; -} - -static EVP_PKEY* evp_pkey_load_pem_file(server *srv, const char *file) { - BIO *in; - EVP_PKEY *x = NULL; - - in=BIO_new(BIO_s_file()); - if (NULL == in) { - log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BIO_new(BIO_s_file()) failed"); - goto error; - } - - if (BIO_read_filename(in,file) <= 0) { - log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed"); - goto error; - } - x = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); - - if (NULL == x) { - log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read private key from '", file,"'"); - goto error; - } - - BIO_free(in); - return x; - -error: - if (NULL != in) BIO_free(in); - return NULL; -} - -static int network_openssl_load_pemfile(server *srv, size_t ndx) { - specific_config *s = srv->config_storage[ndx]; - -#ifdef OPENSSL_NO_TLSEXT - { - data_config *dc = (data_config *)srv->config_context->data[ndx]; - if ((ndx > 0 && (COMP_SERVER_SOCKET != dc->comp || dc->cond != CONFIG_COND_EQ)) - || !s->ssl_enabled) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "ssl.pemfile only works in SSL socket binding context as openssl version does not support TLS extensions"); - return -1; - } - } -#endif - - if (NULL == (s->ssl_pemfile_x509 = x509_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1; - if (NULL == (s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1; - - if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) { - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", - "Private key does not match the certificate public key, reason:", - ERR_error_string(ERR_get_error(), NULL), - s->ssl_pemfile); - return -1; - } - - return 0; -} -#endif - int network_init(server *srv) { buffer *b; size_t i, j; network_backend_t backend; -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh; - int nid; -#endif -#endif - -#ifdef USE_OPENSSL -# ifndef OPENSSL_NO_DH - DH *dh; -# endif - BIO *bio; - - /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) - * -----BEGIN DH PARAMETERS----- - * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y - * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 - * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV - * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 - * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR - * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= - * -----END DH PARAMETERS----- - */ - - static const unsigned char dh1024_p[]={ - 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, - 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, - 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, - 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, - 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, - 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, - 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, - 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, - 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, - 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, - 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, - }; - - static const unsigned char dh1024_g[]={ - 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, - 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, - 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, - 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, - 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, - 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, - 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, - 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, - 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, - 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, - 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, - }; -#endif - struct nb_map { network_backend_t nb; const char *name; @@ -754,270 +495,13 @@ int network_init(server *srv) { { NETWORK_BACKEND_UNSET, NULL } }; -#ifdef USE_OPENSSL - /* load SSL certificates */ - for (i = 0; i < srv->config_context->used; i++) { - specific_config *s = srv->config_storage[i]; -#ifndef SSL_OP_NO_COMPRESSION -# define SSL_OP_NO_COMPRESSION 0 -#endif -#ifndef SSL_MODE_RELEASE_BUFFERS /* OpenSSL >= 1.0.0 */ -#define SSL_MODE_RELEASE_BUFFERS 0 -#endif - long ssloptions = - SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION; - - if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue; - - if (srv->ssl_is_init == 0) { - #if OPENSSL_VERSION_NUMBER >= 0x10100000L \ - && !defined(LIBRESSL_VERSION_NUMBER) - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS - |OPENSSL_INIT_LOAD_CRYPTO_STRINGS,NULL); - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS - |OPENSSL_INIT_ADD_ALL_DIGESTS - |OPENSSL_INIT_LOAD_CONFIG, NULL); - #else - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - #endif - srv->ssl_is_init = 1; - - if (0 == RAND_status()) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "not enough entropy in the pool"); - return -1; - } - } - - if (!buffer_string_is_empty(s->ssl_pemfile)) { -#ifdef OPENSSL_NO_TLSEXT - data_config *dc = (data_config *)srv->config_context->data[i]; - if (COMP_HTTP_HOST == dc->comp) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions"); - return -1; - } -#endif - if (network_openssl_load_pemfile(srv, i)) return -1; - } - - - if (!buffer_string_is_empty(s->ssl_ca_file)) { - s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr); - if (NULL == s->ssl_ca_file_cert_names) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", - ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); - } - } - - if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue; - - if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - /* completely useless identifier; required for client cert verification to work with sessions */ - if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) { - log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:", - "failed to set session context", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - if (s->ssl_empty_fragments) { -#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -#else - ssloptions &= ~0x00000800L; /* hardcode constant */ - log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:", - "'insert empty fragments' not supported by the openssl version used to compile lighttpd with"); -#endif - } - - SSL_CTX_set_options(s->ssl_ctx, ssloptions); - SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback); - - if (!s->ssl_use_sslv2 && 0 != SSL_OP_NO_SSLv2) { - /* disable SSLv2 */ - if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - } - - if (!s->ssl_use_sslv3 && 0 != SSL_OP_NO_SSLv3) { - /* disable SSLv3 */ - if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - } - - if (!buffer_string_is_empty(s->ssl_cipher_list)) { - /* Disable support for low encryption ciphers */ - if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - if (s->ssl_honor_cipher_order) { - SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } - } - -#ifndef OPENSSL_NO_DH - /* Support for Diffie-Hellman key exchange */ - if (!buffer_string_is_empty(s->ssl_dh_file)) { - /* DH parameters from file */ - bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r"); - if (bio == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr); - return -1; - } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (dh == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr); - return -1; - } - } else { - BIGNUM *dh_p, *dh_g; - /* Default DH parameters from RFC5114 */ - dh = DH_new(); - if (dh == NULL) { - log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed"); - return -1; - } - dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL); - dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL); - if ((dh_p == NULL) || (dh_g == NULL)) { - DH_free(dh); - log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed"); - return -1; - } - #if OPENSSL_VERSION_NUMBER < 0x10100000L \ - || defined(LIBRESSL_VERSION_NUMBER) - dh->p = dh_p; - dh->g = dh_g; - dh->length = 160; - #else - DH_set0_pqg(dh, dh_p, NULL, dh_g); - DH_set_length(dh, 160); - #endif - } - SSL_CTX_set_tmp_dh(s->ssl_ctx,dh); - SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE); - DH_free(dh); -#else - if (!buffer_string_is_empty(s->ssl_dh_file)) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr); - } -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#ifndef OPENSSL_NO_ECDH - /* Support for Elliptic-Curve Diffie-Hellman key exchange */ - if (!buffer_string_is_empty(s->ssl_ec_curve)) { - /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */ - nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr); - if (nid == 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr); - return -1; - } - } else { - /* Default curve */ - nid = OBJ_sn2nid("prime256v1"); - } - ecdh = EC_KEY_new_by_curve_name(nid); - if (ecdh == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr); - return -1; - } - SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh); - SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE); - EC_KEY_free(ecdh); -#endif -#endif - - /* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */ - for (j = 0; j < srv->config_context->used; j++) { - specific_config *s1 = srv->config_storage[j]; - - if (!buffer_string_is_empty(s1->ssl_ca_file)) { - if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", - ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file); - return -1; - } - } - } - - if (s->ssl_verifyclient) { - if (NULL == s->ssl_ca_file_cert_names) { - log_error_write(srv, __FILE__, __LINE__, "s", - "SSL: You specified ssl.verifyclient.activate but no ca_file" - ); - return -1; - } - SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names)); - SSL_CTX_set_verify( - s->ssl_ctx, - SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), - NULL - ); - SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth); - } - - if (1 != SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509)) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", - ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); - return -1; - } - - if (1 != SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey)) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", - ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); - return -1; - } - - if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", - "Private key does not match the certificate public key, reason:", - ERR_error_string(ERR_get_error(), NULL), - s->ssl_pemfile); - return -1; - } - SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead); - SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) - | SSL_MODE_ENABLE_PARTIAL_WRITE - | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER - | SSL_MODE_RELEASE_BUFFERS); - -# ifndef OPENSSL_NO_TLSEXT - if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) || - !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", - "failed to initialize TLS servername callback, openssl library does not support TLS servername extension"); - return -1; - } -# endif - } -#endif - b = buffer_init(); buffer_copy_buffer(b, srv->srvconf.bindhost); buffer_append_string_len(b, CONST_STR_LEN(":")); buffer_append_int(b, srv->srvconf.port); - if (0 != network_server_init(srv, b, srv->config_storage[0])) { + if (0 != network_server_init(srv, b, 0)) { buffer_free(b); return -1; } @@ -1067,7 +551,6 @@ int network_init(server *srv) { /* check for $SERVER["socket"] */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; - specific_config *s = srv->config_storage[i]; /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; @@ -1083,7 +566,7 @@ int network_init(server *srv) { } if (j == srv->srv_sockets.used) { - if (0 != network_server_init(srv, dc->string, s)) return -1; + if (0 != network_server_init(srv, dc->string, i)) return -1; } } diff --git a/src/server.c b/src/server.c index db4f61e3..f0df8d52 100644 --- a/src/server.c +++ b/src/server.c @@ -59,6 +59,13 @@ # include <sys/prctl.h> #endif +#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H +#define USE_SSL +#define TEXT_SSL " (ssl)" +#else +#define TEXT_SSL +#endif + #ifndef __sgi /* IRIX doesn't like the alarm based time() optimization */ /* #define USE_ALARM */ @@ -504,16 +511,10 @@ static int server_oneshot_init(server *srv, int fd) { static void show_version (void) { -#ifdef USE_OPENSSL -# define TEXT_SSL " (ssl)" -#else -# define TEXT_SSL -#endif char *b = PACKAGE_DESC TEXT_SSL \ " - a light and fast webserver\n" \ "Build-Date: " __DATE__ " " __TIME__ "\n"; ; -#undef TEXT_SSL write_all(STDOUT_FILENO, b, strlen(b)); } @@ -607,10 +608,10 @@ static void show_features (void) { #else "\t- crypt support\n" #endif -#ifdef USE_OPENSSL - "\t+ SSL Support\n" +#ifdef USE_SSL + "\t+ SSL support\n" #else - "\t- SSL Support\n" + "\t- SSL support\n" #endif #ifdef HAVE_LIBPCRE "\t+ PCRE support\n" @@ -668,11 +669,6 @@ static void show_features (void) { } static void show_help (void) { -#ifdef USE_OPENSSL -# define TEXT_SSL " (ssl)" -#else -# define TEXT_SSL -#endif char *b = PACKAGE_DESC TEXT_SSL " ("__DATE__ " " __TIME__ ")" \ " - a light and fast webserver\n" \ "usage:\n" \ @@ -689,8 +685,6 @@ static void show_help (void) { " -h show this help\n" \ "\n" ; -#undef TEXT_SSL -#undef TEXT_IPV6 write_all(STDOUT_FILENO, b, strlen(b)); } |