/* * Create a new TLS_CONTEXT instance. * * Returns: Pointer to TLS_CONTEXT instance on success * NULL on failure; */ TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir, const char *crlfile, const char *certfile, const char *keyfile, CRYPTO_PEM_PASSWD_CB *pem_callback, const void *pem_userdata, const char *dhfile, bool verify_peer) { TLS_CONTEXT *ctx; BIO *bio; DH *dh; ctx = (TLS_CONTEXT *)malloc(sizeof(TLS_CONTEXT)); /* * Allocate our OpenSSL TLSv1 Context */ ctx->openssl = SSL_CTX_new(TLSv1_method()); if (!ctx->openssl) { openssl_post_errors(M_FATAL, _("Error initializing SSL context")); goto err; } /* * Set up pem encryption callback */ if (pem_callback) { ctx->pem_callback = pem_callback; ctx->pem_userdata = pem_userdata; } else { ctx->pem_callback = crypto_default_pem_callback; ctx->pem_userdata = NULL; } ctx->verify_peer = verify_peer; SSL_CTX_set_default_passwd_cb(ctx->openssl, tls_pem_callback_dispatch); SSL_CTX_set_default_passwd_cb_userdata(ctx->openssl, (void *) ctx); /* * Set certificate verification paths. This requires that at least one value be non-NULL */ if (ca_certfile || ca_certdir) { if (!SSL_CTX_load_verify_locations(ctx->openssl, ca_certfile, ca_certdir)) { openssl_post_errors(M_FATAL, _("Error loading certificate verification stores")); goto err; } } else if (verify_peer) { /* At least one CA is required for peer verification */ Jmsg0(NULL, M_ERROR, 0, _("Either a certificate file or a directory must be" " specified as a verification store\n")); goto err; } #if (OPENSSL_VERSION_NUMBER >= 0x00907000L) /* * Set certificate revocation list. */ if (crlfile) { X509_STORE *store; X509_LOOKUP *lookup; store = SSL_CTX_get_cert_store(ctx->openssl); if (!store) { openssl_post_errors(M_FATAL, _("Error loading revocation list file")); goto err; } lookup = X509_STORE_add_lookup(store, X509_LOOKUP_crl_reloader()); if (!lookup) { openssl_post_errors(M_FATAL, _("Error loading revocation list file")); goto err; } if (!load_new_crl_file(lookup, (char *)crlfile)) { openssl_post_errors(M_FATAL, _("Error loading revocation list file")); goto err; } X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } #endif /* * Load our certificate file, if available. This file may also contain a * private key, though this usage is somewhat unusual. */ if (certfile) { if (!SSL_CTX_use_certificate_chain_file(ctx->openssl, certfile)) { openssl_post_errors(M_FATAL, _("Error loading certificate file")); goto err; } } /* * Load our private key. */ if (keyfile) { if (!SSL_CTX_use_PrivateKey_file(ctx->openssl, keyfile, SSL_FILETYPE_PEM)) { openssl_post_errors(M_FATAL, _("Error loading private key")); goto err; } } /* * Load Diffie-Hellman Parameters. */ if (dhfile) { if (!(bio = BIO_new_file(dhfile, "r"))) { openssl_post_errors(M_FATAL, _("Unable to open DH parameters file")); goto err; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dh) { openssl_post_errors(M_FATAL, _("Unable to load DH parameters from specified file")); goto err; } if (!SSL_CTX_set_tmp_dh(ctx->openssl, dh)) { openssl_post_errors(M_FATAL, _("Failed to set TLS Diffie-Hellman parameters")); DH_free(dh); goto err; } /* * Enable Single-Use DH for Ephemeral Keying */ SSL_CTX_set_options(ctx->openssl, SSL_OP_SINGLE_DH_USE); } if (SSL_CTX_set_cipher_list(ctx->openssl, TLS_DEFAULT_CIPHERS) != 1) { Jmsg0(NULL, M_ERROR, 0, _("Error setting cipher list, no valid ciphers available\n")); goto err; } /* * Verify Peer Certificate */ if (verify_peer) { /* * SSL_VERIFY_FAIL_IF_NO_PEER_CERT has no effect in client mode */ SSL_CTX_set_verify(ctx->openssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, openssl_verify_peer); } else { SSL_CTX_set_verify(ctx->openssl, SSL_VERIFY_NONE, NULL); } return ctx; err: /* * Clean up after ourselves */ if (ctx->openssl) { SSL_CTX_free(ctx->openssl); } free(ctx); return NULL; }
/* * ***FIXME*** this is a sort of dummy to avoid having to * change all the existing code to pass either a jcr or * a NULL. Passing a NULL causes the messages to be * printed by the daemon -- not very good :-( */ void openssl_post_errors(int code, const char *errstring) { openssl_post_errors(NULL, code, errstring); }