forked from mirrors/kore
Compare commits
32 Commits
Author | SHA1 | Date |
---|---|---|
Joris Vink | 9a59f6833a | |
Joris Vink | 3d1145dc50 | |
Joris Vink | bb159da725 | |
Joris Vink | c55ec5c0d8 | |
Joris Vink | 703482bc10 | |
Joris Vink | 0d4114811a | |
Joris Vink | f8524392e8 | |
Joris Vink | 1a0fb72923 | |
Joris Vink | 449fffca44 | |
Joris Vink | bb37f7e5ec | |
Joris Vink | 313133f252 | |
Joris Vink | 3e06668d3f | |
Joris Vink | 70083add32 | |
Joris Vink | c4b82220e4 | |
Joris Vink | 0f13606967 | |
Joris Vink | a34f4597b4 | |
Joris Vink | 6812cd0a12 | |
Joris Vink | a9864c9ff7 | |
Joris Vink | 7e41def497 | |
Joris Vink | dab77e9b52 | |
Joris Vink | 8c836cf9d0 | |
Joris Vink | 2516abdfa2 | |
Joris Vink | e4e8093bc3 | |
Joris Vink | 2377dee21a | |
Joris Vink | 58678ff0ad | |
Joris Vink | 1a9197ffeb | |
Joris Vink | bfcc4afe48 | |
Joris Vink | f2882643ce | |
Joris Vink | 21696a0f2e | |
Joris Vink | 4cd64cd06d | |
Joris Vink | 82709ec2cc | |
Joris Vink | 0a958de9c0 |
7
Makefile
7
Makefile
|
@ -102,6 +102,13 @@ ifeq ("$(OSNAME)", "freebsd")
|
|||
KORE_CURL_INC=-I/usr/local/include
|
||||
endif
|
||||
|
||||
ifneq ("$(ACME)", "")
|
||||
S_SRC+=src/acme.c
|
||||
CURL=1
|
||||
CFLAGS+=-DKORE_USE_ACME
|
||||
FEATURES+=-DKORE_USE_ACME
|
||||
endif
|
||||
|
||||
ifneq ("$(CURL)", "")
|
||||
S_SRC+=src/curl.c
|
||||
KORE_CURL_LIB?=$(shell curl-config --libs)
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* your workers with custom callbacks defined per message ID.
|
||||
*/
|
||||
|
||||
/* Your code shouldn't use IDs < 100. */
|
||||
#define MY_MESSAGE_ID 100
|
||||
/* Your code shouldn't use IDs <= KORE_MSG_APP_BASE. */
|
||||
#define MY_MESSAGE_ID KORE_MSG_APP_BASE + 1
|
||||
|
||||
int init(int);
|
||||
int page(struct http_request *);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.
|
||||
*/
|
||||
|
||||
#ifndef __H_ACME_H
|
||||
#define __H_ACME_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* All acme paths are relative to the keymgr_root directory.
|
||||
*/
|
||||
#define KORE_ACME_ACCOUNT_KEY "account-key.pem"
|
||||
#define KORE_ACME_CERTDIR "certificates"
|
||||
|
||||
#define KORE_ACME_RSAKEY_E (KORE_MSG_ACME_BASE + 1)
|
||||
#define KORE_ACME_RSAKEY_N (KORE_MSG_ACME_BASE + 2)
|
||||
#define KORE_ACME_SIGN (KORE_MSG_ACME_BASE + 3)
|
||||
#define KORE_ACME_SIGN_RESULT (KORE_MSG_ACME_BASE + 4)
|
||||
#define KORE_ACME_PROC_READY (KORE_MSG_ACME_BASE + 5)
|
||||
#define KORE_ACME_ACCOUNT_CREATE (KORE_MSG_ACME_BASE + 10)
|
||||
#define KORE_ACME_ACCOUNT_RESOLVE (KORE_MSG_ACME_BASE + 11)
|
||||
#define KORE_ACME_ORDER_CREATE (KORE_MSG_ACME_BASE + 12)
|
||||
#define KORE_ACME_CSR_REQUEST (KORE_MSG_ACME_BASE + 13)
|
||||
#define KORE_ACME_CSR_RESPONSE (KORE_MSG_ACME_BASE + 14)
|
||||
#define KORE_ACME_INSTALL_CERT (KORE_MSG_ACME_BASE + 15)
|
||||
#define KORE_ACME_ORDER_FAILED (KORE_MSG_ACME_BASE + 16)
|
||||
|
||||
#define KORE_ACME_CHALLENGE_CERT (KORE_MSG_ACME_BASE + 20)
|
||||
#define KORE_ACME_CHALLENGE_SET_CERT (KORE_MSG_ACME_BASE + 21)
|
||||
#define KORE_ACME_CHALLENGE_CLEAR_CERT (KORE_MSG_ACME_BASE + 22)
|
||||
|
||||
void kore_acme_init(void);
|
||||
void kore_acme_run(void);
|
||||
void kore_acme_setup(void);
|
||||
|
||||
int kore_acme_tls_alpn(SSL *, const unsigned char **, unsigned char *,
|
||||
const unsigned char *, unsigned int, void *);
|
||||
|
||||
extern char *acme_provider;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -78,6 +78,8 @@ extern int daemon(int, int);
|
|||
#define KORE_USE_PLATFORM_PLEDGE 1
|
||||
#endif
|
||||
|
||||
#define KORE_RSAKEY_BITS 4096
|
||||
|
||||
#define KORE_RESULT_ERROR 0
|
||||
#define KORE_RESULT_OK 1
|
||||
#define KORE_RESULT_RETRY 2
|
||||
|
@ -86,6 +88,8 @@ extern int daemon(int, int);
|
|||
#define KORE_TLS_VERSION_1_2 1
|
||||
#define KORE_TLS_VERSION_BOTH 2
|
||||
|
||||
#define KORE_BASE64_RAW 0x0001
|
||||
|
||||
#define KORE_WAIT_INFINITE (u_int64_t)-1
|
||||
#define KORE_RESEED_TIME (1800 * 1000)
|
||||
|
||||
|
@ -128,6 +132,9 @@ extern int daemon(int, int);
|
|||
|
||||
#define X509_CN_LENGTH (ub_common_name + 1)
|
||||
|
||||
#define KORE_PEM_CERT_CHAIN 1
|
||||
#define KORE_DER_CERT_DATA 2
|
||||
|
||||
/* XXX hackish. */
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
struct http_request;
|
||||
|
@ -195,6 +202,7 @@ TAILQ_HEAD(netbuf_head, netbuf);
|
|||
#define CONN_CLOSE_EMPTY 0x02
|
||||
#define CONN_WS_CLOSE_SENT 0x04
|
||||
#define CONN_IS_BUSY 0x08
|
||||
#define CONN_ACME_CHALLENGE 0x10
|
||||
|
||||
#define KORE_IDLE_TIMER_MAX 5000
|
||||
|
||||
|
@ -303,6 +311,12 @@ struct kore_domain {
|
|||
struct kore_buf *logbuf;
|
||||
struct kore_server *server;
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
int acme;
|
||||
int acme_challenge;
|
||||
void *acme_cert;
|
||||
size_t acme_cert_len;
|
||||
#endif
|
||||
char *cafile;
|
||||
char *crlfile;
|
||||
char *certfile;
|
||||
|
@ -431,11 +445,9 @@ struct kore_alog_header {
|
|||
u_int16_t loglen;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define KORE_WORKER_MAX UCHAR_MAX
|
||||
|
||||
struct kore_worker {
|
||||
u_int8_t id;
|
||||
u_int8_t cpu;
|
||||
u_int16_t id;
|
||||
u_int16_t cpu;
|
||||
#if defined(__linux__)
|
||||
int tracing;
|
||||
#endif
|
||||
|
@ -600,7 +612,17 @@ struct kore_timer {
|
|||
TAILQ_ENTRY(kore_timer) list;
|
||||
};
|
||||
|
||||
#define KORE_WORKER_KEYMGR 0
|
||||
/*
|
||||
* Keymgr process is worker index 0, but id 2000.
|
||||
* Acme process is worker index 1, but id 2001.
|
||||
*/
|
||||
#define KORE_WORKER_KEYMGR_IDX 0
|
||||
#define KORE_WORKER_ACME_IDX 1
|
||||
#define KORE_WORKER_BASE 2
|
||||
#define KORE_WORKER_KEYMGR 2000
|
||||
#define KORE_WORKER_ACME 2001
|
||||
#define KORE_WORKER_MAX UCHAR_MAX
|
||||
|
||||
#define KORE_WORKER_POLICY_RESTART 1
|
||||
#define KORE_WORKER_POLICY_TERMINATE 2
|
||||
|
||||
|
@ -616,6 +638,10 @@ struct kore_timer {
|
|||
#define KORE_MSG_CRL 9
|
||||
#define KORE_MSG_ACCEPT_AVAILABLE 10
|
||||
#define KORE_PYTHON_SEND_OBJ 11
|
||||
#define KORE_MSG_ACME_BASE 100
|
||||
|
||||
/* messages for applications should start at 201. */
|
||||
#define KORE_MSG_APP_BASE 200
|
||||
|
||||
/* Predefined message targets. */
|
||||
#define KORE_MSG_PARENT 1000
|
||||
|
@ -630,15 +656,13 @@ struct kore_msg {
|
|||
|
||||
struct kore_keyreq {
|
||||
int padding;
|
||||
char domain[KORE_DOMAINNAME_LEN];
|
||||
u_int16_t domain_len;
|
||||
u_int16_t data_len;
|
||||
char domain[KORE_DOMAINNAME_LEN + 1];
|
||||
size_t data_len;
|
||||
u_int8_t data[];
|
||||
};
|
||||
|
||||
struct kore_x509_msg {
|
||||
char domain[KORE_DOMAINNAME_LEN];
|
||||
u_int16_t domain_len;
|
||||
char domain[KORE_DOMAINNAME_LEN + 1];
|
||||
size_t data_len;
|
||||
u_int8_t data[];
|
||||
};
|
||||
|
@ -666,6 +690,8 @@ extern char *rand_file;
|
|||
extern int keymgr_active;
|
||||
extern char *keymgr_runas_user;
|
||||
extern char *keymgr_root_path;
|
||||
extern char *acme_runas_user;
|
||||
extern char *acme_root_path;
|
||||
|
||||
extern u_int8_t nlisteners;
|
||||
extern u_int16_t cpu_count;
|
||||
|
@ -696,9 +722,11 @@ void kore_worker_init(void);
|
|||
void kore_worker_make_busy(void);
|
||||
void kore_worker_shutdown(void);
|
||||
void kore_worker_dispatch_signal(int);
|
||||
void kore_worker_spawn(u_int16_t, u_int16_t);
|
||||
void kore_worker_entry(struct kore_worker *);
|
||||
void kore_worker_privdrop(const char *, const char *);
|
||||
void kore_worker_spawn(u_int16_t, u_int16_t, u_int16_t);
|
||||
int kore_worker_keymgr_response_verify(struct kore_msg *,
|
||||
const void *, struct kore_domain **);
|
||||
|
||||
struct kore_worker *kore_worker_data(u_int8_t);
|
||||
|
||||
|
@ -706,13 +734,13 @@ void kore_platform_init(void);
|
|||
void kore_platform_sandbox(void);
|
||||
void kore_platform_event_init(void);
|
||||
void kore_platform_event_cleanup(void);
|
||||
void kore_platform_proctitle(char *);
|
||||
void kore_platform_disable_read(int);
|
||||
void kore_platform_disable_write(int);
|
||||
void kore_platform_enable_accept(void);
|
||||
void kore_platform_disable_accept(void);
|
||||
void kore_platform_event_wait(u_int64_t);
|
||||
void kore_platform_event_all(int, void *);
|
||||
void kore_platform_proctitle(const char *);
|
||||
void kore_platform_schedule_read(int, void *);
|
||||
void kore_platform_schedule_write(int, void *);
|
||||
void kore_platform_event_schedule(int, int, int, void *);
|
||||
|
@ -830,10 +858,15 @@ long long kore_strtonum(const char *, int, long long, long long, int *);
|
|||
double kore_strtodouble(const char *, long double, long double, int *);
|
||||
int kore_base64_encode(const void *, size_t, char **);
|
||||
int kore_base64_decode(const char *, u_int8_t **, size_t *);
|
||||
int kore_base64url_encode(const void *, size_t, char **, int);
|
||||
int kore_base64url_decode(const char *, u_int8_t **, size_t *, int);
|
||||
void *kore_mem_find(void *, size_t, const void *, size_t);
|
||||
char *kore_text_trim(char *, size_t);
|
||||
char *kore_read_line(FILE *, char *, size_t);
|
||||
|
||||
EVP_PKEY *kore_rsakey_load(const char *);
|
||||
EVP_PKEY *kore_rsakey_generate(const char *);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
void kore_websocket_handshake(struct http_request *,
|
||||
const char *, const char *, const char *);
|
||||
|
@ -885,7 +918,8 @@ void kore_domain_load_crl(void);
|
|||
void kore_domain_keymgr_init(void);
|
||||
void kore_domain_callback(void (*cb)(struct kore_domain *));
|
||||
int kore_domain_attach(struct kore_domain *, struct kore_server *);
|
||||
void kore_domain_tlsinit(struct kore_domain *, const void *, size_t);
|
||||
void kore_domain_tlsinit(struct kore_domain *, int,
|
||||
const void *, size_t);
|
||||
void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
int kore_module_handler_new(struct kore_domain *, const char *,
|
||||
|
@ -930,6 +964,8 @@ struct kore_validator *kore_validator_lookup(const char *);
|
|||
|
||||
void fatal(const char *, ...) __attribute__((noreturn));
|
||||
void fatalx(const char *, ...) __attribute__((noreturn));
|
||||
|
||||
const char *kore_worker_name(int);
|
||||
void kore_debug_internal(char *, int, const char *, ...);
|
||||
|
||||
u_int16_t net_read16(u_int8_t *);
|
||||
|
|
|
@ -164,8 +164,8 @@ void kore_seccomp_init(void);
|
|||
void kore_seccomp_drop(void);
|
||||
void kore_seccomp_enable(void);
|
||||
void kore_seccomp_traceme(void);
|
||||
int kore_seccomp_trace(pid_t, int);
|
||||
int kore_seccomp_syscall_resolve(const char *);
|
||||
int kore_seccomp_trace(struct kore_worker *, int);
|
||||
int kore_seccomp_filter(const char *, void *, size_t);
|
||||
|
||||
const char *kore_seccomp_syscall_name(long);
|
||||
|
|
|
@ -208,7 +208,7 @@ kore_accesslog_gather(void *arg, u_int64_t now, int force)
|
|||
if (logbuf == NULL)
|
||||
logbuf = kore_buf_alloc(LOGBUF_SIZE);
|
||||
|
||||
for (id = 0; id < worker_count; id++) {
|
||||
for (id = KORE_WORKER_BASE; id < worker_count; id++) {
|
||||
kw = kore_worker_data(id);
|
||||
|
||||
accesslog_lock(kw);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -236,7 +236,7 @@ kore_platform_disable_write(int fd)
|
|||
}
|
||||
|
||||
void
|
||||
kore_platform_proctitle(char *title)
|
||||
kore_platform_proctitle(const char *title)
|
||||
{
|
||||
#ifdef __MACH__
|
||||
kore_proctitle(title);
|
||||
|
@ -299,6 +299,9 @@ kore_platform_sandbox(void)
|
|||
void
|
||||
kore_platform_pledge(void)
|
||||
{
|
||||
if (worker->id == KORE_WORKER_KEYMGR || worker->id == KORE_WORKER_ACME)
|
||||
return;
|
||||
|
||||
if (pledge(pledges, NULL) == -1)
|
||||
fatal("failed to pledge process");
|
||||
}
|
||||
|
|
175
src/config.c
175
src/config.c
|
@ -45,13 +45,18 @@
|
|||
#include "curl.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
#include "acme.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include "seccomp.h"
|
||||
#endif
|
||||
|
||||
/* XXX - This is becoming a clusterfuck. Fix it. */
|
||||
|
||||
static int configure_load(char *);
|
||||
static int configure_load(char *);
|
||||
static void configure_check_var(char **, const char *, const char *);
|
||||
|
||||
#if defined(KORE_SINGLE_BINARY)
|
||||
static FILE *config_file_write(void);
|
||||
|
@ -61,6 +66,13 @@ extern u_int32_t asset_len_builtin_kore_conf;
|
|||
static int configure_file(char *);
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
static int configure_acme(char *);
|
||||
static int configure_acme_root(char *);
|
||||
static int configure_acme_runas(char *);
|
||||
static int configure_acme_provider(char *);
|
||||
#endif
|
||||
|
||||
static int configure_tls(char *);
|
||||
static int configure_server(char *);
|
||||
static int configure_include(char *);
|
||||
|
@ -155,15 +167,18 @@ static struct {
|
|||
int (*configure)(char *);
|
||||
} config_directives[] = {
|
||||
{ "tls", configure_tls },
|
||||
{ "server", configure_server },
|
||||
{ "include", configure_include },
|
||||
#if defined(KORE_USE_ACME)
|
||||
{ "acme", configure_acme },
|
||||
#endif
|
||||
{ "bind", configure_bind },
|
||||
{ "unix", configure_bind_unix },
|
||||
{ "load", configure_load },
|
||||
{ "domain", configure_domain },
|
||||
{ "server", configure_server },
|
||||
{ "attach", configure_attach },
|
||||
{ "certfile", configure_certfile },
|
||||
{ "certkey", configure_certkey },
|
||||
{ "certfile", configure_certfile },
|
||||
{ "include", configure_include },
|
||||
{ "unix", configure_bind_unix },
|
||||
{ "client_verify", configure_client_verify },
|
||||
{ "client_verify_depth", configure_client_verify_depth },
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
|
@ -209,6 +224,11 @@ static struct {
|
|||
{ "rand_file", configure_rand_file },
|
||||
{ "keymgr_runas", configure_keymgr_runas },
|
||||
{ "keymgr_root", configure_keymgr_root },
|
||||
#if defined(KORE_USE_ACME)
|
||||
{ "acme_runas", configure_acme_runas },
|
||||
{ "acme_root", configure_acme_root },
|
||||
{ "acme_provider", configure_acme_provider },
|
||||
#endif
|
||||
#if defined(KORE_USE_PLATFORM_PLEDGE)
|
||||
{ "pledge", configure_add_pledge },
|
||||
#endif
|
||||
|
@ -326,22 +346,21 @@ kore_parse_config(void)
|
|||
if (!kore_quiet)
|
||||
kore_log(LOG_WARNING, "privsep: will not change user");
|
||||
} else {
|
||||
if (keymgr_runas_user == NULL) {
|
||||
if (!kore_quiet) {
|
||||
kore_log(LOG_NOTICE, "privsep: no keymgr_runas "
|
||||
"set, using 'runas` user");
|
||||
}
|
||||
keymgr_runas_user = kore_strdup(kore_runas_user);
|
||||
}
|
||||
configure_check_var(&keymgr_runas_user, kore_runas_user,
|
||||
"privsep: no keymgr_runas set, using 'runas` user");
|
||||
#if defined(KORE_USE_ACME)
|
||||
configure_check_var(&acme_runas_user, kore_runas_user,
|
||||
"privsep: no acme_runas set, using 'runas` user");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (keymgr_root_path == NULL) {
|
||||
if (!kore_quiet) {
|
||||
kore_log(LOG_NOTICE, "privsep: no keymgr_root set, "
|
||||
"using 'root` directory");
|
||||
}
|
||||
keymgr_root_path = kore_strdup(kore_root_path);
|
||||
}
|
||||
configure_check_var(&keymgr_root_path, kore_root_path,
|
||||
"privsep: no keymgr_root set, using 'root` directory");
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
configure_check_var(&acme_root_path, kore_root_path,
|
||||
"privsep: no acme_root set, using 'root` directory");
|
||||
#endif
|
||||
|
||||
if (skip_chroot && !kore_quiet)
|
||||
kore_log(LOG_WARNING, "privsep: will not chroot");
|
||||
|
@ -396,11 +415,19 @@ kore_parse_config_file(FILE *fp)
|
|||
current_domain->domain);
|
||||
}
|
||||
|
||||
if (current_domain->server->tls == 1 &&
|
||||
(current_domain->certfile == NULL ||
|
||||
current_domain->certkey == NULL)) {
|
||||
fatal("incomplete TLS setup for '%s'",
|
||||
current_domain->domain);
|
||||
if (current_domain->server->tls == 1) {
|
||||
#if defined(KORE_USE_ACME)
|
||||
if (current_domain->acme) {
|
||||
lineno++;
|
||||
current_domain = NULL;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (current_domain->certfile == NULL ||
|
||||
current_domain->certkey == NULL) {
|
||||
fatal("incomplete TLS setup for '%s'",
|
||||
current_domain->domain);
|
||||
}
|
||||
}
|
||||
|
||||
current_domain = NULL;
|
||||
|
@ -478,6 +505,16 @@ kore_configure_setting(const char *name, char *value)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
configure_check_var(char **var, const char *other, const char *logmsg)
|
||||
{
|
||||
if (*var == NULL) {
|
||||
if (!kore_quiet)
|
||||
kore_log(LOG_NOTICE, "%s", logmsg);
|
||||
*var = kore_strdup(other);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
configure_include(char *path)
|
||||
{
|
||||
|
@ -545,6 +582,82 @@ configure_tls(char *yesno)
|
|||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
static int
|
||||
configure_acme(char *yesno)
|
||||
{
|
||||
int len;
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
if (current_domain == NULL) {
|
||||
printf("acme directive not inside a domain context\n");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (strchr(current_domain->domain, '*')) {
|
||||
printf("wildcards not supported due to lack of dns-01\n");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (!strcmp(yesno, "no")) {
|
||||
current_domain->acme = 0;
|
||||
} else if (!strcmp(yesno, "yes")) {
|
||||
current_domain->acme = 1;
|
||||
|
||||
/* Override keyfile and certfile locations. */
|
||||
kore_free(current_domain->certkey);
|
||||
kore_free(current_domain->certfile);
|
||||
|
||||
len = snprintf(path, sizeof(path), "%s/%s/fullchain.pem",
|
||||
KORE_ACME_CERTDIR, current_domain->domain);
|
||||
if (len == -1 || (size_t)len >= sizeof(path))
|
||||
fatal("failed to create certfile path");
|
||||
|
||||
current_domain->certfile = kore_strdup(path);
|
||||
|
||||
len = snprintf(path, sizeof(path), "%s/%s/key.pem",
|
||||
KORE_ACME_CERTDIR, current_domain->domain);
|
||||
if (len == -1 || (size_t)len >= sizeof(path))
|
||||
fatal("failed to create certkey path");
|
||||
|
||||
current_domain->certkey = kore_strdup(path);
|
||||
} else {
|
||||
printf("invalid '%s' for yes|no acme option\n", yesno);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_acme_runas(char *user)
|
||||
{
|
||||
kore_free(acme_runas_user);
|
||||
acme_runas_user = kore_strdup(user);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_acme_root(char *root)
|
||||
{
|
||||
kore_free(acme_root_path);
|
||||
acme_root_path = kore_strdup(root);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_acme_provider(char *provider)
|
||||
{
|
||||
kore_free(acme_provider);
|
||||
acme_provider = kore_strdup(provider);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
configure_bind(char *options)
|
||||
{
|
||||
|
@ -767,12 +880,7 @@ configure_certfile(char *path)
|
|||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (current_domain->certfile != NULL) {
|
||||
printf("certfile specified twice for %s\n",
|
||||
current_domain->domain);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
kore_free(current_domain->certfile);
|
||||
current_domain->certfile = kore_strdup(path);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
@ -785,12 +893,7 @@ configure_certkey(char *path)
|
|||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (current_domain->certkey != NULL) {
|
||||
printf("certkey specified twice for %s\n",
|
||||
current_domain->domain);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
kore_free(current_domain->certkey);
|
||||
current_domain->certkey = kore_strdup(path);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
|
|
@ -274,8 +274,12 @@ kore_connection_handle(struct connection *c)
|
|||
|
||||
SSL_set_fd(c->ssl, c->fd);
|
||||
SSL_set_accept_state(c->ssl);
|
||||
SSL_set_app_data(c->ssl, c);
|
||||
SSL_set_ex_data(c->ssl, 0, c);
|
||||
|
||||
if (!SSL_set_ex_data(c->ssl, 0, c)) {
|
||||
kore_debug("SSL_set_ex_data(): %s",
|
||||
ssl_errno_s);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
|
@ -293,6 +297,14 @@ kore_connection_handle(struct connection *c)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
if (c->flags & CONN_ACME_CHALLENGE) {
|
||||
kore_log(LOG_INFO, "disconnecting acme client");
|
||||
kore_connection_disconnect(c);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SSL_get_verify_mode(c->ssl) & SSL_VERIFY_PEER) {
|
||||
c->cert = SSL_get_peer_certificate(c->ssl);
|
||||
if (c->cert == NULL) {
|
||||
|
|
|
@ -42,10 +42,13 @@ static struct sock_filter filter_curl[] = {
|
|||
KORE_SYSCALL_ALLOW(set_robust_list),
|
||||
|
||||
/* Other */
|
||||
KORE_SYSCALL_ALLOW(uname),
|
||||
KORE_SYSCALL_ALLOW(ioctl),
|
||||
KORE_SYSCALL_ALLOW(madvise),
|
||||
KORE_SYSCALL_ALLOW(recvmsg),
|
||||
KORE_SYSCALL_ALLOW(sendmmsg),
|
||||
KORE_SYSCALL_ALLOW(faccessat),
|
||||
KORE_SYSCALL_ALLOW(newfstatat),
|
||||
KORE_SYSCALL_ALLOW(getpeername),
|
||||
};
|
||||
#endif
|
||||
|
|
72
src/domain.c
72
src/domain.c
|
@ -38,6 +38,10 @@
|
|||
#include "http.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
#include "acme.h"
|
||||
#endif
|
||||
|
||||
#define KORE_DOMAIN_CACHE 16
|
||||
#define SSL_SESSION_ID "kore_ssl_sessionid"
|
||||
|
||||
|
@ -256,8 +260,10 @@ kore_domain_free(struct kore_domain *dom)
|
|||
}
|
||||
|
||||
void
|
||||
kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
||||
kore_domain_tlsinit(struct kore_domain *dom, int type,
|
||||
const void *data, size_t datalen)
|
||||
{
|
||||
const u_int8_t *ptr;
|
||||
RSA *rsa;
|
||||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
|
@ -329,7 +335,30 @@ kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
|||
}
|
||||
#endif
|
||||
|
||||
x509 = domain_load_certificate_chain(dom->ssl_ctx, pem, pemlen);
|
||||
switch (type) {
|
||||
case KORE_PEM_CERT_CHAIN:
|
||||
x509 = domain_load_certificate_chain(dom->ssl_ctx,
|
||||
data, datalen);
|
||||
break;
|
||||
case KORE_DER_CERT_DATA:
|
||||
ptr = data;
|
||||
if ((x509 = d2i_X509(NULL, &ptr, datalen)) == NULL)
|
||||
fatalx("d2i_X509: %s", ssl_errno_s);
|
||||
if (SSL_CTX_use_certificate(dom->ssl_ctx, x509) == 0)
|
||||
fatalx("SSL_CTX_use_certificate: %s", ssl_errno_s);
|
||||
break;
|
||||
default:
|
||||
fatalx("%s: unknown type %d", __func__, type);
|
||||
}
|
||||
|
||||
if (x509 == NULL) {
|
||||
kore_log(LOG_NOTICE, "failed to load certificate for '%s': %s",
|
||||
dom->domain, ssl_errno_s);
|
||||
SSL_CTX_free(dom->ssl_ctx);
|
||||
dom->ssl_ctx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pkey = X509_get_pubkey(x509)) == NULL)
|
||||
fatalx("certificate has no public key");
|
||||
|
||||
|
@ -362,8 +391,10 @@ kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
|||
if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
|
||||
fatalx("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
|
||||
|
||||
if (!SSL_CTX_check_private_key(dom->ssl_ctx))
|
||||
fatalx("Public/Private key for %s do not match", dom->domain);
|
||||
if (!SSL_CTX_check_private_key(dom->ssl_ctx)) {
|
||||
fatalx("Public/Private key for %s do not match (%s)",
|
||||
dom->domain, ssl_errno_s);
|
||||
}
|
||||
|
||||
if (tls_dhparam == NULL)
|
||||
fatalx("No DH parameters given");
|
||||
|
@ -415,6 +446,10 @@ kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
|||
SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback);
|
||||
SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb);
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
SSL_CTX_set_alpn_select_cb(dom->ssl_ctx, kore_acme_tls_alpn, dom);
|
||||
#endif
|
||||
|
||||
X509_free(x509);
|
||||
}
|
||||
|
||||
|
@ -599,18 +634,18 @@ keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
|
|||
|
||||
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;
|
||||
|
||||
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
|
||||
sizeof(req->domain))
|
||||
fatal("%s: domain truncated", __func__);
|
||||
|
||||
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);
|
||||
keymgr_await_data();
|
||||
|
@ -663,13 +698,14 @@ keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
|
|||
#endif
|
||||
|
||||
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
||||
|
||||
req = (struct kore_keyreq *)keymgr_buf;
|
||||
req->data_len = dgst_len;
|
||||
req->domain_len = strlen(dom->domain);
|
||||
|
||||
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
|
||||
sizeof(req->domain))
|
||||
fatal("%s: domain truncated", __func__);
|
||||
|
||||
req->data_len = dgst_len;
|
||||
memcpy(&req->data[0], dgst, req->data_len);
|
||||
memcpy(req->domain, dom->domain, req->domain_len);
|
||||
|
||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
||||
keymgr_await_data();
|
||||
|
@ -835,11 +871,11 @@ domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
|
|||
in = BIO_new_mem_buf(data, len);
|
||||
|
||||
if ((x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL)) == NULL)
|
||||
fatal("PEM_read_bio_X509_AUX: %s", ssl_errno_s);
|
||||
return (NULL);
|
||||
|
||||
/* refcount for x509 will go up one. */
|
||||
if (SSL_CTX_use_certificate(ctx, x) == 0)
|
||||
fatal("SSL_CTX_use_certificate: %s", ssl_errno_s);
|
||||
return (NULL);
|
||||
|
||||
#if defined(KORE_OPENSSL_NEWER_API)
|
||||
SSL_CTX_clear_chain_certs(ctx);
|
||||
|
@ -853,10 +889,10 @@ domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
|
|||
/* ca its reference count won't be increased. */
|
||||
#if defined(KORE_OPENSSL_NEWER_API)
|
||||
if (SSL_CTX_add0_chain_cert(ctx, ca) == 0)
|
||||
fatal("SSL_CTX_add0_chain_cert: %s", ssl_errno_s);
|
||||
return (NULL);
|
||||
#else
|
||||
if (SSL_CTX_add_extra_chain_cert(ctx, ca) == 0)
|
||||
fatal("SSL_CTX_add_extra_chain_cert: %s", ssl_errno_s);
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -864,7 +900,7 @@ domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
|
|||
|
||||
if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
|
||||
ERR_GET_REASON(err) != PEM_R_NO_START_LINE)
|
||||
fatal("PEM_read_bio_X509: %s", ssl_errno_s);
|
||||
return (NULL);
|
||||
|
||||
BIO_free(in);
|
||||
|
||||
|
|
911
src/keymgr.c
911
src/keymgr.c
File diff suppressed because it is too large
Load Diff
|
@ -45,6 +45,10 @@
|
|||
#include "python_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
#include "acme.h"
|
||||
#endif
|
||||
|
||||
volatile sig_atomic_t sig_recv;
|
||||
struct kore_server_list kore_servers;
|
||||
u_int8_t nlisteners;
|
||||
|
@ -255,6 +259,9 @@ main(int argc, char *argv[])
|
|||
kore_auth_init();
|
||||
kore_validator_init();
|
||||
kore_filemap_init();
|
||||
#endif
|
||||
#if defined(KORE_USE_ACME)
|
||||
kore_acme_init();
|
||||
#endif
|
||||
kore_domain_init();
|
||||
kore_module_init();
|
||||
|
|
|
@ -220,7 +220,7 @@ kore_platform_disable_accept(void)
|
|||
}
|
||||
|
||||
void
|
||||
kore_platform_proctitle(char *title)
|
||||
kore_platform_proctitle(const char *title)
|
||||
{
|
||||
kore_proctitle(title);
|
||||
}
|
||||
|
|
48
src/msg.c
48
src/msg.c
|
@ -40,30 +40,29 @@ static void msg_type_websocket(struct kore_msg *, const void *);
|
|||
#endif
|
||||
|
||||
static TAILQ_HEAD(, msg_type) msg_types;
|
||||
static int cacheidx = 0;
|
||||
static struct connection *conncache[KORE_WORKER_MAX];
|
||||
static size_t cacheidx = 0;
|
||||
static struct connection **conncache = NULL;
|
||||
|
||||
void
|
||||
kore_msg_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KORE_WORKER_MAX; i++)
|
||||
conncache[i] = NULL;
|
||||
|
||||
TAILQ_INIT(&msg_types);
|
||||
}
|
||||
|
||||
void
|
||||
kore_msg_parent_init(void)
|
||||
{
|
||||
u_int8_t i;
|
||||
u_int8_t idx;
|
||||
struct kore_worker *kw;
|
||||
|
||||
for (i = 0; i < worker_count; i++) {
|
||||
if (keymgr_active == 0 && i == KORE_WORKER_KEYMGR)
|
||||
continue;
|
||||
kw = kore_worker_data(i);
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
if (keymgr_active == 0) {
|
||||
if (idx == KORE_WORKER_KEYMGR_IDX ||
|
||||
idx == KORE_WORKER_ACME_IDX)
|
||||
continue;
|
||||
}
|
||||
|
||||
kw = kore_worker_data(idx);
|
||||
kore_msg_parent_add(kw);
|
||||
}
|
||||
|
||||
|
@ -83,8 +82,8 @@ kore_msg_parent_add(struct kore_worker *kw)
|
|||
kw->msg[0]->disconnect = msg_disconnected_worker;
|
||||
kw->msg[0]->handle = kore_connection_handle;
|
||||
|
||||
if (cacheidx >= KORE_WORKER_MAX)
|
||||
fatal("%s: too many workers", __func__);
|
||||
conncache = kore_realloc(conncache,
|
||||
(cacheidx + 1) * sizeof(struct connection *));
|
||||
|
||||
conncache[cacheidx++] = kw->msg[0];
|
||||
|
||||
|
@ -187,11 +186,11 @@ msg_recv_packet(struct netbuf *nb)
|
|||
static int
|
||||
msg_recv_data(struct netbuf *nb)
|
||||
{
|
||||
size_t i;
|
||||
struct connection *c;
|
||||
u_int8_t dst;
|
||||
struct msg_type *type;
|
||||
int deliver, i;
|
||||
u_int16_t destination;
|
||||
int deliver;
|
||||
u_int16_t dst, destination;
|
||||
struct kore_msg *msg = (struct kore_msg *)nb->buf;
|
||||
|
||||
if ((type = msg_type_lookup(msg->id)) != NULL) {
|
||||
|
@ -209,13 +208,20 @@ msg_recv_data(struct netbuf *nb)
|
|||
if (worker == NULL && type == NULL) {
|
||||
destination = msg->dst;
|
||||
|
||||
for (i = 0; conncache[i] != NULL; i++) {
|
||||
for (i = 0; i < cacheidx; i++) {
|
||||
c = conncache[i];
|
||||
if (c->proto != CONN_PROTO_MSG || c->hdlr_extra == NULL)
|
||||
if (c->proto != CONN_PROTO_MSG)
|
||||
fatal("connection not a msg connection");
|
||||
|
||||
/*
|
||||
* If hdlr_extra is NULL it just means the worker
|
||||
* never started, ignore it.
|
||||
*/
|
||||
if (c->hdlr_extra == NULL)
|
||||
continue;
|
||||
|
||||
deliver = 1;
|
||||
dst = *(u_int8_t *)c->hdlr_extra;
|
||||
dst = *(u_int16_t *)c->hdlr_extra;
|
||||
|
||||
if (destination == KORE_MSG_WORKER_ALL) {
|
||||
if (keymgr_active && dst == 0)
|
||||
|
@ -229,7 +235,7 @@ msg_recv_data(struct netbuf *nb)
|
|||
continue;
|
||||
|
||||
/* This allows the worker to receive the correct id. */
|
||||
msg->dst = *(u_int8_t *)c->hdlr_extra;
|
||||
msg->dst = *(u_int16_t *)c->hdlr_extra;
|
||||
|
||||
net_send_queue(c, nb->buf, nb->s_off);
|
||||
net_send_flush(c);
|
||||
|
|
|
@ -103,6 +103,7 @@ static struct sock_filter filter_kore[] = {
|
|||
#if defined(SYS_poll)
|
||||
KORE_SYSCALL_ALLOW(poll),
|
||||
#endif
|
||||
KORE_SYSCALL_ALLOW(ppoll),
|
||||
KORE_SYSCALL_ALLOW(sendto),
|
||||
KORE_SYSCALL_ALLOW(accept),
|
||||
KORE_SYSCALL_ALLOW(sendfile),
|
||||
|
@ -154,7 +155,7 @@ static struct sock_filter *seccomp_filter_update(struct sock_filter *,
|
|||
#define filter_prologue_len KORE_FILTER_LEN(filter_prologue)
|
||||
#define filter_epilogue_len KORE_FILTER_LEN(filter_epilogue)
|
||||
|
||||
static void seccomp_register_violation(struct kore_worker *);
|
||||
static void seccomp_register_violation(pid_t);
|
||||
|
||||
struct filter {
|
||||
char *name;
|
||||
|
@ -313,35 +314,34 @@ kore_seccomp_traceme(void)
|
|||
}
|
||||
|
||||
int
|
||||
kore_seccomp_trace(struct kore_worker *kw, int status)
|
||||
kore_seccomp_trace(pid_t pid, int status)
|
||||
{
|
||||
int evt;
|
||||
|
||||
if (kore_seccomp_tracing == 0)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) {
|
||||
if (kw->tracing == 0) {
|
||||
kw->tracing = 1;
|
||||
if (ptrace(PTRACE_SETOPTIONS, kw->pid, NULL,
|
||||
PTRACE_O_TRACESECCOMP) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
if (ptrace(PTRACE_CONT, kw->pid, NULL, NULL) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
|
||||
if ((status >> 8) ==
|
||||
(SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
|
||||
seccomp_register_violation(kw);
|
||||
if (ptrace(PTRACE_CONT, kw->pid, NULL, NULL) == -1)
|
||||
if (ptrace(PTRACE_SETOPTIONS, pid, NULL,
|
||||
PTRACE_O_TRACESECCOMP | PTRACE_O_TRACECLONE |
|
||||
PTRACE_O_TRACEFORK) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (WIFSTOPPED(status) && kw->tracing) {
|
||||
if (ptrace(PTRACE_CONT, kw->pid, NULL, WSTOPSIG(status)) == -1)
|
||||
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
|
||||
evt = status >> 8;
|
||||
if (evt == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
|
||||
seccomp_register_violation(pid);
|
||||
if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (WIFSTOPPED(status)) {
|
||||
if (ptrace(PTRACE_CONT, pid, NULL, WSTOPSIG(status)) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
@ -420,16 +420,19 @@ kore_seccomp_syscall_flag(const char *name, int action, int arg, int value)
|
|||
}
|
||||
|
||||
static void
|
||||
seccomp_register_violation(struct kore_worker *kw)
|
||||
seccomp_register_violation(pid_t pid)
|
||||
{
|
||||
int idx;
|
||||
struct kore_worker *kw;
|
||||
struct iovec iov;
|
||||
struct user_regs_struct regs;
|
||||
long sysnr;
|
||||
const char *name;
|
||||
|
||||
iov.iov_base = ®s;
|
||||
iov.iov_len = sizeof(regs);
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, kw->pid, 1, &iov) == -1)
|
||||
if (ptrace(PTRACE_GETREGSET, pid, 1, &iov) == -1)
|
||||
fatal("ptrace: %s", errno_s);
|
||||
|
||||
#if SECCOMP_AUDIT_ARCH == AUDIT_ARCH_X86_64
|
||||
|
@ -442,8 +445,20 @@ seccomp_register_violation(struct kore_worker *kw)
|
|||
#error "platform not yet supported"
|
||||
#endif
|
||||
|
||||
kore_log(LOG_INFO, "seccomp violation, worker=%d, syscall=%s",
|
||||
kw->id, kore_seccomp_syscall_name(sysnr));
|
||||
name = NULL;
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
kw = kore_worker_data(idx);
|
||||
if (kw->pid == pid) {
|
||||
name = kore_worker_name(kw->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
name = "<child>";
|
||||
|
||||
kore_log(LOG_INFO, "seccomp violation, %s pid=%d, syscall=%ld:%s",
|
||||
name, pid, sysnr, kore_seccomp_syscall_name(sysnr));
|
||||
}
|
||||
|
||||
static struct sock_filter *
|
||||
|
|
400
src/utils.c
400
src/utils.c
|
@ -17,6 +17,9 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -47,8 +50,19 @@ static struct {
|
|||
};
|
||||
|
||||
static void fatal_log(const char *, va_list);
|
||||
static int utils_base64_encode(const void *, size_t, char **,
|
||||
const char *, int);
|
||||
static int utils_base64_decode(const char *, u_int8_t **,
|
||||
size_t *, const char *, int);
|
||||
|
||||
static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static char b64_table[] = \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static char b64url_table[] = \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
/* b64_table and b64url_table are the same size. */
|
||||
#define B64_TABLE_LEN (sizeof(b64_table))
|
||||
|
||||
#if defined(KORE_DEBUG)
|
||||
void
|
||||
|
@ -83,20 +97,20 @@ void
|
|||
kore_log(int prio, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[2048], tmp[32];
|
||||
const char *name;
|
||||
char buf[2048];
|
||||
|
||||
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 (worker->id == KORE_WORKER_KEYMGR)
|
||||
(void)kore_strlcpy(tmp, "keymgr", sizeof(tmp));
|
||||
name = kore_worker_name(worker->id);
|
||||
|
||||
if (foreground)
|
||||
printf("[%s]: %s\n", tmp, buf);
|
||||
printf("%s: %s\n", name, buf);
|
||||
else
|
||||
syslog(prio, "[%s]: %s", tmp, buf);
|
||||
syslog(prio, "%s: %s", name, buf);
|
||||
} else {
|
||||
if (foreground)
|
||||
printf("[parent]: %s\n", buf);
|
||||
|
@ -410,135 +424,28 @@ kore_time_ms(void)
|
|||
return ((u_int64_t)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000)));
|
||||
}
|
||||
|
||||
int
|
||||
kore_base64url_encode(const void *data, size_t len, char **out, int flags)
|
||||
{
|
||||
return (utils_base64_encode(data, len, out, b64url_table, flags));
|
||||
}
|
||||
|
||||
int
|
||||
kore_base64_encode(const void *data, size_t len, char **out)
|
||||
{
|
||||
u_int8_t n;
|
||||
size_t nb;
|
||||
const u_int8_t *ptr;
|
||||
u_int32_t bytes;
|
||||
struct kore_buf result;
|
||||
return (utils_base64_encode(data, len, out, b64_table, 0));
|
||||
}
|
||||
|
||||
nb = 0;
|
||||
ptr = data;
|
||||
kore_buf_init(&result, (len / 3) * 4);
|
||||
|
||||
while (len > 0) {
|
||||
if (len > 2) {
|
||||
nb = 3;
|
||||
bytes = *ptr++ << 16;
|
||||
bytes |= *ptr++ << 8;
|
||||
bytes |= *ptr++;
|
||||
} else if (len > 1) {
|
||||
nb = 2;
|
||||
bytes = *ptr++ << 16;
|
||||
bytes |= *ptr++ << 8;
|
||||
} else if (len == 1) {
|
||||
nb = 1;
|
||||
bytes = *ptr++ << 16;
|
||||
} else {
|
||||
kore_buf_cleanup(&result);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
n = (bytes >> 18) & 0x3f;
|
||||
kore_buf_append(&result, &(b64table[n]), 1);
|
||||
n = (bytes >> 12) & 0x3f;
|
||||
kore_buf_append(&result, &(b64table[n]), 1);
|
||||
if (nb > 1) {
|
||||
n = (bytes >> 6) & 0x3f;
|
||||
kore_buf_append(&result, &(b64table[n]), 1);
|
||||
if (nb > 2) {
|
||||
n = bytes & 0x3f;
|
||||
kore_buf_append(&result, &(b64table[n]), 1);
|
||||
}
|
||||
}
|
||||
|
||||
len -= nb;
|
||||
}
|
||||
|
||||
switch (nb) {
|
||||
case 1:
|
||||
kore_buf_appendf(&result, "==");
|
||||
break;
|
||||
case 2:
|
||||
kore_buf_appendf(&result, "=");
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
kore_buf_cleanup(&result);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
/* result.data gets taken over so no need to cleanup result. */
|
||||
*out = kore_buf_stringify(&result, NULL);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
int
|
||||
kore_base64url_decode(const char *in, u_int8_t **out, size_t *olen, int flags)
|
||||
{
|
||||
return (utils_base64_decode(in, out, olen, b64url_table, flags));
|
||||
}
|
||||
|
||||
int
|
||||
kore_base64_decode(const char *in, u_int8_t **out, size_t *olen)
|
||||
{
|
||||
int i, c;
|
||||
struct kore_buf *res;
|
||||
u_int8_t d, n, o;
|
||||
u_int32_t b, len, idx;
|
||||
|
||||
i = 4;
|
||||
b = 0;
|
||||
d = 0;
|
||||
c = 0;
|
||||
len = strlen(in);
|
||||
res = kore_buf_alloc(len);
|
||||
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
c = in[idx];
|
||||
if (c == '=')
|
||||
break;
|
||||
|
||||
for (o = 0; o < sizeof(b64table); o++) {
|
||||
if (b64table[o] == c) {
|
||||
d = o;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (o == sizeof(b64table)) {
|
||||
*out = NULL;
|
||||
kore_buf_free(res);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
b |= (d & 0x3f) << ((i - 1) * 6);
|
||||
i--;
|
||||
if (i == 0) {
|
||||
for (i = 2; i >= 0; i--) {
|
||||
n = (b >> (8 * i));
|
||||
kore_buf_append(res, &n, 1);
|
||||
}
|
||||
|
||||
b = 0;
|
||||
i = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '=') {
|
||||
if (i > 2) {
|
||||
*out = NULL;
|
||||
kore_buf_free(res);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
o = i;
|
||||
for (i = 2; i >= o; i--) {
|
||||
n = (b >> (8 * i));
|
||||
kore_buf_append(res, &n, 1);
|
||||
}
|
||||
}
|
||||
|
||||
*out = kore_buf_release(res, olen);
|
||||
return (KORE_RESULT_OK);
|
||||
return (utils_base64_decode(in, out, olen, b64_table, 0));
|
||||
}
|
||||
|
||||
void *
|
||||
|
@ -605,6 +512,79 @@ kore_read_line(FILE *fp, char *in, size_t len)
|
|||
return (p);
|
||||
}
|
||||
|
||||
EVP_PKEY *
|
||||
kore_rsakey_load(const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
if (access(path, R_OK) == -1)
|
||||
return (NULL);
|
||||
|
||||
if ((fp = fopen(path, "r")) == NULL)
|
||||
fatalx("%s(%s): %s", __func__, path, errno_s);
|
||||
|
||||
if ((pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL)
|
||||
fatalx("PEM_read_PrivateKey: %s", ssl_errno_s);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return (pkey);
|
||||
}
|
||||
|
||||
EVP_PKEY *
|
||||
kore_rsakey_generate(const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
EVP_PKEY_CTX *ctx;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
|
||||
fatalx("EVP_PKEY_CTX_new_id: %s", ssl_errno_s);
|
||||
|
||||
if (EVP_PKEY_keygen_init(ctx) <= 0)
|
||||
fatalx("EVP_PKEY_keygen_init: %s", ssl_errno_s);
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KORE_RSAKEY_BITS) <= 0)
|
||||
fatalx("EVP_PKEY_CTX_set_rsa_keygen_bits: %s", ssl_errno_s);
|
||||
|
||||
pkey = NULL;
|
||||
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
|
||||
fatalx("EVP_PKEY_keygen: %s", ssl_errno_s);
|
||||
|
||||
if (path != NULL) {
|
||||
if ((fp = fopen(path, "w")) == NULL)
|
||||
fatalx("fopen(%s): %s", path, errno_s);
|
||||
|
||||
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL))
|
||||
fatalx("PEM_write_PrivateKey: %s", ssl_errno_s);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return (pkey);
|
||||
}
|
||||
|
||||
const char *
|
||||
kore_worker_name(int id)
|
||||
{
|
||||
static char buf[64];
|
||||
|
||||
switch (id) {
|
||||
case KORE_WORKER_KEYMGR:
|
||||
(void)snprintf(buf, sizeof(buf), "[keymgr]");
|
||||
break;
|
||||
case KORE_WORKER_ACME:
|
||||
(void)snprintf(buf, sizeof(buf), "[acme]");
|
||||
break;
|
||||
default:
|
||||
(void)snprintf(buf, sizeof(buf), "[wrk %d]", id);
|
||||
break;
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
void
|
||||
fatal(const char *fmt, ...)
|
||||
{
|
||||
|
@ -649,3 +629,169 @@ fatal_log(const char *fmt, va_list args)
|
|||
|
||||
printf("%s: %s\n", kore_progname, buf);
|
||||
}
|
||||
|
||||
static int
|
||||
utils_base64_encode(const void *data, size_t len, char **out,
|
||||
const char *table, int flags)
|
||||
{
|
||||
u_int8_t n;
|
||||
size_t nb;
|
||||
const u_int8_t *ptr;
|
||||
u_int32_t bytes;
|
||||
struct kore_buf result;
|
||||
|
||||
nb = 0;
|
||||
ptr = data;
|
||||
kore_buf_init(&result, (len / 3) * 4);
|
||||
|
||||
while (len > 0) {
|
||||
if (len > 2) {
|
||||
nb = 3;
|
||||
bytes = *ptr++ << 16;
|
||||
bytes |= *ptr++ << 8;
|
||||
bytes |= *ptr++;
|
||||
} else if (len > 1) {
|
||||
nb = 2;
|
||||
bytes = *ptr++ << 16;
|
||||
bytes |= *ptr++ << 8;
|
||||
} else if (len == 1) {
|
||||
nb = 1;
|
||||
bytes = *ptr++ << 16;
|
||||
} else {
|
||||
kore_buf_cleanup(&result);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
n = (bytes >> 18) & 0x3f;
|
||||
kore_buf_append(&result, &(table[n]), 1);
|
||||
n = (bytes >> 12) & 0x3f;
|
||||
kore_buf_append(&result, &(table[n]), 1);
|
||||
if (nb > 1) {
|
||||
n = (bytes >> 6) & 0x3f;
|
||||
kore_buf_append(&result, &(table[n]), 1);
|
||||
if (nb > 2) {
|
||||
n = bytes & 0x3f;
|
||||
kore_buf_append(&result, &(table[n]), 1);
|
||||
}
|
||||
}
|
||||
|
||||
len -= nb;
|
||||
}
|
||||
|
||||
if (!(flags & KORE_BASE64_RAW)) {
|
||||
switch (nb) {
|
||||
case 1:
|
||||
kore_buf_appendf(&result, "==");
|
||||
break;
|
||||
case 2:
|
||||
kore_buf_appendf(&result, "=");
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
kore_buf_cleanup(&result);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* result.data gets taken over so no need to cleanup result. */
|
||||
*out = kore_buf_stringify(&result, NULL);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
utils_base64_decode(const char *in, u_int8_t **out, size_t *olen,
|
||||
const char *table, int flags)
|
||||
{
|
||||
int i, c;
|
||||
u_int8_t d, n, o;
|
||||
struct kore_buf *res, buf;
|
||||
const char *ptr, *pad;
|
||||
u_int32_t b, len, plen, idx;
|
||||
|
||||
i = 4;
|
||||
b = 0;
|
||||
d = 0;
|
||||
c = 0;
|
||||
len = strlen(in);
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
if (flags & KORE_BASE64_RAW) {
|
||||
switch (len % 4) {
|
||||
case 2:
|
||||
plen = 2;
|
||||
pad = "==";
|
||||
break;
|
||||
case 3:
|
||||
plen = 1;
|
||||
pad = "=";
|
||||
break;
|
||||
default:
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
kore_buf_init(&buf, len + plen);
|
||||
kore_buf_appendf(&buf, in, len);
|
||||
kore_buf_appendf(&buf, pad, plen);
|
||||
|
||||
len = len + plen;
|
||||
ptr = (const char *)buf.data;
|
||||
} else {
|
||||
ptr = in;
|
||||
}
|
||||
|
||||
res = kore_buf_alloc(len);
|
||||
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
c = ptr[idx];
|
||||
if (c == '=')
|
||||
break;
|
||||
|
||||
for (o = 0; o < B64_TABLE_LEN; o++) {
|
||||
if (table[o] == c) {
|
||||
d = o;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (o == B64_TABLE_LEN) {
|
||||
*out = NULL;
|
||||
kore_buf_free(res);
|
||||
kore_buf_cleanup(&buf);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
b |= (d & 0x3f) << ((i - 1) * 6);
|
||||
i--;
|
||||
if (i == 0) {
|
||||
for (i = 2; i >= 0; i--) {
|
||||
n = (b >> (8 * i));
|
||||
kore_buf_append(res, &n, 1);
|
||||
}
|
||||
|
||||
b = 0;
|
||||
i = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '=') {
|
||||
if (i > 2) {
|
||||
*out = NULL;
|
||||
kore_buf_free(res);
|
||||
kore_buf_cleanup(&buf);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
o = i;
|
||||
for (i = 2; i >= o; i--) {
|
||||
n = (b >> (8 * i));
|
||||
kore_buf_append(res, &n, 1);
|
||||
}
|
||||
}
|
||||
|
||||
kore_buf_cleanup(&buf);
|
||||
*out = kore_buf_release(res, olen);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
|
245
src/worker.c
245
src/worker.c
|
@ -31,6 +31,10 @@
|
|||
|
||||
#include "kore.h"
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
#include "acme.h"
|
||||
#endif
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
#include "http.h"
|
||||
#endif
|
||||
|
@ -59,7 +63,7 @@
|
|||
#define WAIT_ANY (-1)
|
||||
#endif
|
||||
|
||||
#define WORKER_SOLO_COUNT 2
|
||||
#define WORKER_SOLO_COUNT 3
|
||||
|
||||
#define WORKER(id) \
|
||||
(struct kore_worker *)((u_int8_t *)kore_workers + \
|
||||
|
@ -80,8 +84,6 @@ static void worker_accept_avail(struct kore_msg *, const void *);
|
|||
|
||||
static void worker_entropy_recv(struct kore_msg *, const void *);
|
||||
static void worker_keymgr_response(struct kore_msg *, const void *);
|
||||
static int worker_keymgr_response_verify(struct kore_msg *, const void *,
|
||||
struct kore_domain **);
|
||||
|
||||
static int accept_avail;
|
||||
static struct kore_worker *kore_workers;
|
||||
|
@ -102,15 +104,15 @@ kore_worker_init(void)
|
|||
{
|
||||
size_t len;
|
||||
struct kore_worker *kw;
|
||||
u_int16_t i, cpu;
|
||||
u_int16_t idx, id, cpu;
|
||||
|
||||
worker_no_lock = 0;
|
||||
|
||||
if (worker_count == 0)
|
||||
worker_count = cpu_count;
|
||||
|
||||
/* Account for the keymgr even if we don't end up starting it. */
|
||||
worker_count += 1;
|
||||
/* Account for the keymgr/acme even if we don't end up starting it. */
|
||||
worker_count += 2;
|
||||
|
||||
len = sizeof(*accept_lock) +
|
||||
(sizeof(struct kore_worker) * worker_count);
|
||||
|
@ -136,30 +138,41 @@ kore_worker_init(void)
|
|||
}
|
||||
|
||||
/* Setup log buffers. */
|
||||
for (i = 0; i < worker_count; i++) {
|
||||
kw = WORKER(i);
|
||||
for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) {
|
||||
kw = WORKER(idx);
|
||||
kw->lb.offset = 0;
|
||||
}
|
||||
|
||||
/* Start keymgr if required. */
|
||||
if (keymgr_active)
|
||||
kore_worker_spawn(0, 0);
|
||||
|
||||
/* Now start all the workers. */
|
||||
id = 1;
|
||||
cpu = 1;
|
||||
for (i = 1; i < worker_count; i++) {
|
||||
for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) {
|
||||
if (cpu >= cpu_count)
|
||||
cpu = 0;
|
||||
kore_worker_spawn(i, cpu++);
|
||||
kore_worker_spawn(idx, id++, cpu++);
|
||||
}
|
||||
|
||||
if (keymgr_active) {
|
||||
#if defined(KORE_USE_ACME)
|
||||
/* The ACME process is only started if we need it. */
|
||||
if (acme_provider) {
|
||||
kore_worker_spawn(KORE_WORKER_ACME_IDX,
|
||||
KORE_WORKER_ACME, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now we can start the keymgr. */
|
||||
kore_worker_spawn(KORE_WORKER_KEYMGR_IDX,
|
||||
KORE_WORKER_KEYMGR, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
kore_worker_spawn(u_int16_t id, u_int16_t cpu)
|
||||
kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
|
||||
{
|
||||
struct kore_worker *kw;
|
||||
|
||||
kw = WORKER(id);
|
||||
kw = WORKER(idx);
|
||||
kw->id = id;
|
||||
kw->cpu = cpu;
|
||||
kw->has_lock = 0;
|
||||
|
@ -198,7 +211,7 @@ kore_worker_shutdown(void)
|
|||
struct kore_worker *kw;
|
||||
pid_t pid;
|
||||
int status;
|
||||
u_int16_t id, done;
|
||||
u_int16_t idx, done;
|
||||
|
||||
if (!kore_quiet) {
|
||||
kore_log(LOG_NOTICE,
|
||||
|
@ -206,15 +219,15 @@ kore_worker_shutdown(void)
|
|||
}
|
||||
|
||||
for (;;) {
|
||||
for (id = 0; id < worker_count; id++) {
|
||||
kw = WORKER(id);
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
kw = WORKER(idx);
|
||||
if (kw->pid != 0) {
|
||||
pid = waitpid(kw->pid, &status, 0);
|
||||
if (pid == -1)
|
||||
continue;
|
||||
|
||||
#if defined(__linux__)
|
||||
kore_seccomp_trace(kw, status);
|
||||
kore_seccomp_trace(kw->pid, status);
|
||||
#endif
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
|
@ -229,8 +242,8 @@ kore_worker_shutdown(void)
|
|||
}
|
||||
|
||||
done = 0;
|
||||
for (id = 0; id < worker_count; id++) {
|
||||
kw = WORKER(id);
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
kw = WORKER(idx);
|
||||
if (kw->pid == 0)
|
||||
done++;
|
||||
}
|
||||
|
@ -248,11 +261,11 @@ kore_worker_shutdown(void)
|
|||
void
|
||||
kore_worker_dispatch_signal(int sig)
|
||||
{
|
||||
u_int16_t id;
|
||||
u_int16_t idx;
|
||||
struct kore_worker *kw;
|
||||
|
||||
for (id = 0; id < worker_count; id++) {
|
||||
kw = WORKER(id);
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
kw = WORKER(idx);
|
||||
if (kill(kw->pid, sig) == -1) {
|
||||
kore_debug("kill(%d, %d): %s", kw->pid, sig, errno_s);
|
||||
}
|
||||
|
@ -329,7 +342,6 @@ void
|
|||
kore_worker_entry(struct kore_worker *kw)
|
||||
{
|
||||
struct kore_runtime_call *rcall;
|
||||
char buf[16];
|
||||
u_int64_t last_seed;
|
||||
int quit, had_lock;
|
||||
u_int64_t netwait, now, next_prune;
|
||||
|
@ -340,10 +352,7 @@ kore_worker_entry(struct kore_worker *kw)
|
|||
kore_seccomp_traceme();
|
||||
#endif
|
||||
|
||||
(void)snprintf(buf, sizeof(buf), "[wrk %d]", kw->id);
|
||||
if (kw->id == KORE_WORKER_KEYMGR)
|
||||
(void)snprintf(buf, sizeof(buf), "[keymgr]");
|
||||
kore_platform_proctitle(buf);
|
||||
kore_platform_proctitle(kore_worker_name(kw->id));
|
||||
|
||||
if (worker_set_affinity == 1)
|
||||
kore_platform_worker_setcpu(kw);
|
||||
|
@ -357,6 +366,13 @@ kore_worker_entry(struct kore_worker *kw)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
if (kw->id == KORE_WORKER_ACME) {
|
||||
kore_acme_run();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_init();
|
||||
kore_connection_init();
|
||||
kore_platform_event_init();
|
||||
|
@ -394,6 +410,12 @@ kore_worker_entry(struct kore_worker *kw)
|
|||
kore_msg_send(KORE_WORKER_KEYMGR,
|
||||
KORE_MSG_CERTIFICATE_REQ, NULL, 0);
|
||||
}
|
||||
#if defined(KORE_USE_ACME)
|
||||
kore_msg_register(KORE_ACME_CHALLENGE_SET_CERT,
|
||||
worker_keymgr_response);
|
||||
kore_msg_register(KORE_ACME_CHALLENGE_CLEAR_CERT,
|
||||
worker_keymgr_response);
|
||||
#endif
|
||||
}
|
||||
|
||||
kore_msg_register(KORE_MSG_ACCEPT_AVAILABLE, worker_accept_avail);
|
||||
|
@ -575,23 +597,79 @@ kore_worker_make_busy(void)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
kore_worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
|
||||
struct kore_domain **out)
|
||||
{
|
||||
struct kore_server *srv;
|
||||
struct kore_domain *dom;
|
||||
const struct kore_x509_msg *req;
|
||||
|
||||
if (msg->length < sizeof(*req)) {
|
||||
kore_log(LOG_WARNING,
|
||||
"short keymgr message (%zu)", msg->length);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
req = (const struct kore_x509_msg *)data;
|
||||
if (msg->length != (sizeof(*req) + req->data_len)) {
|
||||
kore_log(LOG_WARNING,
|
||||
"invalid keymgr payload (%zu)", msg->length);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (req->domain[KORE_DOMAINNAME_LEN] != '\0') {
|
||||
kore_log(LOG_WARNING, "domain not NUL-terminated");
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
}
|
||||
|
||||
if (out == NULL)
|
||||
return (KORE_RESULT_OK);
|
||||
|
||||
LIST_FOREACH(srv, &kore_servers, list) {
|
||||
dom = NULL;
|
||||
|
||||
if (srv->tls == 0)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(dom, &srv->domains, list) {
|
||||
if (!strcmp(dom->domain, req->domain))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dom != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dom == NULL) {
|
||||
kore_log(LOG_WARNING,
|
||||
"got keymgr response for domain that does not exist");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
*out = dom;
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
worker_reaper(pid_t pid, int status)
|
||||
{
|
||||
u_int16_t id;
|
||||
u_int16_t idx;
|
||||
struct kore_worker *kw;
|
||||
const char *func;
|
||||
|
||||
for (id = 0; id < worker_count; id++) {
|
||||
kw = WORKER(id);
|
||||
#if defined(__linux__)
|
||||
if (kore_seccomp_trace(pid, status))
|
||||
return;
|
||||
#endif
|
||||
|
||||
for (idx = 0; idx < worker_count; idx++) {
|
||||
kw = WORKER(idx);
|
||||
if (kw->pid != pid)
|
||||
continue;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (kore_seccomp_trace(kw, status))
|
||||
break;
|
||||
#endif
|
||||
|
||||
if (!kore_quiet) {
|
||||
kore_log(LOG_NOTICE,
|
||||
"worker %d (%d) exited with status %d",
|
||||
|
@ -619,8 +697,10 @@ worker_reaper(pid_t pid, int status)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (id == KORE_WORKER_KEYMGR) {
|
||||
kore_log(LOG_CRIT, "keymgr gone, stopping");
|
||||
if (kw->id == KORE_WORKER_KEYMGR ||
|
||||
kw->id == KORE_WORKER_ACME) {
|
||||
kore_log(LOG_CRIT,
|
||||
"keymgr or acme process gone, stopping");
|
||||
kw->pid = 0;
|
||||
if (raise(SIGTERM) != 0) {
|
||||
kore_log(LOG_WARNING,
|
||||
|
@ -657,7 +737,7 @@ worker_reaper(pid_t pid, int status)
|
|||
kore_log(LOG_NOTICE, "restarting worker %d", kw->id);
|
||||
kw->restarted = 1;
|
||||
kore_msg_parent_remove(kw);
|
||||
kore_worker_spawn(kw->id, kw->cpu);
|
||||
kore_worker_spawn(idx, kw->id, kw->cpu);
|
||||
kore_msg_parent_add(kw);
|
||||
|
||||
break;
|
||||
|
@ -769,74 +849,45 @@ worker_keymgr_response(struct kore_msg *msg, const void *data)
|
|||
struct kore_domain *dom;
|
||||
const struct kore_x509_msg *req;
|
||||
|
||||
if (!worker_keymgr_response_verify(msg, data, &dom))
|
||||
if (!kore_worker_keymgr_response_verify(msg, data, &dom))
|
||||
return;
|
||||
|
||||
req = (const struct kore_x509_msg *)data;
|
||||
|
||||
switch (msg->id) {
|
||||
case KORE_MSG_CERTIFICATE:
|
||||
kore_domain_tlsinit(dom, req->data, req->data_len);
|
||||
kore_domain_tlsinit(dom, KORE_PEM_CERT_CHAIN,
|
||||
req->data, req->data_len);
|
||||
break;
|
||||
case KORE_MSG_CRL:
|
||||
kore_domain_crl_add(dom, req->data, req->data_len);
|
||||
break;
|
||||
#if defined(KORE_USE_ACME)
|
||||
case KORE_ACME_CHALLENGE_SET_CERT:
|
||||
if (dom->ssl_ctx == NULL) {
|
||||
kore_domain_tlsinit(dom, KORE_DER_CERT_DATA,
|
||||
req->data, req->data_len);
|
||||
}
|
||||
|
||||
kore_free(dom->acme_cert);
|
||||
dom->acme_cert_len = req->data_len;
|
||||
dom->acme_cert = kore_calloc(1, req->data_len);
|
||||
memcpy(dom->acme_cert, req->data, req->data_len);
|
||||
|
||||
kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge active",
|
||||
dom->domain);
|
||||
dom->acme_challenge = 1;
|
||||
break;
|
||||
case KORE_ACME_CHALLENGE_CLEAR_CERT:
|
||||
dom->acme_cert_len = 0;
|
||||
dom->acme_challenge = 0;
|
||||
kore_free(dom->acme_cert);
|
||||
kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge disabled",
|
||||
dom->domain);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
kore_log(LOG_WARNING, "unknown keymgr request %u", msg->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
|
||||
struct kore_domain **out)
|
||||
{
|
||||
struct kore_server *srv;
|
||||
struct kore_domain *dom;
|
||||
const struct kore_x509_msg *req;
|
||||
|
||||
if (msg->length < sizeof(*req)) {
|
||||
kore_log(LOG_WARNING,
|
||||
"short keymgr message (%zu)", msg->length);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
req = (const struct kore_x509_msg *)data;
|
||||
if (msg->length != (sizeof(*req) + req->data_len)) {
|
||||
kore_log(LOG_WARNING,
|
||||
"invalid keymgr payload (%zu)", msg->length);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (req->domain_len > KORE_DOMAINNAME_LEN) {
|
||||
kore_log(LOG_WARNING,
|
||||
"invalid keymgr domain (%u)",
|
||||
req->domain_len);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
LIST_FOREACH(srv, &kore_servers, list) {
|
||||
dom = NULL;
|
||||
|
||||
if (srv->tls == 0)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(dom, &srv->domains, list) {
|
||||
if (!strncmp(dom->domain, req->domain, req->domain_len))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dom != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dom == NULL) {
|
||||
kore_log(LOG_WARNING,
|
||||
"got keymgr response for domain that does not exist");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
*out = dom;
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue