From eb90a483ad85e9dc430610a78362837ad344cac1 Mon Sep 17 00:00:00 2001 From: Ben Laurie Date: Sun, 28 Feb 1999 17:41:55 +0000 Subject: [PATCH] Add functions to add certs to stacks, used for CA file/path stuff in servers. --- CHANGES | 8 +++ crypto/bio/bio.h | 4 +- crypto/stack/stack.c | 6 +- crypto/stack/stack.h | 4 +- openssl.doxy | 2 +- ssl/ssl.err | 7 +- ssl/ssl.h | 11 ++- ssl/ssl_cert.c | 160 +++++++++++++++++++++++++++++++++---------- ssl/ssl_err.c | 7 +- 9 files changed, 161 insertions(+), 48 deletions(-) diff --git a/CHANGES b/CHANGES index 107dd7d3ef..aa6ba7859d 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,14 @@ Changes between 0.9.1c and 0.9.2 + *) Add new certificate file to stack functions, SSL_add_cert_file_to_stack() + and SSL_add_cert_dir_to_stack(). These largely supplant + SSL_load_client_CA_file(), and can be used to add multiple certs easily to + a stack (usually this is then handed to SSL_CTX_set_client_CA_list()). + This means that Apache-SSL and similar packages don't have to mess around + to add as many CAs as they want to the preferred list. + [Ben Laurie] + *) Experiment with doxygen documentation. Currently only partially applied to ssl/ssl_lib.c. See http://www.stack.nl/~dimitri/doxygen/index.html, and run doxygen with diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index 82aaf31719..9206f8d734 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -383,8 +383,10 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), #define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) #define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) +/* name is cast to lose const, but might be better to route through a function + so we can do it safely */ #define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ - BIO_CLOSE|BIO_FP_READ,name) + BIO_CLOSE|BIO_FP_READ,(char *)name) #define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ BIO_CLOSE|BIO_FP_WRITE,name) #define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index 7b96326156..683468264a 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c @@ -82,13 +82,17 @@ char *STACK_version="Stack part of OpenSSL 0.9.2 31-Dec-1998"; #include -void sk_set_cmp_func(sk,c) +int (*sk_set_cmp_func(sk,c))() STACK *sk; int (*c)(); { + int (*old)()=sk->comp; + if (sk->comp != c) sk->sorted=0; sk->comp=c; + + return old; } STACK *sk_dup(sk) diff --git a/crypto/stack/stack.h b/crypto/stack/stack.h index 615eb6ff94..6dc52db63c 100644 --- a/crypto/stack/stack.h +++ b/crypto/stack/stack.h @@ -91,7 +91,7 @@ int sk_unshift(STACK *st,char *data); char *sk_shift(STACK *st); char *sk_pop(STACK *st); void sk_zero(STACK *st); -void sk_set_cmp_func(STACK *sk, int (*c)()); +int (*sk_set_cmp_func(STACK *sk, int (*c)()))(); STACK *sk_dup(STACK *st); #else @@ -108,7 +108,7 @@ int sk_unshift(); char *sk_shift(); char *sk_pop(); void sk_zero(); -void sk_set_cmp_func(); +int (*sk_set_cmp_func())(); STACK *sk_dup(); #endif diff --git a/openssl.doxy b/openssl.doxy index c92e03e688..479c311470 100644 --- a/openssl.doxy +++ b/openssl.doxy @@ -1,7 +1,7 @@ PROJECT_NAME=OpenSSL GENERATE_LATEX=no OUTPUT_DIRECTORY=doxygen -INPUT=ssl +INPUT=ssl include FILE_PATTERNS=*.c *.h RECURSIVE=yes PREDEFINED=DOXYGEN diff --git a/ssl/ssl.err b/ssl/ssl.err index ad86fbca50..11a857a7f7 100644 --- a/ssl/ssl.err +++ b/ssl/ssl.err @@ -34,6 +34,7 @@ #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 #define SSL_F_SSL3_CLIENT_HELLO 131 #define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTRL 213 #define SSL_F_SSL3_CTX_CTRL 133 #define SSL_F_SSL3_ENC 134 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 @@ -61,8 +62,11 @@ #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_CERT_DIR_TO_STACK 215 +#define SSL_F_SSL_ADD_CERT_FILE_TO_STACK 216 #define SSL_F_SSL_BAD_METHOD 160 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_INSTANTIATE 214 #define SSL_F_SSL_CERT_NEW 162 #define SSL_F_SSL_CHECK_PRIVATE_KEY 163 #define SSL_F_SSL_CLEAR 164 @@ -113,8 +117,6 @@ #define SSL_F_TLS1_ENC 210 #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 #define SSL_F_WRITE_PENDING 212 -#define SSL_F_SSL3_CTRL 213 -#define SSL_F_SSL_CERT_INSTANTIATE 214 /* Reason codes. */ #define SSL_R_APP_DATA_IN_HANDSHAKE 100 @@ -216,6 +218,7 @@ #define SSL_R_NULL_SSL_METHOD_PASSED 196 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 #define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PATH_TOO_LONG 270 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 #define SSL_R_PEER_ERROR 200 #define SSL_R_PEER_ERROR_CERTIFICATE 201 diff --git a/ssl/ssl.h b/ssl/ssl.h index 594ca96249..f69eea0aeb 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -859,6 +859,8 @@ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); STACK * SSL_load_client_CA_file(char *file); +int SSL_add_cert_file_to_stack(STACK *stackCAs,const char *file); +int SSL_add_cert_dir_to_stack(STACK *stackCAs,const char *dir); #endif void ERR_load_SSL_strings(void ); @@ -1111,6 +1113,8 @@ int SSL_CTX_use_RSAPrivateKey_file(); int SSL_CTX_use_PrivateKey_file(); int SSL_CTX_use_certificate_file(); STACK * SSL_load_client_CA_file(); +int SSL_add_cert_file_to_stack(); +int SSL_add_cert_dir_to_stack(); #endif void ERR_load_SSL_strings(); @@ -1317,6 +1321,7 @@ void SSL_set_tmp_dh_callback(); #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 #define SSL_F_SSL3_CLIENT_HELLO 131 #define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTRL 213 #define SSL_F_SSL3_CTX_CTRL 133 #define SSL_F_SSL3_ENC 134 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 @@ -1344,8 +1349,11 @@ void SSL_set_tmp_dh_callback(); #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_CERT_DIR_TO_STACK 215 +#define SSL_F_SSL_ADD_CERT_FILE_TO_STACK 216 #define SSL_F_SSL_BAD_METHOD 160 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_INSTANTIATE 214 #define SSL_F_SSL_CERT_NEW 162 #define SSL_F_SSL_CHECK_PRIVATE_KEY 163 #define SSL_F_SSL_CLEAR 164 @@ -1396,8 +1404,6 @@ void SSL_set_tmp_dh_callback(); #define SSL_F_TLS1_ENC 210 #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 #define SSL_F_WRITE_PENDING 212 -#define SSL_F_SSL3_CTRL 213 -#define SSL_F_SSL_CERT_INSTANTIATE 214 /* Reason codes. */ #define SSL_R_APP_DATA_IN_HANDSHAKE 100 @@ -1499,6 +1505,7 @@ void SSL_set_tmp_dh_callback(); #define SSL_R_NULL_SSL_METHOD_PASSED 196 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 #define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PATH_TOO_LONG 270 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 #define SSL_R_PEER_ERROR 200 #define SSL_R_PEER_ERROR_CERTIFICATE 201 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 9f06b6966d..909af7c984 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* ssl/ssl_cert.c */ +/*! \file ssl/ssl_cert.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,6 +57,8 @@ */ #include +#include +#include #include "objects.h" #include "bio.h" #include "pem.h" @@ -100,8 +102,7 @@ CERT *ssl_cert_new() return(ret); } -void ssl_cert_free(c) -CERT *c; +void ssl_cert_free(CERT *c) { int i; @@ -165,17 +166,13 @@ int ssl_cert_instantiate(CERT **o, CERT *d) return(1); } -int ssl_set_cert_type(c, type) -CERT *c; -int type; +int ssl_set_cert_type(CERT *c,int type) { c->cert_type=type; return(1); } -int ssl_verify_cert_chain(s,sk) -SSL *s; -STACK *sk; +int ssl_verify_cert_chain(SSL *s,STACK *sk) { X509 *x; int i; @@ -208,9 +205,7 @@ STACK *sk; return(i); } -static void set_client_CA_list(ca_list,list) -STACK **ca_list; -STACK *list; +static void set_client_CA_list(STACK **ca_list,STACK *list) { if (*ca_list != NULL) sk_pop_free(*ca_list,X509_NAME_free); @@ -218,8 +213,7 @@ STACK *list; *ca_list=list; } -STACK *SSL_dup_CA_list(sk) -STACK *sk; +STACK *SSL_dup_CA_list(STACK *sk) { int i; STACK *ret; @@ -238,28 +232,22 @@ STACK *sk; return(ret); } -void SSL_set_client_CA_list(s,list) -SSL *s; -STACK *list; +void SSL_set_client_CA_list(SSL *s,STACK *list) { set_client_CA_list(&(s->client_CA),list); } -void SSL_CTX_set_client_CA_list(ctx,list) -SSL_CTX *ctx; -STACK *list; +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK *list) { set_client_CA_list(&(ctx->client_CA),list); } -STACK *SSL_CTX_get_client_CA_list(ctx) -SSL_CTX *ctx; +STACK *SSL_CTX_get_client_CA_list(SSL_CTX *ctx) { return(ctx->client_CA); } -STACK *SSL_get_client_CA_list(s) -SSL *s; +STACK *SSL_get_client_CA_list(SSL *s) { if (s->type == SSL_ST_CONNECT) { /* we are in the client */ @@ -278,9 +266,7 @@ SSL *s; } } -static int add_client_CA(sk,x) -STACK **sk; -X509 *x; +static int add_client_CA(STACK **sk,X509 *x) { X509_NAME *name; @@ -299,29 +285,31 @@ X509 *x; return(1); } -int SSL_add_client_CA(ssl,x) -SSL *ssl; -X509 *x; +int SSL_add_client_CA(SSL *ssl,X509 *x) { return(add_client_CA(&(ssl->client_CA),x)); } -int SSL_CTX_add_client_CA(ctx,x) -SSL_CTX *ctx; -X509 *x; +int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) { return(add_client_CA(&(ctx->client_CA),x)); } -static int name_cmp(a,b) -X509_NAME **a,**b; +static int name_cmp(X509_NAME **a,X509_NAME **b) { return(X509_NAME_cmp(*a,*b)); } #ifndef NO_STDIO -STACK *SSL_load_client_CA_file(file) -char *file; +/*! + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK *SSL_load_client_CA_file(char *file) { BIO *in; X509 *x=NULL; @@ -372,3 +360,101 @@ err: } #endif +/*! + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_cert_file_to_stack(STACK *stack,const char *file) + { + BIO *in; + X509 *x=NULL; + X509_NAME *xn=NULL; + int ret=1; + int (*oldcmp)(); + + oldcmp=sk_set_cmp_func(stack,name_cmp); + + in=BIO_new(BIO_s_file_internal()); + + if (ret == NULL || in == NULL) + { + SSLerr(SSL_F_SSL_ADD_CERT_FILE_TO_STACK,ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in,file)) + goto err; + + for (;;) + { + if (PEM_read_bio_X509(in,&x,NULL) == NULL) + break; + if ((xn=X509_get_subject_name(x)) == NULL) goto err; + xn=X509_NAME_dup(xn); + if (xn == NULL) goto err; + if (sk_find(stack,(char *)xn) >= 0) + X509_NAME_free(xn); + else + sk_push(stack,(char *)xn); + } + + if (0) + { +err: + ret=0; + } + if(in != NULL) + BIO_free(in); + if(x != NULL) + X509_free(x); + + sk_set_cmp_func(stack,oldcmp); + + return ret; + } + +/*! + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_cert_file_to_stack() that are not already in the stack will be + * included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_cert_dir_to_stack(STACK *stack,const char *dir) + { + DIR *d=opendir(dir); + struct dirent *dstruct; + + /* Note that a side effect is that the CAs will be sorted by name */ + if(!d) + { + SSLerr(SSL_F_SSL_ADD_CERT_DIR_TO_STACK,ERR_R_MALLOC_FAILURE); + return 0; + } + + while((dstruct=readdir(d))) + { + char buf[1024]; + + if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf) + { + SSLerr(SSL_F_SSL_ADD_CERT_DIR_TO_STACK,SSL_R_PATH_TOO_LONG); + return 0; + } + + sprintf(buf,"%s/%s",dir,dstruct->d_name); + if(!SSL_add_cert_file_to_stack(stack,buf)) + return 0; + } + + return 1; + } diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index c850335ca1..137ac4af32 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -96,6 +96,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,0), "SSL3_CHECK_CERT_AND_ALGORITHM"}, {ERR_PACK(0,SSL_F_SSL3_CLIENT_HELLO,0), "SSL3_CLIENT_HELLO"}, {ERR_PACK(0,SSL_F_SSL3_CONNECT,0), "SSL3_CONNECT"}, +{ERR_PACK(0,SSL_F_SSL3_CTRL,0), "SSL3_CTRL"}, {ERR_PACK(0,SSL_F_SSL3_CTX_CTRL,0), "SSL3_CTX_CTRL"}, {ERR_PACK(0,SSL_F_SSL3_ENC,0), "SSL3_ENC"}, {ERR_PACK(0,SSL_F_SSL3_GET_CERTIFICATE_REQUEST,0), "SSL3_GET_CERTIFICATE_REQUEST"}, @@ -123,8 +124,11 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0), "SSL3_SETUP_KEY_BLOCK"}, {ERR_PACK(0,SSL_F_SSL3_WRITE_BYTES,0), "SSL3_WRITE_BYTES"}, {ERR_PACK(0,SSL_F_SSL3_WRITE_PENDING,0), "SSL3_WRITE_PENDING"}, +{ERR_PACK(0,SSL_F_SSL_ADD_CERT_DIR_TO_STACK,0), "SSL_add_cert_dir_to_stack"}, +{ERR_PACK(0,SSL_F_SSL_ADD_CERT_FILE_TO_STACK,0), "SSL_add_cert_file_to_stack"}, {ERR_PACK(0,SSL_F_SSL_BAD_METHOD,0), "SSL_BAD_METHOD"}, {ERR_PACK(0,SSL_F_SSL_BYTES_TO_CIPHER_LIST,0), "SSL_BYTES_TO_CIPHER_LIST"}, +{ERR_PACK(0,SSL_F_SSL_CERT_INSTANTIATE,0), "SSL_CERT_INSTANTIATE"}, {ERR_PACK(0,SSL_F_SSL_CERT_NEW,0), "SSL_CERT_NEW"}, {ERR_PACK(0,SSL_F_SSL_CHECK_PRIVATE_KEY,0), "SSL_check_private_key"}, {ERR_PACK(0,SSL_F_SSL_CLEAR,0), "SSL_clear"}, @@ -175,8 +179,6 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_TLS1_ENC,0), "TLS1_ENC"}, {ERR_PACK(0,SSL_F_TLS1_SETUP_KEY_BLOCK,0), "TLS1_SETUP_KEY_BLOCK"}, {ERR_PACK(0,SSL_F_WRITE_PENDING,0), "WRITE_PENDING"}, -{ERR_PACK(0,SSL_F_SSL3_CTRL,0), "SSL3_CTRL"}, -{ERR_PACK(0,SSL_F_SSL_CERT_INSTANTIATE,0), "SSL_CERT_INSTANTIATE"}, {0,NULL}, }; @@ -281,6 +283,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_NULL_SSL_METHOD_PASSED ,"null ssl method passed"}, {SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED ,"old session cipher not returned"}, {SSL_R_PACKET_LENGTH_TOO_LONG ,"packet length too long"}, +{SSL_R_PATH_TOO_LONG ,"path too long"}, {SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE ,"peer did not return a certificate"}, {SSL_R_PEER_ERROR ,"peer error"}, {SSL_R_PEER_ERROR_CERTIFICATE ,"peer error certificate"}, -- 2.25.1