diff --git a/Makefile b/Makefile index 61f9777..fa14307 100644 --- 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 index de4603d..6b8b586 100644 --- 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 index d3e1e6a..bae9c95 100644 --- 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 index e3e6e45..5e4c978 100644 --- 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 index 85ff5b5..f6fdc71 100755 --- 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 index dd366d4..c03218a 100644 --- 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 index 9bb6744..f55f6a0 100755 --- 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 index 7c6a902..8e1986b 100755 --- 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 index ad1705c..cd40dc3 100755 --- 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 index ed066ef..cf8c7cb 100644 --- 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 index a6c9a60..9b01539 100644 --- 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 index 479523e..7eb3d9b 100644 --- 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 index 85ac46a..5e83e31 100644 --- 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 index 4fb0273..6b98c0e 100644 --- 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 index ee95953..c58b8bb 100644 --- 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 index acc630d..788cc4f 100755 --- 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 index 4424868..4a8d15e 100644 --- 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 index d1b98ac..79ab865 100755 --- 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 index ceddc2c..0ba6a58 100644 --- 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 index 7b7c70a..c4010c2 100755 --- 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 index 7076151..d857c54 100644 --- 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 index 10241a1..4aac080 100644 --- 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 index ed5ddf2..285a18b 100755 --- 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 index 3b9e21a..4aba78f 100644 --- 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 index 4d29274..54b41ce 100644 --- 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 index 1205157..e21a6ea 100644 --- a/examples/tasks/src/tasks.c +++ b/examples/tasks/src/tasks.c @@ -33,6 +33,31 @@ #include #include +/* We need to allow some more syscalls on linux. */ +#if defined(__linux__) +#include + +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 index e5dc193..d5bcd36 100755 --- 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 index 95623c4..d0ad078 100644 --- 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 index d79e00a..edb6ca3 100755 --- 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 index 58eed30..a5bdc6c 100755 --- 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 index 3e65af5..431aa0c 100644 --- a/include/kore/kore.h +++ b/include/kore/kore.h @@ -30,11 +30,9 @@ #include #include -#if !defined(KORE_NO_TLS) #include #include #include -#endif #include #include @@ -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 index 32ce72f..9e4ac4a 100644 --- 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 index 9ca4878..783b10c 100644 --- 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 index cc36662..65b6896 100644 --- 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 index dbff43f..4a95f79 100644 --- 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; } @@ -472,16 +480,79 @@ configure_include(char *path) return (KORE_RESULT_OK); } +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 index 4618d97..3e9c62a 100644 --- 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 index 17aa543..1ec8271 100644 --- 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 index 1abaa12..35118e0 100644 --- a/src/domain.c +++ b/src/domain.c @@ -23,14 +23,12 @@ #include #include -#if !defined(KORE_NO_TLS) #include #include #include #include #include #include -#endif #include @@ -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 index 6ed2a6a..6540ab9 100644 --- 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 index f590229..7071a38 100644 --- 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 index c1b4628..6552a16 100644 --- 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 index 3bb3768..a35b47f 100644 --- 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 index 1cec439..494d57b 100644 --- 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); @@ -638,6 +672,15 @@ kore_signal_setup(void) (void)signal(SIGPIPE, SIG_IGN); } +void +kore_listener_closeall(void) +{ + struct listener *l; + + LIST_FOREACH(l, &listeners, list) + l->fd = -1; +} + void kore_listener_cleanup(void) { @@ -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 index 63a7162..4140c81 100644 --- 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 index 3ef4785..18144ac 100644 --- 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 index 53e6abd..52aba92 100644 --- 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 index 84edf58..ea85b17 100644 --- 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; -} + ip = python_string_from_dict(kwargs, "ip"); + path = python_string_from_dict(kwargs, "path"); -static PyObject * -python_kore_bind_unix(PyObject *self, PyObject *args) -{ - const char *path; - - if (!PyArg_ParseTuple(args, "s", &path)) - 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, + "missing ip or path keywords"); return (NULL); } - Py_RETURN_TRUE; + if (ip != NULL && path != NULL) { + PyErr_SetString(PyExc_RuntimeError, "ip/path are exclusive"); + return (NULL); + } + + 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)) - return (NULL); - - if (ca != NULL && depth < 0) { - PyErr_Format(PyExc_RuntimeError, "invalid depth '%d'", depth); - return (NULL); - } -#else if (!PyArg_ParseTuple(args, "s", &name)) return (NULL); -#endif - if (kore_domain_lookup(name) != NULL) { + if (kwargs == NULL) { + PyErr_SetString(PyExc_RuntimeError, "missing keyword args"); + return (NULL); + } + + if ((attach = python_string_from_dict(kwargs, "attach")) == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "missing or invalid 'attach' keyword"); + return (NULL); + } + + 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(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 index 38cedae..7c28985 100644 --- 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 index 53b70b3..a399d5c 100644 --- 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 index d7a6e4d..1633e43 100644 --- 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 index 45ef809..3f5a7af 100644 --- a/src/worker.c +++ b/src/worker.c @@ -22,9 +22,7 @@ #include #include -#if !defined(KORE_NO_TLS) #include -#endif #include #include @@ -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