diff options
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | doc/index.html | 6 | ||||
-rw-r--r-- | doc/tipidee.conf.html | 31 | ||||
-rw-r--r-- | doc/upgrade.html | 10 | ||||
-rw-r--r-- | package/deps.mak | 3 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/config/defaults.c | 1 | ||||
-rw-r--r-- | src/config/lexparse.c | 1 | ||||
-rw-r--r-- | src/tipideed/deps-exe/tipideed | 1 | ||||
-rw-r--r-- | src/tipideed/responses.c | 41 | ||||
-rw-r--r-- | src/tipideed/tipideed-internal.h | 9 | ||||
-rw-r--r-- | src/tipideed/tipideed.c | 18 | ||||
-rw-r--r-- | src/tipideed/util.c | 29 |
13 files changed, 118 insertions, 38 deletions
@@ -6,8 +6,8 @@ Build Instructions - A POSIX-compliant C development environment - GNU make version 3.81 or later - - skalibs version 2.14.0.1 or later: https://skarnet.org/software/skalibs/ - - (optional but recommended): s6-networking version 2.7.0.0 or later: + - skalibs version 2.14.1.0 or later: https://skarnet.org/software/skalibs/ + - (optional but recommended): s6-networking version 2.7.0.1 or later: https://skarnet.org/software/s6-networking/ This software will run on any operating system that implements diff --git a/doc/index.html b/doc/index.html index 0db88cd..2aef76b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -111,11 +111,11 @@ make it shorter. Just like the code. <li> A POSIX-compliant system with a standard C development environment </li> <li> GNU make, version 3.81 or later </li> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version -2.14.0.1 or later. It's a build-time requirement. It's also a run-time +2.14.1.0 or later. It's a build-time requirement. It's also a run-time requirement if you link against the shared version of the skalibs library. </li> <li> Recommended at run-time: <a href="//skarnet.org/software/s6-networking/">s6-networking</a> version -2.7.0.0 or later. It's not a strict requirement, but tipidee relies on a super-server such as +2.7.0.1 or later. It's not a strict requirement, but tipidee relies on a super-server such as <a href="//skarnet.org/software/s6-networking/s6-tcpserver.html">s6-tcpserver</a> to listen to the network and provide connection information via environment variables. It also defers to tools such as @@ -143,7 +143,7 @@ Don't take my word for it; try it out for yourself. </li> <ul> <li> The current released version of tipidee is -<a href="tipidee-0.0.2.0.tar.gz">0.0.2.0</a>. </li> +<a href="tipidee-0.0.3.0.tar.gz">0.0.3.0</a>. </li> <li> You can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/tipidee/">tipidee git repository</a>: diff --git a/doc/tipidee.conf.html b/doc/tipidee.conf.html index 691ac94..17c1a4f 100644 --- a/doc/tipidee.conf.html +++ b/doc/tipidee.conf.html @@ -302,6 +302,37 @@ a directive can protect dynamically managed content that is restricted to a given hierarchy. </li> </ul> +<div id="XXX_no_translate"> +<h4> <tt>XXX_no_translate</tt> </h4> +</div> + +<p> + <code> global XXX_no_translate <em>value</em> </code> +</p> + +<ul> + <li> This directive is dangerous and significantly changes the behaviour of tipideed, +which is why it is marked with the <tt>XXX_</tt> prefix. If you are not 100% certain +that you need it, do not use it. </li> + <li> <em>value</em> is a non-negative integer. If it is nonzero, then: + <ul> + <li> Symbolic links are <em>not resolved</em> when tipidee looks for resources +or error pages. This means that host names and resource paths will be looked up +in the configuration database as they are given by the client, not as they appear +in the filesystem. </li> + <ul> + <li> In particular, a same resource could have different attributes depending on how +it is accessed: it could be seen as a CGI script from one URI and as a regular file from +another. </li> + <li> This also means that if your configuration file needs local directives, you must +specify them for every host/port combination your server is listening on. </li> + </ul> </li> + <li> If tipideed is not chrooted, symbolic links <em>may</em> point outside of the +server root: this will not be checked. This allows you to serve data from other parts +of the filesystem. </li> + </ul> </li> +</ul> + <div id="index-file"> <h3> The <tt>index-file</tt> directive </h3> </div> diff --git a/doc/upgrade.html b/doc/upgrade.html index 74f7594..f2a6880 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,6 +18,16 @@ <h1> What has changed in tipidee </h1> +<h2> in.0.0.3.0 </h2> + +<ul> + <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> +dependency bumped to 2.14.1.0 </li> + <li> <a href="//skarnet.org/software/s6-networking/">s6-networking</a> +recommendation bumped to 2.7.0.1 </li> + <li> New <tt>global XXX_no_translate</tt> configuration directive. </li> +</ul> + <h2> in.0.0.2.0 </h2> <ul> diff --git a/package/deps.mak b/package/deps.mak index 9ef8eed..cd49648 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -67,6 +67,7 @@ src/tipideed/responses.o src/tipideed/responses.lo: src/tipideed/responses.c src src/tipideed/send_file.o src/tipideed/send_file.lo: src/tipideed/send_file.c src/tipideed/tipideed-internal.h src/tipideed/tipideed.o src/tipideed/tipideed.lo: src/tipideed/tipideed.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h src/tipideed/trace.o src/tipideed/trace.lo: src/tipideed/trace.c src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h +src/tipideed/util.o src/tipideed/util.lo: src/tipideed/util.c src/tipideed/tipideed-internal.h tipidee-config: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} tipidee-config: src/config/tipidee-config.o src/config/util.o src/config/node.o src/config/repo.o src/config/conftree.o src/config/headers.o src/config/defaults.o src/config/lexparse.o @@ -80,5 +81,5 @@ 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_resattr.lo src/libtipidee/tipidee_conf_get_resattr1.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_error_nofile_G.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_file_G.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_G.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_header_writeall.lo src/libtipidee/tipidee_response_header_writeall_G.lo src/libtipidee/tipidee_response_header_writemerge.lo src/libtipidee/tipidee_response_header_writemerge_G.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/trace.o libtipidee.a.xyzzy +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/trace.o src/tipideed/util.o libtipidee.a.xyzzy INTERNAL_LIBS := diff --git a/package/info b/package/info index 3492464..a525420 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=tipidee -version=0.0.2.0 +version=0.0.3.0 category=web package_macro_name=TIPIDEE diff --git a/src/config/defaults.c b/src/config/defaults.c index 7dbab8a..18dfa7e 100644 --- a/src/config/defaults.c +++ b/src/config/defaults.c @@ -25,6 +25,7 @@ static struct defaults_s const defaults[] = RECU32("G:max_cgi_body_length", 4194304), RECU32("G:logv", TIPIDEE_LOG_DEFAULT), RECU32("G:executable_means_cgi", 0), + RECU32("G:XXX_no_translate", 0), RECS("G:index-file", "index.html"), RECS("T:html", "text/html"), diff --git a/src/config/lexparse.c b/src/config/lexparse.c index 99eeaa0..d5fcf6d 100644 --- a/src/config/lexparse.c +++ b/src/config/lexparse.c @@ -97,6 +97,7 @@ static inline void parse_global (char const *s, size_t const *word, size_t n, md { static char const *const globalkeys[] = { + "XXX_no_translate", "cgi_timeout", "executable_means_cgi", "max_cgi_body_length", diff --git a/src/tipideed/deps-exe/tipideed b/src/tipideed/deps-exe/tipideed index e1a6c0a..8e5263e 100644 --- a/src/tipideed/deps-exe/tipideed +++ b/src/tipideed/deps-exe/tipideed @@ -5,5 +5,6 @@ regular.o responses.o send_file.o trace.o +util.o libtipidee.a.xyzzy -lskarnet diff --git a/src/tipideed/responses.c b/src/tipideed/responses.c index ad53351..6e32ea9 100644 --- a/src/tipideed/responses.c +++ b/src/tipideed/responses.c @@ -40,21 +40,14 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s { tain deadline ; tipidee_defaulttext dt ; - char const *file = 0; - size_t salen = g.sa.len ; + char const *file = 0 ; + size_t pos = translate_path(docroot) ; - if (sarealpath(&g.sa, docroot) == -1) - { - if (errno != ENOENT) strerr_diefu2sys(111, "realpath ", docroot) ; - } - else - { - if (!stralloc_0(&g.sa)) strerr_diefu1sys(111, "build response") ; - if (strncmp(g.sa.s + salen, g.sa.s, g.cwdlen) || g.sa.s[salen + g.cwdlen] != '/') - strerr_dief4x(102, "layout error: ", "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 (pos) file = tipidee_conf_get_errorfile(&g.conf, g.sa.s + pos , status) ; + else if (errno == EPERM) + strerr_dief4x(102, "layout error: ", "docroot ", docroot, " points outside of the server's root") ; + else if (errno != ENOENT) + strerr_diefu2sys(111, "translate_path ", docroot) ; if (!tipidee_util_defaulttext(status, &dt)) { @@ -65,13 +58,17 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s if (file) { - if (sarealpath(&g.sa, file) == -1 || !stralloc_0(&g.sa)) - strerr_warnwu3sys("realpath ", "custom response file ", file) ; - else if (strncmp(g.sa.s + salen, g.sa.s, g.cwdlen) || g.sa.s[salen + g.cwdlen] != '/') - strerr_warnw4x("layout error: ", "custom response file ", file, " points outside of the server's root") ; + pos = translate_path(file) ; + if (!pos) + { + if (errno == EPERM) + strerr_warnw4x("layout error: ", "custom response file ", file, " points outside of the server's root") ; + else + strerr_warnwu3sys("translate_path ", "custom response file ", file) ; + } else { - int fd = open_read(g.sa.s + salen + g.cwdlen + 1) ; + int fd = open_read(g.sa.s + pos) ; if (fd == -1) strerr_warnwu3sys("open ", "custom response file ", file) ; else { @@ -88,16 +85,14 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s } else { - tipidee_response_file_G(buffer_1, rql, status, dt.reason, &st, tipidee_conf_get_content_type(&g.conf, g.sa.s + salen + g.cwdlen + 1), g.rhdr, g.rhdrn, options) ; + tipidee_response_file_G(buffer_1, rql, status, dt.reason, &st, tipidee_conf_get_content_type(&g.conf, g.sa.s + pos), g.rhdr, g.rhdrn, options) ; tipidee_log_answer(g.logv, rql, status, st.st_size) ; - send_file(fd, st.st_size, g.sa.s + salen + g.cwdlen + 1) ; + send_file(fd, st.st_size, g.sa.s + pos) ; fd_close(fd) ; - g.sa.len = salen ; return ; } } } - g.sa.len = salen ; } tipidee_response_error_nofile_G(buffer_1, rql, status, dt.reason, dt.text, g.rhdr, g.rhdrn, options & 1 || !g.cont) ; diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h index 8b0e114..8631861 100644 --- a/src/tipideed/tipideed-internal.h +++ b/src/tipideed/tipideed-internal.h @@ -41,6 +41,7 @@ struct global_s uint16_t cont : 2 ; uint16_t ssl : 1 ; uint16_t xiscgi : 1 ; + uint8_t flagnoxlate : 1 ; } ; #define GLOBAL_ZERO \ { \ @@ -64,7 +65,8 @@ struct global_s .indexn = 0, \ .cont = 1, \ .ssl = 0, \ - .xiscgi = 0 \ + .xiscgi = 0, \ + .flagnoxlate = 0 \ } extern struct global_s g ; @@ -138,6 +140,11 @@ extern int respond_304 (tipidee_rql const *, char const *, struct stat const *) extern int respond_cgi (tipidee_rql *, char const *, char const *, size_t, char const *, char *, tipidee_headers const *, tipidee_resattr const *, char const *, size_t) ; + /* util */ + +extern size_t translate_path (char const *) ; + + /* main */ extern void log_and_exit (int) gccattr_noreturn ; diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index 0f5d44c..8323db1 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -195,13 +195,16 @@ 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) { - 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") ; - if (!tipidee_conf_get_resattr(&g.conf, g.sa.s + pos + g.cwdlen + 1, ra)) - die500sys(rql, 102, docroot, "look up resource attributes for ", g.sa.s + pos + g.cwdlen + 1) ; - g.sa.len = pos ; + size_t pos = translate_path(res) ; + if (!pos) + { + if (errno == EPERM) + die500x(rql, 102, docroot, "resource ", res, " points outside of the server's root") ; + else + die500sys(rql, 111, docroot, "path_canonicalize ", res) ; + } + if (!tipidee_conf_get_resattr(&g.conf, g.sa.s + pos, ra)) + die500sys(rql, 102, docroot, "look up resource attributes for ", g.sa.s + pos) ; } static inline void force_redirect (tipidee_rql const *rql, char const *fn) @@ -353,6 +356,7 @@ int main (int argc, char const *const *argv, char const *const *envp) g.maxcgibody = get_uint32("G:max_cgi_body_length") ; g.logv = get_uint32("G:logv") ; g.xiscgi = !!get_uint32("G:executable_means_cgi") ; + g.flagnoxlate = !!get_uint32("G:XXX_no_translate") ; 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 ; diff --git a/src/tipideed/util.c b/src/tipideed/util.c new file mode 100644 index 0000000..2891306 --- /dev/null +++ b/src/tipideed/util.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include <errno.h> +#include <string.h> + +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#include "tipideed-internal.h" + +size_t translate_path (char const *path) +{ + size_t n = g.sa.len ; + if (g.flagnoxlate) + { + if (!stralloc_readyplus(&g.sa, strlen(path) + 2)) return 0 ; + path_canonicalize(g.sa.s + n, path, 0) ; + return n ; + } + if (sarealpath(&g.sa, path) == -1 || !stralloc_0(&g.sa)) + { + g.sa.len = n ; + return 0 ; + } + g.sa.len = n ; + if (strncmp(g.sa.s + n, g.sa.s, g.cwdlen) || g.sa.s[n + g.cwdlen] != '/') + return (errno = EPERM, 0) ; + return n + g.cwdlen + 1 ; +} |