Additional "chain_cert" functions.

PR#3169

This patch, which currently applies successfully against master and
1_0_2, adds the following functions:

SSL_[CTX_]select_current_cert() - set the current certificate without
disturbing the existing structure.

SSL_[CTX_]get0_chain_certs() - get the current certificate's chain.

SSL_[CTX_]clear_chain_certs() - clear the current certificate's chain.

The patch also adds these functions to, and fixes some existing errors
in, SSL_CTX_add1_chain_cert.pod.
(cherry picked from commit 2f56c9c015dbca45379c9a725915b3b8e765a119)
This commit is contained in:
Rob Stradling 2013-11-11 18:04:24 +01:00 committed by Dr. Stephen Henson
parent b03d0513d0
commit dc4bdf592f
5 changed files with 80 additions and 15 deletions

View File

@ -3,9 +3,11 @@
=head1 NAME =head1 NAME
SSL_CTX_set0_chain, SSL_CTX_set1_chain, SSL_CTX_add0_chain_cert, SSL_CTX_set0_chain, SSL_CTX_set1_chain, SSL_CTX_add0_chain_cert,
SSL_CTX_add1_chain_cert, SSL_set0_chain, SSL_set1_chain, SSL_CTX_add1_chain_cert, SSL_CTX_get0_chain_certs, SSL_CTX_clear_chain_certs,
SSL_add0_chain_cert, SSL_add1_chain_cert, SSL_CTX_build_cert_chain, SSL_set0_chain, SSL_set1_chain, SSL_add0_chain_cert, SSL_add1_chain_cert,
SSL_build_cert_chain - extra chain certificate processing SSL_get0_chain_certs, SSL_clear_chain_certs, SSL_CTX_build_cert_chain,
SSL_build_cert_chain, SSL_CTX_select_current_cert,
SSL_select_current_cert - extra chain certificate processing
=head1 SYNOPSIS =head1 SYNOPSIS
@ -13,36 +15,58 @@ SSL_build_cert_chain - extra chain certificate processing
int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *sk); int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *sk); int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, STACK_OF(X509) *x509); int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509);
int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509); int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509);
int SSL_CTX_get0_chain_certs(SSL_CTX *ctx, STACK_OF(X509) **sk);
int SSL_CTX_clear_chain_certs(SSL_CTX *ctx);
int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *sk); int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *sk);
int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *sk); int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *sk);
int SSL_add0_chain_cert(SSL *ssl, STACK_OF(X509) *x509); int SSL_add0_chain_cert(SSL *ssl, X509 *x509);
int SSL_add1_chain_cert(SSL *ssl, X509 *x509); int SSL_add1_chain_cert(SSL *ssl, X509 *x509);
int SSL_get0_chain_certs(SSL *ssl, STACK_OF(X509) **sk);
int SSL_clear_chain_certs(SSL *ssl);
int SSL_CTX_build_cert_chain(SSL_CTX *ctx, flags); int SSL_CTX_build_cert_chain(SSL_CTX *ctx, flags);
int SSL_build_cert_chain(SSL_CTX *ctx, flags); int SSL_build_cert_chain(SSL *ssl, flags);
int SSL_CTX_select_current_cert(SSL_CTX *ctx, X509 *x509);
int SSL_select_current_cert(SSL *ssl, X509 *x509);
=head1 DESCRIPTION =head1 DESCRIPTION
SSL_CTX_set0_chain() and SSL_CTX_set1_chain() set the certificate chain SSL_CTX_set0_chain() and SSL_CTX_set1_chain() set the certificate chain
associated with the current certificate of B<ctx> to B<sk>. If B<sk> is set associated with the current certificate of B<ctx> to B<sk>.
to B<NULL> any existing chain is cleared.
SSL_CTX_add0_chain_cert() and SSL_CTX_add1_chain_cert() append the single SSL_CTX_add0_chain_cert() and SSL_CTX_add1_chain_cert() append the single
certificate B<x509> to the chain associated with the current certificate of certificate B<x509> to the chain associated with the current certificate of
B<ctx>. B<ctx>.
SSL_CTX_get0_chain_certs() retrieves the chain associated with the current
certificate of B<ctx>.
SSL_CTX_clear_chain_certs() clears any existing chain associated with the
current certificate of B<ctx>. (This is implemented by calling
SSL_CTX_set0_chain() with B<sk> set to B<NULL>).
SSL_CTX_build_cert_chain() builds the certificate chain for B<ctx> using the SSL_CTX_build_cert_chain() builds the certificate chain for B<ctx> using the
chain store. Any existing chain certificates are used as untrusted CAs. chain store. Any existing chain certificates are used as untrusted CAs.
If the function is successful the built chain will replace any existing chain. If the function is successful the built chain will replace any existing chain.
The B<flags> parameter can be set to B<SSL_BUILD_CHAIN_FLAG_NO_ROOT> to omit The B<flags> parameter can be set to B<SSL_BUILD_CHAIN_FLAG_NO_ROOT> to omit
the root CA from the built chain. the root CA from the built chain.
SSL_set0_chain(), SSL_set1_chain(), SSL_add0_chain_cert(), SSL_add0_chain_cert() Each of these functions operates on the I<current> end entity
and SSL_build_cert_chain() are similar except they apply to SSL structure (i.e. server or client) certificate. This is the last certificate loaded or
B<ssl>. selected on the corresponding B<ctx> structure.
SSL_CTX_select_current_cert() selects B<x509> as the current end entity
certificate, but only if B<x509> has already been loaded into B<ctx> using a
function such as SSL_CTX_use_certificate().
SSL_set0_chain(), SSL_set1_chain(), SSL_add0_chain_cert(),
SSL_add1_chain_cert(), SSL_get0_chain_certs(), SSL_clear_chain_certs(),
SSL_build_cert_chain() and SSL_select_current_cert() are similar except they
apply to SSL structure B<ssl>.
All these functions are implemented as macros. Those containing a B<1> All these functions are implemented as macros. Those containing a B<1>
increment the reference count of the supplied certificate or chain so it must increment the reference count of the supplied certificate or chain so it must
@ -56,10 +80,6 @@ The chains associate with an SSL_CTX structure are copied to any SSL
structures when SSL_new() is called. SSL structures will not be affected structures when SSL_new() is called. SSL structures will not be affected
by any chains subsequently changed in the parent SSL_CTX. by any chains subsequently changed in the parent SSL_CTX.
Each of these functions operates on the I<current> end entity
(i.e. server or client) certificate. This is the last certificate set
on the corresponding B<ctx> or B<ssl> structure.
One chain can be set for each key type supported by a server. So, for example, One chain can be set for each key type supported by a server. So, for example,
an RSA and a DSA certificate can (and often will) have different chains. an RSA and a DSA certificate can (and often will) have different chains.

View File

@ -3431,6 +3431,13 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
else else
return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg); return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = s->cert->key->chain;
break;
case SSL_CTRL_SELECT_CURRENT_CERT:
return ssl_cert_select_current(s->cert, (X509 *)parg);
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_CURVES: case SSL_CTRL_GET_CURVES:
{ {
@ -3929,6 +3936,13 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
else else
return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg); return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = ctx->cert->key->chain;
break;
case SSL_CTRL_SELECT_CURRENT_CERT:
return ssl_cert_select_current(ctx->cert, (X509 *)parg);
default: default:
return(0); return(0);
} }

View File

@ -1863,6 +1863,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_TLSA_RECORD 113 #define SSL_CTRL_SET_TLSA_RECORD 113
#define SSL_CTRL_PULL_TLSA_RECORD 114 #define SSL_CTRL_PULL_TLSA_RECORD 114
#define SSL_CTRL_GET_CHAIN_CERTS 115
#define SSL_CTRL_SELECT_CURRENT_CERT 116
#define DTLSv1_get_timeout(ssl, arg) \ #define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
#define DTLSv1_handle_timeout(ssl) \ #define DTLSv1_handle_timeout(ssl) \
@ -1912,8 +1915,14 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_CTX_add1_chain_cert(ctx,x509) \ #define SSL_CTX_add1_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
#define SSL_CTX_get0_chain_certs(ctx,px509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
#define SSL_CTX_clear_chain_certs(ctx) \
SSL_CTX_set0_chain(ctx,NULL)
#define SSL_CTX_build_cert_chain(ctx, flags) \ #define SSL_CTX_build_cert_chain(ctx, flags) \
SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
#define SSL_CTX_select_current_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509)
#define SSL_CTX_set0_verify_cert_store(ctx,st) \ #define SSL_CTX_set0_verify_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
@ -1932,8 +1941,15 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_add1_chain_cert(ctx,x509) \ #define SSL_add1_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
#define SSL_get0_chain_certs(ctx,px509) \
SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
#define SSL_clear_chain_certs(ctx) \
SSL_set0_chain(ctx,NULL)
#define SSL_build_cert_chain(s, flags) \ #define SSL_build_cert_chain(s, flags) \
SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
#define SSL_select_current_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509)
#define SSL_set0_verify_cert_store(s,st) \ #define SSL_set0_verify_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
#define SSL_set1_verify_cert_store(s,st) \ #define SSL_set1_verify_cert_store(s,st) \

View File

@ -621,6 +621,20 @@ int ssl_cert_add1_chain_cert(CERT *c, X509 *x)
return 1; return 1;
} }
int ssl_cert_select_current(CERT *c, X509 *x)
{
int i;
for (i = 0; i < SSL_PKEY_NUM; i++)
{
if (c->pkeys[i].x509 == x)
{
c->key = &c->pkeys[i];
return 1;
}
}
return 0;
}
void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg)
{ {
c->cert_cb = cb; c->cert_cb = cb;

View File

@ -1000,6 +1000,7 @@ int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain);
int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain);
int ssl_cert_add0_chain_cert(CERT *c, X509 *x); int ssl_cert_add0_chain_cert(CERT *c, X509 *x);
int ssl_cert_add1_chain_cert(CERT *c, X509 *x); int ssl_cert_add1_chain_cert(CERT *c, X509 *x);
int ssl_cert_select_current(CERT *c, X509 *x);
void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg); void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg);
int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);