diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2023-10-24 09:59:08 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2023-10-24 09:59:08 +0000 |
commit | 37d2f8cb438f68eaa1da8a56ea9ce5023091f128 (patch) | |
tree | 81672ad4254ea18e7d240230ba47ef6743d491ad | |
parent | 907f1c64369095b5b2d5f6fb23a8b937720d94cc (diff) | |
download | tipidee-37d2f8cb438f68eaa1da8a56ea9ce5023091f128.tar.gz tipidee-37d2f8cb438f68eaa1da8a56ea9ce5023091f128.tar.xz tipidee-37d2f8cb438f68eaa1da8a56ea9ce5023091f128.zip |
Full custom header support, switch not made yet
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r-- | doc/tipidee.conf.html | 25 | ||||
-rw-r--r-- | package/deps.mak | 8 | ||||
-rw-r--r-- | src/config/headers.c | 30 | ||||
-rw-r--r-- | src/config/lexparse.c | 27 | ||||
-rw-r--r-- | src/config/tipidee-config-internal.h | 4 | ||||
-rw-r--r-- | src/include/tipidee/conf.h | 4 | ||||
-rw-r--r-- | src/include/tipidee/response.h | 10 | ||||
-rw-r--r-- | src/libtipidee/deps-lib/tipidee | 2 | ||||
-rw-r--r-- | src/libtipidee/tipidee_conf_get_argv.c | 7 | ||||
-rw-r--r-- | src/libtipidee/tipidee_conf_get_responseheaders.c | 22 | ||||
-rw-r--r-- | src/libtipidee/tipidee_response_header_preparebuiltin.c | 28 | ||||
-rw-r--r-- | src/tipideed/tipideed-internal.h | 2 | ||||
-rw-r--r-- | src/tipideed/tipideed.c | 60 |
13 files changed, 187 insertions, 42 deletions
diff --git a/doc/tipidee.conf.html b/doc/tipidee.conf.html index 04ac254..6242b19 100644 --- a/doc/tipidee.conf.html +++ b/doc/tipidee.conf.html @@ -430,6 +430,31 @@ list</a> of default Content-Type mappings; this directive should only be necessa serving files with uncommon extensions or have specific needs. </li> </ul> +<div id="custom-header"> +<h3> The <tt>custom-header</tt> directive </h3> +</div> + +<p> + <tt>custom-header</tt> is also a global directive, but is introduced by the +keyword <tt>custom-header</tt>, without prepending <tt>global</tt>. It allows +the user to define custom headers that are to be added to every response. +</p> + +<p> + <code> custom-header <em>option</em> <em>key</em> <em>value</em> </code> +</p> + +<ul> + <li> <em>option</em> is <tt>weak</tt> or <tt>strong</tt>, and determines what happens when a CGI script +provides a header with the same name. If <tt>weak</tt>, the CGI value has precedence; if <tt>strong</tt>, +<em>value</em> has precedence. </li> + <li> <em>key</em> is the name of the custom header, such as <tt>Content-Security-Policy</tt> or <tt>X-Tacky-Header</tt>. +It is case-insensitive; its spelling be canonicalized when processed. </li> + <li> <em>value</em> is the content of the header. Any whitespace given in <em>value</em> will all register as a single space. </li> + <li> Some headers cannot be customized. <a href="tipidee-config.html">tipidee-config</a> +will reject an attempt to define a <tt>Connection</tt> or a <tt>Date</tt> header, for instance. </li> +</ul> + <div id="local"> <h3> Local directives </h3> </div> diff --git a/package/deps.mak b/package/deps.mak index 7ab6c22..81bbddd 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -23,6 +23,7 @@ src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_argv.lo: src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_content_type.lo: src/libtipidee/tipidee_conf_get_content_type.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_errorfile.o src/libtipidee/tipidee_conf_get_errorfile.lo: src/libtipidee/tipidee_conf_get_errorfile.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_redirection.lo: src/libtipidee/tipidee_conf_get_redirection.c src/include/tipidee/conf.h +src/libtipidee/tipidee_conf_get_responseheaders.o src/libtipidee/tipidee_conf_get_responseheaders.lo: src/libtipidee/tipidee_conf_get_responseheaders.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_string.o src/libtipidee/tipidee_conf_get_string.lo: src/libtipidee/tipidee_conf_get_string.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_uint32.o src/libtipidee/tipidee_conf_get_uint32.lo: src/libtipidee/tipidee_conf_get_uint32.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_init.o src/libtipidee/tipidee_conf_init.lo: src/libtipidee/tipidee_conf_init.c src/include/tipidee/conf.h @@ -43,6 +44,7 @@ src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_respo src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date.lo: src/libtipidee/tipidee_response_header_date.c src/include/tipidee/response.h src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_date_fmt.lo: src/libtipidee/tipidee_response_header_date_fmt.c src/include/tipidee/response.h src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_header_lastmodified.lo: src/libtipidee/tipidee_response_header_lastmodified.c src/include/tipidee/response.h +src/libtipidee/tipidee_response_header_preparebuiltin.o src/libtipidee/tipidee_response_header_preparebuiltin.lo: src/libtipidee/tipidee_response_header_preparebuiltin.c src/include/tipidee/response.h src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_response_status.lo: src/libtipidee/tipidee_response_status.c src/include/tipidee/response.h src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_rql_read.lo: src/libtipidee/tipidee_rql_read.c src/include/tipidee/method.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/libtipidee/tipidee_uri_parse.o src/libtipidee/tipidee_uri_parse.lo: src/libtipidee/tipidee_uri_parse.c src/include/tipidee/uri.h @@ -63,12 +65,12 @@ tipidee-config: src/config/tipidee-config.o src/config/util.o src/config/node.o tipidee-config-preprocess: EXTRA_LIBS := -lskarnet tipidee-config-preprocess: src/config/tipidee-config-preprocess.o ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) -libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.o src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_errorfile.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_string.o src/libtipidee/tipidee_conf_get_uint32.o src/libtipidee/tipidee_conf_init.o src/libtipidee/tipidee_headers_get_content_length.o src/libtipidee/tipidee_headers_init.o src/libtipidee/tipidee_headers_parse.o src/libtipidee/tipidee_headers_search.o src/libtipidee/tipidee_log_answer.o src/libtipidee/tipidee_log_exit.o src/libtipidee/tipidee_log_resource.o src/libtipidee/tipidee_log_request.o src/libtipidee/tipidee_log_start.o src/libtipidee/tipidee_method.o src/libtipidee/tipidee_response_error_nofile.o src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_header_builtin.o src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_uri_parse.o src/libtipidee/tipidee_util_chunked_read.o src/libtipidee/tipidee_util_defaulttext.o src/libtipidee/tipidee_util_httpdate.o +libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.o src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_errorfile.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_responseheaders.o src/libtipidee/tipidee_conf_get_string.o src/libtipidee/tipidee_conf_get_uint32.o src/libtipidee/tipidee_conf_init.o src/libtipidee/tipidee_headers_get_content_length.o src/libtipidee/tipidee_headers_init.o src/libtipidee/tipidee_headers_parse.o src/libtipidee/tipidee_headers_search.o src/libtipidee/tipidee_log_answer.o src/libtipidee/tipidee_log_exit.o src/libtipidee/tipidee_log_resource.o src/libtipidee/tipidee_log_request.o src/libtipidee/tipidee_log_start.o src/libtipidee/tipidee_method.o src/libtipidee/tipidee_response_error_nofile.o src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_header_builtin.o src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_header_preparebuiltin.o src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_uri_parse.o src/libtipidee/tipidee_util_chunked_read.o src/libtipidee/tipidee_util_defaulttext.o src/libtipidee/tipidee_util_httpdate.o else -libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo +libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_responseheaders.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo endif libtipidee.so.xyzzy: EXTRA_LIBS := -lskarnet -libtipidee.so.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo +libtipidee.so.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_responseheaders.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo tipideed: EXTRA_LIBS := -lskarnet tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/harden.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/responses.o src/tipideed/send_file.o src/tipideed/tipideed.o src/tipideed/trace.o libtipidee.a.xyzzy INTERNAL_LIBS := diff --git a/src/config/headers.c b/src/config/headers.c index b080390..351b938 100644 --- a/src/config/headers.c +++ b/src/config/headers.c @@ -1,8 +1,10 @@ /* ISC license. */ +#include <stdint.h> #include <string.h> #include <ctype.h> +#include <skalibs/uint32.h> #include <skalibs/strerr.h> #include <skalibs/genalloc.h> #include <skalibs/avltree.h> @@ -47,7 +49,7 @@ int header_allowed (char const *key) return !p || p->overridable ; } -void header_canonize (char *key) +void header_canonicalize (char *key) { int h = 1 ; size_t len = strlen(key) ; @@ -63,17 +65,25 @@ node const *headers_search (char const *key) return repo_search(&headers, key) ; } -void headers_add (char const *key, char const *value, uint8_t options, size_t filepos, uint32_t line) +void headers_addv (char const *key, uint8_t options, char const *s, size_t const *word, size_t n, size_t filepos, uint32_t line) { node node ; + if (!n) return ; node_start(&headers_storage, &node, key, filepos, line) ; node_add(&headers_storage, &node, options & 1 ? "\1" : "", 1) ; - node_add(&headers_storage, &node, value, strlen(value) + 1) ; + node_add(&headers_storage, &node, s + word[0], strlen(s + word[0])) ; + for (size_t i = 1 ; i < n ; i++) + { + node_add(&headers_storage, &node, " ", 1) ; + node_add(&headers_storage, &node, s + word[i], strlen(s + word[i])) ; + } + node_add(&headers_storage, &node, "", 1) ; repo_add(&headers, &node) ; } -static void headers_defaults (node *node) +static uint32_t headers_defaults (node *node) { + uint32_t n = 0 ; for (size_t i = 0 ; i < sizeof(builtinheaders) / sizeof(struct builtinheaders_s) ; i++) { struct builtinheaders_s const *p = builtinheaders + i ; @@ -82,7 +92,9 @@ static void headers_defaults (node *node) confnode_add(node, p->key, strlen(p->key) + 1) ; confnode_add(node, p->overridable ? "\1" : "", 1) ; confnode_add(node, p->value, strlen(p->value) + 1) ; + n++ ; } + return n ; } static int header_write (uint32_t d, unsigned int h, void *data) @@ -91,16 +103,20 @@ static int header_write (uint32_t d, unsigned int h, void *data) node *const header = genalloc_s(node, &headers.ga) + d ; (void)h ; confnode_add(confnode, headers_storage.s + header->key, header->keylen + 1) ; - confnode_add(confnode, headers_storage.s + header->data, header->datalen + 1) ; + confnode_add(confnode, headers_storage.s + header->data, header->datalen) ; return 1 ; } void headers_finish (void) { + uint32_t n ; + char pack[4] ; node node ; - confnode_start(&node, "G:response-headers", 0, 0) ; - headers_defaults(&node) ; + confnode_start(&node, "G:response_headers", 0, 0) ; + n = avltree_len(&headers.tree) + headers_defaults(&node) ; (void)avltree_iter(&headers.tree, &header_write, &node) ; + uint32_pack_big(pack, n) ; + confnode_add(&node, pack, 4) ; conftree_add(&node) ; avltree_free(&headers.tree) ; genalloc_free(node, &headers.ga) ; diff --git a/src/config/lexparse.c b/src/config/lexparse.c index 27a62df..783e39f 100644 --- a/src/config/lexparse.c +++ b/src/config/lexparse.c @@ -45,6 +45,7 @@ enum token_e T_GLOBAL, T_LOG, T_CONTENTTYPE, + T_CUSTOMHEADER, T_DOMAIN, T_NPHPREFIX, T_REDIRECT, @@ -195,6 +196,27 @@ static inline void parse_contenttype (char const *s, size_t const *word, size_t } } +static inline void parse_customheader (char const *s, size_t const *word, size_t n, mdt const *md) +{ + uint8_t options = 0 ; + if (n < 3) + strerr_dief8x(1, "too ", "few", " arguments to directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (!strcmp(s + word[0], "weak")) options |= 1 ; + else if (!strcmp(s + word[0], "strong")) options &= ~1 ; + else strerr_dief7x(1, "type should be weak or strong for", " directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + word++ ; n-- ; + { + size_t len = strlen(s + *word) ; + char key[len + 1] ; + memcpy(key, s + *word++, len + 1) ; n-- ; + header_canonicalize(key) ; + if (!header_allowed(key)) + strerr_dief7x(1, "header ", key, " cannot be customized", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + headers_checkunique(key, md) ; + headers_addv(key, options, s, word, n, md->filepos, md->line) ; + } +} + static inline void parse_redirect (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md) { static uint32_t const codes[4] = { 307, 308, 302, 301 } ; @@ -360,6 +382,7 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st { .s = "basic-auth", .token = T_BASICAUTH }, { .s = "cgi", .token = T_CGI }, { .s = "content-type", .token = T_CONTENTTYPE }, + { .s = "custom-header", .token = T_CUSTOMHEADER }, { .s = "custom-response", .token = T_CUSTOMRESPONSE }, { .s = "domain", .token = T_DOMAIN }, { .s = "file-type", .token = T_FILETYPE }, @@ -404,6 +427,9 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st case T_CONTENTTYPE : parse_contenttype(s, word, n, md) ; break ; + case T_CUSTOMHEADER : + parse_customheader(s, word, n, md) ; + break ; case T_DOMAIN : if (n != 1) strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", "domain", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; @@ -518,4 +544,5 @@ void conf_lexparse (buffer *b, char const *ifile) stralloc_free(&domain) ; genalloc_free(size_t, &words) ; stralloc_free(&sa) ; + headers_finish() ; } diff --git a/src/config/tipidee-config-internal.h b/src/config/tipidee-config-internal.h index 3508771..d3977c0 100644 --- a/src/config/tipidee-config-internal.h +++ b/src/config/tipidee-config-internal.h @@ -81,11 +81,11 @@ extern int conftree_write (cdbmaker *) ; /* headers */ -extern void header_canonize (char *) ; +extern void header_canonicalize (char *) ; extern int header_allowed (char const *) ; extern node const *headers_search (char const *) ; -extern void headers_add (char const *, char const *, uint8_t, size_t, uint32_t) ; +extern void headers_addv (char const *, uint8_t, char const *, size_t const *, size_t, size_t, uint32_t) ; extern void headers_finish (void) ; diff --git a/src/include/tipidee/conf.h b/src/include/tipidee/conf.h index d0b8fb0..5f3b697 100644 --- a/src/include/tipidee/conf.h +++ b/src/include/tipidee/conf.h @@ -35,7 +35,9 @@ extern int tipidee_conf_init (tipidee_conf *, char const *) ; extern int tipidee_conf_get (tipidee_conf const *, char const *, cdb_data *) ; extern char const *tipidee_conf_get_string (tipidee_conf const *, char const *) ; extern int tipidee_conf_get_uint32 (tipidee_conf const *, char const *, uint32_t *) ; -extern unsigned int tipidee_conf_get_argv (tipidee_conf const *, char const *, char const **, unsigned int, size_t *) ; +extern uint32_t tipidee_conf_get_argv (tipidee_conf const *, char const *, char const **, uint32_t, size_t *) ; + +extern char const *tipidee_conf_get_responseheaders (tipidee_conf const *, char const *, uint32_t *, uint32_t *) ; extern char const *tipidee_conf_get_docroot (tipidee_conf const *, tipidee_uri const *, uint16_t) ; extern int tipidee_conf_get_redirection (tipidee_conf const *, char const *, size_t, char const *, tipidee_redirection *) ; diff --git a/src/include/tipidee/response.h b/src/include/tipidee/response.h index 3850970..bc83fc6 100644 --- a/src/include/tipidee/response.h +++ b/src/include/tipidee/response.h @@ -16,6 +16,14 @@ #include <tipidee/rql.h> +typedef struct tipidee_response_header_s tipidee_response_header, *tipidee_response_header_ref ; +struct tipidee_response_header_s +{ + char const *key ; + char const *value ; + uint8_t options ; +} ; + typedef struct tipidee_response_header_builtin_s tipidee_response_header_builtin, *tipidee_response_header_builtin_ref ; struct tipidee_response_header_builtin_s { @@ -42,4 +50,6 @@ extern size_t tipidee_response_error_nofile (buffer *, tipidee_rql const *, unsi extern tipidee_response_header_builtin const *tipidee_response_header_builtin_table ; extern char const *tipidee_response_header_builtin_search (char const *) ; +extern int tipidee_response_header_preparebuiltin (tipidee_response_header *, uint32_t, char const *, size_t) ; + #endif diff --git a/src/libtipidee/deps-lib/tipidee b/src/libtipidee/deps-lib/tipidee index 93e261a..d406e5c 100644 --- a/src/libtipidee/deps-lib/tipidee +++ b/src/libtipidee/deps-lib/tipidee @@ -4,6 +4,7 @@ tipidee_conf_get_argv.o tipidee_conf_get_content_type.o tipidee_conf_get_errorfile.o tipidee_conf_get_redirection.o +tipidee_conf_get_responseheaders.o tipidee_conf_get_string.o tipidee_conf_get_uint32.o tipidee_conf_init.o @@ -24,6 +25,7 @@ tipidee_response_header_common_put.o tipidee_response_header_date.o tipidee_response_header_date_fmt.o tipidee_response_header_lastmodified.o +tipidee_response_header_preparebuiltin.o tipidee_response_status.o tipidee_rql_read.o tipidee_uri_parse.o diff --git a/src/libtipidee/tipidee_conf_get_argv.c b/src/libtipidee/tipidee_conf_get_argv.c index 0dd016e..79c24e6 100644 --- a/src/libtipidee/tipidee_conf_get_argv.c +++ b/src/libtipidee/tipidee_conf_get_argv.c @@ -1,6 +1,7 @@ /* ISC license. */ #include <errno.h> +#include <stdint.h> #include <string.h> #include <skalibs/cdb.h> @@ -9,11 +10,11 @@ #include <skalibs/posixishard.h> -unsigned int tipidee_conf_get_argv (tipidee_conf const *conf, char const *key, char const **argv, unsigned int max, size_t *maxlen) +uint32_t tipidee_conf_get_argv (tipidee_conf const *conf, char const *key, char const **argv, uint32_t max, size_t *maxlen) { cdb_data data ; - size_t curlen = 0 ; - unsigned int n = 0, pos = 0 ; + size_t curlen = 0, pos = 0 ; + uint32_t n = 0 ; if (!tipidee_conf_get(conf, key, &data)) return 0 ; if (data.s[data.len-1]) return (errno = EPROTO, 0) ; while (pos < data.len) diff --git a/src/libtipidee/tipidee_conf_get_responseheaders.c b/src/libtipidee/tipidee_conf_get_responseheaders.c new file mode 100644 index 0000000..ee8c786 --- /dev/null +++ b/src/libtipidee/tipidee_conf_get_responseheaders.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include <stddef.h> +#include <errno.h> +#include <string.h> + +#include <skalibs/uint32.h> +#include <skalibs/cdb.h> + +#include <tipidee/conf.h> + +#include <skalibs/posixishard.h> + +char const *tipidee_conf_get_responseheaders (tipidee_conf const *conf, char const *key, uint32_t *len, uint32_t *n) +{ + cdb_data data ; + if (!tipidee_conf_get(conf, key, &data)) return NULL ; + if (data.len < 4) return (errno = EPROTO, NULL) ; + uint32_unpack_big(data.s + data.len - 4, n) ; + *len = data.len - 4 ; + return data.s ; +} diff --git a/src/libtipidee/tipidee_response_header_preparebuiltin.c b/src/libtipidee/tipidee_response_header_preparebuiltin.c new file mode 100644 index 0000000..a04b666 --- /dev/null +++ b/src/libtipidee/tipidee_response_header_preparebuiltin.c @@ -0,0 +1,28 @@ +/* ISC license. */ + +#include <stdint.h> +#include <string.h> + +#include <tipidee/response.h> + +int tipidee_response_header_preparebuiltin (tipidee_response_header *tab, uint32_t n, char const *s, size_t len) +{ + size_t pos = 0 ; + for (uint32_t i = 0 ; i < n ; i++) + { + char const *next ; + tab[i].key = s + pos ; + next = memchr(s + pos, 0, len - pos) ; + if (!next) return 0 ; + pos = next - s ; + if (pos++ >= len) return 0 ; + tab[i].options = (uint8_t)s[pos] ; + if (pos++ >= len) return 0 ; + tab[i].value = s + pos ; + next = memchr(s + pos, 0, len - pos) ; + if (!next) return 0 ; + pos = next - s ; + if (pos++ >= len) return 0 ; + } + return pos == len ; +} diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h index a4f6d95..3629f84 100644 --- a/src/tipideed/tipideed-internal.h +++ b/src/tipideed/tipideed-internal.h @@ -30,6 +30,7 @@ struct global_s tain cgitto ; char const *defaulthost ; char const *indexnames[16] ; + tipidee_response_header const *rhdr ; int p[2] ; uint32_t logv ; uint32_t maxrqbody ; @@ -51,6 +52,7 @@ struct global_s .cgitto = TAIN_ZERO, \ .defaulthost = "@", \ .indexnames = { 0 }, \ + .rhdr = 0, \ .p = { -1, -1 }, \ .logv = TIPIDEE_LOG_DEFAULT, \ .maxrqbody = 0, \ diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index b499b2a..f4d18a6 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -350,6 +350,9 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti int main (int argc, char const *const *argv, char const *const *envp) { stralloc bodysa = STRALLOC_ZERO ; + size_t remoteip, remotehost ; + char const *x ; + uint32_t n, rhlen ; char progstr[14 + PID_FMT] = "tipideed: pid " ; progstr[14 + pid_fmt(progstr + 14, getpid())] = 0 ; PROG = progstr ; @@ -383,31 +386,37 @@ int main (int argc, char const *const *argv, char const *const *envp) tipideed_harden(h) ; } - { - size_t remoteip, remotehost ; - unsigned int n ; - prep_env(&remoteip, &remotehost) ; - inittto(&g.readtto, "G:read_timeout") ; - inittto(&g.writetto, "G:write_timeout") ; - inittto(&g.cgitto, "G:cgi_timeout") ; - g.maxrqbody = get_uint32("G:max_request_body_length") ; - g.maxcgibody = get_uint32("G:max_cgi_body_length") ; - g.logv = get_uint32("G:logv") ; - n = tipidee_conf_get_argv(&g.conf, "G:index_file", g.indexnames, 16, &g.indexlen) ; - if (!n) strerr_dief3x(102, "bad", " config value for ", "G:index_file") ; - g.indexn = n-1 ; - - if (ndelay_on(0) == -1 || ndelay_on(1) == -1) - strerr_diefu1sys(111, "set I/O nonblocking") ; - init_splice_pipe() ; - if (!sig_catch(SIGCHLD, &sigchld_handler)) - strerr_diefu1sys(111, "set SIGCHLD handler") ; - if (!sig_altignore(SIGPIPE)) - strerr_diefu1sys(111, "ignore SIGPIPE") ; - if (!tain_now_set_stopwatch_g()) - strerr_diefu1sys(111, "initialize clock") ; - tipidee_log_start(g.logv, g.sa.s + remoteip, g.sa.s + remotehost) ; - } + prep_env(&remoteip, &remotehost) ; + inittto(&g.readtto, "G:read_timeout") ; + inittto(&g.writetto, "G:write_timeout") ; + inittto(&g.cgitto, "G:cgi_timeout") ; + g.maxrqbody = get_uint32("G:max_request_body_length") ; + g.maxcgibody = get_uint32("G:max_cgi_body_length") ; + g.logv = get_uint32("G:logv") ; + n = tipidee_conf_get_argv(&g.conf, "G:index_file", g.indexnames, 16, &g.indexlen) ; + if (!n) strerr_dief3x(102, "bad", " config value for ", "G:index_file") ; + g.indexn = n-1 ; + + x = tipidee_conf_get_responseheaders(&g.conf, "G:response_headers", &rhlen, &n) ; + if (!x) strerr_diefu3sys(102, "get", " config value for ", "G:response_headers") ; + + tipidee_response_header rhdr[n ? n : 1] ; /* should start a block but that's a lot of editing */ + if (!tipidee_response_header_preparebuiltin(rhdr, n, x, rhlen)) + strerr_dief3x(102, "bad", " config value for ", "G:response_headers") ; + g.rhdr = rhdr ; + + if (ndelay_on(0) == -1 || ndelay_on(1) == -1) + strerr_diefu1sys(111, "set I/O nonblocking") ; + init_splice_pipe() ; + if (!sig_catch(SIGCHLD, &sigchld_handler)) + strerr_diefu1sys(111, "set SIGCHLD handler") ; + if (!sig_altignore(SIGPIPE)) + strerr_diefu1sys(111, "ignore SIGPIPE") ; + if (!tain_now_set_stopwatch_g()) + strerr_diefu1sys(111, "initialize clock") ; + + + tipidee_log_start(g.logv, g.sa.s + remoteip, g.sa.s + remotehost) ; /* Main loop */ @@ -419,7 +428,6 @@ int main (int argc, char const *const *argv, char const *const *envp) tipidee_headers hdr ; int e ; unsigned int localredirs = 0 ; - char const *x ; size_t content_length ; tipidee_transfercoding tcoding = TIPIDEE_TRANSFERCODING_UNKNOWN ; char uribuf[URI_BUFSIZE] ; |