Main Page | Modules | File List | Globals

tls.c

00001 /*
00002  * Copyright (c) 2005-2008 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.c,v 1.20 2008/03/26 09:02:24 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <sys/time.h>
00014 #include <unistd.h>
00015 #include <strings.h>
00016 #ifdef HAVE_LIBOPENSSL
00017 #include <openssl/ssl.h>
00018 #include <openssl/rand.h>
00019 #include <openssl/err.h>
00020 #include <openssl/x509_vfy.h>
00021 #include <u/libu.h>
00022 #include <klone/tls.h>
00023 #include <klone/utils.h>
00024 #include <klone/tlsprv.h>
00025 
00026 static int tls_sid = 1;
00027 static int tls_inited = 0; 
00028 
00029 /* private methods */
00030 static int tls_init (void);
00031 static int tls_context (SSL_CTX **);
00032 static int tls_load_x509_creds (SSL_CTX *, tls_ctx_args_t *);
00033 static int tls_gendh_params (SSL_CTX *, const char *);
00034 static int tls_gen_eph_rsa (SSL_CTX *);
00035 static void tls_rand_seed (void);
00036 static int tls_sid_context (SSL_CTX *, int *);
00037 static DH *tls_load_dh_param (const char *);
00038 static int tls_no_passphrase_cb (char *, int, int, void *);
00039 static int tls_init_ctx_args (tls_ctx_args_t *);
00040 static int tls_set_ctx_vdepth (u_config_t *, tls_ctx_args_t *);
00041 static int tls_set_ctx_crlopts (u_config_t *, tls_ctx_args_t *);
00042 static int tls_set_ctx_vmode (u_config_t *, tls_ctx_args_t *);
00043 static int tls_check_ctx (tls_ctx_args_t *);
00044 static void tls_free_ctx_args (tls_ctx_args_t *cargs);
00045 static int tls_load_ctx_args (u_config_t *cfg, tls_ctx_args_t **cargs);
00046 static SSL_CTX *tls_init_ctx (tls_ctx_args_t *cargs);
00047 static int cb_vfy (int ok, X509_STORE_CTX *store_ctx);
00048 #ifdef HAVE_LIBOPENSSL_PSK
00049 static int tls_set_ctx_psk_hash (u_config_t *, tls_ctx_args_t *);
00050 #endif
00051 
00052 SSL_CTX *tls_load_init_ctx (u_config_t *cfg)
00053 {
00054     SSL_CTX *ctx = NULL;
00055     tls_ctx_args_t *cargs = NULL;
00056 
00057     dbg_return_if (cfg == NULL, NULL);
00058 
00059     dbg_err_if (tls_load_ctx_args(cfg, &cargs));
00060     dbg_err_if ((ctx = tls_init_ctx(cargs)) == NULL);
00061 
00062     tls_free_ctx_args(cargs);
00063 
00064     return ctx;
00065 err:
00066     if (cargs)
00067         tls_free_ctx_args(cargs);
00068     if (ctx)
00069         SSL_CTX_free(ctx);
00070     return NULL;
00071 }
00072 
00073 /* load SSL_CTX args from configuration */
00074 static int tls_load_ctx_args (u_config_t *cfg, tls_ctx_args_t **pcargs)
00075 {
00076     tls_ctx_args_t *cargs = NULL;
00077 
00078     dbg_return_if (cfg == NULL, ~0);
00079     dbg_return_if (pcargs == NULL, ~0);
00080 
00081     cargs = u_zalloc(sizeof(tls_ctx_args_t));
00082     dbg_err_if (cargs == NULL);
00083 
00084     (void) tls_init_ctx_args(cargs);
00085 
00086     cargs->cert = u_config_get_subkey_value(cfg, "cert_file");
00087     cargs->key = u_config_get_subkey_value(cfg, "key_file");
00088     cargs->certchain = u_config_get_subkey_value(cfg, "certchain_file");
00089     cargs->ca = u_config_get_subkey_value(cfg, "ca_file");
00090     cargs->dh = u_config_get_subkey_value(cfg, "dh_file");
00091     cargs->crl = u_config_get_subkey_value(cfg, "crl_file");
00092 #ifdef HAVE_LIBOPENSSL_PSK
00093     /* handle 'pskdb_file', 'psk_hint' and 'psk_hash' keywords */
00094     cargs->pskdb = u_config_get_subkey_value(cfg, "pskdb_file");
00095     cargs->psk_hint = u_config_get_subkey_value(cfg, "psk_hint");
00096     dbg_err_if (tls_set_ctx_psk_hash(cfg, cargs));
00097 #endif
00098     dbg_err_if (tls_set_ctx_crlopts(cfg, cargs));
00099     dbg_err_if (tls_set_ctx_vdepth(cfg, cargs));
00100     dbg_err_if (tls_set_ctx_vmode(cfg, cargs));
00101 
00102     /* check cargs consistency against the supplied values */
00103     crit_err_ifm (tls_check_ctx(cargs), 
00104             "error validating SSL configuration options");
00105 
00106     *pcargs = cargs;
00107 
00108     return 0;
00109 err:
00110     if (cargs)
00111         tls_free_ctx_args(cargs);
00112     return ~0;
00113 }
00114 
00115 /* initialize 'parent' SSL context */
00116 static SSL_CTX *tls_init_ctx (tls_ctx_args_t *cargs)
00117 {
00118     SSL_CTX *c = NULL;
00119 
00120     dbg_return_if (cargs == NULL, NULL);
00121 
00122     /* global init */
00123     dbg_err_if (tls_init());
00124 
00125     /* create SSL CTX from where all the SSL sessions will be cloned */
00126     dbg_err_if (tls_context(&c));
00127 
00128     /* don't ask for unlocking passphrases: this assumes that all 
00129      * credentials are stored in clear text */
00130     SSL_CTX_set_default_passwd_cb(c, tls_no_passphrase_cb);
00131 
00132     /* NOTE: configuration has been sanitized earlier by tls_check_ctx, 
00133      * so we can be reasonably sure that one (or both) of PSK or X.509 
00134      * credentials are in place. */
00135 
00136     if (cargs->cert)
00137         /* set key and certs against the SSL context */
00138         dbg_err_if (tls_load_x509_creds(c, cargs));
00139 
00140 #ifdef HAVE_LIBOPENSSL_PSK
00141     if (cargs->pskdb)
00142         /* load psk DB and set psk callback */
00143         dbg_err_if (tls_psk_init(c, cargs));
00144 #endif
00145 
00146     /* generate RSA ephemeral parameters and load into SSL_CTX */
00147     dbg_err_if (tls_gen_eph_rsa(c));
00148 
00149     /* (possibly) generate DH parameters and load into SSL_CTX */
00150     dbg_err_if (tls_gendh_params(c, cargs->dh));
00151 
00152     /* set the session id context */
00153     dbg_err_if (tls_sid_context(c, &tls_sid));
00154 
00155     return c;
00156 err:
00157     if (c)
00158         SSL_CTX_free(c);
00159     return NULL;
00160 }
00161 
00162 static int tls_sid_context (SSL_CTX *c, int *sid)
00163 {
00164     int rc;
00165 
00166     dbg_return_if (c == NULL, ~0); 
00167     dbg_return_if (sid == NULL, ~0); 
00168     
00169     /* every time tls_init_ctx() is called, move on the session id context */
00170     (*sid)++;
00171 
00172     rc = SSL_CTX_set_session_id_context(c, (void *) sid, sizeof(int));
00173     dbg_err_ifm (rc == 0, "error setting sid: %s", tls_get_error());
00174     
00175     return 0;
00176 err:
00177     return ~0;
00178 }
00179 
00180 static int tls_context (SSL_CTX **pc)
00181 {
00182     SSL_CTX *c = NULL;
00183 
00184     dbg_return_if (pc == NULL, ~0);
00185 
00186     c = SSL_CTX_new(TLSv1_server_method());
00187     dbg_err_ifm (c == NULL, "error creating SSL CTX: %s", tls_get_error());
00188 
00189     *pc = c;
00190 
00191     return 0;
00192 err:
00193     return ~0;
00194 }
00195 
00196 /* XXX very primitive */
00197 char *tls_get_error (void)
00198 {
00199     unsigned long e = ERR_get_error();
00200     return ERR_error_string(e, NULL);
00201 }
00202 
00203 /* if skey is NULL, assume private key in scert, ca can be NULL */
00204 static int tls_load_x509_creds (SSL_CTX *c, tls_ctx_args_t *cargs)
00205 {
00206     dbg_return_if (c == NULL, ~0);
00207     dbg_return_if (cargs == NULL, ~0);
00208     dbg_return_if (cargs->cert == NULL, ~0);
00209 
00210     /* if key file unspecified assume key+cert are bundled */
00211     if (!cargs->key)
00212         cargs->key = cargs->cert;
00213     
00214     /* set ca if supplied */
00215     if (cargs->ca)
00216         crit_err_ifm(tls_load_verify_locations(c, cargs->ca),
00217                 "error loading CA certificate from %s", cargs->ca);
00218 
00219     /* explicitly set the list of CAs for which we accept certificates */
00220     if (cargs->ca && cargs->vmode != SSL_VERIFY_NONE)
00221         SSL_CTX_set_client_CA_list(c, tls_load_client_CA_file(cargs->ca));
00222 
00223     /* load server certificate */
00224     crit_err_ifm (tls_use_certificate_file(c, cargs->cert, 
00225                 SSL_FILETYPE_PEM) <= 0, 
00226             "error loading server certificate from %s", cargs->cert);
00227 
00228     /* load private key (perhaps from the cert file) */
00229     crit_err_ifm (tls_use_PrivateKey_file(c, cargs->key, SSL_FILETYPE_PEM) <= 0,
00230             "error loading the private key from %s", cargs->key);
00231 
00232     /* check skey consistency against scert */
00233     crit_err_ifm (!SSL_CTX_check_private_key(c),
00234             "the given private key doesn't seem to belong "
00235             "to the server certificate");
00236 
00237     /* load optional server certficate chain */
00238     if (cargs->certchain)
00239         crit_err_ifm (tls_use_certificate_chain(c, cargs->certchain, 
00240                     0, NULL) < 0, 
00241                 "error loading server certificate chain");
00242 
00243     /* load optional CRL file + opts into args */
00244     if (cargs->crl)
00245         crit_err_ifm (tls_use_crls(c, cargs), "error loading CA CRL file");
00246 
00247     /* set SSL verify mode (no, optional, required) and callbacks */
00248     SSL_CTX_set_verify(c, cargs->vmode, cb_vfy);
00249 
00250     /* set verification depth */
00251     if (cargs->depth > 0)
00252         SSL_CTX_set_verify_depth(c, cargs->depth);
00253 
00254     return 0;
00255 err:
00256     return ~0;
00257 }
00258 
00259 static int cb_vfy (int ok, X509_STORE_CTX *store_ctx)
00260 {
00261     int e;
00262     X509 *x;
00263     char buf[1024];
00264     
00265     if (ok)
00266         return ok;
00267 
00268     e = X509_STORE_CTX_get_error(store_ctx);
00269     x = store_ctx->current_cert;
00270 
00271     /* at present just put a note in the log.
00272      * the idea is that here we can catch CRL specific errors and, based 
00273      * on the value of crl_opts directive, use different accept/reject 
00274      * policies.  e.g. return ok in case X509_V_ERR_CRL_HAS_EXPIRED, etc. */
00275     info("%s; current certificate subject is %s", 
00276             X509_verify_cert_error_string(e), 
00277             X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf));
00278 
00279     return 0;
00280 }
00281 
00282 static int tls_init (void)
00283 {
00284     if (tls_inited)
00285         return 0;
00286 
00287     SSL_load_error_strings();
00288     dbg_err_if (!SSL_library_init());
00289     tls_rand_seed(); 
00290     tls_inited++;
00291 
00292     return 0;
00293 
00294 err:
00295     dbg("%s", tls_get_error()); 
00296     return ~0;
00297 }
00298 
00299 static void tls_rand_seed (void)
00300 {
00301     struct timeval tv;
00302     tls_rand_seed_t seed;
00303 
00304     (void) gettimeofday(&tv, NULL);
00305     
00306     seed.pid = getpid();
00307     seed.t1 = tv.tv_sec; 
00308     seed.t2 = tv.tv_usec;
00309     seed.stack = (void *) &seed;
00310 
00311     RAND_seed((const void *) &seed, sizeof seed);
00312 }
00313 
00314 /* generate RSA ephemeral parameters and load'em into SSL_CTX */
00315 static int tls_gen_eph_rsa(SSL_CTX *c)
00316 {
00317     RSA *eph_rsa = NULL;
00318 
00319     dbg_return_if (c == NULL, ~0);
00320 
00321     dbg_err_if (!(eph_rsa = RSA_generate_key(512, RSA_F4, 0, NULL)));
00322     dbg_err_if (!SSL_CTX_set_tmp_rsa(c, eph_rsa));
00323     RSA_free(eph_rsa); /* eph_rsa is dup'ed by SSL_CTX_set_tmp_rsa() */
00324 
00325     return 0;
00326 err:
00327     dbg("%s", tls_get_error());
00328     if (eph_rsa)
00329         RSA_free(eph_rsa);    
00330 
00331     return ~0;
00332 }
00333 
00334 /* generate DH ephemeral parameters and load'em into SSL_CTX */
00335 static int tls_gendh_params(SSL_CTX *c, const char *dhfile)
00336 {
00337     DH *eph_dh = NULL;
00338 
00339     dbg_return_if (c == NULL, ~0);
00340 
00341     eph_dh = dhfile ? tls_load_dh_param(dhfile) : get_dh1024(); 
00342     dbg_err_if (!(eph_dh));
00343 
00344     dbg_err_if (!SSL_CTX_set_tmp_dh(c, eph_dh));
00345     DH_free(eph_dh);
00346 
00347 #if 0
00348     /* Avoid small subgroup attacks (if p and g are strong primes
00349      * this is not strictly necessary).  This is said to have a negligible (?)
00350      * impact during negotiation phase. TODO: test it ! */
00351     (void) SSL_CTX_set_options(c, SSL_OP_SINGLE_DH_USE); */
00352 #endif /* 0 */
00353 
00354     return 0;
00355 err:
00356     dbg("%s", tls_get_error());
00357     if (eph_dh)
00358         DH_free(eph_dh);
00359 
00360     return ~0;
00361 }
00362 
00363 static DH *tls_load_dh_param (const char *res_name)
00364 {
00365     DH *dh = NULL;
00366     BIO *bio = NULL;
00367 
00368     dbg_return_if (res_name == NULL, NULL);
00369 
00370     /* say return_if here instead of err_if because bio_from_emb()
00371      * could have failed for a non-openssl error */
00372     dbg_return_if (!(bio = tls_get_file_bio(res_name)), NULL);
00373     dbg_err_if (!(dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)));
00374 
00375     BIO_free(bio);
00376 
00377     return dh;
00378 err:
00379     dbg("%s", tls_get_error());
00380     if (bio) 
00381         BIO_free(bio);
00382 
00383     return NULL;
00384 }
00385 
00386 static int tls_no_passphrase_cb (char *buf, int num, int w, void *arg)
00387 {
00388     u_unused_args(buf, num, w, arg);
00389 
00390     return -1;
00391 }
00392 
00393 static int tls_init_ctx_args (tls_ctx_args_t *cargs)
00394 {
00395     dbg_return_if (!cargs, ~0);
00396 
00397     cargs->cert = NULL;
00398     cargs->key = NULL;
00399     cargs->ca = NULL;
00400     cargs->dh = NULL;
00401     cargs->crl = NULL;
00402 #ifdef HAVE_LIBOPENSSL_PSK
00403     cargs->pskdb = NULL;
00404 #endif
00405     cargs->crlopts = 0;
00406     cargs->depth = 1;
00407     cargs->vmode = SSL_VERIFY_NONE;
00408 
00409     return 0;
00410 }
00411 
00412 static int tls_set_ctx_vdepth (u_config_t *cfg, tls_ctx_args_t *cargs)
00413 {
00414     u_config_t    *k;
00415     
00416     dbg_return_if (!cfg || !cargs, ~0);
00417 
00418     if (!u_config_get_subkey(cfg, "verify_depth", &k))
00419         cargs->depth = atoi(u_config_get_value(k));    
00420 
00421     return 0;
00422 }
00423 
00424 #ifdef HAVE_LIBOPENSSL_PSK
00425 static int tls_set_ctx_psk_hash (u_config_t *cfg, tls_ctx_args_t *cargs)
00426 {
00427     int rc; 
00428 
00429     dbg_return_if (cfg == NULL, ~0);
00430     dbg_return_if (cargs == NULL, ~0);
00431 
00432     /* default value is 0 (i.e. cleartext) */
00433     rc = u_config_get_subkey_value_b(cfg, "psk_hash", 0, &cargs->psk_is_hashed);
00434     dbg_return_ifm (rc, ~0, "bad value given to psk_hash directive");
00435 
00436     return 0;
00437 }
00438 #endif
00439 
00440 static int tls_set_ctx_crlopts (u_config_t *cfg, tls_ctx_args_t *cargs)
00441 {
00442     const char *v;
00443     
00444     dbg_return_if (cfg == NULL, ~0);
00445     dbg_return_if (cargs == NULL, ~0);
00446 
00447     v = u_config_get_subkey_value(cfg, "crl_opts");
00448 
00449     if (v == NULL)
00450     {
00451         cargs->crlopts = 0;
00452         return 0;
00453     }
00454 
00455     if (!strcasecmp(v, "check_all"))
00456         cargs->crlopts = X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
00457     else
00458         warn_err("unknown value %s for 'crl_opts' directive", v);
00459 
00460     return 0;
00461 err:
00462     return ~0;
00463 }
00464 
00465 /* 'verify_mode' and 'verify_client' are aliases
00466  * the former is deprecated and retained only for compatibility with klone 1 */
00467 static int tls_set_ctx_vmode (u_config_t *cfg, tls_ctx_args_t *cargs)
00468 {
00469     const char *v;
00470     
00471     dbg_return_if (cfg == NULL, ~0);
00472     dbg_return_if (cargs == NULL, ~0);
00473     
00474     /* try 'verify_mode' directive first then 'verify_client' */
00475     if  ((v = u_config_get_subkey_value(cfg, "verify_mode")) == NULL)
00476         v = u_config_get_subkey_value(cfg, "verify_client");
00477 
00478     if (v == NULL || !strcasecmp(v, "no"))  /* unset == none */
00479         cargs->vmode = SSL_VERIFY_NONE;
00480     else if (!strcasecmp(v, "optional"))
00481         cargs->vmode = SSL_VERIFY_PEER;
00482     else if (!strcasecmp(v, "require"))
00483         cargs->vmode = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00484     else
00485         warn_err("unknown verification value:\'%s\'", v);
00486     
00487     return 0;
00488 err:
00489     return ~0;
00490 }
00491 
00492 static int tls_check_ctx (tls_ctx_args_t *cargs)
00493 {
00494     dbg_return_if (cargs == NULL, ~0);
00495 
00496 #ifdef HAVE_LIBOPENSSL_PSK
00497     /* if no PSK password file is set check for certificate/key */
00498     if (cargs->pskdb == NULL)
00499     {
00500 #endif
00501         /* cert_file is a MUST */
00502         crit_err_ifm (!cargs->cert || strlen(cargs->cert) == 0, 
00503             "missing cert_file option parameter");
00504 
00505         /* if private key file is missing, assume the key is inside cert_file */
00506         warn_ifm (cargs->key == NULL, 
00507             "missing cert key option, assuming the key is inside cert_file");
00508 
00509         /* if verify_mode == "required" the CA file MUST be present */
00510         if (cargs->vmode & SSL_VERIFY_PEER)
00511             crit_err_ifm (cargs->ca == NULL, 
00512                 "SSL verify is required but CA certificate file is missing");
00513 
00514 #ifdef HAVE_LIBOPENSSL_PSK
00515     }
00516 #endif
00517 
00518     /* if 'crl_file' was given, set crlopts at least to verify the client
00519      * certificate against the supplied CRL */
00520     if (cargs->crl && cargs->crlopts == 0)
00521         cargs->crlopts = X509_V_FLAG_CRL_CHECK;
00522 
00523     return 0;
00524 err:
00525     return ~0;
00526 }
00527 
00528 
00529 static void tls_free_ctx_args (tls_ctx_args_t *cargs)
00530 {
00531     KLONE_FREE(cargs);
00532     return;
00533 }
00534 #endif /* HAVE_LIBOPENSSL */