summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2012-12-26 15:21:53 +0000
committerDr. Stephen Henson <steve@openssl.org>2012-12-26 15:21:53 +0000
commitb762acadeb09618a63140e30fb385ea106730635 (patch)
tree8a22cd4ed3d9a467a6bbdd8ab88ee20e995f41cf /apps
parent7d779eefb43309319818090c27778bd3f904748e (diff)
Add support for certificate stores in CERT structure. This makes it
possible to have different stores per SSL structure or one store in the parent SSL_CTX. Include distint stores for certificate chain verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN to build and store a certificate chain in CERT structure: returing an error if the chain cannot be built: this will allow applications to test if a chain is correctly configured. Note: if the CERT based stores are not set then the parent SSL_CTX store is used to retain compatibility with existing behaviour. (backport from HEAD)
Diffstat (limited to 'apps')
-rw-r--r--apps/s_apps.h2
-rw-r--r--apps/s_cb.c32
-rw-r--r--apps/s_client.c8
-rw-r--r--apps/s_server.c71
4 files changed, 103 insertions, 10 deletions
diff --git a/apps/s_apps.h b/apps/s_apps.h
index c04e2d3611..c7e6926a27 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -155,7 +155,7 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
#ifdef HEADER_SSL_H
int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
- STACK_OF(X509) *chain);
+ STACK_OF(X509) *chain, int build_chain);
# ifndef OPENSSL_NO_TLSEXT
int set_cert_key_and_authz(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
unsigned char *authz, size_t authz_length);
diff --git a/apps/s_cb.c b/apps/s_cb.c
index 6e26d43de4..f994fbd93b 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -251,7 +251,7 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
}
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
- STACK_OF(X509) *chain)
+ STACK_OF(X509) *chain, int build_chain)
{
if (cert == NULL)
return 1;
@@ -282,6 +282,13 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
ERR_print_errors(bio_err);
return 0;
}
+ if (!chain && build_chain && !SSL_CTX_build_cert_chain(ctx, 0))
+ {
+ BIO_printf(bio_err,"error building certificate chain\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
return 1;
}
@@ -1125,6 +1132,7 @@ struct ssl_excert_st
X509 *cert;
EVP_PKEY *key;
STACK_OF(X509) *chain;
+ int build_chain;
struct ssl_excert_st *next, *prev;
};
@@ -1152,7 +1160,16 @@ static int set_cert_cb(SSL *ssl, void *arg)
{
SSL_use_certificate(ssl, exc->cert);
SSL_use_PrivateKey(ssl, exc->key);
- if (exc->chain)
+ /* NB: we wouldn't normally do this as it is
+ * not efficient building chains on each connection
+ * better to cache the chain in advance.
+ */
+ if (exc->build_chain)
+ {
+ if (!SSL_build_cert_chain(ssl, 0))
+ return 0;
+ }
+ else if (exc->chain)
SSL_set1_chain(ssl, exc->chain);
}
exc = exc->prev;
@@ -1178,6 +1195,7 @@ static int ssl_excert_prepend(SSL_EXCERT **pexc)
exc->key = NULL;
exc->chain = NULL;
exc->prev = NULL;
+ exc->build_chain = 0;
exc->next = *pexc;
*pexc = exc;
@@ -1262,6 +1280,7 @@ int args_excert(char ***pargs, int *pargc,
{
char *arg = **pargs, *argn = (*pargs)[1];
SSL_EXCERT *exc = *pexc;
+ int narg = 2;
if (!exc)
{
if (ssl_excert_prepend(&exc))
@@ -1318,6 +1337,11 @@ int args_excert(char ***pargs, int *pargc,
}
exc->chainfile = argn;
}
+ else if (strcmp(arg,"-xchain_build") == 0)
+ {
+ narg = 1;
+ exc->build_chain = 1;
+ }
else if (strcmp(arg,"-xcertform") == 0)
{
if (!argn)
@@ -1339,10 +1363,10 @@ int args_excert(char ***pargs, int *pargc,
else
return 0;
- (*pargs) += 2;
+ (*pargs) += narg;
if (pargc)
- *pargc -= 2;
+ *pargc -= narg;
*pexc = exc;
diff --git a/apps/s_client.c b/apps/s_client.c
index 999bd2043c..90b6af80cb 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -558,6 +558,7 @@ int MAIN(int argc, char **argv)
{
unsigned int off=0, clr=0;
unsigned int cert_flags=0;
+ int build_chain = 0;
SSL *con=NULL;
#ifndef OPENSSL_NO_KRB5
KSSL_CTX *kctx;
@@ -867,6 +868,8 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
CApath= *(++argv);
}
+ else if (strcmp(*argv,"-build_chain") == 0)
+ build_chain = 1;
else if (strcmp(*argv,"-CAfile") == 0)
{
if (--argc < 1) goto bad;
@@ -1201,8 +1204,6 @@ bad:
#endif
SSL_CTX_set_verify(ctx,verify,verify_callback);
- if (!set_cert_key_stuff(ctx,cert,key, NULL))
- goto end;
if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
(!SSL_CTX_set_default_verify_paths(ctx)))
@@ -1212,6 +1213,9 @@ bad:
/* goto end; */
}
+ if (!set_cert_key_stuff(ctx,cert,key, NULL, build_chain))
+ goto end;
+
#ifndef OPENSSL_NO_TLSEXT
if (curves != NULL)
if(!SSL_CTX_set1_curves_list(ctx,curves)) {
diff --git a/apps/s_server.c b/apps/s_server.c
index 92ca0a7f85..cabe0980a6 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -212,6 +212,9 @@ static int init_ssl_connection(SSL *s);
static void print_stats(BIO *bp,SSL_CTX *ctx);
static int generate_session_id(const SSL *ssl, unsigned char *id,
unsigned int *id_len);
+static int ssl_load_stores(SSL_CTX *sctx,
+ const char *vfyCApath, const char *vfyCAfile,
+ const char *chCApath, const char *chCAfile);
#ifndef OPENSSL_NO_DH
static DH *load_dh_param(const char *dhfile);
static DH *get_dh512(void);
@@ -942,6 +945,8 @@ int MAIN(int argc, char *argv[])
int badarg = 0;
short port=PORT;
char *CApath=NULL,*CAfile=NULL;
+ char *chCApath=NULL,*chCAfile=NULL;
+ char *vfyCApath=NULL,*vfyCAfile=NULL;
unsigned char *context = NULL;
char *dhfile = NULL;
#ifndef OPENSSL_NO_ECDH
@@ -951,6 +956,7 @@ int MAIN(int argc, char *argv[])
int ret=1;
int off=0;
unsigned int cert_flags = 0;
+ int build_chain = 0;
int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
int state=0;
const SSL_METHOD *meth=NULL;
@@ -1125,6 +1131,16 @@ int MAIN(int argc, char *argv[])
if (--argc < 1) goto bad;
CApath= *(++argv);
}
+ else if (strcmp(*argv,"-chainCApath") == 0)
+ {
+ if (--argc < 1) goto bad;
+ chCApath= *(++argv);
+ }
+ else if (strcmp(*argv,"-verifyCApath") == 0)
+ {
+ if (--argc < 1) goto bad;
+ vfyCApath= *(++argv);
+ }
else if (strcmp(*argv,"-no_cache") == 0)
no_cache = 1;
else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm))
@@ -1150,11 +1166,23 @@ int MAIN(int argc, char *argv[])
if (--argc < 1) goto bad;
cipher= *(++argv);
}
+ else if (strcmp(*argv,"-build_chain") == 0)
+ build_chain = 1;
else if (strcmp(*argv,"-CAfile") == 0)
{
if (--argc < 1) goto bad;
CAfile= *(++argv);
}
+ else if (strcmp(*argv,"-chainCAfile") == 0)
+ {
+ if (--argc < 1) goto bad;
+ chCAfile= *(++argv);
+ }
+ else if (strcmp(*argv,"-verifyCAfile") == 0)
+ {
+ if (--argc < 1) goto bad;
+ vfyCAfile= *(++argv);
+ }
#ifdef FIONBIO
else if (strcmp(*argv,"-nbio") == 0)
{ s_nbio=1; }
@@ -1647,6 +1675,13 @@ bad:
if (vpm)
SSL_CTX_set1_param(ctx, vpm);
+ if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile))
+ {
+ BIO_printf(bio_err, "Error loading store locations\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
#ifndef OPENSSL_NO_TLSEXT
if (s_cert2)
{
@@ -1807,19 +1842,19 @@ bad:
}
#endif
- if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain))
+ if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
#ifndef OPENSSL_NO_TLSEXT
if (s_authz_file != NULL && !SSL_CTX_use_authz_file(ctx, s_authz_file))
goto end;
#endif
#ifndef OPENSSL_NO_TLSEXT
- if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2, NULL))
+ if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2, NULL, build_chain))
goto end;
#endif
if (s_dcert != NULL)
{
- if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain))
+ if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
goto end;
}
@@ -3139,3 +3174,33 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
return 0;
return 1;
}
+
+static int ssl_load_stores(SSL_CTX *sctx,
+ const char *vfyCApath, const char *vfyCAfile,
+ const char *chCApath, const char *chCAfile)
+ {
+ X509_STORE *vfy = NULL, *ch = NULL;
+ int rv = 0;
+ if (vfyCApath || vfyCAfile)
+ {
+ vfy = X509_STORE_new();
+ if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
+ goto err;
+ SSL_CTX_set1_verify_cert_store(ctx, vfy);
+ }
+ if (chCApath || chCAfile)
+ {
+ ch = X509_STORE_new();
+ if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
+ goto err;
+ /*X509_STORE_set_verify_cb(ch, verify_callback);*/
+ SSL_CTX_set1_chain_cert_store(ctx, ch);
+ }
+ rv = 1;
+ err:
+ if (vfy)
+ X509_STORE_free(vfy);
+ if (ch)
+ X509_STORE_free(ch);
+ return rv;
+ }