Merge branch 'master' into 4.x-releng

This commit is contained in:
Joris Vink 2023-04-05 18:53:52 +02:00
commit ab8fe8eb63
44 changed files with 1857 additions and 991 deletions

1
BEERS
View File

@ -15,6 +15,7 @@ I will note down the beer of your choice between the brackets.
[] Cleve Lendon
[] Corbin Hughes
[] Daniel Fahlgren x 6
[] Daniel Melani
[] Dmitrii Golub
[] Elliot Schlegelmilch
[] Erik Karlsson x 2

View File

@ -9,7 +9,6 @@ KODEV=kodev/kodev
KOREPATH?=$(shell pwd)
KORE_CRYPTO?=crypto
INSTALL_DIR=$(PREFIX)/bin
MAN_DIR?=$(PREFIX)/share/man
SHARE_DIR=$(PREFIX)/share/kore
INCLUDE_DIR=$(PREFIX)/include/kore
TLS_BACKEND?=openssl
@ -118,6 +117,16 @@ ifneq ("$(PYTHON)", "")
FEATURES_INC+=$(KORE_PYTHON_INC)
endif
ifneq ("$(LUA)", "")
S_SRC+=src/lua.c
KORE_LUA_LIB?=$(shell pkg-config --libs lua$(LUA_VERSION))
KORE_LUA_INC?=$(shell pkg-config --cflags lua$(LUA_VERSION))
LDFLAGS+=$(KORE_LUA_LIB)
CFLAGS+=$(KORE_LUA_INC) -DKORE_USE_LUA
FEATURES+=-DKORE_USE_LUA
FEATURES_INC+=$(KORE_LUA_INC)
endif
OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z)
ifeq ("$(OSNAME)", "freebsd")
KORE_CURL_LIB=-L/usr/local/lib -lcurl
@ -215,8 +224,6 @@ install:
mkdir -p $(DESTDIR)$(SHARE_DIR)
mkdir -p $(DESTDIR)$(INCLUDE_DIR)
mkdir -p $(DESTDIR)$(INSTALL_DIR)
mkdir -p $(DESTDIR)$(MAN_DIR)/man1
install -m 644 share/man/kodev.1 $(DESTDIR)$(MAN_DIR)/man1/kodev.1
install -m 555 $(KORE) $(DESTDIR)$(INSTALL_DIR)/$(KORE)
install -m 644 kore.features $(DESTDIR)$(SHARE_DIR)/features
install -m 644 kore.linker $(DESTDIR)$(SHARE_DIR)/linker

View File

@ -59,11 +59,10 @@ Kore only supports x64, arm and aarch64 architectures.
Building Kore
-------------
Clone this repository or get the latest release at [https://kore.io/releases/4.2.2](https://kore.io/releases/4.2.2).
Clone this repository or get the latest release at [https://kore.io/releases/4.2.3](https://kore.io/releases/4.2.3).
Requirements
* openssl 1.1.1 or libressl 3.x
(note: openssl 3.0.0 is currently *not* supported)
* openssl 1.1.1, libressl 3.x or openssl 3.
Requirement for asynchronous curl (optional)
* libcurl (7.64.0 or higher)
@ -77,6 +76,9 @@ Requirements for pgsql (optional)
Requirements for python (optional)
* Python 3.6+
Requirements for lua support (optional)
* Lua 5.4+
Normal compilation and installation:
```
@ -88,6 +90,7 @@ $ make
If you would like to build a specific flavor, you can enable
those by setting a shell environment variable before running **_make_**.
* LUA=1 (compiles in LUA support)
* ACME=1 (compiles in ACME support)
* CURL=1 (compiles in asynchronous curl support)
* TASKS=1 (compiles in task support)

View File

@ -55,6 +55,8 @@ KORE_SECCOMP_FILTER("tasks",
KORE_SYSCALL_ALLOW(recvmsg),
KORE_SYSCALL_ALLOW(sendmmsg),
KORE_SYSCALL_ALLOW(getpeername),
KORE_SYSCALL_ALLOW(rseq),
KORE_SYSCALL_ALLOW(clone3),
);
#endif

View File

@ -415,8 +415,8 @@ int http_state_exists(struct http_request *);
void http_state_cleanup(struct http_request *);
void *http_state_create(struct http_request *, size_t);
int http_argument_urldecode(char *);
int http_header_recv(struct netbuf *);
int http_argument_urldecode(char *, int);
void http_populate_qs(struct http_request *);
void http_populate_post(struct http_request *);
void http_populate_multipart_form(struct http_request *);

View File

@ -25,6 +25,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
@ -273,9 +274,11 @@ extern struct connection_list disconnected;
#define KORE_RUNTIME_NATIVE 0
#define KORE_RUNTIME_PYTHON 1
#define KORE_RUNTIME_LUA 2
struct kore_runtime {
int type;
int (*resolve)(const char *, const struct stat *);
#if !defined(KORE_NO_HTTP)
int (*http_request)(void *, struct http_request *);
void (*http_request_free)(void *, struct http_request *);
@ -411,8 +414,9 @@ struct kore_auth {
#define KORE_MODULE_LOAD 1
#define KORE_MODULE_UNLOAD 2
#define KORE_MODULE_NATIVE 0
#define KORE_MODULE_PYTHON 1
#define KORE_MODULE_NATIVE KORE_RUNTIME_NATIVE
#define KORE_MODULE_PYTHON KORE_RUNTIME_PYTHON
#define KORE_MODULE_LUA KORE_RUNTIME_LUA
struct kore_module;
@ -607,29 +611,24 @@ struct kore_json_item {
TAILQ_ENTRY(kore_json_item) list;
};
struct kore_pool_region {
void *start;
size_t length;
LIST_ENTRY(kore_pool_region) list;
};
struct kore_pool_entry {
u_int8_t state;
struct kore_pool_region *region;
LIST_ENTRY(kore_pool_entry) list;
void *uptr;
void *canary;
struct kore_pool_entry *nextfree;
};
struct kore_pool {
size_t elen;
size_t slen;
size_t elms;
size_t inuse;
size_t memsz;
size_t growth;
size_t pagesz;
size_t elmlen;
size_t uselen;
u_int64_t canary;
volatile int lock;
char *name;
LIST_HEAD(, kore_pool_region) regions;
LIST_HEAD(, kore_pool_entry) freelist;
struct kore_pool_entry *freelist;
};
struct kore_timer {
@ -708,6 +707,7 @@ extern int kore_quit;
extern int kore_quiet;
extern int skip_chroot;
extern int skip_runas;
extern int kore_mem_guard;
extern int kore_foreground;
extern char *kore_pidfile;
@ -753,6 +753,7 @@ void kore_server_closeall(void);
void kore_server_cleanup(void);
void kore_server_free(struct kore_server *);
void kore_server_finalize(struct kore_server *);
void kore_hooks_set(const char *, const char *, const char *);
struct kore_server *kore_server_create(const char *);
struct kore_server *kore_server_lookup(const char *);
@ -803,6 +804,7 @@ void kore_platform_schedule_read(int, void *);
void kore_platform_schedule_write(int, void *);
void kore_platform_event_schedule(int, int, int, void *);
void kore_platform_worker_setcpu(struct kore_worker *);
u_int32_t kore_platform_random_uint32(void);
#if defined(KORE_USE_PLATFORM_SENDFILE)
int kore_platform_sendfile(struct connection *, struct netbuf *);
@ -822,6 +824,7 @@ void kore_tls_dh_check(void);
int kore_tls_supported(void);
void kore_tls_version_set(int);
void kore_tls_keymgr_init(void);
void kore_tls_log_version(void);
int kore_tls_dh_load(const char *);
void kore_tls_seed(const void *, size_t);
int kore_tls_ciphersuite_set(const char *);
@ -885,24 +888,27 @@ void kore_connection_check_idletimer(u_int64_t,
struct connection *);
int kore_connection_accept(struct listener *,
struct connection **);
void kore_connection_log(struct connection *,
const char *, ...)
__attribute__((format (printf, 2, 3)));
const char *kore_connection_ip(struct connection *);
void kore_log_init(void);
void kore_log_file(const char *);
#if defined(KORE_USE_PYTHON)
int kore_configure_setting(const char *, char *);
#endif
/* config.c */
void kore_parse_config(void);
void kore_parse_config_file(FILE *);
int kore_configure_setting(const char *, char *);
/* mem.c */
void *kore_malloc(size_t);
void *kore_mmap_region(size_t);
void *kore_calloc(size_t, size_t);
void *kore_realloc(void *, size_t);
void kore_free(void *);
void kore_mem_init(void);
void kore_free_zero(void *);
void kore_mem_cleanup(void);
void kore_mem_untag(void *);
void *kore_mem_lookup(u_int32_t);
@ -933,7 +939,7 @@ u_int64_t kore_strtonum64(const char *, int, int *);
size_t kore_strlcpy(char *, const char *, const size_t);
void kore_server_disconnect(struct connection *);
int kore_split_string(char *, const char *, char **, size_t);
void kore_strip_chars(char *, const char, char **);
void kore_strip_chars(const char *, const char, char **);
int kore_snprintf(char *, size_t, int *, const char *, ...)
__attribute__((format (printf, 4, 5)));
long long kore_strtonum(const char *, int, long long, long long, int *);
@ -1022,6 +1028,7 @@ int kore_route_lookup(struct http_request *,
#endif
/* runtime.c */
const size_t kore_runtime_count(void);
struct kore_runtime_call *kore_runtime_getcall(const char *);
struct kore_module *kore_module_load(const char *,
const char *, int);
@ -1029,6 +1036,7 @@ struct kore_module *kore_module_load(const char *,
void kore_runtime_execute(struct kore_runtime_call *);
int kore_runtime_onload(struct kore_runtime_call *, int);
void kore_runtime_signal(struct kore_runtime_call *, int);
void kore_runtime_resolve(const char *, const struct stat *);
void kore_runtime_configure(struct kore_runtime_call *, int, char **);
void kore_runtime_connect(struct kore_runtime_call *, struct connection *);
#if !defined(KORE_NO_HTTP)

30
include/kore/lua_api.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2023 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __H_LUA_API_H
#define __H_LUA_API_H
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
void kore_lua_init(void);
void kore_lua_cleanup(void);
extern struct kore_module_functions kore_lua_module;
extern struct kore_runtime kore_lua_runtime;
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2023 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __H_LUA_METHODS_H
#define __H_LUA_METHODS_H
static int lua_http_request_gc(lua_State *);
static int lua_http_request_index(lua_State *);
static int lua_http_response(lua_State *);
static int lua_http_request_header(lua_State *);
static int lua_http_response_header(lua_State *);
static const luaL_Reg lua_http_request_meta[] = {
{ "__gc", lua_http_request_gc },
{ "__index", lua_http_request_index },
{ NULL, NULL },
};
static const luaL_Reg lua_http_request_methods[] = {
{ "response", lua_http_response },
{ "request_header", lua_http_request_header },
{ "response_header", lua_http_response_header },
{ NULL, NULL },
};
static int lua_kore_config(lua_State *);
static int lua_kore_server(lua_State *);
static const luaL_Reg lua_kore_functions[] = {
{ "config", lua_kore_config },
{ "server", lua_kore_server },
{ NULL, NULL },
};
#endif

View File

@ -44,10 +44,6 @@ void kore_python_seccomp_cleanup(void);
void kore_python_seccomp_hook(const char *);
#endif
#if !defined(KORE_SINGLE_BINARY)
extern const char *kore_pymodule;
#endif
extern struct kore_module_functions kore_python_module;
extern struct kore_runtime kore_python_runtime;

View File

@ -39,7 +39,6 @@ static PyObject *python_kore_app(PyObject *, PyObject *);
static PyObject *python_kore_log(PyObject *, PyObject *);
static PyObject *python_kore_time(PyObject *, PyObject *);
static PyObject *python_kore_lock(PyObject *, PyObject *);
static PyObject *python_kore_proc(PyObject *, PyObject *);
static PyObject *python_kore_fatal(PyObject *, PyObject *);
static PyObject *python_kore_queue(PyObject *, PyObject *);
static PyObject *python_kore_worker(PyObject *, PyObject *);
@ -56,6 +55,7 @@ static PyObject *python_kore_task_kill(PyObject *, PyObject *);
static PyObject *python_kore_prerequest(PyObject *, PyObject *);
static PyObject *python_kore_task_create(PyObject *, PyObject *);
static PyObject *python_kore_socket_wrap(PyObject *, PyObject *);
static PyObject *python_kore_proc(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_route(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_timer(PyObject *, PyObject *, PyObject *);
static PyObject *python_kore_domain(PyObject *, PyObject *, PyObject *);
@ -92,7 +92,6 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("log", python_kore_log, METH_VARARGS),
METHOD("time", python_kore_time, METH_NOARGS),
METHOD("lock", python_kore_lock, METH_NOARGS),
METHOD("proc", python_kore_proc, METH_VARARGS),
METHOD("queue", python_kore_queue, METH_VARARGS),
METHOD("worker", python_kore_worker, METH_VARARGS),
METHOD("tracer", python_kore_tracer, METH_VARARGS),
@ -109,6 +108,7 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("prerequest", python_kore_prerequest, METH_VARARGS),
METHOD("task_create", python_kore_task_create, METH_VARARGS),
METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS),
METHOD("proc", python_kore_proc, METH_VARARGS | METH_KEYWORDS),
METHOD("route", python_kore_route, METH_VARARGS | METH_KEYWORDS),
METHOD("timer", python_kore_timer, METH_VARARGS | METH_KEYWORDS),
METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS),
@ -231,10 +231,12 @@ struct pydomain {
};
static PyObject *pydomain_filemaps(struct pydomain *, PyObject *);
static PyObject *pydomain_redirect(struct pydomain *, PyObject *);
static PyObject *pydomain_route(struct pydomain *, PyObject *, PyObject *);
static PyMethodDef pydomain_methods[] = {
METHOD("filemaps", pydomain_filemaps, METH_VARARGS),
METHOD("redirect", pydomain_redirect, METH_VARARGS),
METHOD("route", pydomain_route, METH_VARARGS | METH_KEYWORDS),
METHOD(NULL, NULL, -1)
};
@ -560,6 +562,8 @@ static PyTypeObject pylock_op_type = {
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
};
#define PYTHON_PROC_MAX_ENV 32
struct pyproc {
PyObject_HEAD
pid_t pid;
@ -748,6 +752,7 @@ static void pyhttp_dealloc(struct pyhttp_request *);
static void pyhttp_file_dealloc(struct pyhttp_file *);
static PyObject *pyhttp_cookie(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_headers(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_response(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_argument(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_body_read(struct pyhttp_request *, PyObject *);
@ -763,6 +768,7 @@ static PyObject *pyhttp_websocket_handshake(struct pyhttp_request *,
static PyMethodDef pyhttp_request_methods[] = {
METHOD("cookie", pyhttp_cookie, METH_VARARGS),
METHOD("headers", pyhttp_headers, METH_NOARGS),
METHOD("response", pyhttp_response, METH_VARARGS),
METHOD("argument", pyhttp_argument, METH_VARARGS),
METHOD("body_read", pyhttp_body_read, METH_VARARGS),

55
misc/hooks/post-receive Normal file
View File

@ -0,0 +1,55 @@
#!/usr/local/bin/bash
set -x
set -e
URL=discord-hook
while read oldrev newrev ref; do
if [[ $ref =~ .*/master$ ]]; then
logmsg=""
commits=$(git rev-list ${oldrev}..${newrev})
for commit in $commits; do
log=$(git log -1 --pretty=format:'[%h](https://git.kore.io/kore/commit/%H) %cn: %s' $commit)
logmsg="$logmsg $log\\n"
done
curl -i \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-X POST \
-d "{\"content\": \"${logmsg}\"}" \
$URL
fi
done
git update-server-info
ROOT=/var/chroot/kore-site
TARGET=$ROOT/stagit
STATIC=$HOME/src/stagit_static
export TMPDIR=$ROOT/.tmp
STAGING=`mktemp -d`
function update_stagit {
mkdir -p $STAGING/$1
pushd $STAGING/$1
stagit $2
cp log.html index.html
cp -R $2 ${STAGING}/${1}.git
rm ${STAGING}/${1}.git/hooks/post-receive
chmod -R +rx ${STAGING}/${1}.git
popd
}
update_stagit kore /home/git/kore.git
cp -R $STATIC/* $STAGING
chmod -R o+rx $STAGING
rm -rf $ROOT/.old
mv $TARGET $ROOT/.old
mv $STAGING $TARGET
rm -rf $ROOT/.old

View File

@ -1,19 +0,0 @@
#!/bin/sh
set -e
. ./env.sh
if [ $# -ne 3 ]; then
echo "Usage: build-curl.sh [release] [openssl] [nghttp2]"
exit 1
fi
export PKG_CONFIG="pkg-config --static"
export PKG_CONFIG_PATH="$FAKEROOT/openssl-$2/lib/pkgconfig:$FAKEROOT/nghttp2-$3/lib/pkgconfig"
NAME=curl-$1
fetch "https://curl.haxx.se/download/$NAME.tar.gz" $NAME
default_build $NAME --enable-shared=no

View File

@ -1,16 +0,0 @@
#!/bin/sh
set -e
. /home/build/env.sh
if [ $# -ne 4 ]; then
echo "Usage: build-kore.sh [openssl] [python] [curl] [nghttp2]"
exit 1
fi
export PATH=$FAKEROOT/Python-$2/bin:$FAKEROOT/curl-$3/bin:$PATH
export OPENSSL_PATH=$FAKEROOT/openssl-$1
kodev clean
kodev build

View File

@ -1,67 +0,0 @@
#!/bin/sh
set -e
if [ $# -ne 4 ]; then
echo "Usage: build-kore.sh [openssl] [python] [curl] [nghttp2]"
exit 1
fi
# Set ROOT based on the versions given.
VERSION=kore_ossl-$1_python-$2_curl-$3_nghttp2-$4
ROOT=`pwd`/$VERSION
# Pull in the rest of the functions.
. ./helpers.sh
OPENSSL=openssl-$1
PYTHON=Python-$2
CURL=curl-$3
NGHTTP2=nghttp2-$4
# Build OpenSSL
echo "Building $OPENSSL"
fetch "https://www.openssl.org/source/$OPENSSL.tar.gz" $OPENSSL
build $OPENSSL ./config no-shared --prefix=$FAKEROOT/$OPENSSL
# Build Python
echo "Building $PYTHON"
fetch "https://www.python.org/ftp/python/$2/$PYTHON.tgz" $PYTHON
default_build $PYTHON
# Build nghttp2
echo "Building $NGHTTP2"
fetch \
"https://github.com/nghttp2/nghttp2/releases/download/v$4/$NGHTTP2.tar.gz" \
$NGHTTP2
default_build $NGHTTP2 --enable-lib-only --prefix=$FAKEROOT/$NGHTTP2 \
--enable-shared=no
# Build curl
echo "Building $CURL"
export PKG_CONFIG="pkg-config --static"
export PKG_CONFIG_PATH="$FAKEROOT/$OPENSSL/lib/pkgconfig:$FAKEROOT/$NGHTTP2/lib/pkgconfig"
fetch "https://curl.haxx.se/download/$CURL.tar.gz" $CURL
default_build $CURL --enable-shared=no
# Now we can build kore.
unset PKG_CONFIG
unset PKG_CONFIG_PATH
export PATH=$FAKEROOT/bin:$PATH
export OPENSSL_PATH=$FAKEROOT/$OPENSSL
cd $ROOT
if [ ! -d kore ]; then
git clone https://git.kore.io/kore.git
fi
pushd kore
make clean
LDFLAGS=-L$FAKEROOT/$NGHTTP2/lib make PYTHON=1 CURL=1 ACME=1
mv kore $ROOT/kore.bin
popd

View File

@ -1,16 +0,0 @@
#!/bin/sh
set -e
. ./env.sh
if [ $# -ne 1 ]; then
echo "Usage: build-nghttp2.sh [release]"
exit 1
fi
NAME=nghttp2-$1
fetch "https://github.com/nghttp2/nghttp2/releases/download/v$1/$NAME.tar.gz" $NAME
default_build $NAME --enable-lib-only --prefix=$FAKEROOT/$NAME --enable-shared=no

View File

@ -1,16 +0,0 @@
#!/bin/sh
set -e
. ./env.sh
if [ $# -ne 1 ]; then
echo "Usage: build-openssl.sh [release]"
exit 1
fi
NAME=openssl-$1
fetch "https://www.openssl.org/source/$NAME.tar.gz" $NAME
build $NAME ./config no-shared --prefix=$FAKEROOT/$NAME

View File

@ -1,17 +0,0 @@
#!/bin/sh
set -e
set -x
. ./env.sh
if [ $# -ne 1 ]; then
echo "Usage: build-python.sh [release]"
exit 1
fi
NAME=Python-$1
fetch "https://www.python.org/ftp/python/$1/$NAME.tgz" $NAME
default_build $NAME

View File

@ -1,72 +0,0 @@
if [ -z "$ROOT" ]; then
echo "No ROOT set"
exit 1
fi
SOURCES=sources
BUILD=$ROOT/build
FAKEROOT=$ROOT/fakeroot
LASTDIR=`pwd`
pushd() {
LASTDIR=`pwd`
cd $1
}
popd() {
cd $LASTDIR
}
fetch() {
url=$1
name=$2
if [ -f $SOURCES/$name.tar.gz ]; then
return
fi
curl -L "$url" > $SOURCES/$name.tar.gz
}
default_build() {
name=$1
shift
config=$*
build $name ./configure --prefix=$FAKEROOT/$NAME $config
}
build() {
name=$1
shift
configcmd=$*
if [ -f $BUILD/$name/.built ]; then
return
fi
rm -rf $BUILD/$name
rm -rf $FAKEROOT/$name
tar -zvxf $SOURCES/$name.tar.gz -C $BUILD
pushd $BUILD/$name
mkdir -p $FAKEROOT/$name
$configcmd
make -j
make install
popd
touch $BUILD/$name/.built
}
setup() {
mkdir -p $BUILD
mkdir -p $SOURCES
mkdir -p $FAKEROOT
}
setup

View File

@ -287,4 +287,5 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_clone3 435

View File

@ -387,6 +387,7 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_clone3 435
#define __ARM_NR_breakpoint 0x0f0001
#define __ARM_NR_cacheflush 0x0f0002

View File

@ -343,4 +343,5 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_clone3 435

View File

@ -5,10 +5,16 @@ if [ $# -ne 1 ]; then
exit 1
fi
python3-config $1 --embed > /dev/null 2>&1
if [ ! -z "$PYTHON_CONFIG" ]; then
BIN=$PYTHON_CONFIG
else
BIN=python3-config
fi
$BIN $1 --embed > /dev/null 2>&1
if [ $? -eq 0 ]; then
python3-config $1 --embed
$BIN $1 --embed
else
python3-config $1
$BIN $1
fi

View File

@ -1,278 +0,0 @@
.TH KODEV 1
.SH NAME
kodev \- Kore project management tool
.SH SYNOPSIS
.BR kodev
[\fIOPTION\fR] ...
.SH DESCRIPTION
This documentation describes the application management tools for building and
running a Kore project. For information regarding the technical interface and
C bindings, look to
.BR kore(3)
where these functions and structures are described.
.BR Kore
projects may be managed using the following OPTIONS;
.BR create
.RS
Create a new application skeleton with the name that is passed to it. This will
create a new directory with all the files required to begin hacking. See the
\fBGENERATED FILES\fR section for more information.
.RE
.BR build
.RS
Build the application. See the \fBBUILDING\fR section for more information.
.RE
.BR run
.RS
Start the application in the foreground. See the \fBRUNNING\fR section for
more information.
.RE
.BR reload
.RS
Reload the application. This is a shortcut to sending SIGHUP to the parent
process (see kore_pid).
.RE
.BR info
.RS
Show information about the application configuration. Namely; active flavor,
output type, Kore features, Kore source and Kore binary.
.RE
.BR clean
.RS
Cleanup the build files.
.RE
.BR flavor
.RS
Switch between build flavors with the argument being the new flavor.
.RE
.BR help
.RS
Show the help synopsis.
.RE
.SH GENERATED FILES
Executing the
.BR create
command will generate several new files under the directory matching the
application name specified.
These files are:
.RS
.BR conf/build.conf
.RS
The build configuration.
.RE
.BR conf/app.conf
.RS
The Kore application configuration.
.RE
.BR src/app.c
.RS
The initial placeholder source code.
.RE
.BR cert/server.pem
.RS
The self-signed auto-generated x509 certificate.
.RE
.BR cert/key.pem
.RS
The key matching the self-signed x509 certificate.
.RE
.BR dh2048.pem
.RS
The 2048-bit DH parameters used by TLS.
.RE
.RE
Those files are:
.RS
.BR kore.conf
.RS
The Kore application configuration.
.RE
.RE
.RS
.BR handlers.py
.RS
The initial placeholder python page handler.
.RE
.RE
.RS
.BR __init__.py
.RS
The python initialization code. Sets up the kore listener, etc.
.RE
.RE
.RS
.BR cert/server.pem
.RS
The self-signed auto-generated x509 certificate.
.RE
.RE
.RS
.BR cert/key.pem
.RS
The key matching the self-signed x509 certificate.
.RE
.RE
.RS
.BR dh2048.pem
.RS
The 2048-bit DH parameters used by TLS.
.RE
.RE
.SH BUILDING
Executing the
.BR build
command will build your application. How this happens is instructed by
the
.BR conf/build.conf
configuration file. This file supports the following directives:
.RS
.BR single_binary
[yes|no]
.RS
If set to \fByes\fR the build system will produce a single binary containing
both your application code and the Kore code allowing you to distribute
your application more easily.
If set to \fBno\fR the build system will produce a standard dynamically
linked library that will be loaded into Kore at runtime.
.RE
.RE
.RS
.BR kore_source
[path]
.RS
Must be set to point to the a Kore source code directory. Used only if
.BR single_binary
option is set to \fByes\fR.
.BR Example:
kore_source=/home/joris/src/kore
.RE
.RE
.RE
.RS
.BR kore_flavor
[build options]
.RS
Defines the build arguments for building Kore. Used only if
.BR single_binary
option is set to \fByes\fR.
.BR Example:
kore_flavor=NOTLS=1
.RE
.RE
.RS
.BR cflags
.RS
Standard
.BR CFLAGS
used when compiling the application source code.
.RE
.RE
.RS
.BR ldflags
.RS
Standard
.BR LDFLAGS
used when linking the application source code.
.RE
.RE
Note that the
.BR build
command obeys the environment variables
.BR CC
and
.BR CXX
.SH RUNNING
Executing the
.BR run
command will start your application in the foreground.
What binary it executes depends
on whether or not the
.BR single_binary
flag was set in build configuration. If the
.BR single_binary
flag was enabled the
.BR run
command will execute the binary produced by the build system. If the
.BR single_binary
flag was not enabled the
.BR run
command will execute the
.BR $PREFIX/bin/kore
binary.
In both cases the
.BR run
command will pass the \fB\-fnr\fR command line options to the binary.
.RE
.SH EXAMPLES
Changing flavor of the build;
.RS
$ kodev flavor osx
.RE
Building your application;
.RS
$ kodev build
.RE
.SH REPORTING BUGS, CONTRIBUTING && MORE
If you run into any bugs, have suggestions or patches, please contact me at
.BR <joris@coders.se>
More information can be found at
.BR <https://kore.io/>
.SH AUTHOR
.BR Kore
developed by Joris Vink
.BR <joris@coders.se>
Manpage authored by Guy Nankivell
.BR <guynankivell@gmail.com>
.SH LICENCE
Usage of this software is provided under the
.BR ISC
license which may be found, with the source, at
.BR <https://github.com/jorisvink/kore>

View File

@ -298,6 +298,12 @@ kore_platform_sandbox(void)
#endif
}
u_int32_t
kore_platform_random_uint32(void)
{
return (arc4random());
}
#if defined(KORE_USE_PLATFORM_PLEDGE)
void
kore_platform_pledge(void)

189
src/cli.c
View File

@ -43,6 +43,24 @@
#include <unistd.h>
#include <utime.h>
/*
* Turn off deprecated function warnings when building against OpenSSL 3.
*
* The OpenSSL 3 library deprecated most low-level functions in favour
* for their higher level APIs.
*
* I am planning a replacement, but for now we can still make it build
* and function by ignoring these warnings completely.
*
* The functions in question are:
* - SHA256_Init, SHA256_Update, SHA256_Final
* - RSA_new, RSA_generate_key_ex
* - EVP_PKEY_assign
*/
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#define errno_s strerror(errno)
#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL)
@ -54,6 +72,8 @@
#define BUILD_C 1
#define BUILD_CXX 2
#define CLANGDB_FILE_PATH "compile_commands.json"
struct cli_buf {
u_int8_t *data;
size_t length;
@ -120,6 +140,8 @@ static char *cli_text_trim(char *, size_t);
static char *cli_read_line(FILE *, char *, size_t);
static long long cli_strtonum(const char *, long long, long long);
static int cli_split_string(char *, const char *, char **, size_t);
static int cli_generate_compiler_args(struct cfile *, char **,
char **, size_t);
static void usage(void) __attribute__((noreturn));
static void fatal(const char *, ...) __attribute__((noreturn))
@ -186,6 +208,7 @@ static void cli_run(int, char **);
static void cli_help(int, char **);
static void cli_info(int, char **);
static void cli_build(int, char **);
static void cli_build_help(void);
static void cli_clean(int, char **);
static void cli_source(int, char **);
static void cli_reload(int, char **);
@ -194,6 +217,7 @@ static void cli_cflags(int, char **);
static void cli_ldflags(int, char **);
static void cli_genasset(int, char **);
static void cli_genasset_help(void);
static void cli_build_clangdb(const char *);
#if !defined(KODEV_MINIMAL)
static void cli_create(int, char **);
@ -427,10 +451,6 @@ main(int argc, char **argv)
for (i = 0; cmds[i].name != NULL; i++) {
if (!strcmp(argv[0], cmds[i].name)) {
if (strcmp(argv[0], "create")) {
argc--;
argv++;
}
command = &cmds[i];
cmds[i].cb(argc, argv);
break;
@ -545,7 +565,7 @@ cli_flavor(int argc, char **argv)
(void)cli_buildopt_new("_default");
cli_buildopt_parse("conf/build.conf");
if (argc == 0) {
if (argc < 2) {
cli_flavor_load();
TAILQ_FOREACH(bopt, &build_options, list) {
if (!strcmp(bopt->name, "_default"))
@ -557,13 +577,91 @@ cli_flavor(int argc, char **argv)
}
}
} else {
cli_flavor_change(argv[0]);
printf("changed build flavor to: %s\n", argv[0]);
cli_flavor_change(argv[1]);
printf("changed build flavor to: %s\n", argv[1]);
}
cli_buildopt_cleanup();
}
static void
cli_build_clangdb(const char *pwd)
{
struct cfile *cf;
int fd, i, nargs, genpath_len;
char *args[64 + CFLAGS_MAX], *genpath, *ext;
printf("generating %s...\n", CLANGDB_FILE_PATH);
genpath_len = cli_vasprintf(&genpath, "%s/", object_dir);
cli_file_open(CLANGDB_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY, &fd);
cli_file_writef(fd, "[\n");
TAILQ_FOREACH(cf, &source_files, list) {
int tempbuild = cf->build;
/* Exclude generated source files. */
if (!strncmp(cf->fpath, genpath, genpath_len))
continue;
if (cf->build == BUILD_NOBUILD) {
if ((ext = strrchr(cf->fpath, '.')) == NULL)
continue;
/*
* Temporarily rewrite build to our file type to
* include unchanged files.
*/
if (!strcmp(ext, ".cpp"))
cf->build = BUILD_CXX;
else if (!strcmp(ext, ".c"))
cf->build = BUILD_C;
else
continue;
}
cli_file_writef(fd, "\t{\n");
cli_file_writef(fd, "\t\t\"arguments\": [\n");
nargs = cli_generate_compiler_args(cf, NULL, args,
64 + CFLAGS_MAX);
for (i = 0; i < nargs; i++) {
cli_file_writef(fd, "\t\t\t\"%s\"%s\n",
args[i], i == nargs - 1 ? "" : ",");
}
cli_file_writef(fd, "\t\t],\n");
cli_file_writef(fd, "\t\t\"directory\": \"%s\",\n", pwd);
cli_file_writef(fd, "\t\t\"file\": \"%s\"\n", cf->fpath);
cli_file_writef(fd, "\t}%s\n",
cf == TAILQ_LAST(&source_files, cfile_list) ? "" : ",");
cf->build = tempbuild;
}
cli_file_writef(fd, "]\n");
cli_file_close(fd);
free(genpath);
printf("%s generated successfully...\n", CLANGDB_FILE_PATH);
}
static void
cli_build_help(void)
{
printf("Usage: kodev build [-c]\n");
printf("Synopsis:\n");
printf(" Build a kore application in current working directory.\n");
printf("\n");
printf(" Optional flags:\n");
printf("\t-c = generate Clang compilation database after build\n");
exit(1);
}
static void
cli_build(int argc, char **argv)
{
@ -581,6 +679,23 @@ cli_build(int argc, char **argv)
char *sofile, *config;
char *assets_path, *p, *src_path;
char pwd[PATH_MAX], *assets_header;
int ch, clangdb;
clangdb = 0;
while ((ch = getopt(argc, argv, "ch")) != -1) {
switch (ch) {
case 'h':
cli_build_help();
break;
case 'c':
clangdb = 1;
break;
default:
cli_build_help();
break;
}
}
if (getcwd(pwd, sizeof(pwd)) == NULL)
fatal("could not get cwd: %s", errno_s);
@ -733,6 +848,9 @@ cli_build(int argc, char **argv)
printf("nothing to be done!\n");
}
if (clangdb)
cli_build_clangdb(pwd);
if (run_after == 0)
cli_buildopt_cleanup();
}
@ -891,7 +1009,7 @@ cli_genasset(int argc, char **argv)
if (getenv("KORE_OBJDIR") == NULL)
object_dir = out_dir;
if (argv[0] == NULL)
if (argv[1] == NULL)
cli_genasset_help();
(void)cli_vasprintf(&hdr, "%s/assets.h", out_dir);
@ -901,20 +1019,20 @@ cli_genasset(int argc, char **argv)
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 (stat(argv[1], &st) == -1)
fatal("%s: %s", argv[1], errno_s);
if (S_ISDIR(st.st_mode)) {
if (cli_dir_exists(argv[0]))
cli_find_files(argv[0], cli_build_asset);
if (cli_dir_exists(argv[1]))
cli_find_files(argv[1], 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);
basename(argv[1]));
cli_build_asset(argv[1], &dp);
} else {
fatal("%s is not a directory or regular file", argv[0]);
fatal("%s is not a directory or regular file", argv[1]);
}
cli_file_writef(s_fd, "\n#endif\n");
@ -1540,35 +1658,35 @@ cli_generate_certs(void)
}
#endif
static void
cli_compile_source_file(void *arg)
static int
cli_generate_compiler_args(struct cfile *cf, char **cout,
char **args, size_t elm)
{
struct cfile *cf;
int idx, i;
char **flags;
char *compiler;
int flags_count;
char *args[34 + CFLAGS_MAX];
cf = arg;
char *compiler, **flags;
int idx, i, flags_count;
switch (cf->build) {
case BUILD_C:
compiler = compiler_c;
flags = cflags;
compiler = compiler_c;
flags_count = cflags_count;
break;
case BUILD_CXX:
compiler = compiler_cpp;
flags = cxxflags;
compiler = compiler_cpp;
flags_count = cxxflags_count;
break;
default:
fatal("cli_compile_file: unexpected file type: %d",
cf->build);
break;
fatal("%s: unexpected file type: %d", __func__, cf->build);
/* NOTREACHED */
}
if ((size_t)flags_count + 2 >= elm)
fatal("%s: flags %d >= %zu", __func__, flags_count, elm);
if (cout != NULL)
*cout = compiler;
idx = 0;
args[idx++] = compiler;
@ -1583,6 +1701,17 @@ cli_compile_source_file(void *arg)
args[idx++] = cf->opath;
args[idx] = NULL;
return (idx);
}
static void
cli_compile_source_file(void *arg)
{
char *compiler;
char *args[64 + CFLAGS_MAX];
cli_generate_compiler_args(arg, &compiler, args, 64 + CFLAGS_MAX);
execvp(compiler, args);
fatal("failed to start '%s': %s", compiler, errno_s);
}

View File

@ -93,6 +93,7 @@ static int configure_socket_backlog(char *);
static int configure_privsep_skip(char *);
static int configure_privsep_root(char *);
static int configure_privsep_runas(char *);
static int configure_deployment(char *);
#if defined(KORE_USE_PLATFORM_PLEDGE)
static int configure_add_pledge(char *);
@ -157,7 +158,6 @@ static int configure_task_threads(char *);
#endif
#if defined(KORE_USE_PYTHON)
static int configure_deployment(char *);
static int configure_python_path(char *);
static int configure_python_import(char *);
#endif
@ -240,6 +240,7 @@ static struct {
{ "tls_cipher", configure_tls_cipher },
{ "tls_dhparam", configure_tls_dhparam },
{ "rand_file", configure_rand_file },
{ "deployment", configure_deployment },
#if defined(KORE_USE_ACME)
{ "acme_email", configure_acme_email },
{ "acme_provider", configure_acme_provider },
@ -269,9 +270,6 @@ static struct {
{ "websocket_maxframe", configure_websocket_maxframe },
{ "websocket_timeout", configure_websocket_timeout },
#endif
#if defined(KORE_USE_PYTHON)
{ "deployment", configure_deployment },
#endif
#if defined(KORE_USE_PGSQL)
{ "pgsql_conn_max", configure_pgsql_conn_max },
{ "pgsql_queue_limit", configure_pgsql_queue_limit },
@ -524,7 +522,6 @@ kore_parse_config_file(FILE *fp)
}
}
#if defined(KORE_USE_PYTHON)
int
kore_configure_setting(const char *name, char *value)
{
@ -544,7 +541,6 @@ kore_configure_setting(const char *name, char *value)
kore_log(LOG_NOTICE, "ignoring unknown kore.config.%s setting", name);
return (KORE_RESULT_OK);
}
#endif
static void
configure_check_var(char **var, const char *other, const char *logmsg)
@ -2015,7 +2011,6 @@ configure_task_threads(char *option)
}
#endif
#if defined(KORE_USE_PYTHON)
static int
configure_deployment(char *value)
{
@ -2040,6 +2035,7 @@ configure_deployment(char *value)
return (KORE_RESULT_OK);
}
#if defined(KORE_USE_PYTHON)
static int
configure_python_path(char *path)
{

View File

@ -399,3 +399,52 @@ kore_connection_nonblock(int fd, int nodelay)
return (KORE_RESULT_OK);
}
void
kore_connection_log(struct connection *c, const char *fmt, ...)
{
struct kore_buf buf;
va_list args;
char *ptr;
kore_buf_init(&buf, 128);
kore_buf_appendf(&buf, "ip=[%s] msg=[", kore_connection_ip(c));
va_start(args, fmt);
kore_buf_appendv(&buf, fmt, args);
va_end(args);
kore_buf_appendf(&buf, "]");
ptr = kore_buf_stringify(&buf, NULL);
kore_log(LOG_NOTICE, "%s", ptr);
kore_free(ptr);
}
const char *
kore_connection_ip(struct connection *c)
{
static char addr[INET6_ADDRSTRLEN];
memset(addr, 0, sizeof(addr));
switch (c->family) {
case AF_INET:
if (inet_ntop(c->family,
&(c->addr.ipv4.sin_addr), addr, sizeof(addr)) == NULL)
fatal("inet_ntop: %s", errno_s);
break;
case AF_INET6:
if (inet_ntop(c->family,
&(c->addr.ipv6.sin6_addr), addr, sizeof(addr)) == NULL)
fatal("inet_ntop: %s", errno_s);
break;
case AF_UNIX:
(void)kore_strlcpy(addr, "unix-socket", sizeof(addr));
break;
default:
fatal("unknown family %d", c->family);
}
return (addr);
}

View File

@ -195,7 +195,7 @@ filemap_serve(struct http_request *req, const struct filemap_entry *map)
return;
}
if (!http_argument_urldecode(fpath)) {
if (!http_argument_urldecode(fpath, 1)) {
http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
return;
}

View File

@ -799,7 +799,7 @@ http_header_recv(struct netbuf *nb)
c = nb->owner;
if (nb->b_len < 4)
if (nb->s_off < 4)
return (KORE_RESULT_OK);
if (!isalpha(nb->buf[0])) {
@ -811,8 +811,14 @@ http_header_recv(struct netbuf *nb)
end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4);
if (end_headers == NULL) {
end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2);
if (end_headers == NULL)
if (end_headers == NULL) {
if (nb->s_off == http_header_max) {
http_error_response(c,
HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
skip = 2;
}
@ -919,6 +925,7 @@ http_header_recv(struct netbuf *nb)
}
if (req->content_length == 0) {
c->http_timeout = 0;
req->flags |= HTTP_REQUEST_COMPLETE;
req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
return (KORE_RESULT_OK);
@ -1001,7 +1008,7 @@ http_argument_get(struct http_request *req, const char *name,
}
int
http_argument_urldecode(char *arg)
http_argument_urldecode(char *arg, int url)
{
u_int8_t v;
int err;
@ -1039,8 +1046,14 @@ http_argument_urldecode(char *arg)
if (err != KORE_RESULT_OK)
return (err);
if (v <= 0x1f || v == 0x7f)
return (KORE_RESULT_ERROR);
if (url) {
if (v <= 0x1f || v == 0x7f)
return (KORE_RESULT_ERROR);
} else {
if ((v <= 0x1f || v == 0x7f) &&
(v != '\n' && v != '\r'))
return (KORE_RESULT_ERROR);
}
*in++ = (char)v;
p += 3;
@ -1791,6 +1804,9 @@ http_validate_header(char *header)
break;
}
if (*p >= 'A' && *p <= 'Z')
*p += 32;
if (http_token[idx] == 0x00)
return (NULL);
}
@ -2274,7 +2290,7 @@ http_argument_add(struct http_request *req, char *name, char *value, int qs,
struct kore_route_params *p;
if (decode) {
if (!http_argument_urldecode(name))
if (!http_argument_urldecode(name, qs))
return;
}
@ -2291,7 +2307,7 @@ http_argument_add(struct http_request *req, char *name, char *value, int qs,
continue;
if (decode) {
if (!http_argument_urldecode(value))
if (!http_argument_urldecode(value, qs))
return;
}
@ -2342,6 +2358,7 @@ http_body_update(struct http_request *req, const void *data, size_t len)
req->content_length -= len;
if (req->content_length == 0) {
req->owner->http_timeout = 0;
req->owner->rnb->extra = NULL;
http_request_wakeup(req);
req->flags |= HTTP_REQUEST_COMPLETE;

View File

@ -63,6 +63,16 @@
#include "acme.h"
#endif
/*
* Disable deprecated declaration warnings if we're building against
* OpenSSL 3 as they marked all low-level APIs as deprecated.
*
* Work is being done to replace these, but for now let things build.
*/
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#define RAND_TMP_FILE "rnd.tmp"
#define RAND_POLL_INTERVAL (1800 * 1000)
#define RAND_FILE_SIZE 1024
@ -168,10 +178,11 @@ struct key {
TAILQ_ENTRY(key) list;
};
char *kore_rand_file = NULL;
static TAILQ_HEAD(, key) keys;
static int initialized = 0;
/* Helper for weird API designs (looking at you OpenSSL). */
union deconst {
void *p;
const void *cp;
};
#if defined(KORE_USE_ACME)
@ -251,8 +262,6 @@ static void keymgr_x509_msg(const char *, const void *, size_t, int, int);
static void keymgr_rsa_encrypt(struct kore_msg *, const void *,
struct key *);
static void keymgr_ecdsa_sign(struct kore_msg *, const void *,
struct key *);
#if defined(__OpenBSD__)
#if defined(KORE_USE_ACME)
@ -262,6 +271,11 @@ static const char *keymgr_pledges = "stdio rpath";
#endif
#endif
static TAILQ_HEAD(, key) keys;
static int initialized = 0;
char *kore_rand_file = NULL;
void
kore_keymgr_run(void)
{
@ -658,9 +672,6 @@ keymgr_msg_recv(struct kore_msg *msg, const void *data)
case EVP_PKEY_RSA:
keymgr_rsa_encrypt(msg, data, key);
break;
case EVP_PKEY_EC:
keymgr_ecdsa_sign(msg, data, key);
break;
default:
break;
}
@ -685,6 +696,7 @@ keymgr_msg_recv(struct kore_msg *msg, const void *data)
static void
keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
{
union deconst cp;
int ret;
RSA *rsa;
const struct kore_keyreq *req;
@ -692,7 +704,9 @@ keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
u_int8_t buf[1024];
req = (const struct kore_keyreq *)data;
rsa = EVP_PKEY_get0_RSA(key->pkey);
cp.cp = EVP_PKEY_get0_RSA(key->pkey);
rsa = cp.p;
keylen = RSA_size(rsa);
if (req->data_len > keylen || keylen > sizeof(buf))
@ -706,32 +720,6 @@ keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret);
}
static void
keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
{
size_t len;
EC_KEY *ec;
const struct kore_keyreq *req;
unsigned int siglen;
u_int8_t sig[1024];
req = (const struct kore_keyreq *)data;
ec = EVP_PKEY_get0_EC_KEY(key->pkey);
len = ECDSA_size(ec);
if (req->data_len > len || len > sizeof(sig))
return;
if (ECDSA_sign(EVP_PKEY_NONE, req->data, req->data_len,
sig, &siglen, ec) == 0)
return;
if (siglen > sizeof(sig))
return;
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, sig, siglen);
}
static void
keymgr_x509_msg(const char *domain, const void *data, size_t len,
int target, int msg)
@ -759,7 +747,7 @@ keymgr_x509_msg(const char *domain, const void *data, size_t len,
static void
keymgr_acme_init(void)
{
RSA *rsa;
const RSA *rsa;
struct key *key;
char *e, *n;
int needsreg;

View File

@ -46,6 +46,10 @@
#include "python_api.h"
#endif
#if defined(KORE_USE_LUA)
#include "lua_api.h"
#endif
#if defined(KORE_USE_ACME)
#include "acme.h"
#endif
@ -61,7 +65,8 @@ int skip_runas = 0;
int skip_chroot = 0;
u_int8_t worker_count = 0;
char **kore_argv = NULL;
int kore_foreground = 0;
int kore_mem_guard = 0;
int kore_foreground = 1;
char *kore_progname = NULL;
u_int32_t kore_socket_backlog = 5000;
int kore_quit = KORE_QUIT_NONE;
@ -82,42 +87,51 @@ static void kore_server_shutdown(void);
static void kore_server_start(int, char *[]);
static void kore_call_parent_configure(int, char **);
#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
static const char *parent_config_hook = KORE_PYTHON_CONFIG_HOOK;
static const char *parent_teardown_hook = KORE_PYTHON_TEARDOWN_HOOK;
#else
#if !defined(KORE_SINGLE_BINARY)
static const char *rarg0 = NULL;
#endif
static const char *parent_config_hook = KORE_CONFIG_HOOK;
static const char *parent_teardown_hook = KORE_TEARDOWN_HOOK;
#if defined(KORE_SINGLE_BINARY)
static const char *parent_daemonized_hook = KORE_DAEMONIZED_HOOK;
#endif
#endif
static void
usage(void)
{
#if defined(KORE_USE_PYTHON)
printf("Usage: %s [options] [app | app.py]\n", __progname);
#else
printf("Usage: %s [options]\n", __progname);
#endif
if (kore_runtime_count() > 0) {
printf("Usage: %s [options] [app | script]\n", __progname);
} else {
printf("Usage: %s [options]\n", __progname);
}
printf("\n");
printf("Available options:\n");
printf("Command-line options:\n");
#if !defined(KORE_SINGLE_BINARY)
printf("\t-c\tconfiguration to use\n");
printf("\t-c\tThe configuration file to load when starting.\n");
#endif
#if defined(KORE_DEBUG)
printf("\t-d\trun with debug on\n");
#endif
printf("\t-f\tstart in foreground\n");
printf("\t-h\tthis help text\n");
printf("\t-n\tdo not chroot on any worker\n");
printf("\t-q\tonly log errors\n");
printf("\t-r\tdo not change user on any worker\n");
printf("\t-v\tdisplay %s build information\n", __progname);
printf("\t-f\tDo not daemonize, everything runs in the foreground.\n");
printf("\t-h\tThis help text.\n");
printf("\t-n\tDo not do the chroot privsep step.\n");
printf("\t-q\tQuiet mode, only logs errors.\n");
printf("\t-r\tDo not do the privsep user swapping step.\n");
printf("\t-v\tDisplay %s build information.\n", __progname);
printf("\nFind more information on https://kore.io\n");
printf("\n");
printf("Environment options:\n");
printf(" env KORE_MEM_GUARD=1\n");
printf(" Enables memory pool guards and other protections.\n");
printf("\n");
printf(" Enabling this will include guard pages for each\n");
printf(" pool entry allocations and mark pool entries as\n");
printf(" PROT_NONE when unused.\n");
printf("\n");
printf(" This catches bugs and prevents memory vulnerabilities\n");
printf(" but with performance and memory pressure costs.\n");
printf("\n");
exit(1);
}
@ -138,17 +152,22 @@ version(void)
#if defined(KORE_USE_TASKS)
printf("tasks ");
#endif
#if defined(KORE_DEBUG)
printf("debug ");
#endif
#if defined(KORE_USE_PYTHON)
printf("python-%s ", PY_VERSION);
#endif
#if defined(KORE_USE_LUA)
printf("lua-%s.%s.%s ",
LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
#endif
#if defined(KORE_USE_ACME)
printf("acme ");
#endif
#if defined(KORE_DEBUG)
printf("debug ");
#endif
if (!kore_tls_supported())
printf("notls ");
printf("\n");
exit(0);
}
@ -156,10 +175,10 @@ version(void)
int
main(int argc, char *argv[])
{
struct kore_runtime_call *rcall;
#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
#if !defined(KORE_SINGLE_BINARY)
struct stat st;
#endif
struct kore_runtime_call *rcall;
kore_argc = argc;
kore_argv = argv;
@ -171,6 +190,7 @@ main(int argc, char *argv[])
kore_mem_init();
kore_msg_init();
kore_log_init();
kore_tls_init();
kore_progname = kore_strdup(argv[0]);
kore_proctitle_setup();
@ -180,23 +200,22 @@ main(int argc, char *argv[])
argv += optind;
#endif
#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
if (argc > 0) {
kore_pymodule = argv[0];
argc--;
argv++;
} else {
kore_pymodule = NULL;
}
if (kore_pymodule) {
if (lstat(kore_pymodule, &st) == -1) {
fatal("failed to stat '%s': %s",
kore_pymodule, errno_s);
#if !defined(KORE_SINGLE_BINARY)
if (kore_runtime_count() > 0) {
if (argc > 0) {
rarg0 = argv[0];
argc--;
argv++;
}
if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
fatal("%s: not a directory or file", kore_pymodule);
if (rarg0) {
if (lstat(rarg0, &st) == -1) {
if (errno == ENOENT)
rarg0 = NULL;
else
fatal("stat(%s): %s", rarg0, errno_s);
}
}
}
#endif
@ -222,35 +241,30 @@ main(int argc, char *argv[])
#endif
kore_domain_init();
kore_module_init();
kore_tls_init();
#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
if (config_file == NULL)
#if !defined(KORE_SINGLE_BINARY)
if (kore_runtime_count() == 0 && config_file == NULL)
usage();
#endif
kore_module_load(NULL, NULL, KORE_MODULE_NATIVE);
#if defined(KORE_USE_PYTHON)
kore_python_init();
#if !defined(KORE_SINGLE_BINARY)
if (kore_pymodule) {
kore_module_load(kore_pymodule, NULL, KORE_MODULE_PYTHON);
if (S_ISDIR(st.st_mode) && chdir(kore_pymodule) == -1)
fatal("chdir(%s): %s", kore_pymodule, errno_s);
} else {
/* swap back to non-python hooks. */
parent_config_hook = KORE_CONFIG_HOOK;
parent_teardown_hook = KORE_TEARDOWN_HOOK;
}
#endif
#if defined(KORE_USE_LUA)
kore_lua_init();
#endif
#if !defined(KORE_SINGLE_BINARY)
if (kore_runtime_count() > 0 && rarg0 != NULL)
kore_runtime_resolve(rarg0, &st);
#endif
#if defined(KORE_SINGLE_BINARY)
kore_call_parent_configure(argc, argv);
#endif
#if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY)
if (kore_pymodule)
#else
if (kore_runtime_count() > 0 && rarg0 != NULL)
kore_call_parent_configure(argc, argv);
#endif
@ -292,6 +306,10 @@ main(int argc, char *argv[])
kore_python_cleanup();
#endif
#if defined(KORE_USE_LUA)
kore_lua_cleanup();
#endif
kore_mem_cleanup();
return (kore_quit);
@ -303,9 +321,9 @@ kore_default_getopt(int argc, char **argv)
int ch;
#if !defined(KORE_SINGLE_BINARY)
while ((ch = getopt(argc, argv, "c:fhnqrv")) != -1) {
while ((ch = getopt(argc, argv, "c:dfhnqrv")) != -1) {
#else
while ((ch = getopt(argc, argv, "fhnqrv")) != -1) {
while ((ch = getopt(argc, argv, "dfhnqrv")) != -1) {
#endif
switch (ch) {
#if !defined(KORE_SINGLE_BINARY)
@ -315,8 +333,12 @@ kore_default_getopt(int argc, char **argv)
fatal("strdup");
break;
#endif
case 'd':
kore_foreground = 0;
break;
case 'f':
kore_foreground = 1;
printf("note: -f is the default now, "
"use -d to daemonize\n");
break;
case 'h':
usage();
@ -752,6 +774,17 @@ kore_proctitle(const char *title)
memset(kore_argv[0] + len, 0, proctitle_maxlen - len);
}
void
kore_hooks_set(const char *config, const char *teardown, const char *daemonized)
{
parent_config_hook = config;
parent_teardown_hook = teardown;
#if defined(KORE_SINGLE_BINARY)
parent_daemonized_hook = daemonized;
#endif
}
static void
kore_proctitle_setup(void)
{
@ -789,6 +822,8 @@ kore_server_start(int argc, char *argv[])
if (!kore_quiet) {
kore_log(LOG_INFO, "%s %s starting, built=%s",
__progname, kore_version, kore_build_date);
kore_log(LOG_INFO, "memory pool protections: %s",
kore_mem_guard ? "enabled" : "disabled");
kore_log(LOG_INFO, "built-ins: "
#if defined(__linux__)
"seccomp "
@ -810,10 +845,15 @@ kore_server_start(int argc, char *argv[])
#endif
#if defined(KORE_USE_CURL)
"curl "
#endif
#if defined(KORE_USE_LUA)
"lua "
#endif
);
}
kore_tls_log_version();
if (kore_foreground == 0) {
if (daemon(1, 0) == -1)
fatal("cannot daemon(): %s", errno_s);
@ -829,12 +869,8 @@ kore_server_start(int argc, char *argv[])
kore_pid = getpid();
kore_write_kore_pid();
#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
kore_call_parent_configure(argc, argv);
#endif
#if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY)
if (kore_pymodule == NULL)
#if !defined(KORE_SINGLE_BINARY)
if (kore_runtime_count() == 0 || rarg0 == NULL)
kore_call_parent_configure(argc, argv);
#endif

View File

@ -15,6 +15,7 @@
*/
#include <sys/param.h>
#include <sys/random.h>
#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <sys/syscall.h>
@ -59,7 +60,7 @@ kore_platform_worker_setcpu(struct kore_worker *kw)
CPU_SET(kw->cpu, &cpuset);
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) == -1)
kore_log(LOG_WARNING, "kore_worker_setcpu(): %s", errno_s);
kore_log(LOG_NOTICE, "kore_worker_setcpu(): %s", errno_s);
}
void
@ -262,3 +263,18 @@ kore_platform_sandbox(void)
{
kore_seccomp_enable();
}
u_int32_t
kore_platform_random_uint32(void)
{
ssize_t ret;
u_int32_t val;
if ((ret = getrandom(&val, sizeof(val), 0)) == -1)
fatalx("getrandom(): %s", errno_s);
if ((size_t)ret != sizeof(val))
fatalx("getrandom() %zd != %zu", ret, sizeof(val));
return (val);
}

View File

@ -95,9 +95,9 @@ kore_log(int prio, const char *fmt, ...)
str = kore_buf_stringify(&buf, NULL);
if (kore_foreground || fp != stdout)
log_print(prio, "[parent]: %s\n", str);
log_print(prio, "proc=[parent] log=[%s]\n", str);
else
syslog(prio, "[parent]: %s", str);
syslog(prio, "proc=[parent] log=[%s]", str);
}
kore_buf_cleanup(&buf);
@ -120,10 +120,10 @@ log_from_worker(struct kore_msg *msg, const void *data)
name = kore_worker_name(wlog->wid);
if (kore_foreground || fp != stdout) {
log_print(wlog->prio, "%s: %.*s\n",
log_print(wlog->prio, "proc=%s log=[%.*s]\n",
name, (int)wlog->loglen, wlog->logmsg);
} else {
syslog(wlog->prio, "%s: %.*s",
syslog(wlog->prio, "proc=%s log=[%.*s]",
name, (int)wlog->loglen, wlog->logmsg);
}
}

601
src/lua.c Normal file
View File

@ -0,0 +1,601 @@
/*
* Copyright (c) 2023 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 "kore.h"
#if !defined(KORE_NO_HTTP)
#include "http.h"
#endif
#include "lua_api.h"
#include "lua_methods.h"
struct lua_http_request {
struct http_request *req;
};
struct lua_symbol {
lua_State *L;
int ref;
LIST_ENTRY(lua_symbol) list;
};
struct lua_module {
lua_State *L;
LIST_HEAD(, lua_symbol) symbols;
};
static int lua_runtime_resolve(const char *, const struct stat *);
static int lua_runtime_http_request(void *, struct http_request *);
static void lua_runtime_http_request_free(void *, struct http_request *);
static void lua_runtime_http_body_chunk(void *, struct http_request *,
const void *, size_t);
static int lua_runtime_validator(void *, struct http_request *,
const void *);
static void lua_runtime_wsmessage(void *, struct connection *,
u_int8_t, const void *, size_t);
static void lua_runtime_execute(void *);
static int lua_runtime_onload(void *, int);
static void lua_runtime_signal(void *, int);
static void lua_runtime_configure(void *, int, char **);
static void lua_runtime_connect(void *, struct connection *);
static void lua_module_load(struct kore_module *);
static void lua_module_free(struct kore_module *);
static void lua_module_reload(struct kore_module *);
static void *lua_module_getsym(struct kore_module *, const char *);
static void *lua_mem_alloc(void *, void *, size_t, size_t);
static int lua_kore_module_init(lua_State *);
static void lua_symbol_resolve(struct lua_symbol *, lua_State **);
static int lua_argument_get_bool(lua_State *, const char *);
static const char *lua_argument_get_string(lua_State *, const char *);
struct kore_module_functions kore_lua_module = {
.free = lua_module_free,
.load = lua_module_load,
.getsym = lua_module_getsym,
.reload = lua_module_reload
};
struct kore_runtime kore_lua_runtime = {
KORE_RUNTIME_LUA,
.resolve = lua_runtime_resolve,
.http_request = lua_runtime_http_request,
.http_body_chunk = lua_runtime_http_body_chunk,
.http_request_free = lua_runtime_http_request_free,
.validator = lua_runtime_validator,
.wsconnect = lua_runtime_connect,
.wsmessage = lua_runtime_wsmessage,
.wsdisconnect = lua_runtime_connect,
.onload = lua_runtime_onload,
.signal = lua_runtime_signal,
.connect = lua_runtime_connect,
.execute = lua_runtime_execute,
.configure = lua_runtime_configure,
};
#define LUA_CONSTANT(x) { #x, x }
static struct {
const char *symbol;
int value;
} lua_integers[] = {
LUA_CONSTANT(LOG_ERR),
LUA_CONSTANT(LOG_INFO),
LUA_CONSTANT(LOG_NOTICE),
LUA_CONSTANT(HTTP_METHOD_GET),
LUA_CONSTANT(HTTP_METHOD_PUT),
LUA_CONSTANT(HTTP_METHOD_POST),
LUA_CONSTANT(HTTP_METHOD_HEAD),
LUA_CONSTANT(HTTP_METHOD_PATCH),
LUA_CONSTANT(HTTP_METHOD_DELETE),
LUA_CONSTANT(HTTP_METHOD_OPTIONS),
{ NULL, -1 },
};
void
kore_lua_init(void)
{
if (!kore_configure_setting("deployment", "dev"))
fatal("failed to set initial deployment to dev");
}
void
kore_lua_cleanup(void)
{
}
static void *
lua_mem_alloc(void *uptr, void *ptr, size_t osize, size_t nsize)
{
if (nsize == 0) {
kore_free(ptr);
return (NULL);
}
return (kore_realloc(ptr, nsize));
}
static void
lua_symbol_resolve(struct lua_symbol *sym, lua_State **L)
{
lua_rawgeti(sym->L, LUA_REGISTRYINDEX, sym->ref);
*L = sym->L;
}
static int
lua_argument_get_bool(lua_State *L, const char *field)
{
int ret;
lua_pushstring(L, field);
ret = lua_gettable(L, -2);
if (ret == LUA_TNIL) {
lua_pop(L, 1);
return (0);
}
luaL_argcheck(L, ret == LUA_TBOOLEAN, 0, field);
ret = lua_toboolean(L, -1);
lua_pop(L, 1);
return (ret);
}
static const char *
lua_argument_get_string(lua_State *L, const char *field)
{
const char *v;
int type;
lua_pushstring(L, field);
type = lua_gettable(L, -2);
if (type == LUA_TNIL) {
lua_pop(L, 1);
return (NULL);
}
luaL_argcheck(L, type == LUA_TSTRING, 0, field);
v = lua_tostring(L, -1);
lua_pop(L, 1);
return (v);
}
static int
lua_kore_module_init(lua_State *L)
{
int i;
luaL_newlib(L, lua_kore_functions);
for (i = 0; lua_integers[i].symbol != NULL; i++) {
lua_pushstring(L, lua_integers[i].symbol);
lua_pushnumber(L, lua_integers[i].value);
lua_settable(L, -3);
}
return (1);
}
static void
lua_module_free(struct kore_module *module)
{
struct lua_symbol *sym;
struct lua_module *lua;
lua = module->handle;
while ((sym = LIST_FIRST(&lua->symbols)) != NULL) {
LIST_REMOVE(sym, list);
kore_free(sym);
}
kore_free(lua);
}
static void
lua_module_reload(struct kore_module *module)
{
lua_module_free(module);
lua_module_load(module);
}
static void
lua_module_load(struct kore_module *module)
{
struct lua_module *lua;
lua = kore_calloc(1, sizeof(*lua));
LIST_INIT(&lua->symbols);
if ((lua->L = lua_newstate(lua_mem_alloc, NULL)) == NULL)
fatal("luaL_newstate");
luaL_openlibs(lua->L);
luaL_requiref(lua->L, "kore", lua_kore_module_init, 1);
lua_pop(lua->L, 1);
luaL_newmetatable(lua->L, "http_request");
luaL_setfuncs(lua->L, lua_http_request_meta, 0);
lua_pop(lua->L, 1);
lua_pushliteral(lua->L, "http_request_methods");
luaL_newlib(lua->L, lua_http_request_methods);
lua_settable(lua->L, LUA_REGISTRYINDEX);
luaL_newlib(lua->L, lua_http_request_methods);
lua_pop(lua->L, 1);
if (luaL_loadfile(lua->L, module->path) != LUA_OK) {
fatal("%s: failed to import module (%s)", module->path,
lua_tostring(lua->L, -1));
}
if (lua_pcall(lua->L, 0, 0, 0) != LUA_OK) {
fatal("%s: failed to import module (%s)", module->path,
lua_tostring(lua->L, -1));
}
module->handle = lua;
}
static void *
lua_module_getsym(struct kore_module *module, const char *symbol)
{
int ref;
struct lua_module *lua;
struct lua_symbol *sym;
lua = module->handle;
if (lua_getglobal(lua->L, symbol) != LUA_TFUNCTION)
return (NULL);
if ((ref = luaL_ref(lua->L, LUA_REGISTRYINDEX)) == LUA_REFNIL)
return (NULL);
sym = kore_calloc(1, sizeof(*sym));
sym->ref = ref;
sym->L = lua->L;
LIST_INSERT_HEAD(&lua->symbols, sym, list);
return (sym);
}
static int
lua_runtime_resolve(const char *module, const struct stat *st)
{
const char *ext;
if (!S_ISREG(st->st_mode))
return (KORE_RESULT_ERROR);
ext = strrchr(module, '.');
if (ext == NULL || strcasecmp(ext, ".lua"))
return (KORE_RESULT_ERROR);
kore_module_load(module, NULL, KORE_MODULE_LUA);
return (KORE_RESULT_OK);
}
static int
lua_runtime_http_request(void *addr, struct http_request *req)
{
lua_State *L;
struct lua_http_request *lreq;
lua_symbol_resolve(addr, &L);
lreq = lua_newuserdata(L, sizeof(*lreq));
luaL_setmetatable(L, "http_request");
lreq->req = req;
if (lua_pcall(L, 1, 0, 0)) {
kore_log(LOG_NOTICE, "%s: failed to call handler: %s", __func__,
lua_tostring(L, -1));
http_response(req, 500, NULL, 0);
return (KORE_RESULT_OK);
}
return (KORE_RESULT_OK);
}
static void
lua_runtime_http_request_free(void *addr, struct http_request *req)
{
fatal("%s: not yet implemented", __func__);
}
static void
lua_runtime_http_body_chunk(void *addr, struct http_request *req,
const void *data, size_t len)
{
fatal("%s: not yet implemented", __func__);
}
static int
lua_runtime_validator(void *addr, struct http_request *req, const void *data)
{
fatal("%s: not yet implemented", __func__);
return (KORE_RESULT_ERROR);
}
static void
lua_runtime_wsmessage(void *addr, struct connection *c, u_int8_t op,
const void *data, size_t len)
{
fatal("%s: not yet implemented", __func__);
}
static void
lua_runtime_execute(void *addr)
{
lua_State *L;
lua_symbol_resolve(addr, &L);
if (lua_pcall(L, 0, 0, 0)) {
fatal("failed to execute function: %s",
lua_tostring(L, -1));
}
}
static void
lua_runtime_configure(void *addr, int argc, char **argv)
{
lua_State *L;
int idx;
lua_symbol_resolve(addr, &L);
lua_pushinteger(L, argc);
lua_newtable(L);
for (idx = 0; idx < argc; idx++) {
lua_pushstring(L, argv[idx]);
lua_rawseti(L, -2, idx);
}
if (lua_pcall(L, 2, 0, 0)) {
fatal("failed to configure your application (%s)",
lua_tostring(L, -1));
}
}
static int
lua_runtime_onload(void *addr, int action)
{
fatal("%s: not yet implemented", __func__);
return (KORE_RESULT_ERROR);
}
static void
lua_runtime_connect(void *addr, struct connection *c)
{
fatal("%s: not yet implemented", __func__);
}
static void
lua_runtime_signal(void *addr, int sig)
{
fatal("%s: not yet implemented", __func__);
}
static int
lua_kore_config(lua_State *L)
{
char *v;
const char *opt, *val;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (!lua_isstring(L, -2))
fatal("kore.config: keyword not a string");
opt = lua_tostring(L, -2);
if (lua_isinteger(L, -1)) {
lua_pushvalue(L, -1);
val = lua_tostring(L, -1);
lua_pop(L, 1);
} else if (lua_isstring(L, -1)) {
val = lua_tostring(L, -1);
} else {
fatal("kore.config: value not a string or integer");
}
v = kore_strdup(val);
if (!kore_configure_setting(opt, v)) {
kore_free(v);
luaL_error(L, "kore.config: cannot be set at runtime");
lua_pop(L, 1);
return (0);
}
kore_free(v);
lua_pop(L, 1);
}
return (0);
}
static int
lua_kore_server(lua_State *L)
{
struct kore_server *srv;
const char *name, *ip, *port;
if ((name = lua_argument_get_string(L, "name")) == NULL)
name = "default";
if ((ip = lua_argument_get_string(L, "ip")) == NULL) {
luaL_error(L, "kore.server: missing ip keyword");
return (0);
}
if ((port = lua_argument_get_string(L, "port")) == NULL) {
luaL_error(L, "kore.server: missing port keyword");
return (0);
}
if ((srv = kore_server_lookup(name)) != NULL) {
luaL_error(L, "kore.server: server '%s' exists", name);
return (0);
}
srv = kore_server_create(name);
srv->tls = lua_argument_get_bool(L, "tls");
if (srv->tls && !kore_tls_supported()) {
kore_server_free(srv);
luaL_error(L, "kore.server: TLS not supported");
return (0);
}
if (!kore_server_bind(srv, ip, port, NULL)) {
kore_server_free(srv);
luaL_error(L, "kore.server: failed to bind %s:%s", ip, port);
return (0);
}
kore_server_finalize(srv);
return (0);
}
static int
lua_http_request_gc(lua_State *L)
{
struct lua_http_request *lreq;
lreq = luaL_checkudata(L, 1, "http_request");
kore_free(lreq);
return (0);
}
static int
lua_http_request_index(lua_State *L)
{
struct lua_http_request *lreq;
const char *field;
lreq = luaL_checkudata(L, 1, "http_request");
field = luaL_checkstring(L, 2);
lua_getfield(L, LUA_REGISTRYINDEX, "http_request_methods");
lua_getfield(L, -1, field);
if (!lua_isnil(L, -1))
return (1);
lua_pop(L, 2);
if (!strcmp(field, "path")) {
lua_pushstring(L, lreq->req->path);
return (1);
} else if (!strcmp(field, "host")) {
lua_pushstring(L, lreq->req->host);
return (1);
} else if (!strcmp(field, "agent")) {
lua_pushstring(L, lreq->req->agent);
return (1);
} else if (!strcmp(field, "referer")) {
lua_pushstring(L, lreq->req->referer);
return (1);
} else if (!strcmp(field, "method")) {
lua_pushinteger(L, lreq->req->method);
return (1);
}
return (0);
}
static int
lua_http_response_header(lua_State *L)
{
struct lua_http_request *lreq;
const char *header, *value;
lreq = luaL_checkudata(L, 1, "http_request");
header = luaL_checkstring(L, 2);
value = luaL_checkstring(L, 3);
http_response_header(lreq->req, header, value);
return (0);
}
static int
lua_http_request_header(lua_State *L)
{
struct lua_http_request *lreq;
const char *header, *value;
lreq = luaL_checkudata(L, 1, "http_request");
header = luaL_checkstring(L, 2);
if (!http_request_header(lreq->req, header, &value)) {
lua_pushnil(L);
} else {
lua_pushstring(L, value);
}
return (1);
}
static int
lua_http_response(lua_State *L)
{
size_t len;
struct lua_http_request *lreq;
const void *data;
int status;
lreq = luaL_checkudata(L, 1, "http_request");
status = luaL_checkinteger(L, 2);
if (lua_isnil(L, 3)) {
len = 0;
data = NULL;
} else {
data = luaL_checklstring(L, 3, &len);
}
http_response(lreq->req, status, data, len);
return (0);
}

207
src/mem.c
View File

@ -14,35 +14,32 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
/*
* The memory facitilies such as kore_malloc / kore_calloc are all
* based on the kore pool system as long as the allocations are
* below 8192 bytes.
*
* Anything over 8192 bytes will get an mmap() allocation instead
* that does not benefit from the protections offered by the kore_pool API.
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdint.h>
#include "kore.h"
#define KORE_MEM_BLOCKS 11
#define KORE_MEM_BLOCK_SIZE_MAX 8192
#define KORE_MEM_BLOCK_PREALLOC 128
#define KORE_MEM_POOLS 11
#define KORE_MEM_POOLS_PREALLOC 32
#define KORE_MEM_POOLS_SIZE_MAX 8192
#define KORE_MEM_ALIGN 16
#define KORE_MEM_MAGIC 0xd0d0
#define KORE_MEM_TAGGED 0x0001
struct memsize {
size_t len;
size_t magic;
} __attribute__((packed));
#define KORE_MEM_TAGGED 0x0001
struct meminfo {
size_t len;
u_int16_t flags;
u_int16_t magic;
} __attribute__((packed));
struct memblock {
struct kore_pool pool;
};
struct tag {
@ -51,36 +48,38 @@ struct tag {
TAILQ_ENTRY(tag) list;
};
static inline struct memsize *memsize(void *);
static inline struct meminfo *meminfo(void *);
static size_t memblock_index(size_t);
static void *mem_alloc(size_t);
static size_t mem_index(size_t);
static TAILQ_HEAD(, tag) tags;
static struct kore_pool tag_pool;
static struct memblock blocks[KORE_MEM_BLOCKS];
static struct kore_pool mempools[KORE_MEM_POOLS];
void
kore_mem_init(void)
{
const char *opt;
int i, len;
char name[32];
u_int32_t size, elm, mlen;
size_t size, elm, mlen;
if ((opt = getenv("KORE_MEM_GUARD")) != NULL && !strcmp(opt, "1"))
kore_mem_guard = 1;
size = 8;
TAILQ_INIT(&tags);
kore_pool_init(&tag_pool, "tag_pool", sizeof(struct tag), 100);
kore_pool_init(&tag_pool, "tag_pool", sizeof(struct tag), 4);
for (i = 0; i < KORE_MEM_BLOCKS; i++) {
len = snprintf(name, sizeof(name), "block-%u", size);
for (i = 0; i < KORE_MEM_POOLS; i++) {
len = snprintf(name, sizeof(name), "block-%zu", size);
if (len == -1 || (size_t)len >= sizeof(name))
fatal("kore_mem_init: snprintf");
elm = (KORE_MEM_BLOCK_PREALLOC * 1024) / size;
mlen = sizeof(struct memsize) + size +
sizeof(struct meminfo) + KORE_MEM_ALIGN;
mlen = mlen & ~(KORE_MEM_ALIGN - 1);
elm = (KORE_MEM_POOLS_PREALLOC * 1024) / size;
mlen = sizeof(struct meminfo) + size;
kore_pool_init(&blocks[i].pool, name, mlen, elm);
kore_pool_init(&mempools[i], name, mlen, elm);
size = size << 1;
}
@ -91,60 +90,44 @@ kore_mem_cleanup(void)
{
int i;
for (i = 0; i < KORE_MEM_BLOCKS; i++) {
kore_pool_cleanup(&blocks[i].pool);
for (i = 0; i < KORE_MEM_POOLS; i++) {
kore_pool_cleanup(&mempools[i]);
}
}
void *
kore_mmap_region(size_t len)
{
void *ptr;
if ((ptr = mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
fatal("%s: mmap: %s", __func__, errno_s);
return (ptr);
}
void *
kore_malloc(size_t len)
{
void *ptr;
struct meminfo *mem;
struct memsize *size;
u_int8_t *addr;
size_t mlen, idx;
if (len == 0)
len = 8;
if (len <= KORE_MEM_BLOCK_SIZE_MAX) {
idx = memblock_index(len);
ptr = kore_pool_get(&blocks[idx].pool);
} else {
mlen = sizeof(struct memsize) + len + sizeof(struct meminfo);
if ((ptr = calloc(1, mlen)) == NULL)
fatal("kore_malloc(%zu): %d", len, errno);
}
size = (struct memsize *)ptr;
size->len = len;
size->magic = KORE_MEM_MAGIC;
addr = (u_int8_t *)ptr + sizeof(struct memsize);
mem = (struct meminfo *)(addr + size->len);
mem->flags = 0;
mem->magic = KORE_MEM_MAGIC;
return (addr);
return (mem_alloc(len));
}
void *
kore_realloc(void *ptr, size_t len)
{
struct memsize *size;
struct meminfo *mem;
void *nptr;
if (ptr == NULL) {
nptr = kore_malloc(len);
nptr = mem_alloc(len);
} else {
size = memsize(ptr);
if (len == size->len)
mem = meminfo(ptr);
if (len == mem->len)
return (ptr);
nptr = kore_malloc(len);
memcpy(nptr, ptr, MIN(len, size->len));
kore_free(ptr);
nptr = mem_alloc(len);
memcpy(nptr, ptr, MIN(len, mem->len));
kore_free_zero(ptr);
}
return (nptr);
@ -160,18 +143,31 @@ kore_calloc(size_t memb, size_t len)
fatal("kore_calloc(): memb * len > SIZE_MAX");
total = memb * len;
ptr = kore_malloc(total);
ptr = mem_alloc(total);
memset(ptr, 0, total);
return (ptr);
}
void
kore_free_zero(void *ptr)
{
struct meminfo *mem;
if (ptr == NULL)
return;
mem = meminfo(ptr);
kore_mem_zero(ptr, mem->len);
kore_free(ptr);
}
void
kore_free(void *ptr)
{
size_t idx;
struct meminfo *mem;
struct memsize *size;
u_int8_t *addr;
if (ptr == NULL)
@ -183,14 +179,14 @@ kore_free(void *ptr)
mem->flags &= ~KORE_MEM_TAGGED;
}
size = memsize(ptr);
addr = (u_int8_t *)ptr - sizeof(struct memsize);
addr = (u_int8_t *)ptr - sizeof(struct meminfo);
if (size->len <= KORE_MEM_BLOCK_SIZE_MAX) {
idx = memblock_index(size->len);
kore_pool_put(&blocks[idx].pool, addr);
if (mem->len <= KORE_MEM_POOLS_SIZE_MAX) {
idx = mem_index(mem->len);
kore_pool_put(&mempools[idx], addr);
} else {
free(addr);
if (munmap(addr, sizeof(*mem) + mem->len) == -1)
fatal("%s: munmap: %s", __func__, errno_s);
}
}
@ -201,7 +197,7 @@ kore_strdup(const char *str)
char *nstr;
len = strlen(str) + 1;
nstr = kore_malloc(len);
nstr = mem_alloc(len);
(void)kore_strlcpy(nstr, str, len);
return (nstr);
@ -212,7 +208,7 @@ kore_malloc_tagged(size_t len, u_int32_t tag)
{
void *ptr;
ptr = kore_malloc(len);
ptr = mem_alloc(len);
kore_mem_tag(ptr, tag);
return (ptr);
@ -278,8 +274,33 @@ kore_mem_zero(void *ptr, size_t len)
}
}
static void *
mem_alloc(size_t len)
{
void *ptr;
struct meminfo *mem;
size_t mlen, idx;
if (len == 0)
len = 8;
if (len <= KORE_MEM_POOLS_SIZE_MAX) {
idx = mem_index(len);
ptr = kore_pool_get(&mempools[idx]);
} else {
mlen = sizeof(struct meminfo) + len;
ptr = kore_mmap_region(mlen);
}
mem = (struct meminfo *)ptr;
mem->len = len;
mem->flags = 0;
return ((u_int8_t *)ptr + sizeof(struct meminfo));
}
static size_t
memblock_index(size_t len)
mem_index(size_t len)
{
size_t mlen, idx;
@ -290,36 +311,14 @@ memblock_index(size_t len)
mlen = mlen << 1;
}
if (idx > (KORE_MEM_BLOCKS - 1))
fatal("kore_malloc: idx too high");
if (idx > (KORE_MEM_POOLS - 1))
fatal("mem_index: idx too high");
return (idx);
}
static inline struct memsize *
memsize(void *ptr)
{
struct memsize *ms;
ms = (struct memsize *)((u_int8_t *)ptr - sizeof(*ms));
if (ms->magic != KORE_MEM_MAGIC)
fatal("%s: bad memsize magic (0x%zx)", __func__, ms->magic);
return (ms);
}
static inline struct meminfo *
meminfo(void *ptr)
{
struct memsize *ms;
struct meminfo *info;
ms = memsize(ptr);
info = (struct meminfo *)((u_int8_t *)ptr + ms->len);
if (info->magic != KORE_MEM_MAGIC)
fatal("%s: bad meminfo magic (0x%x)", __func__, info->magic);
return (info);
return ((struct meminfo *)((u_int8_t *)ptr - sizeof(struct meminfo)));
}

View File

@ -29,6 +29,10 @@
#include "python_api.h"
#endif
#if defined(KORE_USE_LUA)
#include "lua_api.h"
#endif
static TAILQ_HEAD(, kore_module) modules;
static void native_free(struct kore_module *);
@ -92,6 +96,12 @@ kore_module_load(const char *path, const char *onload, int type)
module->fun = &kore_python_module;
module->runtime = &kore_python_runtime;
break;
#endif
#if defined(KORE_USE_LUA)
case KORE_MODULE_LUA:
module->fun = &kore_lua_module;
module->runtime = &kore_lua_runtime;
break;
#endif
default:
fatal("kore_module_load: unknown type %d", type);

View File

@ -14,6 +14,33 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* A kore_pool is a memory pool containing fixed-sized objects that
* can quickly be obtained by a caller via kore_pool_get() and returned
* via kore_pool_put().
*
* Each entry in a pool will have a canary at the end that is used to
* catch any potential overruns when the entry is returned to the pool.
*
* If memory pool guards are enabled three additional things happen:
*
* 1) The metadata is placed at the start of a page instead
* of right before the returned user pointer.
*
* 2) Each pool entry gets a guard page at the end of its allocation
* that is marked as PROT_NONE. Touching a guard page will cause
* the application to receive a SIGSEGV.
*
* 3) Entries are only marked PROT_READ | PROT_WRITE when they are
* obtained with kore_pool_get(). Their memory protection is
* changed to PROT_NONE when returned to the pool via kore_pool_get().
*
* Caveats:
* Pools are designed to live for the entire lifetime of a Kore process
* until it will exit and are therefor not properly cleaned up when exit
* time arrives.
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/queue.h>
@ -32,156 +59,230 @@ static void pool_lock(struct kore_pool *);
static void pool_unlock(struct kore_pool *);
#endif
static void pool_region_create(struct kore_pool *, size_t);
static void pool_region_destroy(struct kore_pool *);
static void pool_grow(struct kore_pool *, size_t);
static void pool_mark_entry_rw(struct kore_pool *, void *);
static void pool_mark_entry_none(struct kore_pool *, void *);
void
kore_pool_init(struct kore_pool *pool, const char *name,
size_t len, size_t elm)
{
long pagesz;
if (elm < POOL_MIN_ELEMENTS)
elm = POOL_MIN_ELEMENTS;
if ((pagesz = sysconf(_SC_PAGESIZE)) == -1)
fatal("%s: sysconf: %s", __func__, errno_s);
if ((pool->name = strdup(name)) == NULL)
fatal("kore_pool_init: strdup %s", errno_s);
len = (len + (8 - 1)) & ~(8 - 1);
pool->uselen = len;
len = len + sizeof(u_int64_t);
len = (len + (16 - 1)) & ~(16 - 1);
pool->elmlen = len;
pool->lock = 0;
pool->elms = 0;
pool->inuse = 0;
pool->elen = len;
pool->freelist = NULL;
pool->pagesz = pagesz;
pool->growth = elm * 0.25f;
pool->slen = pool->elen + sizeof(struct kore_pool_entry);
pool->canary = (u_int64_t)kore_platform_random_uint32() << 32 |
kore_platform_random_uint32();
LIST_INIT(&(pool->regions));
LIST_INIT(&(pool->freelist));
if (kore_mem_guard) {
pool->memsz = pool->pagesz * 2;
pool_region_create(pool, elm);
while (pool->elmlen >
pool->pagesz - sizeof(struct kore_pool_entry)) {
pool->memsz += pool->pagesz;
pool->elmlen -= MIN(pool->elmlen, pool->pagesz);
}
pool->elmlen = len;
} else {
pool->memsz = pool->elmlen;
}
pool_grow(pool, elm);
}
void
kore_pool_cleanup(struct kore_pool *pool)
{
pool->lock = 0;
pool->elms = 0;
pool->inuse = 0;
pool->elen = 0;
pool->slen = 0;
struct kore_pool_entry *entry, *next;
if (kore_mem_guard) {
for (entry = pool->freelist; entry != NULL; entry = next) {
pool_mark_entry_rw(pool, entry);
next = entry->nextfree;
(void)munmap(entry, pool->memsz);
}
}
free(pool->name);
pool->name = NULL;
pool_region_destroy(pool);
}
void *
kore_pool_get(struct kore_pool *pool)
{
u_int8_t *ptr;
u_int64_t canary;
struct kore_pool_entry *entry;
#if defined(KORE_USE_TASKS)
pool_lock(pool);
#endif
if (LIST_EMPTY(&(pool->freelist)))
pool_region_create(pool, pool->growth);
if (pool->freelist == NULL)
pool_grow(pool, pool->growth);
entry = pool->freelist;
if (kore_mem_guard)
pool_mark_entry_rw(pool, entry);
pool->freelist = entry->nextfree;
entry = LIST_FIRST(&(pool->freelist));
if (entry->state != POOL_ELEMENT_FREE)
fatal("%s: element %p was not free", pool->name, (void *)entry);
LIST_REMOVE(entry, list);
entry->nextfree = NULL;
entry->state = POOL_ELEMENT_BUSY;
ptr = (u_int8_t *)entry + sizeof(struct kore_pool_entry);
pool->inuse++;
canary = pool->canary;
canary ^= (uintptr_t)entry;
canary ^= (uintptr_t)entry->uptr;
memcpy(entry->canary, &canary, sizeof(canary));
#if defined(KORE_USE_TASKS)
pool_unlock(pool);
#endif
return (ptr);
return (entry->uptr);
}
void
kore_pool_put(struct kore_pool *pool, void *ptr)
{
void *base;
u_int64_t canary;
struct kore_pool_entry *entry;
#if defined(KORE_USE_TASKS)
pool_lock(pool);
#endif
entry = (struct kore_pool_entry *)
((u_int8_t *)ptr - sizeof(struct kore_pool_entry));
if (kore_mem_guard) {
base = (u_int8_t *)ptr - ((uintptr_t)ptr % pool->pagesz);
} else {
base = (u_int8_t *)ptr - sizeof(*entry);
}
entry = (struct kore_pool_entry *)base;
if (entry->uptr != ptr) {
fatal("%s: uptr mismatch %p != %p",
pool->name, entry->uptr, ptr);
}
memcpy(&canary, entry->canary, sizeof(canary));
canary ^= (uintptr_t)entry;
canary ^= (uintptr_t)ptr;
if (canary != pool->canary)
fatal("%s: memory corruption detected", pool->name);
if (entry->state != POOL_ELEMENT_BUSY)
fatal("%s: element %p was not busy", pool->name, ptr);
entry->state = POOL_ELEMENT_FREE;
LIST_INSERT_HEAD(&(pool->freelist), entry, list);
entry->nextfree = pool->freelist;
pool->inuse--;
if (kore_mem_guard)
pool_mark_entry_none(pool, entry);
pool->freelist = entry;
#if defined(KORE_USE_TASKS)
pool_unlock(pool);
#endif
}
static void
pool_region_create(struct kore_pool *pool, size_t elms)
pool_grow(struct kore_pool *pool, size_t elms)
{
size_t i;
u_int8_t *p;
struct kore_pool_region *reg;
struct kore_pool_entry *entry;
u_int8_t *base, *p;
struct kore_pool_entry *entry, *prev;
if ((reg = calloc(1, sizeof(struct kore_pool_region))) == NULL)
fatal("pool_region_create: calloc: %s", errno_s);
prev = pool->freelist;
LIST_INSERT_HEAD(&(pool->regions), reg, list);
if (SIZE_MAX / elms < pool->slen)
fatal("pool_region_create: overflow");
reg->length = elms * pool->slen;
reg->start = mmap(NULL, reg->length, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (reg->start == MAP_FAILED)
fatal("mmap: %s", errno_s);
p = (u_int8_t *)reg->start;
if (kore_mem_guard == 0)
base = kore_mmap_region(elms * (sizeof(*entry) + pool->elmlen));
else
base = NULL;
for (i = 0; i < elms; i++) {
entry = (struct kore_pool_entry *)p;
entry->region = reg;
entry->state = POOL_ELEMENT_FREE;
LIST_INSERT_HEAD(&(pool->freelist), entry, list);
if (kore_mem_guard) {
base = kore_mmap_region(pool->memsz);
p = base + (pool->memsz - pool->pagesz - pool->elmlen);
entry = (struct kore_pool_entry *)base;
} else {
p = base + ((sizeof(*entry) + pool->elmlen) * i);
entry = (struct kore_pool_entry *)p;
p += sizeof(*entry);
}
p = p + pool->slen;
entry->uptr = p;
entry->nextfree = NULL;
entry->state = POOL_ELEMENT_FREE;
entry->canary = p + pool->uselen;
if (prev != NULL) {
prev->nextfree = entry;
if (kore_mem_guard)
pool_mark_entry_none(pool, prev);
}
prev = entry;
if (pool->freelist == NULL)
pool->freelist = entry;
if (kore_mem_guard) {
p += pool->elmlen;
if (((uintptr_t)p % pool->pagesz) != 0)
fatal("%s: misaligned page", __func__);
if (mprotect(p, pool->pagesz, PROT_NONE) == -1)
fatal("%s: mprotect: %s", __func__, errno_s);
if (madvise(p, pool->pagesz, MADV_FREE) == -1)
fatal("%s: madvise: %s", __func__, errno_s);
}
}
pool->elms += elms;
if (prev != NULL && kore_mem_guard)
pool_mark_entry_none(pool, prev);
}
static void
pool_region_destroy(struct kore_pool *pool)
pool_mark_entry_none(struct kore_pool *pool, void *ptr)
{
struct kore_pool_region *reg;
if (mprotect(ptr, pool->memsz - pool->pagesz, PROT_NONE) == -1)
fatal("%s: mprotect: %s", __func__, errno_s);
}
/* Take care iterating when modifying list contents */
while (!LIST_EMPTY(&pool->regions)) {
reg = LIST_FIRST(&pool->regions);
LIST_REMOVE(reg, list);
(void)munmap(reg->start, reg->length);
free(reg);
}
/* Freelist references into the regions memory allocations */
LIST_INIT(&pool->freelist);
pool->elms = 0;
static void
pool_mark_entry_rw(struct kore_pool *pool, void *ptr)
{
if (mprotect(ptr, pool->memsz - pool->pagesz,
PROT_READ | PROT_WRITE) == -1)
fatal("%s: mprotect: %s", __func__, errno_s);
}
#if defined(KORE_USE_TASKS)

View File

@ -55,6 +55,10 @@
#include <frameobject.h>
#if PY_VERSION_HEX >= 0x030b0000
#include <internal/pycore_frame.h>
#endif
#if PY_VERSION_HEX < 0x030A0000
typedef enum {
PYGEN_RETURN = 0,
@ -68,11 +72,17 @@ struct reqcall {
TAILQ_ENTRY(reqcall) list;
};
union deconst {
char *p;
const char *cp;
};
TAILQ_HEAD(reqcall_list, reqcall);
PyMODINIT_FUNC python_module_init(void);
static PyObject *python_import(const char *);
static int python_resolve_frame_line(void *);
static PyObject *pyconnection_alloc(struct connection *);
static PyObject *python_callable(PyObject *, const char *);
static void python_split_arguments(char *, char **, size_t);
@ -157,6 +167,7 @@ static void python_push_integer(PyObject *, const char *, long);
static void python_push_type(const char *, PyObject *, PyTypeObject *);
static int python_validator_check(PyObject *);
static int python_runtime_resolve(const char *, const struct stat *);
static int python_runtime_http_request(void *, struct http_request *);
static void python_runtime_http_request_free(void *, struct http_request *);
static void python_runtime_http_body_chunk(void *, struct http_request *,
@ -190,6 +201,7 @@ struct kore_module_functions kore_python_module = {
struct kore_runtime kore_python_runtime = {
KORE_RUNTIME_PYTHON,
.resolve = python_runtime_resolve,
.http_request = python_runtime_http_request,
.http_body_chunk = python_runtime_http_body_chunk,
.http_request_free = python_runtime_http_request_free,
@ -320,7 +332,7 @@ static PyObject *python_tracer = NULL;
static struct python_coro *coro_running = NULL;
#if !defined(KORE_SINGLE_BINARY)
const char *kore_pymodule = NULL;
static const char *kore_pymodule = NULL;
#endif
void
@ -1179,21 +1191,49 @@ python_coro_suspend(struct python_coro *coro)
python_coro_trace("suspended", coro);
}
static int
python_resolve_frame_line(void *ptr)
{
int line;
#if PY_VERSION_HEX >= 0x030b0000
int addr;
_PyInterpreterFrame *frame;
frame = ptr;
addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
line = PyCode_Addr2Line(frame->f_code, addr);
#else
line = PyFrame_GetLineNumber(ptr);
#endif
return (line);
}
static void
python_coro_trace(const char *label, struct python_coro *coro)
{
int line;
PyGenObject *gen;
PyCoroObject *obj;
PyCodeObject *code;
#if PY_VERSION_HEX >= 0x030b0000
_PyInterpreterFrame *frame;
#else
PyFrameObject *frame;
#endif
const char *func, *fname, *file;
if (coro_tracing == 0)
return;
gen = (PyGenObject *)coro->obj;
obj = (PyCoroObject *)coro->obj;
if (gen->gi_frame != NULL && gen->gi_frame->f_code != NULL) {
code = gen->gi_frame->f_code;
#if PY_VERSION_HEX >= 0x030b0000
frame = (_PyInterpreterFrame *)obj->cr_iframe;
#else
frame = obj->cr_frame;
#endif
if (frame != NULL && frame->f_code != NULL) {
code = frame->f_code;
func = PyUnicode_AsUTF8AndSize(code->co_name, NULL);
file = PyUnicode_AsUTF8AndSize(code->co_filename, NULL);
@ -1206,8 +1246,8 @@ python_coro_trace(const char *label, struct python_coro *coro)
fname = "unknown";
}
if (gen->gi_frame != NULL)
line = PyFrame_GetLineNumber(gen->gi_frame);
if (frame != NULL)
line = python_resolve_frame_line(frame);
else
line = -1;
@ -1240,6 +1280,38 @@ pyhttp_file_dealloc(struct pyhttp_file *pyfile)
PyObject_Del((PyObject *)pyfile);
}
static int
python_runtime_resolve(const char *module, const struct stat *st)
{
const char *ext;
if (!S_ISDIR(st->st_mode) && !S_ISREG(st->st_mode))
return (KORE_RESULT_ERROR);
if (S_ISDIR(st->st_mode)) {
kore_module_load(module, NULL, KORE_MODULE_PYTHON);
if (chdir(module) == -1)
fatal("chdir(%s): %s", module, errno_s);
} else {
if ((ext = strrchr(module, '.')) == NULL)
return (KORE_RESULT_ERROR);
if (strcasecmp(ext, ".py"))
return (KORE_RESULT_ERROR);
kore_module_load(module, NULL, KORE_MODULE_PYTHON);
}
#if !defined(KORE_SINGLE_BINARY)
kore_pymodule = module;
#endif
kore_hooks_set(KORE_PYTHON_CONFIG_HOOK,
KORE_PYTHON_TEARDOWN_HOOK, KORE_PYTHON_DAEMONIZED_HOOK);
return (KORE_RESULT_OK);
}
static int
python_runtime_http_request(void *addr, struct http_request *req)
{
@ -2689,12 +2761,15 @@ python_kore_timer(PyObject *self, PyObject *args, PyObject *kwargs)
}
static PyObject *
python_kore_proc(PyObject *self, PyObject *args)
python_kore_proc(PyObject *self, PyObject *args, PyObject *kwargs)
{
union deconst cp;
const char *cmd;
struct pyproc *proc;
char *copy, *argv[32], *env[1];
Py_ssize_t idx, len;
PyObject *obj, *item;
int timeo, in_pipe[2], out_pipe[2];
char *copy, *argv[32], *env[PYTHON_PROC_MAX_ENV + 1];
timeo = -1;
@ -2707,6 +2782,37 @@ python_kore_proc(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i", &cmd, &timeo))
return (NULL);
if (kwargs != NULL &&
(obj = PyDict_GetItemString(kwargs, "env")) != NULL) {
if (!PyList_CheckExact(obj)) {
PyErr_SetString(PyExc_RuntimeError,
"kore.proc: env is not of type 'list'");
return (NULL);
}
len = PyList_Size(obj);
if (len > PYTHON_PROC_MAX_ENV) {
PyErr_SetString(PyExc_RuntimeError,
"kore.proc: too many entries in 'env' keyword");
return (NULL);
}
for (idx = 0; idx < len; idx++) {
if ((item = PyList_GetItem(obj, idx)) == NULL)
return (NULL);
if (!PyUnicode_CheckExact(item))
return (NULL);
if ((cp.cp = PyUnicode_AsUTF8(item)) == NULL)
return (NULL);
env[idx] = cp.p;
}
env[idx] = NULL;
}
if (pipe(in_pipe) == -1) {
PyErr_SetString(PyExc_RuntimeError, errno_s);
return (NULL);
@ -2763,7 +2869,6 @@ python_kore_proc(PyObject *self, PyObject *args)
dup2(in_pipe[0], STDIN_FILENO) == -1)
fatal("dup2: %s", errno_s);
env[0] = NULL;
copy = kore_strdup(cmd);
python_split_arguments(copy, argv, 32);
@ -5022,6 +5127,46 @@ pyhttp_cookie(struct pyhttp_request *pyreq, PyObject *args)
return (value);
}
static PyObject *
pyhttp_headers(struct pyhttp_request *pyreq, PyObject *args)
{
struct http_header *hdr;
struct http_request *req;
PyObject *obj, *dict, *ret;
ret = NULL;
obj = NULL;
dict = NULL;
req = pyreq->req;
if ((dict = PyDict_New()) == NULL)
goto cleanup;
if ((obj = PyUnicode_FromString(req->host)) == NULL)
goto cleanup;
if (PyDict_SetItemString(dict, "host", obj) == -1)
goto cleanup;
TAILQ_FOREACH(hdr, &req->req_headers, list) {
if ((obj = PyUnicode_FromString(hdr->value)) == NULL)
goto cleanup;
if (PyDict_SetItemString(dict, hdr->header, obj) == -1)
goto cleanup;
}
ret = dict;
obj = NULL;
dict = NULL;
cleanup:
Py_XDECREF(obj);
Py_XDECREF(dict);
return (ret);
}
static PyObject *
pyhttp_file_lookup(struct pyhttp_request *pyreq, PyObject *args)
{
@ -5473,6 +5618,23 @@ pydomain_filemaps(struct pydomain *domain, PyObject *args)
Py_RETURN_NONE;
}
static PyObject *
pydomain_redirect(struct pydomain *domain, PyObject *args)
{
int status;
const char *src, *dst;
if (!PyArg_ParseTuple(args, "sis", &src, &status, &dst))
return (NULL);
if (!http_redirect_add(domain->config, src, status, dst)) {
fatal("failed to add redirect '%s' on '%s'",
src, domain->config->domain);
}
Py_RETURN_NONE;
}
static PyObject *
pydomain_route(struct pydomain *domain, PyObject *args, PyObject *kwargs)
{
@ -6328,6 +6490,7 @@ static PyObject *
pycurl_handle_setopt_string(struct pycurl_data *data, int idx, PyObject *obj)
{
const char *str;
CURLoption option;
if (!PyUnicode_Check(obj)) {
PyErr_Format(PyExc_RuntimeError,
@ -6339,8 +6502,8 @@ pycurl_handle_setopt_string(struct pycurl_data *data, int idx, PyObject *obj)
if ((str = PyUnicode_AsUTF8(obj)) == NULL)
return (NULL);
curl_easy_setopt(data->curl.handle,
CURLOPTTYPE_OBJECTPOINT + py_curlopt[idx].value, str);
option = CURLOPTTYPE_OBJECTPOINT + py_curlopt[idx].value;
curl_easy_setopt(data->curl.handle, option, str);
Py_RETURN_TRUE;
}
@ -6349,6 +6512,7 @@ static PyObject *
pycurl_handle_setopt_long(struct pycurl_data *data, int idx, PyObject *obj)
{
long val;
CURLoption option;
if (!PyLong_CheckExact(obj)) {
PyErr_Format(PyExc_RuntimeError,
@ -6362,8 +6526,8 @@ pycurl_handle_setopt_long(struct pycurl_data *data, int idx, PyObject *obj)
if (val == -1 && PyErr_Occurred())
return (NULL);
curl_easy_setopt(data->curl.handle,
CURLOPTTYPE_LONG + py_curlopt[idx].value, val);
option = CURLOPTTYPE_LONG + py_curlopt[idx].value;
curl_easy_setopt(data->curl.handle, option, val);
Py_RETURN_TRUE;
}
@ -6375,6 +6539,7 @@ pycurl_handle_setopt_slist(struct pycurl_data *data, int idx, PyObject *obj)
PyObject *item;
const char *sval;
struct curl_slist *slist;
CURLoption option;
Py_ssize_t list_len, i;
if (!PyList_CheckExact(obj)) {
@ -6405,8 +6570,8 @@ pycurl_handle_setopt_slist(struct pycurl_data *data, int idx, PyObject *obj)
psl->slist = slist;
LIST_INSERT_HEAD(&data->slists, psl, list);
curl_easy_setopt(data->curl.handle,
CURLOPTTYPE_OBJECTPOINT + py_curlopt[idx].value, slist);
option = CURLOPTTYPE_OBJECTPOINT + py_curlopt[idx].value;
curl_easy_setopt(data->curl.handle, option, slist);
Py_RETURN_TRUE;
}

View File

@ -27,6 +27,10 @@
#include "python_api.h"
#endif
#if defined(KORE_USE_LUA)
#include "lua_api.h"
#endif
static void native_runtime_execute(void *);
static int native_runtime_onload(void *, int);
static void native_runtime_signal(void *, int);
@ -62,6 +66,41 @@ struct kore_runtime kore_native_runtime = {
.configure = native_runtime_configure
};
static struct kore_runtime *runtimes[] = {
#if defined(KORE_USE_PYTHON)
&kore_python_runtime,
#endif
#if defined(KORE_USE_LUA)
&kore_lua_runtime,
#endif
NULL
};
const size_t
kore_runtime_count(void)
{
return ((sizeof(runtimes) / sizeof(runtimes[0])) - 1);
}
void
kore_runtime_resolve(const char *module, const struct stat *st)
{
int i;
if (runtimes[0] == NULL)
return;
for (i = 0; runtimes[i] != NULL; i++) {
if (runtimes[i]->resolve == NULL)
continue;
if (runtimes[i]->resolve(module, st))
break;
}
if (runtimes[i] == NULL)
fatal("No runtime available to run '%s'", module);
}
struct kore_runtime_call *
kore_runtime_getcall(const char *symbol)
{

View File

@ -67,6 +67,9 @@ static struct sock_filter filter_kore[] = {
KORE_SYSCALL_ALLOW(fstat),
#if defined(SYS_fstat64)
KORE_SYSCALL_ALLOW(fstat64),
#endif
#if defined(SYS_newfstatat)
KORE_SYSCALL_ALLOW(newfstatat),
#endif
KORE_SYSCALL_ALLOW(write),
KORE_SYSCALL_ALLOW(fcntl),
@ -102,6 +105,9 @@ static struct sock_filter filter_kore[] = {
KORE_SYSCALL_ALLOW(geteuid),
KORE_SYSCALL_ALLOW(exit_group),
KORE_SYSCALL_ALLOW(nanosleep),
#if defined(SYS_clock_gettime64)
KORE_SYSCALL_ALLOW(clock_gettime64),
#endif
#if defined(SYS_clock_nanosleep)
KORE_SYSCALL_ALLOW(clock_nanosleep),
#endif

View File

@ -41,7 +41,12 @@ kore_keymgr_cleanup(int final)
void
kore_tls_init(void)
{
kore_log(LOG_ERR, "No compiled in TLS backend");
}
void
kore_tls_log_version(void)
{
kore_log(LOG_NOTICE, "No compiled in TLS backend");
}
void

View File

@ -36,11 +36,28 @@
#include "kore.h"
#include "http.h"
/*
* Disable deprecated declaration warnings if we're building against
* OpenSSL 3 as they marked all low-level APIs as deprecated.
*
* Work is being done to replace these, but for now let things build.
*/
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#define TLS_SESSION_ID "kore_tls_sessionid"
/* Helper for weird API designs (looking at you OpenSSL). */
union deconst {
void *p;
const void *cp;
};
static int tls_domain_x509_verify(int, X509_STORE_CTX *);
static X509 *tls_domain_load_certificate_chain(SSL_CTX *,
const void *, size_t);
static EVP_PKEY *tls_privsep_private_key(EVP_PKEY *, struct kore_domain *);
static int tls_sni_cb(SSL *, int *, void *);
static void tls_info_callback(const SSL *, int, int);
@ -59,13 +76,8 @@ static int tls_keymgr_rsa_finish(RSA *);
static int tls_keymgr_rsa_privenc(int, const unsigned char *,
unsigned char *, RSA *, int);
static ECDSA_SIG *tls_keymgr_ecdsa_sign(const unsigned char *, int,
const BIGNUM *, const BIGNUM *, EC_KEY *);
static RSA_METHOD *keymgr_rsa_meth = NULL;
static EC_KEY_METHOD *keymgr_ec_meth = NULL;
static DH *dh_params = NULL;
static RSA_METHOD *keymgr_rsa_meth = NULL;
static int tls_version = KORE_TLS_VERSION_BOTH;
static char *tls_cipher_list = KORE_DEFAULT_CIPHER_LIST;
@ -94,21 +106,13 @@ kore_tls_init(void)
SSL_load_error_strings();
ERR_load_crypto_strings();
if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method",
RSA_METHOD_FLAG_NO_CHECK)) == NULL)
fatal("failed to setup RSA method");
RSA_meth_set_init(keymgr_rsa_meth, tls_keymgr_rsa_init);
RSA_meth_set_finish(keymgr_rsa_meth, tls_keymgr_rsa_finish);
RSA_meth_set_priv_enc(keymgr_rsa_meth, tls_keymgr_rsa_privenc);
if ((keymgr_ec_meth = EC_KEY_METHOD_new(NULL)) == NULL)
fatal("failed to allocate EC KEY method");
EC_KEY_METHOD_set_sign(keymgr_ec_meth,
NULL, NULL, tls_keymgr_ecdsa_sign);
}
void
kore_tls_log_version(void)
{
kore_log(LOG_NOTICE, "TLS backend %s", OPENSSL_VERSION_TEXT);
#if !defined(TLS1_3_VERSION)
if (!kore_quiet) {
kore_log(LOG_NOTICE,
@ -122,7 +126,6 @@ void
kore_tls_cleanup(void)
{
RSA_meth_free(keymgr_rsa_meth);
EC_KEY_METHOD_free(keymgr_ec_meth);
}
void
@ -188,6 +191,14 @@ kore_tls_keymgr_init(void)
if ((meth = RSA_get_default_method()) == NULL)
fatal("failed to obtain RSA method");
if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method",
RSA_METHOD_FLAG_NO_CHECK)) == NULL)
fatal("failed to setup RSA method");
RSA_meth_set_init(keymgr_rsa_meth, tls_keymgr_rsa_init);
RSA_meth_set_finish(keymgr_rsa_meth, tls_keymgr_rsa_finish);
RSA_meth_set_priv_enc(keymgr_rsa_meth, tls_keymgr_rsa_privenc);
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_bn_mod_exp(keymgr_rsa_meth, RSA_meth_get_bn_mod_exp(meth));
@ -200,11 +211,9 @@ kore_tls_domain_setup(struct kore_domain *dom, int type,
const void *data, size_t datalen)
{
const u_int8_t *ptr;
RSA *rsa;
X509 *x509;
EVP_PKEY *pkey;
X509 *x509;
STACK_OF(X509_NAME) *certs;
EC_KEY *eckey;
const SSL_METHOD *method;
if (dom->tls_ctx != NULL)
@ -280,16 +289,7 @@ kore_tls_domain_setup(struct kore_domain *dom, int type,
switch (EVP_PKEY_id(pkey)) {
case EVP_PKEY_RSA:
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
fatalx("no RSA public key present");
RSA_set_app_data(rsa, dom);
RSA_set_method(rsa, keymgr_rsa_meth);
break;
case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
fatalx("no EC public key present");
EC_KEY_set_ex_data(eckey, 0, dom);
EC_KEY_set_method(eckey, keymgr_ec_meth);
pkey = tls_privsep_private_key(pkey, dom);
break;
default:
fatalx("unknown public key in certificate");
@ -358,7 +358,9 @@ kore_tls_domain_crl(struct kore_domain *dom, const void *pem, size_t pemlen)
int err;
BIO *in;
X509_CRL *crl;
X509_REVOKED *rev;
X509_STORE *store;
struct connection *c, *next;
ERR_clear_error();
in = BIO_new_mem_buf(pem, pemlen);
@ -369,6 +371,9 @@ kore_tls_domain_crl(struct kore_domain *dom, const void *pem, size_t pemlen)
return;
}
X509_STORE_set_flags(store,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
for (;;) {
crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
if (crl == NULL) {
@ -395,12 +400,42 @@ kore_tls_domain_crl(struct kore_domain *dom, const void *pem, size_t pemlen)
X509_CRL_free(crl);
continue;
}
/*
* Check if any accepted connection authenticated themselves
* with a now revoked certificate.
*/
for (c = TAILQ_FIRST(&connections); c != NULL; c = next) {
next = TAILQ_NEXT(c, list);
if (c->proto != CONN_PROTO_HTTP)
continue;
/*
* Prune any connection that is currently not yet done
* with the TLS handshake. This is to prevent a race
* where a handshake could not yet be complete but
* did pass the x509 verification step and their cert
* was revoked in this CRL update.
*/
if (c->state == CONN_STATE_TLS_SHAKE) {
kore_connection_disconnect(c);
continue;
}
if (c->tls_cert == NULL)
continue;
if (X509_CRL_get0_by_cert(crl, &rev, c->tls_cert) != 1)
continue;
kore_connection_log(c,
"connection removed, its certificate is revoked");
kore_connection_disconnect(c);
}
}
BIO_free(in);
X509_STORE_set_flags(store,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
void
@ -416,13 +451,13 @@ kore_tls_connection_accept(struct connection *c)
int r;
if (primary_dom == NULL) {
kore_log(LOG_NOTICE,
kore_connection_log(c,
"TLS handshake but no TLS configured on server");
return (KORE_RESULT_ERROR);
}
if (primary_dom->tls_ctx == NULL) {
kore_log(LOG_NOTICE,
kore_connection_log(c,
"TLS configuration for %s not yet complete",
primary_dom->domain);
return (KORE_RESULT_ERROR);
@ -436,8 +471,11 @@ kore_tls_connection_accept(struct connection *c)
SSL_set_fd(c->tls, c->fd);
SSL_set_accept_state(c->tls);
if (!SSL_set_ex_data(c->tls, 0, c))
if (!SSL_set_ex_data(c->tls, 0, c)) {
kore_connection_log(c,
"SSL_set_ex_data: %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
if (primary_dom->cafile != NULL)
c->flags |= CONN_LOG_TLS_FAILURE;
@ -454,7 +492,7 @@ kore_tls_connection_accept(struct connection *c)
return (KORE_RESULT_RETRY);
default:
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
kore_connection_log(c,
"SSL_accept: %s", ssl_errno_s);
}
return (KORE_RESULT_ERROR);
@ -463,7 +501,7 @@ kore_tls_connection_accept(struct connection *c)
#if defined(KORE_USE_ACME)
if (c->proto == CONN_PROTO_ACME_ALPN) {
kore_log(LOG_INFO, "disconnecting acme client");
kore_connection_log(c, "disconnecting ACME client");
kore_connection_disconnect(c);
return (KORE_RESULT_ERROR);
}
@ -472,7 +510,7 @@ kore_tls_connection_accept(struct connection *c)
if (SSL_get_verify_mode(c->tls) & SSL_VERIFY_PEER) {
c->tls_cert = SSL_get_peer_certificate(c->tls);
if (c->tls_cert == NULL) {
kore_log(LOG_NOTICE, "no peer certificate");
kore_connection_log(c, "no peer certificate returned");
return (KORE_RESULT_ERROR);
}
} else {
@ -518,8 +556,8 @@ kore_tls_read(struct connection *c, size_t *bytes)
/* FALLTHROUGH */
default:
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
"SSL_read(): %s", ssl_errno_s);
kore_connection_log(c, "SSL_read: %s",
ssl_errno_s);
}
return (KORE_RESULT_ERROR);
}
@ -566,8 +604,8 @@ kore_tls_write(struct connection *c, size_t len, size_t *written)
/* FALLTHROUGH */
default:
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
"SSL_write(): %s", ssl_errno_s);
kore_connection_log(c,
"SSL_write: %s", ssl_errno_s);
}
return (KORE_RESULT_ERROR);
}
@ -652,8 +690,10 @@ kore_tls_x509_subject_name(struct connection *c)
{
X509_NAME *name;
if ((name = X509_get_subject_name(c->tls_cert)) == NULL)
kore_log(LOG_NOTICE, "X509_get_subject_name: %s", ssl_errno_s);
if ((name = X509_get_subject_name(c->tls_cert)) == NULL) {
kore_connection_log(c,
"X509_get_subject_name: %s", ssl_errno_s);
}
return (name);
}
@ -664,7 +704,7 @@ kore_tls_x509_issuer_name(struct connection *c)
X509_NAME *name;
if ((name = X509_get_issuer_name(c->tls_cert)) == NULL)
kore_log(LOG_NOTICE, "X509_get_issuer_name: %s", ssl_errno_s);
kore_connection_log(c, "X509_get_issuer_name: %s", ssl_errno_s);
return (name);
}
@ -737,7 +777,7 @@ kore_tls_x509_data(struct connection *c, u_int8_t **ptr, size_t *olen)
u_int8_t *der, *pp;
if ((len = i2d_X509(c->tls_cert, NULL)) <= 0) {
kore_log(LOG_NOTICE, "i2d_X509: %s", ssl_errno_s);
kore_connection_log(c, "i2d_X509: %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
@ -746,7 +786,7 @@ kore_tls_x509_data(struct connection *c, u_int8_t **ptr, size_t *olen)
if (i2d_X509(c->tls_cert, &pp) <= 0) {
kore_free(der);
kore_log(LOG_NOTICE, "i2d_X509: %s", ssl_errno_s);
kore_connection_log(c, "i2d_X509: %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
@ -894,53 +934,6 @@ tls_keymgr_rsa_finish(RSA *rsa)
return (1);
}
static ECDSA_SIG *
tls_keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
{
size_t len;
ECDSA_SIG *sig;
const u_int8_t *ptr;
struct kore_domain *dom;
struct kore_keyreq *req;
if (in_kinv != NULL || in_r != NULL)
return (NULL);
len = sizeof(*req) + dgst_len;
if (len > sizeof(keymgr_buf))
fatal("keymgr_buf too small");
if ((dom = EC_KEY_get_ex_data(eckey, 0)) == NULL)
fatal("EC_KEY has no domain");
memset(keymgr_buf, 0, sizeof(keymgr_buf));
req = (struct kore_keyreq *)keymgr_buf;
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
sizeof(req->domain))
fatal("%s: domain truncated", __func__);
req->data_len = dgst_len;
memcpy(&req->data[0], dgst, req->data_len);
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
tls_keymgr_await_data();
if (keymgr_response) {
ptr = keymgr_buf;
sig = d2i_ECDSA_SIG(NULL, &ptr, keymgr_buflen);
} else {
sig = NULL;
}
keymgr_buflen = 0;
keymgr_response = 0;
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
return (sig);
}
static void
tls_keymgr_await_data(void)
{
@ -1044,9 +1037,18 @@ tls_keymgr_msg_response(struct kore_msg *msg, const void *data)
static int
tls_domain_x509_verify(int ok, X509_STORE_CTX *ctx)
{
X509 *cert;
const char *text;
int error, depth;
struct connection *c;
SSL *tls;
X509 *cert;
const char *text;
int error, depth;
if ((tls = X509_STORE_CTX_get_ex_data(ctx,
SSL_get_ex_data_X509_STORE_CTX_idx())) == NULL)
fatal("X509_STORE_CTX_get_ex_data: no data");
if ((c = SSL_get_ex_data(tls, 0)) == NULL)
fatal("no connection data in %s", __func__);
error = X509_STORE_CTX_get_error(ctx);
cert = X509_STORE_CTX_get_current_cert(ctx);
@ -1055,8 +1057,8 @@ tls_domain_x509_verify(int ok, X509_STORE_CTX *ctx)
text = X509_verify_cert_error_string(error);
depth = X509_STORE_CTX_get_error_depth(ctx);
kore_log(LOG_WARNING, "X509 verification error depth:%d - %s",
depth, text);
kore_connection_log(c,
"X509 verification error depth:%d - %s", depth, text);
/* Continue on CRL validity errors. */
switch (error) {
@ -1113,6 +1115,41 @@ tls_domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
return (x);
}
static EVP_PKEY *
tls_privsep_private_key(EVP_PKEY *pub, struct kore_domain *dom)
{
EVP_PKEY *pkey;
RSA *rsa_new;
const RSA *rsa_cur;
const BIGNUM *e_cur, *n_cur;
BIGNUM *e_new, *n_new;
if ((pkey = EVP_PKEY_new()) == NULL)
fatalx("failed to create new EVP_PKEY data structure");
if ((rsa_new = RSA_new()) == NULL)
fatalx("failed to create new RSA data structure");
if ((rsa_cur = EVP_PKEY_get0_RSA(pub)) == NULL)
fatalx("no RSA public key present");
RSA_get0_key(rsa_cur, &n_cur, &e_cur, NULL);
if ((n_new = BN_dup(n_cur)) == NULL)
fatalx("BN_dup failed");
if ((e_new = BN_dup(e_cur)) == NULL)
fatalx("BN_dup failed");
RSA_set_app_data(rsa_new, dom);
RSA_set_method(rsa_new, keymgr_rsa_meth);
RSA_set0_key(rsa_new, n_new, e_new, NULL);
EVP_PKEY_set1_RSA(pkey, rsa_new);
return (pkey);
}
#if defined(KORE_USE_ACME)
static int
tls_acme_alpn(SSL *ssl, const unsigned char **out, unsigned char *outlen,

View File

@ -239,10 +239,11 @@ kore_split_string(char *input, const char *delim, char **out, size_t ele)
}
void
kore_strip_chars(char *in, const char strip, char **out)
kore_strip_chars(const char *in, const char strip, char **out)
{
char *p;
const char *s;
u_int32_t len;
char *s, *p;
len = strlen(in);
*out = kore_malloc(len + 1);

View File

@ -132,7 +132,7 @@ kore_worker_init(void)
sizeof(*accept_lock));
memset(kore_workers, 0, sizeof(struct kore_worker) * worker_count);
if (worker_count > cpu_count)
if ((worker_count - 2) > cpu_count)
kore_log(LOG_NOTICE, "more worker processes than cpu cores");
/* Setup log buffers. */
@ -369,6 +369,9 @@ kore_worker_privsep(void)
if (worker == NULL)
fatalx("%s called with no worker", __func__);
if (worker_set_affinity == 1)
kore_platform_worker_setcpu(worker);
pw = NULL;
/* Must happen before chroot. */
@ -450,9 +453,6 @@ kore_worker_entry(struct kore_worker *kw)
kore_platform_proctitle(kore_worker_name(kw->id));
if (worker_set_affinity == 1)
kore_platform_worker_setcpu(kw);
kore_pid = kw->pid;
kore_signal_setup();