summaryrefslogtreecommitdiff
path: root/src/config
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-10-30 11:16:55 +0000
committerLaurent Bercot <ska@appnovation.com>2023-10-30 11:16:55 +0000
commit1c5f682f4dcbca5afa9dd4a9688bde40efaeb12c (patch)
tree9c5ac88f1c430686d45de44ee36f29fe26be42b1 /src/config
parentad88c5ec68b1cfd47017face422132ab8c7b2874 (diff)
downloadtipidee-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.txt42
-rw-r--r--src/config/conftree.c5
-rw-r--r--src/config/headers.c13
-rw-r--r--src/config/lexparse.c41
-rw-r--r--src/config/resattr.c56
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) ;
+}