summaryrefslogtreecommitdiffstats
path: root/ssl/t1_lib.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2014-10-20 17:17:52 +0100
committerDr. Stephen Henson <steve@openssl.org>2014-10-23 14:45:30 +0100
commit82182413a417fabd35a0a8eb9b6a76606eeb3502 (patch)
tree49fbc60b8afd20e3fd485b6ad4c1d93f3520b877 /ssl/t1_lib.c
parent0ce2dbfb5b541ee947814849ecd12f3a76ef9150 (diff)
Parse custom extensions after SNI.
Since SNI will typically switch the SSL_CTX structure to the one corresponding to the appopriate server we need to parse custom extensions using the switched SSL_CTX not the original one. This is done by parsing custom extensions *after* SNI. Reviewed-by: Emilia Käsper <emilia@openssl.org>
Diffstat (limited to 'ssl/t1_lib.c')
-rw-r--r--ssl/t1_lib.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 2986432697..fb0b736d1c 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2424,17 +2424,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
al))
return 0;
}
- /* If this ClientHello extension was unhandled and this is
- * a nonresumed connection, check whether the extension is a
- * custom TLS Extension (has a custom_srv_ext_record), and if
- * so call the callback and record the extension number so that
- * an appropriate ServerHello may be later returned.
- */
- else if (!s->hit)
- {
- if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
- return 0;
- }
data+=size;
}
@@ -2460,10 +2449,51 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
return 1;
}
+/*
+ * Parse any custom extensions found. "data" is the start of the extension data
+ * and "limit" is the end of the record. TODO: add strict syntax checking.
+ */
+
+static int ssl_scan_clienthello_custom_tlsext(SSL *s, const unsigned char *data, const unsigned char *limit, int *al)
+ {
+ unsigned short type, size, len;
+ /* If resumed session or no custom extensions nothing to do */
+ if (s->hit || s->cert->srv_ext.meths_count == 0)
+ return 1;
+
+ if (data >= limit - 2)
+ return 1;
+ n2s(data, len);
+
+ if (data > limit - len)
+ return 1;
+
+ while (data <= limit - 4)
+ {
+ n2s(data, type);
+ n2s(data, size);
+
+ if (data+size > limit)
+ return 1;
+ if (custom_ext_parse(s, 1 /* server */, type, data, size, al) <= 0)
+ return 0;
+
+ data+=size;
+ }
+
+ return 1;
+ }
+
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n)
{
int al = -1;
- custom_ext_init(&s->cert->srv_ext);
+ unsigned char *ptmp = *p;
+ /*
+ * Internally supported extensions are parsed first so SNI can be handled
+ * before custom extensions. An application processing SNI will typically
+ * switch the parent context using SSL_set_SSL_CTX and custom extensions
+ * need to be handled by the new SSL_CTX structure.
+ */
if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
@@ -2475,6 +2505,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
+
+ custom_ext_init(&s->cert->srv_ext);
+ if (ssl_scan_clienthello_custom_tlsext(s, ptmp, d + n, &al) <= 0)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return 0;
+ }
+
return 1;
}