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.
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 5c8aa13..ed50be1 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3431,6 +3431,9 @@
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:
{
@@ -3937,6 +3940,9 @@
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 aa3be29..ee5e996 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1942,6 +1942,10 @@
#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)
@@ -2001,6 +2005,9 @@
#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) \
@@ -2026,6 +2033,8 @@
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 005d82d..47c8b86 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -624,6 +624,32 @@
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 c493f7e..fd6b883 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -999,6 +999,8 @@
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);