Commit Graph

84 Commits

Author SHA1 Message Date
Joris Vink cf9e97f087 Improve TLS settings and dependencies.
- Kore now only supports OpenSSL 1.1.1 and LibreSSL 3.x.
- Revise the default TLS ciphersuites.
- Kore now carries ffdhe4096.pem and installs it under PREFIX/share/kore.
- Kore its tls_dhparam config setting defaults to the path mentioned above
  so you no longer have to set it.
2021-04-21 10:48:00 +02:00
Joris Vink cc276e2471 Add kore_json_item_attach().
Allows a JSON subtree to be engrafted after creation.

from Joel Arbring via patches@
2021-04-08 09:10:58 +02:00
Joris Vink 9cfcd9a4be JSON API improvements.
- Try harder to mark integers as KORE_JSON_TYPE_INTEGER, especially if
  they fit in the internal representation of one (int64_t).

- Move error codes into the JSON code itself, rather then requiring
  a kore_json data structure. This allows the JSON API to relay errors
  such as "item not found" or "type mismatch" properly when looking at items.

- When asking for a KORE_JSON_TYPE_INTEGER_U64 and a KORE_JSON_TYPE_INTEGER
  was found with the same name, check if it could be returned properly and do
  so if possible.
2021-03-30 14:19:48 +02:00
Joris Vink a575881cb9 Enable TLS 1.3 with LibreSSL 3.2.2. 2021-01-21 15:17:21 +02:00
Joris Vink 4e2ca90095 Move Kore hook functions to kore/hooks.h. 2021-01-11 23:58:26 +01:00
Joris Vink cef5ac4003 bump copyright year. 2021-01-11 23:46:08 +01:00
Joris Vink 37f85ed663 rename foreground to kore_foreground. 2021-01-11 23:35:16 +01:00
Joris Vink 599617e7b4 More ACME protocol improvements.
- Make sure tls-alpn01 works even if the underlying SSL library ends up
  calling the ALPN callback *before* the SNI extension was parsed and
  the correct domain was selected.

LibreSSL still does this, and older OpenSSL did too I believe, however
OpenSSL grew a clue and always makes sure SNI is called first.

Yes, TLS extensions have no fixed order but it still makes sense to
notify applications using your library of the SNI extension first
before anything else almost.

Oh well.
2021-01-05 23:25:29 +01:00
Joris Vink 5421b7726e kore_json_init() should take a const void for the data. 2020-11-23 10:48:04 +01:00
Joris Vink d7fbce37f5 Better parsing of JSON integers and numbers.
Add 2 new types:
	KORE_JSON_TYPE_INTEGER
		signed integer type, internally stored as s64.

	KORE_JSON_TYPE_INTEGER_U64
		unsigned integer type, internally stored as u64.

Kore JSON parser will prefer marking integers as INTEGER_U64 if it
was unsigned and did not have fractions.
2020-11-19 14:56:17 +01:00
Joris Vink 67cf3e872b Add kore_default_getopt().
This handles the default option parsing in Kore and should be called
by single_binary=yes builds in kore_parent_configure() unless they
want to handle their own argument parsing.
2020-10-08 13:51:50 +02:00
Joris Vink 8b9f7a6c12 improve our asynchronous curl support.
- Remove the edge trigger io hacks we had in place.
- Use level triggered io for the libcurl fds instead.
- Batch all curl events together and process them at the end
  of our worker event loop.
2020-08-17 15:15:04 +02:00
Joris Vink e53de1cf4f mark kore_worker_entry as noreturn. 2020-03-25 13:35:02 +01:00
Joris Vink 9d0aef0079 bump copyright 2020-02-10 14:47:33 +01:00
Joris Vink fa2e8ef0b6 Add support for config based redirection.
Inside the domain contexts a 'redirect' rule will allow you to redirect
a request to another URI.

Ex:

Redirect all requests with a 301 to example.com

	redirect ^/.*$ 301 https://example.com

Using capture groups

	redirect ^/account/(.*)$ 301 https://example.com/account/$1

Adding the query string in the mix

	redirect ^/(.*)$ 301 https://example.com/$1?$qs
2020-02-07 06:42:33 +01:00
Joris Vink 01cc981632 Improve waiting on workers to exit take 2.
Keep track of what workers are running and account for those when things
exit. Somewhat reverts the entire last commit, that was the wrong approach.
2020-01-17 21:48:55 +01:00
Joris Vink ca70f9d726 TLS improvements.
These changes improve the constraint kore had with client authentication and
multiple domains.

- Add kore_x509_subject_name() which will return a C string containing
  the x509 subject name in full (in utf8).

- Log TLS errors if client authentication was turned on, will help debug
  issues with client authentication in the future.

- If SNI was present in the TLS handshake, check it against the host specified
  in the HTTP request and send a 421 in case they mismatch.

- Throw a 403 if client authentication was enabled but no client certificate
  was specified.
2019-11-19 11:09:24 +01:00
Joris Vink c78535aa5d 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:43:48 +01:00
Joris Vink 8311c036d9 Add seccomp_tracing configuration option for linux.
If set to "yes" then Kore will trace its child processes and properly
notify you of seccomp violations while still allowing the syscalls.

This can be very useful when running Kore on new platforms that have
not been properly tested with seccomp, allowing me to adjust the default
policies as we move further.
2019-10-31 12:52:10 +01:00
Joris Vink d001b022a7 Cleanup ifdef mess for different OpenSSL based libs.
Now everything that has the "newer" OpenSSL API (1.1.x) is hidden
behind a KORE_OPENSSL_NEWER_API define. Tone down minimum libressl
version again to 2.7.5.
2019-10-28 12:33:39 +01:00
Joris Vink 5f03f991c9 Change kore_json_find() to operate on a kore_json_item.
This way you can call the lookup function on any JSON value that you
previously obtained (or the JSON context root).
2019-10-25 12:27:16 +02:00
Joris Vink 890eb78fd8 Improve our new JSON api a bit.
Allow JSON to be constructed via kore_json_create_item and its
handy macro family:
	- kore_json_create_object()
	- kore_json_create_array()
	- kore_json_create_string()
	- kore_json_create_number()
	- kore_json_create_literal().

Adds kore_json_item_tobuf() to convert a JSON item into a string
representation in a kore_buf data structure.

Renames the kore_json_get* family to kore_json_find* instead.

Allows for quite clean code:

	struct kore_buf		buf;
	struct kore_json_item	*root;

	root = kore_json_create_object(NULL, NULL);
	kore_json_create_string(root, "hello", "world");
	kore_json_create_number(root, "value", 2.241);

	kore_buf_init(&buf, 128);
	kore_json_item_tobuf(root, &buf);

	kore_json_item_free(root);
	kore_buf_cleanup(&buf);
2019-10-22 23:56:47 +02:00
Joris Vink 06fa452c96 Add a full native JSON parser to Kore.
Mostly compliant, ignores \uXXXX in strings for now.

New API functions:

void kore_json_init(struct kore_json *json, const u_int8_t *data, size_t len);
  - Prepares JSON data for parsing.

int kore_json_parse(struct kore_json *json)
  - Parses the JSON data prepared via kore_json_init. Returns KORE_RESULT_ERROR
    if parsing failed or KORE_RESULT_OK if it succeeded.

struct kore_json_item *kore_json_get(struct kore_json *json, const char *path,
                                     int type);
  - Try to find the object matching a given search patch and type.

  eg, given a JSON structure of:
    {
      "reasons": {
        "strings": [
          "first reason",
          "second"
        ]
      }
    }

  one can obtain the second element in the reasons.strings array via:

    item = kore_json_get(json, "reasons/strings[0]", KORE_JSON_TYPE_STRING);

  Returns NULL if the item was not found or a type mismatch was hit,
  otherwise will return the item of that type.

  The kore_json_item data structure has a data member that contains the
  relevant bits depending on the type:

    KORE_JSON_TYPE_ARRAY, KORE_JSON_TYPE_OBJECT:
      the data.items member is valid.

    KORE_JSON_TYPE_STRING:
      the data.string member is valid.

    KORE_JSON_TYPE_NUMBER:
      the data.number member is valid.

    KORE_JSON_TYPE_LITERAL:
      the data.literal member is valid.

void kore_json_cleanup(struct kore_json *json);
  - Cleanup any resources

const char *kore_json_strerror(struct kore_json *json);
  - Return pointer to human readable error string.
2019-10-20 23:22:11 +02:00
Joris Vink cdc3347120 Add kore.sendmsg(object, worker=None) to the python api.
This allows you to send Python objects that can be run through pickle
to other worker processes.

If your application implements koreapp.onmsg() you will be able to receive
these objects.
2019-10-16 12:05:27 +02:00
Joris Vink 0eb11794f5 Do not add keymgr its msg fd if not started.
Reshuffles the keymgr_active flag to keymgr.c and let it be figured out
from inside kore_server_start() instead of the worker init code.
2019-10-07 10:31:35 +02:00
Joris Vink 46375303cb Allow multiple binds on new server directive. 2019-09-27 20:00:35 +02:00
Joris Vink 7350131232 Allow listening of tls/notls ports at the same time.
Before kore needed to be built with NOTLS=1 to be able to do non TLS
connections. This has been like this for years.

It is time to allow non TLS listeners without having to rebuild Kore.

This commit changes your configuration format and will break existing
applications their config.

Configurations now get listener {} contexts:

listen default {
	bind 127.0.0.1 8888
}

The above will create a listener on 127.0.0.1, port 8888 that will serve
TLS (still the default).

If you want to turn off TLS on that listener, specify "tls no" in that
context.

Domains now need to be attached to a listener:

Eg:
	domain * {
		attach	default
	}

For the Python API this kills kore.bind(), and kore.bind_unix(). They are
replaced with:

	kore.listen("name", ip=None, port=None, path=None, tls=True).
2019-09-27 12:27:04 +02:00
Joris Vink 0d72f11902 make sure we can still run normal apps even with PYTHON=1 2019-09-26 20:38:02 +02:00
Joris Vink 937c39f041 Many many Python improvements.
- Kore can now fully be configured via Python code if one wants nothing to
  do with configuration files.

- Kore can now start single python files and no longer requires them to be
  inside a module directory.

- Pass all regex capture groups to the handler methods, allowing you to
  get access to them immediately.

- Change python websocket_handshake to take callable objects directly.

- Added a new deployment configuration option. If set to "dev" or
  "development" Kore will automatically foreground, no chroot / etc.
  If set to "production" Kore *will* chroot, drop privs, etc.

- Many more..

These are all backported from a project that I was working on a while
ago. I decided these should go back into mainline Kore.
2019-09-26 15:49:00 +02:00
Joris Vink cd9971247c Add seccomp syscall filtering to kore.
With this commit all Kore processes (minus the parent) are running
under seccomp.

The worker processes get the bare minimum allowed syscalls while each module
like curl, pgsql, etc will add their own filters to allow what they require.

New API functions:
    int kore_seccomp_filter(const char *name, void *filter, size_t len);

    Adds a filter into the seccomp system (must be called before
    seccomp is enabled).

New helpful macro:
    define KORE_SYSCALL_ALLOW(name)

    Allow the syscall with a given name, should be used in
    a sock_filter data structure.

New hooks:
    void kore_seccomp_hook(void);

    Called before seccomp is enabled, allows developers to add their
    own BPF filters into seccomp.
2019-09-25 14:31:20 +02:00
Joris Vink 6c18856a3e get rid of mtime in modules.
kore should always reload things when it was told to reload things.
there are use cases were a module reload is because the code itself changed.
2019-06-09 23:24:53 +02:00
Joris Vink 3c9a141cd0 allow an iterator to be passed to req.response().
if an iterator is passed kore will send the response with
transfer-encoding: chunked and call the iterator for every
chunk that was sent.

The iterator must return a utf-8 string.

Works wonderful with TemplateStream from jinja2.
2019-05-03 13:42:34 +02:00
Joris Vink 2c88bc6120 Add asynchronous libcurl support.
This commit adds the CURL=1 build option. When enabled allows
you to schedule CURL easy handles onto the Kore event loop.

It also adds an easy to use HTTP client API that abstracts away the
settings required from libcurl to make HTTP requests.

Tied together with HTTP request state machines this means you can
write fully asynchronous HTTP client requests in an easy way.

Additionally this exposes that API to the Python code as well
allowing you do to things like:

	client = kore.httpclient("https://kore.io")
	status, body = await client.get()

Introduces 2 configuration options:
	- curl_recv_max
		Max incoming bytes for a response.

	- curl_timeout
		Timeout in seconds before a transfer is cancelled.

This API also allows you to take the CURL easy handle and send emails
with it, run FTP, etc. All asynchronously.
2019-04-24 00:15:17 +02:00
Joris Vink aa49e181b6 Add http_[header|body]_timeout.
If the HTTP request headers or the HTTP body have not arrived before
these timeouts expire, Kore will send a 408 back to the client.
2019-04-11 20:51:49 +02:00
Joris Vink d2aa64df5c add kore_proctitle().
manipulates the argv+environ pointers to get a sensible process title
under linux / darwin.
2019-03-29 16:24:14 +01:00
Joris Vink 4238431b9e Add worker_death_policy setting.
By default kore will restart worker processes if they terminate
unexpected. However in certain scenarios you may want to bring down
an entire kore instance if a worker process fails.

By setting worker_death_policy to "terminate" the Kore server will
completely stop if a worker exits unexpected.
2019-03-22 09:49:50 +01:00
Joris Vink 370041656e Get rid of WORKER_LOCK_TIMEOUT.
Instead let the workers send a message on the msg channel to each
other when they have given up the accept lock and it is now available
to be grabbed.
2019-03-21 14:03:11 +01:00
Joris Vink 8b0279879a rework timers so they fire more predictably.
this change also stops python coroutines from waking up very
late after their timeout has expired.

in filerefs, don't prime the timer until we actually have something
to expire, and kill the timer when the last ref drops.
2019-03-21 10:17:08 +01:00
Joris Vink 31b6365da3 include sys/types.h explictly. 2019-03-14 19:20:46 +01:00
Joris Vink bf1e8e5ffb bump copyright to 2019 2019-02-22 16:57:28 +01:00
Joris Vink d6b05bcff7 always force reload cert so we get a new x509 store.
Otherwise older OpenSSL or current LibreSSL will fail to add the new
CRL as they still match on subject name rather then hash of the CRL data.
2019-01-14 20:57:40 +01:00
Joris Vink 73cdbd1a01 Let CRLs be reloadable via keymgr.
With these changes CRLs can be reloaded like certificates
by sending a SIGUSR1 to the parent process.

Track mtime on both certificate files and CRL files as well
and only submit them to the workers if this has changed.
2019-01-14 11:41:50 +01:00
Joris Vink c070e77ea5 include signal.h from kore.h 2019-01-11 11:32:33 +01:00
Joris Vink 7aa17df4a1 make ACCESSLOG_* unsigned 2018-12-22 10:52:57 +01:00
Joris Vink 4d184e00de correct define number 2018-12-22 10:22:59 +01:00
Joris Vink 9aa0e95643 Rework accesslog handling.
Move away from the parent constantly hitting the disk for every
accesslog the workers are sending.

The workers will now write their own accesslogs to shared
memory before the parent will pick those up. The parent
will flush them to disk once every second or if they grow
larger then 1MB.

This removes the heavy penalty for having access logs
turned on when you are dealing with a large volume
of requests.
2018-12-22 09:25:00 +01:00
Joris Vink 272d659f1c we use certain things from sys/param.h 2018-11-29 10:31:14 +01:00
Joris Vink baafa4897e Add -q flag.
If specified Kore will run quietly and only log important messages.
2018-11-15 16:01:37 +01:00
Joris Vink 71c145932c grow kore_pools at a slower rate.
Before we just doubled in size the second we exhausted a pool instead
of doing a more controlled expansion.

Now we will expand at 25% of the initial elm count whenever we need to.

Will help with memory pressure in certain scenarios.
2018-10-30 10:36:18 +01:00
Joris Vink 339df66fd5 Add support for TLS 1.3 via OpenSSL 1.1.1.
This commit removes TLS 1.0 support no matter what OpenSSL
you are linking against.

Changes the value of tls_version from 1.2 to both. Meaning if
you link with OpenSSL 1.1.1 you will get 1.2 + 1.3.
2018-10-29 20:38:58 +01:00