diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2023-09-30 09:38:18 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2023-09-30 09:38:18 +0000 |
commit | 00774b3f92bd6898ce56f41ce39074e9fe89c08e (patch) | |
tree | deeb2a9b483ed3e4e637fc0ea744c65cc64d1763 | |
parent | f1a6903f46c0e2edcdd2b7fa83c8a5bb4ca0e021 (diff) | |
download | tipidee-00774b3f92bd6898ce56f41ce39074e9fe89c08e.tar.gz tipidee-00774b3f92bd6898ce56f41ce39074e9fe89c08e.tar.xz tipidee-00774b3f92bd6898ce56f41ce39074e9fe89c08e.zip |
Some fixes; new SERVER_NAME source; prepare for more config
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r-- | doc/tipideed.html | 31 | ||||
-rw-r--r-- | src/libtipidee/tipidee_rql_read.c | 7 | ||||
-rw-r--r-- | src/libtipidee/tipidee_uri_parse.c | 2 | ||||
-rw-r--r-- | src/tipideed/cgi.c | 3 | ||||
-rw-r--r-- | src/tipideed/tipideed-internal.h | 14 | ||||
-rw-r--r-- | src/tipideed/tipideed.c | 91 |
6 files changed, 85 insertions, 63 deletions
diff --git a/doc/tipideed.html b/doc/tipideed.html index 79c055b..2fa626a 100644 --- a/doc/tipideed.html +++ b/doc/tipideed.html @@ -138,14 +138,6 @@ operations itself. <dd> The IP address the server is bound to. It will be passed as <tt>SERVER_ADDR</tt> to CGI scripts. </dd> - <dt> TCPLOCALPORT </dt> - <dd> The port the server is bound to. It will be passed as <tt>SERVER_PORT</tt> -to CGI scripts. </dd> - - <dt> TCPLOCALHOST </dt> - <dd> The domain name associated to the local IP address. It will be -passed as <tt>SERVER_NAME</tt> to CGI scripts. </dd> - <dt> TCPREMOTEIP </dt> <dd> The IP address of the client. It will be passed as <tt>REMOTE_ADDR</tt> to CGI scripts. </dd> @@ -163,6 +155,19 @@ uses them to get more information. </p> <dl> + <dt> TCPLOCALHOST </dt> + <dd> The default domain name associated to the local IP address. It will be +passed as <tt>SERVER_NAME</tt> to CGI scripts when the requested URI does +not mention a Host, i.e. in HTTP/1.0 requests. If this variable is absent, +the default will be set to the local IP address itself (between square +brackets if IPv6). </dd> + + <dt> TCPLOCALPORT </dt> + <dd> The port the server is bound to. It will be passed as <tt>SERVER_PORT</tt> +to CGI scripts unless the requested URI explicitly mentions a different port. +If this variable is absent, the default will be set to 80 in case of HTTP or +443 in the case of HTTPS. </dd> + <dt> TCPREMOTEHOST </dt> <dd> The domain name associated to the IP address of the client. It will be passed as <tt>REMOTE_HOST</tt> to CGI scripts; if absent, the value of @@ -377,11 +382,11 @@ it on its stdout, to the client. </li> </ul> </li> <li> tipideed exits on EOF (when the client closes the connection), or when the client times out before sending a request, or after tipideed receives a -single HTTP/1.0 request, or when it has answered a request with a -<tt>Connection: close</tt> header, or when it encounters an error where it is -likely that the client will have no use for the connection anymore anyway -and exiting is simpler and cheaper — in which case tipideed adds -<tt>Connection: close</tt> to its last answer. </li> +single HTTP/1.0 request, or when it has executed into an NPH script, or when +it has answered a request with a <tt>Connection: close</tt> header. It also +exits when it encounters an error making it likely that the client will have +no use for the connection anymore anyway and exiting is simpler and cheaper; +in which case tipideed adds <tt>Connection: close</tt> to its last answer. </li> </ul> <div id="performance"> diff --git a/src/libtipidee/tipidee_rql_read.c b/src/libtipidee/tipidee_rql_read.c index f3508cf..fc99f37 100644 --- a/src/libtipidee/tipidee_rql_read.c +++ b/src/libtipidee/tipidee_rql_read.c @@ -1,5 +1,6 @@ /* ISC license. */ +#include <errno.h> #include <stdint.h> #include <string.h> #include <strings.h> @@ -8,7 +9,6 @@ #include <skalibs/bytestr.h> #include <skalibs/buffer.h> #include <skalibs/unix-timed.h> -// #include <skalibs/lolstdio.h> #include <tipidee/method.h> #include <tipidee/uri.h> @@ -66,12 +66,11 @@ static inline int get_version (char const *in, tipidee_rql *rql) int tipidee_rql_read (buffer *b, char *buf, size_t max, size_t *w, tipidee_rql *rql, tain const *deadline, tain *stamp) { size_t pos[3] = { 0 } ; - if (timed_getlnmax(b, buf, max, &pos[0], '\n', deadline, stamp) <= 0) return -1 ; + if (timed_getlnmax(b, buf, max, &pos[0], '\n', deadline, stamp) == -1) + return errno == ETIMEDOUT ? 99 : -1 ; buf[--pos[0]] = 0 ; if (buf[pos[0] - 1] == '\r') buf[--pos[0]] = 0 ; -// LOLDEBUG("tipidee_rql_read: timed_getlnmax: len is %zu, line is %s", pos[0], buf) ; if (!rql_tokenize(buf, pos)) return 400 ; -// LOLDEBUG("tipidee_rql_read: method: %s, version: %s, uri to parse: %s", buf + pos[0], buf + pos[2], buf + pos[1]) ; rql->m = tipidee_method_tonum(buf + pos[0]) ; if (rql->m == TIPIDEE_METHOD_UNKNOWN) return 400 ; if (!get_version(buf + pos[2], rql)) return 400 ; diff --git a/src/libtipidee/tipidee_uri_parse.c b/src/libtipidee/tipidee_uri_parse.c index 10b0f91..6f0064a 100644 --- a/src/libtipidee/tipidee_uri_parse.c +++ b/src/libtipidee/tipidee_uri_parse.c @@ -154,7 +154,7 @@ size_t tipidee_uri_parse (char *out, size_t max, char const *in, tipidee_uri *ur if (c & 0x4000) host = out + w ; if (c & 0x2000) { if (w >= max) return 0 ; out[w++] = 0 ; } if (c & 0x1000) mark = w ; - if (c & 0x0800) { if (!uint160_scan(out + mark, &port)) return 0 ; w = mark ; } + if (c & 0x0800) { if (!uint160_scan(out + mark, &port) || !port) return 0 ; w = mark ; } if (c & 0x0400) path = out + w ; if (c & 0x0200) { if (w >= max) return 0 ; out[w++] = *in ; } if (c & 0x0100) query = out + w ; diff --git a/src/tipideed/cgi.c b/src/tipideed/cgi.c index dc813c8..a875acd 100644 --- a/src/tipideed/cgi.c +++ b/src/tipideed/cgi.c @@ -65,6 +65,7 @@ static inline void modify_env (tipidee_rql const *rql, tipidee_headers const *hd if (rql->uri.query) addenv(rql, "QUERY_STRING", rql->uri.query) ; else delenv(rql, "QUERY_STRING") ; addenv(rql, "SCRIPT_NAME", script) ; + addenv(rql, "SERVER_NAME", rql->uri.host) ; for (size_t i = 0 ; i < hdr->n ; i++) { @@ -83,7 +84,7 @@ static inline void modify_env (tipidee_rql const *rql, tipidee_headers const *hd } } else if (!strcasecmp(key, "Content-Type")) { addenv(rql, "CONTENT_TYPE", val) ; got |= 2 ; } - else if (!strcasecmp(key, "Content-Length") || !strcasecmp(key, "Connection")) ; + else if (!strcasecmp(key, "Content-Length") || !strcasecmp(key, "Connection") || !strcasecmp(key, "Host")) ; else { size_t len = strlen(key), pos = g.sa.len + 5 ; diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h index 75f5be2..770596b 100644 --- a/src/tipideed/tipideed-internal.h +++ b/src/tipideed/tipideed-internal.h @@ -33,21 +33,22 @@ struct global_s stralloc sa ; size_t envlen ; size_t localip ; - size_t localhost ; size_t localport ; - size_t localportlen ; + size_t localhost ; size_t remoteip ; - size_t remotehost ; size_t remoteport ; + size_t remotehost ; size_t cwdlen ; size_t indexlen ; tain readtto ; tain writetto ; tain cgitto ; + char const *defaulthost ; char const *indexnames[16] ; int p[2] ; uint32_t maxrqbody ; uint32_t maxcgibody ; + uint16_t defaultport ; uint16_t indexn : 4 ; uint16_t verbosity : 3 ; uint16_t cont : 2 ; @@ -59,21 +60,22 @@ struct global_s .sa = STRALLOC_ZERO, \ .envlen = 0, \ .localip = 0, \ - .localhost = 0, \ .localport = 0, \ - .localportlen = 0, \ + .localhost = 0, \ .remoteip = 0, \ - .remotehost = 0, \ .remoteport = 0, \ + .remotehost = 0, \ .cwdlen = 1, \ .indexlen = 0, \ .readtto = TAIN_ZERO, \ .writetto = TAIN_ZERO, \ .cgitto = TAIN_ZERO, \ + .defaulthost = "@", \ .indexnames = { 0 }, \ .p = { -1, -1 }, \ .maxrqbody = 0, \ .maxcgibody = 0, \ + .defaultport = 0, \ .indexn = 0, \ .verbosity = 1, \ .cont = 1, \ diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index b5e1ea3..e7dd3a1 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -50,18 +50,20 @@ static inline void prep_env (void) static char const basevars[] = "PROTO\0TCPCONNNUM\0GATEWAY_INTERFACE=CGI/1.1\0SERVER_PROTOCOL=HTTP/1.1\0SERVER_SOFTWARE=tipidee/" TIPIDEE_VERSION ; static char const sslvars[] = "SSL_PROTOCOL\0SSL_CIPHER\0SSL_TLS_SNI_SERVERNAME\0SSL_PEER_CERT_HASH\0SSL_PEER_CERT_SUBJECT\0HTTPS=on" ; char const *x = getenv("SSL_PROTOCOL") ; - if (!stralloc_readyplus(&g.sa, 320)) dienomem() ; + size_t protolen ; if (sagetcwd(&g.sa) == -1) strerr_diefu1sys(111, "getcwd") ; if (g.sa.len == 1) g.sa.len = 0 ; g.cwdlen = g.sa.len ; - if (g.cwdlen && !stralloc_0(&g.sa)) dienomem() ; - if (!stralloc_catb(&g.sa, basevars, sizeof(basevars))) dienomem() ; - if (x && !stralloc_catb(&g.sa, sslvars, sizeof(sslvars))) dienomem() ; + if (!stralloc_readyplus(&g.sa, 220 + sizeof(basevars) + sizeof(sslvars))) dienomem() ; + if (g.cwdlen) stralloc_0(&g.sa) ; + stralloc_catb(&g.sa, basevars, sizeof(basevars)) ; + if (x) stralloc_catb(&g.sa, sslvars, sizeof(sslvars)) ; g.ssl = !!x ; x = getenv(basevars) ; - if (!x) strerr_dienotset(100, "PROTO") ; + protolen = strlen(x) ; + if (protolen > 1000) strerr_dieinvalid(100, "PROTO") ; + if (!x) strerr_dienotset(100, "PROTO") ; { - size_t protolen = strlen(x) ; size_t m ; ip46 ip ; uint16_t port ; @@ -69,6 +71,16 @@ static inline void prep_env (void) char var[protolen + 11] ; memcpy(var, x, protolen) ; + memcpy(var + protolen, "LOCALPORT", 10) ; + x = getenv(var) ; + if (!x) strerr_dienotset(100, var) ; + if (!uint160_scan(x, &g.defaultport)) strerr_dieinvalid(100, var) ; + if (!stralloc_catb(&g.sa, var, protolen + 10) + || !stralloc_catb(&g.sa, "SERVER_PORT=", 12)) dienomem() ; + g.localport = g.sa.len ; + m = uint16_fmt(fmt, g.defaultport) ; fmt[m++] = 0 ; + if (!stralloc_catb(&g.sa, fmt, m)) dienomem() ; + memcpy(var + protolen, "LOCALIP", 8) ; x = getenv(var) ; if (!x) strerr_dienotset(100, var) ; @@ -81,21 +93,21 @@ static inline void prep_env (void) memcpy(var + protolen, "LOCALHOST", 10) ; x = getenv(var) ; - if (!x) strerr_dienotset(100, var) ; - if (!stralloc_catb(&g.sa, var, protolen + 10) - || !stralloc_catb(&g.sa, "SERVER_NAME=", 12)) dienomem() ; - g.localhost = g.sa.len ; - if (!stralloc_cats(&g.sa, x) || !stralloc_0(&g.sa)) dienomem() ; + if (x) + { + if (!stralloc_catb(&g.sa, var, protolen + 10)) dienomem() ; + g.defaulthost = x ; + } - memcpy(var + protolen, "LOCALPORT", 10) ; + memcpy(var + protolen, "REMOTEPORT", 11) ; x = getenv(var) ; if (!x) strerr_dienotset(100, var) ; if (!uint160_scan(x, &port)) strerr_dieinvalid(100, var) ; - if (!stralloc_catb(&g.sa, var, protolen + 10) - || !stralloc_catb(&g.sa, "SERVER_PORT=", 12)) dienomem() ; - g.localport = g.sa.len ; - g.localportlen = uint16_fmt(fmt, port) ; fmt[g.localportlen] = 0 ; - if (!stralloc_catb(&g.sa, fmt, g.localportlen + 1)) dienomem() ; + if (!stralloc_catb(&g.sa, var, protolen + 11) + || !stralloc_catb(&g.sa, "REMOTE_PORT=", 12)) dienomem() ; + g.remoteport = g.sa.len ; + m = uint16_fmt(fmt, port) ; fmt[m++] = 0 ; + if (!stralloc_catb(&g.sa, fmt, m)) dienomem() ; memcpy(var + protolen, "REMOTEIP", 9) ; x = getenv(var) ; @@ -112,18 +124,18 @@ static inline void prep_env (void) if ((x && !stralloc_catb(&g.sa, var, protolen + 11)) || !stralloc_catb(&g.sa, "REMOTE_HOST=", 12)) dienomem() ; g.remotehost = g.sa.len ; - if (!stralloc_cats(&g.sa, x ? x : fmt) - || !stralloc_0(&g.sa)) dienomem() ; - - memcpy(var + protolen, "REMOTEPORT", 11) ; - x = getenv(var) ; - if (!x) strerr_dienotset(100, var) ; - if (!uint160_scan(x, &port)) strerr_dieinvalid(100, var) ; - if (!stralloc_catb(&g.sa, var, protolen + 11) - || !stralloc_catb(&g.sa, "REMOTE_PORT=", 12)) dienomem() ; - g.remoteport = g.sa.len ; - m = uint16_fmt(fmt, port) ; fmt[m++] = 0 ; - if (!stralloc_catb(&g.sa, fmt, m)) dienomem() ; + if (x) + { + if (!stralloc_cats(&g.sa, x)) dienomem() ; + } + else + { + if (!stralloc_readyplus(&g.sa, m + 2)) dienomem() ; + if (ip46_is6(&ip)) stralloc_catb(&g.sa, "[", 1) ; + stralloc_catb(&g.sa, g.sa.s + g.remoteip, m) ; + if (ip46_is6(&ip)) stralloc_catb(&g.sa, "]", 1) ; + } + if (!stralloc_0(&g.sa)) dienomem() ; memcpy(var + protolen, "REMOTEINFO", 11) ; x = getenv(var) ; @@ -243,9 +255,10 @@ static inline void force_redirect (tipidee_rql const *rql, char const *fn) respond_30x(rql, &rd) ; } -static inline int serve (tipidee_rql *rql, char const *docroot, size_t docrootlen, char *uribuf, tipidee_headers const *hdr, char const *body, size_t bodylen) +static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, tipidee_headers const *hdr, char const *body, size_t bodylen) { tipidee_resattr ra = TIPIDEE_RESATTR_ZERO ; + size_t docrootlen = strlen(docroot) ; size_t pathlen = strlen(rql->uri.path) ; char const *infopath = 0 ; struct stat st ; @@ -420,8 +433,9 @@ int main (int argc, char const *const *argv, char const *const *envp) e = tipidee_rql_read_g(buffer_0, uribuf, URI_BUFSIZE, &content_length, &rql, &deadline) ; switch (e) { - case -1 : log_and_exit(1) ; /* Timeout, malicious client, or shitty client */ + case -1 : log_and_exit(1) ; /* Malicious or shitty client */ case 0 : break ; + case 99 : g.cont = 0 ; continue ; /* timeout, it's ok */ case 400 : exit_400(&rql, "Syntax error in request line") ; default : strerr_dief2x(101, "can't happen: ", "unknown tipidee_rql_read return code") ; } @@ -442,7 +456,7 @@ int main (int argc, char const *const *argv, char const *const *envp) default : die500x(&rql, 101, "can't happen: ", "unknown tipidee_headers_parse return code") ; } - if (rql.http_minor == 0) g.cont = 0 ; + if (!rql.http_minor) g.cont = 0 ; else { x = tipidee_headers_search(&hdr, "Connection") ; @@ -490,7 +504,7 @@ int main (int argc, char const *const *argv, char const *const *envp) default : die500x(&rql, 101, "can't happen: unknown HTTP method") ; } - if (!rql.uri.host) + if (rql.http_minor) { x = tipidee_headers_search(&hdr, "Host") ; if (x) @@ -504,17 +518,18 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!*x || *x == '.') exit_400(&rql, "Invalid Host header") ; rql.uri.host = x ; } - else if (!rql.http_minor) rql.uri.host = "@" ; - else exit_400(&rql, "Missing Host header") ; + else if (!rql.uri.host) exit_400(&rql, "Missing Host header") ; } + else if (!rql.uri.host) rql.uri.host = g.defaulthost ; + if (!rql.uri.port) rql.uri.port = g.defaultport ; { size_t hostlen = strlen(rql.uri.host) ; - char docroot[hostlen + g.localportlen + 2] ; + char docroot[hostlen + UINT16_FMT + 1] ; if (rql.uri.host[hostlen - 1] == '.') hostlen-- ; memcpy(docroot, rql.uri.host, hostlen) ; docroot[hostlen] = ':' ; - memcpy(docroot + hostlen + 1, g.sa.s + g.localport, g.localportlen + 1) ; + docroot[hostlen + 1 + uint16_fmt(docroot + hostlen + 1, rql.uri.port)] = 0 ; /* All good. Read the body if any */ @@ -550,7 +565,7 @@ int main (int argc, char const *const *argv, char const *const *envp) /* And serve the resource. The loop is in case of CGI local-redirection. */ - while (serve(&rql, docroot, hostlen + 1 + g.localportlen, uribuf, &hdr, bodysa.s, bodysa.len)) + while (serve(&rql, docroot, uribuf, &hdr, bodysa.s, bodysa.len)) if (localredirs++ >= MAX_LOCALREDIRS) die502x(&rql, 2, "too many local redirections - possible loop involving path ", rql.uri.path) ; } |