Trying cherrypick:
Add support for arbitrary TLS extensions. Contributed by Trevor Perrin. Conflicts: CHANGES ssl/ssl.h ssl/ssltest.c test/testssl Fix compilation due to #endif. Cherrypicking more stuff. Cleanup of custom extension stuff. serverinfo rejects non-empty extensions. Omit extension if no relevant serverinfo data. Improve error-handling in serverinfo callback. Cosmetic cleanups. s_client documentation. s_server documentation. SSL_CTX_serverinfo documentation. Cleaup -1 and NULL callback handling for custom extensions, add tests. Cleanup ssl_rsa.c serverinfo code. Whitespace cleanup. Improve comments in ssl.h for serverinfo. Whitespace. Cosmetic cleanup. Reject non-zero-len serverinfo extensions. Whitespace. Make it build. Conflicts: test/testssl
This commit is contained in:
143
ssl/t1_lib.c
143
ssl/t1_lib.c
@@ -1400,6 +1400,40 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
|
||||
*(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
|
||||
}
|
||||
|
||||
/* Add custom TLS Extensions to ClientHello */
|
||||
if (s->ctx->custom_cli_ext_records_count)
|
||||
{
|
||||
size_t i;
|
||||
custom_cli_ext_record* record;
|
||||
|
||||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
|
||||
{
|
||||
const unsigned char* out = NULL;
|
||||
unsigned short outlen = 0;
|
||||
|
||||
record = &s->ctx->custom_cli_ext_records[i];
|
||||
/* NULL callback sends empty extension */
|
||||
/* -1 from callback omits extension */
|
||||
if (record->fn1)
|
||||
{
|
||||
int cb_retval = 0;
|
||||
cb_retval = record->fn1(s, record->ext_type,
|
||||
&out, &outlen,
|
||||
record->arg);
|
||||
if (cb_retval == 0)
|
||||
return NULL; /* error */
|
||||
if (cb_retval == -1)
|
||||
continue; /* skip this extension */
|
||||
}
|
||||
if (limit < ret + 4 + outlen)
|
||||
return NULL;
|
||||
s2n(record->ext_type, ret);
|
||||
s2n(outlen, ret);
|
||||
memcpy(ret, out, outlen);
|
||||
ret += outlen;
|
||||
}
|
||||
}
|
||||
|
||||
if ((extdatalen = ret-p-2) == 0)
|
||||
return p;
|
||||
|
||||
@@ -1667,6 +1701,47 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
|
||||
}
|
||||
}
|
||||
|
||||
/* If custom types were sent in ClientHello, add ServerHello responses */
|
||||
if (s->s3->tlsext_custom_types_count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < s->s3->tlsext_custom_types_count; i++)
|
||||
{
|
||||
size_t j;
|
||||
custom_srv_ext_record *record;
|
||||
|
||||
for (j = 0; j < s->ctx->custom_srv_ext_records_count; j++)
|
||||
{
|
||||
record = &s->ctx->custom_srv_ext_records[j];
|
||||
if (s->s3->tlsext_custom_types[i] == record->ext_type)
|
||||
{
|
||||
const unsigned char *out = NULL;
|
||||
unsigned short outlen = 0;
|
||||
int cb_retval = 0;
|
||||
|
||||
/* NULL callback or -1 omits extension */
|
||||
if (!record->fn2)
|
||||
break;
|
||||
cb_retval = record->fn2(s, record->ext_type,
|
||||
&out, &outlen,
|
||||
record->arg);
|
||||
if (cb_retval == 0)
|
||||
return NULL; /* error */
|
||||
if (cb_retval == -1)
|
||||
break; /* skip this extension */
|
||||
if (limit < ret + 4 + outlen)
|
||||
return NULL;
|
||||
s2n(record->ext_type, ret);
|
||||
s2n(outlen, ret);
|
||||
memcpy(ret, out, outlen);
|
||||
ret += outlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((extdatalen = ret-p-2)== 0)
|
||||
return p;
|
||||
|
||||
@@ -2235,6 +2310,54 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 && s->ctx->custom_srv_ext_records_count)
|
||||
{
|
||||
custom_srv_ext_record *record;
|
||||
|
||||
for (i=0; i < s->ctx->custom_srv_ext_records_count; i++)
|
||||
{
|
||||
record = &s->ctx->custom_srv_ext_records[i];
|
||||
if (type == record->ext_type)
|
||||
{
|
||||
/* Error on duplicate TLS Extensions */
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < s->s3->tlsext_custom_types_count; j++)
|
||||
{
|
||||
if (s->s3->tlsext_custom_types[j] == type)
|
||||
{
|
||||
*al = TLS1_AD_DECODE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback */
|
||||
if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
|
||||
return 0;
|
||||
|
||||
/* Add the (non-duplicated) entry */
|
||||
s->s3->tlsext_custom_types_count++;
|
||||
s->s3->tlsext_custom_types = OPENSSL_realloc(
|
||||
s->s3->tlsext_custom_types,
|
||||
s->s3->tlsext_custom_types_count*2);
|
||||
if (s->s3->tlsext_custom_types == NULL)
|
||||
{
|
||||
s->s3->tlsext_custom_types = 0;
|
||||
*al = TLS1_AD_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
s->s3->tlsext_custom_types[
|
||||
s->s3->tlsext_custom_types_count-1] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data+=size;
|
||||
}
|
||||
|
||||
@@ -2542,6 +2665,26 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
|
||||
|
||||
s->s3->tlsext_authz_server_promised = 1;
|
||||
}
|
||||
|
||||
/* If this extension type was not otherwise handled, but
|
||||
* matches a custom_cli_ext_record, then send it to the c
|
||||
* callback */
|
||||
else if (s->ctx->custom_cli_ext_records_count)
|
||||
{
|
||||
size_t i;
|
||||
custom_cli_ext_record* record;
|
||||
|
||||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
|
||||
{
|
||||
record = &s->ctx->custom_cli_ext_records[i];
|
||||
if (record->ext_type == type)
|
||||
{
|
||||
if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data += size;
|
||||
}
|
||||
|
Reference in New Issue
Block a user