kore/src/config.c

2120 lines
48 KiB
C
Raw Permalink Normal View History

2013-05-01 17:17:16 +02:00
/*
2022-01-31 22:02:06 +01:00
* Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
2013-05-01 17:17:16 +02:00
*
* 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/param.h>
#include <sys/types.h>
2014-03-07 09:55:28 +01:00
#include <sys/stat.h>
2016-01-22 12:08:13 +01:00
#include <stdio.h>
#include <string.h>
2017-02-06 12:13:29 +01:00
#include <stdint.h>
2013-05-01 17:17:16 +02:00
#include <ctype.h>
#include <limits.h>
2013-05-01 17:17:16 +02:00
#include <fcntl.h>
2013-06-26 11:18:32 +02:00
#include <pwd.h>
2013-05-01 17:17:16 +02:00
#include "kore.h"
#include "http.h"
2013-05-01 17:17:16 +02:00
#if defined(KORE_USE_PGSQL)
#include "pgsql.h"
#endif
#if defined(KORE_USE_TASKS)
#include "tasks.h"
#endif
#if defined(KORE_USE_PYTHON)
#include "python_api.h"
#endif
#if defined(KORE_USE_CURL)
#include "curl.h"
#endif
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
#include "acme.h"
#endif
#if defined(__linux__)
#include "seccomp.h"
#endif
/* XXX - This is becoming a clusterfuck. Fix it. */
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static int configure_load(char *);
static char *configure_resolve_var(char *);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void configure_check_var(char **, const char *, const char *);
#if defined(KORE_SINGLE_BINARY)
static FILE *config_file_write(void);
extern u_int8_t asset_builtin_kore_conf[];
extern u_int32_t asset_len_builtin_kore_conf;
#elif defined(KORE_USE_PYTHON)
static int configure_file(char *);
#endif
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
static int configure_acme(char *);
static int configure_acme_email(char *);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static int configure_acme_provider(char *);
#endif
static int configure_tls(char *);
static int configure_server(char *);
static int configure_include(char *);
static int configure_bind(char *);
static int configure_bind_unix(char *);
static int configure_attach(char *);
static int configure_domain(char *);
static int configure_privsep(char *);
static int configure_logfile(char *);
static int configure_workers(char *);
static int configure_pidfile(char *);
static int configure_rlimit_nofiles(char *);
static int configure_max_connections(char *);
static int configure_accept_threshold(char *);
static int configure_death_policy(char *);
static int configure_set_affinity(char *);
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 *);
#endif
static int configure_rand_file(char *);
static int configure_certfile(char *);
static int configure_certkey(char *);
static int configure_tls_version(char *);
static int configure_tls_cipher(char *);
static int configure_tls_dhparam(char *);
static int configure_client_verify(char *);
static int configure_client_verify_depth(char *);
#if !defined(KORE_NO_HTTP)
static int configure_route(char *);
static int configure_route_methods(char *);
static int configure_route_handler(char *);
static int configure_route_on_free(char *);
static int configure_route_on_headers(char *);
static int configure_route_authenticate(char *);
static int configure_route_on_body_chunk(char *);
static int configure_filemap(char *);
static int configure_return(char *);
static int configure_redirect(char *);
static int configure_static_handler(char *);
static int configure_dynamic_handler(char *);
static int configure_accesslog(char *);
static int configure_http_header_max(char *);
static int configure_http_header_timeout(char *);
static int configure_http_body_max(char *);
static int configure_http_body_timeout(char *);
static int configure_filemap_ext(char *);
static int configure_filemap_index(char *);
static int configure_http_media_type(char *);
static int configure_http_hsts_enable(char *);
static int configure_http_keepalive_time(char *);
static int configure_http_request_ms(char *);
static int configure_http_request_limit(char *);
static int configure_http_body_disk_offload(char *);
static int configure_http_body_disk_path(char *);
static int configure_http_server_version(char *);
static int configure_http_pretty_error(char *);
static int configure_validator(char *);
static int configure_validate(char *);
static int configure_authentication(char *);
static int configure_authentication_uri(char *);
static int configure_authentication_type(char *);
static int configure_authentication_value(char *);
static int configure_authentication_validator(char *);
static int configure_websocket_maxframe(char *);
static int configure_websocket_timeout(char *);
#endif
#if defined(KORE_USE_PGSQL)
static int configure_pgsql_conn_max(char *);
static int configure_pgsql_queue_limit(char *);
#endif
#if defined(KORE_USE_TASKS)
static int configure_task_threads(char *);
#endif
#if defined(KORE_USE_PYTHON)
static int configure_python_path(char *);
static int configure_python_import(char *);
#endif
#if defined(KORE_USE_CURL)
static int configure_curl_timeout(char *);
static int configure_curl_recv_max(char *);
#endif
#if defined(__linux__)
static int configure_seccomp_tracing(char *);
#endif
2013-05-01 17:17:16 +02:00
static struct {
const char *name;
int (*configure)(char *);
} config_directives[] = {
{ "tls", configure_tls },
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
{ "acme", configure_acme },
#endif
{ "bind", configure_bind },
{ "load", configure_load },
{ "domain", configure_domain },
{ "privsep", configure_privsep },
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{ "server", configure_server },
{ "attach", configure_attach },
{ "certkey", configure_certkey },
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{ "certfile", configure_certfile },
{ "include", configure_include },
{ "unix", configure_bind_unix },
{ "skip", configure_privsep_skip },
{ "root", configure_privsep_root },
{ "runas", configure_privsep_runas },
{ "client_verify", configure_client_verify },
{ "client_verify_depth", configure_client_verify_depth },
#if defined(KORE_USE_PYTHON)
{ "python_path", configure_python_path },
{ "python_import", configure_python_import },
#endif
#if !defined(KORE_NO_HTTP)
{ "route", configure_route },
{ "handler", configure_route_handler },
{ "on_headers", configure_route_on_headers },
{ "on_body_chunk", configure_route_on_body_chunk },
{ "on_free", configure_route_on_free },
{ "methods", configure_route_methods },
{ "authenticate", configure_route_authenticate },
{ "filemap", configure_filemap },
{ "redirect", configure_redirect },
{ "return", configure_return },
{ "static", configure_static_handler },
{ "dynamic", configure_dynamic_handler },
{ "accesslog", configure_accesslog },
{ "validator", configure_validator },
{ "validate", configure_validate },
{ "authentication", configure_authentication },
{ "authentication_uri", configure_authentication_uri },
{ "authentication_type", configure_authentication_type },
{ "authentication_value", configure_authentication_value },
{ "authentication_validator", configure_authentication_validator },
#endif
{ NULL, NULL },
};
static struct {
const char *name;
int (*configure)(char *);
} config_settings[] = {
{ "logfile", configure_logfile },
{ "workers", configure_workers },
{ "worker_max_connections", configure_max_connections },
{ "worker_rlimit_nofiles", configure_rlimit_nofiles },
{ "worker_accept_threshold", configure_accept_threshold },
{ "worker_death_policy", configure_death_policy },
{ "worker_set_affinity", configure_set_affinity },
{ "pidfile", configure_pidfile },
{ "socket_backlog", configure_socket_backlog },
{ "tls_version", configure_tls_version },
{ "tls_cipher", configure_tls_cipher },
{ "tls_dhparam", configure_tls_dhparam },
{ "rand_file", configure_rand_file },
{ "deployment", configure_deployment },
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
{ "acme_email", configure_acme_email },
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{ "acme_provider", configure_acme_provider },
#endif
#if defined(KORE_USE_PLATFORM_PLEDGE)
{ "pledge", configure_add_pledge },
#endif
#if defined(__linux__)
{ "seccomp_tracing", configure_seccomp_tracing },
#endif
#if !defined(KORE_NO_HTTP)
{ "filemap_ext", configure_filemap_ext },
{ "filemap_index", configure_filemap_index },
{ "http_media_type", configure_http_media_type },
{ "http_header_max", configure_http_header_max },
{ "http_header_timeout", configure_http_header_timeout },
{ "http_body_max", configure_http_body_max },
{ "http_body_timeout", configure_http_body_timeout },
{ "http_hsts_enable", configure_http_hsts_enable },
{ "http_keepalive_time", configure_http_keepalive_time },
{ "http_request_ms", configure_http_request_ms },
{ "http_request_limit", configure_http_request_limit },
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
{ "http_body_disk_offload", configure_http_body_disk_offload },
{ "http_body_disk_path", configure_http_body_disk_path },
{ "http_server_version", configure_http_server_version },
{ "http_pretty_error", configure_http_pretty_error },
{ "websocket_maxframe", configure_websocket_maxframe },
{ "websocket_timeout", configure_websocket_timeout },
#endif
#if defined(KORE_USE_PGSQL)
{ "pgsql_conn_max", configure_pgsql_conn_max },
{ "pgsql_queue_limit", configure_pgsql_queue_limit },
#endif
#if defined(KORE_USE_TASKS)
{ "task_threads", configure_task_threads },
#endif
#if defined(KORE_USE_CURL)
{ "curl_timeout", configure_curl_timeout },
{ "curl_recv_max", configure_curl_recv_max },
#endif
#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
{ "file", configure_file },
#endif
{ NULL, NULL },
2013-05-01 17:17:16 +02:00
};
static int finalized = 0;
#if !defined(KORE_SINGLE_BINARY)
char *config_file = NULL;
#endif
#if !defined(KORE_NO_HTTP)
static struct kore_auth *current_auth = NULL;
static struct kore_route *current_route = NULL;
#endif
extern const char *__progname;
static struct kore_domain *current_domain = NULL;
static struct kore_server *current_server = NULL;
static struct kore_privsep *current_privsep = NULL;
2013-05-01 17:17:16 +02:00
void
2013-06-26 11:18:32 +02:00
kore_parse_config(void)
{
FILE *fp;
struct passwd *pwd;
char path[PATH_MAX];
if (finalized)
return;
fp = NULL;
#if !defined(KORE_SINGLE_BINARY)
if (config_file != NULL) {
if ((fp = fopen(config_file, "r")) == NULL) {
fatal("configuration given cannot be opened: %s",
config_file);
}
}
#else
fp = config_file_write();
#endif
if (fp != NULL) {
kore_parse_config_file(fp);
(void)fclose(fp);
}
kore_tls_dh_check();
2021-04-21 22:39:35 +02:00
if (!kore_module_loaded())
fatal("no application module was loaded");
if (worker_privsep.root == NULL) {
if (getcwd(path, sizeof(path)) == NULL)
fatal("getcwd: %s", errno_s);
worker_privsep.root = kore_strdup(path);
if (!kore_quiet)
kore_log(LOG_NOTICE, "privsep: no root path set");
}
2015-05-20 11:34:57 +02:00
if (worker_privsep.runas == NULL) {
if ((pwd = getpwuid(getuid())) == NULL)
fatal("getpwuid: %s", errno_s);
worker_privsep.runas = kore_strdup(pwd->pw_name);
if (!kore_quiet)
kore_log(LOG_NOTICE, "privsep: no runas user set");
2015-05-20 11:34:57 +02:00
endpwent();
}
configure_check_var(&keymgr_privsep.runas, worker_privsep.runas,
"privsep: no keymgr runas set");
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
configure_check_var(&acme_privsep.runas, worker_privsep.runas,
"privsep: no acme runas set");
#endif
configure_check_var(&keymgr_privsep.root, worker_privsep.root,
"privsep: no keymgr root set");
#if defined(KORE_USE_ACME)
configure_check_var(&acme_privsep.root, worker_privsep.root,
"privsep: no acme root set");
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#endif
if (skip_chroot) {
worker_privsep.skip_chroot = 1;
keymgr_privsep.skip_chroot = 1;
#if defined(KORE_USE_ACME)
acme_privsep.skip_chroot = 1;
#endif
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (skip_runas) {
worker_privsep.skip_runas = 1;
keymgr_privsep.skip_runas = 1;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
acme_privsep.skip_runas = 1;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#endif
}
if (skip_runas && !kore_quiet)
kore_log(LOG_NOTICE, "privsep: skipping all runas options");
if (skip_chroot && !kore_quiet)
kore_log(LOG_NOTICE, "privsep: skipping all chroot options");
finalized = 1;
}
void
kore_parse_config_file(FILE *fp)
2013-05-01 17:17:16 +02:00
{
int i, lineno;
char buf[BUFSIZ], *p, *t, *v;
2013-05-01 17:17:16 +02:00
lineno = 1;
while ((p = kore_read_line(fp, buf, sizeof(buf))) != NULL) {
if (strlen(p) == 0) {
2013-05-01 17:17:16 +02:00
lineno++;
continue;
}
if (!strcmp(p, "}") && current_privsep != NULL) {
lineno++;
current_privsep = NULL;
continue;
}
if (!strcmp(p, "}") && current_server != NULL) {
lineno++;
kore_server_finalize(current_server);
current_server = NULL;
continue;
}
#if !defined(KORE_NO_HTTP)
if (!strcmp(p, "}") && current_route != NULL) {
lineno++;
current_route = NULL;
continue;
}
if (!strcmp(p, "}") && current_auth != NULL) {
if (current_auth->validator == NULL) {
fatal("no authentication validator for %s",
current_auth->name);
}
lineno++;
current_auth = NULL;
continue;
}
#endif
if (!strcmp(p, "}") && current_domain != NULL) {
if (current_domain->server == NULL) {
fatal("domain '%s' not attached to server",
current_domain->domain);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (current_domain->server->tls == 1) {
#if defined(KORE_USE_ACME)
if (current_domain->acme) {
lineno++;
current_domain = NULL;
continue;
}
#endif
if (current_domain->certfile == NULL ||
current_domain->certkey == NULL) {
fatal("incomplete TLS setup for '%s'",
current_domain->domain);
}
}
current_domain = NULL;
}
if (!strcmp(p, "}")) {
lineno++;
continue;
}
if ((t = strchr(p, ' ')) == NULL) {
kore_log(LOG_NOTICE,
"ignoring \"%s\" on line %d", p, lineno++);
continue;
2013-05-01 17:17:16 +02:00
}
*(t)++ = '\0';
p = kore_text_trim(p, strlen(p));
t = kore_text_trim(t, strlen(t));
if (strlen(p) == 0 || strlen(t) == 0) {
kore_log(LOG_NOTICE,
"ignoring \"%s\" on line %d", p, lineno++);
continue;
}
for (i = 0; config_directives[i].name != NULL; i++) {
if (!strcmp(config_directives[i].name, p)) {
if ((v = configure_resolve_var(t)) == NULL)
fatal("variable %s does not exist", t);
if (config_directives[i].configure(v))
break;
fatal("configuration error on line %d", lineno);
/* NOTREACHED */
}
}
if (config_directives[i].name != NULL) {
lineno++;
continue;
}
for (i = 0; config_settings[i].name != NULL; i++) {
if (!strcmp(config_settings[i].name, p)) {
if ((v = configure_resolve_var(t)) == NULL)
fatal("variable %s does not exist", t);
if (config_settings[i].configure(v))
break;
fatal("configuration error on line %d", lineno);
/* NOTREACHED */
}
}
if (config_settings[i].name == NULL) {
kore_log(LOG_NOTICE,
"ignoring \"%s\" on line %d", p, lineno);
}
2013-05-01 17:17:16 +02:00
lineno++;
}
}
2014-04-09 14:43:23 +02:00
int
kore_configure_setting(const char *name, char *value)
{
int i;
if (finalized)
return (KORE_RESULT_ERROR);
for (i = 0; config_settings[i].name != NULL; i++) {
if (!strcmp(config_settings[i].name, name)) {
if (config_settings[i].configure(value))
return (KORE_RESULT_OK);
fatal("bad value '%s' for '%s'", value, name);
}
}
kore_log(LOG_NOTICE, "ignoring unknown kore.config.%s setting", name);
return (KORE_RESULT_OK);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void
configure_check_var(char **var, const char *other, const char *logmsg)
{
if (*var == NULL) {
if (!kore_quiet)
kore_log(LOG_NOTICE, "%s", logmsg);
*var = kore_strdup(other);
}
}
static char *
configure_resolve_var(char *var)
{
char *v;
if (var[0] == '$') {
if ((v = getenv(&var[1])) == NULL)
return (NULL);
} else {
v = var;
}
return (v);
}
static int
configure_include(char *path)
{
FILE *fp;
if ((fp = fopen(path, "r")) == NULL)
fatal("failed to open include '%s'", path);
kore_parse_config_file(fp);
(void)fclose(fp);
Rework HTTP and worker processes. The HTTP layer used to make a copy of each incoming header and its value for a request. Stop doing that and make HTTP headers zero-copy all across the board. This change comes with some api function changes, notably the http_request_header() function which now takes a const char ** rather than a char ** out pointer. This commit also constifies several members of http_request, beware. Additional rework how the worker processes deal with the accept lock. Before: if a worker held the accept lock and it accepted a new connection it would release the lock for others and back off for 500ms before attempting to grab the lock again. This approach worked but under high load this starts becoming obvious. Now: - workers not holding the accept lock and not having any connections will wait less long before returning from kore_platform_event_wait(). - workers not holding the accept lock will no longer blindly wait an arbitrary amount in kore_platform_event_wait() but will look at how long until the next lock grab is and base their timeout on that. - if a worker its next_lock timeout is up and failed to grab the lock it will try again in half the time again. - the worker process holding the lock will when releasing the lock double check if it still has space for newer connections, if it does it will keep the lock until it is full. This prevents the lock from bouncing between several non busy worker processes all the time. Additional fixes: - Reduce the number of times we check the timeout list, only do it twice per second rather then every event tick. - Fix solo worker count for TLS (we actually hold two processes, not one). - Make sure we don't accidentally miscalculate the idle time causing new connections under heavy load to instantly drop. - Swap from gettimeofday() to clock_gettime() now that MacOS caught up.
2018-02-14 13:48:49 +01:00
return (KORE_RESULT_OK);
2013-05-01 17:17:16 +02:00
}
static int
configure_server(char *options)
{
struct kore_server *srv;
char *argv[3];
if (current_server != NULL) {
kore_log(LOG_ERR, "nested server contexts are not allowed");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL || argv[1] == NULL) {
kore_log(LOG_ERR, "server context invalid");
return (KORE_RESULT_ERROR);
}
if (strcmp(argv[1], "{")) {
kore_log(LOG_ERR, "server context not opened correctly");
return (KORE_RESULT_ERROR);
}
if ((srv = kore_server_lookup(argv[0])) != NULL) {
kore_log(LOG_ERR, "server with name '%s' exists", srv->name);
return (KORE_RESULT_ERROR);
}
current_server = kore_server_create(argv[0]);
return (KORE_RESULT_OK);
}
static int
configure_tls(char *yesno)
{
if (!kore_tls_supported()) {
current_server->tls = 0;
if (!strcmp(yesno, "yes")) {
kore_log(LOG_ERR, "TLS not supported in this build");
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
if (current_server == NULL) {
kore_log(LOG_ERR, "tls keyword not inside a server context");
return (KORE_RESULT_ERROR);
}
if (!strcmp(yesno, "no")) {
current_server->tls = 0;
} else if (!strcmp(yesno, "yes")) {
current_server->tls = 1;
} else {
kore_log(LOG_ERR, "invalid '%s' for yes|no tls option", yesno);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(KORE_USE_ACME)
static int
configure_acme(char *yesno)
{
if (current_domain == NULL) {
kore_log(LOG_ERR, "acme keyword not inside a domain context");
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
return (KORE_RESULT_ERROR);
}
if (strchr(current_domain->domain, '*')) {
kore_log(LOG_ERR,
"wildcards not supported due to lack of dns-01");
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
return (KORE_RESULT_ERROR);
}
if (!strcmp(yesno, "no")) {
current_domain->acme = 0;
} else if (!strcmp(yesno, "yes")) {
current_domain->acme = 1;
/* Override keyfile and certfile locations. */
kore_free(current_domain->certkey);
kore_free(current_domain->certfile);
2019-11-13 23:01:24 +01:00
kore_acme_get_paths(current_domain->domain,
&current_domain->certkey, &current_domain->certfile);
acme_domains++;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
} else {
kore_log(LOG_ERR, "invalid '%s' for yes|no acme option", yesno);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_acme_email(char *email)
{
kore_free(acme_email);
acme_email = kore_strdup(email);
return (KORE_RESULT_OK);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static int
configure_acme_provider(char *provider)
{
kore_free(acme_provider);
acme_provider = kore_strdup(provider);
return (KORE_RESULT_OK);
}
#endif
2013-05-01 17:17:16 +02:00
static int
configure_bind(char *options)
2013-05-01 17:17:16 +02:00
{
char *argv[4];
if (current_server == NULL) {
kore_log(LOG_ERR, "bind keyword not inside a server context");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 4);
if (argv[0] == NULL || argv[1] == NULL)
2013-05-01 17:17:16 +02:00
return (KORE_RESULT_ERROR);
return (kore_server_bind(current_server, argv[0], argv[1], argv[2]));
2013-05-01 17:17:16 +02:00
}
static int
configure_bind_unix(char *options)
{
char *argv[3];
if (current_server == NULL) {
kore_log(LOG_ERR,
"bind_unix keyword not inside a server context");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL)
return (KORE_RESULT_ERROR);
return (kore_server_bind_unix(current_server, argv[0], argv[1]));
}
2013-05-01 17:17:16 +02:00
static int
configure_load(char *options)
2013-05-01 17:17:16 +02:00
{
char *argv[3];
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL)
2013-05-01 17:17:16 +02:00
return (KORE_RESULT_ERROR);
kore_module_load(argv[0], argv[1], KORE_MODULE_NATIVE);
return (KORE_RESULT_OK);
}
#if defined(KORE_SINGLE_BINARY)
static FILE *
config_file_write(void)
{
FILE *fp;
ssize_t ret;
int fd, len;
char fpath[MAXPATHLEN];
len = snprintf(fpath, sizeof(fpath), "%s/%s.XXXXXX", KORE_TMPDIR,
__progname);
if (len == -1 || (size_t)len >= sizeof(fpath))
fatal("failed to create temporary path");
if ((fd = mkstemp(fpath)) == -1)
fatal("mkstemp(%s): %s", fpath, errno_s);
(void)unlink(fpath);
for (;;) {
ret = write(fd, asset_builtin_kore_conf,
asset_len_builtin_kore_conf);
if (ret == -1) {
if (errno == EINTR)
continue;
fatal("failed to write temporary config: %s", errno_s);
}
if ((size_t)ret != asset_len_builtin_kore_conf)
fatal("failed to write temporary config");
break;
}
if ((fp = fdopen(fd, "w+")) == NULL)
fatal("fdopen(): %s", errno_s);
rewind(fp);
return (fp);
}
#elif defined(KORE_USE_PYTHON)
static int
configure_file(char *file)
{
free(config_file);
if ((config_file = strdup(file)) == NULL)
fatal("strdup");
return (KORE_RESULT_OK);
}
#endif
static int
configure_tls_version(char *version)
{
int ver;
if (!strcmp(version, "1.3")) {
ver = KORE_TLS_VERSION_1_3;
} else if (!strcmp(version, "1.2")) {
ver = KORE_TLS_VERSION_1_2;
} else if (!strcmp(version, "both")) {
ver = KORE_TLS_VERSION_BOTH;
} else {
kore_log(LOG_ERR,
"unknown value for tls_version: %s (use 1.3, 1.2, both)",
version);
return (KORE_RESULT_ERROR);
}
kore_tls_version_set(ver);
return (KORE_RESULT_OK);
}
static int
configure_tls_cipher(char *cipherlist)
{
return (kore_tls_ciphersuite_set(cipherlist));
}
static int
configure_tls_dhparam(char *path)
{
return (kore_tls_dh_load(path));
2013-05-01 17:17:16 +02:00
}
static int
configure_client_verify_depth(char *value)
{
int err, depth;
if (current_domain == NULL) {
kore_log(LOG_ERR,
"client_verify_depth keyword not in domain context");
return (KORE_RESULT_ERROR);
}
depth = kore_strtonum(value, 10, 0, INT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad client_verify_depth value: %s", value);
return (KORE_RESULT_ERROR);
}
current_domain->x509_verify_depth = depth;
return (KORE_RESULT_OK);
}
2013-12-14 16:31:07 +01:00
static int
configure_client_verify(char *options)
2013-12-14 16:31:07 +01:00
{
char *argv[3];
2013-12-14 16:31:07 +01:00
if (current_domain == NULL) {
kore_log(LOG_ERR,
"client_verify keyword not in domain context");
2013-12-14 16:31:07 +01:00
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL) {
kore_log(LOG_ERR, "client_verify is missing a parameter");
2013-12-14 16:31:07 +01:00
return (KORE_RESULT_ERROR);
}
if (current_domain->cafile != NULL) {
kore_log(LOG_ERR, "client_verify already set for '%s'",
2013-12-14 16:31:07 +01:00
current_domain->domain);
return (KORE_RESULT_ERROR);
}
current_domain->cafile = kore_strdup(argv[0]);
if (argv[1] != NULL)
current_domain->crlfile = kore_strdup(argv[1]);
2013-12-14 16:31:07 +01:00
return (KORE_RESULT_OK);
}
static int
configure_rand_file(char *path)
{
if (kore_rand_file != NULL)
kore_free(kore_rand_file);
kore_rand_file = kore_strdup(path);
return (KORE_RESULT_OK);
}
2013-06-24 09:36:40 +02:00
static int
configure_certfile(char *path)
2013-06-24 09:36:40 +02:00
{
if (current_domain == NULL) {
kore_log(LOG_ERR,
"certfile keyword not specified in domain context");
2013-06-24 09:36:40 +02:00
return (KORE_RESULT_ERROR);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_free(current_domain->certfile);
current_domain->certfile = kore_strdup(path);
return (KORE_RESULT_OK);
}
static int
configure_certkey(char *path)
{
if (current_domain == NULL) {
kore_log(LOG_ERR,
"certkey keyword not specified in domain context");
2013-06-24 09:36:40 +02:00
return (KORE_RESULT_ERROR);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_free(current_domain->certkey);
current_domain->certkey = kore_strdup(path);
2013-06-24 09:36:40 +02:00
return (KORE_RESULT_OK);
}
static int
configure_privsep(char *options)
{
char *argv[3];
if (current_privsep != NULL) {
kore_log(LOG_ERR, "nested privsep contexts are not allowed");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL || argv[1] == NULL) {
kore_log(LOG_ERR, "invalid privsep context");
return (KORE_RESULT_ERROR);
}
if (strcmp(argv[1], "{")) {
kore_log(LOG_ERR, "privsep context not opened correctly");
return (KORE_RESULT_ERROR);
}
if (!strcmp(argv[0], "worker")) {
current_privsep = &worker_privsep;
} else if (!strcmp(argv[0], "keymgr")) {
current_privsep = &keymgr_privsep;
#if defined(KORE_USE_ACME)
2021-12-02 19:33:20 +01:00
} else if (!strcmp(argv[0], "acme")) {
current_privsep = &acme_privsep;
#endif
} else {
kore_log(LOG_ERR, "unknown privsep context: %s", argv[0]);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_privsep_runas(char *user)
{
if (current_privsep == NULL) {
kore_log(LOG_ERR, "runas keyword not in privsep context");
return (KORE_RESULT_ERROR);
}
if (current_privsep->runas != NULL)
kore_free(current_privsep->runas);
current_privsep->runas = kore_strdup(user);
return (KORE_RESULT_OK);
}
static int
configure_privsep_root(char *root)
{
if (current_privsep == NULL) {
kore_log(LOG_ERR, "root keyword not in privsep context");
return (KORE_RESULT_ERROR);
}
if (current_privsep->root != NULL)
kore_free(current_privsep->root);
current_privsep->root = kore_strdup(root);
return (KORE_RESULT_OK);
}
static int
configure_privsep_skip(char *option)
{
if (current_privsep == NULL) {
kore_log(LOG_ERR, "skip keyword not in privsep context");
return (KORE_RESULT_ERROR);
}
if (!strcmp(option, "chroot")) {
current_privsep->skip_chroot = 1;
} else {
kore_log(LOG_ERR, "unknown skip option '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_domain(char *options)
{
char *argv[3];
if (current_domain != NULL) {
kore_log(LOG_ERR, "nested domain contexts are not allowed");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[0] == NULL || argv[1] == NULL) {
kore_log(LOG_ERR, "invalid domain context");
return (KORE_RESULT_ERROR);
}
if (strcmp(argv[1], "{")) {
kore_log(LOG_ERR, "domain context not opened correctly");
return (KORE_RESULT_ERROR);
}
if (strlen(argv[0]) >= KORE_DOMAINNAME_LEN - 1) {
kore_log(LOG_ERR, "domain name '%s' too long", argv[0]);
return (KORE_RESULT_ERROR);
}
current_domain = kore_domain_new(argv[0]);
return (KORE_RESULT_OK);
}
static int
configure_attach(char *name)
{
struct kore_server *srv;
if (current_domain == NULL) {
kore_log(LOG_ERR, "attach keyword not in domain context");
return (KORE_RESULT_ERROR);
}
if (current_domain->server != NULL) {
kore_log(LOG_ERR, "domain '%s' already attached to server",
current_domain->domain);
return (KORE_RESULT_ERROR);
}
if ((srv = kore_server_lookup(name)) == NULL) {
kore_log(LOG_ERR, "server '%s' does not exist", name);
return (KORE_RESULT_ERROR);
}
if (!kore_domain_attach(current_domain, srv)) {
kore_log(LOG_ERR, "failed to attach '%s' to '%s'",
current_domain->domain, name);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#if !defined(KORE_NO_HTTP)
static int
configure_static_handler(char *options)
{
kore_log(LOG_NOTICE, "static keyword removed, use route instead");
return (KORE_RESULT_ERROR);
}
static int
configure_dynamic_handler(char *options)
{
kore_log(LOG_NOTICE, "dynamic keyword removed, use route instead");
return (KORE_RESULT_ERROR);
}
static int
configure_route(char *options)
{
struct kore_route *rt;
int type;
char *argv[4];
if (current_domain == NULL) {
kore_log(LOG_ERR, "route keyword not in domain context");
return (KORE_RESULT_ERROR);
}
if (current_route != NULL) {
kore_log(LOG_ERR, "nested route contexts not allowed");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 4);
if (argv[1] == NULL || strcmp(argv[1], "{")) {
kore_log(LOG_ERR, "invalid route context");
return (KORE_RESULT_ERROR);
}
if (*argv[0] == '/')
type = HANDLER_TYPE_STATIC;
else
type = HANDLER_TYPE_DYNAMIC;
if ((rt = kore_route_create(current_domain, argv[0], type)) == NULL) {
kore_log(LOG_ERR,
"failed to create route handler for '%s'", argv[0]);
return (KORE_RESULT_ERROR);
}
current_route = rt;
return (KORE_RESULT_OK);
}
static int
configure_route_handler(char *name)
{
if (current_route == NULL) {
kore_log(LOG_ERR,
"handler keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
kore_route_callback(current_route, name);
return (KORE_RESULT_OK);
}
static int
configure_route_on_headers(char *name)
{
if (current_route == NULL) {
kore_log(LOG_ERR,
"on_header keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
if ((current_route->on_headers = kore_runtime_getcall(name)) == NULL) {
kore_log(LOG_ERR, "on_headers callback '%s' for '%s' not found",
name, current_route->path);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_route_on_body_chunk(char *name)
{
if (current_route == NULL) {
kore_log(LOG_ERR,
"on_body_chunk keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
current_route->on_body_chunk = kore_runtime_getcall(name);
if (current_route->on_body_chunk == NULL) {
kore_log(LOG_ERR,
"on_body_chunk callback '%s' for '%s' not found",
name, current_route->path);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_route_on_free(char *name)
{
if (current_route == NULL) {
kore_log(LOG_ERR,
"on_free keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
if ((current_route->on_free = kore_runtime_getcall(name)) == NULL) {
kore_log(LOG_ERR, "on_free callback '%s' for '%s' not found",
name, current_route->path);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_route_authenticate(char *name)
{
if (current_route == NULL) {
kore_log(LOG_ERR,
"authenticate keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
current_route->auth = kore_auth_lookup(name);
if (current_route->auth == NULL) {
kore_log(LOG_ERR, "no such authentication '%s' for '%s' found",
name, current_route->path);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_route_methods(char *options)
{
int i, cnt;
char *argv[10];
if (current_route == NULL) {
kore_log(LOG_ERR,
"methods keyword not inside of route context");
return (KORE_RESULT_ERROR);
}
cnt = kore_split_string(options, " ", argv, 10);
if (cnt < 1) {
kore_log(LOG_ERR,
"bad methods option '%s', missing methods", options);
return (KORE_RESULT_ERROR);
}
current_route->methods = 0;
for (i = 0; i < cnt; i++) {
if (!strcasecmp(argv[i], "post")) {
current_route->methods |= HTTP_METHOD_POST;
} else if (!strcasecmp(argv[i], "get")) {
current_route->methods |= HTTP_METHOD_GET;
} else if (!strcasecmp(argv[i], "put")) {
current_route->methods |= HTTP_METHOD_PUT;
} else if (!strcasecmp(argv[i], "delete")) {
current_route->methods |= HTTP_METHOD_DELETE;
} else if (!strcasecmp(argv[i], "head")) {
current_route->methods |= HTTP_METHOD_HEAD;
} else if (!strcasecmp(argv[i], "patch")) {
current_route->methods |= HTTP_METHOD_PATCH;
} else if (!strcasecmp(argv[i], "options")) {
current_route->methods |= HTTP_METHOD_OPTIONS;
} else {
kore_log(LOG_ERR, "unknown method: %s in method for %s",
argv[i], current_route->path);
return (KORE_RESULT_ERROR);
}
}
return (KORE_RESULT_OK);
}
static int
configure_return(char *options)
{
char *argv[3];
int elm, status, err;
if (current_domain == NULL) {
kore_log(LOG_ERR, "return keyword not in domain context");
return (KORE_RESULT_ERROR);
}
elm = kore_split_string(options, " ", argv, 3);
if (elm != 2) {
kore_log(LOG_ERR, "missing parameters for return");
return (KORE_RESULT_ERROR);
}
status = kore_strtonum(argv[1], 10, 400, 600, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"invalid status code on return (%s)", argv[1]);
return (KORE_RESULT_ERROR);
}
if (!http_redirect_add(current_domain, argv[0], status, NULL)) {
kore_log(LOG_ERR, "invalid regex on return path");
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_redirect(char *options)
{
char *argv[4];
int elm, status, err;
if (current_domain == NULL) {
kore_log(LOG_ERR, "redirect keyword not in domain context");
return (KORE_RESULT_ERROR);
}
elm = kore_split_string(options, " ", argv, 4);
if (elm != 3) {
kore_log(LOG_ERR, "missing parameters for redirect");
return (KORE_RESULT_ERROR);
}
status = kore_strtonum(argv[1], 10, 300, 399, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"invalid status code on redirect (%s)", argv[1]);
return (KORE_RESULT_ERROR);
}
if (!http_redirect_add(current_domain, argv[0], status, argv[2])) {
kore_log(LOG_ERR, "invalid regex on redirect path");
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_filemap(char *options)
{
char *argv[4];
if (current_domain == NULL) {
kore_log(LOG_ERR, "filemap keyword not in domain context");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 4);
if (argv[0] == NULL || argv[1] == NULL) {
kore_log(LOG_ERR, "missing parameters for filemap");
return (KORE_RESULT_ERROR);
}
2022-08-10 10:20:18 +02:00
if (kore_filemap_create(current_domain,
argv[1], argv[0], argv[2]) == NULL) {
kore_log(LOG_ERR, "cannot create filemap for %s", argv[1]);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_accesslog(char *path)
{
if (current_domain == NULL) {
kore_log(LOG_ERR, "accesslog not specified in domain context");
return (KORE_RESULT_ERROR);
}
if (current_domain->accesslog != -1) {
kore_log(LOG_ERR, "domain '%s' already has an open accesslog",
current_domain->domain);
return (KORE_RESULT_ERROR);
}
current_domain->accesslog = open(path,
O_CREAT | O_APPEND | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (current_domain->accesslog == -1) {
kore_log(LOG_ERR, "accesslog open(%s): %s", path, errno_s);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_filemap_ext(char *ext)
{
kore_free(kore_filemap_ext);
kore_filemap_ext = kore_strdup(ext);
return (KORE_RESULT_OK);
}
static int
configure_filemap_index(char *index)
{
kore_free(kore_filemap_index);
kore_filemap_index = kore_strdup(index);
return (KORE_RESULT_OK);
}
static int
configure_http_media_type(char *type)
{
int i;
char *extensions, *ext[10];
extensions = strchr(type, ' ');
if (extensions == NULL) {
kore_log(LOG_ERR, "bad http_media_type value '%s'", type);
return (KORE_RESULT_ERROR);
}
*(extensions)++ = '\0';
kore_split_string(extensions, " \t", ext, 10);
for (i = 0; ext[i] != NULL; i++) {
if (!http_media_register(ext[i], type)) {
kore_log(LOG_ERR,
"duplicate extension found '%s'", ext[i]);
return (KORE_RESULT_ERROR);
}
}
if (i == 0) {
kore_log(LOG_ERR, "missing extensions in '%s'", type);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_header_max(char *option)
{
int err;
http_header_max = kore_strtonum(option, 10, 1, 65535, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_header_max value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_header_timeout(char *option)
{
int err;
http_header_timeout = kore_strtonum(option, 10, 1, 65535, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_header_timeout value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_body_max(char *option)
{
int err;
2017-02-06 21:28:33 +01:00
http_body_max = kore_strtonum(option, 10, 0, LONG_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_body_max value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_body_timeout(char *option)
{
int err;
http_body_timeout = kore_strtonum(option, 10, 1, 65535, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_body_timeout value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
static int
configure_http_body_disk_offload(char *option)
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
{
int err;
http_body_disk_offload = kore_strtonum(option, 10, 0, LONG_MAX, &err);
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad http_body_disk_offload value '%s'", option);
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_body_disk_path(char *path)
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
{
if (strcmp(http_body_disk_path, HTTP_BODY_DISK_PATH))
kore_free(http_body_disk_path);
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
http_body_disk_path = kore_strdup(path);
Massive rework of HTTP layer. This commit is a flag day, your old modules will almost certainly need to be updated in order to build properly with these changes. Summary of changes: - Offload HTTP bodies to disk if they are large (inspired by #100). (disabled by default) - The http_argument_get* macros now takes an explicit http_request parameter. - Kore will now throw 404 errors almost immediately after an HTTP request has come in instead of waiting until all data has arrived. API changes: - http_argument_get* macros now require an explicit http_request parameter. (no more magic invokations). - http_generic_404() is gone - http_populate_arguments() is gone - http_body_bytes() is gone - http_body_text() is gone - http_body_read() has been added - http_populate_post() has been added - http_populate_get() has been added - http_file_read() has been added - http_file_rewind() has been added - http_file_lookup() no longer takes name, fname, data and len parameters. - http_file_lookup() now returns a struct http_file pointer. - http_populate_multipart_form() no longer takes an secondary parameter. New configuration options: - http_body_disk_offload: Number of bytes after which Kore will offload the HTTP body to disk instead of retaining it in memory. If 0 this feature is disabled. (Default: 0) - http_body_disk_path: The path where Kore will store temporary HTTP body files. (this directory does not get created if http_body_disk_offload is 0). New example: The upload example has been added, demonstrating how to deal with file uploads from a multipart form.
2016-01-18 11:30:22 +01:00
return (KORE_RESULT_OK);
}
static int
configure_http_server_version(char *version)
{
http_server_version(version);
return (KORE_RESULT_OK);
}
static int
configure_http_pretty_error(char *yesno)
{
if (!strcmp(yesno, "no")) {
http_pretty_error = 0;
} else if (!strcmp(yesno, "yes")) {
http_pretty_error = 1;
} else {
kore_log(LOG_ERR,
"invalid '%s' for yes|no http_pretty_error option", yesno);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_hsts_enable(char *option)
{
int err;
http_hsts_enable = kore_strtonum(option, 10, 0, LONG_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_hsts_enable value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_keepalive_time(char *option)
{
int err;
http_keepalive_time = kore_strtonum(option, 10, 0, USHRT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad http_keepalive_time value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_request_ms(char *option)
{
int err;
http_request_ms = kore_strtonum(option, 10, 0, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_request_ms value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_request_limit(char *option)
{
int err;
http_request_limit = kore_strtonum(option, 10, 0, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad http_request_limit value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_validator(char *name)
{
u_int8_t type;
char *tname, *value;
if ((tname = strchr(name, ' ')) == NULL) {
kore_log(LOG_ERR, "missing validator name");
return (KORE_RESULT_ERROR);
}
*(tname)++ = '\0';
tname = kore_text_trim(tname, strlen(tname));
if ((value = strchr(tname, ' ')) == NULL) {
kore_log(LOG_ERR, "missing validator value");
return (KORE_RESULT_ERROR);
}
*(value)++ = '\0';
value = kore_text_trim(value, strlen(value));
if (!strcmp(tname, "regex")) {
type = KORE_VALIDATOR_TYPE_REGEX;
} else if (!strcmp(tname, "function")) {
type = KORE_VALIDATOR_TYPE_FUNCTION;
} else {
kore_log(LOG_ERR,
"bad type '%s' for validator '%s'", tname, name);
return (KORE_RESULT_ERROR);
}
if (!kore_validator_add(name, type, value)) {
kore_log(LOG_ERR, "bad validator specified for '%s'", name);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_validate(char *options)
{
struct kore_validator *val;
struct kore_route_params *param;
char *method, *argv[4];
int flags, http_method;
if (kore_split_string(options, " ", argv, 4) != 3) {
kore_log(LOG_ERR,
"validate keyword needs 3 args: method param validator");
return (KORE_RESULT_ERROR);
}
flags = 0;
if ((method = strchr(argv[0], ':')) != NULL) {
*(method)++ = '\0';
if (!strcasecmp(argv[0], "qs")) {
flags = KORE_PARAMS_QUERY_STRING;
} else {
kore_log(LOG_ERR,
"unknown validate method prefix '%s' for '%s'",
argv[0], current_route->path);
return (KORE_RESULT_ERROR);
}
} else {
method = argv[0];
}
if ((val = kore_validator_lookup(argv[2])) == NULL) {
kore_log(LOG_ERR, "unknown validator '%s'", argv[2]);
return (KORE_RESULT_ERROR);
}
if (!strcasecmp(method, "post")) {
http_method = HTTP_METHOD_POST;
} else if (!strcasecmp(method, "get")) {
http_method = HTTP_METHOD_GET;
/* Let params get /foo {} imply qs:get automatically. */
flags |= KORE_PARAMS_QUERY_STRING;
} else if (!strcasecmp(method, "put")) {
http_method = HTTP_METHOD_PUT;
} else if (!strcasecmp(method, "delete")) {
http_method = HTTP_METHOD_DELETE;
} else if (!strcasecmp(method, "head")) {
http_method = HTTP_METHOD_HEAD;
} else if (!strcasecmp(method, "patch")) {
http_method = HTTP_METHOD_PATCH;
} else {
kore_log(LOG_ERR, "unknown method: %s in validator for %s",
method, current_route->path);
return (KORE_RESULT_ERROR);
}
if (!(current_route->methods & http_method)) {
kore_log(LOG_ERR, "method '%s' not enabled for route '%s'",
method, current_route->path);
return (KORE_RESULT_ERROR);
}
param = kore_calloc(1, sizeof(*param));
param->flags = flags;
param->validator = val;
param->method = http_method;
param->name = kore_strdup(argv[1]);
TAILQ_INSERT_TAIL(&current_route->params, param, list);
return (KORE_RESULT_OK);
}
static int
configure_authentication(char *options)
{
char *argv[3];
if (current_auth != NULL) {
kore_log(LOG_ERR, "previous authentication block not closed");
return (KORE_RESULT_ERROR);
}
kore_split_string(options, " ", argv, 3);
if (argv[1] == NULL) {
kore_log(LOG_ERR, "missing name for authentication block");
return (KORE_RESULT_ERROR);
}
if (strcmp(argv[1], "{")) {
kore_log(LOG_ERR, "missing { for authentication block");
return (KORE_RESULT_ERROR);
}
if (!kore_auth_new(argv[0]))
return (KORE_RESULT_ERROR);
current_auth = kore_auth_lookup(argv[0]);
return (KORE_RESULT_OK);
}
static int
configure_authentication_type(char *option)
{
if (current_auth == NULL) {
kore_log(LOG_ERR,
"authentication_type keyword not in correct context");
return (KORE_RESULT_ERROR);
}
if (!strcmp(option, "cookie")) {
current_auth->type = KORE_AUTH_TYPE_COOKIE;
} else if (!strcmp(option, "header")) {
current_auth->type = KORE_AUTH_TYPE_HEADER;
} else if (!strcmp(option, "request")) {
current_auth->type = KORE_AUTH_TYPE_REQUEST;
} else {
kore_log(LOG_ERR, "unknown authentication type '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_authentication_value(char *option)
{
if (current_auth == NULL) {
kore_log(LOG_ERR,
"authentication_value keyword not in correct context");
return (KORE_RESULT_ERROR);
}
if (current_auth->value != NULL)
kore_free(current_auth->value);
current_auth->value = kore_strdup(option);
return (KORE_RESULT_OK);
}
static int
configure_authentication_validator(char *validator)
{
struct kore_validator *val;
if (current_auth == NULL) {
kore_log(LOG_ERR,
"authentication_validator not in correct context");
return (KORE_RESULT_ERROR);
}
if ((val = kore_validator_lookup(validator)) == NULL) {
kore_log(LOG_ERR,
"authentication validator '%s' not found", validator);
return (KORE_RESULT_ERROR);
}
current_auth->validator = val;
return (KORE_RESULT_OK);
}
static int
configure_authentication_uri(char *uri)
{
if (current_auth == NULL) {
kore_log(LOG_ERR,
"authentication_uri keyword not in correct context");
return (KORE_RESULT_ERROR);
}
if (current_auth->redirect != NULL)
kore_free(current_auth->redirect);
current_auth->redirect = kore_strdup(uri);
return (KORE_RESULT_OK);
}
static int
configure_websocket_maxframe(char *option)
{
int err;
kore_websocket_maxframe = kore_strtonum64(option, 1, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad kore_websocket_maxframe value '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_websocket_timeout(char *option)
{
int err;
kore_websocket_timeout = kore_strtonum64(option, 1, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad kore_websocket_timeout value '%s'", option);
return (KORE_RESULT_ERROR);
}
kore_websocket_timeout = kore_websocket_timeout * 1000;
return (KORE_RESULT_OK);
}
2015-11-27 18:12:08 +01:00
#endif /* !KORE_NO_HTTP */
static int
configure_logfile(char *path)
{
kore_log_file(path);
return (KORE_RESULT_OK);
}
static int
configure_workers(char *option)
{
int err;
worker_count = kore_strtonum(option, 10, 1, KORE_WORKER_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad value for worker '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_pidfile(char *path)
{
if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT))
kore_free(kore_pidfile);
kore_pidfile = kore_strdup(path);
return (KORE_RESULT_OK);
}
static int
configure_max_connections(char *option)
{
int err;
worker_max_connections = kore_strtonum(option, 10, 1, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad value for worker_max_connections '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_rlimit_nofiles(char *option)
{
int err;
worker_rlimit_nofiles = kore_strtonum(option, 10, 1, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad value for worker_rlimit_nofiles '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_accept_threshold(char *option)
{
int err;
worker_accept_threshold = kore_strtonum(option, 0, 1, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad value for worker_accept_threshold '%s'\n", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_death_policy(char *option)
{
if (!strcmp(option, "restart")) {
worker_policy = KORE_WORKER_POLICY_RESTART;
} else if (!strcmp(option, "terminate")) {
worker_policy = KORE_WORKER_POLICY_TERMINATE;
} else {
kore_log(LOG_ERR,
"bad value for worker_death_policy '%s'\n", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_set_affinity(char *option)
{
int err;
worker_set_affinity = kore_strtonum(option, 10, 0, 1, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad value for worker_set_affinity '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_socket_backlog(char *option)
{
int err;
kore_socket_backlog = kore_strtonum(option, 10, 0, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad socket_backlog value: '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#if defined(KORE_USE_PGSQL)
static int
configure_pgsql_conn_max(char *option)
{
int err;
pgsql_conn_max = kore_strtonum(option, 10, 0, USHRT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad value for pgsql_conn_max '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_pgsql_queue_limit(char *option)
{
int err;
pgsql_queue_limit = kore_strtonum(option, 10, 0, UINT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR,
"bad value for pgsql_queue_limit '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#endif
#if defined(KORE_USE_TASKS)
static int
configure_task_threads(char *option)
{
int err;
kore_task_threads = kore_strtonum(option, 10, 0, UCHAR_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad value for task_threads: '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#endif
static int
configure_deployment(char *value)
{
if (!strcmp(value, "docker")) {
kore_foreground = 1;
2021-05-10 10:32:54 +02:00
skip_runas = 0;
skip_chroot = 0;
} else if (!strcmp(value, "dev") || !strcmp(value, "development")) {
2021-01-11 23:35:16 +01:00
kore_foreground = 1;
skip_runas = 1;
skip_chroot = 1;
} else if (!strcmp(value, "production")) {
2021-01-11 23:35:16 +01:00
kore_foreground = 0;
skip_runas = 0;
skip_chroot = 0;
} else {
kore_log(LOG_NOTICE,
"kore.config.deployment: bad value '%s'", value);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#if defined(KORE_USE_PYTHON)
static int
configure_python_path(char *path)
{
kore_python_path(path);
return (KORE_RESULT_OK);
}
static int
configure_python_import(char *module)
{
char *argv[3];
kore_split_string(module, " ", argv, 3);
if (argv[0] == NULL)
return (KORE_RESULT_ERROR);
kore_module_load(argv[0], argv[1], KORE_MODULE_PYTHON);
return (KORE_RESULT_OK);
}
#endif
#if defined(KORE_USE_PLATFORM_PLEDGE)
static int
configure_add_pledge(char *pledge)
{
kore_platform_add_pledge(pledge);
return (KORE_RESULT_OK);
}
#endif
#if defined(KORE_USE_CURL)
static int
configure_curl_recv_max(char *option)
{
int err;
kore_curl_recv_max = kore_strtonum64(option, 1, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad curl_recv_max value '%s'\n", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_curl_timeout(char *option)
{
int err;
kore_curl_timeout = kore_strtonum(option, 10, 0, USHRT_MAX, &err);
if (err != KORE_RESULT_OK) {
kore_log(LOG_ERR, "bad kore_curl_timeout value: '%s'", option);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#endif
#if defined(__linux__)
static int
configure_seccomp_tracing(char *opt)
{
if (!strcmp(opt, "yes")) {
kore_seccomp_tracing = 1;
} else if (!strcmp(opt, "no")) {
kore_seccomp_tracing = 0;
} else {
kore_log(LOG_ERR,
"bad seccomp_tracing value '%s' (expected yes|no)\n", opt);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
#endif