diff options
Diffstat (limited to 'src/ssl/ssl_cert.c')
-rw-r--r-- | src/ssl/ssl_cert.c | 254 |
1 files changed, 78 insertions, 176 deletions
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c index 624c41a..770912b 100644 --- a/src/ssl/ssl_cert.c +++ b/src/ssl/ssl_cert.c @@ -112,7 +112,9 @@ * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ +#include <errno.h> #include <stdio.h> +#include <string.h> #include <openssl/bio.h> #include <openssl/bn.h> @@ -126,7 +128,7 @@ #include "../crypto/dh/internal.h" #include "../crypto/directory.h" -#include "ssl_locl.h" +#include "internal.h" int SSL_get_ex_data_X509_STORE_CTX_idx(void) { @@ -178,7 +180,6 @@ CERT *ssl_cert_dup(CERT *cert) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); return NULL; } - memset(ret, 0, sizeof(CERT)); ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; @@ -213,15 +214,8 @@ CERT *ssl_cert_dup(CERT *cert) { } ret->dh_tmp_cb = cert->dh_tmp_cb; - if (cert->ecdh_tmp) { - ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); - if (ret->ecdh_tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB); - goto err; - } - } + ret->ecdh_nid = cert->ecdh_nid; ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; - ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; for (i = 0; i < SSL_PKEY_NUM; i++) { CERT_PKEY *cpk = cert->pkeys + i; @@ -231,7 +225,7 @@ CERT *ssl_cert_dup(CERT *cert) { } if (cpk->privatekey != NULL) { - rpk->privatekey = EVP_PKEY_dup(cpk->privatekey); + rpk->privatekey = EVP_PKEY_up_ref(cpk->privatekey); } if (cpk->chain) { @@ -243,34 +237,24 @@ CERT *ssl_cert_dup(CERT *cert) { } } - /* Peer sigalgs set to NULL as we get these from handshake too */ - ret->peer_sigalgs = NULL; - ret->peer_sigalgslen = 0; - /* Configured sigalgs however we copy across */ - + /* Copy over signature algorithm configuration. */ if (cert->conf_sigalgs) { - ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); + ret->conf_sigalgs = BUF_memdup(cert->conf_sigalgs, cert->conf_sigalgslen); if (!ret->conf_sigalgs) { goto err; } - memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen); ret->conf_sigalgslen = cert->conf_sigalgslen; - } else { - ret->conf_sigalgs = NULL; } if (cert->client_sigalgs) { - ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); + ret->client_sigalgs = BUF_memdup(cert->client_sigalgs, + cert->client_sigalgslen); if (!ret->client_sigalgs) { goto err; } - memcpy(ret->client_sigalgs, cert->client_sigalgs, cert->client_sigalgslen); ret->client_sigalgslen = cert->client_sigalgslen; - } else { - ret->client_sigalgs = NULL; } - /* Shared sigalgs also NULL */ - ret->shared_sigalgs = NULL; + /* Copy any custom client certificate types */ if (cert->client_certificate_types) { ret->client_certificate_types = BUF_memdup( @@ -281,8 +265,6 @@ CERT *ssl_cert_dup(CERT *cert) { ret->num_client_certificate_types = cert->num_client_certificate_types; } - ret->cert_flags = cert->cert_flags; - ret->cert_cb = cert->cert_cb; ret->cert_cb_arg = cert->cert_cb_arg; @@ -296,8 +278,6 @@ CERT *ssl_cert_dup(CERT *cert) { ret->chain_store = cert->chain_store; } - ret->ciphers_raw = NULL; - return ret; err: @@ -334,79 +314,32 @@ void ssl_cert_free(CERT *c) { return; } - if (c->dh_tmp) { - DH_free(c->dh_tmp); - } - if (c->ecdh_tmp) { - EC_KEY_free(c->ecdh_tmp); - } + DH_free(c->dh_tmp); ssl_cert_clear_certs(c); - if (c->peer_sigalgs) { - OPENSSL_free(c->peer_sigalgs); - } - if (c->conf_sigalgs) { - OPENSSL_free(c->conf_sigalgs); - } - if (c->client_sigalgs) { - OPENSSL_free(c->client_sigalgs); - } - if (c->shared_sigalgs) { - OPENSSL_free(c->shared_sigalgs); - } - if (c->client_certificate_types) { - OPENSSL_free(c->client_certificate_types); - } - if (c->verify_store) { - X509_STORE_free(c->verify_store); - } - if (c->chain_store) { - X509_STORE_free(c->chain_store); - } - if (c->ciphers_raw) { - OPENSSL_free(c->ciphers_raw); - } + OPENSSL_free(c->peer_sigalgs); + OPENSSL_free(c->conf_sigalgs); + OPENSSL_free(c->client_sigalgs); + OPENSSL_free(c->shared_sigalgs); + OPENSSL_free(c->client_certificate_types); + X509_STORE_free(c->verify_store); + X509_STORE_free(c->chain_store); OPENSSL_free(c); } -int ssl_cert_inst(CERT **o) { - /* Create a CERT if there isn't already one (which cannot really happen, as - * it is initially created in SSL_CTX_new; but the earlier code usually - * allows for that one being non-existant, so we follow that behaviour, as it - * might turn out that there actually is a reason for it -- but I'm not sure - * that *all* of the existing code could cope with s->cert being NULL, - * otherwise we could do without the initialization in SSL_CTX_new). */ - - if (o == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl_cert_inst, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - if (*o == NULL) { - *o = ssl_cert_new(); - if (*o == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE); - return 0; - } - } - - return 1; -} - -int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) * chain) { +int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) { CERT_PKEY *cpk = c->key; if (!cpk) { return 0; } - if (cpk->chain) { - sk_X509_pop_free(cpk->chain, X509_free); - } + sk_X509_pop_free(cpk->chain, X509_free); cpk->chain = chain; return 1; } -int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) * chain) { - STACK_OF(X509) * dchain; +int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) { + STACK_OF(X509) *dchain; if (!chain) { return ssl_cert_set0_chain(c, NULL); } @@ -499,22 +432,14 @@ void ssl_sess_cert_free(SESS_CERT *sc) { return; } - if (sc->cert_chain != NULL) { - sk_X509_pop_free(sc->cert_chain, X509_free); - } + sk_X509_pop_free(sc->cert_chain, X509_free); for (i = 0; i < SSL_PKEY_NUM; i++) { - if (sc->peer_pkeys[i].x509 != NULL) { - X509_free(sc->peer_pkeys[i].x509); - } + X509_free(sc->peer_pkeys[i].x509); } - if (sc->peer_dh_tmp != NULL) { - DH_free(sc->peer_dh_tmp); - } - if (sc->peer_ecdh_tmp != NULL) { - EC_KEY_free(sc->peer_ecdh_tmp); - } + DH_free(sc->peer_dh_tmp); + EC_KEY_free(sc->peer_ecdh_tmp); OPENSSL_free(sc); } @@ -524,7 +449,7 @@ int ssl_set_peer_cert_type(SESS_CERT *sc, int type) { return 1; } -int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk) { +int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) { X509 *x; int i; X509_STORE *verify_store; @@ -571,18 +496,15 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk) { return i; } -static void set_client_CA_list(STACK_OF(X509_NAME) * *ca_list, - STACK_OF(X509_NAME) * name_list) { - if (*ca_list != NULL) { - sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); - } - +static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list, + STACK_OF(X509_NAME) *name_list) { + sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); *ca_list = name_list; } -STACK_OF(X509_NAME) * SSL_dup_CA_list(STACK_OF(X509_NAME) * sk) { +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) { size_t i; - STACK_OF(X509_NAME) * ret; + STACK_OF(X509_NAME) *ret; X509_NAME *name; ret = sk_X509_NAME_new_null(); @@ -597,19 +519,19 @@ STACK_OF(X509_NAME) * SSL_dup_CA_list(STACK_OF(X509_NAME) * sk) { return ret; } -void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) * name_list) { +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) { set_client_CA_list(&(s->client_CA), name_list); } -void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) * name_list) { +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) { set_client_CA_list(&(ctx->client_CA), name_list); } -STACK_OF(X509_NAME) * SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { return ctx->client_CA; } -STACK_OF(X509_NAME) * SSL_get_client_CA_list(const SSL *s) { +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) { if (s->server) { if (s->client_CA != NULL) { return s->client_CA; @@ -625,7 +547,7 @@ STACK_OF(X509_NAME) * SSL_get_client_CA_list(const SSL *s) { } } -static int add_client_CA(STACK_OF(X509_NAME) * *sk, X509 *x) { +static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) { X509_NAME *name; if (x == NULL) { @@ -670,7 +592,7 @@ static int xname_cmp(const X509_NAME **a, const X509_NAME **b) { * * \param file the file containing one or more certs. * \return a ::STACK containing the certs. */ -STACK_OF(X509_NAME) * SSL_load_client_CA_file(const char *file) { +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { BIO *in; X509 *x = NULL; X509_NAME *xn = NULL; @@ -719,21 +641,13 @@ STACK_OF(X509_NAME) * SSL_load_client_CA_file(const char *file) { if (0) { err: - if (ret != NULL) { - sk_X509_NAME_pop_free(ret, X509_NAME_free); - } + sk_X509_NAME_pop_free(ret, X509_NAME_free); ret = NULL; } - if (sk != NULL) { - sk_X509_NAME_free(sk); - } - if (in != NULL) { - BIO_free(in); - } - if (x != NULL) { - X509_free(x); - } + sk_X509_NAME_free(sk); + BIO_free(in); + X509_free(x); if (ret != NULL) { ERR_clear_error(); } @@ -747,7 +661,7 @@ STACK_OF(X509_NAME) * SSL_load_client_CA_file(const char *file) { * already in the stack will be added. * \return 1 for success, 0 for failure. Note that in the case of failure some * certs may have been added to \c stack. */ -int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *file) { BIO *in; X509 *x = NULL; @@ -794,12 +708,8 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, ret = 0; } - if (in != NULL) { - BIO_free(in); - } - if (x != NULL) { - X509_free(x); - } + BIO_free(in); + X509_free(x); (void) sk_X509_NAME_set_cmp_func(stack, oldcmp); @@ -815,7 +725,7 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, * be included. * \return 1 for success, 0 for failure. Note that in the case of failure some * certs may have been added to \c stack. */ -int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) { OPENSSL_DIR_CTX *d = NULL; const char *filename; @@ -842,7 +752,7 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, } if (errno) { - OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, ERR_R_SYS_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_add_dir_cert_subjects_to_stack, ERR_R_SYS_LIB); ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); goto err; } @@ -881,12 +791,13 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { int no_chain = 0; size_t i; - X509 *x = NULL; - STACK_OF(X509) * extra_certs; + X509 *x = cpk->x509; + STACK_OF(X509) *extra_certs; X509_STORE *chain_store; - if (cpk) { - x = cpk->x509; + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, SSL_R_NO_CERTIFICATE_SET); + return 0; } if (s->cert->chain_store) { @@ -906,44 +817,36 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { no_chain = 1; } - /* TLSv1 sends a chain with nothing in it, instead of an alert. */ - if (!BUF_MEM_grow_clean(buf, 10)) { - OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_BUF_LIB); - return 0; - } + if (no_chain) { + if (!ssl_add_cert_to_buf(buf, l, x)) { + return 0; + } - if (x != NULL) { - if (no_chain) { + for (i = 0; i < sk_X509_num(extra_certs); i++) { + x = sk_X509_value(extra_certs, i); if (!ssl_add_cert_to_buf(buf, l, x)) { return 0; } - } else { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) { - OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_X509_LIB); - return 0; - } - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { - x = sk_X509_value(xs_ctx.chain, i); - - if (!ssl_add_cert_to_buf(buf, l, x)) { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); } - } + } else { + X509_STORE_CTX xs_ctx; - for (i = 0; i < sk_X509_num(extra_certs); i++) { - x = sk_X509_value(extra_certs, i); - if (!ssl_add_cert_to_buf(buf, l, x)) { + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_X509_LIB); return 0; } + X509_verify_cert(&xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { + x = sk_X509_value(xs_ctx.chain, i); + + if (!ssl_add_cert_to_buf(buf, l, x)) { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); } return 1; @@ -956,7 +859,7 @@ int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) { STACK_OF(X509) *chain = NULL, *untrusted = NULL; X509 *x; int i, rv = 0; - unsigned long error; + uint32_t error; if (!cpk->x509) { OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_NO_CERTIFICATE_SET); @@ -1050,8 +953,9 @@ int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) { } cpk->chain = chain; - if (rv == 0) + if (rv == 0) { rv = 1; + } err: if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) { @@ -1069,9 +973,7 @@ int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) { pstore = &c->verify_store; } - if (*pstore) { - X509_STORE_free(*pstore); - } + X509_STORE_free(*pstore); *pstore = store; if (ref && store) { |