2013-04-17 22:34:27 +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 <sys/socket.h>
|
|
|
|
|
2013-07-27 20:56:15 +02:00
|
|
|
#include <netdb.h>
|
2013-05-03 00:04:06 +02:00
|
|
|
#include <signal.h>
|
2013-04-17 22:34:27 +02:00
|
|
|
|
|
|
|
#include "kore.h"
|
|
|
|
|
2013-05-03 00:04:06 +02:00
|
|
|
volatile sig_atomic_t sig_recv;
|
2013-05-02 09:10:35 +02:00
|
|
|
|
2013-07-27 20:56:15 +02:00
|
|
|
struct listener_head listeners;
|
|
|
|
u_int8_t nlisteners;
|
2013-06-26 11:18:32 +02:00
|
|
|
struct passwd *pw = NULL;
|
|
|
|
pid_t kore_pid = -1;
|
2013-06-17 23:39:17 +02:00
|
|
|
u_int16_t cpu_count = 1;
|
2013-06-05 08:55:07 +02:00
|
|
|
int kore_debug = 0;
|
2013-06-04 16:53:30 +02:00
|
|
|
u_int8_t worker_count = 0;
|
2013-05-30 19:36:42 +02:00
|
|
|
char *runas_user = NULL;
|
2013-06-05 09:47:08 +02:00
|
|
|
char *chroot_path = NULL;
|
2013-06-04 16:53:30 +02:00
|
|
|
char *kore_pidfile = KORE_PIDFILE_DEFAULT;
|
2013-06-27 08:43:07 +02:00
|
|
|
char *kore_ssl_cipher_list = KORE_DEFAULT_CIPHER_LIST;
|
2013-04-17 22:34:27 +02:00
|
|
|
|
2013-06-05 08:55:07 +02:00
|
|
|
static void usage(void);
|
2013-06-26 11:18:32 +02:00
|
|
|
static void kore_server_start(void);
|
|
|
|
static void kore_write_kore_pid(void);
|
2013-06-24 11:32:45 +02:00
|
|
|
static void kore_server_sslstart(void);
|
2013-04-17 22:34:27 +02:00
|
|
|
|
2013-06-05 08:55:07 +02:00
|
|
|
static void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Usage: kore [-c config] [-d]\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2013-04-17 22:34:27 +02:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
2013-06-05 08:55:07 +02:00
|
|
|
int ch;
|
2013-07-27 20:56:15 +02:00
|
|
|
struct listener *l;
|
2013-04-17 22:34:27 +02:00
|
|
|
|
2013-06-04 16:53:30 +02:00
|
|
|
if (getuid() != 0)
|
|
|
|
fatal("kore must be started as root");
|
2013-04-17 22:34:27 +02:00
|
|
|
|
2013-06-05 08:55:07 +02:00
|
|
|
while ((ch = getopt(argc, argv, "c:d")) != -1) {
|
|
|
|
switch (ch) {
|
|
|
|
case 'c':
|
|
|
|
config_file = optarg;
|
|
|
|
break;
|
|
|
|
case 'd':
|
2013-07-15 10:13:36 +02:00
|
|
|
#if defined(KORE_DEBUG)
|
2013-06-05 08:55:07 +02:00
|
|
|
kore_debug = 1;
|
2013-07-15 10:13:36 +02:00
|
|
|
#else
|
|
|
|
printf("kore not compiled with debug support\n");
|
|
|
|
#endif
|
2013-06-05 08:55:07 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_pid = getpid();
|
2013-06-27 08:43:07 +02:00
|
|
|
|
2013-07-27 20:56:15 +02:00
|
|
|
nlisteners = 0;
|
|
|
|
LIST_INIT(&listeners);
|
|
|
|
|
2013-07-15 10:13:36 +02:00
|
|
|
kore_log_init();
|
2013-06-27 08:43:07 +02:00
|
|
|
kore_mem_init();
|
2013-06-24 11:32:45 +02:00
|
|
|
kore_domain_init();
|
|
|
|
kore_server_sslstart();
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_parse_config();
|
2013-06-27 08:43:07 +02:00
|
|
|
|
2013-06-24 09:36:40 +02:00
|
|
|
kore_platform_init();
|
|
|
|
kore_accesslog_init();
|
2013-05-04 22:18:27 +02:00
|
|
|
|
2013-05-03 00:04:06 +02:00
|
|
|
sig_recv = 0;
|
|
|
|
signal(SIGHUP, kore_signal);
|
2013-06-05 09:47:08 +02:00
|
|
|
signal(SIGQUIT, kore_signal);
|
|
|
|
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_server_start();
|
2013-05-03 00:04:06 +02:00
|
|
|
|
2013-06-04 23:24:47 +02:00
|
|
|
kore_log(LOG_NOTICE, "server shutting down");
|
2013-06-26 16:37:22 +02:00
|
|
|
kore_worker_shutdown();
|
2013-06-04 16:53:30 +02:00
|
|
|
unlink(kore_pidfile);
|
2013-07-27 20:56:15 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(l, &listeners, list)
|
|
|
|
close(l->fd);
|
2013-06-04 11:55:38 +02:00
|
|
|
|
2013-06-26 16:37:22 +02:00
|
|
|
kore_log(LOG_NOTICE, "goodbye");
|
2013-04-17 22:34:27 +02:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
int
|
|
|
|
kore_ssl_npn_cb(SSL *ssl, const u_char **data, unsigned int *len, void *arg)
|
2013-06-17 23:39:17 +02:00
|
|
|
{
|
2013-06-24 11:32:45 +02:00
|
|
|
kore_debug("kore_ssl_npn_cb(): sending protocols");
|
2013-06-17 23:39:17 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
*data = (const unsigned char *)KORE_SSL_PROTO_STRING;
|
|
|
|
*len = strlen(KORE_SSL_PROTO_STRING);
|
2013-06-17 23:39:17 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
return (SSL_TLSEXT_ERR_OK);
|
|
|
|
}
|
2013-06-17 23:39:17 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
int
|
|
|
|
kore_ssl_sni_cb(SSL *ssl, int *ad, void *arg)
|
|
|
|
{
|
|
|
|
struct kore_domain *dom;
|
|
|
|
const char *sname;
|
|
|
|
|
|
|
|
sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
|
|
|
kore_debug("kore_ssl_sni_cb(): received host %s", sname);
|
|
|
|
|
|
|
|
if (sname != NULL && (dom = kore_domain_lookup(sname)) != NULL) {
|
|
|
|
kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname);
|
|
|
|
SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
|
|
|
|
return (SSL_TLSEXT_ERR_OK);
|
2013-06-17 23:39:17 +02:00
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
return (SSL_TLSEXT_ERR_NOACK);
|
|
|
|
}
|
2013-06-17 23:39:17 +02:00
|
|
|
|
2013-07-27 20:56:15 +02:00
|
|
|
int
|
|
|
|
kore_server_bind(const char *ip, const char *port)
|
|
|
|
{
|
|
|
|
struct listener *l;
|
|
|
|
int on, r;
|
|
|
|
struct addrinfo *results;
|
|
|
|
|
|
|
|
kore_debug("kore_server_bind(%s, %s)", ip, port);
|
|
|
|
|
|
|
|
r = getaddrinfo(ip, port, NULL, &results);
|
|
|
|
if (r != 0)
|
|
|
|
fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
|
|
|
|
|
|
|
|
l = kore_malloc(sizeof(struct listener));
|
|
|
|
l->type = KORE_TYPE_LISTENER;
|
|
|
|
l->addrtype = results->ai_family;
|
|
|
|
|
|
|
|
if (l->addrtype != AF_INET && l->addrtype != AF_INET6)
|
|
|
|
fatal("getaddrinfo(): unknown address family %d", l->addrtype);
|
|
|
|
|
|
|
|
if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) {
|
|
|
|
kore_mem_free(l);
|
|
|
|
freeaddrinfo(results);
|
|
|
|
kore_debug("socket(): %s", errno_s);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!kore_connection_nonblock(l->fd)) {
|
|
|
|
kore_mem_free(l);
|
|
|
|
freeaddrinfo(results);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
on = 1;
|
|
|
|
if (setsockopt(l->fd, SOL_SOCKET,
|
|
|
|
SO_REUSEADDR, (const char *)&on, sizeof(on)) == -1) {
|
|
|
|
close(l->fd);
|
|
|
|
kore_mem_free(l);
|
|
|
|
freeaddrinfo(results);
|
|
|
|
kore_debug("setsockopt(): %s", errno_s);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
|
|
|
|
close(l->fd);
|
|
|
|
kore_mem_free(l);
|
|
|
|
freeaddrinfo(results);
|
|
|
|
kore_debug("bind(): %s", errno_s);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo(results);
|
|
|
|
|
|
|
|
if (listen(l->fd, 5000) == -1) {
|
|
|
|
close(l->fd);
|
|
|
|
kore_mem_free(l);
|
|
|
|
kore_debug("listen(): %s", errno_s);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
nlisteners++;
|
|
|
|
LIST_INSERT_HEAD(&listeners, l, list);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-06-26 11:18:32 +02:00
|
|
|
void
|
|
|
|
kore_signal(int sig)
|
|
|
|
{
|
|
|
|
sig_recv = sig;
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
static void
|
|
|
|
kore_server_sslstart(void)
|
|
|
|
{
|
|
|
|
kore_debug("kore_server_sslstart()");
|
|
|
|
|
|
|
|
SSL_library_init();
|
|
|
|
SSL_load_error_strings();
|
2013-06-17 23:39:17 +02:00
|
|
|
}
|
|
|
|
|
2013-06-26 11:18:32 +02:00
|
|
|
static void
|
|
|
|
kore_server_start(void)
|
|
|
|
{
|
2013-06-27 08:43:07 +02:00
|
|
|
kore_mem_free(runas_user);
|
2013-06-26 16:37:22 +02:00
|
|
|
|
2013-06-26 11:18:32 +02:00
|
|
|
if (daemon(1, 1) == -1)
|
|
|
|
fatal("cannot daemon(): %s", errno_s);
|
|
|
|
|
|
|
|
kore_pid = getpid();
|
|
|
|
kore_write_kore_pid();
|
|
|
|
|
|
|
|
kore_log(LOG_NOTICE, "kore is starting up");
|
|
|
|
kore_platform_proctitle("kore [parent]");
|
|
|
|
kore_worker_init();
|
|
|
|
|
2013-06-26 16:37:22 +02:00
|
|
|
for (;;) {
|
|
|
|
if (sig_recv != 0) {
|
|
|
|
if (sig_recv == SIGHUP || sig_recv == SIGQUIT) {
|
|
|
|
kore_worker_dispatch_signal(sig_recv);
|
|
|
|
if (sig_recv == SIGHUP)
|
|
|
|
kore_module_reload();
|
|
|
|
if (sig_recv == SIGQUIT)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sig_recv = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!kore_accesslog_wait())
|
|
|
|
break;
|
|
|
|
kore_worker_wait(0);
|
|
|
|
}
|
2013-06-26 11:18:32 +02:00
|
|
|
}
|
|
|
|
|
2013-06-17 23:39:17 +02:00
|
|
|
static void
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_write_kore_pid(void)
|
2013-06-04 16:53:30 +02:00
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if ((fp = fopen(kore_pidfile, "w+")) == NULL) {
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_debug("kore_write_kore_pid(): fopen() %s", errno_s);
|
2013-06-04 16:53:30 +02:00
|
|
|
} else {
|
2013-06-26 11:18:32 +02:00
|
|
|
fprintf(fp, "%d\n", kore_pid);
|
2013-06-04 16:53:30 +02:00
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
}
|