tls.c

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

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