kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit ae31ec01ac0337e1269d1f08f4974dcc6830c50b
parent 2b97d371f5a3a6fae04dc3a81555b04f0b4c67f8
Author: Joris Vink <joris@coders.se>
Date:   Wed,  8 Jun 2016 13:55:14 +0200

Separate private keys from worker processes.

Kore will now isolate RSA private keys to a separate process (keymgr).

Worker processes that require RSA signing for TLS connections will
communicate with this keymgr process in order to do so.

This behaviour cannot be disabled and is always turned on.

Diffstat:
Makefile | 2+-
includes/kore.h | 24+++++++++++++++++++++++-
src/config.c | 5+++++
src/domain.c | 229++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/keymgr.c | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kore.c | 21++++++++++++++++-----
src/module.c | 15+++++++++++++++
src/utils.c | 16+++++++++++++---
src/worker.c | 55++++++++++++++++++++++++++++++++++++++++++++-----------
9 files changed, 509 insertions(+), 28 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,7 +8,7 @@ INCLUDE_DIR=$(PREFIX)/include/kore S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \ src/domain.c src/mem.c src/msg.c src/module.c src/net.c \ - src/pool.c src/timer.c src/utils.c src/worker.c + src/pool.c src/timer.c src/utils.c src/worker.c src/keymgr.c S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes diff --git a/includes/kore.h b/includes/kore.h @@ -69,7 +69,7 @@ extern int daemon(int, int); #define errno_s strerror(errno) #define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) -#define KORE_DOMAINNAME_LEN 254 +#define KORE_DOMAINNAME_LEN 255 #define KORE_PIDFILE_DEFAULT "kore.pid" #define KORE_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA" @@ -370,9 +370,13 @@ struct kore_timer { TAILQ_ENTRY(kore_timer) list; }; +#define KORE_WORKER_KEYMGR 0 + /* Reserved message ids, registered on workers. */ #define KORE_MSG_ACCESSLOG 1 #define KORE_MSG_WEBSOCKET 2 +#define KORE_MSG_KEYMGR_REQ 3 +#define KORE_MSG_KEYMGR_RESP 4 /* Predefined message targets. */ #define KORE_MSG_PARENT 1000 @@ -385,6 +389,16 @@ struct kore_msg { u_int32_t length; }; +#if !defined(KORE_NO_TLS) +struct kore_keyreq { + int padding; + char domain[KORE_DOMAINNAME_LEN]; + u_int8_t domain_len; + u_int16_t data_len; + u_int8_t data[]; +}; +#endif + extern pid_t kore_pid; extern int foreground; extern int kore_debug; @@ -426,6 +440,7 @@ void kore_signal(int); void kore_worker_wait(int); void kore_worker_init(void); void kore_worker_shutdown(void); +void kore_worker_privdrop(void); void kore_worker_dispatch_signal(int); void kore_worker_spawn(u_int16_t, u_int16_t); void kore_worker_entry(struct kore_worker *); @@ -463,6 +478,7 @@ void kore_timer_remove(struct kore_timer *); struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t), u_int64_t, void *, int); +void kore_listener_cleanup(void); int kore_server_bind(const char *, const char *, const char *); #if !defined(KORE_NO_TLS) int kore_tls_sni_cb(SSL *, int *, void *); @@ -541,14 +557,17 @@ void kore_domain_cleanup(void); int kore_domain_new(char *); void kore_domain_free(struct kore_domain *); void kore_module_init(void); +void kore_module_cleanup(void); void kore_module_reload(int); void kore_module_onload(void); int kore_module_loaded(void); void kore_domain_closelogs(void); void *kore_module_getsym(const char *); void kore_domain_load_crl(void); +void kore_domain_keymgr_init(void); void kore_module_load(const char *, const char *); void kore_domain_sslstart(struct kore_domain *); +void kore_domain_callback(void (*cb)(struct kore_domain *)); int kore_module_handler_new(const char *, const char *, const char *, const char *, int); void kore_module_handler_free(struct kore_module_handle *); @@ -609,6 +628,9 @@ void kore_buf_appendv(struct kore_buf *, const char *, va_list); void kore_buf_appendb(struct kore_buf *, struct kore_buf *); void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); +void kore_keymgr_run(void); +void kore_keymgr_cleanup(void); + #if defined(__cplusplus) } #endif diff --git a/src/config.c b/src/config.c @@ -435,6 +435,11 @@ configure_domain(char *options) return (KORE_RESULT_ERROR); } + if (strlen(argv[0]) >= KORE_DOMAINNAME_LEN - 1) { + printf("domain name '%s' too long\n", argv[0]); + return (KORE_RESULT_ERROR); + } + if (!kore_domain_new(argv[0])) { printf("could not create new domain %s\n", argv[0]); return (KORE_RESULT_ERROR); diff --git a/src/domain.c b/src/domain.c @@ -16,6 +16,14 @@ #include <sys/param.h> +#if !defined(KORE_NO_TLS) +#include <openssl/x509.h> +#include <openssl/bio.h> +#include <openssl/evp.h> + +#include <poll.h> +#endif + #include <fnmatch.h> #include "kore.h" @@ -26,6 +34,9 @@ struct kore_domain_h domains; struct kore_domain *primary_dom = NULL; #if !defined(KORE_NO_TLS) +static u_int8_t keymgr_buf[2048]; +static size_t keymgr_buflen = 0; +static int keymgr_response = 0; DH *tls_dhparam = NULL; int tls_version = KORE_TLS_VERSION_1_2; #endif @@ -34,6 +45,31 @@ static void domain_load_crl(struct kore_domain *); #if !defined(KORE_NO_TLS) static int domain_x509_verify(int, X509_STORE_CTX *); + +static void keymgr_msg_response(struct kore_msg *, const void *); +static void keymgr_init(void); +static int keymgr_rsa_init(RSA *); +static int keymgr_rsa_finish(RSA *); +static int keymgr_rsa_privenc(int, const unsigned char *, + unsigned char *, RSA *, int); + +static RSA_METHOD keymgr_rsa = { + "kore RSA keymgr engine", + NULL, + NULL, + keymgr_rsa_privenc, + NULL, + NULL, + NULL, + keymgr_rsa_init, + keymgr_rsa_finish, + RSA_METHOD_FLAG_NO_CHECK, + NULL, + NULL, + NULL, + NULL +}; + #endif void @@ -126,6 +162,10 @@ void kore_domain_sslstart(struct kore_domain *dom) { #if !defined(KORE_NO_TLS) + BIO *in; + RSA *rsa; + X509 *x509; + EVP_PKEY *pkey; STACK_OF(X509_NAME) *certs; X509_STORE *store; const SSL_METHOD *method; @@ -158,11 +198,26 @@ kore_domain_sslstart(struct kore_domain *dom) 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 ((in = BIO_new(BIO_s_file_internal())) == NULL) + fatal("BIO_new: %s", ssl_errno_s); + if (BIO_read_filename(in, dom->certfile) <= 0) + fatal("BIO_read_filename: %s", ssl_errno_s); + if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) + fatal("PEM_read_bio_X509: %s", ssl_errno_s); + + BIO_free(in); + + if ((pkey = X509_get_pubkey(x509)) == NULL) + fatal("certificate has no public key"); + + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + fatal("no RSA public key present"); + + RSA_set_app_data(rsa, dom); + RSA_set_method(rsa, &keymgr_rsa); + + if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey)) + fatal("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s); if (!SSL_CTX_check_private_key(dom->ssl_ctx)) fatal("Public/Private key for %s do not match", dom->domain); @@ -230,12 +285,20 @@ kore_domain_sslstart(struct kore_domain *dom) SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb); kore_mem_free(dom->certfile); - kore_mem_free(dom->certkey); dom->certfile = NULL; - dom->certkey = NULL; #endif } +void +kore_domain_callback(void (*cb)(struct kore_domain *)) +{ + struct kore_domain *dom; + + TAILQ_FOREACH(dom, &domains, list) { + cb(dom); + } +} + struct kore_domain * kore_domain_lookup(const char *domain) { @@ -270,6 +333,15 @@ kore_domain_load_crl(void) domain_load_crl(dom); } +void +kore_domain_keymgr_init(void) +{ +#if !defined(KORE_NO_TLS) + keymgr_init(); + kore_msg_register(KORE_MSG_KEYMGR_RESP, keymgr_msg_response); +#endif +} + static void domain_load_crl(struct kore_domain *dom) { @@ -303,6 +375,149 @@ domain_load_crl(struct kore_domain *dom) } #if !defined(KORE_NO_TLS) +static void +keymgr_init(void) +{ + const RSA_METHOD *meth; + + if ((meth = RSA_get_default_method()) == NULL) + fatal("failed to obtain RSA method"); + + keymgr_rsa.rsa_pub_enc = meth->rsa_pub_enc; + keymgr_rsa.rsa_pub_dec = meth->rsa_pub_dec; + keymgr_rsa.bn_mod_exp = meth->bn_mod_exp; +} + +static int +keymgr_rsa_init(RSA *rsa) +{ + if (rsa != NULL) { + rsa->flags |= RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK; + return (1); + } + + return (0); +} + +static int +keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to, + RSA *rsa, int padding) +{ + int ret; + size_t len; + struct kore_keyreq *req; + struct kore_domain *dom; + struct pollfd pfd[1]; + u_int64_t start, cur; + + len = sizeof(*req) + flen; + + if (len > sizeof(keymgr_buf)) + fatal("keymgr_buf too small"); + + if ((dom = RSA_get_app_data(rsa)) == NULL) + fatal("RSA key has no domain attached"); + if (strlen(dom->domain) >= KORE_DOMAINNAME_LEN - 1) + fatal("domain name too long"); + + memset(keymgr_buf, 0, sizeof(keymgr_buf)); + + req = (struct kore_keyreq *)keymgr_buf; + req->data_len = flen; + req->padding = padding; + req->domain_len = strlen(dom->domain); + + memcpy(&req->data[0], from, req->data_len); + memcpy(req->domain, dom->domain, req->domain_len); + + kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len); + + /* + * We need to wait until the keymgr responds to us, so keep doing + * net_recv_flush() until our callback for KORE_MSG_KEYMGR_RESP + * tells us that we have obtained the response. + * + * This means other internal messages can still be delivered by + * this worker process to the appropriate callbacks but we do not + * drop out until we've either received an answer from the keymgr + * or until the timeout has been reached. + * + * It will however block any other I/O and request handling on + * this worker until either of the above criteria is met. + */ + start = kore_time_ms(); + kore_platform_disable_read(worker->msg[1]->fd); + + keymgr_response = 0; + memset(keymgr_buf, 0, sizeof(keymgr_buf)); + + for (;;) { + pfd[0].fd = worker->msg[1]->fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + + ret = poll(pfd, 1, 100); + if (ret == -1) { + if (errno == EINTR) + continue; + fatal("poll: %s", errno_s); + } + + cur = kore_time_ms(); + if ((cur - start) > 1000) + break; + + if (ret == 0) + continue; + + if (pfd[0].revents & (POLLERR | POLLHUP)) + break; + if (!(pfd[0].revents & POLLIN)) + break; + + worker->msg[1]->flags |= CONN_READ_POSSIBLE; + if (!net_recv_flush(worker->msg[1])) + break; + + if (keymgr_response) + break; + } + + ret = -1; + + if (keymgr_response) { + if (keymgr_buflen < INT_MAX && + (int)keymgr_buflen == RSA_size(rsa)) { + ret = RSA_size(rsa); + memcpy(to, keymgr_buf, RSA_size(rsa)); + } + } + + keymgr_buflen = 0; + keymgr_response = 0; + kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]); + + return (ret); +} + +static void +keymgr_msg_response(struct kore_msg *msg, const void *data) +{ + keymgr_response = 1; + keymgr_buflen = msg->length; + + if (keymgr_buflen > sizeof(keymgr_buf)) + return; + + memcpy(keymgr_buf, data, keymgr_buflen); +} + +static int +keymgr_rsa_finish(RSA *rsa) +{ + return (1); +} + static int domain_x509_verify(int ok, X509_STORE_CTX *ctx) { diff --git a/src/keymgr.c b/src/keymgr.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016 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 <sys/param.h> + +#include <openssl/rsa.h> + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> + +#include "kore.h" + +#if !defined(KORE_NO_TLS) +struct key { + RSA *rsa; + struct kore_domain *dom; + TAILQ_ENTRY(key) list; +}; + +static TAILQ_HEAD(, key) keys; +extern volatile sig_atomic_t sig_recv; +static int initialized = 0; + +static void keymgr_load_privatekey(struct kore_domain *); +static void keymgr_msg_recv(struct kore_msg *, const void *); + +void +kore_keymgr_run(void) +{ + int quit; + + quit = 0; + initialized = 1; + TAILQ_INIT(&keys); + + kore_listener_cleanup(); + kore_module_cleanup(); + + kore_domain_callback(keymgr_load_privatekey); + kore_worker_privdrop(); + + net_init(); + kore_connection_init(); + kore_platform_event_init(); + + kore_msg_worker_init(); + kore_msg_register(KORE_MSG_KEYMGR_REQ, keymgr_msg_recv); + + kore_log(LOG_NOTICE, "key manager started"); + + while (quit != 1) { + if (sig_recv != 0) { + switch (sig_recv) { + case SIGQUIT: + case SIGINT: + case SIGTERM: + quit = 1; + break; + default: + break; + } + sig_recv = 0; + } + + kore_platform_event_wait(1000); + kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); + } + + kore_keymgr_cleanup(); + kore_platform_event_cleanup(); + kore_connection_cleanup(); + net_cleanup(); +} + +void +kore_keymgr_cleanup(void) +{ + struct key *key, *next; + + kore_log(LOG_NOTICE, "cleaning up keys"); + + if (initialized == 0) + return; + + for (key = TAILQ_FIRST(&keys); key != NULL; key = next) { + next = TAILQ_NEXT(key, list); + TAILQ_REMOVE(&keys, key, list); + + RSA_free(key->rsa); + kore_mem_free(key); + } +} + +static void +keymgr_load_privatekey(struct kore_domain *dom) +{ + FILE *fp; + struct key *key; + + if (dom->certkey == NULL) + return; + + if ((fp = fopen(dom->certkey, "r")) == NULL) + fatal("failed to open private key: %s", dom->certkey); + + key = kore_malloc(sizeof(*key)); + key->dom = dom; + + if ((key->rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) + fatal("PEM_read_RSAPrivateKey: %s", ssl_errno_s); + + (void)fclose(fp); + kore_mem_free(dom->certkey); + dom->certkey = NULL; + + TAILQ_INSERT_TAIL(&keys, key, list); +} + +static void +keymgr_msg_recv(struct kore_msg *msg, const void *data) +{ + int ret; + const struct kore_keyreq *req; + struct key *key; + size_t keylen; + u_int8_t buf[1024]; + + if (msg->length < sizeof(*req)) + return; + + key = NULL; + req = (const struct kore_keyreq *)data; + + if (msg->length != (sizeof(*req) + req->data_len)) + return; + + TAILQ_FOREACH(key, &keys, list) { + if (strncmp(key->dom->domain, req->domain, req->domain_len)) + continue; + + keylen = RSA_size(key->rsa); + if (req->data_len > keylen || keylen > sizeof(buf)) + return; + + ret = RSA_private_encrypt(req->data_len, req->data, + buf, key->rsa, req->padding); + if (ret != RSA_size(key->rsa)) + return; + + kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret); + break; + } +} + +#endif diff --git a/src/kore.c b/src/kore.c @@ -98,8 +98,7 @@ version(void) int main(int argc, char *argv[]) { - struct listener *l; - int ch, flags; + int ch, flags; flags = 0; @@ -195,10 +194,9 @@ main(int argc, char *argv[]) if (!foreground) unlink(kore_pidfile); - LIST_FOREACH(l, &listeners, list) - close(l->fd); - + kore_listener_cleanup(); kore_log(LOG_NOTICE, "goodbye"); + return (0); } @@ -340,6 +338,19 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) } void +kore_listener_cleanup(void) +{ + struct listener *l; + + while (!LIST_EMPTY(&listeners)) { + l = LIST_FIRST(&listeners); + LIST_REMOVE(l, list); + close(l->fd); + kore_mem_free(l); + } +} + +void kore_signal(int sig) { sig_recv = sig; diff --git a/src/module.c b/src/module.c @@ -29,6 +29,21 @@ kore_module_init(void) } void +kore_module_cleanup(void) +{ + struct kore_module *module, *next; + + for (module = TAILQ_FIRST(&modules); module != NULL; module = next) { + next = TAILQ_NEXT(module, list); + TAILQ_REMOVE(&modules, module, list); + + kore_mem_free(module->path); + (void)dlclose(module->handle); + kore_mem_free(module); + } +} + +void kore_module_load(const char *path, const char *onload) { struct stat st; diff --git a/src/utils.c b/src/utils.c @@ -71,17 +71,22 @@ void kore_log(int prio, const char *fmt, ...) { va_list args; - char buf[2048]; + char buf[2048], tmp[32]; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (worker != NULL) { + (void)snprintf(tmp, sizeof(tmp), "wrk %d", worker->id); +#if !defined(KORE_NO_TLS) + if (worker->id == KORE_WORKER_KEYMGR) + kore_strlcpy(tmp, "keymgr", sizeof(tmp)); +#endif if (foreground) - printf("[wrk %d]: %s\n", worker->id, buf); + printf("[%s]: %s\n", tmp, buf); else - syslog(prio, "[wrk %d]: %s", worker->id, buf); + syslog(prio, "[%s]: %s", tmp, buf); } else { if (foreground) printf("[parent]: %s\n", buf); @@ -558,6 +563,11 @@ fatal(const char *fmt, ...) if (!foreground) kore_log(LOG_ERR, "%s", buf); +#if !defined(KORE_NO_TLS) + if (worker != NULL && worker->id == KORE_WORKER_KEYMGR) + kore_keymgr_cleanup(); +#endif + printf("kore: %s\n", buf); exit(1); } diff --git a/src/worker.c b/src/worker.c @@ -89,6 +89,11 @@ kore_worker_init(void) if (worker_count == 0) worker_count = 1; +#if !defined(KORE_NO_TLS) + /* account for the key manager. */ + worker_count += 1; +#endif + len = sizeof(*accept_lock) + (sizeof(struct kore_worker) * worker_count); @@ -200,17 +205,12 @@ kore_worker_dispatch_signal(int sig) } void -kore_worker_entry(struct kore_worker *kw) +kore_worker_privdrop(void) { rlim_t fd; struct rlimit rl; - char buf[16]; - int quit, had_lock, r; - u_int64_t now, idle_check, next_lock, netwait; struct passwd *pw = NULL; - worker = kw; - /* Must happen before chroot. */ if (skip_runas == 0) { pw = getpwnam(runas_user); @@ -258,8 +258,22 @@ kore_worker_entry(struct kore_worker *kw) #endif fatal("cannot drop privileges"); } +} + +void +kore_worker_entry(struct kore_worker *kw) +{ + char buf[16]; + int quit, had_lock, r; + u_int64_t now, idle_check, next_lock, netwait; + + worker = kw; (void)snprintf(buf, sizeof(buf), "kore [wrk %d]", kw->id); +#if !defined(KORE_NO_TLS) + if (kw->id == KORE_WORKER_KEYMGR) + (void)snprintf(buf, sizeof(buf), "kore [keymgr]"); +#endif kore_platform_proctitle(buf); if (worker_set_affinity == 1) @@ -278,6 +292,15 @@ kore_worker_entry(struct kore_worker *kw) else signal(SIGINT, SIG_IGN); +#if !defined(KORE_NO_TLS) + if (kw->id == KORE_WORKER_KEYMGR) { + kore_keymgr_run(); + exit(0); + } +#endif + + kore_worker_privdrop(); + net_init(); #if !defined(KORE_NO_HTTP) http_init(); @@ -286,6 +309,7 @@ kore_worker_entry(struct kore_worker *kw) kore_timer_init(); kore_connection_init(); kore_domain_load_crl(); + kore_domain_keymgr_init(); quit = 0; had_lock = 0; @@ -359,22 +383,19 @@ kore_worker_entry(struct kore_worker *kw) kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); -#if !defined(KORE_NO_HTTP) - if (quit && http_request_count == 0) - break; -#else if (quit) break; -#endif } kore_platform_event_cleanup(); kore_connection_cleanup(); kore_domain_cleanup(); + kore_module_cleanup(); #if !defined(KORE_NO_HTTP) http_cleanup(); #endif net_cleanup(); + kore_debug("worker %d shutting down", kw->id); exit(0); } @@ -421,6 +442,18 @@ kore_worker_wait(int final) (kw->active_hdlr != NULL) ? kw->active_hdlr->func : "none"); +#if !defined(KORE_NO_TLS) + if (id == KORE_WORKER_KEYMGR) { + kore_log(LOG_CRIT, "keymgr gone, stopping"); + kw->pid = 0; + if (raise(SIGTERM) != 0) { + kore_log(LOG_WARNING, + "failed to raise SIGTERM signal"); + } + break; + } +#endif + if (kw->pid == accept_lock->current) worker_unlock();