X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_cert.c;h=665623eed8ddbc2668ef34b754831057f0a1df48;hp=6dfde2f8da5950354922f2200e48106d7e035922;hb=8b8e5bed233a2d8106296c8e460be252719e0fdd;hpb=2ea803546046e61783da398306b4a19070c51448 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 6dfde2f8da..665623eed8 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -257,6 +257,7 @@ CERT *ssl_cert_dup(CERT *cert) } } ret->dh_tmp_cb = cert->dh_tmp_cb; + ret->dh_tmp_auto = cert->dh_tmp_auto; #endif #ifndef OPENSSL_NO_ECDH @@ -329,22 +330,24 @@ CERT *ssl_cert_dup(CERT *cert) } } rpk->valid_flags = 0; - if (cert->pkeys[i].authz != NULL) +#ifndef OPENSSL_NO_TLSEXT + if (cert->pkeys[i].serverinfo != NULL) { /* Just copy everything. */ - ret->pkeys[i].authz_length = - cert->pkeys[i].authz_length; - ret->pkeys[i].authz = - OPENSSL_malloc(ret->pkeys[i].authz_length); - if (ret->pkeys[i].authz == NULL) + ret->pkeys[i].serverinfo = + OPENSSL_malloc(cert->pkeys[i].serverinfo_length); + if (ret->pkeys[i].serverinfo == NULL) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); - return(NULL); + return NULL; } - memcpy(ret->pkeys[i].authz, - cert->pkeys[i].authz, - cert->pkeys[i].authz_length); + ret->pkeys[i].serverinfo_length = + cert->pkeys[i].serverinfo_length; + memcpy(ret->pkeys[i].serverinfo, + cert->pkeys[i].serverinfo, + cert->pkeys[i].serverinfo_length); } +#endif } ret->references=1; @@ -409,6 +412,8 @@ CERT *ssl_cert_dup(CERT *cert) ret->chain_store = cert->chain_store; } + ret->ciphers_raw = NULL; + return(ret); #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) @@ -458,8 +463,12 @@ void ssl_cert_clear_certs(CERT *c) cpk->chain = NULL; } #ifndef OPENSSL_NO_TLSEXT - if (cpk->authz != NULL) - OPENSSL_free(cpk->authz); + if (cpk->serverinfo) + { + OPENSSL_free(cpk->serverinfo); + cpk->serverinfo = NULL; + cpk->serverinfo_length = 0; + } #endif /* Clear all flags apart from explicit sign */ cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN; @@ -511,6 +520,8 @@ void ssl_cert_free(CERT *c) 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); } @@ -589,6 +600,60 @@ int ssl_cert_add1_chain_cert(CERT *c, X509 *x) return 1; } +int ssl_cert_select_current(CERT *c, X509 *x) + { + int i; + if (x == NULL) + return 0; + for (i = 0; i < SSL_PKEY_NUM; i++) + { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509 == x && cpk->privatekey) + { + c->key = cpk; + return 1; + } + } + + for (i = 0; i < SSL_PKEY_NUM; i++) + { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) + { + c->key = cpk; + return 1; + } + } + return 0; + } + +int ssl_cert_set_current(CERT *c, long op) + { + int i, idx; + if (!c) + return 0; + if (op == SSL_CERT_SET_FIRST) + idx = 0; + else if (op == SSL_CERT_SET_NEXT) + { + idx = (int)(c->key - c->pkeys + 1); + if (idx >= SSL_PKEY_NUM) + return 0; + } + else + return 0; + for (i = idx; i < SSL_PKEY_NUM; i++) + { + CERT_PKEY *cpk = c->key + i; + if (cpk->x509 && cpk->privatekey) + { + c->key = cpk; + return 1; + } + } + return 0; + } + void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) { c->cert_cb = cb; @@ -1049,81 +1114,74 @@ static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { BUF_MEM *buf = s->init_buf; - int no_chain; int i; X509 *x; STACK_OF(X509) *extra_certs; X509_STORE *chain_store; - if (cpk) - x = cpk->x509; - else - x = NULL; + /* TLSv1 sends a chain with nothing in it, instead of an alert */ + if (!BUF_MEM_grow_clean(buf,10)) + { + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB); + return 0; + } - if (s->cert->chain_store) - chain_store = s->cert->chain_store; - else - chain_store = s->ctx->cert_store; + if (!cpk || !cpk->x509) + return 1; + + x = cpk->x509; /* If we have a certificate specific chain use it, else use * parent ctx. */ - if (cpk && cpk->chain) + if (cpk->chain) extra_certs = cpk->chain; else extra_certs = s->ctx->extra_certs; if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) - no_chain = 1; + chain_store = NULL; + else if (s->cert->chain_store) + chain_store = s->cert->chain_store; else - no_chain = 0; + chain_store = s->ctx->cert_store; - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - if (!BUF_MEM_grow_clean(buf,10)) + if (chain_store) { - SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB); - return 0; - } - if (x != NULL) - { - if (no_chain) + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL)) { - if (!ssl_add_cert_to_buf(buf, l, x)) - return 0; + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB); + return(0); } - else + 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++) { - X509_STORE_CTX xs_ctx; + x = sk_X509_value(xs_ctx.chain, i); - if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL)) - { - SSLerr(SSL_F_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++) + if (!ssl_add_cert_to_buf(buf, l, x)) { - 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 0; } - X509_STORE_CTX_cleanup(&xs_ctx); } + X509_STORE_CTX_cleanup(&xs_ctx); } - for (i=0; ix509) { SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET); - return 0; + goto err; } + /* Rearranging and check the chain: add everything to a store */ + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) + { + chain_store = X509_STORE_new(); + if (!chain_store) + goto err; + for (i = 0; i < sk_X509_num(cpk->chain); i++) + { + x = sk_X509_value(cpk->chain, i); + if (!X509_STORE_add_cert(chain_store, x)) + { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) + goto err; + ERR_clear_error(); + } + } + /* Add EE cert too: it might be self signed */ + if (!X509_STORE_add_cert(chain_store, cpk->x509)) + { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) + goto err; + ERR_clear_error(); + } + } + else + { + if (c->chain_store) + chain_store = c->chain_store; - if (c->chain_store) - chain_store = c->chain_store; - - if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) - untrusted = cpk->chain; + if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) + untrusted = cpk->chain; + } if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) { SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB); - return 0; + goto err; } /* Set suite B flags if needed */ X509_STORE_CTX_set_flags(&xs_ctx, c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS); i = X509_verify_cert(&xs_ctx); + if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) + { + if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) + ERR_clear_error(); + i = 1; + rv = 2; + } if (i > 0) chain = X509_STORE_CTX_get1_chain(&xs_ctx); - X509_STORE_CTX_cleanup(&xs_ctx); if (i <= 0) { SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED); - return 0; + i = X509_STORE_CTX_get_error(&xs_ctx); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(i)); + + X509_STORE_CTX_cleanup(&xs_ctx); + goto err; } + X509_STORE_CTX_cleanup(&xs_ctx); if (cpk->chain) sk_X509_pop_free(cpk->chain, X509_free); /* Remove EE certificate from chain */ @@ -1172,12 +1273,26 @@ int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) X509_free(x); if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) { - x = sk_X509_pop(chain); - X509_free(x); + if (sk_X509_num(chain) > 0) + { + /* See if last cert is self signed */ + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + { + x = sk_X509_pop(chain); + X509_free(x); + } + } } cpk->chain = chain; + if (rv == 0) + rv = 1; + err: + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) + X509_STORE_free(chain_store); - return 1; + return rv; } int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)