27847ae318
- fix CVE-2009-3555 - note that the fix is bypassed if SSL_OP_ALL is used so the compatibility with unfixed clients is not broken. The protocol extension is also not final.
238 lines
7.4 KiB
Diff
238 lines
7.4 KiB
Diff
diff -up openssl-1.0.0-beta4/apps/s_cb.c.reneg openssl-1.0.0-beta4/apps/s_cb.c
|
|
--- openssl-1.0.0-beta4/apps/s_cb.c.reneg 2009-10-15 20:48:47.000000000 +0200
|
|
+++ openssl-1.0.0-beta4/apps/s_cb.c 2009-11-12 15:02:30.000000000 +0100
|
|
@@ -669,6 +669,10 @@ void MS_CALLBACK tlsext_cb(SSL *s, int c
|
|
extname = "server ticket";
|
|
break;
|
|
|
|
+ case TLSEXT_TYPE_renegotiate:
|
|
+ extname = "renegotiate";
|
|
+ break;
|
|
+
|
|
#ifdef TLSEXT_TYPE_opaque_prf_input
|
|
case TLSEXT_TYPE_opaque_prf_input:
|
|
extname = "opaque PRF input";
|
|
diff -up openssl-1.0.0-beta4/apps/s_client.c.reneg openssl-1.0.0-beta4/apps/s_client.c
|
|
--- openssl-1.0.0-beta4/apps/s_client.c.reneg 2009-11-12 14:57:48.000000000 +0100
|
|
+++ openssl-1.0.0-beta4/apps/s_client.c 2009-11-12 15:01:48.000000000 +0100
|
|
@@ -343,6 +343,7 @@ static void sc_usage(void)
|
|
BIO_printf(bio_err," -status - request certificate status from server\n");
|
|
BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n");
|
|
#endif
|
|
+ BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
|
|
}
|
|
|
|
#ifndef OPENSSL_NO_TLSEXT
|
|
@@ -657,6 +658,8 @@ int MAIN(int argc, char **argv)
|
|
#endif
|
|
else if (strcmp(*argv,"-serverpref") == 0)
|
|
off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
|
|
+ else if (strcmp(*argv,"-legacy_renegotiation") == 0)
|
|
+ off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
|
|
else if (strcmp(*argv,"-cipher") == 0)
|
|
{
|
|
if (--argc < 1) goto bad;
|
|
diff -up openssl-1.0.0-beta4/apps/s_server.c.reneg openssl-1.0.0-beta4/apps/s_server.c
|
|
--- openssl-1.0.0-beta4/apps/s_server.c.reneg 2009-11-12 14:57:48.000000000 +0100
|
|
+++ openssl-1.0.0-beta4/apps/s_server.c 2009-11-12 15:01:48.000000000 +0100
|
|
@@ -491,6 +491,7 @@ static void sv_usage(void)
|
|
BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT2);
|
|
BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n");
|
|
BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n");
|
|
+ BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
|
|
#endif
|
|
}
|
|
|
|
@@ -1013,6 +1014,8 @@ int MAIN(int argc, char *argv[])
|
|
verify_return_error = 1;
|
|
else if (strcmp(*argv,"-serverpref") == 0)
|
|
{ off|=SSL_OP_CIPHER_SERVER_PREFERENCE; }
|
|
+ else if (strcmp(*argv,"-legacy_renegotiation") == 0)
|
|
+ off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
|
|
else if (strcmp(*argv,"-cipher") == 0)
|
|
{
|
|
if (--argc < 1) goto bad;
|
|
diff -up openssl-1.0.0-beta4/ssl/tls1.h.reneg openssl-1.0.0-beta4/ssl/tls1.h
|
|
--- openssl-1.0.0-beta4/ssl/tls1.h.reneg 2009-11-12 14:57:47.000000000 +0100
|
|
+++ openssl-1.0.0-beta4/ssl/tls1.h 2009-11-12 15:02:30.000000000 +0100
|
|
@@ -201,6 +201,9 @@ extern "C" {
|
|
# define TLSEXT_TYPE_opaque_prf_input ?? */
|
|
#endif
|
|
|
|
+/* Temporary extension type */
|
|
+#define TLSEXT_TYPE_renegotiate 0xff01
|
|
+
|
|
/* NameType value from RFC 3546 */
|
|
#define TLSEXT_NAMETYPE_host_name 0
|
|
/* status request value from RFC 3546 */
|
|
diff -up openssl-1.0.0-beta4/ssl/t1_lib.c.reneg openssl-1.0.0-beta4/ssl/t1_lib.c
|
|
--- openssl-1.0.0-beta4/ssl/t1_lib.c.reneg 2009-11-08 15:36:32.000000000 +0100
|
|
+++ openssl-1.0.0-beta4/ssl/t1_lib.c 2009-11-12 15:02:30.000000000 +0100
|
|
@@ -315,6 +315,30 @@ unsigned char *ssl_add_clienthello_tlsex
|
|
ret+=size_str;
|
|
}
|
|
|
|
+ /* Add the renegotiation option: TODOEKR switch */
|
|
+ {
|
|
+ int el;
|
|
+
|
|
+ if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if((limit - p - 4 - el) < 0) return NULL;
|
|
+
|
|
+ s2n(TLSEXT_TYPE_renegotiate,ret);
|
|
+ s2n(el,ret);
|
|
+
|
|
+ if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ret += el;
|
|
+ }
|
|
+
|
|
#ifndef OPENSSL_NO_EC
|
|
if (s->tlsext_ecpointformatlist != NULL)
|
|
{
|
|
@@ -490,6 +514,31 @@ unsigned char *ssl_add_serverhello_tlsex
|
|
s2n(TLSEXT_TYPE_server_name,ret);
|
|
s2n(0,ret);
|
|
}
|
|
+
|
|
+ if(s->s3->send_connection_binding)
|
|
+ {
|
|
+ int el;
|
|
+
|
|
+ if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if((limit - p - 4 - el) < 0) return NULL;
|
|
+
|
|
+ s2n(TLSEXT_TYPE_renegotiate,ret);
|
|
+ s2n(el,ret);
|
|
+
|
|
+ if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ret += el;
|
|
+ }
|
|
+
|
|
#ifndef OPENSSL_NO_EC
|
|
if (s->tlsext_ecpointformatlist != NULL)
|
|
{
|
|
@@ -574,11 +623,23 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
|
unsigned short size;
|
|
unsigned short len;
|
|
unsigned char *data = *p;
|
|
+ int renegotiate_seen = 0;
|
|
+
|
|
s->servername_done = 0;
|
|
s->tlsext_status_type = -1;
|
|
+ s->s3->send_connection_binding = 0;
|
|
|
|
if (data >= (d+n-2))
|
|
+ {
|
|
+ if (s->new_session
|
|
+ && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
|
|
+ {
|
|
+ /* We should always see one extension: the renegotiate extension */
|
|
+ *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
|
|
+ return 0;
|
|
+ }
|
|
return 1;
|
|
+ }
|
|
n2s(data,len);
|
|
|
|
if (data > (d+n-len))
|
|
@@ -790,6 +851,12 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
|
return 0;
|
|
}
|
|
}
|
|
+ else if (type == TLSEXT_TYPE_renegotiate)
|
|
+ {
|
|
+ if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
|
|
+ return 0;
|
|
+ renegotiate_seen = 1;
|
|
+ }
|
|
else if (type == TLSEXT_TYPE_status_request
|
|
&& s->ctx->tlsext_status_cb)
|
|
{
|
|
@@ -894,6 +961,14 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
|
/* session ticket processed earlier */
|
|
data+=size;
|
|
}
|
|
+
|
|
+ if (s->new_session && !renegotiate_seen
|
|
+ && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
|
|
+ {
|
|
+ *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
|
|
*p = data;
|
|
return 1;
|
|
@@ -905,11 +980,22 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
|
unsigned short size;
|
|
unsigned short len;
|
|
unsigned char *data = *p;
|
|
-
|
|
int tlsext_servername = 0;
|
|
+ int renegotiate_seen = 0;
|
|
|
|
if (data >= (d+n-2))
|
|
+ {
|
|
+ /* Because the client does not see any renegotiation during an
|
|
+ attack, we must enforce this on all server hellos, even the
|
|
+ first */
|
|
+ if (!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
|
|
+ {
|
|
+ /* We should always see one extension: the renegotiate extension */
|
|
+ *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
|
|
+ return 0;
|
|
+ }
|
|
return 1;
|
|
+ }
|
|
|
|
n2s(data,len);
|
|
|
|
@@ -1025,7 +1111,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
|
/* Set flag to expect CertificateStatus message */
|
|
s->tlsext_status_expected = 1;
|
|
}
|
|
-
|
|
+ else if (type == TLSEXT_TYPE_renegotiate)
|
|
+ {
|
|
+ if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
|
|
+ return 0;
|
|
+ renegotiate_seen = 1;
|
|
+ }
|
|
data+=size;
|
|
}
|
|
|
|
@@ -1035,6 +1126,13 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
|
return 0;
|
|
}
|
|
|
|
+ if (!renegotiate_seen
|
|
+ && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
|
|
+ {
|
|
+ *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (!s->hit && tlsext_servername == 1)
|
|
{
|
|
if (s->tlsext_hostname)
|