summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-10-19 06:36:35 +0000
committerLaurent Bercot <ska@appnovation.com>2023-10-19 06:36:35 +0000
commite782d9cf91c4b5b92897032277c795126d404889 (patch)
tree71c4793c21350edc3235072e825823494005f5f3 /src
parent1a7e3d00588725da3d8764fa9d624bc8611be070 (diff)
downloadtipidee-e782d9cf91c4b5b92897032277c795126d404889.tar.xz
Fix custom response, get rid of secondary static stralloc
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src')
-rw-r--r--src/config/lexparse.c39
-rw-r--r--src/libtipidee/tipidee_conf_get.c2
-rw-r--r--src/tipideed/responses.c25
-rw-r--r--src/tipideed/tipideed.c19
4 files changed, 66 insertions, 19 deletions
diff --git a/src/config/lexparse.c b/src/config/lexparse.c
index d7d9e1b..88a9157 100644
--- a/src/config/lexparse.c
+++ b/src/config/lexparse.c
@@ -55,7 +55,8 @@ enum token_e
T_NONNPH,
T_BASICAUTH,
T_NOAUTH,
- T_FILETYPE
+ T_FILETYPE,
+ T_CUSTOMRESPONSE
} ;
struct directive_s
@@ -200,7 +201,7 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n,
if (!domain)
strerr_dief6x(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[word[0]] != '/')
- strerr_dief5x(1, "redirected resource must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief6x(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!uint320_scan(s + word[1], &code))
strerr_dief6x(1, "invalid redirection code ", s + word[1], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
for (; i < 4 ; i++) if (code == codes[i]) break ;
@@ -237,7 +238,7 @@ static void parse_bitattr (char const *s, size_t const *word, size_t n, char con
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] != '/')
- strerr_dief5x(1, "resource must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief6x(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
{
confnode const *oldnode ;
size_t arglen = strlen(s + *word) ;
@@ -279,7 +280,7 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n,
if (!domain)
strerr_dief7x(1, "file-type", " definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[word[0]] != '/')
- strerr_dief5x(1, "resource must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief6x(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
{
confnode const *oldnode ;
size_t arglen = strlen(s + word[0]) ;
@@ -321,6 +322,32 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n,
}
}
+static inline void parse_customresponse (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md)
+{
+ uint32_t status ;
+ size_t word1, len ;
+ char key[7 + domainlen] ;
+
+ if (n != 2)
+ strerr_dief8x(1, "too ", n > 2 ? "many" : "few", " arguments to directive ", "custom-response", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (!domain)
+ strerr_dief7x(1, "custom-response", " definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (!uint320_scan(s + word[0], &status) || status < 100 || status > 999)
+ strerr_dief6x(1, "invalid status", " for custom-response", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ word1 = word[1] ;
+ while (s[word1] == '/') word1++ ;
+ len = strlen(s + word1) ;
+ if (!len || !strncmp(s + word1, "../", 3) || strstr(s + word1, "/../") || (len >= 3 && !strcmp(s + word1 + len - 3, "/..")))
+ strerr_dief6x(1, "invalid file", " for custom-response", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ key[0] = 'E' ;
+ key[1] = ':' ;
+ uint32_fmt(key + 2, status) ;
+ key[5] = ':' ;
+ memcpy(key + 6, domain, domainlen) ;
+ key[6 + domainlen] = 0 ;
+ add_unique(key, s + word1, len + 1, md) ;
+}
+
static inline void process_line (char const *s, size_t const *word, size_t n, stralloc *domain, mdt *md)
{
static struct directive_s const directives[] =
@@ -329,6 +356,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-response", .token = T_CUSTOMRESPONSE },
{ .s = "domain", .token = T_DOMAIN },
{ .s = "file-type", .token = T_FILETYPE },
{ .s = "global", .token = T_GLOBAL },
@@ -420,6 +448,9 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st
case T_FILETYPE :
parse_filetype(s, word, n, domain->s, domain->len, md) ;
break ;
+ case T_CUSTOMRESPONSE :
+ parse_customresponse(s, word, n, domain->s, domain->len, md) ;
+ break ;
}
}
diff --git a/src/libtipidee/tipidee_conf_get.c b/src/libtipidee/tipidee_conf_get.c
index 2c96d2b..b056fd6 100644
--- a/src/libtipidee/tipidee_conf_get.c
+++ b/src/libtipidee/tipidee_conf_get.c
@@ -4,12 +4,14 @@
#include <string.h>
#include <skalibs/cdb.h>
+#include <skalibs/lolstdio.h>
#include <tipidee/conf.h>
int tipidee_conf_get (tipidee_conf const *conf, char const *key, cdb_data *data)
{
size_t keylen = strlen(key) ;
+ LOLDEBUG("tipidee_conf_get: looking up %s", key) ;
if (keylen > TIPIDEE_CONF_KEY_MAXLEN) return (errno = EINVAL, 0) ;
switch (cdb_find(&conf->c, data, key, keylen))
{
diff --git a/src/tipideed/responses.c b/src/tipideed/responses.c
index 0d0840c..70dcddf 100644
--- a/src/tipideed/responses.c
+++ b/src/tipideed/responses.c
@@ -8,6 +8,7 @@
#include <skalibs/types.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr.h>
+#include <skalibs/stralloc.h>
#include <skalibs/tai.h>
#include <skalibs/djbunix.h>
#include <skalibs/unix-timed.h>
@@ -37,7 +38,14 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s
{
tain deadline ;
tipidee_defaulttext dt ;
- char const *file = tipidee_conf_get_errorfile(&g.conf, docroot, status) ;
+ char const *file ;
+ size_t salen = g.sa.len ;
+ if (sarealpath(&g.sa, docroot) == -1 || !stralloc_0(&g.sa))
+ die500sys(rql, 111, docroot, "realpath ", docroot) ;
+ if (strncmp(g.sa.s + salen, g.sa.s, g.cwdlen) || g.sa.s[salen + g.cwdlen] != '/')
+ die500x(rql, 102, docroot, "docroot ", docroot, " points outside of the server's root") ;
+ file = tipidee_conf_get_errorfile(&g.conf, g.sa.s + salen + g.cwdlen + 1, status) ;
+ g.sa.len = salen ;
if (!tipidee_util_defaulttext(status, &dt))
{
char fmt[UINT_FMT] ;
@@ -47,20 +55,27 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s
if (file)
{
- int fd = open_read(file) ;
- if (fd == -1) strerr_warnwu3sys("open ", "custom error file ", file) ;
+ int fd ;
+ if (file[0] == '/')
+ {
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, status)] = 0 ;
+ strerr_dief4x(102, "bad configuration: absolute path for custom ", fmt, " file: ", file) ;
+ }
+ fd = open_read(file) ;
+ if (fd == -1) strerr_warnwu3sys("open ", "custom response file ", file) ;
else
{
struct stat st ;
if (fstat(fd, &st) == -1)
{
fd_close(fd) ;
- strerr_warnwu3sys("stat ", "custom error file ", file) ;
+ strerr_warnwu3sys("stat ", "custom response file ", file) ;
}
else if (!S_ISREG(st.st_mode))
{
fd_close(fd) ;
- strerr_warnw3x("custom error file ", file, " is not a regular file") ;
+ strerr_warnw3x("custom response file ", file, " is not a regular file") ;
}
else
{
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index b004782..b499b2a 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -195,18 +195,17 @@ static inline unsigned int indexify (tipidee_rql const *rql, char const *docroot
static inline void get_resattr (tipidee_rql const *rql, char const *docroot, char const *res, tipidee_resattr *ra)
{
- static stralloc sa = STRALLOC_ZERO ;
- sa.len = 0 ;
- if (sarealpath(&sa, res) == -1 || !stralloc_0(&sa)) die500sys(rql, 111, docroot, "realpath ", res) ;
- if (strncmp(sa.s, g.sa.s, g.cwdlen) || sa.s[g.cwdlen] != '/')
+ size_t pos = g.sa.len ;
+ if (sarealpath(&g.sa, res) == -1 || !stralloc_0(&g.sa)) die500sys(rql, 111, docroot, "realpath ", res) ;
+ if (strncmp(g.sa.s + pos, g.sa.s, g.cwdlen) || g.sa.s[pos + g.cwdlen] != '/')
die500x(rql, 102, docroot, "resource ", res, " points outside of the server's root") ;
{
char const *attr = 0 ;
- size_t len = sa.len - g.cwdlen + 1 ;
+ size_t len = g.sa.len - pos - g.cwdlen + 1 ;
char key[len + 1] ;
key[0] = 'A' ; key[1] = ':' ;
- memcpy(key + 2, sa.s + 1 + g.cwdlen, sa.len - 1 - g.cwdlen) ;
+ memcpy(key + 2, g.sa.s + pos + 1 + g.cwdlen, len - 2) ;
key[len] = '/' ;
errno = ENOENT ;
while (!attr)
@@ -233,18 +232,18 @@ static inline void get_resattr (tipidee_rql const *rql, char const *docroot, cha
nphprefix = tipidee_conf_get_string(&g.conf, key) ;
if (nphprefix)
{
- char const *base = strrchr(sa.s + g.cwdlen, '/') ;
+ char const *base = strrchr(g.sa.s + pos + g.cwdlen, '/') ;
if (str_start(base + 1, nphprefix)) ra->isnph = 1 ;
}
}
}
}
-
if (!ra->iscgi && !ra->content_type)
{
- ra->content_type = tipidee_conf_get_content_type(&g.conf, sa.s + g.cwdlen) ;
- if (!ra->content_type) die500sys(rql, 111, docroot, "get content type for ", sa.s + g.cwdlen) ;
+ ra->content_type = tipidee_conf_get_content_type(&g.conf, g.sa.s + pos + g.cwdlen) ;
+ if (!ra->content_type) die500sys(rql, 111, docroot, "get content type for ", g.sa.s + pos + g.cwdlen) ;
}
+ g.sa.len = pos ;
}
static inline void force_redirect (tipidee_rql const *rql, char const *fn)