diff --git a/libhttp/httpconnection.c b/libhttp/httpconnection.c index 12ea365..67cc644 100644 --- a/libhttp/httpconnection.c +++ b/libhttp/httpconnection.c @@ -88,7 +88,7 @@ static int httpPromoteToSSL(struct HttpConnection *http, const char *buf, int len) { if (http->ssl->enabled && !http->sslHndl) { - debug("Switching to SSL (replaying %d+%d bytes)", + debug("SSL: switching to SSL (replaying %d+%d bytes)", http->partialLength, len); if (http->partial && len > 0) { check(http->partial = realloc(http->partial, @@ -102,6 +102,8 @@ static int httpPromoteToSSL(struct HttpConnection *http, const char *buf, http->partial ? http->partialLength : len); if (http->sslHndl) { check(!rc); + // Reset renegotiations count for connections promoted to SSL. + http->ssl->renegotiationCount = 0; SSL_set_app_data(http->sslHndl, http); } free(http->partial); @@ -138,6 +140,13 @@ static ssize_t httpRead(struct HttpConnection *http, char *buf, ssize_t len) { break; } dcheck(!ERR_peek_error()); + + // Shutdown SSL connection, if client initiated renegotiation. + if (http->ssl->renegotiationCount > 1) { + debug("SSL: connection shutdown due to client initiated renegotiation!"); + rc = 0; + errno = EINVAL; + } } else { rc = NOINTR(read(http->fd, buf, len)); } diff --git a/libhttp/ssl.c b/libhttp/ssl.c index 28229cf..2564584 100644 --- a/libhttp/ssl.c +++ b/libhttp/ssl.c @@ -113,7 +113,9 @@ int (*SSL_CTX_check_private_key)(const SSL_CTX *); long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *); void (*SSL_CTX_free)(SSL_CTX *); SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *); -int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str); +int (*SSL_CTX_set_cipher_list)(SSL_CTX *, const char *); +void (*SSL_CTX_set_info_callback)(SSL_CTX *, + void (*)(const SSL *, int, int)); int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int); int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *, const unsigned char *, long); @@ -168,6 +170,7 @@ void initSSL(struct SSLSupport *ssl) { ssl->sslContext = NULL; ssl->sniCertificatePattern = NULL; ssl->generateMissing = 0; + ssl->renegotiationCount = 0; initTrie(&ssl->sniContexts, sslDestroyCachedContext, ssl); } @@ -292,6 +295,7 @@ static void loadSSL(void) { { { &SSL_CTX_free }, "SSL_CTX_free" }, { { &SSL_CTX_new }, "SSL_CTX_new" }, { { &SSL_CTX_set_cipher_list }, "SSL_CTX_set_cipher_list" }, + { { &SSL_CTX_set_info_callback }, "SSL_CTX_set_info_callback" }, { { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" }, { { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" }, { { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"}, @@ -602,6 +606,15 @@ static int sslSetCertificateFromFile(SSL_CTX *context, return rc; } +static void sslInfoCallback(const SSL *sslHndl, int type, int val) { + // Count the number of renegotiations for each SSL session. + if (type & SSL_CB_HANDSHAKE_START) { + struct HttpConnection *http = + (struct HttpConnection *) SSL_get_app_data(sslHndl); + http->ssl->renegotiationCount += 1; + } +} + static SSL_CTX *sslMakeContext(void) { SSL_CTX *context; @@ -657,6 +670,8 @@ static SSL_CTX *sslMakeContext(void) { "ECDHE-RSA-DES-CBC3-SHA:" "HIGH:MEDIUM:!RC4:!aNULL:!MD5")); + SSL_CTX_set_info_callback(context, sslInfoCallback); + debug("SSL: server context succesfully initialized..."); return context; } diff --git a/libhttp/ssl.h b/libhttp/ssl.h index cd93aae..0be3830 100644 --- a/libhttp/ssl.h +++ b/libhttp/ssl.h @@ -95,7 +95,9 @@ extern int (*x_SSL_CTX_check_private_key)(const SSL_CTX *); extern long (*x_SSL_CTX_ctrl)(SSL_CTX *, int, long, void *); extern void (*x_SSL_CTX_free)(SSL_CTX *); extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *); -extern int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str); +extern int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *, const char *); +extern void (*x_SSL_CTX_set_info_callback)(SSL_CTX *, + void (*)(const SSL *, int, int)); extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int); extern int (*x_SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *, const unsigned char *, long); @@ -141,6 +143,7 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void); #define SSL_CTX_free x_SSL_CTX_free #define SSL_CTX_new x_SSL_CTX_new #define SSL_CTX_set_cipher_list x_SSL_CTX_set_cipher_list +#define SSL_CTX_set_info_callback x_SSL_CTX_set_info_callback #define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file #define SSL_CTX_use_PrivateKey_ASN1 x_SSL_CTX_use_PrivateKey_ASN1 #define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file @@ -198,6 +201,7 @@ struct SSLSupport { SSL_CTX *sslContext; char *sniCertificatePattern; int generateMissing; + int renegotiationCount; struct Trie sniContexts; };