mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 12:39:01 -04:00
Merge branch 'master' into 4.x-releng
This commit is contained in:
commit
ab8fe8eb63
1
BEERS
1
BEERS
@ -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
|
||||
|
13
Makefile
13
Makefile
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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
30
include/kore/lua_api.h
Normal 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
|
49
include/kore/lua_methods.h
Normal file
49
include/kore/lua_methods.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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
55
misc/hooks/post-receive
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -287,4 +287,5 @@
|
||||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_clone3 435
|
||||
|
||||
|
@ -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
|
||||
|
@ -343,4 +343,5 @@
|
||||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_clone3 435
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
189
src/cli.c
@ -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);
|
||||
}
|
||||
|
10
src/config.c
10
src/config.c
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
31
src/http.c
31
src/http.c
@ -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;
|
||||
|
@ -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;
|
||||
|
174
src/kore.c
174
src/kore.c
@ -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
|
||||
|
||||
|
18
src/linux.c
18
src/linux.c
@ -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);
|
||||
}
|
||||
|
@ -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
601
src/lua.c
Normal 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
207
src/mem.c
@ -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)));
|
||||
}
|
||||
|
10
src/module.c
10
src/module.c
@ -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);
|
||||
|
235
src/pool.c
235
src/pool.c
@ -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)
|
||||
|
197
src/python.c
197
src/python.c
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user