From: Dr. Stephen Henson Date: Sun, 2 Feb 2014 02:51:30 +0000 (+0000) Subject: New ctrl to set current certificate. X-Git-Tag: OpenSSL_1_0_2-beta1~54 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e2f06800bce44a87596534b9f23710becf51771a;p=oweals%2Fopenssl.git New ctrl to set current certificate. New ctrl sets current certificate based on certain criteria. Currently two options: set the first valid certificate as current and set the next valid certificate as current. Using these an application can iterate over all certificates in an SSL_CTX or SSL structure. (cherry picked from commit 0f78819c8ccb7c526edbe90d5b619281366ce75c) --- diff --git a/demos/bio/server-arg.c b/demos/bio/server-arg.c index be35e6210b..0d432a4762 100644 --- a/demos/bio/server-arg.c +++ b/demos/bio/server-arg.c @@ -82,7 +82,24 @@ int main(int argc, char *argv[]) ERR_print_errors_fp(stderr); goto err; } - +#if 0 + /* Demo of how to iterate over all certificates in an SSL_CTX + * structure. + */ + { + X509 *x; + int rv; + rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST); + while (rv) + { + X509 *x = SSL_CTX_get0_certificate(ctx); + X509_NAME_print_ex_fp(stdout, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); + printf("\n"); + rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT); + } + fflush(stdout); + } +#endif /* Setup server side SSL bio */ ssl_bio=BIO_new_ssl(ctx,0); diff --git a/doc/ssl/SSL_CTX_add1_chain_cert.pod b/doc/ssl/SSL_CTX_add1_chain_cert.pod index a97969260d..0c977aa1a7 100644 --- a/doc/ssl/SSL_CTX_add1_chain_cert.pod +++ b/doc/ssl/SSL_CTX_add1_chain_cert.pod @@ -7,7 +7,8 @@ SSL_CTX_add1_chain_cert, SSL_CTX_get0_chain_certs, SSL_CTX_clear_chain_certs, SSL_set0_chain, SSL_set1_chain, SSL_add0_chain_cert, SSL_add1_chain_cert, 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 +SSL_select_current_cert, SSL_CTX_set_current_cert, SSL_set_current_cert - extra +chain certificate processing =head1 SYNOPSIS @@ -32,6 +33,8 @@ SSL_select_current_cert - extra chain certificate processing int SSL_CTX_select_current_cert(SSL_CTX *ctx, X509 *x509); int SSL_select_current_cert(SSL *ssl, X509 *x509); + int SSL_CTX_set_current_cert(SSL_CTX *ctx, long op); + int SSL_set_current_cert(SSL *ssl, long op); =head1 DESCRIPTION @@ -65,8 +68,14 @@ 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_build_cert_chain(), SSL_select_current_cert() and SSL_set_current_cert() +are similar except they apply to SSL structure B. + +SSL_CTX_set_current_cert() changes the current certificate to a value based +on the B argument. Currently B can be B to use +the first valid certificate or B to set the next valid +certificate after the current certificate. These two operations can be +used to iterate over all certificates in an B structure. 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 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index e52d2dbb42..bb1d50810d 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3438,6 +3438,9 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) case SSL_CTRL_SELECT_CURRENT_CERT: return ssl_cert_select_current(s->cert, (X509 *)parg); + case SSL_CTRL_SET_CURRENT_CERT: + return ssl_cert_set_current(s->cert, larg); + #ifndef OPENSSL_NO_EC case SSL_CTRL_GET_CURVES: { @@ -3943,6 +3946,9 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) case SSL_CTRL_SELECT_CURRENT_CERT: return ssl_cert_select_current(ctx->cert, (X509 *)parg); + case SSL_CTRL_SET_CURRENT_CERT: + return ssl_cert_set_current(ctx->cert, larg); + default: return(0); } diff --git a/ssl/ssl.h b/ssl/ssl.h index 1505816d34..e46f8c967b 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -1870,6 +1870,10 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) #define SSL_CTRL_GET_CHAIN_CERTS 115 #define SSL_CTRL_SELECT_CURRENT_CERT 116 +#define SSL_CTRL_SET_CURRENT_CERT 117 + +#define SSL_CERT_SET_FIRST 1 +#define SSL_CERT_SET_NEXT 2 #define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) @@ -1929,6 +1933,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) #define SSL_CTX_select_current_cert(ctx,x509) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509) +#define SSL_CTX_set_current_cert(ctx, op) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) + #define SSL_CTX_set0_verify_cert_store(ctx,st) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) #define SSL_CTX_set1_verify_cert_store(ctx,st) \ @@ -1954,6 +1961,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) 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_set_current_cert(ctx,op) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) #define SSL_set0_verify_cert_store(s,st) \ SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index e6234eba88..b771105785 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -646,6 +646,32 @@ int ssl_cert_select_current(CERT *c, X509 *x) 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++) + { + if (c->pkeys[i].x509) + { + 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) { c->cert_cb = cb; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 273f277a24..0faf2a1cbf 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1001,6 +1001,8 @@ int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_add0_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); +int ssl_cert_set_current(CERT *c, long arg); +X509 *ssl_cert_get0_next_certificate(CERT *c, int first); 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);