Browse Source

[ssl] count renegotiations to prevent client renegotiations

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2808 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.30
Stefan Bühler 10 years ago
parent
commit
a94bdd07df
  1. 1
      NEWS
  2. 2
      src/base.h
  3. 7
      src/configfile.c
  4. 7
      src/connections.c
  5. 26
      src/network.c
  6. 18
      src/network_openssl.c

1
NEWS

@ -11,6 +11,7 @@ NEWS
* Don't overwrite 401 (auth required) with 501 (unknown method) (fixes #2341)
* Fix mod_status bug: always showed "0/0" in the "Read" column for uploads (fixes #2351)
* [mod_auth] Fix signedness error in http_auth (fixes #2370, CVE-2011-4362)
* [ssl] count renegotiations to prevent client renegotiations
- 1.4.29 - 2011-07-03
* Fix mod_proxy waiting for response even if content-length is 0 (fixes #2259)

2
src/base.h

@ -284,6 +284,7 @@ typedef struct {
unsigned short ssl_verifyclient_depth;
buffer *ssl_verifyclient_username;
unsigned short ssl_verifyclient_export_cert;
unsigned short ssl_disable_client_renegotiation;
unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */
unsigned short defer_accept;
@ -437,6 +438,7 @@ typedef struct {
# 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;

7
src/configfile.c

@ -105,6 +105,7 @@ static int config_insert(server *srv) {
{ "ssl.use-sslv3", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 62 */
{ "ssl.dh-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 63 */
{ "ssl.ec-curve", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 64 */
{ "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 65 */
{ "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
{ "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
@ -199,6 +200,7 @@ static int config_insert(server *srv) {
s->ssl_verifyclient_username = buffer_init();
s->ssl_verifyclient_depth = 9;
s->ssl_verifyclient_export_cert = 0;
s->ssl_disable_client_renegotiation = 1;
cv[2].destination = s->errorfile_prefix;
@ -245,6 +247,7 @@ static int config_insert(server *srv) {
cv[62].destination = &(s->ssl_use_sslv3);
cv[63].destination = s->ssl_dh_file;
cv[64].destination = s->ssl_ec_curve;
cv[49].destination = &(s->etag_use_inode);
cv[50].destination = &(s->etag_use_mtime);
cv[51].destination = &(s->etag_use_size);
@ -255,6 +258,7 @@ static int config_insert(server *srv) {
cv[58].destination = &(s->ssl_verifyclient_depth);
cv[59].destination = s->ssl_verifyclient_username;
cv[60].destination = &(s->ssl_verifyclient_export_cert);
cv[65].destination = &(s->ssl_disable_client_renegotiation);
srv->config_storage[i] = s;
@ -346,6 +350,7 @@ int config_setup_connection(server *srv, connection *con) {
PATCH(ssl_verifyclient_depth);
PATCH(ssl_verifyclient_username);
PATCH(ssl_verifyclient_export_cert);
PATCH(ssl_disable_client_renegotiation);
return 0;
}
@ -454,6 +459,8 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
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);
}
}
}

7
src/connections.c

@ -223,6 +223,12 @@ static int connection_handle_read_ssl(server *srv, connection *con) {
len = SSL_read(con->ssl, b->ptr + read_offset, toread);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
connection_set_state(srv, con, CON_STATE_ERROR);
log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
return -1;
}
if (len > 0) {
if (b->used > 0) b->used--;
b->used += len;
@ -1353,6 +1359,7 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
return NULL;
}
con->renegotiations = 0;
#ifndef OPENSSL_NO_TLSEXT
SSL_set_app_data(con->ssl, con);
#endif

26
src/network.c

@ -27,6 +27,17 @@
# include <openssl/rand.h>
#endif
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;
} else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) {
server_socket *srv_socket = (server_socket *)context;
connection *con;
@ -555,6 +566,11 @@ int network_init(server *srv) {
/* 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
long ssloptions =
SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
if (buffer_is_empty(s->ssl_pemfile)) continue;
@ -588,6 +604,16 @@ int network_init(server *srv) {
return -1;
}
SSL_CTX_set_options(s->ssl_ctx, ssloptions);
SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, 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_sslv2) {
/* disable SSLv2 */
if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {

18
src/network_openssl.c

@ -87,7 +87,14 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
*/
ERR_clear_error();
if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
r = SSL_write(ssl, offset, toSend);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
return -1;
}
if (r <= 0) {
unsigned long err;
switch ((ssl_r = SSL_get_error(ssl, r))) {
@ -192,7 +199,14 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
close(ifd);
ERR_clear_error();
if ((r = SSL_write(ssl, s, toSend)) <= 0) {
r = SSL_write(ssl, s, toSend);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
return -1;
}
if (r <= 0) {
unsigned long err;
switch ((ssl_r = SSL_get_error(ssl, r))) {

Loading…
Cancel
Save