}
}
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;
ret->chain_store = cert->chain_store;
}
+ ret->ciphers_raw = NULL;
+
return(ret);
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
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;
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);
}
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;
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; i<sk_X509_num(extra_certs); i++)
+ else
{
- x=sk_X509_value(extra_certs,i);
if (!ssl_add_cert_to_buf(buf, l, x))
return 0;
+ 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;
+ }
}
-
return 1;
}
X509_STORE_CTX xs_ctx;
STACK_OF(X509) *chain = NULL, *untrusted = NULL;
X509 *x;
- int i;
+ int i, rv = 0;
+ unsigned long error;
if (!cpk->x509)
{
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 */
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)