Disable secure client-initiated renegotiation
* In case that this SSL feature is abused it is possible to overload the server. Other web servers disable this feature by default, but users are able to change it with configuration. This is not possible with shellinabox as this feature is not needed. * Solution was implemented similary as in Lighttpd web server.
This commit is contained in:
parent
f0437832d3
commit
eacb2fcb81
3 changed files with 31 additions and 3 deletions
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue