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 7350131232b44bf660099f165a434097d80a8e44
parent 0d72f11902dbe9564996ecbb6824fc23c42d3375
Author: Joris Vink <joris@coders.se>
Date:   Fri, 27 Sep 2019 10:22:35 +0000

Allow listening of tls/notls ports at the same time.

Before kore needed to be built with NOTLS=1 to be able to do non TLS
connections. This has been like this for years.

It is time to allow non TLS listeners without having to rebuild Kore.

This commit changes your configuration format and will break existing
applications their config.

Configurations now get listener {} contexts:

listen default {
	bind 127.0.0.1 8888
}

The above will create a listener on 127.0.0.1, port 8888 that will serve
TLS (still the default).

If you want to turn off TLS on that listener, specify "tls no" in that
context.

Domains now need to be attached to a listener:

Eg:
	domain * {
		attach	default
	}

For the Python API this kills kore.bind(), and kore.bind_unix(). They are
replaced with:

	kore.listen("name", ip=None, port=None, path=None, tls=True).

Diffstat:
Makefile | 10----------
README.md | 2--
examples/async-curl/conf/async-curl.conf | 6+++++-
examples/cookies/conf/cookies.conf | 7++++++-
examples/cpp/conf/cpp.conf | 7++++++-
examples/generic/conf/generic.conf | 7++++++-
examples/headers/conf/headers.conf | 7++++++-
examples/integers/conf/integers.conf | 7++++++-
examples/json_yajl/conf/json_yajl.conf | 7++++++-
examples/jsonrpc/conf/jsonrpc.conf | 7++++++-
examples/memtag/conf/memtag.conf | 7++++++-
examples/messaging/conf/messaging.conf | 7++++++-
examples/nohttp/README.md | 2--
examples/nohttp/conf/build.conf | 7+++++++
examples/nohttp/conf/nohttp.conf | 18++++++------------
examples/parameters/conf/parameters.conf | 7++++++-
examples/pgsql-sync/conf/pgsql-sync.conf | 7++++++-
examples/pgsql/conf/pgsql.conf | 11+++++++++--
examples/pipe_task/conf/build.conf | 7+++++++
examples/pipe_task/conf/pipe_task.conf | 7++++++-
examples/python-async/conf/python-async.conf | 7++++++-
examples/python-pgsql/kore.conf | 6+++++-
examples/sse/conf/sse.conf | 7++++++-
examples/tasks/conf/build.conf | 7+++++++
examples/tasks/conf/tasks.conf | 7++++++-
examples/tasks/src/tasks.c | 25+++++++++++++++++++++++++
examples/tls-proxy/conf/tls-proxy.conf | 6+++++-
examples/upload/conf/upload.conf | 7++++++-
examples/video_stream/conf/video_stream.conf | 7++++++-
examples/websocket/conf/websocket.conf | 7++++++-
include/kore/kore.h | 100+++++++++++++++++++++++++++++++++++++++----------------------------------------
include/kore/python_methods.h | 18+++++++-----------
src/accesslog.c | 5-----
src/cli.c | 7++++++-
src/config.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
src/connection.c | 45++++++++++++++++++++-------------------------
src/curl.c | 4++++
src/domain.c | 113+++++++++++++++++++++++++++++++++++--------------------------------------------
src/filemap.c | 11+++++++----
src/fileref.c | 29++++++++++++++++++++++++-----
src/http.c | 1+
src/keymgr.c | 27++++++++++++++++++---------
src/kore.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
src/linux.c | 2++
src/module.c | 33+++++++++++++++++----------------
src/net.c | 13+++++++++----
src/python.c | 281++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
src/seccomp.c | 11++---------
src/tasks.c | 14++++++++++++++
src/utils.c | 4----
src/worker.c | 49++++++++++++++++---------------------------------
51 files changed, 810 insertions(+), 474 deletions(-)

diff --git a/Makefile b/Makefile @@ -63,16 +63,6 @@ else src/validator.c src/websocket.c endif -ifneq ("$(NOTLS)", "") - CFLAGS+=-DKORE_NO_TLS - FEATURES+=-DKORE_NO_TLS - ifneq ("$(NOHTTP)", "") - LDFLAGS=-rdynamic - else - LDFLAGS=-rdynamic -l$(KORE_CRYPTO) - endif -endif - ifneq ("$(PGSQL)", "") S_SRC+=src/pgsql.c LDFLAGS+=-L$(shell pg_config --libdir) -lpq diff --git a/README.md b/README.md @@ -52,7 +52,6 @@ Clone this repository or get the latest release at [https://kore.io/releases/3.2 Requirements * openssl (1.0.2, 1.1.0 or 1.1.1) - (note: this requirement drops away when building with NOTLS=1 NOHTTP=1) (note: libressl 3.0.0+ works as a replacement) Requirement for asynchronous curl (optional) @@ -82,7 +81,6 @@ those by setting a shell environment variable before running **_make_**. * TASKS=1 (compiles in task support) * PGSQL=1 (compiles in pgsql support) * DEBUG=1 (enables use of -d for debug) -* NOTLS=1 (compiles Kore without TLS) * NOHTTP=1 (compiles Kore without HTTP support) * NOOPT=1 (disable compiler optimizations) * JSONRPC=1 (compiles in JSONRPC support) diff --git a/examples/async-curl/conf/async-curl.conf b/examples/async-curl/conf/async-curl.conf @@ -1,6 +1,8 @@ # ht configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} workers 1 tls_dhparam dh2048.pem @@ -8,6 +10,8 @@ tls_dhparam dh2048.pem pledge dns domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/cookies/conf/cookies.conf b/examples/cookies/conf/cookies.conf @@ -1,11 +1,16 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./cookies.so tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/cpp/conf/cpp.conf b/examples/cpp/conf/cpp.conf @@ -1,10 +1,15 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./cpp.so tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem static / page diff --git a/examples/generic/conf/generic.conf b/examples/generic/conf/generic.conf @@ -1,6 +1,9 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./generic.so example_load tls_dhparam dh2048.pem @@ -21,6 +24,8 @@ authentication auth_example { } domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem accesslog kore_access.log diff --git a/examples/headers/conf/headers.conf b/examples/headers/conf/headers.conf @@ -1,11 +1,16 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./headers.so tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem static / page diff --git a/examples/integers/conf/integers.conf b/examples/integers/conf/integers.conf @@ -1,6 +1,9 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./integers.so workers 2 @@ -11,6 +14,8 @@ tls_dhparam dh2048.pem validator v_id regex ^-?[0-9]*.?[0-9]+$ domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem static / page diff --git a/examples/json_yajl/conf/json_yajl.conf b/examples/json_yajl/conf/json_yajl.conf @@ -1,11 +1,16 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./json_yajl.so tls_dhparam dh2048.pem domain 127.0.0.1 { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/jsonrpc/conf/jsonrpc.conf b/examples/jsonrpc/conf/jsonrpc.conf @@ -1,11 +1,16 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./jsonrpc.so tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/memtag/conf/memtag.conf b/examples/memtag/conf/memtag.conf @@ -1,11 +1,16 @@ # memtag configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./memtag.so init tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/messaging/conf/messaging.conf b/examples/messaging/conf/messaging.conf @@ -1,11 +1,16 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./messaging.so init tls_dhparam dh2048.pem workers 4 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem static / page diff --git a/examples/nohttp/README.md b/examples/nohttp/README.md @@ -1,7 +1,5 @@ Kore NOHTTP example -Note that this example only works if Kore was built with NOHTTP=1. - Run: ``` $ kodev run diff --git a/examples/nohttp/conf/build.conf b/examples/nohttp/conf/build.conf @@ -1,6 +1,13 @@ # nohttp build config # You can switch flavors using: kodev flavor [newflavor] +# Set to yes if you wish to produce a single binary instead +# of a dynamic library. If you set this to yes you must also +# set kore_source together with kore_flavor. +single_binary=yes +kore_source=../../ +kore_flavor=NOHTTP=1 + # The cflags below are shared between flavors cflags=-Wall -Wmissing-declarations -Wshadow cflags=-Wstrict-prototypes -Wmissing-prototypes diff --git a/examples/nohttp/conf/nohttp.conf b/examples/nohttp/conf/nohttp.conf @@ -1,22 +1,16 @@ -# Kore can be used as a network layer if it was -# built with NOHTTP=1. -# -# With this you can bind a callback for every new -# connection that has been established. For TLS connections -# the callback is called after the TLS handshake is completed. +# nohttp configuration -# We must load the module first as we need the callback from it. load ./nohttp.so -# Listen on port 8888 and call connection_setup for each new connection. -bind 127.0.0.1 8888 connection_setup +listen tls { + bind 127.0.0.1 8888 connection_setup +} -# TLS dh params. tls_dhparam dh2048.pem -# We must still define a domain to use TLS. This might go away -# in the future for NOHTTP=1 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem } diff --git a/examples/parameters/conf/parameters.conf b/examples/parameters/conf/parameters.conf @@ -1,6 +1,9 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./parameters.so tls_dhparam dh2048.pem @@ -11,6 +14,8 @@ tls_dhparam dh2048.pem validator v_id regex ^[0-9]*$ domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/pgsql-sync/conf/pgsql-sync.conf b/examples/pgsql-sync/conf/pgsql-sync.conf @@ -1,10 +1,15 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./pgsql-sync.so init tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem static / page diff --git a/examples/pgsql/conf/pgsql.conf b/examples/pgsql/conf/pgsql.conf @@ -2,14 +2,21 @@ load ./pgsql.so init -bind 127.0.0.1 8888 -bind 127.0.0.1 8889 connection_new +listen tls { + bind 127.0.0.1 8888 +} + +listen other { + bind 127.0.0.1 8889 connection_new +} tls_dhparam dh2048.pem http_keepalive_time 0 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/pipe_task/conf/build.conf b/examples/pipe_task/conf/build.conf @@ -1,6 +1,13 @@ # pipe_task build config # You can switch flavors using: kodev flavor [newflavor] +# Set to yes if you wish to produce a single binary instead +# of a dynamic library. If you set this to yes you must also +# set kore_source together with kore_flavor. +single_binary=yes +kore_source=../../ +kore_flavor=TASKS=1 + # The cflags below are shared between flavors cflags=-Wall -Wmissing-declarations -Wshadow cflags=-Wstrict-prototypes -Wmissing-prototypes diff --git a/examples/pipe_task/conf/pipe_task.conf b/examples/pipe_task/conf/pipe_task.conf @@ -1,6 +1,9 @@ # Kore pipe_task example -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./pipe_task.so init tls_dhparam dh2048.pem @@ -9,6 +12,8 @@ websocket_maxframe 65536 websocket_timeout 10000 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/python-async/conf/python-async.conf b/examples/python-async/conf/python-async.conf @@ -1,6 +1,9 @@ # python-async configuration -bind 127.0.0.1 8888 +listen notls { + tls no + bind 127.0.0.1 8888 +} python_path src @@ -12,6 +15,8 @@ python_import ./src/async_socket.py python_import ./src/async_http.py domain * { + attach notls + static /queue async_queue static /lock async_lock static /proc async_proc diff --git a/examples/python-pgsql/kore.conf b/examples/python-pgsql/kore.conf @@ -1,10 +1,14 @@ # sql configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} tls_dhparam dh2048.pem domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/sse/conf/sse.conf b/examples/sse/conf/sse.conf @@ -1,12 +1,17 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./sse.so tls_dhparam dh2048.pem http_keepalive_time 600 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/tasks/conf/build.conf b/examples/tasks/conf/build.conf @@ -1,6 +1,13 @@ # tasks build config # You can switch flavors using: kodev flavor [newflavor] +# Set to yes if you wish to produce a single binary instead +# of a dynamic library. If you set this to yes you must also +# set kore_source together with kore_flavor. +single_binary=yes +kore_source=../../ +kore_flavor=TASKS=1 + # The cflags below are shared between flavors cflags=-Wall -Wmissing-declarations -Wshadow cflags=-Wstrict-prototypes -Wmissing-prototypes diff --git a/examples/tasks/conf/tasks.conf b/examples/tasks/conf/tasks.conf @@ -1,6 +1,9 @@ # Kore config for tasks example -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./tasks.so tls_dhparam dh2048.pem @@ -12,6 +15,8 @@ http_keepalive_time 0 validator v_user regex ^[a-z]*$ domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem accesslog kore_access.log diff --git a/examples/tasks/src/tasks.c b/examples/tasks/src/tasks.c @@ -33,6 +33,31 @@ #include <kore/http.h> #include <kore/tasks.h> +/* We need to allow some more syscalls on linux. */ +#if defined(__linux__) +#include <kore/seccomp.h> + +KORE_SECCOMP_FILTER("tasks", + /* Allow sockets and libcurl to call connect. */ + KORE_SYSCALL_ALLOW(bind), + KORE_SYSCALL_ALLOW(ioctl), + KORE_SYSCALL_ALLOW(connect), + KORE_SYSCALL_ALLOW(getsockopt), + KORE_SYSCALL_ALLOW(getsockname), + KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET), + KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6), + KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX), + KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_NETLINK), + + /* Other */ + KORE_SYSCALL_ALLOW(ioctl), + KORE_SYSCALL_ALLOW(madvise), + KORE_SYSCALL_ALLOW(recvmsg), + KORE_SYSCALL_ALLOW(sendmmsg), + KORE_SYSCALL_ALLOW(getpeername), +); +#endif + int run_curl(struct kore_task *); int post_back(struct http_request *); int page_handler(struct http_request *); diff --git a/examples/tls-proxy/conf/tls-proxy.conf b/examples/tls-proxy/conf/tls-proxy.conf @@ -8,10 +8,14 @@ tls_dhparam dh2048.pem # connection we receive we will call client_setup # so it can kick things in action. # -bind 127.0.0.1 8888 client_setup +listen tls { + bind 127.0.0.1 8888 client_setup +} # Setup domain for TLS usage. domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem } diff --git a/examples/upload/conf/upload.conf b/examples/upload/conf/upload.conf @@ -1,6 +1,9 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./upload.so tls_dhparam dh2048.pem @@ -9,6 +12,8 @@ http_body_max 1024000000 http_body_disk_offload 4096 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/examples/video_stream/conf/video_stream.conf b/examples/video_stream/conf/video_stream.conf @@ -1,6 +1,9 @@ # Placeholder configuration -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./video_stream.so init tls_dhparam dh2048.pem @@ -8,6 +11,8 @@ tls_dhparam dh2048.pem http_keepalive_time 600 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem accesslog access.log diff --git a/examples/websocket/conf/websocket.conf b/examples/websocket/conf/websocket.conf @@ -1,6 +1,9 @@ # Kore websocket example -bind 127.0.0.1 8888 +listen tls { + bind 127.0.0.1 8888 +} + load ./websocket.so tls_dhparam dh2048.pem @@ -13,6 +16,8 @@ websocket_maxframe 65536 websocket_timeout 20 domain * { + attach tls + certfile cert/server.pem certkey cert/key.pem diff --git a/include/kore/kore.h b/include/kore/kore.h @@ -30,11 +30,9 @@ #include <netinet/in.h> #include <arpa/inet.h> -#if !defined(KORE_NO_TLS) #include <openssl/err.h> #include <openssl/dh.h> #include <openssl/ssl.h> -#endif #include <errno.h> #include <regex.h> @@ -57,7 +55,7 @@ extern int daemon(int, int); #define st_mtim st_mtimespec #endif -#if !defined(KORE_NO_SENDFILE) && defined(KORE_NO_TLS) +#if !defined(KORE_NO_SENDFILE) #if defined(__MACH__) || defined(__FreeBSD_version) || defined(__linux__) #define KORE_USE_PLATFORM_SENDFILE 1 #endif @@ -127,16 +125,14 @@ struct http_request; struct kore_fileref { int cnt; int flags; + int ontls; off_t size; char *path; u_int64_t mtime; time_t mtime_sec; u_int64_t expiration; -#if !defined(KORE_USE_PLATFORM_SENDFILE) void *base; -#else int fd; -#endif TAILQ_ENTRY(kore_fileref) list; }; @@ -149,12 +145,10 @@ struct netbuf { u_int8_t flags; struct kore_fileref *file_ref; -#if defined(KORE_USE_PLATFORM_SENDFILE) off_t fd_off; off_t fd_len; -#endif - void *owner; + struct connection *owner; void *extra; int (*cb)(struct netbuf *); @@ -218,12 +212,10 @@ struct connection { int fd; u_int8_t state; u_int8_t proto; - void *owner; -#if !defined(KORE_NO_TLS) + struct listener *owner; X509 *cert; SSL *ssl; int tls_reneg; -#endif u_int8_t flags; void *hdlr_extra; @@ -288,13 +280,40 @@ struct kore_runtime_call { struct kore_runtime *runtime; }; +struct kore_domain { + u_int16_t id; + int logerr; + u_int64_t logwarn; + int accesslog; + + char *domain; + struct kore_buf *logbuf; + struct listener *listener; + + char *cafile; + char *crlfile; + char *certfile; + char *certkey; + SSL_CTX *ssl_ctx; + int x509_verify_depth; +#if !defined(KORE_NO_HTTP) + TAILQ_HEAD(, kore_module_handle) handlers; +#endif + TAILQ_ENTRY(kore_domain) list; +}; + +TAILQ_HEAD(kore_domain_h, kore_domain); + extern struct kore_runtime kore_native_runtime; struct listener { struct kore_event evt; int fd; + int tls; int family; struct kore_runtime_call *connect; + char *name; + struct kore_domain_h domains; LIST_ENTRY(listener) list; }; @@ -410,29 +429,6 @@ struct kore_worker { } lb; }; -struct kore_domain { - u_int16_t id; - char *domain; - int accesslog; - struct kore_buf *logbuf; - int logerr; - u_int64_t logwarn; -#if !defined(KORE_NO_TLS) - char *cafile; - char *crlfile; - char *certfile; - char *certkey; - SSL_CTX *ssl_ctx; - int x509_verify_depth; -#endif -#if !defined(KORE_NO_HTTP) - TAILQ_HEAD(, kore_module_handle) handlers; -#endif - TAILQ_ENTRY(kore_domain) list; -}; - -TAILQ_HEAD(kore_domain_h, kore_domain); - #if !defined(KORE_NO_HTTP) #define KORE_VALIDATOR_TYPE_REGEX 1 @@ -520,7 +516,6 @@ struct kore_msg { size_t length; }; -#if !defined(KORE_NO_TLS) struct kore_keyreq { int padding; char domain[KORE_DOMAINNAME_LEN]; @@ -535,7 +530,6 @@ struct kore_x509_msg { size_t data_len; u_int8_t data[]; }; -#endif #if !defined(KORE_SINGLE_BINARY) extern char *config_file; @@ -554,13 +548,11 @@ extern char *kore_tls_cipher_list; extern volatile sig_atomic_t sig_recv; -#if !defined(KORE_NO_TLS) extern int tls_version; extern DH *tls_dhparam; extern char *rand_file; extern char *keymgr_runas_user; extern char *keymgr_root_path; -#endif extern u_int8_t nlisteners; extern u_int16_t cpu_count; @@ -578,7 +570,6 @@ extern u_int32_t kore_socket_backlog; extern struct listener_head listeners; extern struct kore_worker *worker; -extern struct kore_domain_h domains; extern struct kore_domain *primary_dom; extern struct kore_pool nb_pool; @@ -646,17 +637,21 @@ struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t), u_int64_t, void *, int); void kore_listener_cleanup(void); +void kore_listener_closeall(void); void kore_listener_accept(void *, int); +struct listener *kore_listener_create(const char *); +struct listener *kore_listener_lookup(const char *); void kore_listener_free(struct listener *); -struct listener *kore_listener_alloc(int, const char *); +int kore_listener_init(struct listener *, int, const char *); int kore_sockopt(int, int, int); -int kore_server_bind_unix(const char *, const char *); -int kore_server_bind(const char *, const char *, const char *); -#if !defined(KORE_NO_TLS) +int kore_server_bind_unix(struct listener *, + const char *, const char *); +int kore_server_bind(struct listener *, + const char *, const char *, const char *); + int kore_tls_sni_cb(SSL *, int *, void *); void kore_tls_info_callback(const SSL *, int, int); -#endif void kore_connection_init(void); void kore_connection_cleanup(void); @@ -749,14 +744,15 @@ extern char *kore_filemap_index; #endif void kore_fileref_init(void); -struct kore_fileref *kore_fileref_get(const char *); -struct kore_fileref *kore_fileref_create(const char *, int, off_t, - struct timespec *); +struct kore_fileref *kore_fileref_get(const char *, int); +struct kore_fileref *kore_fileref_create(struct connection *, + const char *, int, off_t, struct timespec *); void kore_fileref_release(struct kore_fileref *); +struct kore_domain *kore_domain_new(const char *); + void kore_domain_init(void); void kore_domain_cleanup(void); -int kore_domain_new(const char *); void kore_domain_free(struct kore_domain *); void kore_module_init(void); void kore_module_cleanup(void); @@ -768,10 +764,11 @@ void *kore_module_getsym(const char *, struct kore_runtime **); 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 listener *, struct kore_domain *); void kore_domain_tlsinit(struct kore_domain *, 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(const char *, const char *, +int kore_module_handler_new(struct kore_domain *, const char *, const char *, const char *, int); void kore_module_handler_free(struct kore_module_handle *); struct kore_module_handle *kore_module_handler_find(struct http_request *, @@ -799,7 +796,8 @@ void kore_runtime_wsmessage(struct kore_runtime_call *, #endif struct kore_domain *kore_domain_byid(u_int16_t); -struct kore_domain *kore_domain_lookup(const char *); +struct kore_domain *kore_domain_lookup(struct listener *, + const char *); #if !defined(KORE_NO_HTTP) void kore_validator_init(void); diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h @@ -38,26 +38,27 @@ static PyObject *python_kore_log(PyObject *, PyObject *); static PyObject *python_kore_time(PyObject *, PyObject *); static PyObject *python_kore_lock(PyObject *, PyObject *); static PyObject *python_kore_proc(PyObject *, PyObject *); -static PyObject *python_kore_bind(PyObject *, PyObject *); static PyObject *python_kore_timer(PyObject *, PyObject *); static PyObject *python_kore_fatal(PyObject *, PyObject *); static PyObject *python_kore_queue(PyObject *, PyObject *); static PyObject *python_kore_worker(PyObject *, PyObject *); static PyObject *python_kore_tracer(PyObject *, PyObject *); -static PyObject *python_kore_domain(PyObject *, PyObject *); static PyObject *python_kore_fatalx(PyObject *, PyObject *); static PyObject *python_kore_setname(PyObject *, PyObject *); static PyObject *python_kore_suspend(PyObject *, PyObject *); static PyObject *python_kore_shutdown(PyObject *, PyObject *); static PyObject *python_kore_coroname(PyObject *, PyObject *); static PyObject *python_kore_corotrace(PyObject *, PyObject *); -static PyObject *python_kore_bind_unix(PyObject *, PyObject *); static PyObject *python_kore_task_kill(PyObject *, PyObject *); static PyObject *python_kore_prerequest(PyObject *, PyObject *); static PyObject *python_kore_task_create(PyObject *, PyObject *); static PyObject *python_kore_socket_wrap(PyObject *, PyObject *); +static PyObject *python_kore_domain(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_gather(PyObject *, PyObject *, PyObject *); +static PyObject *python_kore_listen(PyObject *, PyObject *, + PyObject *); + #if defined(KORE_USE_PGSQL) static PyObject *python_kore_pgsql_query(PyObject *, PyObject *, PyObject *); @@ -81,13 +82,10 @@ static struct PyMethodDef pykore_methods[] = { METHOD("time", python_kore_time, METH_NOARGS), METHOD("lock", python_kore_lock, METH_NOARGS), METHOD("proc", python_kore_proc, METH_VARARGS), - METHOD("bind", python_kore_bind, METH_VARARGS), METHOD("timer", python_kore_timer, METH_VARARGS), METHOD("queue", python_kore_queue, METH_VARARGS), METHOD("worker", python_kore_worker, METH_VARARGS), METHOD("tracer", python_kore_tracer, METH_VARARGS), - METHOD("domain", python_kore_domain, METH_VARARGS), - METHOD("gather", python_kore_gather, METH_VARARGS | METH_KEYWORDS), METHOD("fatal", python_kore_fatal, METH_VARARGS), METHOD("fatalx", python_kore_fatalx, METH_VARARGS), METHOD("setname", python_kore_setname, METH_VARARGS), @@ -96,10 +94,12 @@ static struct PyMethodDef pykore_methods[] = { METHOD("coroname", python_kore_coroname, METH_VARARGS), METHOD("corotrace", python_kore_corotrace, METH_VARARGS), METHOD("task_kill", python_kore_task_kill, METH_VARARGS), - METHOD("bind_unix", python_kore_bind_unix, METH_VARARGS), METHOD("prerequest", python_kore_prerequest, METH_VARARGS), METHOD("task_create", python_kore_task_create, METH_VARARGS), METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS), + METHOD("listen", python_kore_listen, METH_VARARGS | METH_KEYWORDS), + METHOD("gather", python_kore_gather, METH_VARARGS | METH_KEYWORDS), + METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS), METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS), #if defined(KORE_USE_PGSQL) METHOD("dbsetup", python_kore_pgsql_register, METH_VARARGS), @@ -589,16 +589,12 @@ static PyMethodDef pyconnection_methods[] = { static PyObject *pyconnection_get_fd(struct pyconnection *, void *); static PyObject *pyconnection_get_addr(struct pyconnection *, void *); -#if !defined(KORE_NO_TLS) static PyObject *pyconnection_get_peer_x509(struct pyconnection *, void *); -#endif static PyGetSetDef pyconnection_getset[] = { GETTER("fd", pyconnection_get_fd), GETTER("addr", pyconnection_get_addr), -#if !defined(KORE_NO_TLS) GETTER("x509", pyconnection_get_peer_x509), -#endif GETTER(NULL, NULL), }; diff --git a/src/accesslog.c b/src/accesslog.c @@ -47,10 +47,7 @@ static void accesslog_flush(struct kore_domain *, u_int64_t, int); static u_int64_t time_cache = 0; static char tbuf[128] = { '\0' }; - -#if !defined(KORE_NO_TLS) char cnbuf[1024] = { '\0' }; -#endif static struct kore_buf *logbuf = NULL; @@ -106,12 +103,10 @@ kore_accesslog(struct http_request *req) req->agent = "-"; cn = "-"; -#if !defined(KORE_NO_TLS) if (req->owner->cert != NULL) { if (X509_GET_CN(req->owner->cert, cnbuf, sizeof(cnbuf)) != -1) cn = cnbuf; } -#endif switch (req->owner->family) { case AF_INET: diff --git a/src/cli.c b/src/cli.c @@ -273,12 +273,17 @@ static const char *src_data = static const char *config_data = "# %s configuration\n" "\n" - "bind\t\t127.0.0.1 8888\n" + "listen tls {\n" + "\tbind 127.0.0.1 8888\n" + "}\n" + "\n" "load\t\t./%s.so\n" "\n" "tls_dhparam\tdh2048.pem\n" "\n" "domain * {\n" + "\tattach\t\ttls\n" + "\n" "\tcertfile\tcert/server.pem\n" "\tcertkey\t\tcert/key.pem\n" "\n" diff --git a/src/config.c b/src/config.c @@ -57,9 +57,12 @@ extern u_int32_t asset_len_builtin_kore_conf; static int configure_file(char *); #endif +static int configure_tls(char *); +static int configure_listen(char *); static int configure_include(char *); static int configure_bind(char *); static int configure_bind_unix(char *); +static int configure_attach(char *); static int configure_domain(char *); static int configure_root(char *); static int configure_runas(char *); @@ -76,7 +79,6 @@ static int configure_socket_backlog(char *); static int configure_add_pledge(char *); #endif -#if !defined(KORE_NO_TLS) static int configure_rand_file(char *); static int configure_certfile(char *); static int configure_certkey(char *); @@ -87,7 +89,6 @@ static int configure_keymgr_root(char *); static int configure_keymgr_runas(char *); static int configure_client_verify(char *); static int configure_client_verify_depth(char *); -#endif #if !defined(KORE_NO_HTTP) static int configure_filemap(char *); @@ -145,20 +146,21 @@ static struct { const char *name; int (*configure)(char *); } config_directives[] = { + { "tls", configure_tls }, + { "listen", configure_listen }, { "include", configure_include }, { "bind", configure_bind }, - { "bind_unix", configure_bind_unix }, + { "unix", configure_bind_unix }, { "load", configure_load }, { "domain", configure_domain }, -#if defined(KORE_USE_PYTHON) - { "python_path", configure_python_path }, - { "python_import", configure_python_import }, -#endif -#if !defined(KORE_NO_TLS) + { "attach", configure_attach }, { "certfile", configure_certfile }, { "certkey", configure_certkey }, { "client_verify", configure_client_verify }, { "client_verify_depth", configure_client_verify_depth }, +#if defined(KORE_USE_PYTHON) + { "python_path", configure_python_path }, + { "python_import", configure_python_import }, #endif #if !defined(KORE_NO_HTTP) { "filemap", configure_filemap }, @@ -193,16 +195,14 @@ static struct { { "worker_set_affinity", configure_set_affinity }, { "pidfile", configure_pidfile }, { "socket_backlog", configure_socket_backlog }, -#if defined(KORE_USE_PLATFORM_PLEDGE) - { "pledge", configure_add_pledge }, -#endif -#if !defined(KORE_NO_TLS) { "tls_version", configure_tls_version }, { "tls_cipher", configure_tls_cipher }, { "tls_dhparam", configure_tls_dhparam }, { "rand_file", configure_rand_file }, { "keymgr_runas", configure_keymgr_runas }, { "keymgr_root", configure_keymgr_root }, +#if defined(KORE_USE_PLATFORM_PLEDGE) + { "pledge", configure_add_pledge }, #endif #if !defined(KORE_NO_HTTP) { "filemap_ext", configure_filemap_ext }, @@ -256,6 +256,7 @@ static struct kore_module_handle *current_handler = NULL; extern const char *__progname; static struct kore_domain *current_domain = NULL; +static struct listener *current_listener = NULL; void kore_parse_config(void) @@ -314,7 +315,6 @@ kore_parse_config(void) if (!kore_quiet) kore_log(LOG_WARNING, "privsep: will not change user"); } else { -#if !defined(KORE_NO_TLS) if (keymgr_runas_user == NULL) { if (!kore_quiet) { kore_log(LOG_NOTICE, "privsep: no keymgr_runas " @@ -322,10 +322,8 @@ kore_parse_config(void) } keymgr_runas_user = kore_strdup(kore_runas_user); } -#endif } -#if !defined(KORE_NO_TLS) if (keymgr_root_path == NULL) { if (!kore_quiet) { kore_log(LOG_NOTICE, "privsep: no keymgr_root set, " @@ -333,7 +331,6 @@ kore_parse_config(void) } keymgr_root_path = kore_strdup(kore_root_path); } -#endif if (skip_chroot && !kore_quiet) kore_log(LOG_WARNING, "privsep: will not chroot"); @@ -354,6 +351,12 @@ kore_parse_config_file(FILE *fp) continue; } + if (!strcmp(p, "}") && current_listener != NULL) { + lineno++; + current_listener = NULL; + continue; + } + #if !defined(KORE_NO_HTTP) if (!strcmp(p, "}") && current_handler != NULL) { lineno++; @@ -376,13 +379,18 @@ kore_parse_config_file(FILE *fp) #endif if (!strcmp(p, "}") && current_domain != NULL) { -#if !defined(KORE_NO_TLS) - if (current_domain->certfile == NULL || - current_domain->certkey == NULL) { + if (current_domain->listener == NULL) { + fatal("domain '%s' not attached to listener", + current_domain->domain); + } + + if (current_domain->listener->tls == 1 && + (current_domain->certfile == NULL || + current_domain->certkey == NULL)) { fatal("incomplete TLS setup for '%s'", current_domain->domain); } -#endif + current_domain = NULL; } @@ -473,15 +481,78 @@ configure_include(char *path) } static int +configure_listen(char *options) +{ + struct listener *l; + char *argv[3]; + + if (current_listener != NULL) { + printf("nested listener contexts are not allowed\n"); + return (KORE_RESULT_ERROR); + } + + kore_split_string(options, " ", argv, 3); + + if (argv[0] == NULL || argv[1] == NULL) { + printf("invalid listener context\n"); + return (KORE_RESULT_ERROR); + } + + if (strcmp(argv[1], "{")) { + printf("listener context not opened correctly\n"); + return (KORE_RESULT_ERROR); + } + + if ((l = kore_listener_lookup(argv[0])) != NULL) { + printf("a listener with name '%s' already exists\n", l->name); + return (KORE_RESULT_ERROR); + } + + current_listener = kore_listener_create(argv[0]); + + return (KORE_RESULT_OK); +} + +static int +configure_tls(char *yesno) +{ + if (current_listener == NULL) { + printf("bind directive not inside a listener context\n"); + return (KORE_RESULT_ERROR); + } + + if (!strcmp(yesno, "no")) { + current_listener->tls = 0; + } else if (!strcmp(yesno, "yes")) { + current_listener->tls = 1; + } else { + printf("invalid '%s' for yes|no tls option\n", yesno); + return (KORE_RESULT_ERROR); + } + + return (KORE_RESULT_OK); +} + +static int configure_bind(char *options) { char *argv[4]; + if (current_listener == NULL) { + printf("bind directive not inside a listener context\n"); + return (KORE_RESULT_ERROR); + } + + if (current_listener->fd != -1) { + printf("listener '%s' already bound\n", current_listener->name); + return (KORE_RESULT_ERROR); + } + kore_split_string(options, " ", argv, 4); if (argv[0] == NULL || argv[1] == NULL) return (KORE_RESULT_ERROR); - return (kore_server_bind(argv[0], argv[1], argv[2])); + return (kore_server_bind(current_listener, argv[0], argv[1], argv[2])); } static int @@ -489,11 +560,21 @@ configure_bind_unix(char *options) { char *argv[3]; + if (current_listener == NULL) { + printf("bind_unix directive not inside a listener context\n"); + return (KORE_RESULT_ERROR); + } + + if (current_listener->fd != -1) { + printf("listener '%s' already bound\n", current_listener->name); + return (KORE_RESULT_ERROR); + } + kore_split_string(options, " ", argv, 3); if (argv[0] == NULL) return (KORE_RESULT_ERROR); - return (kore_server_bind_unix(argv[0], argv[1])); + return (kore_server_bind_unix(current_listener, argv[0], argv[1])); } static int @@ -560,7 +641,6 @@ configure_file(char *file) } #endif -#if !defined(KORE_NO_TLS) static int configure_tls_version(char *version) { @@ -733,8 +813,6 @@ configure_keymgr_root(char *root) return (KORE_RESULT_OK); } -#endif /* !KORE_NO_TLS */ - static int configure_domain(char *options) { @@ -747,6 +825,11 @@ configure_domain(char *options) kore_split_string(options, " ", argv, 3); + if (argv[0] == NULL || argv[1] == NULL) { + printf("invalid domain context\n"); + return (KORE_RESULT_ERROR); + } + if (strcmp(argv[1], "{")) { printf("domain context not opened correctly\n"); return (KORE_RESULT_ERROR); @@ -757,12 +840,38 @@ configure_domain(char *options) return (KORE_RESULT_ERROR); } - if (!kore_domain_new(argv[0])) { - printf("could not create new domain %s\n", argv[0]); + current_domain = kore_domain_new(argv[0]); + + return (KORE_RESULT_OK); +} + +static int +configure_attach(char *name) +{ + struct listener *l; + + if (current_domain == NULL) { + printf("attach not specified in domain context\n"); + return (KORE_RESULT_ERROR); + } + + if (current_domain->listener != NULL) { + printf("domain '%s' already attached to listener\n", + current_domain->domain); + return (KORE_RESULT_ERROR); + } + + if ((l = kore_listener_lookup(name)) == NULL) { + printf("listener '%s' does not exist\n", name); + return (KORE_RESULT_ERROR); + } + + if (!kore_domain_attach(l, current_domain)) { + printf("failed to attach '%s' to '%s'\n", + current_domain->domain, name); return (KORE_RESULT_ERROR); } - current_domain = kore_domain_lookup(argv[0]); return (KORE_RESULT_OK); } @@ -796,8 +905,8 @@ configure_handler(int type, char *options) return (KORE_RESULT_ERROR); } - if (!kore_module_handler_new(argv[0], - current_domain->domain, argv[1], argv[2], type)) { + if (!kore_module_handler_new(current_domain, + argv[0], argv[1], argv[2], type)) { printf("cannot create handler for %s\n", argv[0]); return (KORE_RESULT_ERROR); } diff --git a/src/connection.c b/src/connection.c @@ -61,11 +61,9 @@ kore_connection_new(void *owner) c = kore_pool_get(&connection_pool); -#if !defined(KORE_NO_TLS) c->ssl = NULL; c->cert = NULL; c->tls_reneg = 0; -#endif c->flags = 0; c->rnb = NULL; c->snb = NULL; @@ -146,27 +144,29 @@ kore_connection_accept(struct listener *listener, struct connection **out) c->handle = kore_connection_handle; TAILQ_INSERT_TAIL(&connections, c, list); -#if !defined(KORE_NO_TLS) - c->state = CONN_STATE_TLS_SHAKE; - c->write = net_write_tls; - c->read = net_read_tls; -#else - c->state = CONN_STATE_ESTABLISHED; - c->write = net_write; - c->read = net_read; - - if (listener->connect != NULL) { - kore_runtime_connect(listener->connect, c); + if (listener->tls) { + c->state = CONN_STATE_TLS_SHAKE; + c->write = net_write_tls; + c->read = net_read_tls; } else { + c->state = CONN_STATE_ESTABLISHED; + c->write = net_write; + c->read = net_read; + + if (listener->connect != NULL) { + kore_runtime_connect(listener->connect, c); + } else { #if !defined(KORE_NO_HTTP) - c->proto = CONN_PROTO_HTTP; - if (http_keepalive_time != 0) - c->idle_timer.length = http_keepalive_time * 1000; - net_recv_queue(c, http_header_max, - NETBUF_CALL_CB_ALWAYS, http_header_recv); + c->proto = CONN_PROTO_HTTP; + if (http_keepalive_time != 0) { + c->idle_timer.length = + http_keepalive_time * 1000; + } + net_recv_queue(c, http_header_max, + NETBUF_CALL_CB_ALWAYS, http_header_recv); #endif + } } -#endif kore_connection_start_idletimer(c); worker_active_connections++; @@ -246,17 +246,14 @@ kore_connection_event(void *arg, int error) int kore_connection_handle(struct connection *c) { -#if !defined(KORE_NO_TLS) int r; struct listener *listener; char cn[X509_CN_LENGTH]; -#endif kore_debug("kore_connection_handle(%p) -> %d", c, c->state); kore_connection_stop_idletimer(c); switch (c->state) { -#if !defined(KORE_NO_TLS) case CONN_STATE_TLS_SHAKE: if (primary_dom->ssl_ctx == NULL) { kore_log(LOG_NOTICE, @@ -275,6 +272,7 @@ 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); } ERR_clear_error(); @@ -331,7 +329,6 @@ kore_connection_handle(struct connection *c) c->state = CONN_STATE_ESTABLISHED; /* FALLTHROUGH */ -#endif /* !KORE_NO_TLS */ case CONN_STATE_ESTABLISHED: if (c->evt.flags & KORE_EVENT_READ) { if (!net_recv_flush(c)) @@ -365,7 +362,6 @@ kore_connection_remove(struct connection *c) kore_debug("kore_connection_remove(%p)", c); -#if !defined(KORE_NO_TLS) if (c->ssl != NULL) { SSL_shutdown(c->ssl); SSL_free(c->ssl); @@ -373,7 +369,6 @@ kore_connection_remove(struct connection *c) if (c->cert != NULL) X509_free(c->cert); -#endif close(c->fd); diff --git a/src/curl.c b/src/curl.c @@ -28,10 +28,14 @@ static struct sock_filter filter_curl[] = { /* Allow sockets and libcurl to call connect. */ KORE_SYSCALL_ALLOW(bind), + KORE_SYSCALL_ALLOW(ioctl), KORE_SYSCALL_ALLOW(connect), + KORE_SYSCALL_ALLOW(getsockopt), + KORE_SYSCALL_ALLOW(getsockname), KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET), KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6), KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX), + KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_NETLINK), /* Threading related. */ KORE_SYSCALL_ALLOW(clone), diff --git a/src/domain.c b/src/domain.c @@ -23,14 +23,12 @@ #include <sys/param.h> #include <sys/types.h> -#if !defined(KORE_NO_TLS) #include <openssl/x509.h> #include <openssl/bio.h> #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/ecdsa.h> #include <poll.h> -#endif #include <fnmatch.h> @@ -43,18 +41,14 @@ #define KORE_DOMAIN_CACHE 16 #define SSL_SESSION_ID "kore_ssl_sessionid" -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_BOTH; -#endif -#if !defined(KORE_NO_TLS) static int domain_x509_verify(int, X509_STORE_CTX *); static X509 *domain_load_certificate_chain(SSL_CTX *, const void *, size_t); @@ -90,7 +84,6 @@ struct ecdsa_method { int flags; char *app_data; }; -#endif static ECDSA_METHOD keymgr_ecdsa = { "kore ECDSA keymgr method", @@ -117,9 +110,8 @@ static RSA_METHOD keymgr_rsa = { NULL, NULL }; - +#endif #endif /* OPENSSL_VERSION_NUMBER */ -#endif /* KORE_NO_TLS */ static u_int16_t domain_id = 0; static struct kore_domain *cached[KORE_DOMAIN_CACHE]; @@ -129,12 +121,9 @@ kore_domain_init(void) { int i; - TAILQ_INIT(&domains); - for (i = 0; i < KORE_DOMAIN_CACHE; i++) cached[i] = NULL; -#if !defined(KORE_NO_TLS) #if !defined(LIBRESSL_VERSION_TEXT) && OPENSSL_VERSION_NUMBER >= 0x10100000L if (keymgr_rsa_meth == NULL) { if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method", @@ -161,21 +150,11 @@ kore_domain_init(void) OPENSSL_VERSION_TEXT); } #endif - -#endif } void kore_domain_cleanup(void) { - struct kore_domain *dom; - - while ((dom = TAILQ_FIRST(&domains)) != NULL) { - TAILQ_REMOVE(&domains, dom, list); - kore_domain_free(dom); - } - -#if !defined(KORE_NO_TLS) #if !defined(LIBRESSL_VERSION_TEXT) && OPENSSL_VERSION_NUMBER >= 0x10100000L if (keymgr_rsa_meth != NULL) { RSA_meth_free(keymgr_rsa_meth); @@ -187,33 +166,20 @@ kore_domain_cleanup(void) keymgr_ec_meth = NULL; } #endif -#endif } -int +struct kore_domain * kore_domain_new(const char *domain) { struct kore_domain *dom; - if (kore_domain_lookup(domain) != NULL) - return (KORE_RESULT_ERROR); - kore_debug("kore_domain_new(%s)", domain); - dom = kore_malloc(sizeof(*dom)); + dom = kore_calloc(1, sizeof(*dom)); dom->id = domain_id++; - dom->logbuf = NULL; dom->accesslog = -1; - dom->logwarn = 0; - dom->logerr = 0; -#if !defined(KORE_NO_TLS) - dom->cafile = NULL; - dom->certkey = NULL; - dom->ssl_ctx = NULL; - dom->certfile = NULL; - dom->crlfile = NULL; + dom->x509_verify_depth = 1; -#endif dom->domain = kore_strdup(domain); #if !defined(KORE_NO_HTTP) @@ -226,11 +192,28 @@ kore_domain_new(const char *domain) cached[dom->id] = dom; } - TAILQ_INSERT_TAIL(&domains, dom, list); - if (primary_dom == NULL) primary_dom = dom; + return (dom); +} + +int +kore_domain_attach(struct listener *l, struct kore_domain *dom) +{ + struct kore_domain *d; + + if (dom->listener != NULL) + return (KORE_RESULT_ERROR); + + TAILQ_FOREACH(d, &l->domains, list) { + if (!strcmp(d->domain, dom->domain)) + return (KORE_RESULT_ERROR); + } + + dom->listener = l; + TAILQ_INSERT_TAIL(&l->domains, dom, list); + return (KORE_RESULT_OK); } @@ -246,12 +229,11 @@ kore_domain_free(struct kore_domain *dom) if (primary_dom == dom) primary_dom = NULL; - TAILQ_REMOVE(&domains, dom, list); + TAILQ_REMOVE(&dom->listener->domains, dom, list); if (dom->domain != NULL) kore_free(dom->domain); -#if !defined(KORE_NO_TLS) if (dom->ssl_ctx != NULL) SSL_CTX_free(dom->ssl_ctx); if (dom->cafile != NULL) @@ -262,7 +244,6 @@ kore_domain_free(struct kore_domain *dom) kore_free(dom->certfile); if (dom->crlfile != NULL) kore_free(dom->crlfile); -#endif #if !defined(KORE_NO_HTTP) /* Drop all handlers associated with this domain */ @@ -274,7 +255,6 @@ kore_domain_free(struct kore_domain *dom) kore_free(dom); } -#if !defined(KORE_NO_TLS) void kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen) { @@ -488,24 +468,26 @@ kore_domain_crl_add(struct kore_domain *dom, const void *pem, size_t pemlen) X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } -#endif void kore_domain_callback(void (*cb)(struct kore_domain *)) { + struct listener *l; struct kore_domain *dom; - TAILQ_FOREACH(dom, &domains, list) { - cb(dom); + LIST_FOREACH(l, &listeners, list) { + TAILQ_FOREACH(dom, &l->domains, list) { + cb(dom); + } } } struct kore_domain * -kore_domain_lookup(const char *domain) +kore_domain_lookup(struct listener *l, const char *domain) { struct kore_domain *dom; - TAILQ_FOREACH(dom, &domains, list) { + TAILQ_FOREACH(dom, &l->domains, list) { if (!strcmp(dom->domain, domain)) return (dom); if (!fnmatch(dom->domain, domain, FNM_CASEFOLD)) @@ -518,14 +500,17 @@ kore_domain_lookup(const char *domain) struct kore_domain * kore_domain_byid(u_int16_t id) { + struct listener *l; struct kore_domain *dom; if (id < KORE_DOMAIN_CACHE) return (cached[id]); - TAILQ_FOREACH(dom, &domains, list) { - if (dom->id == id) - return (dom); + LIST_FOREACH(l, &listeners, list) { + TAILQ_FOREACH(dom, &l->domains, list) { + if (dom->id == id) + return (dom); + } } return (NULL); @@ -538,15 +523,21 @@ kore_domain_byid(u_int16_t id) void kore_domain_closelogs(void) { + struct listener *l; struct kore_domain *dom; - TAILQ_FOREACH(dom, &domains, list) { - if (dom->accesslog != -1) { - (void)close(dom->accesslog); - /* turn into flag to indicate accesslogs are active. */ - dom->accesslog = 1; - } else { - dom->accesslog = 0; + LIST_FOREACH(l, &listeners, list) { + TAILQ_FOREACH(dom, &l->domains, list) { + if (dom->accesslog != -1) { + (void)close(dom->accesslog); + /* + * Turn into flag to indicate accesslogs + * are active. + */ + dom->accesslog = 1; + } else { + dom->accesslog = 0; + } } } } @@ -554,13 +545,10 @@ kore_domain_closelogs(void) void kore_domain_keymgr_init(void) { -#if !defined(KORE_NO_TLS) keymgr_init(); kore_msg_register(KORE_MSG_KEYMGR_RESP, keymgr_msg_response); -#endif } -#if !defined(KORE_NO_TLS) static void keymgr_init(void) { @@ -872,4 +860,3 @@ domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len) return (x); } -#endif diff --git a/src/filemap.c b/src/filemap.c @@ -86,8 +86,8 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root) if (len == -1 || (size_t)len >= sizeof(regex)) fatal("kore_filemap_create: buffer too small"); - if (!kore_module_handler_new(regex, dom->domain, - "filemap_resolve", NULL, HANDLER_TYPE_DYNAMIC)) + if (!kore_module_handler_new(dom, regex, "filemap_resolve", + NULL, HANDLER_TYPE_DYNAMIC)) return (KORE_RESULT_ERROR); hdlr = NULL; @@ -177,6 +177,7 @@ static void filemap_serve(struct http_request *req, struct filemap_entry *map) { struct stat st; + struct connection *c; struct kore_fileref *ref; const char *path; int len, fd, index; @@ -224,7 +225,9 @@ lookup: return; } - if ((ref = kore_fileref_get(rpath)) == NULL) { + c = req->owner; + + if ((ref = kore_fileref_get(rpath, c->owner->tls)) == NULL) { if ((fd = open(fpath, O_RDONLY | O_NOFOLLOW)) == -1) { switch (errno) { case ENOENT: @@ -271,7 +274,7 @@ lookup: } /* kore_fileref_create() takes ownership of the fd. */ - ref = kore_fileref_create(fpath, fd, + ref = kore_fileref_create(c, fpath, fd, st.st_size, &st.st_mtim); if (ref == NULL) { http_response(req, diff --git a/src/fileref.c b/src/fileref.c @@ -23,6 +23,8 @@ #include "kore.h" +#define FILEREF_DEBUG 1 + /* cached filerefs expire after 30 seconds of inactivity. */ #define FILEREF_EXPIRATION (1000 * 30) @@ -43,13 +45,14 @@ kore_fileref_init(void) } struct kore_fileref * -kore_fileref_create(const char *path, int fd, off_t size, struct timespec *ts) +kore_fileref_create(struct connection *c, const char *path, int fd, + off_t size, struct timespec *ts) { struct kore_fileref *ref; fileref_timer_prime(); - if ((ref = kore_fileref_get(path)) != NULL) + if ((ref = kore_fileref_get(path, c->owner->tls)) != NULL) return (ref); ref = kore_pool_get(&ref_pool); @@ -57,6 +60,7 @@ kore_fileref_create(const char *path, int fd, off_t size, struct timespec *ts) ref->cnt = 1; ref->flags = 0; ref->size = size; + ref->ontls = c->owner->tls; ref->path = kore_strdup(path); ref->mtime_sec = ts->tv_sec; ref->mtime = ((u_int64_t)(ts->tv_sec * 1000 + (ts->tv_nsec / 1000000))); @@ -74,7 +78,22 @@ kore_fileref_create(const char *path, int fd, off_t size, struct timespec *ts) fatal("net_send_file: madvise: %s", errno_s); close(fd); #else - ref->fd = fd; + if (c->owner->tls == 0) { + ref->fd = fd; + } else { + if ((uintmax_t)size> SIZE_MAX) { + kore_pool_put(&ref_pool, ref); + return (NULL); + } + + ref->base = mmap(NULL, + (size_t)size, PROT_READ, MAP_PRIVATE, fd, 0); + if (ref->base == MAP_FAILED) + fatal("net_send_file: mmap failed: %s", errno_s); + if (madvise(ref->base, (size_t)size, MADV_SEQUENTIAL) == -1) + fatal("net_send_file: madvise: %s", errno_s); + close(fd); + } #endif #if defined(FILEREF_DEBUG) @@ -91,14 +110,14 @@ kore_fileref_create(const char *path, int fd, off_t size, struct timespec *ts) * if they don't end up using the ref. */ struct kore_fileref * -kore_fileref_get(const char *path) +kore_fileref_get(const char *path, int ontls) { struct stat st; struct kore_fileref *ref; u_int64_t mtime; TAILQ_FOREACH(ref, &refs, list) { - if (!strcmp(ref->path, path)) { + if (!strcmp(ref->path, path) && ref->ontls == ontls) { if (stat(ref->path, &st) == -1) { if (errno != ENOENT) { kore_log(LOG_ERR, "stat(%s): %s", diff --git a/src/http.c b/src/http.c @@ -1551,6 +1551,7 @@ http_request_new(struct connection *c, const char *host, } req = kore_pool_get(&http_request_pool); + req->owner = c; if ((hdlr = kore_module_handler_find(req, host, path)) == NULL) { kore_pool_put(&http_request_pool, req); diff --git a/src/keymgr.c b/src/keymgr.c @@ -46,8 +46,6 @@ #include "kore.h" -#if !defined(KORE_NO_TLS) - #define RAND_TMP_FILE "rnd.tmp" #define RAND_POLL_INTERVAL (1800 * 1000) #define RAND_FILE_SIZE 1024 @@ -135,7 +133,7 @@ kore_keymgr_run(void) quit = 0; - kore_listener_cleanup(); + kore_listener_closeall(); kore_module_cleanup(); net_init(); @@ -232,6 +230,7 @@ kore_keymgr_cleanup(int final) static void keymgr_reload(void) { + struct listener *l; struct kore_domain *dom; if (!kore_quiet) @@ -243,8 +242,12 @@ keymgr_reload(void) kore_domain_callback(keymgr_load_privatekey); /* can't use kore_domain_callback() due to dst parameter. */ - TAILQ_FOREACH(dom, &domains, list) - keymgr_submit_certificates(dom, KORE_MSG_WORKER_ALL); + LIST_FOREACH(l, &listeners, list) { + if (l->tls == 0) + continue; + TAILQ_FOREACH(dom, &l->domains, list) + keymgr_submit_certificates(dom, KORE_MSG_WORKER_ALL); + } } static void @@ -414,6 +417,9 @@ keymgr_load_privatekey(struct kore_domain *dom) FILE *fp; struct key *key; + if (dom->listener->tls == 0) + return; + if ((fp = fopen(dom->certkey, "r")) == NULL) fatal("failed to open private key: %s", dom->certkey); @@ -431,10 +437,15 @@ keymgr_load_privatekey(struct kore_domain *dom) static void keymgr_certificate_request(struct kore_msg *msg, const void *data) { + struct listener *l; struct kore_domain *dom; - TAILQ_FOREACH(dom, &domains, list) - keymgr_submit_certificates(dom, msg->src); + LIST_FOREACH(l, &listeners, list) { + if (l->tls == 0) + continue; + TAILQ_FOREACH(dom, &l->domains, list) + keymgr_submit_certificates(dom, msg->src); + } } static void @@ -546,5 +557,3 @@ keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key) kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, sig, siglen); } - -#endif diff --git a/src/kore.c b/src/kore.c @@ -125,9 +125,6 @@ static void version(void) { printf("%s ", kore_version); -#if defined(KORE_NO_TLS) - printf("no-tls "); -#endif #if defined(KORE_NO_HTTP) printf("no-http "); #endif @@ -339,17 +336,21 @@ main(int argc, char *argv[]) return (0); } -#if !defined(KORE_NO_TLS) int kore_tls_sni_cb(SSL *ssl, int *ad, void *arg) { + struct connection *c; struct kore_domain *dom; const char *sname; + if ((c = SSL_get_ex_data(ssl, 0)) == NULL) + fatal("no connection data in %s", __func__); + sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); kore_debug("kore_tls_sni_cb(): received host %s", sname); - if (sname != NULL && (dom = kore_domain_lookup(sname)) != NULL) { + if (sname != NULL && + (dom = kore_domain_lookup(c->owner, sname)) != NULL) { if (dom->ssl_ctx == NULL) { kore_log(LOG_NOTICE, "TLS configuration for %s not complete", @@ -388,16 +389,16 @@ kore_tls_info_callback(const SSL *ssl, int flags, int ret) c->tls_reneg++; } } -#endif int -kore_server_bind(const char *ip, const char *port, const char *ccb) +kore_server_bind(struct listener *l, const char *ip, const char *port, + const char *ccb) { int r; - struct listener *l; + const char *proto; struct addrinfo hints, *results; - kore_debug("kore_server_bind(%s, %s)", ip, port); + kore_debug("kore_server_bind(%s, %s, %s)", l->name, ip, port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -409,8 +410,9 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) if (r != 0) fatal("getaddrinfo(%s): %s", ip, gai_strerror(r)); - if ((l = kore_listener_alloc(results->ai_family, ccb)) == NULL) { + if (kore_listener_init(l, results->ai_family, ccb) == -1) { freeaddrinfo(results); + kore_listener_free(l); return (KORE_RESULT_ERROR); } @@ -430,20 +432,20 @@ kore_server_bind(const char *ip, const char *port, const char *ccb) } if (foreground && !kore_quiet) { -#if !defined(KORE_NO_TLS) - kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port); -#else - kore_log(LOG_NOTICE, "running on http://%s:%s", ip, port); -#endif + if (l->tls) + proto = "https"; + else + proto = "http"; + + kore_log(LOG_NOTICE, "running on %s://%s:%s", proto, ip, port); } return (KORE_RESULT_OK); } int -kore_server_bind_unix(const char *path, const char *ccb) +kore_server_bind_unix(struct listener *l, const char *path, const char *ccb) { - struct listener *l; int len; struct sockaddr_un sun; socklen_t socklen; @@ -465,8 +467,10 @@ kore_server_bind_unix(const char *path, const char *ccb) socklen = sizeof(sun); #endif - if ((l = kore_listener_alloc(AF_UNIX, ccb)) == NULL) + if (kore_listener_init(l, AF_UNIX, ccb) == -1) { + kore_listener_free(l); return (KORE_RESULT_ERROR); + } if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) { kore_log(LOG_ERR, "bind: %s", errno_s); @@ -487,10 +491,43 @@ kore_server_bind_unix(const char *path, const char *ccb) } struct listener * -kore_listener_alloc(int family, const char *ccb) +kore_listener_create(const char *name) +{ + struct listener *l; + + l = kore_calloc(1, sizeof(struct listener)); + + nlisteners++; + LIST_INSERT_HEAD(&listeners, l, list); + + l->fd = -1; + l->tls = 1; + l->name = kore_strdup(name); + + l->evt.type = KORE_TYPE_LISTENER; + l->evt.handle = kore_listener_accept; + + TAILQ_INIT(&l->domains); + + return (l); +} + +struct listener * +kore_listener_lookup(const char *name) { struct listener *l; + LIST_FOREACH(l, &listeners, list) { + if (!strcmp(l->name, name)) + return (l); + } + + return (NULL); +} + +int +kore_listener_init(struct listener *l, int family, const char *ccb) +{ switch (family) { case AF_INET: case AF_INET6: @@ -500,57 +537,54 @@ kore_listener_alloc(int family, const char *ccb) fatal("unknown address family %d", family); } - l = kore_calloc(1, sizeof(struct listener)); - - nlisteners++; - LIST_INSERT_HEAD(&listeners, l, list); - - l->fd = -1; l->family = family; - l->evt.type = KORE_TYPE_LISTENER; - l->evt.handle = kore_listener_accept; - if ((l->fd = socket(family, SOCK_STREAM, 0)) == -1) { kore_listener_free(l); kore_log(LOG_ERR, "socket(): %s", errno_s); - return (NULL); + return (KORE_RESULT_ERROR); } if (fcntl(l->fd, F_SETFD, FD_CLOEXEC) == -1) { kore_listener_free(l); kore_log(LOG_ERR, "fcntl(): %s", errno_s); - return (NULL); + return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(l->fd, family != AF_UNIX)) { kore_listener_free(l); kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s); - return (NULL); + return (KORE_RESULT_ERROR); } if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) { kore_listener_free(l); - return (NULL); + return (KORE_RESULT_ERROR); } if (ccb != NULL) { if ((l->connect = kore_runtime_getcall(ccb)) == NULL) { kore_log(LOG_ERR, "no such callback: '%s'", ccb); kore_listener_free(l); - return (NULL); + return (KORE_RESULT_ERROR); } } else { l->connect = NULL; } - return (l); + return (KORE_RESULT_OK); } void kore_listener_free(struct listener *l) { + struct kore_domain *dom; + + while ((dom = TAILQ_FIRST(&l->domains)) != NULL) + kore_domain_free(dom); + LIST_REMOVE(l, list); + kore_free(l->name); if (l->fd != -1) close(l->fd); @@ -639,6 +673,15 @@ kore_signal_setup(void) } void +kore_listener_closeall(void) +{ + struct listener *l; + + LIST_FOREACH(l, &listeners, list) + l->fd = -1; +} + +void kore_listener_cleanup(void) { struct listener *l; @@ -703,12 +746,8 @@ kore_proctitle_setup(void) static void kore_server_sslstart(void) { -#if !defined(KORE_NO_TLS) - kore_debug("kore_server_sslstart()"); - SSL_library_init(); SSL_load_error_strings(); -#endif } static void diff --git a/src/linux.c b/src/linux.c @@ -225,6 +225,8 @@ kore_platform_sendfile(struct connection *c, struct netbuf *nb) ssize_t sent; size_t len, prevoff; + printf("sendfile is used\n"); + prevoff = nb->fd_off; smin = nb->fd_len - nb->fd_off; len = MIN(SENDFILE_PAYLOAD_MAX, smin); diff --git a/src/module.c b/src/module.c @@ -136,6 +136,7 @@ kore_module_reload(int cbs) struct stat st; int ret; #if !defined(KORE_NO_HTTP) + struct listener *l; struct kore_domain *dom; struct kore_module_handle *hdlr; #endif @@ -182,13 +183,17 @@ kore_module_reload(int cbs) } #if !defined(KORE_NO_HTTP) - TAILQ_FOREACH(dom, &domains, list) { - TAILQ_FOREACH(hdlr, &(dom->handlers), list) { - kore_free(hdlr->rcall); - hdlr->rcall = kore_runtime_getcall(hdlr->func); - if (hdlr->rcall == NULL) - fatal("no function '%s' found", hdlr->func); - hdlr->errors = 0; + LIST_FOREACH(l, &listeners, list) { + TAILQ_FOREACH(dom, &l->domains, list) { + TAILQ_FOREACH(hdlr, &(dom->handlers), list) { + kore_free(hdlr->rcall); + hdlr->rcall = kore_runtime_getcall(hdlr->func); + if (hdlr->rcall == NULL) { + fatal("no function '%s' found", + hdlr->func); + } + hdlr->errors = 0; + } } } #endif @@ -209,19 +214,12 @@ kore_module_loaded(void) #if !defined(KORE_NO_HTTP) int -kore_module_handler_new(const char *path, const char *domain, +kore_module_handler_new(struct kore_domain *dom, const char *path, const char *func, const char *auth, int type) { struct kore_auth *ap; - struct kore_domain *dom; struct kore_module_handle *hdlr; - kore_debug("kore_module_handler_new(%s, %s, %s, %s, %d)", path, - domain, func, auth, type); - - if ((dom = kore_domain_lookup(domain)) == NULL) - return (KORE_RESULT_ERROR); - if (auth != NULL) { if ((ap = kore_auth_lookup(auth)) == NULL) fatal("no authentication block '%s' found", auth); @@ -289,10 +287,13 @@ struct kore_module_handle * kore_module_handler_find(struct http_request *req, const char *domain, const char *path) { + struct connection *c; struct kore_domain *dom; struct kore_module_handle *hdlr; - if ((dom = kore_domain_lookup(domain)) == NULL) + c = req->owner; + + if ((dom = kore_domain_lookup(c->owner, domain)) == NULL) return (NULL); TAILQ_FOREACH(hdlr, &(dom->handlers), list) { diff --git a/src/net.c b/src/net.c @@ -156,8 +156,15 @@ net_send_fileref(struct connection *c, struct kore_fileref *ref) nb->flags = NETBUF_IS_FILEREF; #if defined(KORE_USE_PLATFORM_SENDFILE) - nb->fd_off = 0; - nb->fd_len = ref->size; + if (c->owner->tls == 0) { + nb->fd_off = 0; + nb->fd_len = ref->size; + } else { + nb->buf = ref->base; + nb->b_len = ref->size; + nb->m_len = nb->b_len; + nb->flags |= NETBUF_IS_STREAM; + } #else nb->buf = ref->base; nb->b_len = ref->size; @@ -329,7 +336,6 @@ net_remove_netbuf(struct connection *c, struct netbuf *nb) kore_pool_put(&nb_pool, nb); } -#if !defined(KORE_NO_TLS) int net_write_tls(struct connection *c, size_t len, size_t *written) { @@ -417,7 +423,6 @@ net_read_tls(struct connection *c, size_t *bytes) return (KORE_RESULT_OK); } -#endif int net_write(struct connection *c, size_t len, size_t *written) diff --git a/src/python.c b/src/python.c @@ -57,6 +57,10 @@ static PyObject *pyconnection_alloc(struct connection *); static PyObject *python_callable(PyObject *, const char *); static void python_split_arguments(char *, char **, size_t); +static const char *python_string_from_dict(PyObject *, const char *); +static int python_bool_from_dict(PyObject *, const char *, int *); +static int python_long_from_dict(PyObject *, const char *, long *); + static int pyhttp_response_sent(struct netbuf *); static PyObject *pyhttp_file_alloc(struct http_file *); static PyObject *pyhttp_request_alloc(const struct http_request *); @@ -467,6 +471,57 @@ kore_python_proc_reap(void) } } +static int +python_long_from_dict(PyObject *dict, const char *key, long *result) +{ + PyObject *obj; + + if ((obj = PyDict_GetItemString(dict, key)) == NULL) + return (KORE_RESULT_ERROR); + + if (!PyLong_CheckExact(obj)) + return (KORE_RESULT_ERROR); + + PyErr_Clear(); + *result = PyLong_AsLong(obj); + if (*result == -1 && PyErr_Occurred()) { + PyErr_Clear(); + return (KORE_RESULT_ERROR); + } + + return (KORE_RESULT_OK); +} + +static int +python_bool_from_dict(PyObject *dict, const char *key, int *result) +{ + PyObject *obj; + + if ((obj = PyDict_GetItemString(dict, key)) == NULL) + return (KORE_RESULT_ERROR); + + if (!PyBool_Check(obj)) + return (KORE_RESULT_ERROR); + + *result = (obj == Py_True); + + return (KORE_RESULT_OK); +} + +static const char * +python_string_from_dict(PyObject *dict, const char *key) +{ + PyObject *obj; + + if ((obj = PyDict_GetItemString(dict, key)) == NULL) + return (NULL); + + if (!PyUnicode_Check(obj)) + return (NULL); + + return (PyUnicode_AsUTF8AndSize(obj, NULL)); +} + static void * python_malloc(void *ctx, size_t len) { @@ -1294,35 +1349,59 @@ python_kore_time(PyObject *self, PyObject *args) } static PyObject * -python_kore_bind(PyObject *self, PyObject *args) +python_kore_listen(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *ip, *port; + struct listener *l; + const char *name, *ip, *port, *path; - if (!PyArg_ParseTuple(args, "ss", &ip, &port)) + if (!PyArg_ParseTuple(args, "s", &name)) return (NULL); - if (!kore_server_bind(ip, port, NULL)) { - PyErr_SetString(PyExc_RuntimeError, "failed to listen"); + if (kwargs == NULL) { + PyErr_SetString(PyExc_RuntimeError, "missing keyword args"); return (NULL); } - Py_RETURN_TRUE; -} - -static PyObject * -python_kore_bind_unix(PyObject *self, PyObject *args) -{ - const char *path; + ip = python_string_from_dict(kwargs, "ip"); + path = python_string_from_dict(kwargs, "path"); - if (!PyArg_ParseTuple(args, "s", &path)) + if (ip == NULL && path == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "missing ip or path keywords"); return (NULL); + } - if (!kore_server_bind_unix(path, NULL)) { - PyErr_SetString(PyExc_RuntimeError, "failed bind to path"); + if (ip != NULL && path != NULL) { + PyErr_SetString(PyExc_RuntimeError, "ip/path are exclusive"); return (NULL); } - Py_RETURN_TRUE; + l = kore_listener_create(name); + + if (ip != NULL) { + if ((port = python_string_from_dict(kwargs, "port")) == NULL) { + kore_listener_free(l); + PyErr_SetString(PyExc_RuntimeError, + "missing or invalid 'port' keyword"); + return (NULL); + } + + if (!kore_server_bind(l, ip, port, NULL)) { + PyErr_Format(PyExc_RuntimeError, + "failed to bind to '%s:%s'", ip, port); + return (NULL); + } + } else { + if (!kore_server_bind_unix(l, path, NULL)) { + PyErr_Format(PyExc_RuntimeError, + "failed to bind to '%s'", path); + return (NULL); + } + } + + python_bool_from_dict(kwargs, "tls", &l->tls); + + Py_RETURN_NONE; } static PyObject * @@ -1498,30 +1577,64 @@ python_kore_tracer(PyObject *self, PyObject *args) } static PyObject * -python_kore_domain(PyObject *self, PyObject *args) +python_kore_domain(PyObject *self, PyObject *args, PyObject *kwargs) { + struct listener *l; + long depth; const char *name; struct pydomain *domain; -#if !defined(KORE_NO_TLS) - int depth; - const char *x509, *key, *ca; + const char *cert, *key, *ca, *attach; ca = NULL; depth = -1; + key = NULL; + cert = NULL; + attach = NULL; - if (!PyArg_ParseTuple(args, "sss|si", &name, &x509, &key, &ca, &depth)) + if (!PyArg_ParseTuple(args, "s", &name)) return (NULL); - if (ca != NULL && depth < 0) { - PyErr_Format(PyExc_RuntimeError, "invalid depth '%d'", depth); + if (kwargs == NULL) { + PyErr_SetString(PyExc_RuntimeError, "missing keyword args"); return (NULL); } -#else - if (!PyArg_ParseTuple(args, "s", &name)) + + if ((attach = python_string_from_dict(kwargs, "attach")) == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "missing or invalid 'attach' keyword"); return (NULL); -#endif + } + + if ((l = kore_listener_lookup(attach)) == NULL) { + PyErr_Format(PyExc_RuntimeError, + "listener '%s' does not exist", attach); + return (NULL); + } + + if (l->tls) { + key = python_string_from_dict(kwargs, "key"); + cert = python_string_from_dict(kwargs, "cert"); + + if (key == NULL || cert == NULL) { + PyErr_Format(PyExc_RuntimeError, + "missing key or cert keywords for TLS listener"); + return (NULL); + } + + ca = python_string_from_dict(kwargs, "client_authority"); + if (ca != NULL) { + python_long_from_dict(kwargs, "verify_depth", &depth); + if (depth < 0) { + PyErr_Format(PyExc_RuntimeError, + "invalid depth '%d'", depth); + return (NULL); + } + } + } else if (key != NULL || cert != NULL || ca != NULL) { + kore_log(LOG_INFO, "ignoring tls settings for '%s'", name); + } - if (kore_domain_lookup(name) != NULL) { + if (kore_domain_lookup(l, name) != NULL) { PyErr_SetString(PyExc_RuntimeError, "domain exists"); return (NULL); } @@ -1529,21 +1642,21 @@ python_kore_domain(PyObject *self, PyObject *args) if ((domain = PyObject_New(struct pydomain, &pydomain_type)) == NULL) return (NULL); - if (!kore_domain_new(name)) + if ((domain->config = kore_domain_new(name)) == NULL) fatal("failed to create new domain configuration"); - if ((domain->config = kore_domain_lookup(name)) == NULL) - fatal("failed to find new domain configuration"); + if (!kore_domain_attach(l, domain->config)) + fatal("failed to attach domain configuration"); -#if !defined(KORE_NO_TLS) - domain->config->certkey = kore_strdup(key); - domain->config->certfile = kore_strdup(x509); + if (l->tls) { + domain->config->certkey = kore_strdup(key); + domain->config->certfile = kore_strdup(cert); - if (ca != NULL) { - domain->config->cafile = kore_strdup(ca); - domain->config->x509_verify_depth = depth; + if (ca != NULL) { + domain->config->cafile = kore_strdup(ca); + domain->config->x509_verify_depth = depth; + } } -#endif return ((PyObject *)domain); } @@ -2013,7 +2126,6 @@ pyconnection_get_addr(struct pyconnection *pyc, void *closure) return (result); } -#if !defined(KORE_NO_TLS) static PyObject * pyconnection_get_peer_x509(struct pyconnection *pyc, void *closure) { @@ -2044,7 +2156,6 @@ pyconnection_get_peer_x509(struct pyconnection *pyc, void *closure) return (bytes); } -#endif static void pytimer_run(void *arg, u_int64_t now) @@ -4448,15 +4559,12 @@ pydomain_auth(PyObject *dict, struct kore_module_handle *hdlr) if (!PyDict_CheckExact(dict)) return (KORE_RESULT_ERROR); - if ((obj = PyDict_GetItemString(dict, "type")) == NULL || - !PyUnicode_CheckExact(obj)) { - PyErr_Format(PyExc_RuntimeError, - "missing 'type' in auth dictionary for '%s'", hdlr->path); + if ((value = python_string_from_dict(dict, "type")) == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "missing or invalid 'type' keyword"); return (KORE_RESULT_ERROR); } - value = PyUnicode_AsUTF8(obj); - if (!strcmp(value, "cookie")) { type = KORE_AUTH_TYPE_COOKIE; } else if (!strcmp(value, "header")) { @@ -4468,27 +4576,13 @@ pydomain_auth(PyObject *dict, struct kore_module_handle *hdlr) return (KORE_RESULT_ERROR); } - if ((obj = PyDict_GetItemString(dict, "value")) == NULL || - !PyUnicode_CheckExact(obj)) { - PyErr_Format(PyExc_RuntimeError, - "missing 'value' in auth dictionary for '%s'", hdlr->path); + if ((value = python_string_from_dict(dict, "value")) == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "missing or invalid 'value' keyword"); return (KORE_RESULT_ERROR); } - value = PyUnicode_AsUTF8(obj); - - if ((obj = PyDict_GetItemString(dict, "redirect")) != NULL) { - if (!PyUnicode_CheckExact(obj)) { - PyErr_Format(PyExc_RuntimeError, - "redirect for auth on '%s' is not a string", - hdlr->path); - return (KORE_RESULT_ERROR); - } - - redir = PyUnicode_AsUTF8(obj); - } else { - redir = NULL; - } + redir = python_string_from_dict(dict, "redirect"); if ((obj = PyDict_GetItemString(dict, "verify")) == NULL || !PyCallable_Check(obj)) { @@ -4836,7 +4930,6 @@ pykore_pgsql_result(struct pykore_pgsql *pysql) static PyObject * python_kore_httpclient(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *obj; struct pyhttp_client *client; const char *url, *v; @@ -4856,54 +4949,19 @@ python_kore_httpclient(PyObject *self, PyObject *args, PyObject *kwargs) client->url = kore_strdup(url); if (kwargs != NULL) { - if ((obj = PyDict_GetItemString(kwargs, "tlscert")) != NULL) { - if ((v = PyUnicode_AsUTF8(obj)) == NULL) { - Py_DECREF((PyObject *)client); - return (NULL); - } - + if ((v = python_string_from_dict(kwargs, "tlscert")) != NULL) client->tlscert = kore_strdup(v); - } - - if ((obj = PyDict_GetItemString(kwargs, "tlskey")) != NULL) { - if ((v = PyUnicode_AsUTF8(obj)) == NULL) { - Py_DECREF((PyObject *)client); - return (NULL); - } + if ((v = python_string_from_dict(kwargs, "tlskey")) != NULL) client->tlskey = kore_strdup(v); - } - - if ((obj = PyDict_GetItemString(kwargs, "cabundle")) != NULL) { - if ((v = PyUnicode_AsUTF8(obj)) == NULL) { - Py_DECREF((PyObject *)client); - return (NULL); - } + if ((v = python_string_from_dict(kwargs, "cabundle")) != NULL) client->cabundle = kore_strdup(v); - } - - if ((obj = PyDict_GetItemString(kwargs, "unix")) != NULL) { - if ((v = PyUnicode_AsUTF8(obj)) == NULL) { - Py_DECREF((PyObject *)client); - return (NULL); - } + if ((v = python_string_from_dict(kwargs, "unix")) != NULL) client->unix = kore_strdup(v); - } - if ((obj = PyDict_GetItemString(kwargs, "tlsverify")) != NULL) { - if (obj == Py_True) { - client->tlsverify = 1; - } else if (obj == Py_False) { - client->tlsverify = 0; - } else { - Py_DECREF((PyObject *)client); - PyErr_SetString(PyExc_RuntimeError, - "tlsverify not True or False"); - return (NULL); - } - } + python_bool_from_dict(kwargs, "tlsverify", &client->tlsverify); } if ((client->tlscert != NULL && client->tlskey == NULL) || @@ -5103,19 +5161,8 @@ pyhttp_client_request(struct pyhttp_client *client, int m, PyObject *kwargs) } } - if (kwargs != NULL && - ((item = PyDict_GetItemString(kwargs, "return_headers")) != NULL)) { - if (item == Py_True) { - op->headers = 1; - } else if (item == Py_False) { - op->headers = 0; - } else { - Py_DECREF((PyObject *)op); - PyErr_SetString(PyExc_RuntimeError, - "return_headers not True or False"); - return (NULL); - } - } + if (kwargs != NULL) + python_bool_from_dict(kwargs, "return_headers", &op->headers); return ((PyObject *)op); } diff --git a/src/seccomp.c b/src/seccomp.c @@ -79,6 +79,7 @@ static struct sock_filter filter_kore[] = { KORE_SYSCALL_DENY_WITH_FLAG(mprotect, 2, PROT_EXEC, EINVAL), KORE_SYSCALL_ALLOW(mmap), + KORE_SYSCALL_ALLOW(madvise), KORE_SYSCALL_ALLOW(mprotect), /* Net related. */ @@ -178,7 +179,6 @@ kore_seccomp_enable(void) struct kore_runtime_call *rcall; struct filter *filter; size_t prog_len, off, i; - int skip_worker_filter; #if defined(KORE_DEBUG) memset(&sa, 0, sizeof(sa)); @@ -200,14 +200,7 @@ kore_seccomp_enable(void) ufilter = NULL; } - skip_worker_filter = 0; - -#if !defined(KORE_NO_TLS) - if (worker->id == KORE_WORKER_KEYMGR) - skip_worker_filter = 1; -#endif - - if (skip_worker_filter == 0) { + if (worker->id != KORE_WORKER_KEYMGR) { /* Add worker required syscalls. */ kore_seccomp_filter("worker", filter_kore, KORE_FILTER_LEN(filter_kore)); diff --git a/src/tasks.c b/src/tasks.c @@ -26,6 +26,16 @@ #include "http.h" #include "tasks.h" +#if defined(__linux__) +#include "seccomp.h" + +static struct sock_filter filter_task[] = { + KORE_SYSCALL_ALLOW(clone), + KORE_SYSCALL_ALLOW(socketpair), + KORE_SYSCALL_ALLOW(set_robust_list), +}; +#endif + static u_int8_t threads; static TAILQ_HEAD(, kore_task_thread) task_threads; @@ -50,6 +60,10 @@ kore_task_init(void) { threads = 0; TAILQ_INIT(&task_threads); + +#if defined(__linux__) + kore_seccomp_filter("task", filter_task, KORE_FILTER_LEN(filter_task)); +#endif } void diff --git a/src/utils.c b/src/utils.c @@ -91,10 +91,8 @@ kore_log(int prio, const char *fmt, ...) if (worker != NULL) { (void)snprintf(tmp, sizeof(tmp), "wrk %d", worker->id); -#if !defined(KORE_NO_TLS) if (worker->id == KORE_WORKER_KEYMGR) (void)kore_strlcpy(tmp, "keymgr", sizeof(tmp)); -#endif if (foreground) printf("[%s]: %s\n", tmp, buf); else @@ -646,10 +644,8 @@ fatal_log(const char *fmt, va_list args) if (!foreground) kore_log(LOG_ERR, "%s", buf); -#if !defined(KORE_NO_TLS) if (worker != NULL && worker->id == KORE_WORKER_KEYMGR) kore_keymgr_cleanup(1); -#endif printf("%s: %s\n", kore_progname, buf); } diff --git a/src/worker.c b/src/worker.c @@ -22,9 +22,7 @@ #include <sys/resource.h> #include <sys/socket.h> -#if !defined(KORE_NO_TLS) #include <openssl/rand.h> -#endif #include <fcntl.h> #include <grp.h> @@ -57,12 +55,7 @@ #define WAIT_ANY (-1) #endif -#if !defined(KORE_NO_TLS) #define WORKER_SOLO_COUNT 2 -#else -#define WORKER_SOLO_COUNT 1 -#endif - #define WORKER(id) \ (struct kore_worker *)((u_int8_t *)kore_workers + \ (sizeof(struct kore_worker) * id)) @@ -79,12 +72,10 @@ static inline int worker_acceptlock_obtain(void); static inline void worker_acceptlock_release(void); static void worker_accept_avail(struct kore_msg *, const void *); -#if !defined(KORE_NO_TLS) 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 **); -#endif static int accept_avail; static struct kore_worker *kore_workers; @@ -112,10 +103,8 @@ kore_worker_init(void) if (worker_count == 0) worker_count = cpu_count; -#if !defined(KORE_NO_TLS) /* account for the key manager. */ worker_count += 1; -#endif len = sizeof(*accept_lock) + (sizeof(struct kore_worker) * worker_count); @@ -318,19 +307,15 @@ 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; -#if !defined(KORE_NO_TLS) - u_int64_t last_seed; -#endif worker = kw; (void)snprintf(buf, sizeof(buf), "[wrk %d]", kw->id); -#if !defined(KORE_NO_TLS) if (kw->id == KORE_WORKER_KEYMGR) (void)snprintf(buf, sizeof(buf), "[keymgr]"); -#endif kore_platform_proctitle(buf); if (worker_set_affinity == 1) @@ -340,17 +325,20 @@ kore_worker_entry(struct kore_worker *kw) kore_signal_setup(); -#if !defined(KORE_NO_TLS) if (kw->id == KORE_WORKER_KEYMGR) { kore_keymgr_run(); exit(0); } -#endif + net_init(); kore_connection_init(); kore_platform_event_init(); kore_msg_worker_init(); +#if defined(KORE_USE_TASKS) + kore_task_init(); +#endif + kore_worker_privdrop(kore_runas_user, kore_root_path); #if !defined(KORE_NO_HTTP) @@ -368,11 +356,6 @@ kore_worker_entry(struct kore_worker *kw) accept_avail = 1; worker_active_connections = 0; -#if defined(KORE_USE_TASKS) - kore_task_init(); -#endif - -#if !defined(KORE_NO_TLS) last_seed = 0; kore_msg_register(KORE_MSG_CRL, worker_keymgr_response); kore_msg_register(KORE_MSG_ENTROPY_RESP, worker_entropy_recv); @@ -381,7 +364,6 @@ kore_worker_entry(struct kore_worker *kw) kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_CERTIFICATE_REQ, NULL, 0); } -#endif kore_msg_register(KORE_MSG_ACCEPT_AVAILABLE, worker_accept_avail); @@ -406,13 +388,11 @@ kore_worker_entry(struct kore_worker *kw) for (;;) { now = kore_time_ms(); -#if !defined(KORE_NO_TLS) if ((now - last_seed) > KORE_RESEED_TIME) { kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_ENTROPY_REQ, NULL, 0); last_seed = now; } -#endif if (!worker->has_lock && accept_avail) { accept_avail = 0; @@ -573,7 +553,6 @@ kore_worker_reap(void) } #endif -#if !defined(KORE_NO_TLS) if (id == KORE_WORKER_KEYMGR) { kore_log(LOG_CRIT, "keymgr gone, stopping"); kw->pid = 0; @@ -583,7 +562,6 @@ kore_worker_reap(void) } break; } -#endif if (kw->pid == accept_lock->current && worker_no_lock == 0) @@ -720,7 +698,6 @@ worker_accept_avail(struct kore_msg *msg, const void *data) accept_avail = 1; } -#if !defined(KORE_NO_TLS) static void worker_entropy_recv(struct kore_msg *msg, const void *data) { @@ -762,6 +739,7 @@ static int worker_keymgr_response_verify(struct kore_msg *msg, const void *data, struct kore_domain **out) { + struct listener *l; struct kore_domain *dom; const struct kore_x509_msg *req; @@ -785,9 +763,15 @@ worker_keymgr_response_verify(struct kore_msg *msg, const void *data, return (KORE_RESULT_ERROR); } - dom = NULL; - TAILQ_FOREACH(dom, &domains, list) { - if (!strncmp(dom->domain, req->domain, req->domain_len)) + LIST_FOREACH(l, &listeners, list) { + dom = NULL; + + TAILQ_FOREACH(dom, &l->domains, list) { + if (!strncmp(dom->domain, req->domain, req->domain_len)) + break; + } + + if (dom != NULL) break; } @@ -801,4 +785,3 @@ worker_keymgr_response_verify(struct kore_msg *msg, const void *data, return (KORE_RESULT_OK); } -#endif