SSL: reject unsupported protocols "negotiated" during handshake
Piotr Sikora
piotr at cloudflare.com
Wed Apr 3 01:06:02 UTC 2013
Hey,
OpenSSL doesn't do anything to verify that "negotiated" protocol
was actually advertised to the client, so we have to do it ourselves.
Note: I dislike the way NGX_HTTP_NPN_NEGOTIATED is defined here,
but it kind of matches the way NGX_HTTP_NPN_ADVERTISE is defined
and I didn't see a better place to add it. Feel free to move it
elsewhere.
Best regards,
Piotr Sikora
diff -r 4bcd35e7a0f0 src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c Fri Mar 29 08:47:37 2013 +0000
+++ b/src/http/ngx_http_request.c Tue Apr 02 17:54:05 2013 -0700
@@ -712,6 +712,10 @@
}
+#ifdef TLSEXT_TYPE_next_proto_neg
+#define NGX_HTTP_NPN_NEGOTIATED "http/1.1"
+#endif
+
static void
ngx_http_ssl_handshake_handler(ngx_connection_t *c)
{
@@ -727,17 +731,34 @@
c->ssl->no_wait_shutdown = 1;
-#if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg)
+#ifdef TLSEXT_TYPE_next_proto_neg
{
unsigned int len;
const unsigned char *data;
+ static const ngx_str_t http = ngx_string(NGX_HTTP_NPN_NEGOTIATED);
+#if (NGX_HTTP_SPDY)
static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
+#endif
SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
- if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
- ngx_http_spdy_init(c->read);
- return;
+ if (len) {
+#if (NGX_HTTP_SPDY)
+ if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0)
+ {
+ ngx_http_spdy_init(c->read);
+ return;
+ }
+#endif
+
+ if (len != http.len || ngx_strncmp(data, http.data, http.len)) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "client negotiated unsupported protocol \"%*s\"",
+ len, data);
+
+ ngx_http_close_connection(c);
+ return;
+ }
}
}
#endif
More information about the nginx-devel
mailing list