diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2023-10-30 11:16:55 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2023-10-30 11:16:55 +0000 |
commit | 1c5f682f4dcbca5afa9dd4a9688bde40efaeb12c (patch) | |
tree | 9c5ac88f1c430686d45de44ee36f29fe26be42b1 /src/config | |
parent | ad88c5ec68b1cfd47017face422132ab8c7b2874 (diff) | |
download | tipidee-1c5f682f4dcbca5afa9dd4a9688bde40efaeb12c.tar.xz |
Revamp (and hopefully fix) resattr management
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/config')
-rw-r--r-- | src/config/PROTOCOL.txt | 42 | ||||
-rw-r--r-- | src/config/conftree.c | 5 | ||||
-rw-r--r-- | src/config/headers.c | 13 | ||||
-rw-r--r-- | src/config/lexparse.c | 41 | ||||
-rw-r--r-- | src/config/resattr.c | 56 |
5 files changed, 87 insertions, 70 deletions
diff --git a/src/config/PROTOCOL.txt b/src/config/PROTOCOL.txt deleted file mode 100644 index f6cc304..0000000 --- a/src/config/PROTOCOL.txt +++ /dev/null @@ -1,42 +0,0 @@ -* Globals - -G:read_timeout -> 4 bytes exit if waiting on client input for read_timeout ms -G:write_timeout -> 4 bytes die if waiting on flush to client for write_timeout ms -G:cgi_timeout -> 4 bytes 504 if CGI hasn't finished answering / die if NPH hasn't finished reading -G:max_request_body_length -> 4 bytes -G:max_cgi_body_length -> 4 bytes -G:index_file -> file1\0file2\0file3\0 list of files to attempt when URL is a directory - -They all need to exist, tipidee-config creates defaults. - - -* Content-Type - -T:extension -> string T:pdf -> application/pdf -or individual Content-Types in resource attributes - -tipidee-config hardcodes a number of default content-types, they -can be overridden. - - -* Individual redirection - -R:vres -> Xurl R:skarnet.org/rickroll.html -> Xhttps://www.youtube.com/watch?v=dQw4w9WgXcQ - X = '@' | redir_type (307=0, 308=1, 302=2, 301=3) - - -* Prefix redirection - -r:prefix -> Xurlprefix r:s6.org -> Xhttps://skarnet.org/software/s6 - X = '@' | redir_type (307=0, 308=1, 302=2, 301=3) - -* Resource attributes - -A:file -> Xstring X = '@' | 1 (iscgi) - if string nonempty: it's the content-type for the resource. If empty, default ctype - -a:prefix -> Xstring same, but for prefixes - -* NPH prefixes - -N:domain -> nphprefix N:skarnet.org -> nph- any CGI under skarnet.org starting with nph diff --git a/src/config/conftree.c b/src/config/conftree.c index d4b01ef..a146188 100644 --- a/src/config/conftree.c +++ b/src/config/conftree.c @@ -42,11 +42,6 @@ static int confnode_write (uint32_t d, unsigned int h, void *data) { node *nod = genalloc_s(node, &conftree.ga) + d ; (void)h ; - if ((conftree.storage->s[nod->key] & ~0x20) == 'A') - { - conftree.storage->s[++nod->data] |= '@' ; - nod->datalen-- ; - } return cdbmake_add((cdbmaker *)data, conftree.storage->s + nod->key, nod->keylen, conftree.storage->s + nod->data, nod->datalen) ; } diff --git a/src/config/headers.c b/src/config/headers.c index 31d3e69..4fcdf7d 100644 --- a/src/config/headers.c +++ b/src/config/headers.c @@ -25,11 +25,8 @@ static struct builtinheaders_s const builtinheaders[] = { .key = "Allow", .value = 0, .overridable = 0 }, { .key = "Cache-Control", .value = "private", .overridable = 1 }, { .key = "Connection", .value = 0, .overridable = 0 }, - { .key = "Content-Length", .value = 0, .overridable = 0 }, { .key = "Content-Security-Policy", .value = "default-src 'self'; style-src 'self' 'unsafe-inline';", .overridable = 1 }, - { .key = "Content-Type", .value = 0, .overridable = 0 }, { .key = "Date", .value = 0, .overridable = 0 }, - { .key = "Location", .value = 0, .overridable = 0 }, { .key = "Referrer-Policy", .value = "no-referrer-when-downgrade", .overridable = 1 }, { .key = "Server", .value = "tipidee/" TIPIDEE_VERSION, .overridable = 0 }, { .key = "Status", .value = 0, .overridable = 0 }, @@ -49,7 +46,15 @@ static repo headers = \ int header_allowed (char const *key) { - struct builtinheaders_s const *p = BSEARCH(struct builtinheaders_s, key, builtinheaders) ; + static char const *const nope[] = + { + "Content-Length", + "Content-Type", + "Location" + } ; + struct builtinheaders_s const *p ; + if (BSEARCH(char const *, key, nope)) return 0 ; + p = BSEARCH(struct builtinheaders_s, key, builtinheaders) ; return !p || p->overridable ; } diff --git a/src/config/lexparse.c b/src/config/lexparse.c index b72182e..afd22a5 100644 --- a/src/config/lexparse.c +++ b/src/config/lexparse.c @@ -273,12 +273,11 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n, } } -static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, unsigned int bit, int set) +static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint8_t bit, int h) { static char const *const attr[3][2] = { { "noncgi", "cgi" }, { "nonnph", "nph", }, { "noauth", "basic-auth" } } ; - uint8_t mask = (uint8_t)0x01 << bit ; if (n != 1) - strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][set], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!domain) strerr_dief7x(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (s[*word] != '/') @@ -294,24 +293,31 @@ static void parse_bitattr (char const *s, size_t const *word, size_t n, char con key[2 + domainlen + arglen] = 0 ; oldnode = conftree_search(key) ; if (oldnode) - if (g.storage.s[oldnode->data] & mask) + { + uint32_t flags, mask ; + uint32_unpack_big(g.storage.s + oldnode->data, &flags) ; + uint32_unpack_big(g.storage.s + oldnode->data + 4, &mask) ; + if (mask & 1 << bit) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, oldnode->line)] = 0 ; - strerr_diefn(1, 13, "resource attribute ", attr[bit][set], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; - } - else - { - g.storage.s[oldnode->data] |= mask ; - if (set) g.storage.s[oldnode->data + 1] |= mask ; - else g.storage.s[oldnode->data + 1] &= ~mask ; + strerr_diefn(1, 13, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; } + mask |= 1 << bit ; + if (h) flags |= 1 << bit ; else flags &= ~(1 << bit) ; + uint32_pack_big(g.storage.s + oldnode->data, flags) ; + uint32_pack_big(g.storage.s + oldnode->data + 4, mask) ; + } else { node node ; - char val[3] = { mask, set ? mask : 0, 0 } ; + uint32_t flags = h ? 1 << bit : 0 ; + uint32_t mask = 1 << bit ; + char val[9] = "\0\0\0\0\0\0\0\0" ; + uint32_pack_big(val, flags) ; + uint32_pack_big(val + 4, mask) ; confnode_start(&node, key, md->filepos, md->line) ; - confnode_add(&node, val, 3) ; + confnode_add(&node, val, 9) ; conftree_add(&node) ; } } @@ -337,19 +343,17 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n, oldnode = conftree_search(key) ; if (oldnode) { - if (g.storage.s[oldnode->data] & 0x80) + if (g.storage.s[oldnode->data + 8]) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, oldnode->line)] = 0 ; strerr_diefn(1, 12, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; } - else { node node ; - char val[2] = { g.storage.s[oldnode->data] | 0x80, g.storage.s[oldnode->data + 1] } ; confnode_start(&node, key, md->filepos, md->line) ; - confnode_add(&node, val, 2) ; + confnode_add(&node, g.storage.s + oldnode->data, 8) ; confnode_add(&node, s + word[1], strlen(s + word[1]) + 1) ; conftree_update(&node) ; } @@ -357,9 +361,8 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n, else { node node ; - char val[2] = { 0x80, 0x00 } ; confnode_start(&node, key, md->filepos, md->line) ; - confnode_add(&node, val, 2) ; + confnode_add(&node, "\0\0\0\0\0\0\0", 8) ; confnode_add(&node, s + word[1], strlen(s + word[1]) + 1) ; conftree_add(&node) ; } diff --git a/src/config/resattr.c b/src/config/resattr.c new file mode 100644 index 0000000..80bd0e0 --- /dev/null +++ b/src/config/resattr.c @@ -0,0 +1,56 @@ +/* ISC license. */ + +#include <skalibs/genalloc.h> +#include <skalibs/avltree.h> +#include <skalibs/cdbmake.h> + +#include "tipidee-config-internal.h" + +static repo resattr = \ +{ \ + .ga = GENALLOC_ZERO, \ + .tree = AVLTREE_INIT(8, 3, 8, &node_dtok, &node_cmp, &resattr.ga), \ + .storage = &g.storage \ +} ; + +void confnode_start (node *node, char const *key, size_t filepos, uint32_t line) +{ + return node_start(&g.storage, node, key, filepos, line) ; +} + +void confnode_add (node *node, char const *s, size_t len) +{ + return node_add(&g.storage, node, s, len) ; +} + +node const *conftree_search (char const *key) +{ + return repo_search(&conftree, key) ; +} + +void conftree_add (node const *node) +{ + return repo_add(&conftree, node) ; +} + +void conftree_update (node const *node) +{ + return repo_update(&conftree, node) ; +} + +static int confnode_write (uint32_t d, unsigned int h, void *data) +{ + node *nod = genalloc_s(node, &conftree.ga) + d ; + (void)h ; + if ((conftree.storage->s[nod->key] & ~0x20) == 'A') + { + conftree.storage->s[++nod->data] |= '@' ; + nod->datalen-- ; + } + return cdbmake_add((cdbmaker *)data, conftree.storage->s + nod->key, nod->keylen, conftree.storage->s + nod->data, nod->datalen) ; +} + +int conftree_write (cdbmaker *cm) +{ + return avltree_iter(&conftree.tree, &confnode_write, cm) ; +} |