X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_cert.c;h=cc3df568303bb4da481019ad20b118a930b637ef;hp=c1cb86e1b7d5f6b5f0a545bc58260ddd84cdb310;hb=a49034aba9f9adf4278e23ab7dc8cb8bb1b83892;hpb=78414a6a897db42c9bcf06aa21c705811ab33921 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index c1cb86e1b7..cc3df56830 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,11 +57,27 @@ */ #include +#include +#ifndef WIN32 +#include +#endif #include "objects.h" #include "bio.h" #include "pem.h" #include "ssl_locl.h" +int SSL_get_ex_data_X509_STORE_CTX_idx() + { + static int ssl_x509_store_ctx_idx= -1; + + if (ssl_x509_store_ctx_idx < 0) + { + ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( + 0,"SSL for verify callback",NULL,NULL,NULL); + } + return(ssl_x509_store_ctx_idx); + } + CERT *ssl_cert_new() { CERT *ret; @@ -88,11 +104,13 @@ CERT *ssl_cert_new() return(ret); } -void ssl_cert_free(c) -CERT *c; +void ssl_cert_free(CERT *c) { int i; + if(c == NULL) + return; + i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); #ifdef REF_PRINT REF_PRINT("CERT",c); @@ -129,17 +147,34 @@ CERT *c; Free(c); } -int ssl_set_cert_type(c, type) -CERT *c; -int type; +int ssl_cert_instantiate(CERT **o, CERT *d) + { + CERT *n; + if (o == NULL) + { + SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if (*o != NULL && (d == NULL || *o != d)) + return(1); + if ((n = ssl_cert_new()) == NULL) + { + SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_MALLOC_FAILURE); + return(0); + } + if (*o != NULL) + ssl_cert_free(*o); + *o = n; + return(1); + } + +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; @@ -150,22 +185,29 @@ STACK *sk; x=(X509 *)sk_value(sk,0); X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk); - X509_STORE_CTX_set_app_data(&ctx,(char *)s); + X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(), + (char *)s); if (s->ctx->app_verify_callback != NULL) i=s->ctx->app_verify_callback(&ctx); else + { +#ifndef NO_X509_VERIFY i=X509_verify_cert(&ctx); +#else + i=0; + ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK); +#endif + } - X509_STORE_CTX_cleanup(&ctx); s->verify_result=ctx.error; + X509_STORE_CTX_cleanup(&ctx); 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); @@ -173,8 +215,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; @@ -193,28 +234,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 */ @@ -233,9 +268,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; @@ -254,29 +287,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; @@ -327,3 +362,105 @@ 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_file_cert_subjects_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 (in == NULL) + { + SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_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. + */ + +#ifndef WIN32 + +int SSL_add_dir_cert_subjects_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_DIR_CERT_SUBJECTS_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_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); + return 0; + } + + sprintf(buf,"%s/%s",dir,dstruct->d_name); + if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) + return 0; + } + + return 1; + } + +#endif