kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 8b47863cd45cf4685b74f5390a800c1e28b721b9
parent b75ac15e5063b49878567f602d1fbe7da57fc4d1
Author: Joris Vink <joris@coders.se>
Date:   Tue, 15 Oct 2013 10:44:56 +0200

Add http_hsts_enable (enabled by default with max-age=31536000) to Kore's configuration file.

If enabled Kore adds the HSTS header to every response.

- Additionally, fix some typos in the example configuration.
- Change default SSL cipher list again, no more RC4 and almost PFS for all browsers.

Diffstat:
includes/http.h | 2++
includes/kore.h | 2+-
modules/example/module.conf | 14++++++++++----
src/config.c | 24++++++++++++++++++++++++
src/http.c | 15+++++++++++++++
5 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/includes/http.h b/includes/http.h @@ -17,6 +17,7 @@ #ifndef __H_HTTP_H #define __H_HTTP_H +#define HTTP_HSTS_ENABLE 31536000 #define HTTP_HEADER_MAX_LEN 4096 #define HTTP_POSTBODY_MAX_LEN 10240000 #define HTTP_URI_LEN 2000 @@ -80,6 +81,7 @@ struct http_request { extern int http_request_count; extern u_int16_t http_header_max; extern u_int64_t http_postbody_max; +extern u_int64_t http_hsts_enable; void http_init(void); void http_process(void); diff --git a/includes/kore.h b/includes/kore.h @@ -46,7 +46,7 @@ #define KORE_DOMAINNAME_LEN 254 #define KORE_PIDFILE_DEFAULT "/var/run/kore.pid" -#define KORE_DEFAULT_CIPHER_LIST "EECDH+AES:EDH+AES:-SHA1:EECDH+RC4:EDH+RC4:RC4-SHA:EECDH+AES256:EDH+AES256:AES256-SHA:!aNULL:!eNULL:!EXP:!LOW:!MD5" +#define KORE_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK" #if defined(KORE_DEBUG) #define kore_debug(fmt, ...) \ diff --git a/modules/example/module.conf b/modules/example/module.conf @@ -4,7 +4,7 @@ bind 127.0.0.1 443 bind ::1 443 -# The path worker processes will chroot too after starting. +# The path worker processes will chroot into after starting. chroot /home/joris/src/kore # Worker processes will run as the specified user. @@ -25,7 +25,7 @@ workers 4 #onload myinit # You can define a callback Kore calls from its parent process or -# workers everytime # the kore_cb_interval timer (in milliseconds) is reached. +# workers everytime the kore_cb_interval timer (in milliseconds) is reached. # # NOTE: Remember that the parent process runs as root and is not chroot(). # NOTE: If you want the cb to run on a worker, be sure to set kore_cb_worker. @@ -36,21 +36,25 @@ workers 4 # HTTP specific settings. # http_header_max Maximum size of HTTP headers (in bytes). # http_postbody_max Maximum size of an HTTP POST body (in bytes). +# http_hsts_enable Send Strict Transport Security header in +# all responses. Parameter is the age. +# Set age to 0 to disable sending this header. #http_header_max 4096 #http_postbody_max 10240000 +#http_hsts_enable 31536000 # Specifies what module to be loaded. load modules/example/example.module # Specify the SSL ciphers that will be used. -#ssl_cipher EECDH+AES:EDH+AES:-SHA1:EECDH+RC4:EDH+RC4:RC4-SHA:EECDH+AES256:EDH+AES256:AES256-SHA:!aNULL:!eNULL:!EXP:!LOW:!MD5 +#ssl_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK # If you wish to use EDH / ECDH specify a file containing # a generated DH key (See OpenSSL dhparam). #ssl_dhparam dh2048.pem # Set this if you want to disable SSL zlib compression. -#ssl_no_compression +ssl_no_compression # Specify the amount of seconds a SPDY connection is kept open. # You can keep it open indefinately by setting this to 0. @@ -78,6 +82,8 @@ domain localhost { certfile cert/server.crt certkey cert/server.key accesslog /var/log/kore_access.log + + # Page handlers static /css/style.css serve_style_css static / serve_index static /intro.jpg serve_intro diff --git a/src/config.c b/src/config.c @@ -44,6 +44,7 @@ static int configure_kore_cb_interval(char **); static int configure_kore_cb_worker(char **); static int configure_http_header_max(char **); static int configure_http_postbody_max(char **); +static int configure_http_hsts_enable(char **); static void domain_sslstart(void); static struct { @@ -73,6 +74,7 @@ static struct { { "kore_cb_interval", configure_kore_cb_interval }, { "http_header_max", configure_http_header_max }, { "http_postbody_max", configure_http_postbody_max }, + { "http_hsts_enable", configure_http_hsts_enable }, { NULL, NULL }, }; @@ -551,6 +553,28 @@ configure_http_postbody_max(char **argv) return (KORE_RESULT_OK); } +static int +configure_http_hsts_enable(char **argv) +{ + int err; + + if (argv[1] == NULL) + return (KORE_RESULT_ERROR); + + if (http_hsts_enable != HTTP_HSTS_ENABLE) { + kore_debug("http_hsts_enable already set"); + return (KORE_RESULT_ERROR); + } + + http_hsts_enable = kore_strtonum(argv[1], 10, 1, ULONG_MAX, &err); + if (err != KORE_RESULT_OK) { + printf("bad http_hsts_enable value: %s\n", argv[1]); + return (KORE_RESULT_ERROR); + } + + return (KORE_RESULT_OK); +} + static void domain_sslstart(void) { diff --git a/src/http.c b/src/http.c @@ -31,6 +31,7 @@ static struct kore_pool http_request_pool; static struct kore_pool http_header_pool; int http_request_count; +u_int64_t http_hsts_enable = HTTP_HSTS_ENABLE; u_int16_t http_header_max = HTTP_HEADER_MAX_LEN; u_int64_t http_postbody_max = HTTP_POSTBODY_MAX_LEN; @@ -258,6 +259,14 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len) spdy_header_block_add(hblock, ":status", sbuf); spdy_header_block_add(hblock, ":version", "HTTP/1.1"); spdy_header_block_add(hblock, ":server", KORE_NAME_STRING); + + if (http_hsts_enable) { + snprintf(sbuf, sizeof(sbuf), + "max-age=%lu", http_hsts_enable); + spdy_header_block_add(hblock, + ":strict-transport-security", sbuf); + } + TAILQ_FOREACH(hdr, &(req->resp_headers), list) spdy_header_block_add(hblock, hdr->header, hdr->value); @@ -293,6 +302,12 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len) kore_buf_appendf(buf, "Keep-Alive: timeout=20\r\n"); kore_buf_appendf(buf, "Server: %s\r\n", KORE_NAME_STRING); + if (http_hsts_enable) { + kore_buf_appendf(buf, + "Strict-Transport-Security: max-age=%lu\r\n", + http_hsts_enable); + } + TAILQ_FOREACH(hdr, &(req->resp_headers), list) { kore_buf_appendf(buf, "%s: %s\r\n", hdr->header, hdr->value);