Skip to content

Commit

Permalink
Add support for certificate stores in CERT structure. This makes it
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
snhenson committed Jul 23, 2012
1 parent 5818a07 commit 74ecfab
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 13 deletions.
13 changes: 13 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@

Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]

*) 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.

[Steve Henson]

*) New function ssl_set_client_disabled to set a ciphersuite disabled
mask based on the current session, check mask when sending client
hello and checking the requested ciphersuite.
Expand Down
2 changes: 1 addition & 1 deletion apps/s_apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
32 changes: 28 additions & 4 deletions apps/s_cb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1123,6 +1130,7 @@ struct ssl_excert_st
X509 *cert;
EVP_PKEY *key;
STACK_OF(X509) *chain;
int build_chain;
struct ssl_excert_st *next, *prev;
};

Expand Down Expand Up @@ -1150,7 +1158,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;
Expand All @@ -1176,6 +1193,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;
Expand Down Expand Up @@ -1260,6 +1278,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))
Expand Down Expand Up @@ -1316,6 +1335,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)
Expand All @@ -1337,10 +1361,10 @@ int args_excert(char ***pargs, int *pargc,
else
return 0;

(*pargs) += 2;
(*pargs) += narg;

if (pargc)
*pargc -= 2;
*pargc -= narg;

*pexc = exc;

Expand Down
8 changes: 6 additions & 2 deletions apps/s_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,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;
Expand Down Expand Up @@ -877,6 +878,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;
Expand Down Expand Up @@ -1212,8 +1215,6 @@ int MAIN(int argc, char **argv)
#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)))
Expand All @@ -1223,6 +1224,9 @@ int MAIN(int argc, char **argv)
/* 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)) {
Expand Down
72 changes: 68 additions & 4 deletions apps/s_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void);
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);
Expand Down Expand Up @@ -952,6 +955,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
Expand All @@ -961,6 +966,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;
Expand Down Expand Up @@ -1135,6 +1141,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 (strcmp(*argv,"-ext_cache") == 0)
Expand Down Expand Up @@ -1162,11 +1178,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; }
Expand Down Expand Up @@ -1672,6 +1700,13 @@ int MAIN(int argc, char *argv[])
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)
{
Expand Down Expand Up @@ -1834,19 +1869,19 @@ int MAIN(int argc, char *argv[])
}
#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;
}

Expand Down Expand Up @@ -3305,7 +3340,36 @@ static void free_sessions(void)
}
first = NULL;
}


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;
}



Expand Down
18 changes: 18 additions & 0 deletions ssl/s3_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -3449,6 +3449,15 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return 0;
return ssl3_set_req_cert_type(s->cert, parg, larg);

case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg);

case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(s->cert, parg, 0, larg);

case SSL_CTRL_SET_CHAIN_CERT_STORE:
return ssl_cert_set_cert_store(s->cert, parg, 1, larg);

default:
break;
}
Expand Down Expand Up @@ -3746,6 +3755,15 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_SET_CLIENT_CERT_TYPES:
return ssl3_set_req_cert_type(ctx->cert, parg, larg);

case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg);

case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);

case SSL_CTRL_SET_CHAIN_CERT_STORE:
return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);

case SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG:
ctx->tlsext_authz_server_audit_proof_cb_arg = parg;
break;
Expand Down
32 changes: 32 additions & 0 deletions ssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,12 @@ struct ssl_session_st
*/
#define SSL_CERT_FLAG_TLS_STRICT 0x00000001L

/* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */
#define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1
/* Con't include root CA in chain */
#define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2

/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
* they cannot be used to clear bits. */

Expand Down Expand Up @@ -1666,6 +1672,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102
#define SSL_CTRL_GET_CLIENT_CERT_TYPES 103
#define SSL_CTRL_SET_CLIENT_CERT_TYPES 104
#define SSL_CTRL_BUILD_CERT_CHAIN 105
#define SSL_CTRL_SET_VERIFY_CERT_STORE 106
#define SSL_CTRL_SET_CHAIN_CERT_STORE 107

#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
Expand Down Expand Up @@ -1716,6 +1725,17 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_CTX_add1_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
#define SSL_CTX_build_cert_chain(ctx, flags) \
SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, 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) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st)
#define SSL_CTX_set0_chain_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st)
#define SSL_CTX_set1_chain_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st)

#define SSL_set0_chain(ctx,sk) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk)
Expand All @@ -1725,6 +1745,17 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_add1_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
#define SSL_build_cert_chain(s, flags) \
SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
#define SSL_set0_verify_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
#define SSL_set1_verify_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st)
#define SSL_set0_chain_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st)
#define SSL_set1_chain_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st)

#define SSL_get1_curves(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_GET_CURVES,0,(char *)s)
#define SSL_CTX_set1_curves(ctx, clist, clistlen) \
Expand Down Expand Up @@ -2328,6 +2359,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278
#define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308
#define SSL_F_SSL_BAD_METHOD 160
#define SSL_F_SSL_BUILD_CERT_CHAIN 332
#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161
#define SSL_F_SSL_CERT_DUP 221
#define SSL_F_SSL_CERT_INST 222
Expand Down
Loading

0 comments on commit 74ecfab

Please sign in to comment.