Revision of custom extension code.
Move custom extension structures from SSL_CTX to CERT structure. This change means the form can be revised in future without binary compatibility issues. Also since CERT is part of SSL structures so per-SSL custom extensions could be supported in future as well as per SSL_CTX. Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Emilia Käsper <emilia@openssl.org>
This commit is contained in:
parent
06f5d12f51
commit
b83294fe30
6 changed files with 98 additions and 57 deletions
|
@ -368,7 +368,7 @@ static int ssl23_client_hello(SSL *s)
|
||||||
if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
|
if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
|
||||||
ssl2_compat = 0;
|
ssl2_compat = 0;
|
||||||
#endif
|
#endif
|
||||||
if (s->ctx->custom_cli_ext_records_count != 0)
|
if (s->cert->custom_cli_ext_records_count != 0)
|
||||||
ssl2_compat = 0;
|
ssl2_compat = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
19
ssl/ssl.h
19
ssl/ssl.h
|
@ -425,20 +425,6 @@ typedef int (*custom_srv_ext_second_cb_fn)(SSL *s, unsigned short ext_type,
|
||||||
const unsigned char **out,
|
const unsigned char **out,
|
||||||
unsigned short *outlen, int *al, void *arg);
|
unsigned short *outlen, int *al, void *arg);
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned short ext_type;
|
|
||||||
custom_cli_ext_first_cb_fn fn1;
|
|
||||||
custom_cli_ext_second_cb_fn fn2;
|
|
||||||
void *arg;
|
|
||||||
} custom_cli_ext_record;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned short ext_type;
|
|
||||||
custom_srv_ext_first_cb_fn fn1;
|
|
||||||
custom_srv_ext_second_cb_fn fn2;
|
|
||||||
void *arg;
|
|
||||||
} custom_srv_ext_record;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SSL_INTERN
|
#ifndef OPENSSL_NO_SSL_INTERN
|
||||||
|
@ -1160,11 +1146,6 @@ struct ssl_ctx_st
|
||||||
size_t tlsext_ellipticcurvelist_length;
|
size_t tlsext_ellipticcurvelist_length;
|
||||||
unsigned char *tlsext_ellipticcurvelist;
|
unsigned char *tlsext_ellipticcurvelist;
|
||||||
# endif /* OPENSSL_NO_EC */
|
# endif /* OPENSSL_NO_EC */
|
||||||
/* Arrays containing the callbacks for custom TLS Extensions. */
|
|
||||||
custom_cli_ext_record *custom_cli_ext_records;
|
|
||||||
size_t custom_cli_ext_records_count;
|
|
||||||
custom_srv_ext_record *custom_srv_ext_records;
|
|
||||||
size_t custom_srv_ext_records_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -423,6 +423,27 @@ CERT *ssl_cert_dup(CERT *cert)
|
||||||
ret->sec_level = cert->sec_level;
|
ret->sec_level = cert->sec_level;
|
||||||
ret->sec_ex = cert->sec_ex;
|
ret->sec_ex = cert->sec_ex;
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
|
if (cert->custom_cli_ext_records_count)
|
||||||
|
{
|
||||||
|
ret->custom_cli_ext_records = BUF_memdup(cert->custom_cli_ext_records, sizeof(custom_cli_ext_record) * cert->custom_cli_ext_records_count);
|
||||||
|
if (ret->custom_cli_ext_records == NULL)
|
||||||
|
goto err;
|
||||||
|
ret->custom_cli_ext_records_count =
|
||||||
|
cert->custom_cli_ext_records_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert->custom_srv_ext_records_count)
|
||||||
|
{
|
||||||
|
ret->custom_srv_ext_records = BUF_memdup(cert->custom_srv_ext_records, sizeof(custom_srv_ext_record) * cert->custom_srv_ext_records_count);
|
||||||
|
if (ret->custom_srv_ext_records == NULL)
|
||||||
|
goto err;
|
||||||
|
ret->custom_srv_ext_records_count =
|
||||||
|
cert->custom_srv_ext_records_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
|
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
|
||||||
|
@ -441,6 +462,13 @@ err:
|
||||||
EC_KEY_free(ret->ecdh_tmp);
|
EC_KEY_free(ret->ecdh_tmp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
|
if (ret->custom_cli_ext_records)
|
||||||
|
OPENSSL_free(ret->custom_cli_ext_records);
|
||||||
|
if (ret->custom_srv_ext_records)
|
||||||
|
OPENSSL_free(ret->custom_srv_ext_records);
|
||||||
|
#endif
|
||||||
|
|
||||||
ssl_cert_clear_certs(ret);
|
ssl_cert_clear_certs(ret);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -531,6 +559,12 @@ void ssl_cert_free(CERT *c)
|
||||||
X509_STORE_free(c->chain_store);
|
X509_STORE_free(c->chain_store);
|
||||||
if (c->ciphers_raw)
|
if (c->ciphers_raw)
|
||||||
OPENSSL_free(c->ciphers_raw);
|
OPENSSL_free(c->ciphers_raw);
|
||||||
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
|
if (c->custom_cli_ext_records)
|
||||||
|
OPENSSL_free(c->custom_cli_ext_records);
|
||||||
|
if (c->custom_srv_ext_records)
|
||||||
|
OPENSSL_free(c->custom_srv_ext_records);
|
||||||
|
#endif
|
||||||
OPENSSL_free(c);
|
OPENSSL_free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1751,7 +1751,7 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
static int cert_set_custom_cli_ext(CERT *cert, unsigned short ext_type,
|
||||||
custom_cli_ext_first_cb_fn fn1,
|
custom_cli_ext_first_cb_fn fn1,
|
||||||
custom_cli_ext_second_cb_fn fn2, void* arg)
|
custom_cli_ext_second_cb_fn fn2, void* arg)
|
||||||
{
|
{
|
||||||
|
@ -1759,19 +1759,19 @@ int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
custom_cli_ext_record* record;
|
custom_cli_ext_record* record;
|
||||||
|
|
||||||
/* Check for duplicates */
|
/* Check for duplicates */
|
||||||
for (i=0; i < ctx->custom_cli_ext_records_count; i++)
|
for (i=0; i < cert->custom_cli_ext_records_count; i++)
|
||||||
if (ext_type == ctx->custom_cli_ext_records[i].ext_type)
|
if (ext_type == cert->custom_cli_ext_records[i].ext_type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ctx->custom_cli_ext_records = OPENSSL_realloc(ctx->custom_cli_ext_records,
|
cert->custom_cli_ext_records = OPENSSL_realloc(cert->custom_cli_ext_records,
|
||||||
(ctx->custom_cli_ext_records_count + 1) *
|
(cert->custom_cli_ext_records_count + 1) *
|
||||||
sizeof(custom_cli_ext_record));
|
sizeof(custom_cli_ext_record));
|
||||||
if (!ctx->custom_cli_ext_records) {
|
if (!cert->custom_cli_ext_records) {
|
||||||
ctx->custom_cli_ext_records_count = 0;
|
cert->custom_cli_ext_records_count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ctx->custom_cli_ext_records_count++;
|
cert->custom_cli_ext_records_count++;
|
||||||
record = &ctx->custom_cli_ext_records[ctx->custom_cli_ext_records_count - 1];
|
record = &cert->custom_cli_ext_records[cert->custom_cli_ext_records_count - 1];
|
||||||
record->ext_type = ext_type;
|
record->ext_type = ext_type;
|
||||||
record->fn1 = fn1;
|
record->fn1 = fn1;
|
||||||
record->fn2 = fn2;
|
record->fn2 = fn2;
|
||||||
|
@ -1779,7 +1779,7 @@ int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
|
static int cert_set_custom_srv_ext(CERT *cert, unsigned short ext_type,
|
||||||
custom_srv_ext_first_cb_fn fn1,
|
custom_srv_ext_first_cb_fn fn1,
|
||||||
custom_srv_ext_second_cb_fn fn2, void* arg)
|
custom_srv_ext_second_cb_fn fn2, void* arg)
|
||||||
{
|
{
|
||||||
|
@ -1787,19 +1787,19 @@ int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
custom_srv_ext_record* record;
|
custom_srv_ext_record* record;
|
||||||
|
|
||||||
/* Check for duplicates */
|
/* Check for duplicates */
|
||||||
for (i=0; i < ctx->custom_srv_ext_records_count; i++)
|
for (i=0; i < cert->custom_srv_ext_records_count; i++)
|
||||||
if (ext_type == ctx->custom_srv_ext_records[i].ext_type)
|
if (ext_type == cert->custom_srv_ext_records[i].ext_type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ctx->custom_srv_ext_records = OPENSSL_realloc(ctx->custom_srv_ext_records,
|
cert->custom_srv_ext_records = OPENSSL_realloc(cert->custom_srv_ext_records,
|
||||||
(ctx->custom_srv_ext_records_count + 1) *
|
(cert->custom_srv_ext_records_count + 1) *
|
||||||
sizeof(custom_srv_ext_record));
|
sizeof(custom_srv_ext_record));
|
||||||
if (!ctx->custom_srv_ext_records) {
|
if (!cert->custom_srv_ext_records) {
|
||||||
ctx->custom_srv_ext_records_count = 0;
|
cert->custom_srv_ext_records_count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ctx->custom_srv_ext_records_count++;
|
cert->custom_srv_ext_records_count++;
|
||||||
record = &ctx->custom_srv_ext_records[ctx->custom_srv_ext_records_count - 1];
|
record = &cert->custom_srv_ext_records[cert->custom_srv_ext_records_count - 1];
|
||||||
record->ext_type = ext_type;
|
record->ext_type = ext_type;
|
||||||
record->fn1 = fn1;
|
record->fn1 = fn1;
|
||||||
record->fn2 = fn2;
|
record->fn2 = fn2;
|
||||||
|
@ -1807,6 +1807,20 @@ int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
|
custom_cli_ext_first_cb_fn fn1,
|
||||||
|
custom_cli_ext_second_cb_fn fn2, void *arg)
|
||||||
|
{
|
||||||
|
return cert_set_custom_cli_ext(ctx->cert, ext_type, fn1, fn2,arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
|
custom_srv_ext_first_cb_fn fn1,
|
||||||
|
custom_srv_ext_second_cb_fn fn2, void *arg)
|
||||||
|
{
|
||||||
|
return cert_set_custom_srv_ext(ctx->cert, ext_type, fn1, fn2,arg);
|
||||||
|
}
|
||||||
|
|
||||||
/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
|
/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
|
||||||
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
|
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
|
||||||
* length-prefixed strings).
|
* length-prefixed strings).
|
||||||
|
@ -2078,10 +2092,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
|
||||||
#ifndef OPENSSL_NO_SRP
|
#ifndef OPENSSL_NO_SRP
|
||||||
SSL_CTX_SRP_CTX_init(ret);
|
SSL_CTX_SRP_CTX_init(ret);
|
||||||
#endif
|
#endif
|
||||||
ret->custom_cli_ext_records = NULL;
|
|
||||||
ret->custom_cli_ext_records_count = 0;
|
|
||||||
ret->custom_srv_ext_records = NULL;
|
|
||||||
ret->custom_srv_ext_records_count = 0;
|
|
||||||
#ifndef OPENSSL_NO_BUF_FREELISTS
|
#ifndef OPENSSL_NO_BUF_FREELISTS
|
||||||
ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
|
ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
|
||||||
ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
|
ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
|
||||||
|
@ -2220,10 +2230,6 @@ void SSL_CTX_free(SSL_CTX *a)
|
||||||
#ifndef OPENSSL_NO_SRP
|
#ifndef OPENSSL_NO_SRP
|
||||||
SSL_CTX_SRP_CTX_free(a);
|
SSL_CTX_SRP_CTX_free(a);
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_TLSEXT
|
|
||||||
OPENSSL_free(a->custom_cli_ext_records);
|
|
||||||
OPENSSL_free(a->custom_srv_ext_records);
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
if (a->client_cert_engine)
|
if (a->client_cert_engine)
|
||||||
ENGINE_finish(a->client_cert_engine);
|
ENGINE_finish(a->client_cert_engine);
|
||||||
|
|
|
@ -532,6 +532,20 @@ typedef struct cert_pkey_st
|
||||||
#define SSL_CERT_FLAGS_CHECK_TLS_STRICT \
|
#define SSL_CERT_FLAGS_CHECK_TLS_STRICT \
|
||||||
(SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT)
|
(SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short ext_type;
|
||||||
|
custom_cli_ext_first_cb_fn fn1;
|
||||||
|
custom_cli_ext_second_cb_fn fn2;
|
||||||
|
void *arg;
|
||||||
|
} custom_cli_ext_record;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short ext_type;
|
||||||
|
custom_srv_ext_first_cb_fn fn1;
|
||||||
|
custom_srv_ext_second_cb_fn fn2;
|
||||||
|
void *arg;
|
||||||
|
} custom_srv_ext_record;
|
||||||
|
|
||||||
typedef struct cert_st
|
typedef struct cert_st
|
||||||
{
|
{
|
||||||
/* Current active set */
|
/* Current active set */
|
||||||
|
@ -628,6 +642,12 @@ typedef struct cert_st
|
||||||
unsigned char *ciphers_raw;
|
unsigned char *ciphers_raw;
|
||||||
size_t ciphers_rawlen;
|
size_t ciphers_rawlen;
|
||||||
|
|
||||||
|
/* Arrays containing the callbacks for custom TLS Extensions. */
|
||||||
|
custom_cli_ext_record *custom_cli_ext_records;
|
||||||
|
size_t custom_cli_ext_records_count;
|
||||||
|
custom_srv_ext_record *custom_srv_ext_records;
|
||||||
|
size_t custom_srv_ext_records_count;
|
||||||
|
|
||||||
/* Security callback */
|
/* Security callback */
|
||||||
int (*sec_cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex);
|
int (*sec_cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex);
|
||||||
/* Security level */
|
/* Security level */
|
||||||
|
|
22
ssl/t1_lib.c
22
ssl/t1_lib.c
|
@ -1482,17 +1482,17 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add custom TLS Extensions to ClientHello */
|
/* Add custom TLS Extensions to ClientHello */
|
||||||
if (s->ctx->custom_cli_ext_records_count)
|
if (s->cert->custom_cli_ext_records_count)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
custom_cli_ext_record* record;
|
custom_cli_ext_record* record;
|
||||||
|
|
||||||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
|
for (i = 0; i < s->cert->custom_cli_ext_records_count; i++)
|
||||||
{
|
{
|
||||||
const unsigned char* out = NULL;
|
const unsigned char* out = NULL;
|
||||||
unsigned short outlen = 0;
|
unsigned short outlen = 0;
|
||||||
|
|
||||||
record = &s->ctx->custom_cli_ext_records[i];
|
record = &s->cert->custom_cli_ext_records[i];
|
||||||
/* NULL callback sends empty extension */
|
/* NULL callback sends empty extension */
|
||||||
/* -1 from callback omits extension */
|
/* -1 from callback omits extension */
|
||||||
if (record->fn1)
|
if (record->fn1)
|
||||||
|
@ -1747,13 +1747,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++)
|
for (i = 0; i < s->cert->custom_srv_ext_records_count; i++)
|
||||||
{
|
{
|
||||||
const unsigned char *out = NULL;
|
const unsigned char *out = NULL;
|
||||||
unsigned short outlen = 0;
|
unsigned short outlen = 0;
|
||||||
int cb_retval = 0;
|
int cb_retval = 0;
|
||||||
|
|
||||||
record = &s->ctx->custom_srv_ext_records[i];
|
record = &s->cert->custom_srv_ext_records[i];
|
||||||
|
|
||||||
/* NULL callback or -1 omits extension */
|
/* NULL callback or -1 omits extension */
|
||||||
if (!record->fn2)
|
if (!record->fn2)
|
||||||
|
@ -2503,13 +2503,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
|
||||||
* so call the callback and record the extension number so that
|
* so call the callback and record the extension number so that
|
||||||
* an appropriate ServerHello may be later returned.
|
* an appropriate ServerHello may be later returned.
|
||||||
*/
|
*/
|
||||||
else if (!s->hit && s->ctx->custom_srv_ext_records_count)
|
else if (!s->hit && s->cert->custom_srv_ext_records_count)
|
||||||
{
|
{
|
||||||
custom_srv_ext_record *record;
|
custom_srv_ext_record *record;
|
||||||
|
|
||||||
for (i=0; i < s->ctx->custom_srv_ext_records_count; i++)
|
for (i=0; i < s->cert->custom_srv_ext_records_count; i++)
|
||||||
{
|
{
|
||||||
record = &s->ctx->custom_srv_ext_records[i];
|
record = &s->cert->custom_srv_ext_records[i];
|
||||||
if (type == record->ext_type)
|
if (type == record->ext_type)
|
||||||
{
|
{
|
||||||
if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
|
if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
|
||||||
|
@ -2848,14 +2848,14 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
|
||||||
/* If this extension type was not otherwise handled, but
|
/* If this extension type was not otherwise handled, but
|
||||||
* matches a custom_cli_ext_record, then send it to the c
|
* matches a custom_cli_ext_record, then send it to the c
|
||||||
* callback */
|
* callback */
|
||||||
else if (s->ctx->custom_cli_ext_records_count)
|
else if (s->cert->custom_cli_ext_records_count)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
custom_cli_ext_record* record;
|
custom_cli_ext_record* record;
|
||||||
|
|
||||||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
|
for (i = 0; i < s->cert->custom_cli_ext_records_count; i++)
|
||||||
{
|
{
|
||||||
record = &s->ctx->custom_cli_ext_records[i];
|
record = &s->cert->custom_cli_ext_records[i];
|
||||||
if (record->ext_type == type)
|
if (record->ext_type == type)
|
||||||
{
|
{
|
||||||
if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))
|
if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))
|
||||||
|
|
Loading…
Reference in a new issue