Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

tls_glue.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: tls_glue.c,v 1.12 2006/02/25 18:32:40 tat Exp $
00009  */
00010 
00011 /*
00012  * This product includes software developed by Ralf S. Engelschall 
00013  * <rse@engelschall.com> for use in the mod_ssl project (http://www.modssl.org/)
00014  * 
00015  * This product includes software developed by the OpenSSL Project
00016  * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
00017  */
00018 
00019 #include "klone_conf.h"
00020 #include <u/libu.h>
00021 #include <klone/io.h>
00022 #include <klone/emb.h>
00023 
00024 #ifndef HAVE_LIBOPENSSL
00025 int tls_dummy_decl_stub = 0;
00026 #else /* HAVE_LIBOPENSSL */
00027 #include <openssl/ssl.h>
00028 #include <openssl/x509.h>
00029 
00030 /* map an emb resource to a OpenSSL memory BIO */
00031 BIO *bio_from_emb (const char *res_name)
00032 {
00033     int     c;
00034     enum    { BUFSZ = 1024 };
00035     char    buf[BUFSZ];
00036     io_t    *tmp = NULL;
00037     BIO     *b = NULL;
00038 
00039     dbg_return_if (!res_name, NULL);
00040 
00041     dbg_err_if (emb_open(res_name, &tmp));
00042     dbg_err_if (!(b = BIO_new(BIO_s_mem())));
00043 
00044     for (;;)
00045     {
00046         c = io_read(tmp, buf, BUFSZ);
00047 
00048         if (c == 0)     /* EOF */
00049             break;
00050         else if (c < 0) /* read error */
00051             goto err;
00052 
00053         dbg_err_if (BIO_write(b, buf, c) <= 0);
00054     }
00055 
00056     io_free(tmp);
00057 
00058     return b;
00059 
00060 err:
00061     if (tmp) 
00062         io_free(tmp);
00063     if (b)  
00064         BIO_free(b);
00065 
00066     return NULL;
00067 }
00068 
00069 BIO* tls_get_file_bio(const char *res_name)
00070 {
00071     BIO *b = NULL;
00072 
00073     /* load the cert from the embfs */
00074     if((b = bio_from_emb(res_name)) != NULL)
00075         return b;
00076 
00077     /* load the cert from the file system */
00078     if((b = BIO_new_file(res_name, "r")) != NULL)
00079         return b;
00080 
00081     /* no cert found */
00082     return NULL;
00083 }
00084 
00085 
00086 /* XXX the original returns the number of certs/crls added */
00087 int tls_load_verify_locations (SSL_CTX *c, const char *res_name)
00088 {
00089     int i;
00090     BIO *b = NULL;
00091     STACK_OF(X509_INFO) *info = NULL;
00092 
00093     dbg_return_if (!c, ~0);
00094     dbg_return_if (!res_name, ~0);
00095 
00096     dbg_err_if (!(b = tls_get_file_bio(res_name)));
00097     dbg_err_if (!(info = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL)));
00098     BIO_free(b);
00099 
00100     for (i = 0; i < sk_X509_INFO_num(info); i++)
00101     {
00102         X509_INFO   *tmp = sk_X509_INFO_value(info, i);
00103 
00104         if (tmp->x509)
00105             X509_STORE_add_cert(c->cert_store, tmp->x509); 
00106 
00107         if (tmp->crl)
00108             X509_STORE_add_crl(c->cert_store, tmp->crl); 
00109     }
00110 
00111     sk_X509_INFO_pop_free(info, X509_INFO_free);
00112 
00113     return 0;
00114 
00115 err:
00116     if (b)
00117         BIO_free(b);
00118     if (info)
00119         sk_X509_INFO_pop_free(info, X509_INFO_free);
00120 
00121     return ~0;
00122 } 
00123 
00124 /* reads certificates from file and returns a STACK_OF(X509_NAME) with 
00125  * the subject names found */
00126 STACK_OF(X509_NAME) *tls_load_client_CA_file (const char *res_name)
00127 {
00128     BIO *b = NULL;
00129     X509 *x = NULL;
00130     X509_NAME *xn = NULL;
00131     STACK_OF(X509_NAME) *ret, *sk;
00132 
00133     dbg_return_if (!res_name, NULL);
00134     
00135     dbg_err_if (!(ret = sk_X509_NAME_new_null()));
00136     dbg_err_if (!(sk = sk_X509_NAME_new(X509_NAME_cmp)));
00137     dbg_err_if (!(b = tls_get_file_bio(res_name)));
00138 
00139     for (;;)
00140     {
00141         if (!PEM_read_bio_X509(b, &x, NULL, NULL))
00142             break;
00143 
00144         dbg_err_if (!(xn = X509_get_subject_name(x)));
00145 
00146         /* check for duplicates */
00147         dbg_err_if (!(xn = X509_NAME_dup(xn)));
00148         if (sk_X509_NAME_find(sk, xn) >= 0)
00149             X509_NAME_free(xn);
00150         else
00151         {
00152             sk_X509_NAME_push(sk, xn);
00153             sk_X509_NAME_push(ret, xn);
00154         }
00155     }
00156 
00157     sk_X509_NAME_free(sk);
00158     BIO_free(b);
00159     X509_free(x);
00160 
00161     return ret;
00162 
00163 err:
00164     if (ret)
00165     {
00166         sk_X509_NAME_pop_free(ret, X509_NAME_free);
00167         ret = NULL;
00168     }
00169     if (sk)
00170         sk_X509_NAME_free(sk);
00171     if (b)
00172         BIO_free(b);
00173     if (x)
00174         X509_free(x);
00175 
00176     return ret;
00177 }
00178 
00179 /* basically a wrapper for SSL_CTX_use_certificate() */
00180 int tls_use_certificate_file (SSL_CTX *ctx, const char *res_name, int type)
00181 {
00182     BIO *b = NULL;
00183     int ret = 0;
00184     X509 *x = NULL;
00185 
00186     dbg_return_if (!ctx, 0);
00187     dbg_return_if (!res_name, 0);
00188     dbg_return_if (type != SSL_FILETYPE_PEM, 0);
00189 
00190     dbg_goto_if (!(b = tls_get_file_bio(res_name)), end);
00191     dbg_goto_if (!(x = PEM_read_bio_X509(b, NULL, NULL, NULL)), end);
00192     ret = SSL_CTX_use_certificate(ctx, x);
00193 
00194 end:
00195     if (x)
00196         X509_free(x);
00197     if (b)
00198         BIO_free(b);
00199 
00200     return ret;
00201 }
00202 
00203 
00204 /* wrapper for SSL_CTX_use_PrivateKey() */
00205 int tls_use_PrivateKey_file (SSL_CTX *ctx, const char *res_name, int type)
00206 {
00207     int ret = 0;
00208     BIO *b = NULL;
00209     EVP_PKEY *pkey = NULL;
00210 
00211     dbg_return_if (!ctx, 0);
00212     dbg_return_if (!res_name, 0);
00213     dbg_return_if (type != SSL_FILETYPE_PEM, 0);
00214 
00215     dbg_goto_if (!(b = tls_get_file_bio(res_name)), end);
00216     dbg_goto_if (!(pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL)), end);
00217     ret = SSL_CTX_use_PrivateKey(ctx, pkey);
00218     EVP_PKEY_free(pkey);
00219 
00220 end:
00221     if (b)
00222         BIO_free(b);
00223 
00224     return ret;
00225 }
00226 
00227 /* Read a file that optionally contains the server certificate in PEM
00228  * format, possibly followed by a sequence of CA certificates that
00229  * should be sent to the peer in the SSL Certificate message.  */
00230 int tls_use_certificate_chain (SSL_CTX *ctx, const char *res_name, 
00231                                int skipfirst, int (*cb)())
00232 {
00233     BIO *b = NULL;
00234     X509 *x = NULL;
00235     unsigned long err;
00236     int n;
00237 
00238     dbg_return_if (!ctx, -1);
00239     dbg_return_if (!res_name, -1);
00240 
00241     dbg_err_if (!(b = tls_get_file_bio(res_name)));
00242 
00243     /* optionally skip a leading server certificate */
00244     if (skipfirst)
00245     {
00246         dbg_err_if (!(x = PEM_read_bio_X509(b, NULL, cb, NULL)));
00247         X509_free(x);
00248         x = NULL;
00249     }
00250 
00251     /* free a perhaps already configured extra chain */
00252     if (!ctx->extra_certs)
00253     {
00254         sk_X509_pop_free(ctx->extra_certs, X509_free);
00255         ctx->extra_certs = NULL;
00256     }
00257 
00258     /* create new extra chain by loading the certs */
00259     n = 0;
00260     while ((x = PEM_read_bio_X509(b, NULL, cb, NULL))) 
00261     {
00262         dbg_err_if (!SSL_CTX_add_extra_chain_cert(ctx, x));
00263         n++;
00264     }
00265 
00266     /* Make sure that only the error is just an EOF */
00267     if ((err = ERR_peek_error()) > 0) 
00268     {
00269         dbg_err_if (!(ERR_GET_LIB(err) == ERR_LIB_PEM && 
00270                       ERR_GET_REASON(err) == PEM_R_NO_START_LINE));
00271 
00272         while (ERR_get_error() > 0) ;
00273     }
00274 
00275     BIO_free(b);
00276 
00277     return n;
00278 
00279 err:
00280     if (b)
00281         BIO_free(b);
00282     if (x)
00283         X509_free(x);
00284 
00285     return -1;
00286 }
00287 
00288 #endif /* HAVE_LIBOPENSSL */

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved