Merge branch 'master' into 4.x-releng

This commit is contained in:
Joris Vink 2022-01-24 17:54:37 +01:00
commit e466871b59
89 changed files with 3885 additions and 2653 deletions

6
BEERS
View File

@ -17,20 +17,22 @@ I will note down the beer of your choice between the brackets.
[] Daniel Fahlgren x 2 [] Daniel Fahlgren x 2
[] Dmitrii Golub [] Dmitrii Golub
[] Elliot Schlegelmilch [] Elliot Schlegelmilch
[] Erik Karlsson [] Erik Karlsson x 2
[] Frederic Cambus [] Frederic Cambus
[] Guy Nankivell [] Guy Nankivell
[] James Turner [] James Turner
[] Joel Arbring x 2
[] Manuel Kniep [] Manuel Kniep
[] Marcin Szczepaniak [] Marcin Szczepaniak
[] Matt Thompson [] Matt Thompson
[] Matthew Norström
[] Nandor Kracser [] Nandor Kracser
[] Pascal Borreli [] Pascal Borreli
[] Quentin Perez [] Quentin Perez
[] Raphaël Monrouzeau [] Raphaël Monrouzeau
[] Raymond Pasco [] Raymond Pasco
[] Remy Noulin [] Remy Noulin
[] Rickard Lind [] Rickard Lind x 2
[] Shih-Yuan Lee [] Shih-Yuan Lee
[] Stanislav Yudin [] Stanislav Yudin
[] Stig Telfer [] Stig Telfer

View File

@ -21,9 +21,9 @@ VERSION=$(OBJDIR)/version.c
PYTHON_CURLOPT=misc/curl/python_curlopt.h PYTHON_CURLOPT=misc/curl/python_curlopt.h
S_SRC= src/kore.c src/buf.c src/config.c src/connection.c \ S_SRC= src/kore.c src/buf.c src/config.c src/connection.c \
src/domain.c src/filemap.c src/fileref.c src/json.c src/mem.c \ src/domain.c src/filemap.c src/fileref.c src/json.c src/log.c \
src/msg.c src/module.c src/net.c src/pool.c src/runtime.c src/timer.c \ src/mem.c src/msg.c src/module.c src/net.c src/pool.c src/runtime.c \
src/utils.c src/worker.c src/keymgr.c src/timer.c src/utils.c src/worker.c src/keymgr.c
FEATURES= FEATURES=
FEATURES_INC= FEATURES_INC=
@ -31,7 +31,7 @@ FEATURES_INC=
CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+=-Wsign-compare -Iinclude/kore -I$(OBJDIR) -std=c99 -pedantic CFLAGS+=-Wsign-compare -Iinclude/kore -I$(OBJDIR) -std=c99 -pedantic
CFLAGS+=-Wtype-limits CFLAGS+=-Wtype-limits -fno-common
CFLAGS+=-DPREFIX='"$(PREFIX)"' -fstack-protector-all CFLAGS+=-DPREFIX='"$(PREFIX)"' -fstack-protector-all
ifneq ("$(OPENSSL_PATH)", "") ifneq ("$(OPENSSL_PATH)", "")
@ -66,7 +66,7 @@ ifneq ("$(NOHTTP)", "")
FEATURES+=-DKORE_NO_HTTP FEATURES+=-DKORE_NO_HTTP
else else
S_SRC+= src/auth.c src/accesslog.c src/http.c \ S_SRC+= src/auth.c src/accesslog.c src/http.c \
src/validator.c src/websocket.c src/route.c src/validator.c src/websocket.c
endif endif
ifneq ("$(PGSQL)", "") ifneq ("$(PGSQL)", "")
@ -132,8 +132,10 @@ ifneq ("$(SANITIZE)", "")
endif endif
ifeq ("$(OSNAME)", "darwin") ifeq ("$(OSNAME)", "darwin")
CFLAGS+=-I/opt/local/include/ -I/usr/local/opt/openssl/include OSSL_INCL=$(shell pkg-config openssl --cflags)
LDFLAGS+=-L/opt/local/lib -L/usr/local/opt/openssl/lib CFLAGS+=$(OSSL_INCL)
LDFLAGS+=$(shell pkg-config openssl --libs)
FEATURES_INC+=$(OSSL_INCL)
S_SRC+=src/bsd.c S_SRC+=src/bsd.c
else ifeq ("$(OSNAME)", "linux") else ifeq ("$(OSNAME)", "linux")
CFLAGS+=-D_GNU_SOURCE=1 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 CFLAGS+=-D_GNU_SOURCE=1 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
@ -160,7 +162,7 @@ $(PLATFORM): $(OBJDIR) force
$(PYTHON_CURLOPT): $(OBJDIR) force $(PYTHON_CURLOPT): $(OBJDIR) force
@cp $(PYTHON_CURLOPT) $(OBJDIR) @cp $(PYTHON_CURLOPT) $(OBJDIR)
$(VERSION): force $(VERSION): $(OBJDIR) force
@if [ -d .git ]; then \ @if [ -d .git ]; then \
GIT_REVISION=`git rev-parse --short=8 HEAD`; \ GIT_REVISION=`git rev-parse --short=8 HEAD`; \
GIT_BRANCH=`git rev-parse --abbrev-ref HEAD`; \ GIT_BRANCH=`git rev-parse --abbrev-ref HEAD`; \
@ -174,12 +176,15 @@ $(VERSION): force
echo "No version information found (no .git or RELEASE)"; \ echo "No version information found (no .git or RELEASE)"; \
exit 1; \ exit 1; \
fi fi
@printf "const char *kore_build_date = \"%s\";\n" \
`date +"%Y-%m-%d"` >> $(VERSION);
$(KODEV): src/cli.c $(KODEV): src/cli.c
$(MAKE) -C kodev $(MAKE) -C kodev
$(KORE): $(OBJDIR) $(S_OBJS) $(KORE): $(OBJDIR) $(S_OBJS)
$(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE) $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE)
@echo $(LDFLAGS) > kore.linker
@echo $(FEATURES) $(FEATURES_INC) > kore.features @echo $(FEATURES) $(FEATURES_INC) > kore.features
objects: $(OBJDIR) $(PLATFORM) $(GENERATED) $(S_OBJS) objects: $(OBJDIR) $(PLATFORM) $(GENERATED) $(S_OBJS)
@ -197,7 +202,9 @@ install:
install -m 644 share/man/kodev.1 $(DESTDIR)$(MAN_DIR)/man1/kodev.1 install -m 644 share/man/kodev.1 $(DESTDIR)$(MAN_DIR)/man1/kodev.1
install -m 555 $(KORE) $(DESTDIR)$(INSTALL_DIR)/$(KORE) install -m 555 $(KORE) $(DESTDIR)$(INSTALL_DIR)/$(KORE)
install -m 644 kore.features $(DESTDIR)$(SHARE_DIR)/features install -m 644 kore.features $(DESTDIR)$(SHARE_DIR)/features
install -m 644 kore.linker $(DESTDIR)$(SHARE_DIR)/linker
install -m 644 include/kore/*.h $(DESTDIR)$(INCLUDE_DIR) install -m 644 include/kore/*.h $(DESTDIR)$(INCLUDE_DIR)
install -m 644 misc/ffdhe4096.pem $(DESTDIR)$(SHARE_DIR)/ffdhe4096.pem
$(MAKE) -C kodev install $(MAKE) -C kodev install
$(MAKE) install-sources $(MAKE) install-sources
@ -253,6 +260,8 @@ tools-install:
$(OBJDIR)/%.o: src/%.c $(OBJDIR)/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
src/kore.c: $(VERSION)
src/python.c: $(PYTHON_CURLOPT) src/python.c: $(PYTHON_CURLOPT)
src/seccomp.c: $(PLATFORM) src/seccomp.c: $(PLATFORM)
@ -260,7 +269,7 @@ src/seccomp.c: $(PLATFORM)
clean: clean:
rm -f $(VERSION) rm -f $(VERSION)
find . -type f -name \*.o -exec rm {} \; find . -type f -name \*.o -exec rm {} \;
rm -rf $(KORE) $(OBJDIR) kore.features rm -rf $(KORE) $(OBJDIR) kore.features kore.linker
$(MAKE) -C kodev clean $(MAKE) -C kodev clean
releng-build-examples: releng-build-examples:

View File

@ -35,7 +35,7 @@ License
Documentation Documentation
-------------- --------------
[Read the documentation](https://docs.kore.io/4.0.0/) [Read the documentation](https://docs.kore.io/4.1.0/)
Performance Performance
----------- -----------
@ -52,11 +52,11 @@ Kore only supports x64, arm and aarch64 architectures.
Building Kore Building Kore
------------- -------------
Clone this repository or get the latest release at [https://kore.io/releases/4.0.0](https://kore.io/releases/4.0.0). Clone this repository or get the latest release at [https://kore.io/releases/4.1.0](https://kore.io/releases/4.1.0).
Requirements Requirements
* openssl (1.0.2, 1.1.0 or 1.1.1) * openssl 1.1.1 or libressl 3.x
(note: libressl 3.0.0+ works as a replacement) (note: openssl 3.0.0 is currently *not* supported)
Requirement for asynchronous curl (optional) Requirement for asynchronous curl (optional)
* libcurl (7.64.0 or higher) * libcurl (7.64.0 or higher)

View File

@ -12,7 +12,7 @@
# Server configuration. # Server configuration.
server tls { server tls {
bind 127.0.0.1 443 bind 127.0.0.1 443
#bind_unix /var/run/kore.sock #unix /var/run/kore.sock
} }
#server notls { #server notls {
@ -20,16 +20,57 @@ server tls {
# tls no # tls no
#} #}
# The worker process root directory. If chrooting was not disabled # Kore can have multiple settings for each processes that run under it.
# at startup the worker processes will chroot into this directory. # There are 3 different type of processes:
# #
# If this configuration option is not set, Kore will take the current # 1) Worker processes, these handle the HTTP requests and your code
# working directory as the root. # runs inside of these.
root /home/joris/src/kore # 2) The keymgr process, this handles your domain private keys
# and signing during the TLS handshakes. It also holds your
# ACME account-key and will sign ACME requests.
# 3) The acme process, this talks to the ACME servers.
#
# You can individually turn on/off chrooting and dropping user
# privileges per process. The -n and -r command-line options
# are a global override for skipping chroot or dropping user
# permissions on all processes.
#
# If no root/runas options are set in a process, it will inherit the
# default values from the worker processes.
#
# The worker processes will get the current working directory or
# current user if no options where specified for it.
#
# Configures the worker processes.
privsep worker {
# The user the workers will run as.
runas kore
# Worker processes will run as the specified user. If this option is # The root directory for the worker processes, if chroot isn't
# missing Kore will run as the current user. # skipped, this is the directory it will chroot into.
runas joris #
# If not set, Kore will take the current working directory.
root /var/chroot/kore
# We could configure this process to not chroot and only
# chdir into its root directory.
#skip chroot
}
# Configures the keymgr process.
# If TLS is enabled you will need to specify paths to the domain
# certificate and key that Kore will load. This loading is done
# from the keymgr (separate process) and all paths must be relative
# to the keymgr process its root configuration option.
privsep keymgr {
# The user the keymgr will run as.
runas keymgr
# The root directory for the keymgr process. In this example
# we do not turn off chroot for this process so the keymgr
# will chroot into this directory.
root /etc/keymgr
}
# How many worker processes Kore will spawn. If the directive # How many worker processes Kore will spawn. If the directive
# worker_set_affinity is set to 1 (the default) Kore will automatically # worker_set_affinity is set to 1 (the default) Kore will automatically
@ -88,25 +129,6 @@ workers 4
# NOTE: This file location must be inside your chrooted environment. # NOTE: This file location must be inside your chrooted environment.
#rand_file random.data #rand_file random.data
# Key manager specific options.
# If TLS is enabled you will need to specify paths to the domain
# certificate and key that Kore will load. This loading is done
# from the keymgr (separate process) and all paths must be relative
# to the keymgr_root configuration option.
#
# keymgr_root The root path the keymgr will chdir into.
# If chroot was not disable at startup time
# the keymgr process will chroot into here.
#
# keymgr_runas The user to run the keymgr as.
#
# If privsep and chrooting is enabled at startup time but these
# configuration options were not set, they will take over the
# values from the 'root' and 'runas' configuration options.
#
#keymgr_root
#keymgr_runas
# Filemap settings # Filemap settings
# filemap_index Name of the file to be used as the directory # filemap_index Name of the file to be used as the directory
# index for a filemap. # index for a filemap.
@ -189,18 +211,20 @@ validator v_regex regex ^/test/[a-z]*$
validator v_number regex ^[0-9]*$ validator v_number regex ^[0-9]*$
validator v_session function v_session_validate validator v_session function v_session_validate
# Specify what TLS version to be used. Default is TLSv1.2 # Specify what TLS version to be used. Default is TLSv1.3 if available.
# Otherwise it will use TLS 1.2.
# Allowed values: # Allowed values:
# 1.2 for TLSv1.2 (default) # 1.3 for TLSv1.3 (default, if available)
# 1.0 for TLSv1.0 # 1.2 for TLSv1.2
# both for TLSv1.0 and TLSv1.2 # both for TLSv1.2 and TLSv1.3
#tls_version 1.2 #tls_version 1.3
# Specify the TLS ciphers that will be used. # Specify the TLS ciphers that will be used.
#tls_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA #tls_cipher AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256
# Required DH parameters for TLS. # Required DH parameters for TLS if DHE ciphersuites are in-use.
#tls_dhparam dh2048.pem # Defaults to SHARE_DIR/ffdhe4096.pem, can be overwritten.
#tls_dhparam /usr/local/share/kore/ffdhe4096.pem
# OpenBSD specific settings. # OpenBSD specific settings.
# Add more pledges if your application requires more privileges. # Add more pledges if your application requires more privileges.
@ -298,24 +322,24 @@ domain localhost {
accesslog /var/log/kore_access.log accesslog /var/log/kore_access.log
# Page handlers with no authentication required. # Page handlers with no authentication required.
static /css/style.css serve_style_css route /css/style.css serve_style_css
static / serve_index route / serve_index
static /intro.jpg serve_intro route /intro.jpg serve_intro
static /b64test serve_b64test route /b64test serve_b64test
static /upload serve_file_upload route /upload serve_file_upload
static /lock-test serve_lock_test route /lock-test serve_lock_test
static /validator serve_validator route /validator serve_validator
static /params-test serve_params_test route /params-test serve_params_test
static /private serve_private route /private serve_private
# Restrict some URIs to certain methods # Restrict some URIs to certain methods
restrict /private post restrict /private post
restrict /validator post get head restrict /validator post get head
# Page handlers with authentication. # Page handlers with authentication.
static /private/test serve_private_test auth_example route /private/test serve_private_test auth_example
# Allow access to files from the directory static_files via # Allow access to files from the directory route_files via
# the /files/ URI. # the /files/ URI.
# #
# Note the directory given must be relative to the root configuration # Note the directory given must be relative to the root configuration
@ -369,7 +393,7 @@ domain localhost {
# client_verify /other/ca.crt # client_verify /other/ca.crt
# client_verify_depth 1 # client_verify_depth 1
# static /css/style.css serve_style_css # route /css/style.css serve_style_css
# static / serve_index # route / serve_index
# dynamic ^/[a-z0-9_]*$ serve_profile # route ^/[a-z0-9_]*$ serve_profile
#} #}

View File

@ -5,8 +5,6 @@ server tls {
} }
workers 1 workers 1
tls_dhparam dh2048.pem
pledge dns pledge dns
domain * { domain * {
@ -15,6 +13,11 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / http route / {
route /ftp ftp handler http
}
route /ftp {
handler ftp
}
} }

View File

@ -44,7 +44,7 @@ state_setup(struct http_request *req)
{ {
struct kore_curl *client; struct kore_curl *client;
client = http_state_create(req, sizeof(*client), NULL); client = http_state_create(req, sizeof(*client));
if (!kore_curl_init(client, if (!kore_curl_init(client,
"http://ftp.eu.openbsd.org/pub/OpenBSD/README", KORE_CURL_ASYNC)) { "http://ftp.eu.openbsd.org/pub/OpenBSD/README", KORE_CURL_ASYNC)) {

View File

@ -59,7 +59,7 @@ state_setup(struct http_request *req)
{ {
struct kore_curl *client; struct kore_curl *client;
client = http_state_create(req, sizeof(*client), NULL); client = http_state_create(req, sizeof(*client));
/* Initialize curl. */ /* Initialize curl. */
if (!kore_curl_init(client, "https://kore.io", KORE_CURL_ASYNC)) { if (!kore_curl_init(client, "https://kore.io", KORE_CURL_ASYNC)) {

View File

@ -6,15 +6,21 @@ server tls {
load ./cookies.so load ./cookies.so
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / serve_cookies route / {
route /secure serve_cookies handler serve_cookies
route /vault serve_cookies }
route /secure {
handler serve_cookies
}
route /vault {
handler serve_cookies
}
} }

View File

@ -5,12 +5,14 @@ server tls {
} }
load ./cpp.so load ./cpp.so
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page
route / {
handler page
}
} }

View File

@ -1,8 +0,0 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv
VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY
Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/
PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV
Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN
xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==
-----END DH PARAMETERS-----

View File

@ -6,8 +6,6 @@ server tls {
load ./generic.so example_load load ./generic.so example_load
tls_dhparam dh2048.pem
http_body_max 1024000000 http_body_max 1024000000
http_body_disk_offload 1024000 http_body_disk_offload 1024000

View File

@ -2,13 +2,13 @@ Test parameter to integer conversions.
Run: Run:
``` ```
# kodev run $ kodev run
``` ```
Test: Test:
``` ```
# curl -i -k https://127.0.0.1:8888/?id=123123 $ curl -i -k https://127.0.0.1:8888/?id=123123
# curl -i -k https://127.0.0.1:8888/?id=-123123 $ curl -i -k https://127.0.0.1:8888/?id=-123123
``` ```
The correct integer types should only be represented in the output. The correct integer types should only be represented in the output.

View File

@ -9,8 +9,6 @@ load ./integers.so
workers 2 workers 2
worker_max_connections 5000 worker_max_connections 5000
tls_dhparam dh2048.pem
validator v_id regex ^-?[0-9]*.?[0-9]+$ validator v_id regex ^-?[0-9]*.?[0-9]+$
domain * { domain * {
@ -18,10 +16,12 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page
# allowed parameters in the query string for GETs route / {
params qs:get / { handler page
validate id v_id methods get
# allowed parameters in the query string for GETs
validate get id v_id
} }
} }

View File

@ -6,14 +6,14 @@ server tls {
load ./json.so load ./json.so
tls_dhparam dh2048.pem
domain 127.0.0.1 { domain 127.0.0.1 {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
restrict / post handler page
methods post
}
} }

View File

@ -30,14 +30,24 @@ page(struct http_request *req)
kore_json_init(&json, req->http_body->data, req->http_body->length); kore_json_init(&json, req->http_body->data, req->http_body->length);
if (!kore_json_parse(&json)) { if (!kore_json_parse(&json)) {
kore_buf_appendf(&buf, "%s\n", kore_json_strerror(&json)); kore_buf_appendf(&buf, "%s\n", kore_json_strerror());
} else { } else {
item = kore_json_find_string(json.root, "foo/bar"); item = kore_json_find_string(json.root, "foo/bar");
if (item != NULL) { if (item != NULL) {
kore_buf_appendf(&buf, kore_buf_appendf(&buf,
"foo.bar = '%s'\n", item->data.string); "foo.bar = '%s'\n", item->data.string);
} else { } else {
kore_buf_appendf(&buf, "string foo.bar not found\n"); kore_buf_appendf(&buf, "foo.bar %s\n",
kore_json_strerror());
}
item = kore_json_find_integer_u64(json.root, "foo/integer");
if (item != NULL) {
kore_buf_appendf(&buf,
"foo.integer = '%" PRIu64 "'\n", item->data.u64);
} else {
kore_buf_appendf(&buf, "foo.integer %s\n",
kore_json_strerror());
} }
} }

View File

@ -1,5 +0,0 @@
*.o
.objs
json_yajl.so
assets.h
cert

View File

@ -1,21 +0,0 @@
This example demonstrates how you can use external libs in your application.
In this case we link against yajl (Yet Another JSON library) in order to
parse a JSON string that was POSTed to the server.
Take a peek at conf/build.conf for different build flavors and how to
link to other libraries.
Run:
```
$ kodev run
```
Test:
```
$ curl -i -k -d '{"foo":{"bar": "Hello world"}}' https://127.0.0.1:8888
```
The result should echo back the foo.bar JSON path value: Hello world.
The yajl repo is available @ https://github.com/lloyd/yajl

View File

@ -1,19 +0,0 @@
# json_yajl build config
# You can switch flavors using: kodev flavor [newflavor]
# The cflags below are shared between flavors
cflags=-Wall -Wmissing-declarations -Wshadow
cflags=-Wstrict-prototypes -Wmissing-prototypes
cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
dev {
# These cflags are added to the shared ones when
# you build the "dev" flavor.
cflags=-g
ldflags=-lyajl
}
#prod {
# You can specify additional CFLAGS here which are only
# included if you build with the "prod" flavor.
#}

View File

@ -1,18 +0,0 @@
# Placeholder configuration
server 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
route / page
}

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2013-2018 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <kore/kore.h>
#include <kore/http.h>
#include <yajl/yajl_tree.h>
int page(struct http_request *);
int
page(struct http_request *req)
{
ssize_t ret;
struct kore_buf *buf;
char *body;
yajl_val node, v;
char eb[1024];
u_int8_t data[BUFSIZ];
const char *path[] = { "foo", "bar", NULL };
/* We only allow POST/PUT methods. */
if (req->method != HTTP_METHOD_POST &&
req->method != HTTP_METHOD_PUT) {
http_response_header(req, "allow", "POST, PUT");
http_response(req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
return (KORE_RESULT_OK);
}
/*
* Read the entire received body into a memory buffer.
*/
buf = kore_buf_alloc(128);
for (;;) {
ret = http_body_read(req, data, sizeof(data));
if (ret == -1) {
kore_buf_free(buf);
kore_log(LOG_NOTICE, "error reading body");
http_response(req, 500, NULL, 0);
return (KORE_RESULT_OK);
}
if (ret == 0)
break;
kore_buf_append(buf, data, ret);
}
/* Grab our body data as a NUL-terminated string. */
body = kore_buf_stringify(buf, NULL);
/* Parse the body via yajl now. */
node = yajl_tree_parse(body, eb, sizeof(eb));
if (node == NULL) {
if (strlen(eb)) {
kore_log(LOG_NOTICE, "parse error: %s", eb);
} else {
kore_log(LOG_NOTICE, "parse error: unknown");
}
kore_buf_free(buf);
http_response(req, 400, NULL, 0);
return (KORE_RESULT_OK);
}
/* Reuse old buffer, don't need it anymore for body. */
kore_buf_reset(buf);
/* Attempt to grab foo.bar from the JSON tree. */
v = yajl_tree_get(node, path, yajl_t_string);
if (v == NULL) {
kore_buf_appendf(buf, "no such path: foo.bar\n");
} else {
kore_buf_appendf(buf, "foo.bar = '%s'\n", YAJL_GET_STRING(v));
}
/* Release the JSON tree now. */
yajl_tree_free(node);
/* Respond to the client. */
http_response(req, 200, buf->data, buf->offset);
kore_buf_free(buf);
return (KORE_RESULT_OK);
}

View File

@ -6,14 +6,17 @@ server tls {
load ./jsonrpc.so load ./jsonrpc.so
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / homepage route / {
route /v1 v1 handler homepage
}
route /v1 {
handler v1
}
} }

View File

@ -6,13 +6,13 @@ server tls {
load ./memtag.so init load ./memtag.so init
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
handler page
}
} }

View File

@ -5,14 +5,18 @@ server tls {
} }
load ./messaging.so init load ./messaging.so init
tls_dhparam dh2048.pem
workers 4
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page
route /shutdown page_shutdown route / {
handler page
}
route /shutdown {
handler page_shutdown
}
} }

View File

@ -4,8 +4,6 @@ server tls {
bind 127.0.0.1 8888 connection_setup bind 127.0.0.1 8888 connection_setup
} }
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls

View File

@ -6,8 +6,6 @@ server tls {
load ./parameters.so load ./parameters.so
tls_dhparam dh2048.pem
# The validator used to validate the 'id' parameter # The validator used to validate the 'id' parameter
# defined below. We'll use a simple regex to make sure # defined below. We'll use a simple regex to make sure
# it only matches positive numbers. # it only matches positive numbers.
@ -19,15 +17,10 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
handler page
methods get
# The parameters allowed for "/" (GET method). validate qs:get id v_id
#
# If you would want to declare parameters available
# to the page handler for POST, swap the 'get' setting
# to 'post' instead, Kore takes care of the rest.
params qs:get / {
# Validate the id parameter with the v_id validator.
validate id v_id
} }
} }

View File

@ -4,13 +4,15 @@ server tls {
bind 127.0.0.1 8888 bind 127.0.0.1 8888
} }
load ./pgsql-sync.so init load ./pgsql-sync.so init
tls_dhparam dh2048.pem
domain * { domain * {
attach tls attach tls
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page
route / {
handler page
}
} }

View File

@ -10,8 +10,6 @@ server other {
bind 127.0.0.1 8889 connection_new bind 127.0.0.1 8889 connection_new
} }
tls_dhparam dh2048.pem
http_keepalive_time 0 http_keepalive_time 0
domain * { domain * {
@ -20,6 +18,11 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
route /hello hello handler page
}
route /hello {
handler hello
}
} }

View File

@ -85,7 +85,7 @@ request_perform_init(struct http_request *req)
/* Setup our state context (if not yet set). */ /* Setup our state context (if not yet set). */
if (!http_state_exists(req)) { if (!http_state_exists(req)) {
state = http_state_create(req, sizeof(*state), NULL); state = http_state_create(req, sizeof(*state));
/* /*
* Initialize the kore_pgsql data structure and bind it * Initialize the kore_pgsql data structure and bind it

View File

@ -4,8 +4,6 @@ server tls {
bind 127.0.0.1 8888 bind 127.0.0.1 8888
} }
tls_dhparam dh2048.pem
websocket_maxframe 65536 websocket_maxframe 65536
websocket_timeout 10000 websocket_timeout 10000
@ -15,6 +13,12 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
route /connect page_ws_connect handler page
}
route /connect {
handler page_ws_connect
methods get
}
} }

View File

@ -28,6 +28,7 @@
#include <kore/kore.h> #include <kore/kore.h>
#include <kore/http.h> #include <kore/http.h>
#include <kore/tasks.h> #include <kore/tasks.h>
#include <kore/hooks.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -49,17 +50,12 @@ void pipe_data_available(struct kore_task *);
/* Our pipe reader. */ /* Our pipe reader. */
struct kore_task pipe_task; struct kore_task pipe_task;
/* Module init function (see config). */ void
int kore_worker_configure(void)
init(int state)
{ {
/* Do not allow reload. */
if (state == KORE_MODULE_UNLOAD)
return (KORE_RESULT_ERROR);
/* Only do this on a dedicated worker. */ /* Only do this on a dedicated worker. */
if (worker->id != 1) if (worker->id != 1)
return (KORE_RESULT_OK); return;
/* Create our task. */ /* Create our task. */
kore_task_create(&pipe_task, pipe_reader); kore_task_create(&pipe_task, pipe_reader);
@ -69,8 +65,6 @@ init(int state)
/* Start the task. */ /* Start the task. */
kore_task_run(&pipe_task); kore_task_run(&pipe_task);
return (KORE_RESULT_OK);
} }
/* Called whenever we get a new websocket connection. */ /* Called whenever we get a new websocket connection. */

View File

@ -3,9 +3,11 @@ Kore python async/await examples.
This example also shows off the asynchronous HTTP client support This example also shows off the asynchronous HTTP client support
and requires libcurl on your machine. and requires libcurl on your machine.
Requires that Kore is built with PYTHON=1 CURL=1
Run: Run:
``` ```
$ kodev run $ kore app.py
``` ```
Test: Test:

View File

@ -16,8 +16,13 @@
import kore import kore
from async_queue import queue_helper import async_http
import async_queue
import async_socket
import async_process
import async_process
# Kore worker started, start the queue helper coroutine. kore.server(ip="127.0.0.1", port="8888", tls=False)
def kore_worker_configure(): kore.domain("*")
kore.task_create(queue_helper())
kore.task_create(async_queue.queue_helper())

View File

@ -21,6 +21,7 @@
import kore import kore
# Handler called for /httpclient # Handler called for /httpclient
@kore.route("/httpclient", methods=["get"])
async def httpclient(req): async def httpclient(req):
# Create an httpclient. # Create an httpclient.
client = kore.httpclient("https://kore.io") client = kore.httpclient("https://kore.io")

View File

@ -28,6 +28,7 @@ import kore
# The shared lock # The shared lock
lock = kore.lock() lock = kore.lock()
@kore.route("/lock", methods=["get"])
async def async_lock(req): async def async_lock(req):
# A kore.lock should be used with the "async with" syntax. # A kore.lock should be used with the "async with" syntax.
async with lock: async with lock:

View File

@ -25,6 +25,7 @@
import kore import kore
import json import json
@kore.route("/proc", methods=["get"])
async def async_proc(req): async def async_proc(req):
# #
# You may specify a timeout when creating the kore.proc object. # You may specify a timeout when creating the kore.proc object.

View File

@ -36,6 +36,7 @@ async def queue_helper():
# Send it on the received queue. # Send it on the received queue.
obj["rq"].push(msg) obj["rq"].push(msg)
@kore.route("/queue", methods=["get"])
async def async_queue(req): async def async_queue(req):
# Create our own queue. # Create our own queue.
rq = kore.queue() rq = kore.queue()

View File

@ -23,6 +23,7 @@
import kore import kore
import socket import socket
@kore.route("/socket", methods=["get"])
async def async_socket(req): async def async_socket(req):
# Create the socket using Pythons built-in socket class. # Create the socket using Pythons built-in socket class.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -51,6 +52,7 @@ async def async_socket(req):
conn.close() conn.close()
@kore.route("/socket-test", methods=["get"])
async def socket_test(req): async def socket_test(req):
# Delay response a bit, just cause we can. # Delay response a bit, just cause we can.
await kore.suspend(5000) await kore.suspend(5000)

View File

@ -1,34 +0,0 @@
# python-async 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=PYTHON=1 CURL=1 NOTLS=1 DEBUG=1
# The flags below are shared between flavors
cflags=-Wall -Wmissing-declarations -Wshadow
cflags=-Wstrict-prototypes -Wmissing-prototypes
cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
cxxflags=-Wall -Wmissing-declarations -Wshadow
cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare
# Mime types for assets served via the builtin asset_serve_*
#mime_add=txt:text/plain; charset=utf-8
#mime_add=png:image/png
#mime_add=html:text/html; charset=utf-8
dev {
# These flags are added to the shared ones when
# you build the "dev" flavor.
cflags=-g
cxxflags=-g
}
#prod {
# You can specify additional flags here which are only
# included if you build with the "prod" flavor.
#}

View File

@ -1,28 +0,0 @@
# python-async configuration
server notls {
tls no
bind 127.0.0.1 8888
}
python_path src
python_import ./src/setup.py
python_import ./src/async_lock.py
python_import ./src/async_queue.py
python_import ./src/async_process.py
python_import ./src/async_socket.py
python_import ./src/async_http.py
domain * {
attach notls
route /queue async_queue
route /lock async_lock
route /proc async_proc
route /socket async_socket
route /socket-test socket_test
route /httpclient httpclient
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 2020 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <kore/kore.h>
#include <kore/hooks.h>
/* Let kore handle the default option parsing. */
void
kore_parent_configure(int argc, char **argv)
{
kore_default_getopt(argc, argv);
}

View File

@ -0,0 +1,11 @@
Example of using the asynchronous python api to create a simple
echo server.
Kore must have been built with PYTHON=1.
On the command-line run the following
$ kore echo.py
Then connect to 127.0.0.1 port 6969 using netcat or so and you'll
see it echo back everything you send it.

View File

@ -1,34 +0,0 @@
# python-echo 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=NOTLS=1 PYTHON=1
# The flags below are shared between flavors
cflags=-Wall -Wmissing-declarations -Wshadow
cflags=-Wstrict-prototypes -Wmissing-prototypes
cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
cxxflags=-Wall -Wmissing-declarations -Wshadow
cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare
# Mime types for assets served via the builtin asset_serve_*
#mime_add=txt:text/plain; charset=utf-8
#mime_add=png:image/png
#mime_add=html:text/html; charset=utf-8
dev {
# These flags are added to the shared ones when
# you build the "dev" flavor.
cflags=-g
cxxflags=-g
}
#prod {
# You can specify additional flags here which are only
# included if you build with the "prod" flavor.
#}

View File

@ -1,3 +0,0 @@
# python-echo configuration
python_import src/echo.py

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 2020 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <kore/kore.h>
#include <kore/hooks.h>
/* Let kore handle the default option parsing. */
void
kore_parent_configure(int argc, char **argv)
{
kore_default_getopt(argc, argv);
}

View File

@ -4,10 +4,8 @@ server tls {
bind 127.0.0.1 8888 bind 127.0.0.1 8888
} }
load ./sse.so load ./sse.so
tls_dhparam dh2048.pem http_keepalive_time 600
http_keepalive_time 600
domain * { domain * {
attach tls attach tls
@ -15,6 +13,11 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
route /subscribe subscribe handler page
}
route /subscribe {
handler subscribe
}
} }

View File

@ -4,8 +4,6 @@ server tls {
bind 127.0.0.1 8888 bind 127.0.0.1 8888
} }
tls_dhparam dh2048.pem
task_threads 4 task_threads 4
worker_max_connections 1000 worker_max_connections 1000
http_keepalive_time 0 http_keepalive_time 0
@ -19,14 +17,14 @@ domain * {
certkey cert/key.pem certkey cert/key.pem
accesslog kore_access.log accesslog kore_access.log
route / page_handler route / {
route /post_back post_back handler page_handler
validate qs:get user v_user
params qs:get / {
validate user v_user
} }
params post /post_back { route /post_back {
validate user v_user handler post_back
methods post
validate post user v_user
} }
} }

View File

@ -1,7 +1,6 @@
# Kore as a TLS proxy configuration. # Kore as a TLS proxy configuration.
load ./tls-proxy.so load ./tls-proxy.so
tls_dhparam dh2048.pem
# #
# Bind the proxy to a given IP and port. For every # Bind the proxy to a given IP and port. For every

View File

@ -6,8 +6,6 @@ server tls {
load ./upload.so load ./upload.so
tls_dhparam dh2048.pem
http_body_max 1024000000 http_body_max 1024000000
http_body_disk_offload 4096 http_body_disk_offload 4096
@ -17,5 +15,7 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
handler page
}
} }

View File

@ -6,8 +6,6 @@ server tls {
load ./video_stream.so init load ./video_stream.so init
tls_dhparam dh2048.pem
http_keepalive_time 600 http_keepalive_time 600
domain * { domain * {
@ -17,6 +15,11 @@ domain * {
certkey cert/key.pem certkey cert/key.pem
accesslog access.log accesslog access.log
route / asset_serve_video_html route / {
route ^/[a-z]*.[a-z0-9]{3}$ video_stream handler asset_serve_video_html
}
route ^/[a-z]*.[a-z0-9]{3}$ {
handler video_stream
}
} }

View File

@ -6,8 +6,6 @@ server tls {
load ./websocket.so load ./websocket.so
tls_dhparam dh2048.pem
# Increase workers so connections are spread # Increase workers so connections are spread
# across them to demonstrate WEBSOCKET_BROADCAST_GLOBAL. # across them to demonstrate WEBSOCKET_BROADCAST_GLOBAL.
workers 4 workers 4
@ -21,6 +19,11 @@ domain * {
certfile cert/server.pem certfile cert/server.pem
certkey cert/key.pem certkey cert/key.pem
route / page route / {
route /connect page_ws_connect handler page
}
route /connect {
handler page_ws_connect
}
} }

View File

@ -54,6 +54,7 @@ int kore_acme_tls_alpn(SSL *, const unsigned char **, unsigned char *,
const unsigned char *, unsigned int, void *); const unsigned char *, unsigned int, void *);
extern char *acme_email; extern char *acme_email;
extern int acme_domains;
extern char *acme_provider; extern char *acme_provider;
#if defined(__cplusplus) #if defined(__cplusplus)

View File

@ -22,6 +22,7 @@
#define KORE_DAEMONIZED_HOOK "kore_parent_daemonized" #define KORE_DAEMONIZED_HOOK "kore_parent_daemonized"
void kore_seccomp_hook(void); void kore_seccomp_hook(void);
void kore_worker_signal(int);
void kore_worker_teardown(void); void kore_worker_teardown(void);
void kore_parent_teardown(void); void kore_parent_teardown(void);
void kore_worker_configure(void); void kore_worker_configure(void);

View File

@ -119,7 +119,7 @@ struct http_arg {
do { \ do { \
int err; \ int err; \
type nval; \ type nval; \
nval = (type)kore_strtonum64(q->s_value, sign, &err); \ nval = (type)kore_strtonum64(data, sign, &err); \
if (err != KORE_RESULT_OK) \ if (err != KORE_RESULT_OK) \
return (KORE_RESULT_ERROR); \ return (KORE_RESULT_ERROR); \
COPY_ARG_TYPE(nval, type); \ COPY_ARG_TYPE(nval, type); \
@ -129,7 +129,7 @@ struct http_arg {
do { \ do { \
int err; \ int err; \
type nval; \ type nval; \
nval = kore_strtodouble(q->s_value, min, max, &err); \ nval = kore_strtodouble(data, min, max, &err); \
if (err != KORE_RESULT_OK) \ if (err != KORE_RESULT_OK) \
return (KORE_RESULT_ERROR); \ return (KORE_RESULT_ERROR); \
COPY_ARG_TYPE(nval, type); \ COPY_ARG_TYPE(nval, type); \
@ -139,7 +139,7 @@ struct http_arg {
do { \ do { \
int err; \ int err; \
int64_t nval; \ int64_t nval; \
nval = kore_strtonum(q->s_value, 10, min, max, &err); \ nval = kore_strtonum(data, 10, min, max, &err); \
if (err != KORE_RESULT_OK) \ if (err != KORE_RESULT_OK) \
return (KORE_RESULT_ERROR); \ return (KORE_RESULT_ERROR); \
COPY_ARG_TYPE(nval, type); \ COPY_ARG_TYPE(nval, type); \
@ -159,38 +159,62 @@ struct http_arg {
COPY_ARG_INT(min, max, type); \ COPY_ARG_INT(min, max, type); \
} while (0) } while (0)
#define http_argument_type(r, n, so, no, t) \
http_argument_get(r, n, so, no, t)
#define http_argument_get_string(r, n, o) \ #define http_argument_get_string(r, n, o) \
http_argument_type(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING) http_argument_get(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING)
#define http_argument_get_byte(r, n, o) \ #define http_argument_get_byte(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_BYTE) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
#define http_argument_get_uint16(r, n, o) \ #define http_argument_get_uint16(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT16) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
#define http_argument_get_int16(r, n, o) \ #define http_argument_get_int16(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT16) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
#define http_argument_get_uint32(r, n, o) \ #define http_argument_get_uint32(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT32) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
#define http_argument_get_int32(r, n, o) \ #define http_argument_get_int32(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT32) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
#define http_argument_get_uint64(r, n, o) \ #define http_argument_get_uint64(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT64) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
#define http_argument_get_int64(r, n, o) \ #define http_argument_get_int64(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT64) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
#define http_argument_get_float(r, n, o) \ #define http_argument_get_float(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT)
#define http_argument_get_double(r, n, o) \ #define http_argument_get_double(r, n, o) \
http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE) http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE)
#define http_request_header_byte(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
#define http_request_header_uint16(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
#define http_request_header_int16(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
#define http_request_header_uint32(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
#define http_request_header_int32(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
#define http_request_header_uint64(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
#define http_request_header_int64(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
#define http_request_header_float(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT)
#define http_request_header_double(r, n, o) \
http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE)
struct http_file { struct http_file {
char *name; char *name;
@ -262,13 +286,13 @@ struct http_request {
struct kore_buf *http_body; struct kore_buf *http_body;
int http_body_fd; int http_body_fd;
char *http_body_path; char *http_body_path;
size_t http_body_length; u_int64_t http_body_length;
size_t http_body_offset; u_int64_t http_body_offset;
size_t content_length; u_int64_t content_length;
void *hdlr_extra; void *hdlr_extra;
size_t state_len; size_t state_len;
char *query_string; char *query_string;
struct kore_module_handle *hdlr; struct kore_route *rt;
struct http_runlock_queue *runlock; struct http_runlock_queue *runlock;
void (*onfree)(struct http_request *); void (*onfree)(struct http_request *);
@ -357,6 +381,10 @@ int http_body_digest(struct http_request *, char *, size_t);
int http_redirect_add(struct kore_domain *, int http_redirect_add(struct kore_domain *,
const char *, int, const char *); const char *, int, const char *);
void http_response(struct http_request *, int, const void *, size_t); void http_response(struct http_request *, int, const void *, size_t);
void http_response_json(struct http_request *, int,
struct kore_json_item *);
void http_response_close(struct http_request *, int,
const void *, size_t);
void http_response_fileref(struct http_request *, int, void http_response_fileref(struct http_request *, int,
struct kore_fileref *); struct kore_fileref *);
void http_serveable(struct http_request *, const void *, void http_serveable(struct http_request *, const void *,
@ -385,8 +413,7 @@ const char *http_media_type(const char *);
void *http_state_get(struct http_request *); void *http_state_get(struct http_request *);
int http_state_exists(struct http_request *); int http_state_exists(struct http_request *);
void http_state_cleanup(struct http_request *); void http_state_cleanup(struct http_request *);
void *http_state_create(struct http_request *, size_t, void *http_state_create(struct http_request *, size_t);
void (*onfree)(struct http_request *));
int http_argument_urldecode(char *); int http_argument_urldecode(char *);
int http_header_recv(struct netbuf *); int http_header_recv(struct netbuf *);
@ -396,6 +423,8 @@ void http_populate_multipart_form(struct http_request *);
void http_populate_cookies(struct http_request *); void http_populate_cookies(struct http_request *);
int http_argument_get(struct http_request *, int http_argument_get(struct http_request *,
const char *, void **, void *, int); const char *, void **, void *, int);
int http_request_header_get(struct http_request *,
const char *, void **, void *, int);
void http_file_rewind(struct http_file *); void http_file_rewind(struct http_file *);
ssize_t http_file_read(struct http_file *, void *, size_t); ssize_t http_file_read(struct http_file *, void *, size_t);

View File

@ -103,7 +103,8 @@ extern int daemon(int, int);
#define KORE_DOMAINNAME_LEN 255 #define KORE_DOMAINNAME_LEN 255
#define KORE_PIDFILE_DEFAULT "kore.pid" #define KORE_PIDFILE_DEFAULT "kore.pid"
#define KORE_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA" #define KORE_DHPARAM_PATH PREFIX "/share/kore/ffdhe4096.pem"
#define KORE_DEFAULT_CIPHER_LIST "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256"
#if defined(KORE_DEBUG) #if defined(KORE_DEBUG)
#define kore_debug(...) \ #define kore_debug(...) \
@ -286,6 +287,9 @@ struct kore_runtime {
int type; int type;
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
int (*http_request)(void *, struct http_request *); int (*http_request)(void *, struct http_request *);
void (*http_request_free)(void *, struct http_request *);
void (*http_body_chunk)(void *,
struct http_request *, const void *, size_t);
int (*validator)(void *, struct http_request *, const void *); int (*validator)(void *, struct http_request *, const void *);
void (*wsconnect)(void *, struct connection *); void (*wsconnect)(void *, struct connection *);
void (*wsdisconnect)(void *, struct connection *); void (*wsdisconnect)(void *, struct connection *);
@ -294,6 +298,7 @@ struct kore_runtime {
#endif #endif
void (*execute)(void *); void (*execute)(void *);
int (*onload)(void *, int); int (*onload)(void *, int);
void (*signal)(void *, int);
void (*connect)(void *, struct connection *); void (*connect)(void *, struct connection *);
void (*configure)(void *, int, char **); void (*configure)(void *, int, char **);
}; };
@ -303,6 +308,37 @@ struct kore_runtime_call {
struct kore_runtime *runtime; struct kore_runtime *runtime;
}; };
#if !defined(KORE_NO_HTTP)
struct kore_route_params {
char *name;
int flags;
u_int8_t method;
struct kore_validator *validator;
TAILQ_ENTRY(kore_route_params) list;
};
struct kore_route {
char *path;
char *func;
int type;
int errors;
int methods;
regex_t rctx;
struct kore_domain *dom;
struct kore_auth *auth;
struct kore_runtime_call *rcall;
struct kore_runtime_call *on_free;
struct kore_runtime_call *on_headers;
struct kore_runtime_call *on_body_chunk;
TAILQ_HEAD(, kore_route_params) params;
TAILQ_ENTRY(kore_route) list;
};
#endif
struct kore_domain { struct kore_domain {
u_int16_t id; u_int16_t id;
int logerr; int logerr;
@ -326,7 +362,7 @@ struct kore_domain {
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
int x509_verify_depth; int x509_verify_depth;
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
TAILQ_HEAD(, kore_module_handle) handlers; TAILQ_HEAD(, kore_route) routes;
TAILQ_HEAD(, http_redirect) redirects; TAILQ_HEAD(, http_redirect) redirects;
#endif #endif
TAILQ_ENTRY(kore_domain) list; TAILQ_ENTRY(kore_domain) list;
@ -362,15 +398,6 @@ LIST_HEAD(kore_server_list, kore_server);
#define KORE_PARAMS_QUERY_STRING 0x0001 #define KORE_PARAMS_QUERY_STRING 0x0001
struct kore_handler_params {
char *name;
int flags;
u_int8_t method;
struct kore_validator *validator;
TAILQ_ENTRY(kore_handler_params) list;
};
#define KORE_AUTH_TYPE_COOKIE 1 #define KORE_AUTH_TYPE_COOKIE 1
#define KORE_AUTH_TYPE_HEADER 2 #define KORE_AUTH_TYPE_HEADER 2
#define KORE_AUTH_TYPE_REQUEST 3 #define KORE_AUTH_TYPE_REQUEST 3
@ -419,23 +446,6 @@ struct kore_module {
TAILQ_ENTRY(kore_module) list; TAILQ_ENTRY(kore_module) list;
}; };
#if !defined(KORE_NO_HTTP)
struct kore_module_handle {
char *path;
char *func;
int type;
int errors;
regex_t rctx;
struct kore_domain *dom;
struct kore_runtime_call *rcall;
struct kore_auth *auth;
int methods;
TAILQ_HEAD(, kore_handler_params) params;
TAILQ_ENTRY(kore_module_handle) list;
};
#endif
/* /*
* The workers get a 128KB log buffer per worker, and parent will fetch their * The workers get a 128KB log buffer per worker, and parent will fetch their
* logs when it reached at least 75% of that or if its been > 1 second since * logs when it reached at least 75% of that or if its been > 1 second since
@ -449,9 +459,17 @@ struct kore_alog_header {
u_int16_t loglen; u_int16_t loglen;
} __attribute__((packed)); } __attribute__((packed));
struct kore_privsep {
char *root;
char *runas;
int skip_runas;
int skip_chroot;
};
struct kore_worker { struct kore_worker {
u_int16_t id; u_int16_t id;
u_int16_t cpu; u_int16_t cpu;
int ready;
int running; int running;
#if defined(__linux__) #if defined(__linux__)
int tracing; int tracing;
@ -462,7 +480,8 @@ struct kore_worker {
u_int8_t has_lock; u_int8_t has_lock;
int restarted; int restarted;
u_int64_t time_locked; u_int64_t time_locked;
struct kore_module_handle *active_hdlr; struct kore_route *active_route;
struct kore_privsep *ps;
/* Used by the workers to store accesslogs. */ /* Used by the workers to store accesslogs. */
struct { struct {
@ -570,7 +589,6 @@ struct kore_buf {
struct kore_json { struct kore_json {
const u_int8_t *data; const u_int8_t *data;
int depth; int depth;
int error;
size_t length; size_t length;
size_t offset; size_t offset;
@ -588,7 +606,7 @@ struct kore_json_item {
char *string; char *string;
double number; double number;
int literal; int literal;
int64_t s64; int64_t integer;
u_int64_t u64; u_int64_t u64;
} data; } data;
@ -659,6 +677,7 @@ struct kore_timer {
#define KORE_MSG_CRL 9 #define KORE_MSG_CRL 9
#define KORE_MSG_ACCEPT_AVAILABLE 10 #define KORE_MSG_ACCEPT_AVAILABLE 10
#define KORE_PYTHON_SEND_OBJ 11 #define KORE_PYTHON_SEND_OBJ 11
#define KORE_MSG_WORKER_LOG 12
#define KORE_MSG_ACME_BASE 100 #define KORE_MSG_ACME_BASE 100
/* messages for applications should start at 201. */ /* messages for applications should start at 201. */
@ -693,6 +712,7 @@ extern char *config_file;
#endif #endif
extern pid_t kore_pid; extern pid_t kore_pid;
extern int kore_quit;
extern int kore_quiet; extern int kore_quiet;
extern int kore_debug; extern int kore_debug;
extern int skip_chroot; extern int skip_chroot;
@ -700,8 +720,6 @@ extern int skip_runas;
extern int kore_foreground; extern int kore_foreground;
extern char *kore_pidfile; extern char *kore_pidfile;
extern char *kore_root_path;
extern char *kore_runas_user;
extern char *kore_tls_cipher_list; extern char *kore_tls_cipher_list;
extern volatile sig_atomic_t sig_recv; extern volatile sig_atomic_t sig_recv;
@ -710,15 +728,16 @@ extern int tls_version;
extern DH *tls_dhparam; extern DH *tls_dhparam;
extern char *rand_file; extern char *rand_file;
extern int keymgr_active; extern int keymgr_active;
extern char *keymgr_runas_user;
extern char *keymgr_root_path; extern struct kore_privsep worker_privsep;
extern char *acme_runas_user; extern struct kore_privsep keymgr_privsep;
extern char *acme_root_path; extern struct kore_privsep acme_privsep;
extern u_int8_t nlisteners; extern u_int8_t nlisteners;
extern u_int16_t cpu_count; extern u_int16_t cpu_count;
extern u_int8_t worker_count; extern u_int8_t worker_count;
extern const char *kore_version; extern const char *kore_version;
extern const char *kore_build_date;
extern int worker_policy; extern int worker_policy;
extern u_int8_t worker_set_affinity; extern u_int8_t worker_set_affinity;
extern u_int32_t worker_rlimit_nofiles; extern u_int32_t worker_rlimit_nofiles;
@ -736,17 +755,19 @@ extern struct kore_server_list kore_servers;
void kore_signal(int); void kore_signal(int);
void kore_shutdown(void); void kore_shutdown(void);
void kore_signal_trap(int);
void kore_signal_setup(void); void kore_signal_setup(void);
void kore_proctitle(const char *); void kore_proctitle(const char *);
void kore_default_getopt(int, char **); void kore_default_getopt(int, char **);
void kore_worker_reap(void); void kore_worker_reap(void);
void kore_worker_init(void); int kore_worker_init(void);
void kore_worker_privsep(void);
void kore_worker_started(void);
void kore_worker_make_busy(void); void kore_worker_make_busy(void);
void kore_worker_shutdown(void); void kore_worker_shutdown(void);
void kore_worker_dispatch_signal(int); void kore_worker_dispatch_signal(int);
void kore_worker_privdrop(const char *, const char *); int kore_worker_spawn(u_int16_t, u_int16_t, u_int16_t);
void kore_worker_spawn(u_int16_t, u_int16_t, u_int16_t);
int kore_worker_keymgr_response_verify(struct kore_msg *, int kore_worker_keymgr_response_verify(struct kore_msg *,
const void *, struct kore_domain **); const void *, struct kore_domain **);
@ -845,6 +866,7 @@ int kore_connection_accept(struct listener *,
u_int64_t kore_time_ms(void); u_int64_t kore_time_ms(void);
void kore_log_init(void); void kore_log_init(void);
void kore_log_file(const char *);
#if defined(KORE_USE_PYTHON) #if defined(KORE_USE_PYTHON)
int kore_configure_setting(const char *, char *); int kore_configure_setting(const char *, char *);
@ -892,7 +914,11 @@ char *kore_read_line(FILE *, char *, size_t);
EVP_PKEY *kore_rsakey_load(const char *); EVP_PKEY *kore_rsakey_load(const char *);
EVP_PKEY *kore_rsakey_generate(const char *); EVP_PKEY *kore_rsakey_generate(const char *);
int kore_x509_issuer_name(struct connection *, char **, int);
int kore_x509_subject_name(struct connection *, char **, int); int kore_x509_subject_name(struct connection *, char **, int);
int kore_x509name_foreach(X509_NAME *, int, void *,
int (*)(void *, int, int, const char *,
const void *, size_t, int));
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
void kore_websocket_handshake(struct http_request *, void kore_websocket_handshake(struct http_request *,
@ -948,12 +974,16 @@ int kore_domain_attach(struct kore_domain *, struct kore_server *);
void kore_domain_tlsinit(struct kore_domain *, int, void kore_domain_tlsinit(struct kore_domain *, int,
const void *, size_t); const void *, size_t);
void kore_domain_crl_add(struct kore_domain *, const void *, size_t); void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
int kore_module_handler_new(struct kore_domain *, const char *, void kore_route_reload(void);
const char *, const char *, int); void kore_route_free(struct kore_route *);
void kore_module_handler_free(struct kore_module_handle *); void kore_route_callback(struct kore_route *, const char *);
struct kore_module_handle *kore_module_handler_find(struct http_request *,
struct kore_domain *); struct kore_route *kore_route_create(struct kore_domain *,
const char *, int);
int kore_route_lookup(struct http_request *,
struct kore_domain *, int, struct kore_route **);
#endif #endif
struct kore_runtime_call *kore_runtime_getcall(const char *); struct kore_runtime_call *kore_runtime_getcall(const char *);
@ -962,11 +992,16 @@ struct kore_module *kore_module_load(const char *,
void kore_runtime_execute(struct kore_runtime_call *); void kore_runtime_execute(struct kore_runtime_call *);
int kore_runtime_onload(struct kore_runtime_call *, int); int kore_runtime_onload(struct kore_runtime_call *, int);
void kore_runtime_signal(struct kore_runtime_call *, int);
void kore_runtime_configure(struct kore_runtime_call *, int, char **); void kore_runtime_configure(struct kore_runtime_call *, int, char **);
void kore_runtime_connect(struct kore_runtime_call *, struct connection *); void kore_runtime_connect(struct kore_runtime_call *, struct connection *);
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
int kore_runtime_http_request(struct kore_runtime_call *, int kore_runtime_http_request(struct kore_runtime_call *,
struct http_request *); struct http_request *);
void kore_runtime_http_request_free(struct kore_runtime_call *,
struct http_request *);
void kore_runtime_http_body_chunk(struct kore_runtime_call *,
struct http_request *, const void *, size_t);
int kore_runtime_validator(struct kore_runtime_call *, int kore_runtime_validator(struct kore_runtime_call *,
struct http_request *, const void *); struct http_request *, const void *);
void kore_runtime_wsconnect(struct kore_runtime_call *, struct connection *); void kore_runtime_wsconnect(struct kore_runtime_call *, struct connection *);
@ -1038,13 +1073,15 @@ void kore_buf_appendv(struct kore_buf *, const char *, va_list);
void kore_buf_replace_string(struct kore_buf *, void kore_buf_replace_string(struct kore_buf *,
const char *, const void *, size_t); const char *, const void *, size_t);
int kore_json_errno(void);
int kore_json_parse(struct kore_json *); int kore_json_parse(struct kore_json *);
void kore_json_cleanup(struct kore_json *); void kore_json_cleanup(struct kore_json *);
void kore_json_item_free(struct kore_json_item *); void kore_json_item_free(struct kore_json_item *);
void kore_json_init(struct kore_json *, const void *, size_t); void kore_json_init(struct kore_json *, const void *, size_t);
void kore_json_item_tobuf(struct kore_json_item *, struct kore_buf *); void kore_json_item_tobuf(struct kore_json_item *, struct kore_buf *);
void kore_json_item_attach(struct kore_json_item *, struct kore_json_item *);
const char *kore_json_strerror(struct kore_json *); const char *kore_json_strerror(void);
struct kore_json_item *kore_json_find(struct kore_json_item *, struct kore_json_item *kore_json_find(struct kore_json_item *,
const char *, u_int32_t); const char *, u_int32_t);
struct kore_json_item *kore_json_create_item(struct kore_json_item *, struct kore_json_item *kore_json_create_item(struct kore_json_item *,

View File

@ -21,6 +21,8 @@
#undef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE
#undef _XOPEN_SOURCE #undef _XOPEN_SOURCE
#define PY_SSIZE_T_CLEAN 1
#include <Python.h> #include <Python.h>
#include <frameobject.h> #include <frameobject.h>
@ -32,6 +34,7 @@ void kore_python_proc_reap(void);
int kore_python_coro_pending(void); int kore_python_coro_pending(void);
void kore_python_path(const char *); void kore_python_path(const char *);
void kore_python_coro_delete(void *); void kore_python_coro_delete(void *);
void kore_python_routes_resolve(void);
void kore_python_log_error(const char *); void kore_python_log_error(const char *);
PyObject *kore_python_callable(PyObject *, const char *); PyObject *kore_python_callable(PyObject *, const char *);
@ -48,8 +51,11 @@ extern const char *kore_pymodule;
extern struct kore_module_functions kore_python_module; extern struct kore_module_functions kore_python_module;
extern struct kore_runtime kore_python_runtime; extern struct kore_runtime kore_python_runtime;
#define KORE_PYTHON_SIGNAL_HOOK "koreapp.signal"
#define KORE_PYTHON_TEARDOWN_HOOK "koreapp.cleanup" #define KORE_PYTHON_TEARDOWN_HOOK "koreapp.cleanup"
#define KORE_PYTHON_CONFIG_HOOK "koreapp.configure" #define KORE_PYTHON_CONFIG_HOOK "koreapp.configure"
#define KORE_PYTHON_DAEMONIZED_HOOK "koreapp.daemonized" #define KORE_PYTHON_DAEMONIZED_HOOK "koreapp.daemonized"
#define KORE_PYTHON_WORKER_STOP_HOOK "koreapp.workerstop"
#define KORE_PYTHON_WORKER_START_HOOK "koreapp.workerstart"
#endif #endif

View File

@ -18,7 +18,7 @@
#define CORO_STATE_SUSPENDED 2 #define CORO_STATE_SUSPENDED 2
struct python_coro { struct python_coro {
u_int32_t id; u_int64_t id;
int state; int state;
int killed; int killed;
PyObject *obj; PyObject *obj;
@ -45,6 +45,8 @@ static PyObject *python_kore_queue(PyObject *, PyObject *);
static PyObject *python_kore_worker(PyObject *, PyObject *); static PyObject *python_kore_worker(PyObject *, PyObject *);
static PyObject *python_kore_tracer(PyObject *, PyObject *); static PyObject *python_kore_tracer(PyObject *, PyObject *);
static PyObject *python_kore_fatalx(PyObject *, PyObject *); static PyObject *python_kore_fatalx(PyObject *, PyObject *);
static PyObject *python_kore_task_id(PyObject *, PyObject *);
static PyObject *python_kore_sigtrap(PyObject *, PyObject *);
static PyObject *python_kore_setname(PyObject *, PyObject *); static PyObject *python_kore_setname(PyObject *, PyObject *);
static PyObject *python_kore_suspend(PyObject *, PyObject *); static PyObject *python_kore_suspend(PyObject *, PyObject *);
static PyObject *python_kore_shutdown(PyObject *, PyObject *); static PyObject *python_kore_shutdown(PyObject *, PyObject *);
@ -54,6 +56,7 @@ static PyObject *python_kore_task_kill(PyObject *, PyObject *);
static PyObject *python_kore_prerequest(PyObject *, PyObject *); static PyObject *python_kore_prerequest(PyObject *, PyObject *);
static PyObject *python_kore_task_create(PyObject *, PyObject *); static PyObject *python_kore_task_create(PyObject *, PyObject *);
static PyObject *python_kore_socket_wrap(PyObject *, PyObject *); static PyObject *python_kore_socket_wrap(PyObject *, PyObject *);
static PyObject *python_kore_route(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_timer(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_timer(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_domain(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_domain(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_gather(PyObject *, PyObject *, PyObject *); static PyObject *python_kore_gather(PyObject *, PyObject *, PyObject *);
@ -61,6 +64,9 @@ static PyObject *python_kore_sendobj(PyObject *, PyObject *,
PyObject *); PyObject *);
static PyObject *python_kore_server(PyObject *, PyObject *, static PyObject *python_kore_server(PyObject *, PyObject *,
PyObject *); PyObject *);
static PyObject *python_kore_privsep(PyObject *, PyObject *,
PyObject *);
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
static PyObject *python_kore_pgsql_query(PyObject *, PyObject *, static PyObject *python_kore_pgsql_query(PyObject *, PyObject *,
@ -92,6 +98,8 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("tracer", python_kore_tracer, METH_VARARGS), METHOD("tracer", python_kore_tracer, METH_VARARGS),
METHOD("fatal", python_kore_fatal, METH_VARARGS), METHOD("fatal", python_kore_fatal, METH_VARARGS),
METHOD("fatalx", python_kore_fatalx, METH_VARARGS), METHOD("fatalx", python_kore_fatalx, METH_VARARGS),
METHOD("task_id", python_kore_task_id, METH_NOARGS),
METHOD("sigtrap", python_kore_sigtrap, METH_VARARGS),
METHOD("setname", python_kore_setname, METH_VARARGS), METHOD("setname", python_kore_setname, METH_VARARGS),
METHOD("suspend", python_kore_suspend, METH_VARARGS), METHOD("suspend", python_kore_suspend, METH_VARARGS),
METHOD("shutdown", python_kore_shutdown, METH_NOARGS), METHOD("shutdown", python_kore_shutdown, METH_NOARGS),
@ -101,10 +109,12 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("prerequest", python_kore_prerequest, METH_VARARGS), METHOD("prerequest", python_kore_prerequest, METH_VARARGS),
METHOD("task_create", python_kore_task_create, METH_VARARGS), METHOD("task_create", python_kore_task_create, METH_VARARGS),
METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS), METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS),
METHOD("route", python_kore_route, METH_VARARGS | METH_KEYWORDS),
METHOD("timer", python_kore_timer, METH_VARARGS | METH_KEYWORDS), METHOD("timer", python_kore_timer, METH_VARARGS | METH_KEYWORDS),
METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS),
METHOD("server", python_kore_server, METH_VARARGS | METH_KEYWORDS), METHOD("server", python_kore_server, METH_VARARGS | METH_KEYWORDS),
METHOD("gather", python_kore_gather, METH_VARARGS | METH_KEYWORDS), METHOD("gather", python_kore_gather, METH_VARARGS | METH_KEYWORDS),
METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS), METHOD("privsep", python_kore_privsep, METH_VARARGS | METH_KEYWORDS),
METHOD("sendobj", python_kore_sendobj, METH_VARARGS | METH_KEYWORDS), METHOD("sendobj", python_kore_sendobj, METH_VARARGS | METH_KEYWORDS),
METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS), METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS),
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
@ -186,9 +196,38 @@ static PyTypeObject pyseccomp_type = {
}; };
#endif #endif
struct pyroute {
PyObject_HEAD
char *path;
PyObject *func;
PyObject *kwargs;
struct kore_domain *domain;
TAILQ_ENTRY(pyroute) list;
};
static PyObject *pyroute_inner(struct pyroute *, PyObject *);
static void pyroute_dealloc(struct pyroute *);
static PyMethodDef pyroute_methods[] = {
METHOD("inner", pyroute_inner, METH_VARARGS),
METHOD(NULL, NULL, -1)
};
static PyTypeObject pyroute_type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "kore.route",
.tp_doc = "kore route function",
.tp_methods = pyroute_methods,
.tp_basicsize = sizeof(struct pyroute),
.tp_dealloc = (destructor)pyroute_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
};
struct pydomain { struct pydomain {
PyObject_HEAD PyObject_HEAD
struct kore_domain *config; struct kore_domain *config;
struct kore_module_handle *next;
PyObject *kwargs;
}; };
static PyObject *pydomain_filemaps(struct pydomain *, PyObject *); static PyObject *pydomain_filemaps(struct pydomain *, PyObject *);
@ -659,11 +698,13 @@ static PyObject *pyconnection_get_fd(struct pyconnection *, void *);
static PyObject *pyconnection_get_addr(struct pyconnection *, void *); static PyObject *pyconnection_get_addr(struct pyconnection *, void *);
static PyObject *pyconnection_get_peer_x509(struct pyconnection *, void *); static PyObject *pyconnection_get_peer_x509(struct pyconnection *, void *);
static PyObject *pyconnection_get_peer_x509dict(struct pyconnection *, void *);
static PyGetSetDef pyconnection_getset[] = { static PyGetSetDef pyconnection_getset[] = {
GETTER("fd", pyconnection_get_fd), GETTER("fd", pyconnection_get_fd),
GETTER("addr", pyconnection_get_addr), GETTER("addr", pyconnection_get_addr),
GETTER("x509", pyconnection_get_peer_x509), GETTER("x509", pyconnection_get_peer_x509),
GETTER("x509dict", pyconnection_get_peer_x509dict),
GETTER(NULL, NULL), GETTER(NULL, NULL),
}; };
@ -741,8 +782,10 @@ static PyObject *pyhttp_get_path(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_body(struct pyhttp_request *, void *); static PyObject *pyhttp_get_body(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_agent(struct pyhttp_request *, void *); static PyObject *pyhttp_get_agent(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_method(struct pyhttp_request *, void *); static PyObject *pyhttp_get_method(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_protocol(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_body_path(struct pyhttp_request *, void *); static PyObject *pyhttp_get_body_path(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_connection(struct pyhttp_request *, void *); static PyObject *pyhttp_get_connection(struct pyhttp_request *, void *);
static PyObject *pyhttp_get_body_digest(struct pyhttp_request *, void *);
static PyGetSetDef pyhttp_request_getset[] = { static PyGetSetDef pyhttp_request_getset[] = {
GETTER("host", pyhttp_get_host), GETTER("host", pyhttp_get_host),
@ -750,7 +793,9 @@ static PyGetSetDef pyhttp_request_getset[] = {
GETTER("body", pyhttp_get_body), GETTER("body", pyhttp_get_body),
GETTER("agent", pyhttp_get_agent), GETTER("agent", pyhttp_get_agent),
GETTER("method", pyhttp_get_method), GETTER("method", pyhttp_get_method),
GETTER("protocol", pyhttp_get_protocol),
GETTER("body_path", pyhttp_get_body_path), GETTER("body_path", pyhttp_get_body_path),
GETTER("body_digest", pyhttp_get_body_digest),
GETTER("connection", pyhttp_get_connection), GETTER("connection", pyhttp_get_connection),
GETTER(NULL, NULL) GETTER(NULL, NULL)
}; };
@ -806,12 +851,16 @@ struct pycurl_slist {
LIST_ENTRY(pycurl_slist) list; LIST_ENTRY(pycurl_slist) list;
}; };
struct pycurl_data {
struct kore_curl curl;
LIST_HEAD(, pycurl_slist) slists;
};
struct pycurl_handle { struct pycurl_handle {
PyObject_HEAD PyObject_HEAD
struct kore_curl curl; char *url;
char *url; struct kore_buf *body;
struct kore_buf *body; struct pycurl_data data;
LIST_HEAD(, pycurl_slist) slists;
}; };
struct pycurl_handle_op { struct pycurl_handle_op {
@ -831,11 +880,11 @@ static PyObject *pycurl_handle_run(struct pycurl_handle *, PyObject *);
static PyObject *pycurl_handle_setopt(struct pycurl_handle *, PyObject *); static PyObject *pycurl_handle_setopt(struct pycurl_handle *, PyObject *);
static PyObject *pycurl_handle_setbody(struct pycurl_handle *, PyObject *); static PyObject *pycurl_handle_setbody(struct pycurl_handle *, PyObject *);
static PyObject *pycurl_handle_setopt_string(struct pycurl_handle *, static PyObject *pycurl_handle_setopt_string(struct pycurl_data *,
int, PyObject *); int, PyObject *);
static PyObject *pycurl_handle_setopt_long(struct pycurl_handle *, static PyObject *pycurl_handle_setopt_long(struct pycurl_data *,
int, PyObject *); int, PyObject *);
static PyObject *pycurl_handle_setopt_slist(struct pycurl_handle *, static PyObject *pycurl_handle_setopt_slist(struct pycurl_data *,
int, PyObject *); int, PyObject *);
static PyMethodDef pycurl_handle_methods[] = { static PyMethodDef pycurl_handle_methods[] = {
@ -879,6 +928,7 @@ struct pyhttp_client {
char *tlskey; char *tlskey;
char *tlscert; char *tlscert;
char *cabundle; char *cabundle;
PyObject *curlopt;
int tlsverify; int tlsverify;
}; };
@ -886,11 +936,12 @@ struct pyhttp_client_op {
PyObject_HEAD PyObject_HEAD
int state; int state;
int headers; int headers;
struct kore_curl curl;
struct python_coro *coro; struct python_coro *coro;
struct pyhttp_client *client; struct pyhttp_client *client;
struct pycurl_data data;
}; };
static PyObject *pyhttp_client_op_await(PyObject *); static PyObject *pyhttp_client_op_await(PyObject *);
static PyObject *pyhttp_client_op_iternext(struct pyhttp_client_op *); static PyObject *pyhttp_client_op_iternext(struct pyhttp_client_op *);

View File

@ -145,7 +145,7 @@
* KORE_SYSCALL_DENY_ERRNO(socket, EACCESS), * KORE_SYSCALL_DENY_ERRNO(socket, EACCESS),
* KORE_SYSCALL_DENY_ERRNO(ioctl, EACCESS), * KORE_SYSCALL_DENY_ERRNO(ioctl, EACCESS),
* KORE_SYSCALL_ALLOW(poll), * KORE_SYSCALL_ALLOW(poll),
* ); * )
*/ */
#define KORE_SECCOMP_FILTER(name, ...) \ #define KORE_SECCOMP_FILTER(name, ...) \
struct sock_filter _scfilt[] = { \ struct sock_filter _scfilt[] = { \

View File

@ -28,8 +28,8 @@ endif
OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z)
ifeq ("$(OSNAME)", "darwin") ifeq ("$(OSNAME)", "darwin")
CFLAGS+=-I/opt/local/include/ -I/usr/local/opt/openssl/include CFLAGS+=$(shell pkg-config openssl --cflags)
LDFLAGS+=-L/opt/local/lib -L/usr/local/opt/openssl/lib LDFLAGS+=$(shell pkg-config openssl --libs)
else ifeq ("$(OSNAME)", "linux") else ifeq ("$(OSNAME)", "linux")
CFLAGS+=-D_GNU_SOURCE=1 CFLAGS+=-D_GNU_SOURCE=1
endif endif

View File

@ -3,7 +3,7 @@
struct { struct {
const char *name; const char *name;
int value; int value;
PyObject *(*cb)(struct pycurl_handle *, int, PyObject *); PyObject *(*cb)(struct pycurl_data *, int, PyObject *);
} py_curlopt[] = { } py_curlopt[] = {
{ "CURLOPT_WRITEDATA", 1, NULL }, { "CURLOPT_WRITEDATA", 1, NULL },
{ "CURLOPT_URL", 2, pycurl_handle_setopt_string }, { "CURLOPT_URL", 2, pycurl_handle_setopt_string },

13
misc/ffdhe4096.pem Normal file
View File

@ -0,0 +1,13 @@
-----BEGIN DH PARAMETERS-----
MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
-----END DH PARAMETERS-----

View File

@ -2,7 +2,12 @@
# #
# Linux specific defines and system call maps. # Linux specific defines and system call maps.
PLATFORM=$(uname -m) if [ -z "$TARGET_PLATFORM" ]; then
PLATFORM=$(uname -m)
else
PLATFORM=$TARGET_PLATFORM
fi
BASE=$(dirname $0) BASE=$(dirname $0)
case "$PLATFORM" in case "$PLATFORM" in

View File

@ -18,6 +18,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <time.h> #include <time.h>
#include <inttypes.h>
#include <signal.h> #include <signal.h>
#include "kore.h" #include "kore.h"
@ -66,7 +67,7 @@ kore_accesslog(struct http_request *req)
size_t avail; size_t avail;
time_t curtime; time_t curtime;
int len, attempts; int len, attempts;
const char *ptr, *method, *cn, *referer; const char *ptr, *method, *http_version, *cn, *referer;
char addr[INET6_ADDRSTRLEN], *cn_value; char addr[INET6_ADDRSTRLEN], *cn_value;
switch (req->method) { switch (req->method) {
@ -93,6 +94,12 @@ kore_accesslog(struct http_request *req)
break; break;
} }
if (req->flags & HTTP_VERSION_1_0)
http_version = "HTTP/1.0";
if (req->flags & HTTP_VERSION_1_1)
http_version = "HTTP/1.1";
if (req->referer != NULL) if (req->referer != NULL)
referer = req->referer; referer = req->referer;
else else
@ -168,9 +175,9 @@ kore_accesslog(struct http_request *req)
worker->lb.offset += sizeof(*hdr); worker->lb.offset += sizeof(*hdr);
len = snprintf(worker->lb.buf + worker->lb.offset, avail, len = snprintf(worker->lb.buf + worker->lb.offset, avail,
"%s - %s [%s] \"%s %s HTTP/1.1\" %d %zu \"%s\" \"%s\"\n", "%s - %s [%s] \"%s %s %s\" %d %" PRIu64" \"%s\" \"%s\"\n",
addr, cn, tbuf, method, req->path, req->status, addr, cn, tbuf, method, req->path, http_version,
req->content_length, referer, req->agent); req->status, req->content_length, referer, req->agent);
if (len == -1) if (len == -1)
fatal("failed to create log entry"); fatal("failed to create log entry");
@ -189,7 +196,7 @@ kore_accesslog(struct http_request *req)
} }
hdr->loglen = len; hdr->loglen = len;
hdr->domain = req->hdlr->dom->id; hdr->domain = req->rt->dom->id;
worker->lb.offset += (size_t)len; worker->lb.offset += (size_t)len;
break; break;

View File

@ -265,10 +265,10 @@ static char *account_url = NULL;
static u_int8_t acme_alpn_name[] = static u_int8_t acme_alpn_name[] =
{ 0xa, 'a', 'c', 'm', 'e', '-', 't', 'l', 's', '/', '1' }; { 0xa, 'a', 'c', 'm', 'e', '-', 't', 'l', 's', '/', '1' };
struct kore_privsep acme_privsep;
int acme_domains = 0;
char *acme_email = NULL; char *acme_email = NULL;
char *acme_provider = NULL; char *acme_provider = NULL;
char *acme_root_path = NULL;
char *acme_runas_user = NULL;
u_int32_t acme_request_timeout = 8; u_int32_t acme_request_timeout = 8;
void void
@ -310,7 +310,7 @@ kore_acme_run(void)
#if defined(KORE_USE_PYTHON) #if defined(KORE_USE_PYTHON)
kore_msg_unregister(KORE_PYTHON_SEND_OBJ); kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
#endif #endif
kore_worker_privdrop(acme_runas_user, acme_root_path); kore_worker_privsep();
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
if (unveil("/etc/ssl/", "r") == -1) if (unveil("/etc/ssl/", "r") == -1)
@ -321,14 +321,10 @@ kore_acme_run(void)
http_init(); http_init();
if (!kore_quiet) {
kore_log(LOG_NOTICE,
"acme worker started (pid#%d)", worker->pid);
}
LIST_INIT(&orders); LIST_INIT(&orders);
LIST_INIT(&signops); LIST_INIT(&signops);
kore_worker_started();
acme_parse_directory(); acme_parse_directory();
while (quit != 1) { while (quit != 1) {
@ -434,7 +430,7 @@ kore_acme_tls_challenge_use_cert(SSL *ssl, struct kore_domain *dom)
return; return;
} }
kore_log(LOG_NOTICE, "[%s] acme-tls/1 challenge requested", kore_log(LOG_INFO, "[%s] acme-tls/1 challenge requested",
dom->domain); dom->domain);
if ((c = SSL_get_ex_data(ssl, 0)) == NULL) if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
@ -483,7 +479,7 @@ acme_parse_directory(void)
if (!kore_json_parse(&json)) { if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"failed to parse directory payload from ACME server (%s)", "failed to parse directory payload from ACME server (%s)",
kore_json_strerror(&json)); kore_json_strerror());
goto cleanup; goto cleanup;
} }
@ -688,7 +684,7 @@ acme_order_create_submit(struct acme_sign_op *op, struct kore_buf *payload)
if (!kore_json_parse(&json)) { if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"[%s] failed to parse order payload from ACME server (%s)", "[%s] failed to parse order payload from ACME server (%s)",
domain, kore_json_strerror(&json)); domain, kore_json_strerror());
goto cleanup; goto cleanup;
} }
@ -806,7 +802,7 @@ acme_order_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
if (!kore_json_parse(&json)) { if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"[%s] failed to parse order payload from ACME server (%s)", "[%s] failed to parse order payload from ACME server (%s)",
order->domain, kore_json_strerror(&json)); order->domain, kore_json_strerror());
goto cleanup; goto cleanup;
} }
@ -989,7 +985,7 @@ acme_order_remove(struct acme_order *order, const char *reason)
kore_free(auth); kore_free(auth);
} }
kore_log(LOG_NOTICE, "[%s] order removed (%s)", order->domain, reason); kore_log(LOG_INFO, "[%s] order removed (%s)", order->domain, reason);
if (strcmp(reason, "completed")) if (strcmp(reason, "completed"))
acme_order_retry(order->domain); acme_order_retry(order->domain);
@ -1224,7 +1220,7 @@ acme_order_auth_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
if (!kore_json_parse(&json)) { if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"[%s:auth] failed to parse payload from ACME server (%s)", "[%s:auth] failed to parse payload from ACME server (%s)",
order->domain, kore_json_strerror(&json)); order->domain, kore_json_strerror());
goto cleanup; goto cleanup;
} }
@ -1366,7 +1362,7 @@ cleanup:
} else { } else {
order->auths--; order->auths--;
if (order->auths == 0) { if (order->auths == 0) {
kore_log(LOG_NOTICE, kore_log(LOG_INFO,
"[%s:auth] authentications done", order->domain); "[%s:auth] authentications done", order->domain);
order->state = ACME_ORDER_STATE_RUNNING; order->state = ACME_ORDER_STATE_RUNNING;
} }
@ -1389,12 +1385,12 @@ acme_challenge_tls_alpn_01(struct acme_order *order,
acme_challenge_tls_alpn_01_create(order, challenge); acme_challenge_tls_alpn_01_create(order, challenge);
break; break;
case ACME_STATUS_PROCESSING: case ACME_STATUS_PROCESSING:
kore_log(LOG_NOTICE, kore_log(LOG_INFO,
"[%s:auth:challenge:tls-alpn-01] processing", "[%s:auth:challenge:tls-alpn-01] processing",
order->domain); order->domain);
break; break;
case ACME_STATUS_VALID: case ACME_STATUS_VALID:
kore_log(LOG_NOTICE, kore_log(LOG_INFO,
"[%s:auth:challenge:tls-alpn-01] valid", "[%s:auth:challenge:tls-alpn-01] valid",
order->domain); order->domain);
ret = KORE_RESULT_OK; ret = KORE_RESULT_OK;
@ -1419,7 +1415,7 @@ acme_challenge_tls_alpn_01_create(struct acme_order *order,
u_int8_t digest[SHA256_DIGEST_LENGTH]; u_int8_t digest[SHA256_DIGEST_LENGTH];
if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) { if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) {
kore_log(LOG_NOTICE, kore_log(LOG_INFO,
"[%s:auth:challenge:tls-alpn-01] pending keymgr", "[%s:auth:challenge:tls-alpn-01] pending keymgr",
order->domain); order->domain);
return; return;
@ -1427,7 +1423,7 @@ acme_challenge_tls_alpn_01_create(struct acme_order *order,
challenge->flags |= ACME_FLAG_CHALLENGE_CREATED; challenge->flags |= ACME_FLAG_CHALLENGE_CREATED;
kore_log(LOG_NOTICE, kore_log(LOG_INFO,
"[%s:auth:challenge:tls-alpn-01] requested from keymgr", "[%s:auth:challenge:tls-alpn-01] requested from keymgr",
order->domain); order->domain);

View File

@ -35,7 +35,7 @@ kore_auth_new(const char *name)
{ {
struct kore_auth *auth; struct kore_auth *auth;
if ((auth = kore_auth_lookup(name)) != NULL) if (kore_auth_lookup(name) != NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
auth = kore_malloc(sizeof(*auth)); auth = kore_malloc(sizeof(*auth));
@ -90,12 +90,12 @@ kore_auth_run(struct http_request *req, struct kore_auth *auth)
kore_debug("kore_auth_run() for %s failed", req->path); kore_debug("kore_auth_run() for %s failed", req->path);
if (auth->redirect == NULL) { if (auth->redirect == NULL) {
http_response(req, 403, NULL, 0); http_response(req, HTTP_STATUS_FORBIDDEN, NULL, 0);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
http_response_header(req, "location", auth->redirect); http_response_header(req, "location", auth->redirect);
http_response(req, 302, NULL, 0); http_response(req, HTTP_STATUS_FOUND, NULL, 0);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }

241
src/cli.c
View File

@ -187,9 +187,12 @@ static void cli_buildopt_kore_flavor(struct buildopt *,
const char *); const char *);
static void cli_buildopt_mime(struct buildopt *, const char *); static void cli_buildopt_mime(struct buildopt *, const char *);
static void cli_build_flags_common(struct buildopt *,
struct cli_buf *);
static void cli_flavor_load(void); static void cli_flavor_load(void);
static void cli_flavor_change(const char *); static void cli_flavor_change(const char *);
static void cli_kore_features(struct buildopt *, static void cli_kore_load_file(const char *, struct buildopt *,
char **, size_t *); char **, size_t *);
static void cli_run(int, char **); static void cli_run(int, char **);
@ -200,6 +203,10 @@ static void cli_clean(int, char **);
static void cli_source(int, char **); static void cli_source(int, char **);
static void cli_reload(int, char **); static void cli_reload(int, char **);
static void cli_flavor(int, char **); static void cli_flavor(int, char **);
static void cli_cflags(int, char **);
static void cli_ldflags(int, char **);
static void cli_genasset(int, char **);
static void cli_genasset_help(void);
#if !defined(KODEV_MINIMAL) #if !defined(KODEV_MINIMAL)
static void cli_create(int, char **); static void cli_create(int, char **);
@ -209,7 +216,6 @@ static void file_create_src(void);
static void file_create_config(void); static void file_create_config(void);
static void file_create_gitignore(void); static void file_create_gitignore(void);
static void file_create_python_src(void); static void file_create_python_src(void);
static void file_create_python_config(void);
static void cli_generate_certs(void); static void cli_generate_certs(void);
static void cli_file_create(const char *, const char *, size_t); static void cli_file_create(const char *, const char *, size_t);
@ -218,6 +224,7 @@ static void cli_file_create(const char *, const char *, size_t);
static struct cmd cmds[] = { static struct cmd cmds[] = {
{ "help", "this help text", cli_help }, { "help", "this help text", cli_help },
{ "run", "run an application (-fnr implied)", cli_run }, { "run", "run an application (-fnr implied)", cli_run },
{ "gen", "generate asset file for compilation", cli_genasset },
{ "reload", "reload the application (SIGHUP)", cli_reload }, { "reload", "reload the application (SIGHUP)", cli_reload },
{ "info", "show info on kore on this system", cli_info }, { "info", "show info on kore on this system", cli_info },
{ "build", "build an application", cli_build }, { "build", "build an application", cli_build },
@ -227,6 +234,8 @@ static struct cmd cmds[] = {
{ "create", "create a new application skeleton", cli_create }, { "create", "create a new application skeleton", cli_create },
#endif #endif
{ "flavor", "switch between build flavors", cli_flavor }, { "flavor", "switch between build flavors", cli_flavor },
{ "cflags", "show kore CFLAGS", cli_cflags },
{ "ldflags", "show kore LDFLAGS", cli_ldflags },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
@ -253,7 +262,6 @@ static const char *python_gen_dirs[] = {
static struct filegen python_gen_files[] = { static struct filegen python_gen_files[] = {
{ file_create_python_src }, { file_create_python_src },
{ file_create_python_config },
{ file_create_gitignore }, { file_create_gitignore },
{ NULL } { NULL }
}; };
@ -289,15 +297,16 @@ static const char *config_data =
"\n" "\n"
"load\t\t./%s.so\n" "load\t\t./%s.so\n"
"\n" "\n"
"tls_dhparam\tdh2048.pem\n"
"\n"
"domain * {\n" "domain * {\n"
"\tattach\t\ttls\n" "\tattach\t\ttls\n"
"\n" "\n"
"\tcertfile\tcert/server.pem\n" "\tcertfile\tcert/server.pem\n"
"\tcertkey\t\tcert/key.pem\n" "\tcertkey\t\tcert/key.pem\n"
"\n" "\n"
"\troute\t/\tpage\n" "\troute / {\n"
"\t\thandler page\n"
"\t}\n"
"\n"
"}\n"; "}\n";
static const char *build_data = static const char *build_data =
@ -336,51 +345,29 @@ static const char *build_data =
"# included if you build with the \"prod\" flavor.\n" "# included if you build with the \"prod\" flavor.\n"
"#}\n"; "#}\n";
static const char *python_config_data =
"# %s configuration\n"
"\n"
"server tls {\n"
"\tbind 127.0.0.1 8888\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"
"\troute\t/\tkoreapp.index\n"
"}\n";
static const char *python_init_data = static const char *python_init_data =
"from .app import koreapp\n"; "from .app import koreapp\n";
static const char *python_app_data = static const char *python_app_data =
"import kore\n" "import kore\n"
"\n" "\n"
"class App:\n" "class KoreApp:\n"
" def __init__(self):\n"
" pass\n"
"\n"
" def configure(self, args):\n" " def configure(self, args):\n"
" kore.config.file = \"kore.conf\"\n"
" kore.config.deployment = \"development\"\n" " kore.config.deployment = \"development\"\n"
" kore.server(\"default\", ip=\"127.0.0.1\", port=\"8888\")\n"
"\n"
" d = kore.domain(\"*\",\n"
" attach=\"default\",\n"
" key=\"cert/key.pem\",\n"
" cert=\"cert/server.pem\",\n"
" )\n"
"\n"
" d.route(\"/\", self.index, methods=[\"get\"])\n"
"\n" "\n"
" async def index(self, req):\n" " async def index(self, req):\n"
" req.response(200, b'')\n" " req.response(200, b'')\n"
"\n" "\n"
"koreapp = App()"; "koreapp = KoreApp()";
static const char *dh2048_data =
"-----BEGIN DH PARAMETERS-----\n"
"MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv\n"
"VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY\n"
"Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/\n"
"PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV\n"
"Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN\n"
"xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==\n"
"-----END DH PARAMETERS-----";
static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n"; static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n";
@ -400,6 +387,7 @@ static int source_files_count;
static int cxx_files_count; static int cxx_files_count;
static struct cmd *command = NULL; static struct cmd *command = NULL;
static int cflags_count = 0; static int cflags_count = 0;
static int genasset_cmd = 0;
static int cxxflags_count = 0; static int cxxflags_count = 0;
static int ldflags_count = 0; static int ldflags_count = 0;
static char *flavor = NULL; static char *flavor = NULL;
@ -546,8 +534,7 @@ cli_create(int argc, char **argv)
cli_generate_certs(); cli_generate_certs();
printf("%s created successfully!\n", appl); printf("%s created successfully!\n", appl);
printf("WARNING: DO NOT USE THE GENERATED DH PARAMETERS " printf("WARNING: DO NOT USE THE GENERATED CERTIFICATE IN PRODUCTION\n");
"AND CERTIFICATES IN PRODUCTION\n");
} }
#endif #endif
@ -742,9 +729,9 @@ cli_build(int argc, char **argv)
if (bopt->single_binary) { if (bopt->single_binary) {
requires_relink++; requires_relink++;
(void)cli_vasprintf(&sofile, "%s", appl); (void)cli_vasprintf(&sofile, "%s/%s", out_dir, appl);
} else { } else {
(void)cli_vasprintf(&sofile, "%s.so", appl); (void)cli_vasprintf(&sofile, "%s/%s.so", out_dir, appl);
} }
if (!cli_file_exists(sofile) && source_files_count > 0) if (!cli_file_exists(sofile) && source_files_count > 0)
@ -772,7 +759,8 @@ cli_source(int argc, char **argv)
static void static void
cli_clean(int argc, char **argv) cli_clean(int argc, char **argv)
{ {
char pwd[PATH_MAX], *sofile; struct buildopt *bopt;
char pwd[PATH_MAX], *bin;
if (cli_dir_exists(object_dir)) if (cli_dir_exists(object_dir))
cli_cleanup_files(object_dir); cli_cleanup_files(object_dir);
@ -781,11 +769,23 @@ cli_clean(int argc, char **argv)
fatal("could not get cwd: %s", errno_s); fatal("could not get cwd: %s", errno_s);
appl = basename(pwd); appl = basename(pwd);
(void)cli_vasprintf(&sofile, "%s.so", appl);
if (unlink(sofile) == -1 && errno != ENOENT)
printf("couldn't unlink %s: %s", sofile, errno_s);
free(sofile); TAILQ_INIT(&mime_types);
TAILQ_INIT(&build_options);
cli_flavor_load();
bopt = cli_buildopt_new("_default");
cli_buildopt_parse("conf/build.conf");
if (bopt->single_binary)
(void)cli_vasprintf(&bin, "%s/%s", out_dir, appl);
else
(void)cli_vasprintf(&bin, "%s/%s.so", out_dir, appl);
if (unlink(bin) == -1 && errno != ENOENT)
printf("couldn't unlink %s: %s", bin, errno_s);
free(bin);
} }
static void static void
@ -853,13 +853,101 @@ cli_info(int argc, char **argv)
printf("kore features\t %s\n", bopt->kore_flavor); printf("kore features\t %s\n", bopt->kore_flavor);
printf("kore source \t %s\n", bopt->kore_source); printf("kore source \t %s\n", bopt->kore_source);
} else { } else {
cli_kore_features(bopt, &features, &len); cli_kore_load_file("features", bopt, &features, &len);
printf("kore binary \t %s/bin/kore\n", prefix); printf("kore binary \t %s/bin/kore\n", prefix);
printf("kore features\t %.*s\n", (int)len, features); printf("kore features\t %.*s\n", (int)len, features);
free(features); free(features);
} }
} }
static void
cli_cflags(int argc, char **argv)
{
struct cli_buf *buf;
buf = cli_buf_alloc(128);
cli_build_flags_common(NULL, buf);
printf("%.*s\n", (int)buf->offset, buf->data);
cli_buf_free(buf);
}
static void
cli_ldflags(int argc, char **argv)
{
char *p;
size_t len;
cli_kore_load_file("linker", NULL, &p, &len);
printf("%.*s ", (int)len, p);
#if defined(__MACH__)
printf("-dynamiclib -undefined suppress -flat_namespace ");
#else
printf("-shared ");
#endif
printf("\n");
free(p);
}
static void
cli_genasset(int argc, char **argv)
{
struct stat st;
struct dirent dp;
char *hdr;
genasset_cmd = 1;
TAILQ_INIT(&build_options);
(void)cli_buildopt_new("_default");
if (getenv("KORE_OBJDIR") == NULL)
object_dir = out_dir;
if (argv[0] == NULL)
cli_genasset_help();
(void)cli_vasprintf(&hdr, "%s/assets.h", out_dir);
(void)unlink(hdr);
cli_file_open(hdr, O_CREAT | O_TRUNC | O_WRONLY, &s_fd);
cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n");
cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n");
if (stat(argv[0], &st) == -1)
fatal("%s: %s", argv[0], errno_s);
if (S_ISDIR(st.st_mode)) {
if (cli_dir_exists(argv[0]))
cli_find_files(argv[0], cli_build_asset);
} else if (S_ISREG(st.st_mode)) {
memset(&dp, 0, sizeof(dp));
dp.d_type = DT_REG;
(void)snprintf(dp.d_name, sizeof(dp.d_name), "%s",
basename(argv[0]));
cli_build_asset(argv[0], &dp);
} else {
fatal("%s is not a directory or regular file", argv[0]);
}
cli_file_writef(s_fd, "\n#endif\n");
cli_file_close(s_fd);
}
static void
cli_genasset_help(void)
{
printf("Usage: kodev genasset [source]\n");
printf("Synopsis:\n");
printf(" Generates asset file(s) to be used for compilation.\n");
printf(" The source can be a single file or directory.\n");
printf("\n");
printf("This command honors the KODEV_OUTPUT environment variable.\n");
printf("This command honors the KORE_OBJDIR environment variable.\n");
exit(1);
}
#if !defined(KODEV_MINIMAL) #if !defined(KODEV_MINIMAL)
static void static void
file_create_python_src(void) file_create_python_src(void)
@ -875,19 +963,6 @@ file_create_python_src(void)
free(name); free(name);
} }
static void
file_create_python_config(void)
{
int l;
char *name, *data;
(void)cli_vasprintf(&name, "%s/kore.conf", appl);
l = cli_vasprintf(&data, python_config_data, appl);
cli_file_create(name, data, l);
free(name);
free(data);
}
static void static void
file_create_src(void) file_create_src(void)
{ {
@ -1257,7 +1332,9 @@ cli_build_asset(char *fpath, struct dirent *dp)
*--ext = '.'; *--ext = '.';
/* Register the .c file now (cpath is free'd later). */ /* Register the .c file now (cpath is free'd later). */
cli_add_source_file(name, cpath, opath, &st, BUILD_C); if (genasset_cmd == 0)
cli_add_source_file(name, cpath, opath, &st, BUILD_C);
free(name); free(name);
} }
@ -1396,9 +1473,6 @@ cli_generate_certs(void)
RSA *kpair; RSA *kpair;
char issuer[64]; char issuer[64];
/* Write out DH parameters. */
cli_file_create("dh2048.pem", dh2048_data, strlen(dh2048_data));
/* Create new certificate. */ /* Create new certificate. */
if ((x509 = X509_new()) == NULL) if ((x509 = X509_new()) == NULL)
fatal("X509_new(): %s", ssl_errno_s); fatal("X509_new(): %s", ssl_errno_s);
@ -1616,10 +1690,8 @@ cli_run_kore_python(void)
fatal("could not get cwd: %s", errno_s); fatal("could not get cwd: %s", errno_s);
args[0] = cmd; args[0] = cmd;
args[1] = "-frnc"; args[1] = pwd;
args[2] = "kore.conf"; args[2] = NULL;
args[3] = pwd;
args[4] = NULL;
execvp(args[0], args); execvp(args[0], args);
fatal("failed to start '%s': %s", args[0], errno_s); fatal("failed to start '%s': %s", args[0], errno_s);
@ -1935,20 +2007,18 @@ cli_build_flags_common(struct buildopt *bopt, struct cli_buf *buf)
size_t len; size_t len;
char *data; char *data;
cli_buf_appendf(buf, "-fPIC -Isrc -Isrc/includes "); cli_buf_appendf(buf, "-fPIC ");
if (bopt->single_binary == 0) if (bopt != NULL)
cli_buf_appendf(buf, "-Isrc -Isrc/includes ");
if (bopt == NULL || bopt->single_binary == 0)
cli_buf_appendf(buf, "-I%s/include ", prefix); cli_buf_appendf(buf, "-I%s/include ", prefix);
else else
cli_buf_appendf(buf, "-I%s/include ", bopt->kore_source); cli_buf_appendf(buf, "-I%s/include ", bopt->kore_source);
#if defined(__MACH__) if (bopt == NULL || bopt->single_binary == 0) {
/* Add default openssl include path from homebrew / ports under OSX. */ cli_kore_load_file("features", bopt, &data, &len);
cli_buf_appendf(buf, "-I/opt/local/include ");
cli_buf_appendf(buf, "-I/usr/local/opt/openssl/include ");
#endif
if (bopt->single_binary == 0) {
cli_kore_features(bopt, &data, &len);
cli_buf_append(buf, data, len); cli_buf_append(buf, data, len);
cli_buf_appendf(buf, " "); cli_buf_appendf(buf, " ");
free(data); free(data);
@ -1976,7 +2046,7 @@ cli_build_cflags(struct buildopt *bopt)
} }
if (bopt->single_binary) { if (bopt->single_binary) {
cli_kore_features(bopt, &buf, &len); cli_kore_load_file("features", bopt, &buf, &len);
cli_buf_append(bopt->cflags, buf, len); cli_buf_append(bopt->cflags, buf, len);
cli_buf_appendf(bopt->cflags, " "); cli_buf_appendf(bopt->cflags, " ");
free(buf); free(buf);
@ -2106,16 +2176,17 @@ cli_flavor_load(void)
} }
static void static void
cli_kore_features(struct buildopt *bopt, char **out, size_t *outlen) cli_kore_load_file(const char *name, struct buildopt *bopt,
char **out, size_t *outlen)
{ {
int fd; int fd;
size_t len; size_t len;
char *path, *data; char *path, *data;
if (bopt->single_binary) { if (bopt != NULL && bopt->single_binary) {
(void)cli_vasprintf(&path, "%s/features", object_dir); (void)cli_vasprintf(&path, "%s/%s", object_dir, name);
} else { } else {
(void)cli_vasprintf(&path, "%s/share/kore/features", prefix); (void)cli_vasprintf(&path, "%s/share/kore/%s", prefix, name);
} }
cli_file_open(path, O_RDONLY, &fd); cli_file_open(path, O_RDONLY, &fd);
@ -2124,7 +2195,7 @@ cli_kore_features(struct buildopt *bopt, char **out, size_t *outlen)
free(path); free(path);
if (len == 0) if (len == 0)
fatal("features is empty"); fatal("%s is empty", name);
len--; len--;

File diff suppressed because it is too large Load Diff

View File

@ -258,6 +258,12 @@ kore_connection_handle(struct connection *c)
switch (c->state) { switch (c->state) {
case CONN_STATE_TLS_SHAKE: case CONN_STATE_TLS_SHAKE:
if (primary_dom == NULL) {
kore_log(LOG_NOTICE,
"TLS handshake but no TLS configured on server");
return (KORE_RESULT_ERROR);
}
if (primary_dom->ssl_ctx == NULL) { if (primary_dom->ssl_ctx == NULL) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"TLS configuration for %s not yet complete", "TLS configuration for %s not yet complete",

View File

@ -407,18 +407,17 @@ kore_curl_http_setup(struct kore_curl *client, int method, const void *data,
switch (method) { switch (method) {
case HTTP_METHOD_GET: case HTTP_METHOD_GET:
case HTTP_METHOD_OPTIONS:
break; break;
case HTTP_METHOD_HEAD: case HTTP_METHOD_HEAD:
curl_easy_setopt(client->handle, CURLOPT_NOBODY, 1); curl_easy_setopt(client->handle, CURLOPT_NOBODY, 1);
break; break;
case HTTP_METHOD_DELETE:
case HTTP_METHOD_OPTIONS:
break;
case HTTP_METHOD_PUT: case HTTP_METHOD_PUT:
has_body = 1; has_body = 1;
curl_easy_setopt(client->handle, CURLOPT_UPLOAD, 1); curl_easy_setopt(client->handle, CURLOPT_UPLOAD, 1);
break; break;
case HTTP_METHOD_PATCH: case HTTP_METHOD_PATCH:
case HTTP_METHOD_DELETE:
mname = http_method_text(method); mname = http_method_text(method);
/* fallthrough */ /* fallthrough */
case HTTP_METHOD_POST: case HTTP_METHOD_POST:

View File

@ -14,12 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/*
* XXX - Lots of OPENSSL ifdefs here for 1.0.2 and 1.1.0 release lines.
* The idea is to only support 1.1.1 down the line and remove the rest.
* (although we have to remain compat with 1.0.2 due to LibreSSL).
*/
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
@ -68,54 +62,8 @@ static int keymgr_rsa_privenc(int, const unsigned char *,
static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int, static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int,
const BIGNUM *, const BIGNUM *, EC_KEY *); const BIGNUM *, const BIGNUM *, EC_KEY *);
#if defined(KORE_OPENSSL_NEWER_API)
static RSA_METHOD *keymgr_rsa_meth = NULL; static RSA_METHOD *keymgr_rsa_meth = NULL;
static EC_KEY_METHOD *keymgr_ec_meth = NULL; static EC_KEY_METHOD *keymgr_ec_meth = NULL;
#else
/*
* Run own ecdsa_method data structure as OpenSSL has this in ecs_locl.h
* and does not export this on systems.
*/
struct ecdsa_method {
const char *name;
ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *,
int, const BIGNUM *, const BIGNUM *, EC_KEY *);
int (*ecdsa_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **,
BIGNUM **);
int (*ecdsa_do_verify)(const unsigned char *, int,
const ECDSA_SIG *, EC_KEY *);
int flags;
char *app_data;
};
#endif
#if !defined(KORE_OPENSSL_NEWER_API)
static ECDSA_METHOD keymgr_ecdsa = {
"kore ECDSA keymgr method",
keymgr_ecdsa_sign,
NULL,
NULL,
0,
NULL
};
static RSA_METHOD keymgr_rsa = {
"kore RSA keymgr method",
NULL,
NULL,
keymgr_rsa_privenc,
NULL,
NULL,
NULL,
keymgr_rsa_init,
keymgr_rsa_finish,
RSA_METHOD_FLAG_NO_CHECK,
NULL,
NULL,
NULL,
NULL
};
#endif
static u_int16_t domain_id = 0; static u_int16_t domain_id = 0;
static struct kore_domain *cached[KORE_DOMAIN_CACHE]; static struct kore_domain *cached[KORE_DOMAIN_CACHE];
@ -128,7 +76,6 @@ kore_domain_init(void)
for (i = 0; i < KORE_DOMAIN_CACHE; i++) for (i = 0; i < KORE_DOMAIN_CACHE; i++)
cached[i] = NULL; cached[i] = NULL;
#if defined(KORE_OPENSSL_NEWER_API)
if (keymgr_rsa_meth == NULL) { if (keymgr_rsa_meth == NULL) {
if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method", if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method",
RSA_METHOD_FLAG_NO_CHECK)) == NULL) RSA_METHOD_FLAG_NO_CHECK)) == NULL)
@ -145,7 +92,6 @@ kore_domain_init(void)
} }
EC_KEY_METHOD_set_sign(keymgr_ec_meth, NULL, NULL, keymgr_ecdsa_sign); EC_KEY_METHOD_set_sign(keymgr_ec_meth, NULL, NULL, keymgr_ecdsa_sign);
#endif
#if !defined(TLS1_3_VERSION) #if !defined(TLS1_3_VERSION)
if (!kore_quiet) { if (!kore_quiet) {
@ -159,7 +105,6 @@ kore_domain_init(void)
void void
kore_domain_cleanup(void) kore_domain_cleanup(void)
{ {
#if defined(KORE_OPENSSL_NEWER_API)
if (keymgr_rsa_meth != NULL) { if (keymgr_rsa_meth != NULL) {
RSA_meth_free(keymgr_rsa_meth); RSA_meth_free(keymgr_rsa_meth);
keymgr_rsa_meth = NULL; keymgr_rsa_meth = NULL;
@ -169,7 +114,6 @@ kore_domain_cleanup(void)
EC_KEY_METHOD_free(keymgr_ec_meth); EC_KEY_METHOD_free(keymgr_ec_meth);
keymgr_ec_meth = NULL; keymgr_ec_meth = NULL;
} }
#endif
} }
struct kore_domain * struct kore_domain *
@ -187,8 +131,8 @@ kore_domain_new(const char *domain)
dom->domain = kore_strdup(domain); dom->domain = kore_strdup(domain);
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
TAILQ_INIT(&(dom->handlers)); TAILQ_INIT(&dom->routes);
TAILQ_INIT(&(dom->redirects)); TAILQ_INIT(&dom->redirects);
#endif #endif
if (dom->id < KORE_DOMAIN_CACHE) { if (dom->id < KORE_DOMAIN_CACHE) {
@ -230,8 +174,8 @@ void
kore_domain_free(struct kore_domain *dom) kore_domain_free(struct kore_domain *dom)
{ {
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
struct kore_route *rt;
struct http_redirect *rdr; struct http_redirect *rdr;
struct kore_module_handle *hdlr;
#endif #endif
if (dom == NULL) if (dom == NULL)
return; return;
@ -246,20 +190,17 @@ kore_domain_free(struct kore_domain *dom)
if (dom->ssl_ctx != NULL) if (dom->ssl_ctx != NULL)
SSL_CTX_free(dom->ssl_ctx); SSL_CTX_free(dom->ssl_ctx);
if (dom->cafile != NULL)
kore_free(dom->cafile); kore_free(dom->cafile);
if (dom->certkey != NULL) kore_free(dom->certkey);
kore_free(dom->certkey); kore_free(dom->certfile);
if (dom->certfile != NULL) kore_free(dom->crlfile);
kore_free(dom->certfile);
if (dom->crlfile != NULL)
kore_free(dom->crlfile);
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
/* Drop all handlers associated with this domain */ /* Drop all handlers associated with this domain */
while ((hdlr = TAILQ_FIRST(&(dom->handlers))) != NULL) { while ((rt = TAILQ_FIRST(&dom->routes)) != NULL) {
TAILQ_REMOVE(&(dom->handlers), hdlr, list); TAILQ_REMOVE(&dom->routes, rt, list);
kore_module_handler_free(hdlr); kore_route_free(rt);
} }
while ((rdr = TAILQ_FIRST(&(dom->redirects))) != NULL) { while ((rdr = TAILQ_FIRST(&(dom->redirects))) != NULL) {
@ -283,35 +224,18 @@ kore_domain_tlsinit(struct kore_domain *dom, int type,
STACK_OF(X509_NAME) *certs; STACK_OF(X509_NAME) *certs;
EC_KEY *eckey; EC_KEY *eckey;
const SSL_METHOD *method; const SSL_METHOD *method;
#if !defined(KORE_OPENSSL_NEWER_API)
EC_KEY *ecdh;
#endif
kore_debug("kore_domain_tlsinit(%s)", dom->domain); kore_debug("kore_domain_tlsinit(%s)", dom->domain);
if (dom->ssl_ctx != NULL) if (dom->ssl_ctx != NULL)
SSL_CTX_free(dom->ssl_ctx); SSL_CTX_free(dom->ssl_ctx);
#if defined(KORE_OPENSSL_NEWER_API)
if ((method = TLS_method()) == NULL) if ((method = TLS_method()) == NULL)
fatalx("TLS_method(): %s", ssl_errno_s); fatalx("TLS_method(): %s", ssl_errno_s);
#else
switch (tls_version) {
case KORE_TLS_VERSION_1_3:
case KORE_TLS_VERSION_1_2:
case KORE_TLS_VERSION_BOTH:
method = TLSv1_2_server_method();
break;
default:
fatalx("unknown tls_version: %d", tls_version);
return;
}
#endif
if ((dom->ssl_ctx = SSL_CTX_new(method)) == NULL) if ((dom->ssl_ctx = SSL_CTX_new(method)) == NULL)
fatalx("SSL_ctx_new(): %s", ssl_errno_s); fatalx("SSL_ctx_new(): %s", ssl_errno_s);
#if defined(KORE_OPENSSL_NEWER_API)
if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx, TLS1_2_VERSION)) if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx, TLS1_2_VERSION))
fatalx("SSL_CTX_set_min_proto_version: %s", ssl_errno_s); fatalx("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
@ -346,7 +270,6 @@ kore_domain_tlsinit(struct kore_domain *dom, int type,
fatalx("unknown tls_version: %d", tls_version); fatalx("unknown tls_version: %d", tls_version);
return; return;
} }
#endif
switch (type) { switch (type) {
case KORE_PEM_CERT_CHAIN: case KORE_PEM_CERT_CHAIN:
@ -380,22 +303,13 @@ kore_domain_tlsinit(struct kore_domain *dom, int type,
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
fatalx("no RSA public key present"); fatalx("no RSA public key present");
RSA_set_app_data(rsa, dom); RSA_set_app_data(rsa, dom);
#if defined(KORE_OPENSSL_NEWER_API)
RSA_set_method(rsa, keymgr_rsa_meth); RSA_set_method(rsa, keymgr_rsa_meth);
#else
RSA_set_method(rsa, &keymgr_rsa);
#endif
break; break;
case EVP_PKEY_EC: case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
fatalx("no EC public key present"); fatalx("no EC public key present");
#if defined(KORE_OPENSSL_NEWER_API)
EC_KEY_set_ex_data(eckey, 0, dom); EC_KEY_set_ex_data(eckey, 0, dom);
EC_KEY_set_method(eckey, keymgr_ec_meth); EC_KEY_set_method(eckey, keymgr_ec_meth);
#else
ECDSA_set_ex_data(eckey, 0, dom);
ECDSA_set_method(eckey, &keymgr_ecdsa);
#endif
break; break;
default: default:
fatalx("unknown public key in certificate"); fatalx("unknown public key in certificate");
@ -410,21 +324,13 @@ kore_domain_tlsinit(struct kore_domain *dom, int type,
} }
if (tls_dhparam == NULL) if (tls_dhparam == NULL)
fatalx("No DH parameters given"); fatal("no DH parameters specified");
SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam); SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE);
#if defined(KORE_OPENSSL_NEWER_API)
if (!SSL_CTX_set_ecdh_auto(dom->ssl_ctx, 1)) if (!SSL_CTX_set_ecdh_auto(dom->ssl_ctx, 1))
fatalx("SSL_CTX_set_ecdh_auto: %s", ssl_errno_s); fatalx("SSL_CTX_set_ecdh_auto: %s", ssl_errno_s);
#else
if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL)
fatalx("EC_KEY_new_by_curve_name: %s", ssl_errno_s);
SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
EC_KEY_free(ecdh);
#endif
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION);
@ -605,27 +511,17 @@ keymgr_init(void)
if ((meth = RSA_get_default_method()) == NULL) if ((meth = RSA_get_default_method()) == NULL)
fatal("failed to obtain RSA method"); fatal("failed to obtain RSA method");
#if defined(KORE_OPENSSL_NEWER_API)
RSA_meth_set_pub_enc(keymgr_rsa_meth, RSA_meth_get_pub_enc(meth)); RSA_meth_set_pub_enc(keymgr_rsa_meth, RSA_meth_get_pub_enc(meth));
RSA_meth_set_pub_dec(keymgr_rsa_meth, RSA_meth_get_pub_dec(meth)); RSA_meth_set_pub_dec(keymgr_rsa_meth, RSA_meth_get_pub_dec(meth));
RSA_meth_set_bn_mod_exp(keymgr_rsa_meth, RSA_meth_get_bn_mod_exp(meth)); RSA_meth_set_bn_mod_exp(keymgr_rsa_meth, RSA_meth_get_bn_mod_exp(meth));
#else
keymgr_rsa.rsa_pub_enc = meth->rsa_pub_enc;
keymgr_rsa.rsa_pub_dec = meth->rsa_pub_dec;
keymgr_rsa.bn_mod_exp = meth->bn_mod_exp;
#endif
} }
static int static int
keymgr_rsa_init(RSA *rsa) keymgr_rsa_init(RSA *rsa)
{ {
if (rsa != NULL) { if (rsa != NULL) {
#if defined(KORE_OPENSSL_NEWER_API)
RSA_set_flags(rsa, RSA_flags(rsa) | RSA_set_flags(rsa, RSA_flags(rsa) |
RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK); RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK);
#else
rsa->flags |= RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK;
#endif
return (1); return (1);
} }
@ -702,13 +598,8 @@ keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
if (len > sizeof(keymgr_buf)) if (len > sizeof(keymgr_buf))
fatal("keymgr_buf too small"); fatal("keymgr_buf too small");
#if defined(KORE_OPENSSL_NEWER_API)
if ((dom = EC_KEY_get_ex_data(eckey, 0)) == NULL) if ((dom = EC_KEY_get_ex_data(eckey, 0)) == NULL)
fatal("EC_KEY has no domain"); fatal("EC_KEY has no domain");
#else
if ((dom = ECDSA_get_ex_data(eckey, 0)) == NULL)
fatal("EC_KEY has no domain");
#endif
memset(keymgr_buf, 0, sizeof(keymgr_buf)); memset(keymgr_buf, 0, sizeof(keymgr_buf));
req = (struct kore_keyreq *)keymgr_buf; req = (struct kore_keyreq *)keymgr_buf;
@ -890,23 +781,13 @@ domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
if (SSL_CTX_use_certificate(ctx, x) == 0) if (SSL_CTX_use_certificate(ctx, x) == 0)
return (NULL); return (NULL);
#if defined(KORE_OPENSSL_NEWER_API)
SSL_CTX_clear_chain_certs(ctx); SSL_CTX_clear_chain_certs(ctx);
#else
sk_X509_pop_free(ctx->extra_certs, X509_free);
ctx->extra_certs = NULL;
#endif
ERR_clear_error(); ERR_clear_error();
while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL) { while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL) {
/* ca its reference count won't be increased. */ /* ca its reference count won't be increased. */
#if defined(KORE_OPENSSL_NEWER_API)
if (SSL_CTX_add0_chain_cert(ctx, ca) == 0) if (SSL_CTX_add0_chain_cert(ctx, ca) == 0)
return (NULL); return (NULL);
#else
if (SSL_CTX_add_extra_chain_cert(ctx, ca) == 0)
return (NULL);
#endif
} }
err = ERR_peek_last_error(); err = ERR_peek_last_error();

View File

@ -58,7 +58,7 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root)
size_t sz; size_t sz;
struct stat st; struct stat st;
int len; int len;
struct kore_module_handle *hdlr; struct kore_route *rt;
struct filemap_entry *entry; struct filemap_entry *entry;
char regex[1024], fpath[PATH_MAX]; char regex[1024], fpath[PATH_MAX];
@ -69,9 +69,9 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root)
if (root[0] != '/' || root[sz - 1] != '/') if (root[0] != '/' || root[sz - 1] != '/')
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
if (kore_root_path != NULL) { if (worker_privsep.root != NULL) {
len = snprintf(fpath, sizeof(fpath), "%s/%s", len = snprintf(fpath, sizeof(fpath), "%s/%s",
kore_root_path, path); worker_privsep.root, path);
if (len == -1 || (size_t)len >= sizeof(fpath)) if (len == -1 || (size_t)len >= sizeof(fpath))
fatal("kore_filemap_create: failed to concat paths"); fatal("kore_filemap_create: failed to concat paths");
} else { } else {
@ -79,27 +79,21 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root)
fatal("kore_filemap_create: failed to copy path"); fatal("kore_filemap_create: failed to copy path");
} }
if (stat(fpath, &st) == -1) if (stat(fpath, &st) == -1) {
kore_log(LOG_ERR, "%s: failed to stat '%s': %s", __func__,
fpath, errno_s);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
}
len = snprintf(regex, sizeof(regex), "^%s.*$", root); len = snprintf(regex, sizeof(regex), "^%s.*$", root);
if (len == -1 || (size_t)len >= sizeof(regex)) if (len == -1 || (size_t)len >= sizeof(regex))
fatal("kore_filemap_create: buffer too small"); fatal("kore_filemap_create: buffer too small");
if (!kore_module_handler_new(dom, regex, "filemap_resolve", if ((rt = kore_route_create(dom, regex, HANDLER_TYPE_DYNAMIC)) == NULL)
NULL, HANDLER_TYPE_DYNAMIC))
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
hdlr = NULL; kore_route_callback(rt, "filemap_resolve");
TAILQ_FOREACH(hdlr, &dom->handlers, list) { rt->methods = HTTP_METHOD_GET | HTTP_METHOD_HEAD;
if (!strcmp(hdlr->path, regex))
break;
}
if (hdlr == NULL)
fatal("couldn't find newly created handler for filemap");
hdlr->methods = HTTP_METHOD_GET | HTTP_METHOD_HEAD;
entry = kore_calloc(1, sizeof(*entry)); entry = kore_calloc(1, sizeof(*entry));
entry->domain = dom; entry->domain = dom;
@ -151,7 +145,7 @@ filemap_resolve(struct http_request *req)
best_len = 0; best_len = 0;
TAILQ_FOREACH(entry, &maps, list) { TAILQ_FOREACH(entry, &maps, list) {
if (entry->domain != req->hdlr->dom) if (entry->domain != req->rt->dom)
continue; continue;
if (!strncmp(entry->root, req->path, entry->root_len)) { if (!strncmp(entry->root, req->path, entry->root_len)) {

View File

@ -79,7 +79,7 @@ kore_fileref_create(struct kore_server *srv, const char *path, int fd,
if (srv->tls == 0) { if (srv->tls == 0) {
ref->fd = fd; ref->fd = fd;
} else { } else {
if ((uintmax_t)size> SIZE_MAX) { if ((uintmax_t)size > SIZE_MAX) {
kore_pool_put(&ref_pool, ref); kore_pool_put(&ref_pool, ref);
return (NULL); return (NULL);
} }

1767
src/http.c

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,8 @@ static u_int8_t json_null_literal[] = { 'n', 'u', 'l', 'l' };
static u_int8_t json_true_literal[] = { 't', 'r', 'u', 'e' }; static u_int8_t json_true_literal[] = { 't', 'r', 'u', 'e' };
static u_int8_t json_false_literal[] = { 'f', 'a', 'l', 's', 'e' }; static u_int8_t json_false_literal[] = { 'f', 'a', 'l', 's', 'e' };
static int json_errno = 0;
static const char *json_errtab[] = { static const char *json_errtab[] = {
"no error", "no error",
"invalid JSON object", "invalid JSON object",
@ -84,8 +86,10 @@ kore_json_parse(struct kore_json *json)
if (json->root) if (json->root)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
json_errno = 0;
if (json_consume_whitespace(json) == -1) { if (json_consume_whitespace(json) == -1) {
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
@ -93,22 +97,22 @@ kore_json_parse(struct kore_json *json)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
if (!json_guess_type(ch, &type)) { if (!json_guess_type(ch, &type)) {
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
json->root = json_item_alloc(type, NULL, NULL); json->root = json_item_alloc(type, NULL, NULL);
if (!json->root->parse(json, json->root)) { if (!json->root->parse(json, json->root)) {
if (json->error == 0) if (json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
/* Don't allow garbage at the end. */ /* Don't allow garbage at the end. */
(void)json_consume_whitespace(json); (void)json_consume_whitespace(json);
if (json->offset != json->length) { if (json->offset != json->length) {
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
@ -122,16 +126,21 @@ kore_json_find(struct kore_json_item *root, const char *path, u_int32_t type)
char *copy; char *copy;
char *tokens[KORE_JSON_DEPTH_MAX + 1]; char *tokens[KORE_JSON_DEPTH_MAX + 1];
json_errno = 0;
copy = kore_strdup(path); copy = kore_strdup(path);
if (!kore_split_string(copy, "/", tokens, KORE_JSON_DEPTH_MAX)) { if (!kore_split_string(copy, "/", tokens, KORE_JSON_DEPTH_MAX)) {
kore_free(copy); kore_free(copy);
json_errno = KORE_JSON_ERR_INVALID_SEARCH;
return (NULL); return (NULL);
} }
item = json_find_item(root, tokens, type, 0); item = json_find_item(root, tokens, type, 0);
kore_free(copy); kore_free(copy);
if (item == NULL && json_errno == 0)
json_errno = KORE_JSON_ERR_INVALID_SEARCH;
return (item); return (item);
} }
@ -145,11 +154,17 @@ kore_json_cleanup(struct kore_json *json)
kore_json_item_free(json->root); kore_json_item_free(json->root);
} }
const char * int
kore_json_strerror(struct kore_json *json) kore_json_errno(void)
{ {
if (json->error >= 0 && json->error <= KORE_JSON_ERR_LAST) return (json_errno);
return (json_errtab[json->error]); }
const char *
kore_json_strerror(void)
{
if (json_errno >= 0 && json_errno <= KORE_JSON_ERR_LAST)
return (json_errtab[json_errno]);
return ("unknown JSON error"); return ("unknown JSON error");
} }
@ -182,7 +197,7 @@ kore_json_create_item(struct kore_json_item *parent, const char *name,
item->data.number = va_arg(args, double); item->data.number = va_arg(args, double);
break; break;
case KORE_JSON_TYPE_INTEGER: case KORE_JSON_TYPE_INTEGER:
item->data.s64 = va_arg(args, int64_t); item->data.integer = va_arg(args, int64_t);
break; break;
case KORE_JSON_TYPE_INTEGER_U64: case KORE_JSON_TYPE_INTEGER_U64:
item->data.u64 = va_arg(args, u_int64_t); item->data.u64 = va_arg(args, u_int64_t);
@ -248,7 +263,7 @@ kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
kore_buf_appendf(buf, "%f", item->data.number); kore_buf_appendf(buf, "%f", item->data.number);
break; break;
case KORE_JSON_TYPE_INTEGER: case KORE_JSON_TYPE_INTEGER:
kore_buf_appendf(buf, "%" PRId64, item->data.s64); kore_buf_appendf(buf, "%" PRId64, item->data.integer);
break; break;
case KORE_JSON_TYPE_INTEGER_U64: case KORE_JSON_TYPE_INTEGER_U64:
kore_buf_appendf(buf, "%" PRIu64, item->data.u64); kore_buf_appendf(buf, "%" PRIu64, item->data.u64);
@ -277,6 +292,24 @@ kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
} }
} }
void
kore_json_item_attach(struct kore_json_item *parent,
struct kore_json_item *item)
{
if (item->parent != NULL)
fatal("%s: item already has parent", __func__);
item->parent = parent;
if (parent->type != KORE_JSON_TYPE_OBJECT &&
parent->type != KORE_JSON_TYPE_ARRAY) {
fatal("%s: invalid parent type (%d)",
__func__, parent->type);
}
TAILQ_INSERT_TAIL(&parent->data.items, item, list);
}
static struct kore_json_item * static struct kore_json_item *
json_find_item(struct kore_json_item *object, char **tokens, json_find_item(struct kore_json_item *object, char **tokens,
u_int32_t type, int pos) u_int32_t type, int pos)
@ -321,15 +354,33 @@ json_find_item(struct kore_json_item *object, char **tokens,
break; break;
} }
if (nitem == NULL) if (nitem == NULL) {
json_errno = KORE_JSON_ERR_NOT_FOUND;
return (NULL); return (NULL);
}
item = nitem; item = nitem;
} }
if (tokens[pos + 1] == NULL) { if (tokens[pos + 1] == NULL) {
/*
* If an uint64 was required and we find an item
* with the same name but marked as an integer check
* if it can be represented as a uint64.
*
* If it can, reduce the type to integer so we match
* on it as well.
*/
if (type == KORE_JSON_TYPE_INTEGER_U64 &&
item->type == KORE_JSON_TYPE_INTEGER) {
if (item->data.integer >= 0)
type = KORE_JSON_TYPE_INTEGER;
}
if (item->type == type) if (item->type == type)
return (item); return (item);
json_errno = KORE_JSON_ERR_TYPE_MISMATCH;
return (NULL); return (NULL);
} }
@ -343,6 +394,9 @@ json_find_item(struct kore_json_item *object, char **tokens,
break; break;
} }
if (item == NULL && json_errno == 0)
json_errno = KORE_JSON_ERR_NOT_FOUND;
return (item); return (item);
} }
@ -443,7 +497,7 @@ static int
json_next_byte(struct kore_json *json, u_int8_t *ch, int peek) json_next_byte(struct kore_json *json, u_int8_t *ch, int peek)
{ {
if (json->offset >= json->length) { if (json->offset >= json->length) {
json->error = KORE_JSON_ERR_EOF; json_errno = KORE_JSON_ERR_EOF;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
@ -513,7 +567,7 @@ json_parse_object(struct kore_json *json, struct kore_json_item *object)
int ret, hasnext; int ret, hasnext;
if (json->depth++ >= KORE_JSON_DEPTH_MAX) { if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
json->error = KORE_JSON_ERR_DEPTH; json_errno = KORE_JSON_ERR_DEPTH;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
@ -537,7 +591,7 @@ json_parse_object(struct kore_json *json, struct kore_json_item *object)
switch (ch) { switch (ch) {
case '}': case '}':
if (hasnext) { if (hasnext) {
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
goto cleanup; goto cleanup;
} }
json->offset++; json->offset++;
@ -596,8 +650,8 @@ json_parse_object(struct kore_json *json, struct kore_json_item *object)
} }
cleanup: cleanup:
if (ret == KORE_RESULT_ERROR && json->error == 0) if (ret == KORE_RESULT_ERROR && json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_OBJECT; json_errno = KORE_JSON_ERR_INVALID_OBJECT;
json->depth--; json->depth--;
@ -614,7 +668,7 @@ json_parse_array(struct kore_json *json, struct kore_json_item *array)
int ret, hasnext; int ret, hasnext;
if (json->depth++ >= KORE_JSON_DEPTH_MAX) { if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
json->error = KORE_JSON_ERR_DEPTH; json_errno = KORE_JSON_ERR_DEPTH;
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
@ -637,7 +691,7 @@ json_parse_array(struct kore_json *json, struct kore_json_item *array)
if (ch == ']') { if (ch == ']') {
if (hasnext) { if (hasnext) {
json->error = KORE_JSON_ERR_INVALID_JSON; json_errno = KORE_JSON_ERR_INVALID_JSON;
goto cleanup; goto cleanup;
} }
json->offset++; json->offset++;
@ -675,8 +729,8 @@ json_parse_array(struct kore_json *json, struct kore_json_item *array)
} }
cleanup: cleanup:
if (ret == KORE_RESULT_ERROR && json->error == 0) if (ret == KORE_RESULT_ERROR && json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_ARRAY; json_errno = KORE_JSON_ERR_INVALID_ARRAY;
json->depth--; json->depth--;
@ -762,10 +816,14 @@ json_parse_number(struct kore_json *json, struct kore_json_item *number)
kore_strtodouble(str, -DBL_MAX, DBL_MAX, &ret); kore_strtodouble(str, -DBL_MAX, DBL_MAX, &ret);
break; break;
case KORE_JSON_TYPE_INTEGER: case KORE_JSON_TYPE_INTEGER:
number->data.s64 = (int64_t)kore_strtonum64(str, 1, &ret); number->data.integer = (int64_t)kore_strtonum64(str, 1, &ret);
break; break;
case KORE_JSON_TYPE_INTEGER_U64: case KORE_JSON_TYPE_INTEGER_U64:
number->data.s64 = kore_strtonum64(str, 0, &ret); number->data.u64 = kore_strtonum64(str, 0, &ret);
if (number->data.u64 <= INT64_MAX) {
type = KORE_JSON_TYPE_INTEGER;
number->data.integer = number->data.u64;
}
break; break;
default: default:
goto cleanup; goto cleanup;
@ -774,8 +832,8 @@ json_parse_number(struct kore_json *json, struct kore_json_item *number)
number->type = type; number->type = type;
cleanup: cleanup:
if (ret == KORE_RESULT_ERROR && json->error == 0) if (ret == KORE_RESULT_ERROR && json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_NUMBER; json_errno = KORE_JSON_ERR_INVALID_NUMBER;
return (ret); return (ret);
} }
@ -826,8 +884,8 @@ json_parse_literal(struct kore_json *json, struct kore_json_item *literal)
ret = KORE_RESULT_OK; ret = KORE_RESULT_OK;
cleanup: cleanup:
if (ret == KORE_RESULT_ERROR && json->error == 0) if (ret == KORE_RESULT_ERROR && json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_LITERAL; json_errno = KORE_JSON_ERR_INVALID_LITERAL;
return (ret); return (ret);
} }
@ -895,8 +953,8 @@ json_get_string(struct kore_json *json)
res = kore_buf_stringify(&json->tmpbuf, NULL); res = kore_buf_stringify(&json->tmpbuf, NULL);
cleanup: cleanup:
if (res == NULL && json->error == 0) if (res == NULL && json_errno == 0)
json->error = KORE_JSON_ERR_INVALID_STRING; json_errno = KORE_JSON_ERR_INVALID_STRING;
return (res); return (res);
} }

View File

@ -423,13 +423,13 @@ jsonrpc_error(struct jsonrpc_request *req, int code, const char *msg)
http_response_header(req->http, "content-type", "application/json"); http_response_header(req->http, "content-type", "application/json");
yajl_gen_get_buf(req->gen, &body, &body_len); yajl_gen_get_buf(req->gen, &body, &body_len);
succeeded: succeeded:
http_response(req->http, 200, body, body_len); http_response(req->http, HTTP_STATUS_OK, body, body_len);
if (req->gen != NULL) if (req->gen != NULL)
yajl_gen_clear(req->gen); yajl_gen_clear(req->gen);
jsonrpc_destroy_request(req); jsonrpc_destroy_request(req);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
failed: failed:
http_response(req->http, 500, NULL, 0); http_response(req->http, HTTP_STATUS_INTERNAL_ERROR, NULL, 0);
jsonrpc_destroy_request(req); jsonrpc_destroy_request(req);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -466,13 +466,13 @@ jsonrpc_result(struct jsonrpc_request *req,
http_response_header(req->http, "content-type", "application/json"); http_response_header(req->http, "content-type", "application/json");
yajl_gen_get_buf(req->gen, &body, &body_len); yajl_gen_get_buf(req->gen, &body, &body_len);
succeeded: succeeded:
http_response(req->http, 200, body, body_len); http_response(req->http, HTTP_STATUS_OK, body, body_len);
if (req->gen != NULL) if (req->gen != NULL)
yajl_gen_clear(req->gen); yajl_gen_clear(req->gen);
jsonrpc_destroy_request(req); jsonrpc_destroy_request(req);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
failed: failed:
http_response(req->http, 500, NULL, 0); http_response(req->http, HTTP_STATUS_INTERNAL_ERROR, NULL, 0);
jsonrpc_destroy_request(req); jsonrpc_destroy_request(req);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }

View File

@ -87,6 +87,9 @@ static struct sock_filter filter_keymgr[] = {
KORE_SYSCALL_ALLOW(fstat), KORE_SYSCALL_ALLOW(fstat),
#if defined(SYS_fstat64) #if defined(SYS_fstat64)
KORE_SYSCALL_ALLOW(fstat64), KORE_SYSCALL_ALLOW(fstat64),
#endif
#if defined(SYS_newfstatat)
KORE_SYSCALL_ALLOW(newfstatat),
#endif #endif
KORE_SYSCALL_ALLOW(futex), KORE_SYSCALL_ALLOW(futex),
KORE_SYSCALL_ALLOW(writev), KORE_SYSCALL_ALLOW(writev),
@ -137,6 +140,9 @@ static struct sock_filter filter_keymgr[] = {
#endif #endif
#if defined(SYS_mmap2) #if defined(SYS_mmap2)
KORE_SYSCALL_ALLOW(mmap2), KORE_SYSCALL_ALLOW(mmap2),
#endif
#if defined(SYS_madvise)
KORE_SYSCALL_ALLOW(madvise),
#endif #endif
KORE_SYSCALL_ALLOW(munmap), KORE_SYSCALL_ALLOW(munmap),
KORE_SYSCALL_ALLOW(clock_gettime), KORE_SYSCALL_ALLOW(clock_gettime),
@ -245,9 +251,8 @@ static void keymgr_rsa_encrypt(struct kore_msg *, const void *,
static void keymgr_ecdsa_sign(struct kore_msg *, const void *, static void keymgr_ecdsa_sign(struct kore_msg *, const void *,
struct key *); struct key *);
int keymgr_active = 0; struct kore_privsep keymgr_privsep;
char *keymgr_root_path = NULL; int keymgr_active = 0;
char *keymgr_runas_user = NULL;
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
#if defined(KORE_USE_ACME) #if defined(KORE_USE_ACME)
@ -290,10 +295,7 @@ kore_keymgr_run(void)
#if defined(KORE_USE_PYTHON) #if defined(KORE_USE_PYTHON)
kore_msg_unregister(KORE_PYTHON_SEND_OBJ); kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
#endif #endif
kore_worker_privdrop(keymgr_runas_user, keymgr_root_path); kore_worker_privsep();
if (!kore_quiet)
kore_log(LOG_NOTICE, "key manager started (pid#%d)", getpid());
if (rand_file != NULL) { if (rand_file != NULL) {
keymgr_load_randfile(); keymgr_load_randfile();
@ -318,6 +320,8 @@ kore_keymgr_run(void)
X509V3_EXT_add_alias(acme_oid, NID_subject_key_identifier); X509V3_EXT_add_alias(acme_oid, NID_subject_key_identifier);
#endif #endif
kore_worker_started();
while (quit != 1) { while (quit != 1) {
now = kore_time_ms(); now = kore_time_ms();
if ((now - last_seed) > RAND_POLL_INTERVAL) { if ((now - last_seed) > RAND_POLL_INTERVAL) {
@ -363,9 +367,6 @@ kore_keymgr_cleanup(int final)
{ {
struct key *key, *next; struct key *key, *next;
if (final && !kore_quiet)
kore_log(LOG_NOTICE, "cleaning up keys");
if (initialized == 0) if (initialized == 0)
return; return;
@ -574,7 +575,8 @@ keymgr_load_domain_privatekey(struct kore_domain *dom)
key->dom = dom; key->dom = dom;
kore_log(LOG_INFO, "loaded private key for '%s'", dom->domain); if (!kore_quiet)
kore_log(LOG_INFO, "loaded private key for '%s'", dom->domain);
} }
static struct key * static struct key *
@ -690,12 +692,8 @@ keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
u_int8_t buf[1024]; u_int8_t buf[1024];
req = (const struct kore_keyreq *)data; req = (const struct kore_keyreq *)data;
#if defined(KORE_OPENSSL_NEWER_API)
rsa = EVP_PKEY_get0_RSA(key->pkey); rsa = EVP_PKEY_get0_RSA(key->pkey);
#else
rsa = key->pkey->pkey.rsa;
#endif
keylen = RSA_size(rsa); keylen = RSA_size(rsa);
if (req->data_len > keylen || keylen > sizeof(buf)) if (req->data_len > keylen || keylen > sizeof(buf))
return; return;
@ -718,11 +716,8 @@ keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
u_int8_t sig[1024]; u_int8_t sig[1024];
req = (const struct kore_keyreq *)data; req = (const struct kore_keyreq *)data;
#if defined(KORE_OPENSSL_NEWER_API)
ec = EVP_PKEY_get0_EC_KEY(key->pkey); ec = EVP_PKEY_get0_EC_KEY(key->pkey);
#else
ec = key->pkey->pkey.ec;
#endif
len = ECDSA_size(ec); len = ECDSA_size(ec);
if (req->data_len > len || len > sizeof(sig)) if (req->data_len > len || len > sizeof(sig))
return; return;
@ -791,21 +786,15 @@ keymgr_acme_init(void)
ACME_RENEWAL_TIMER, NULL, 0); ACME_RENEWAL_TIMER, NULL, 0);
if (key->pkey == NULL) { if (key->pkey == NULL) {
kore_log(LOG_NOTICE, "generating new ACME account key"); kore_log(LOG_INFO, "generating new ACME account key");
key->pkey = kore_rsakey_generate(KORE_ACME_ACCOUNT_KEY); key->pkey = kore_rsakey_generate(KORE_ACME_ACCOUNT_KEY);
needsreg = 1; needsreg = 1;
} else { } else {
kore_log(LOG_INFO, "loaded existing ACME account key"); kore_log(LOG_INFO, "loaded existing ACME account key");
} }
#if defined(KORE_OPENSSL_NEWER_API)
rsa = EVP_PKEY_get0_RSA(key->pkey); rsa = EVP_PKEY_get0_RSA(key->pkey);
RSA_get0_key(rsa, &bn, &be, NULL); RSA_get0_key(rsa, &bn, &be, NULL);
#else
rsa = key->pkey->pkey.rsa;
be = rsa->e;
bn = rsa->n;
#endif
e = keymgr_bignum_base64(be); e = keymgr_bignum_base64(be);
n = keymgr_bignum_base64(bn); n = keymgr_bignum_base64(bn);
@ -837,7 +826,7 @@ keymgr_acme_domainkey(struct kore_domain *dom, struct key *key)
{ {
char *p; char *p;
kore_log(LOG_NOTICE, "generated new domain key for %s", dom->domain); kore_log(LOG_INFO, "generated new domain key for %s", dom->domain);
if ((p = strrchr(dom->certkey, '/')) == NULL) if ((p = strrchr(dom->certkey, '/')) == NULL)
fatalx("invalid certkey path '%s'", dom->certkey); fatalx("invalid certkey path '%s'", dom->certkey);
@ -1038,7 +1027,7 @@ keymgr_acme_install_cert(const void *data, size_t len, struct key *key)
fd = open(key->dom->certfile, O_CREAT | O_TRUNC | O_WRONLY, 0700); fd = open(key->dom->certfile, O_CREAT | O_TRUNC | O_WRONLY, 0700);
if (fd == -1) if (fd == -1)
fatal("open(%s): %s", key->dom->certfile, errno_s); fatalx("open(%s): %s", key->dom->certfile, errno_s);
kore_log(LOG_INFO, "writing %zu bytes of data", len); kore_log(LOG_INFO, "writing %zu bytes of data", len);
@ -1047,14 +1036,14 @@ keymgr_acme_install_cert(const void *data, size_t len, struct key *key)
if (ret == -1) { if (ret == -1) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
fatal("write(%s): %s", key->dom->certfile, errno_s); fatalx("write(%s): %s", key->dom->certfile, errno_s);
} }
break; break;
} }
if ((size_t)ret != len) { if ((size_t)ret != len) {
fatal("incorrect write on %s (%zd/%zu)", fatalx("incorrect write on %s (%zd/%zu)",
key->dom->certfile, ret, len); key->dom->certfile, ret, len);
} }
@ -1111,7 +1100,7 @@ keymgr_acme_challenge_cert(const void *data, size_t len, struct key *key)
slen = snprintf(hex + (idx * 2), sizeof(hex) - (idx * 2), slen = snprintf(hex + (idx * 2), sizeof(hex) - (idx * 2),
"%02x", digest[idx]); "%02x", digest[idx]);
if (slen == -1 || (size_t)slen >= sizeof(hex)) if (slen == -1 || (size_t)slen >= sizeof(hex))
fatal("failed to convert digest to hex"); fatalx("failed to convert digest to hex");
} }
if ((x509 = X509_new()) == NULL) if ((x509 = X509_new()) == NULL)
@ -1185,7 +1174,7 @@ keymgr_acme_csr(const struct kore_keyreq *req, struct key *key)
kore_log(LOG_INFO, "[%s] creating CSR", req->domain); kore_log(LOG_INFO, "[%s] creating CSR", req->domain);
if ((csr = X509_REQ_new()) == NULL) if ((csr = X509_REQ_new()) == NULL)
fatal("X509_REQ_new: %s", ssl_errno_s); fatalx("X509_REQ_new: %s", ssl_errno_s);
if (!X509_REQ_set_version(csr, 3)) if (!X509_REQ_set_version(csr, 3))
fatalx("X509_REQ_set_version(): %s", ssl_errno_s); fatalx("X509_REQ_set_version(): %s", ssl_errno_s);

View File

@ -54,6 +54,7 @@ volatile sig_atomic_t sig_recv;
struct kore_server_list kore_servers; struct kore_server_list kore_servers;
u_int8_t nlisteners; u_int8_t nlisteners;
int kore_argc = 0; int kore_argc = 0;
int kore_quit = 0;
pid_t kore_pid = -1; pid_t kore_pid = -1;
u_int16_t cpu_count = 1; u_int16_t cpu_count = 1;
int kore_debug = 0; int kore_debug = 0;
@ -64,12 +65,12 @@ u_int8_t worker_count = 0;
char **kore_argv = NULL; char **kore_argv = NULL;
int kore_foreground = 0; int kore_foreground = 0;
char *kore_progname = NULL; char *kore_progname = NULL;
char *kore_root_path = NULL;
char *kore_runas_user = NULL;
u_int32_t kore_socket_backlog = 5000; u_int32_t kore_socket_backlog = 5000;
char *kore_pidfile = KORE_PIDFILE_DEFAULT; char *kore_pidfile = KORE_PIDFILE_DEFAULT;
char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST; char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST;
struct kore_privsep worker_privsep;
extern char **environ; extern char **environ;
extern char *__progname; extern char *__progname;
static size_t proctitle_maxlen = 0; static size_t proctitle_maxlen = 0;
@ -80,6 +81,7 @@ static void version(void);
static void kore_write_kore_pid(void); static void kore_write_kore_pid(void);
static void kore_proctitle_setup(void); static void kore_proctitle_setup(void);
static void kore_server_sslstart(void); static void kore_server_sslstart(void);
static void kore_server_shutdown(void);
static void kore_server_start(int, char *[]); static void kore_server_start(int, char *[]);
static void kore_call_parent_configure(int, char **); static void kore_call_parent_configure(int, char **);
@ -113,9 +115,9 @@ usage(void)
#endif #endif
printf("\t-f\tstart in foreground\n"); printf("\t-f\tstart in foreground\n");
printf("\t-h\tthis help text\n"); printf("\t-h\tthis help text\n");
printf("\t-n\tdo not chroot\n"); printf("\t-n\tdo not chroot on any worker\n");
printf("\t-q\tonly log errors\n"); printf("\t-q\tonly log errors\n");
printf("\t-r\tdo not drop privileges\n"); printf("\t-r\tdo not change user on any worker\n");
printf("\t-v\tdisplay %s build information\n", __progname); printf("\t-v\tdisplay %s build information\n", __progname);
printf("\nFind more information on https://kore.io\n"); printf("\nFind more information on https://kore.io\n");
@ -168,6 +170,9 @@ main(int argc, char *argv[])
#endif #endif
kore_mem_init(); kore_mem_init();
kore_msg_init();
kore_log_init();
kore_progname = kore_strdup(argv[0]); kore_progname = kore_strdup(argv[0]);
kore_proctitle_setup(); kore_proctitle_setup();
@ -194,10 +199,6 @@ main(int argc, char *argv[])
if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
fatal("%s: not a directory or file", kore_pymodule); fatal("%s: not a directory or file", kore_pymodule);
} }
#elif !defined(KORE_SINGLE_BINARY)
if (argc > 0)
fatal("did you mean to run `kodev' instead?");
#endif #endif
kore_pid = getpid(); kore_pid = getpid();
@ -205,8 +206,6 @@ main(int argc, char *argv[])
LIST_INIT(&kore_servers); LIST_INIT(&kore_servers);
kore_platform_init(); kore_platform_init();
kore_log_init();
kore_msg_init();
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
http_parent_init(); http_parent_init();
#if defined(KORE_USE_CURL) #if defined(KORE_USE_CURL)
@ -274,11 +273,7 @@ main(int argc, char *argv[])
kore_signal_setup(); kore_signal_setup();
kore_server_start(argc, argv); kore_server_start(argc, argv);
kore_server_shutdown();
if (!kore_quiet)
kore_log(LOG_NOTICE, "server shutting down");
kore_worker_shutdown();
rcall = kore_runtime_getcall(parent_teardown_hook); rcall = kore_runtime_getcall(parent_teardown_hook);
if (rcall != NULL) { if (rcall != NULL) {
@ -292,7 +287,7 @@ main(int argc, char *argv[])
kore_server_cleanup(); kore_server_cleanup();
if (!kore_quiet) if (!kore_quiet)
kore_log(LOG_NOTICE, "goodbye"); kore_log(LOG_INFO, "goodbye");
#if defined(KORE_USE_PYTHON) #if defined(KORE_USE_PYTHON)
kore_python_cleanup(); kore_python_cleanup();
@ -497,6 +492,15 @@ kore_server_bind_unix(struct kore_server *srv, const char *path,
if (!kore_listener_init(l, AF_UNIX, ccb)) if (!kore_listener_init(l, AF_UNIX, ccb))
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
if (sun.sun_path[0] != '\0') {
if (unlink(sun.sun_path) == -1 && errno != ENOENT) {
kore_log(LOG_ERR, "unlink: %s: %s",
sun.sun_path, errno_s);
kore_listener_free(l);
return (KORE_RESULT_ERROR);
}
}
if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) { if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) {
kore_log(LOG_ERR, "bind: %s", errno_s); kore_log(LOG_ERR, "bind: %s", errno_s);
kore_listener_free(l); kore_listener_free(l);
@ -545,10 +549,10 @@ kore_server_finalize(struct kore_server *srv)
proto = "http"; proto = "http";
if (l->family == AF_UNIX) { if (l->family == AF_UNIX) {
kore_log(LOG_NOTICE, "%s serving %s on %s", kore_log(LOG_INFO, "%s serving %s on %s",
srv->name, proto, l->host); srv->name, proto, l->host);
} else { } else {
kore_log(LOG_NOTICE, "%s serving %s on %s:%s", kore_log(LOG_INFO, "%s serving %s on %s:%s",
srv->name, proto, l->host, l->port); srv->name, proto, l->host, l->port);
} }
} }
@ -657,11 +661,30 @@ kore_server_free(struct kore_server *srv)
void void
kore_listener_free(struct listener *l) kore_listener_free(struct listener *l)
{ {
int rm;
LIST_REMOVE(l, list); LIST_REMOVE(l, list);
if (l->fd != -1) if (l->fd != -1)
close(l->fd); close(l->fd);
rm = 0;
#if defined(__linux__)
if (worker == NULL && l->family == AF_UNIX && l->host[0] != '@')
rm++;
#else
if (worker == NULL && l->family == AF_UNIX)
rm++;
#endif
if (rm) {
if (unlink(l->host) == -1) {
kore_log(LOG_NOTICE,
"failed to remove unix socket %s (%s)", l->host,
errno_s);
}
}
kore_free(l->host); kore_free(l->host);
kore_free(l->port); kore_free(l->port);
@ -717,6 +740,23 @@ kore_sockopt(int fd, int what, int opt)
void void
kore_signal_setup(void) kore_signal_setup(void)
{
kore_signal_trap(SIGHUP);
kore_signal_trap(SIGQUIT);
kore_signal_trap(SIGTERM);
kore_signal_trap(SIGUSR1);
kore_signal_trap(SIGCHLD);
if (kore_foreground)
kore_signal_trap(SIGINT);
else
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGPIPE, SIG_IGN);
}
void
kore_signal_trap(int sig)
{ {
struct sigaction sa; struct sigaction sa;
@ -727,25 +767,8 @@ kore_signal_setup(void)
if (sigfillset(&sa.sa_mask) == -1) if (sigfillset(&sa.sa_mask) == -1)
fatal("sigfillset: %s", errno_s); fatal("sigfillset: %s", errno_s);
if (sigaction(SIGHUP, &sa, NULL) == -1) if (sigaction(sig, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s); fatal("sigaction: %s", errno_s);
if (sigaction(SIGQUIT, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
if (sigaction(SIGTERM, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
if (sigaction(SIGUSR1, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
if (sigaction(SIGCHLD, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
if (kore_foreground) {
if (sigaction(SIGINT, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
} else {
(void)signal(SIGINT, SIG_IGN);
}
(void)signal(SIGPIPE, SIG_IGN);
} }
void void
@ -833,11 +856,39 @@ kore_server_start(int argc, char *argv[])
u_int32_t tmp; u_int32_t tmp;
struct kore_server *srv; struct kore_server *srv;
u_int64_t netwait; u_int64_t netwait;
int quit, last_sig; int last_sig;
#if defined(KORE_SINGLE_BINARY) #if defined(KORE_SINGLE_BINARY)
struct kore_runtime_call *rcall; struct kore_runtime_call *rcall;
#endif #endif
if (!kore_quiet) {
kore_log(LOG_INFO, "%s %s starting, built=%s",
__progname, kore_version, kore_build_date);
kore_log(LOG_INFO, "built-ins: "
#if defined(__linux__)
"seccomp "
#endif
#if defined(KORE_USE_PGSQL)
"pgsql "
#endif
#if defined(KORE_USE_TASKS)
"tasks "
#endif
#if defined(KORE_USE_JSONRPC)
"jsonrpc "
#endif
#if defined(KORE_USE_PYTHON)
"python "
#endif
#if defined(KORE_USE_ACME)
"acme "
#endif
#if defined(KORE_USE_CURL)
"curl "
#endif
);
}
if (kore_foreground == 0) { if (kore_foreground == 0) {
if (daemon(1, 0) == -1) if (daemon(1, 0) == -1)
fatal("cannot daemon(): %s", errno_s); fatal("cannot daemon(): %s", errno_s);
@ -853,25 +904,6 @@ kore_server_start(int argc, char *argv[])
kore_pid = getpid(); kore_pid = getpid();
kore_write_kore_pid(); kore_write_kore_pid();
if (!kore_quiet) {
kore_log(LOG_NOTICE, "%s is starting up", __progname);
#if defined(__linux__)
kore_log(LOG_NOTICE, "seccomp sandbox enabled");
#endif
#if defined(KORE_USE_PGSQL)
kore_log(LOG_NOTICE, "pgsql built-in enabled");
#endif
#if defined(KORE_USE_TASKS)
kore_log(LOG_NOTICE, "tasks built-in enabled");
#endif
#if defined(KORE_USE_JSONRPC)
kore_log(LOG_NOTICE, "jsonrpc built-in enabled");
#endif
#if defined(KORE_USE_PYTHON)
kore_log(LOG_NOTICE, "python built-in enabled");
#endif
}
#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON) #if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
kore_call_parent_configure(argc, argv); kore_call_parent_configure(argc, argv);
#endif #endif
@ -881,6 +913,10 @@ kore_server_start(int argc, char *argv[])
kore_call_parent_configure(argc, argv); kore_call_parent_configure(argc, argv);
#endif #endif
#if defined(KORE_USE_PYTHON)
kore_python_routes_resolve();
#endif
/* Check if keymgr will be active. */ /* Check if keymgr will be active. */
LIST_FOREACH(srv, &kore_servers, list) { LIST_FOREACH(srv, &kore_servers, list) {
if (srv->tls) { if (srv->tls) {
@ -890,7 +926,19 @@ kore_server_start(int argc, char *argv[])
} }
kore_platform_proctitle("[parent]"); kore_platform_proctitle("[parent]");
kore_worker_init();
if (!kore_worker_init()) {
kore_log(LOG_ERR, "last worker log lines:");
kore_log(LOG_ERR, "=====================================");
net_init();
kore_connection_init();
kore_platform_event_init();
kore_msg_parent_init();
kore_platform_event_wait(10);
kore_worker_dispatch_signal(SIGQUIT);
kore_log(LOG_ERR, "=====================================");
return;
}
/* Set worker_max_connections for kore_connection_init(). */ /* Set worker_max_connections for kore_connection_init(). */
tmp = worker_max_connections; tmp = worker_max_connections;
@ -901,7 +949,6 @@ kore_server_start(int argc, char *argv[])
kore_platform_event_init(); kore_platform_event_init();
kore_msg_parent_init(); kore_msg_parent_init();
quit = 0;
worker_max_connections = tmp; worker_max_connections = tmp;
kore_timer_init(); kore_timer_init();
@ -913,23 +960,23 @@ kore_server_start(int argc, char *argv[])
kore_msg_unregister(KORE_PYTHON_SEND_OBJ); kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
#endif #endif
while (quit != 1) { while (kore_quit != 1) {
if (sig_recv != 0) { last_sig = sig_recv;
last_sig = sig_recv;
switch (sig_recv) { if (last_sig != 0) {
switch (last_sig) {
case SIGHUP: case SIGHUP:
kore_worker_dispatch_signal(sig_recv); kore_worker_dispatch_signal(last_sig);
kore_module_reload(0); kore_module_reload(0);
break; break;
case SIGINT: case SIGINT:
case SIGQUIT: case SIGQUIT:
case SIGTERM: case SIGTERM:
quit = 1; kore_quit = 1;
kore_worker_dispatch_signal(sig_recv); kore_worker_dispatch_signal(last_sig);
continue; continue;
case SIGUSR1: case SIGUSR1:
kore_worker_dispatch_signal(sig_recv); kore_worker_dispatch_signal(last_sig);
break; break;
case SIGCHLD: case SIGCHLD:
kore_worker_reap(); kore_worker_reap();
@ -948,8 +995,20 @@ kore_server_start(int argc, char *argv[])
kore_platform_event_wait(netwait); kore_platform_event_wait(netwait);
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
kore_timer_run(kore_time_ms()); kore_timer_run(kore_time_ms());
kore_worker_reap();
} }
kore_worker_dispatch_signal(SIGQUIT);
}
static void
kore_server_shutdown(void)
{
if (!kore_quiet)
kore_log(LOG_INFO, "server shutting down");
kore_worker_shutdown();
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
kore_accesslog_gather(NULL, kore_time_ms(), 1); kore_accesslog_gather(NULL, kore_time_ms(), 1);
#endif #endif

159
src/log.c Normal file
View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2021 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <time.h>
#include <syslog.h>
#include "kore.h"
struct kore_wlog {
int prio;
u_int16_t wid;
size_t loglen;
char logmsg[];
};
static void log_print(int, const char *, ...);
static void log_from_worker(struct kore_msg *, const void *);
static FILE *fp = NULL;
void
kore_log_init(void)
{
#if defined(KORE_SINGLE_BINARY)
extern const char *__progname;
const char *name = kore_strdup(__progname);
#else
const char *name = "kore";
#endif
fp = stdout;
if (!kore_foreground)
openlog(name, LOG_NDELAY | LOG_PID, LOG_DAEMON);
kore_msg_register(KORE_MSG_WORKER_LOG, log_from_worker);
}
void
kore_log_file(const char *path)
{
if ((fp = fopen(path, "a")) == NULL) {
fp = stdout;
fatal("fopen(%s): %s", path, errno_s);
}
}
void
kore_log(int prio, const char *fmt, ...)
{
va_list args;
const char *str;
struct kore_wlog wlog;
struct kore_buf buf, pkt;
kore_buf_init(&buf, 128);
va_start(args, fmt);
kore_buf_appendv(&buf, fmt, args);
va_end(args);
if (worker != NULL) {
kore_buf_init(&pkt, sizeof(wlog) + buf.offset);
memset(&wlog, 0, sizeof(wlog));
wlog.prio = prio;
wlog.wid = worker->id;
wlog.loglen = buf.offset;
kore_buf_append(&pkt, &wlog, sizeof(wlog));
kore_buf_append(&pkt, buf.data, buf.offset);
kore_msg_send(KORE_MSG_PARENT, KORE_MSG_WORKER_LOG,
pkt.data, pkt.offset);
kore_buf_cleanup(&pkt);
} else {
str = kore_buf_stringify(&buf, NULL);
if (kore_foreground || fp != stdout)
log_print(prio, "[parent]: %s\n", str);
else
syslog(prio, "[parent]: %s", str);
}
kore_buf_cleanup(&buf);
}
static void
log_from_worker(struct kore_msg *msg, const void *data)
{
const char *name;
const struct kore_wlog *wlog;
if (msg->length < sizeof(*wlog)) {
kore_log(LOG_NOTICE,
"too short worker log received (%zu < %zu)",
msg->length, sizeof(*wlog));
return;
}
wlog = data;
name = kore_worker_name(wlog->wid);
if (kore_foreground || fp != stdout) {
log_print(wlog->prio, "%s: %.*s\n",
name, (int)wlog->loglen, wlog->logmsg);
} else {
syslog(wlog->prio, "%s: %.*s",
name, (int)wlog->loglen, wlog->logmsg);
}
}
static void
log_print(int prio, const char *fmt, ...)
{
struct tm *t;
struct timespec ts;
va_list args;
char tbuf[32];
va_start(args, fmt);
switch (prio) {
case LOG_ERR:
case LOG_WARNING:
case LOG_NOTICE:
case LOG_INFO:
case LOG_DEBUG:
break;
}
(void)clock_gettime(CLOCK_REALTIME, &ts);
t = gmtime(&ts.tv_sec);
if (strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", t) > 0)
fprintf(fp, "%s.%03ld UTC ", tbuf, ts.tv_nsec / 1000000);
vfprintf(fp, fmt, args);
fflush(fp);
va_end(args);
}

View File

@ -135,11 +135,6 @@ kore_module_reload(int cbs)
{ {
struct stat st; struct stat st;
int ret; int ret;
#if !defined(KORE_NO_HTTP)
struct kore_server *srv;
struct kore_domain *dom;
struct kore_module_handle *hdlr;
#endif
struct kore_module *module; struct kore_module *module;
TAILQ_FOREACH(module, &modules, list) { TAILQ_FOREACH(module, &modules, list) {
@ -183,22 +178,7 @@ kore_module_reload(int cbs)
} }
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
LIST_FOREACH(srv, &kore_servers, list) { kore_route_reload();
TAILQ_FOREACH(dom, &srv->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
#if !defined(KORE_NO_HTTP)
kore_validator_reload(); kore_validator_reload();
#endif #endif
} }
@ -212,97 +192,6 @@ kore_module_loaded(void)
return (1); return (1);
} }
#if !defined(KORE_NO_HTTP)
int
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_module_handle *hdlr;
if (auth != NULL) {
if ((ap = kore_auth_lookup(auth)) == NULL)
fatal("no authentication block '%s' found", auth);
} else {
ap = NULL;
}
hdlr = kore_malloc(sizeof(*hdlr));
hdlr->auth = ap;
hdlr->dom = dom;
hdlr->errors = 0;
hdlr->type = type;
hdlr->path = kore_strdup(path);
hdlr->func = kore_strdup(func);
hdlr->methods = HTTP_METHOD_ALL;
TAILQ_INIT(&(hdlr->params));
if ((hdlr->rcall = kore_runtime_getcall(func)) == NULL) {
kore_module_handler_free(hdlr);
kore_log(LOG_ERR, "function '%s' not found", func);
return (KORE_RESULT_ERROR);
}
if (hdlr->type == HANDLER_TYPE_DYNAMIC) {
if (regcomp(&(hdlr->rctx), hdlr->path,
REG_EXTENDED | REG_NOSUB)) {
kore_module_handler_free(hdlr);
kore_debug("regcomp() on %s failed", path);
return (KORE_RESULT_ERROR);
}
}
TAILQ_INSERT_TAIL(&(dom->handlers), hdlr, list);
return (KORE_RESULT_OK);
}
void
kore_module_handler_free(struct kore_module_handle *hdlr)
{
struct kore_handler_params *param;
if (hdlr == NULL)
return;
if (hdlr->func != NULL)
kore_free(hdlr->func);
if (hdlr->path != NULL)
kore_free(hdlr->path);
if (hdlr->type == HANDLER_TYPE_DYNAMIC)
regfree(&(hdlr->rctx));
/* Drop all validators associated with this handler */
while ((param = TAILQ_FIRST(&(hdlr->params))) != NULL) {
TAILQ_REMOVE(&(hdlr->params), param, list);
if (param->name != NULL)
kore_free(param->name);
kore_free(param);
}
kore_free(hdlr);
}
struct kore_module_handle *
kore_module_handler_find(struct http_request *req, struct kore_domain *dom)
{
struct kore_module_handle *hdlr;
TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
if (hdlr->type == HANDLER_TYPE_STATIC) {
if (!strcmp(hdlr->path, req->path))
return (hdlr);
} else {
if (!regexec(&(hdlr->rctx), req->path,
HTTP_CAPTURE_GROUPS, req->cgroups, 0))
return (hdlr);
}
}
return (NULL);
}
#endif /* !KORE_NO_HTTP */
void * void *
kore_module_getsym(const char *symbol, struct kore_runtime **runtime) kore_module_getsym(const char *symbol, struct kore_runtime **runtime)
{ {

View File

@ -22,6 +22,10 @@
#include "kore.h" #include "kore.h"
#include "http.h" #include "http.h"
#if defined(KORE_USE_ACME)
#include "acme.h"
#endif
struct msg_type { struct msg_type {
u_int8_t id; u_int8_t id;
void (*cb)(struct kore_msg *, const void *); void (*cb)(struct kore_msg *, const void *);
@ -29,9 +33,8 @@ struct msg_type {
}; };
static struct msg_type *msg_type_lookup(u_int8_t); static struct msg_type *msg_type_lookup(u_int8_t);
static int msg_recv_packet(struct netbuf *);
static int msg_recv_data(struct netbuf *); static int msg_recv_data(struct netbuf *);
static void msg_disconnected_parent(struct connection *); static int msg_recv_packet(struct netbuf *);
static void msg_disconnected_worker(struct connection *); static void msg_disconnected_worker(struct connection *);
static void msg_type_shutdown(struct kore_msg *, const void *); static void msg_type_shutdown(struct kore_msg *, const void *);
@ -56,19 +59,9 @@ kore_msg_parent_init(void)
struct kore_worker *kw; struct kore_worker *kw;
for (idx = 0; idx < worker_count; idx++) { for (idx = 0; idx < worker_count; idx++) {
if (keymgr_active == 0) {
if (idx == KORE_WORKER_KEYMGR_IDX ||
idx == KORE_WORKER_ACME_IDX)
continue;
}
#if !defined(KORE_USE_ACME)
if (idx == KORE_WORKER_ACME_IDX)
continue;
#endif
kw = kore_worker_data(idx); kw = kore_worker_data(idx);
kore_msg_parent_add(kw); if (kw->ps != NULL)
kore_msg_parent_add(kw);
} }
kore_msg_register(KORE_MSG_SHUTDOWN, msg_type_shutdown); kore_msg_register(KORE_MSG_SHUTDOWN, msg_type_shutdown);
@ -119,7 +112,6 @@ kore_msg_worker_init(void)
worker->msg[1]->write = net_write; worker->msg[1]->write = net_write;
worker->msg[1]->proto = CONN_PROTO_MSG; worker->msg[1]->proto = CONN_PROTO_MSG;
worker->msg[1]->state = CONN_STATE_ESTABLISHED; worker->msg[1]->state = CONN_STATE_ESTABLISHED;
worker->msg[1]->disconnect = msg_disconnected_parent;
worker->msg[1]->handle = kore_connection_handle; worker->msg[1]->handle = kore_connection_handle;
worker->msg[1]->evt.flags = KORE_EVENT_WRITE; worker->msg[1]->evt.flags = KORE_EVENT_WRITE;
@ -147,7 +139,7 @@ kore_msg_register(u_int8_t id, void (*cb)(struct kore_msg *, const void *))
{ {
struct msg_type *type; struct msg_type *type;
if ((type = msg_type_lookup(id)) != NULL) if (msg_type_lookup(id) != NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
type = kore_malloc(sizeof(*type)); type = kore_malloc(sizeof(*type));
@ -251,16 +243,6 @@ msg_recv_data(struct netbuf *nb)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
static void
msg_disconnected_parent(struct connection *c)
{
if (!kore_quiet)
kore_log(LOG_ERR, "parent gone, shutting down");
if (kill(worker->pid, SIGQUIT) == -1)
kore_log(LOG_ERR, "failed to send SIGQUIT: %s", errno_s);
}
static void static void
msg_disconnected_worker(struct connection *c) msg_disconnected_worker(struct connection *c)
{ {
@ -275,7 +257,7 @@ msg_type_shutdown(struct kore_msg *msg, const void *data)
"shutdown requested by worker %u, going down", msg->src); "shutdown requested by worker %u, going down", msg->src);
} }
(void)raise(SIGQUIT); kore_quit = 1;
} }
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)

View File

@ -292,6 +292,9 @@ net_recv_flush(struct connection *c)
if (c->rnb->buf == NULL) if (c->rnb->buf == NULL)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
if ((c->rnb->b_len - c->rnb->s_off) == 0)
return (KORE_RESULT_OK);
if (!c->read(c, &r)) if (!c->read(c, &r))
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
if (!(c->evt.flags & KORE_EVENT_READ)) if (!(c->evt.flags & KORE_EVENT_READ))

View File

@ -772,6 +772,10 @@ pgsql_read_result(struct kore_pgsql *pgsql)
} }
switch (PQresultStatus(pgsql->result)) { switch (PQresultStatus(pgsql->result)) {
#if PG_VERSION_NUM >= 140000
case PGRES_PIPELINE_SYNC:
case PGRES_PIPELINE_ABORTED:
#endif
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
case PGRES_COPY_IN: case PGRES_COPY_IN:
case PGRES_NONFATAL_ERROR: case PGRES_NONFATAL_ERROR:

View File

@ -47,6 +47,8 @@ kore_pool_init(struct kore_pool *pool, const char *name,
if ((pool->name = strdup(name)) == NULL) if ((pool->name = strdup(name)) == NULL)
fatal("kore_pool_init: strdup %s", errno_s); fatal("kore_pool_init: strdup %s", errno_s);
len = (len + (8 - 1)) & ~(8 - 1);
pool->lock = 0; pool->lock = 0;
pool->elms = 0; pool->elms = 0;
pool->inuse = 0; pool->inuse = 0;

File diff suppressed because it is too large Load Diff

138
src/route.c Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2021 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include "kore.h"
#include "http.h"
struct kore_route *
kore_route_create(struct kore_domain *dom, const char *path, int type)
{
struct kore_route *rt;
rt = kore_calloc(1, sizeof(*rt));
rt->dom = dom;
rt->type = type;
rt->path = kore_strdup(path);
rt->methods = HTTP_METHOD_ALL;
TAILQ_INIT(&rt->params);
if (rt->type == HANDLER_TYPE_DYNAMIC) {
if (regcomp(&rt->rctx, rt->path, REG_EXTENDED | REG_NOSUB)) {
kore_route_free(rt);
return (NULL);
}
}
TAILQ_INSERT_TAIL(&dom->routes, rt, list);
return (rt);
}
void
kore_route_free(struct kore_route *rt)
{
struct kore_route_params *param;
if (rt == NULL)
return;
kore_free(rt->func);
kore_free(rt->path);
if (rt->type == HANDLER_TYPE_DYNAMIC)
regfree(&rt->rctx);
/* Drop all validators associated with this handler */
while ((param = TAILQ_FIRST(&rt->params)) != NULL) {
TAILQ_REMOVE(&rt->params, param, list);
kore_free(param->name);
kore_free(param);
}
kore_free(rt);
}
void
kore_route_callback(struct kore_route *rt, const char *func)
{
if ((rt->rcall = kore_runtime_getcall(func)) == NULL)
fatal("callback '%s' for '%s' not found", func, rt->path);
kore_free(rt->func);
rt->func = kore_strdup(func);
}
int
kore_route_lookup(struct http_request *req, struct kore_domain *dom,
int method, struct kore_route **out)
{
struct kore_route *rt;
int exists;
exists = 0;
*out = NULL;
TAILQ_FOREACH(rt, &dom->routes, list) {
if (rt->type == HANDLER_TYPE_STATIC) {
if (!strcmp(rt->path, req->path)) {
if (rt->methods & method) {
*out = rt;
return (1);
}
exists++;
}
} else {
if (!regexec(&rt->rctx, req->path,
HTTP_CAPTURE_GROUPS, req->cgroups, 0)) {
if (rt->methods & method) {
*out = rt;
return (1);
}
exists++;
}
}
}
return (exists);
}
void
kore_route_reload(void)
{
struct kore_route *rt;
struct kore_server *srv;
struct kore_domain *dom;
LIST_FOREACH(srv, &kore_servers, list) {
TAILQ_FOREACH(dom, &srv->domains, list) {
TAILQ_FOREACH(rt, &dom->routes, list) {
kore_free(rt->rcall);
rt->rcall = kore_runtime_getcall(rt->func);
if (rt->rcall == NULL) {
fatal("no function '%s' for route '%s'",
rt->func, rt->path);
}
rt->errors = 0;
}
}
}
}

View File

@ -29,10 +29,14 @@
static void native_runtime_execute(void *); static void native_runtime_execute(void *);
static int native_runtime_onload(void *, int); static int native_runtime_onload(void *, int);
static void native_runtime_signal(void *, int);
static void native_runtime_connect(void *, struct connection *); static void native_runtime_connect(void *, struct connection *);
static void native_runtime_configure(void *, int, char **); static void native_runtime_configure(void *, int, char **);
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
static int native_runtime_http_request(void *, struct http_request *); static int native_runtime_http_request(void *, struct http_request *);
static void native_runtime_http_request_free(void *, struct http_request *);
static void native_runtime_http_body_chunk(void *, struct http_request *,
const void *, size_t);
static int native_runtime_validator(void *, struct http_request *, static int native_runtime_validator(void *, struct http_request *,
const void *); const void *);
@ -44,12 +48,15 @@ struct kore_runtime kore_native_runtime = {
KORE_RUNTIME_NATIVE, KORE_RUNTIME_NATIVE,
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
.http_request = native_runtime_http_request, .http_request = native_runtime_http_request,
.http_request_free = native_runtime_http_request_free,
.http_body_chunk = native_runtime_http_body_chunk,
.validator = native_runtime_validator, .validator = native_runtime_validator,
.wsconnect = native_runtime_connect, .wsconnect = native_runtime_connect,
.wsmessage = native_runtime_wsmessage, .wsmessage = native_runtime_wsmessage,
.wsdisconnect = native_runtime_connect, .wsdisconnect = native_runtime_connect,
#endif #endif
.onload = native_runtime_onload, .onload = native_runtime_onload,
.signal = native_runtime_signal,
.connect = native_runtime_connect, .connect = native_runtime_connect,
.execute = native_runtime_execute, .execute = native_runtime_execute,
.configure = native_runtime_configure .configure = native_runtime_configure
@ -97,6 +104,12 @@ kore_runtime_connect(struct kore_runtime_call *rcall, struct connection *c)
rcall->runtime->connect(rcall->addr, c); rcall->runtime->connect(rcall->addr, c);
} }
void
kore_runtime_signal(struct kore_runtime_call *rcall, int sig)
{
rcall->runtime->signal(rcall->addr, sig);
}
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
int int
kore_runtime_http_request(struct kore_runtime_call *rcall, kore_runtime_http_request(struct kore_runtime_call *rcall,
@ -105,6 +118,20 @@ kore_runtime_http_request(struct kore_runtime_call *rcall,
return (rcall->runtime->http_request(rcall->addr, req)); return (rcall->runtime->http_request(rcall->addr, req));
} }
void
kore_runtime_http_request_free(struct kore_runtime_call *rcall,
struct http_request *req)
{
rcall->runtime->http_request_free(rcall->addr, req);
}
void
kore_runtime_http_body_chunk(struct kore_runtime_call *rcall,
struct http_request *req, const void *data, size_t len)
{
rcall->runtime->http_body_chunk(rcall->addr, req, data, len);
}
int int
kore_runtime_validator(struct kore_runtime_call *rcall, kore_runtime_validator(struct kore_runtime_call *rcall,
struct http_request *req, const void *data) struct http_request *req, const void *data)
@ -168,6 +195,15 @@ native_runtime_onload(void *addr, int action)
return (cb(action)); return (cb(action));
} }
static void
native_runtime_signal(void *addr, int sig)
{
void (*cb)(int);
*(void **)&(cb) = addr;
cb(sig);
}
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
static int static int
native_runtime_http_request(void *addr, struct http_request *req) native_runtime_http_request(void *addr, struct http_request *req)
@ -178,6 +214,26 @@ native_runtime_http_request(void *addr, struct http_request *req)
return (cb(req)); return (cb(req));
} }
static void
native_runtime_http_request_free(void *addr, struct http_request *req)
{
int (*cb)(struct http_request *);
*(void **)&(cb) = addr;
cb(req);
}
static void
native_runtime_http_body_chunk(void *addr, struct http_request *req,
const void *data, size_t len)
{
void (*cb)(struct http_request *, const void *, size_t);
*(void **)&(cb) = addr;
cb(req, data, len);
}
static int static int
native_runtime_validator(void *addr, struct http_request *req, const void *data) native_runtime_validator(void *addr, struct http_request *req, const void *data)
{ {

View File

@ -90,6 +90,9 @@ static struct sock_filter filter_kore[] = {
#if defined(SYS_readlink) #if defined(SYS_readlink)
KORE_SYSCALL_ALLOW(readlink), KORE_SYSCALL_ALLOW(readlink),
#endif #endif
#if defined(SYS_readlinkat)
KORE_SYSCALL_ALLOW(readlinkat),
#endif
/* Process related. */ /* Process related. */
KORE_SYSCALL_ALLOW(exit), KORE_SYSCALL_ALLOW(exit),

View File

@ -54,6 +54,9 @@ static int utils_base64_encode(const void *, size_t, char **,
const char *, int); const char *, int);
static int utils_base64_decode(const char *, u_int8_t **, static int utils_base64_decode(const char *, u_int8_t **,
size_t *, const char *, int); size_t *, const char *, int);
static int utils_x509name_tobuf(void *, int, int, const char *,
const void *, size_t, int);
static char b64_table[] = \ static char b64_table[] = \
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@ -79,46 +82,6 @@ kore_debug_internal(char *file, int line, const char *fmt, ...)
} }
#endif #endif
void
kore_log_init(void)
{
#if defined(KORE_SINGLE_BINARY)
extern const char *__progname;
const char *name = kore_strdup(__progname);
#else
const char *name = "kore";
#endif
if (!kore_foreground)
openlog(name, LOG_NDELAY | LOG_PID, LOG_DAEMON);
}
void
kore_log(int prio, const char *fmt, ...)
{
va_list args;
const char *name;
char buf[2048];
va_start(args, fmt);
(void)vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (worker != NULL) {
name = kore_worker_name(worker->id);
if (kore_foreground)
printf("%s: %s\n", name, buf);
else
syslog(prio, "%s: %s", name, buf);
} else {
if (kore_foreground)
printf("[parent]: %s\n", buf);
else
syslog(prio, "[parent]: %s", buf);
}
}
size_t size_t
kore_strlcpy(char *dst, const char *src, const size_t len) kore_strlcpy(char *dst, const char *src, const size_t len)
{ {
@ -585,35 +548,72 @@ kore_worker_name(int id)
return (buf); return (buf);
} }
int
kore_x509_issuer_name(struct connection *c, char **out, int flags)
{
struct kore_buf buf;
X509_NAME *name;
if ((name = X509_get_issuer_name(c->cert)) == NULL)
return (KORE_RESULT_ERROR);
kore_buf_init(&buf, 1024);
if (!kore_x509name_foreach(name, flags, &buf, utils_x509name_tobuf)) {
kore_buf_cleanup(&buf);
return (KORE_RESULT_ERROR);
}
*out = kore_buf_stringify(&buf, NULL);
buf.offset = 0;
buf.data = NULL;
return (KORE_RESULT_OK);
}
int int
kore_x509_subject_name(struct connection *c, char **out, int flags) kore_x509_subject_name(struct connection *c, char **out, int flags)
{ {
struct kore_buf buf; struct kore_buf buf;
X509_NAME *name;
if ((name = X509_get_subject_name(c->cert)) == NULL)
return (KORE_RESULT_ERROR);
kore_buf_init(&buf, 1024);
if (!kore_x509name_foreach(name, flags, &buf, utils_x509name_tobuf)) {
kore_buf_cleanup(&buf);
return (KORE_RESULT_ERROR);
}
*out = kore_buf_stringify(&buf, NULL);
buf.offset = 0;
buf.data = NULL;
return (KORE_RESULT_OK);
}
int
kore_x509name_foreach(X509_NAME *name, int flags, void *udata,
int (*cb)(void *, int, int, const char *, const void *, size_t, int))
{
u_int8_t *data; u_int8_t *data;
ASN1_STRING *astr; ASN1_STRING *astr;
X509_NAME *name;
X509_NAME_ENTRY *entry; X509_NAME_ENTRY *entry;
const char *field; const char *field;
int ret, idx, namelen, nid, len; int islast, ret, idx, namelen, nid, len;
data = NULL; data = NULL;
ret = KORE_RESULT_ERROR; ret = KORE_RESULT_ERROR;
kore_buf_init(&buf, 1024); if ((namelen = X509_NAME_entry_count(name)) == 0)
if (c->cert == NULL)
goto cleanup;
if ((name = X509_get_subject_name(c->cert)) == NULL)
goto cleanup;
namelen = X509_NAME_entry_count(name);
if (namelen == 0)
goto cleanup; goto cleanup;
for (idx = 0; idx < namelen; idx++) { for (idx = 0; idx < namelen; idx++) {
entry = X509_NAME_get_entry(name, idx); if ((entry = X509_NAME_get_entry(name, idx)) == NULL)
if (entry == NULL)
goto cleanup; goto cleanup;
nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry)); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry));
@ -627,33 +627,24 @@ kore_x509_subject_name(struct connection *c, char **out, int flags)
if ((len = ASN1_STRING_to_UTF8(&data, astr)) < 0) if ((len = ASN1_STRING_to_UTF8(&data, astr)) < 0)
goto cleanup; goto cleanup;
if (flags & KORE_X509_COMMON_NAME_ONLY) { if (idx != (namelen - 1))
if (nid == NID_commonName) { islast = 0;
kore_buf_append(&buf, data, len); else
break; islast = 1;
}
} else { if (!cb(udata, islast, nid, field, data, len, flags))
kore_buf_appendf(&buf, "%s=", field); goto cleanup;
kore_buf_append(&buf, data, len);
if (idx != (namelen - 1))
kore_buf_appendf(&buf, " ");
}
OPENSSL_free(data); OPENSSL_free(data);
data = NULL; data = NULL;
} }
ret = KORE_RESULT_OK; ret = KORE_RESULT_OK;
*out = kore_buf_stringify(&buf, NULL);
buf.offset = 0;
buf.data = NULL;
cleanup: cleanup:
if (data != NULL) if (data != NULL)
OPENSSL_free(data); OPENSSL_free(data);
kore_buf_cleanup(&buf);
return (ret); return (ret);
} }
@ -689,17 +680,31 @@ static void
fatal_log(const char *fmt, va_list args) fatal_log(const char *fmt, va_list args)
{ {
char buf[2048]; char buf[2048];
extern const char *kore_progname;
(void)vsnprintf(buf, sizeof(buf), fmt, args); (void)vsnprintf(buf, sizeof(buf), fmt, args);
kore_log(LOG_ERR, "FATAL: %s", buf);
if (!kore_foreground)
kore_log(LOG_ERR, "%s", buf);
if (worker != NULL && worker->id == KORE_WORKER_KEYMGR) if (worker != NULL && worker->id == KORE_WORKER_KEYMGR)
kore_keymgr_cleanup(1); kore_keymgr_cleanup(1);
}
printf("%s: %s\n", kore_progname, buf); static int
utils_x509name_tobuf(void *udata, int islast, int nid, const char *field,
const void *data, size_t len, int flags)
{
struct kore_buf *buf = udata;
if (flags & KORE_X509_COMMON_NAME_ONLY) {
if (nid == NID_commonName)
kore_buf_append(buf, data, len);
} else {
kore_buf_appendf(buf, "%s=", field);
kore_buf_append(buf, data, len);
if (!islast)
kore_buf_appendf(buf, " ");
}
return (KORE_RESULT_OK);
} }
static int static int

View File

@ -16,6 +16,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <sys/shm.h> #include <sys/shm.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h> #include <sys/time.h>
@ -28,6 +29,7 @@
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include "kore.h" #include "kore.h"
@ -77,6 +79,11 @@ struct wlock {
static int worker_trylock(void); static int worker_trylock(void);
static void worker_unlock(void); static void worker_unlock(void);
static void worker_reaper(pid_t, int); static void worker_reaper(pid_t, int);
static void worker_runtime_teardown(void);
static void worker_runtime_configure(void);
static void worker_domain_check(struct kore_domain *);
static struct kore_runtime_call *worker_runtime_signal(void);
static inline int worker_acceptlock_obtain(void); static inline int worker_acceptlock_obtain(void);
static inline void worker_acceptlock_release(void); static inline void worker_acceptlock_release(void);
@ -99,7 +106,7 @@ u_int32_t worker_max_connections = 512;
u_int32_t worker_active_connections = 0; u_int32_t worker_active_connections = 0;
int worker_policy = KORE_WORKER_POLICY_RESTART; int worker_policy = KORE_WORKER_POLICY_RESTART;
void int
kore_worker_init(void) kore_worker_init(void)
{ {
size_t len; size_t len;
@ -143,42 +150,59 @@ kore_worker_init(void)
kw->lb.offset = 0; kw->lb.offset = 0;
} }
if (!kore_quiet)
kore_log(LOG_INFO, "starting worker processes");
/* Now start all the workers. */ /* Now start all the workers. */
id = 1; id = 1;
cpu = 1; cpu = 1;
for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) { for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) {
if (cpu >= cpu_count) if (cpu >= cpu_count)
cpu = 0; cpu = 0;
kore_worker_spawn(idx, id++, cpu++); if (!kore_worker_spawn(idx, id++, cpu++))
return (KORE_RESULT_ERROR);
} }
if (keymgr_active) { if (keymgr_active) {
#if defined(KORE_USE_ACME) #if defined(KORE_USE_ACME)
/* The ACME process is only started if we need it. */ /* The ACME process is only started if we need it. */
if (acme_provider) { if (acme_domains) {
kore_worker_spawn(KORE_WORKER_ACME_IDX, if (!kore_worker_spawn(KORE_WORKER_ACME_IDX,
KORE_WORKER_ACME, 0); KORE_WORKER_ACME, 0))
return (KORE_RESULT_ERROR);
} }
#endif #endif
/* Now we can start the keymgr. */ /* Now we can start the keymgr. */
kore_worker_spawn(KORE_WORKER_KEYMGR_IDX, if (!kore_worker_spawn(KORE_WORKER_KEYMGR_IDX,
KORE_WORKER_KEYMGR, 0); KORE_WORKER_KEYMGR, 0))
return (KORE_RESULT_ERROR);
} }
if (!kore_quiet)
kore_log(LOG_INFO, "all worker processes started");
return (KORE_RESULT_OK);
} }
void int
kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu) kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
{ {
int cnt;
struct kore_worker *kw; struct kore_worker *kw;
#if defined(__linux__)
int status;
#endif
kw = WORKER(idx); kw = WORKER(idx);
kw->id = id; kw->id = id;
kw->cpu = cpu; kw->cpu = cpu;
kw->has_lock = 0;
kw->active_hdlr = NULL;
kw->running = 1; kw->running = 1;
kw->ready = 0;
kw->has_lock = 0;
kw->active_route = NULL;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1) if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1)
fatal("socketpair(): %s", errno_s); fatal("socketpair(): %s", errno_s);
@ -186,6 +210,20 @@ kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
!kore_connection_nonblock(kw->pipe[1], 0)) !kore_connection_nonblock(kw->pipe[1], 0))
fatal("could not set pipe fds to nonblocking: %s", errno_s); fatal("could not set pipe fds to nonblocking: %s", errno_s);
switch (id) {
case KORE_WORKER_KEYMGR:
kw->ps = &keymgr_privsep;
break;
#if defined(KORE_USE_ACME)
case KORE_WORKER_ACME:
kw->ps = &acme_privsep;
break;
#endif
default:
kw->ps = &worker_privsep;
break;
}
kw->pid = fork(); kw->pid = fork();
if (kw->pid == -1) if (kw->pid == -1)
fatal("could not spawn worker child: %s", errno_s); fatal("could not spawn worker child: %s", errno_s);
@ -193,8 +231,34 @@ kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
if (kw->pid == 0) { if (kw->pid == 0) {
kw->pid = getpid(); kw->pid = getpid();
kore_worker_entry(kw); kore_worker_entry(kw);
/* NOTREACHED */ exit(1);
} else {
for (cnt = 0; cnt < 50; cnt++) {
if (kw->ready == 1)
break;
usleep(100000);
#if defined(__linux__)
/*
* If seccomp_tracing is enabled, make sure we
* handle the SIGSTOP from the child processes.
*/
if (kore_seccomp_tracing) {
if (waitpid(kw->pid, &status, WNOHANG) > 0)
kore_seccomp_trace(kw->pid, status);
}
#endif
}
if (kw->ready == 0) {
kore_log(LOG_NOTICE,
"worker %d failed to start, shutting down",
kw->id);
return (KORE_RESULT_ERROR);
}
} }
return (KORE_RESULT_OK);
} }
struct kore_worker * struct kore_worker *
@ -237,9 +301,13 @@ kore_worker_shutdown(void)
kw->pid = 0; kw->pid = 0;
kw->running = 0; kw->running = 0;
kw->msg[0]->evt.flags |= KORE_EVENT_READ;
net_recv_flush(kw->msg[0]);
if (!kore_quiet) { if (!kore_quiet) {
kore_log(LOG_NOTICE, "worker %s exited", kore_log(LOG_NOTICE,
kore_worker_name(kw->id)); "worker %s exited (%d)",
kore_worker_name(kw->id), status);
} }
} }
} }
@ -282,37 +350,43 @@ kore_worker_dispatch_signal(int sig)
} }
void void
kore_worker_privdrop(const char *runas, const char *root) kore_worker_privsep(void)
{ {
rlim_t fd; rlim_t fd;
struct rlimit rl; struct rlimit rl;
struct passwd *pw = NULL; struct passwd *pw;
if (root == NULL) if (worker == NULL)
fatalx("no root directory for kore_worker_privdrop"); fatalx("%s called with no worker", __func__);
pw = NULL;
/* Must happen before chroot. */ /* Must happen before chroot. */
if (skip_runas == 0) { if (worker->ps->skip_runas == 0) {
if (runas == NULL) if (worker->ps->runas == NULL) {
fatalx("no runas user given and -r not specified"); fatalx("no runas user given for %s",
pw = getpwnam(runas); kore_worker_name(worker->id));
if (pw == NULL) { }
if ((pw = getpwnam(worker->ps->runas)) == NULL) {
fatalx("cannot getpwnam(\"%s\") for user: %s", fatalx("cannot getpwnam(\"%s\") for user: %s",
runas, errno_s); worker->ps->runas, errno_s);
} }
} }
if (skip_chroot == 0) { if (worker->ps->skip_chroot == 0) {
if (chroot(root) == -1) { if (chroot(worker->ps->root) == -1) {
fatalx("cannot chroot(\"%s\"): %s", fatalx("cannot chroot(\"%s\"): %s",
root, errno_s); worker->ps->root, errno_s);
} }
if (chdir("/") == -1) if (chdir("/") == -1)
fatalx("cannot chdir(\"/\"): %s", errno_s); fatalx("cannot chdir(\"/\"): %s", errno_s);
} else { } else {
if (chdir(root) == -1) if (chdir(worker->ps->root) == -1) {
fatalx("cannot chdir(\"%s\"): %s", root, errno_s); fatalx("cannot chdir(\"%s\"): %s",
worker->ps->root, errno_s);
}
} }
if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
@ -332,7 +406,7 @@ kore_worker_privdrop(const char *runas, const char *root)
worker_rlimit_nofiles, errno_s); worker_rlimit_nofiles, errno_s);
} }
if (skip_runas == 0) { if (worker->ps->skip_runas == 0) {
if (setgroups(1, &pw->pw_gid) || if (setgroups(1, &pw->pw_gid) ||
#if defined(__MACH__) || defined(NetBSD) #if defined(__MACH__) || defined(NetBSD)
setgid(pw->pw_gid) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || setegid(pw->pw_gid) ||
@ -341,7 +415,7 @@ kore_worker_privdrop(const char *runas, const char *root)
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
#endif #endif
fatalx("cannot drop privileges"); fatalx("cannot drop privileges (%s)", errno_s);
} }
kore_platform_sandbox(); kore_platform_sandbox();
@ -350,13 +424,16 @@ kore_worker_privdrop(const char *runas, const char *root)
void void
kore_worker_entry(struct kore_worker *kw) kore_worker_entry(struct kore_worker *kw)
{ {
struct kore_runtime_call *rcall; struct kore_runtime_call *sigcall;
u_int64_t last_seed; u_int64_t last_seed;
int quit, had_lock; int quit, had_lock, sig;
u_int64_t netwait, now, next_timeo; u_int64_t netwait, now, next_timeo;
worker = kw; worker = kw;
if (!kore_foreground)
closelog();
#if defined(__linux__) #if defined(__linux__)
kore_seccomp_traceme(); kore_seccomp_traceme();
#endif #endif
@ -367,7 +444,6 @@ kore_worker_entry(struct kore_worker *kw)
kore_platform_worker_setcpu(kw); kore_platform_worker_setcpu(kw);
kore_pid = kw->pid; kore_pid = kw->pid;
kore_signal_setup(); kore_signal_setup();
if (kw->id == KORE_WORKER_KEYMGR) { if (kw->id == KORE_WORKER_KEYMGR) {
@ -391,7 +467,7 @@ kore_worker_entry(struct kore_worker *kw)
kore_task_init(); kore_task_init();
#endif #endif
kore_worker_privdrop(kore_runas_user, kore_root_path); kore_worker_privsep();
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
http_init(); http_init();
@ -432,21 +508,16 @@ kore_worker_entry(struct kore_worker *kw)
if (nlisteners == 0) if (nlisteners == 0)
worker_no_lock = 1; worker_no_lock = 1;
if (!kore_quiet) { worker_runtime_configure();
kore_log(LOG_NOTICE,
"worker %d started (cpu#%d, pid#%d)",
kw->id, kw->cpu, kw->pid);
}
rcall = kore_runtime_getcall("kore_worker_configure");
if (rcall != NULL) {
kore_runtime_execute(rcall);
kore_free(rcall);
}
kore_module_onload(); kore_module_onload();
kore_domain_callback(worker_domain_check);
kore_worker_started();
worker->restarted = 0; worker->restarted = 0;
sigcall = worker_runtime_signal();
for (;;) { for (;;) {
now = kore_time_ms(); now = kore_time_ms();
@ -495,8 +566,9 @@ kore_worker_entry(struct kore_worker *kw)
} }
} }
if (sig_recv != 0) { sig = sig_recv;
switch (sig_recv) { if (sig != 0) {
switch (sig) {
case SIGHUP: case SIGHUP:
kore_module_reload(1); kore_module_reload(1);
break; break;
@ -514,7 +586,11 @@ kore_worker_entry(struct kore_worker *kw)
break; break;
} }
sig_recv = 0; if (sigcall != NULL)
kore_runtime_signal(sigcall, sig);
if (sig == sig_recv)
sig_recv = 0;
} }
if (quit) if (quit)
@ -539,13 +615,7 @@ kore_worker_entry(struct kore_worker *kw)
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
} }
rcall = kore_runtime_getcall("kore_worker_teardown"); worker_runtime_teardown();
if (rcall != NULL) {
kore_runtime_execute(rcall);
kore_free(rcall);
}
kore_msg_send(KORE_MSG_PARENT, KORE_MSG_SHUTDOWN, NULL, 0);
kore_server_cleanup(); kore_server_cleanup();
kore_platform_event_cleanup(); kore_platform_event_cleanup();
@ -577,24 +647,19 @@ kore_worker_reap(void)
pid_t pid; pid_t pid;
int status; int status;
for (;;) { pid = waitpid(WAIT_ANY, &status, WNOHANG);
pid = waitpid(WAIT_ANY, &status, WNOHANG);
if (pid == -1) { if (pid == -1) {
if (errno == ECHILD) if (errno == ECHILD || errno == EINTR)
return;
if (errno == EINTR)
continue;
kore_log(LOG_ERR,
"failed to wait for children: %s", errno_s);
return; return;
} kore_log(LOG_ERR, "%s: waitpid(): %s", __func__, errno_s);
return;
if (pid == 0)
return;
worker_reaper(pid, status);
} }
if (pid == 0)
return;
worker_reaper(pid, status);
} }
void void
@ -669,6 +734,97 @@ kore_worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
void
kore_worker_started(void)
{
const char *chroot;
if (worker->ps->skip_chroot)
chroot = "root";
else
chroot = "chroot";
if (!kore_quiet) {
kore_log(LOG_NOTICE,
"started (#%d %s=%s%s%s)",
getpid(), chroot, worker->ps->root,
worker->ps->skip_runas ? "" : " user=",
worker->ps->skip_runas ? "" : worker->ps->runas);
}
worker->ready = 1;
}
static void
worker_runtime_configure(void)
{
struct kore_runtime_call *rcall;
rcall = NULL;
#if defined(KORE_USE_PYTHON)
rcall = kore_runtime_getcall(KORE_PYTHON_WORKER_START_HOOK);
#endif
if (rcall == NULL)
rcall = kore_runtime_getcall("kore_worker_configure");
if (rcall != NULL) {
kore_runtime_execute(rcall);
kore_free(rcall);
}
}
static struct kore_runtime_call *
worker_runtime_signal(void)
{
struct kore_runtime_call *rcall;
rcall = NULL;
#if defined(KORE_USE_PYTHON)
rcall = kore_runtime_getcall(KORE_PYTHON_SIGNAL_HOOK);
#endif
if (rcall == NULL)
rcall = kore_runtime_getcall("kore_worker_signal");
return (rcall);
}
static void
worker_runtime_teardown(void)
{
struct kore_runtime_call *rcall;
rcall = NULL;
#if defined(KORE_USE_PYTHON)
rcall = kore_runtime_getcall(KORE_PYTHON_WORKER_STOP_HOOK);
#endif
if (rcall == NULL)
rcall = kore_runtime_getcall("kore_worker_teardown");
if (rcall != NULL) {
kore_runtime_execute(rcall);
kore_free(rcall);
}
}
static void
worker_domain_check(struct kore_domain *dom)
{
struct stat st;
if (dom->cafile != NULL) {
if (stat(dom->cafile, &st) == -1)
fatalx("'%s': %s", dom->cafile, errno_s);
if (access(dom->cafile, R_OK) == -1)
fatalx("'%s': not readable", dom->cafile, errno_s);
}
}
static void static void
worker_reaper(pid_t pid, int status) worker_reaper(pid_t pid, int status)
{ {
@ -686,6 +842,9 @@ worker_reaper(pid_t pid, int status)
if (kw->pid != pid) if (kw->pid != pid)
continue; continue;
kw->msg[0]->evt.flags |= KORE_EVENT_READ;
net_recv_flush(kw->msg[0]);
if (!kore_quiet) { if (!kore_quiet) {
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"worker %s (%d) exited with status %d", "worker %s (%d) exited with status %d",
@ -701,8 +860,8 @@ worker_reaper(pid_t pid, int status)
func = "none"; func = "none";
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
if (kw->active_hdlr != NULL) if (kw->active_route != NULL)
func = kw->active_hdlr->func; func = kw->active_route->func;
#endif #endif
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"worker %d (pid: %d) (hdlr: %s) gone", "worker %d (pid: %d) (hdlr: %s) gone",
@ -720,10 +879,7 @@ worker_reaper(pid_t pid, int status)
kore_log(LOG_CRIT, kore_log(LOG_CRIT,
"keymgr or acme process gone, stopping"); "keymgr or acme process gone, stopping");
kw->pid = 0; kw->pid = 0;
if (raise(SIGTERM) != 0) { kore_quit = 1;
kore_log(LOG_WARNING,
"failed to raise SIGTERM signal");
}
break; break;
} }
@ -732,12 +888,12 @@ worker_reaper(pid_t pid, int status)
worker_unlock(); worker_unlock();
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
if (kw->active_hdlr != NULL) { if (kw->active_route != NULL) {
kw->active_hdlr->errors++; kw->active_route->errors++;
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"hdlr %s has caused %d error(s)", "hdlr %s has caused %d error(s)",
kw->active_hdlr->func, kw->active_route->func,
kw->active_hdlr->errors); kw->active_route->errors);
} }
#endif #endif
@ -745,20 +901,24 @@ worker_reaper(pid_t pid, int status)
kw->pid = 0; kw->pid = 0;
kore_log(LOG_NOTICE, kore_log(LOG_NOTICE,
"worker policy is 'terminate', stopping"); "worker policy is 'terminate', stopping");
if (raise(SIGTERM) != 0) { kore_quit = 1;
kore_log(LOG_WARNING,
"failed to raise SIGTERM signal");
}
break; break;
} }
kore_log(LOG_NOTICE, "restarting worker %d", kw->id); if (kore_quit == 0) {
kw->restarted = 1; kore_log(LOG_NOTICE, "restarting worker %d", kw->id);
kore_msg_parent_remove(kw); kw->restarted = 1;
kore_worker_spawn(idx, kw->id, kw->cpu); kore_msg_parent_remove(kw);
kore_msg_parent_add(kw);
break; if (!kore_worker_spawn(idx, kw->id, kw->cpu)) {
kore_quit = 1;
kore_log(LOG_ERR, "failed to restart worker");
} else {
kore_msg_parent_add(kw);
}
break;
}
} }
} }
@ -899,7 +1059,10 @@ worker_keymgr_response(struct kore_msg *msg, const void *data)
case KORE_ACME_CHALLENGE_CLEAR_CERT: case KORE_ACME_CHALLENGE_CLEAR_CERT:
dom->acme_cert_len = 0; dom->acme_cert_len = 0;
dom->acme_challenge = 0; dom->acme_challenge = 0;
kore_free(dom->acme_cert); kore_free(dom->acme_cert);
dom->acme_cert = NULL;
kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge disabled", kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge disabled",
dom->domain); dom->domain);
break; break;