2013-06-24 11:32:45 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013 Joris Vink <joris@coders.se>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kore.h"
|
|
|
|
|
2013-12-14 16:31:07 +01:00
|
|
|
#define SSL_SESSION_ID "kore_ssl_sessionid"
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
struct kore_domain_h domains;
|
|
|
|
struct kore_domain *primary_dom = NULL;
|
2013-08-07 16:51:39 +02:00
|
|
|
DH *ssl_dhparam = NULL;
|
2013-08-07 16:59:45 +02:00
|
|
|
int ssl_no_compression = 0;
|
2013-06-24 11:32:45 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
kore_domain_init(void)
|
|
|
|
{
|
|
|
|
TAILQ_INIT(&domains);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kore_domain_new(char *domain)
|
|
|
|
{
|
|
|
|
struct kore_domain *dom;
|
|
|
|
|
|
|
|
if (kore_domain_lookup(domain) != NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-06-27 08:43:07 +02:00
|
|
|
kore_debug("kore_domain_new(%s)", domain);
|
2013-06-24 11:32:45 +02:00
|
|
|
|
2013-07-13 21:08:55 +02:00
|
|
|
dom = kore_malloc(sizeof(*dom));
|
2013-06-24 11:32:45 +02:00
|
|
|
dom->accesslog = -1;
|
2013-12-14 16:31:07 +01:00
|
|
|
dom->cafile = NULL;
|
2013-06-24 11:32:45 +02:00
|
|
|
dom->certkey = NULL;
|
2013-06-27 08:43:07 +02:00
|
|
|
dom->ssl_ctx = NULL;
|
2013-12-14 16:31:07 +01:00
|
|
|
dom->certfile = NULL;
|
2013-06-24 11:32:45 +02:00
|
|
|
dom->domain = kore_strdup(domain);
|
|
|
|
TAILQ_INIT(&(dom->handlers));
|
|
|
|
TAILQ_INSERT_TAIL(&domains, dom, list);
|
|
|
|
|
|
|
|
if (primary_dom == NULL)
|
|
|
|
primary_dom = dom;
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_domain_sslstart(struct kore_domain *dom)
|
|
|
|
{
|
2014-08-01 10:22:32 +02:00
|
|
|
#if !defined(KORE_BENCHMARK)
|
2013-12-14 16:31:07 +01:00
|
|
|
STACK_OF(X509_NAME) *certs;
|
|
|
|
|
2013-09-24 08:58:05 +02:00
|
|
|
#if !defined(OPENSSL_NO_EC)
|
|
|
|
EC_KEY *ecdh;
|
|
|
|
#endif
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
kore_debug("kore_domain_sslstart(%s)", dom->domain);
|
|
|
|
|
|
|
|
dom->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
|
|
|
if (dom->ssl_ctx == NULL)
|
2013-06-27 08:43:07 +02:00
|
|
|
fatal("kore_domain_sslstart(): SSL_ctx_new(): %s", ssl_errno_s);
|
2013-06-24 11:32:45 +02:00
|
|
|
if (!SSL_CTX_use_certificate_chain_file(dom->ssl_ctx, dom->certfile)) {
|
|
|
|
fatal("SSL_CTX_use_certificate_chain_file(%s): %s",
|
|
|
|
dom->certfile, ssl_errno_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SSL_CTX_use_PrivateKey_file(dom->ssl_ctx, dom->certkey,
|
|
|
|
SSL_FILETYPE_PEM)) {
|
|
|
|
fatal("SSL_CTX_use_PrivateKey_file(%s): %s",
|
|
|
|
dom->certkey, ssl_errno_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SSL_CTX_check_private_key(dom->ssl_ctx))
|
|
|
|
fatal("Public/Private key for %s do not match", dom->domain);
|
|
|
|
|
2013-08-07 16:51:39 +02:00
|
|
|
if (ssl_dhparam != NULL) {
|
|
|
|
SSL_CTX_set_tmp_dh(dom->ssl_ctx, ssl_dhparam);
|
|
|
|
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE);
|
2013-09-24 08:58:05 +02:00
|
|
|
|
|
|
|
#if !defined(OPENSSL_NO_EC)
|
|
|
|
if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) != NULL) {
|
|
|
|
SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
|
|
|
|
EC_KEY_free(ecdh);
|
|
|
|
}
|
|
|
|
#endif
|
2013-08-07 16:51:39 +02:00
|
|
|
}
|
|
|
|
|
2013-08-07 16:59:45 +02:00
|
|
|
if (ssl_no_compression)
|
|
|
|
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION);
|
|
|
|
|
2013-12-14 16:31:07 +01:00
|
|
|
if (dom->cafile != NULL) {
|
|
|
|
if ((certs = SSL_load_client_CA_file(dom->cafile)) == NULL) {
|
|
|
|
fatal("SSL_load_client_CA_file(%s): %s",
|
|
|
|
dom->cafile, ssl_errno_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_load_verify_locations(dom->ssl_ctx, dom->cafile, NULL);
|
|
|
|
SSL_CTX_set_verify_depth(dom->ssl_ctx, 1);
|
|
|
|
SSL_CTX_set_client_CA_list(dom->ssl_ctx, certs);
|
|
|
|
SSL_CTX_set_verify(dom->ssl_ctx, SSL_VERIFY_PEER |
|
|
|
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set_session_id_context(dom->ssl_ctx,
|
|
|
|
(unsigned char *)SSL_SESSION_ID, strlen(SSL_SESSION_ID));
|
|
|
|
|
2014-04-11 08:46:50 +02:00
|
|
|
/*
|
|
|
|
* Force OpenSSL to not use its freelists. Even without using
|
|
|
|
* SSL_MODE_RELEASE_BUFFERS there are times it will use the
|
|
|
|
* freelists. So forcefully putting its max length to 0 is the
|
|
|
|
* only we choice we seem to have.
|
|
|
|
*
|
|
|
|
* Note that OpenBSD has since heartbleed removed freelists
|
|
|
|
* from its OpenSSL in base so we don't need to care about it.
|
|
|
|
*/
|
|
|
|
#if !defined(OpenBSD) || (OpenBSD < 201405)
|
2014-04-09 14:14:09 +02:00
|
|
|
dom->ssl_ctx->freelist_max_len = 0;
|
2014-04-11 08:46:50 +02:00
|
|
|
#endif
|
2013-06-24 11:32:45 +02:00
|
|
|
SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
2013-08-07 20:42:19 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv2);
|
2013-08-07 20:42:19 +02:00
|
|
|
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|
|
|
SSL_CTX_set_cipher_list(dom->ssl_ctx, kore_ssl_cipher_list);
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_ssl_sni_cb);
|
|
|
|
SSL_CTX_set_next_protos_advertised_cb(dom->ssl_ctx,
|
|
|
|
kore_ssl_npn_cb, NULL);
|
|
|
|
|
2013-06-27 08:43:07 +02:00
|
|
|
kore_mem_free(dom->certfile);
|
|
|
|
kore_mem_free(dom->certkey);
|
2014-08-01 10:22:32 +02:00
|
|
|
#endif
|
2013-06-24 11:32:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct kore_domain *
|
|
|
|
kore_domain_lookup(const char *domain)
|
|
|
|
{
|
|
|
|
struct kore_domain *dom;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dom, &domains, list) {
|
|
|
|
if (!strcmp(dom->domain, domain))
|
|
|
|
return (dom);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_domain_closelogs(void)
|
|
|
|
{
|
|
|
|
struct kore_domain *dom;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dom, &domains, list)
|
|
|
|
close(dom->accesslog);
|
|
|
|
}
|