int extdatalen=0;
unsigned char *ret = p;
- /* don't add extensions for SSLv3 */
- if (s->client_version == SSL3_VERSION)
+ /* don't add extensions for SSLv3 unless doing secure renegotiation */
+ if (s->client_version == SSL3_VERSION
+ && !s->s3->send_connection_binding)
return p;
ret+=2;
ret+=size_str;
}
-
- /* Add the renegotiation option: TODOEKR switch */
- {
+
+ /* Add RI if renegotiating */
+ if (s->new_session)
+ {
int el;
if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
}
}
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
+ s->version != DTLS1_VERSION)
{
int i;
long extlen, idlen, itmp;
int extdatalen=0;
unsigned char *ret = p;
- /* don't add extensions for SSLv3 */
- if (s->version == SSL3_VERSION)
+ /* don't add extensions for SSLv3, unless doing secure renegotiation */
+ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
return p;
ret+=2;
s2n(0,ret);
}
- if(s->s3->send_connection_binding)
+ if(s->s3->send_connection_binding)
{
int el;
if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
{
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
{
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
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;
- }
+ goto ri_check;
+
n2s(data,len);
if (data > (d+n-len))
- return 1;
+ goto ri_check;
while (data <= (d+n-4))
{
n2s(data,size);
if (data+size > (d+n))
- return 1;
+ goto ri_check;
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size,
switch (servname_type)
{
case TLSEXT_NAMETYPE_host_name:
- if (s->session->tlsext_hostname == NULL)
+ if (!s->hit)
{
- if (len > TLSEXT_MAXLEN_host_name ||
- ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
+ if(s->session->tlsext_hostname)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (len > TLSEXT_MAXLEN_host_name)
{
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
}
+ if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
memcpy(s->session->tlsext_hostname, sdata, len);
s->session->tlsext_hostname[len]='\0';
if (strlen(s->session->tlsext_hostname) != len) {
}
else
- s->servername_done = strlen(s->session->tlsext_hostname) == len
+ s->servername_done = s->session->tlsext_hostname
+ && strlen(s->session->tlsext_hostname) == len
&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
break;
return 0;
renegotiate_seen = 1;
}
- else if (type == TLSEXT_TYPE_status_request
- && s->ctx->tlsext_status_cb)
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
{
if (size < 5)
}
n2s(data, idsize);
dsize -= 2 + idsize;
+ size -= 2 + idsize;
if (dsize < 0)
{
*al = SSL_AD_DECODE_ERROR;
}
/* Read in request_extensions */
+ if (size < 2)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
n2s(data,dsize);
size -= 2;
- if (dsize > size)
+ if (dsize != size)
{
*al = SSL_AD_DECODE_ERROR;
return 0;
sdata = data;
if (dsize > 0)
{
+ if (s->tlsext_ocsp_exts)
+ {
+ sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+ X509_EXTENSION_free);
+ }
+
s->tlsext_ocsp_exts =
d2i_X509_EXTENSIONS(NULL,
&sdata, dsize);
data+=size;
}
+ *p = data;
- if (s->new_session && !renegotiate_seen
- && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+ ri_check:
+
+ /* Need RI if renegotiating */
+
+ if (!renegotiate_seen && s->new_session &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
{
- *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
- *p = data;
return 1;
}
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
{
+ unsigned short length;
unsigned short type;
unsigned short size;
- unsigned short len;
unsigned char *data = *p;
int tlsext_servername = 0;
int renegotiate_seen = 0;
if (data >= (d+n-2))
+ goto ri_check;
+
+ n2s(data,length);
+ if (data+length != d+n)
{
- /* 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;
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
}
- n2s(data,len);
-
while(data <= (d+n-4))
{
n2s(data,type);
n2s(data,size);
if (data+size > (d+n))
- return 1;
+ goto ri_check;
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 1, type, data, size,
}
s->tlsext_ticket_expected = 1;
}
- else if (type == TLSEXT_TYPE_status_request)
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION)
{
/* MUST be empty and only sent if we've requested
* a status request message.
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)
}
*p = data;
+
+ ri_check:
+
+ /* Determine if we need to see RI. Strictly speaking if we want to
+ * avoid an attack we should *always* see RI even on initial server
+ * hello because the client doesn't see any renegotiation during an
+ * attack. However this would mean we could not connect to any server
+ * which doesn't support RI so for the immediate future tolerate RI
+ * absence on initial connect only.
+ */
+ if (!renegotiate_seen
+ && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
+ && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+ {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
return 1;
}