From f005928d63165d28b32851f04f29055a4d0cdad5 Mon Sep 17 00:00:00 2001 From: Vincent Douillet Date: Thu, 29 Aug 2024 17:46:14 +0200 Subject: get data dir from env variable --- Makefile | 6 +++--- README.md | 7 ++++--- browse.c | 13 ++++++++++++- config.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ config.h | 17 ++++++++--------- download.c | 14 ++++++++++++-- file.c | 8 ++++++-- main.c | 7 ++++++- url.c | 16 ++++++++++------ 9 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 config.c diff --git a/Makefile b/Makefile index 7e84eea..0c485c0 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ LDFLAGS=-static $(LDFLAGS_DEPS) .if make(debug) || make(test) PWD!=pwd -CFLAGS+=-O0 -g -W -Wall -Wextra -DDATA_DIR='"$(PWD)/test-data"' -DTEMPLATE_DIR='"template"' +CFLAGS+=-O0 -g -W -Wall -Wextra -DTEMPLATE_DIR='"template"' .else CFLAGS+=-O2 .endif @@ -47,10 +47,10 @@ all: main .c.o: $(CC) -o $@ -c $< $(CFLAGS) -main: str.o mime.o url.o template.o file.o http.o download.o browse.o main.o +main: str.o config.o mime.o url.o template.o file.o http.o download.o browse.o main.o $(CC) -o $@ $> $(LDFLAGS) -test: str.o mime.o url.o template.o file.o http.o download.o browse.o test.o +test: str.o config.o mime.o url.o template.o file.o http.o download.o browse.o test.o $(CC) -o $@ $> $(LDFLAGS) env: env.o diff --git a/README.md b/README.md index 512453c..a140bc0 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,10 @@ By default on OpenBSD, the `slowcgi(8)` daemon allows a timeout of 2 minutes for server "server" { listen on * port 80 connection timeout 540 - location "/cgi-bin/vault/*" { - fastcgi - root "/" + location "/vault/*" { + root "/cgi-bin/vault" + fastcgi param VAULT_DATA_DIR "/vault-data" + request strip 1 } location "/static/*" { root "/vault-static" diff --git a/browse.c b/browse.c index 51f41dd..868388f 100644 --- a/browse.c +++ b/browse.c @@ -208,6 +208,7 @@ browse(struct kreq * r) { size_t url_len; char current_dir[PATH_MAX]; + char *data_dir; struct file *file; struct page_template *tmpl; struct http_ret ret; @@ -223,6 +224,16 @@ browse(struct kreq * r) KHTTP_200, "" }; + /* check that data dir is configured */ + data_dir = config_data_dir(); + if (data_dir == NULL) { + ret = (struct http_ret) { + KHTTP_400, + "browse: data dir is not configured" + }; + goto end; + } + /* check that the requested URL can be safely processed */ if (!check_request_path(r->path, r->suffix)) { ret = (struct http_ret) { @@ -232,7 +243,7 @@ browse(struct kreq * r) goto end; } /* list requested directory content */ - url_len = url_build(current_dir, PATH_MAX, DATA_DIR, r->path, + url_len = url_build(current_dir, PATH_MAX, data_dir, r->path, NULL); if (url_len == 0) { ret = (struct http_ret) { diff --git a/config.c b/config.c new file mode 100644 index 0000000..4401d31 --- /dev/null +++ b/config.c @@ -0,0 +1,51 @@ +/* + * Copyright 2023, Vincent Douillet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "config.h" + +extern char **environ; + +char * +config_data_dir() +{ + char *key; + + key = "VAULT_DATA_DIR"; + for (char **var = environ; *var; var++) { + if (strncmp(key, *var, strlen(key)) == 0) { + if (strlen(*var) <= strlen(key)) + return NULL; + return *var + strlen(key) + 1; + } + } + return NULL; +} diff --git a/config.h b/config.h index 3f58258..edb494b 100644 --- a/config.h +++ b/config.h @@ -31,15 +31,6 @@ #ifndef CONFIG_H #define CONFIG_H -/* - * The directory that will be browseable through vault. The vault process - * should have full read/write access to this folder and any subfolders and - * files. - */ -#ifndef DATA_DIR -#define DATA_DIR "/vault-data" -#endif - /* * The log file. The vault process needs write permissions to this file, * otherwise it will quit with an error. @@ -53,4 +44,12 @@ #define TEMPLATE_DIR "/usr/share/vault/template" #endif +/* + * The directory that will be browseable through vault. It is read from the env + * variable VAULT_DATA_DIR. The vault process should have full read/write + * access to this folder and any subfolders and files. + */ +char * +config_data_dir(); + #endif /* CONFIG_H */ diff --git a/download.c b/download.c index bff1dd6..a8f5947 100644 --- a/download.c +++ b/download.c @@ -79,7 +79,7 @@ build_download_url(struct kreq * r, struct file * file) struct http_ret download(struct kreq * r) { - char *file_name; + char *file_name, *data_dir; void *buffer; struct file *f; int fd; @@ -93,6 +93,16 @@ download(struct kreq * r) KHTTP_200, "" }; + /* check that data dir is configured */ + data_dir = config_data_dir(); + if (data_dir == NULL) { + ret = (struct http_ret) { + KHTTP_400, + "download: data dir not configured" + }; + goto end; + } + /* check that the requested URL can be safely processed */ if (strlen(r->path) == 0 || !check_request_path(r->path, r->suffix)) { ret = (struct http_ret) { @@ -122,7 +132,7 @@ download(struct kreq * r) } } - path_size = url_build(file_path, PATH_MAX, DATA_DIR, request_path, + path_size = url_build(file_path, PATH_MAX, data_dir, request_path, NULL); if (path_size == 0) { ret = (struct http_ret) { diff --git a/file.c b/file.c index be044ca..5785805 100644 --- a/file.c +++ b/file.c @@ -64,16 +64,20 @@ file_free(struct file * file) static bool fill_metadata(struct file * f) { - char *ext; + char *ext, *data_dir; char path[PATH_MAX]; struct stat sb; size_t path_len; + data_dir = config_data_dir(); + if (data_dir == NULL) + return false; + /* default mime */ f->mime = MIME__MAX; /* check if it is a directory */ - path_len = url_build(path, PATH_MAX, DATA_DIR, f->path, f->name, NULL); + path_len = url_build(path, PATH_MAX, data_dir, f->path, f->name, NULL); if (path_len == 0 || path_len >= PATH_MAX) return false; diff --git a/main.c b/main.c index 0b8e867..1561a09 100644 --- a/main.c +++ b/main.c @@ -53,6 +53,7 @@ static const char *const pages[PAGE__MAX] = { int main(void) { + char *data_dir; enum kcgi_err parse_err; struct kreq r; struct http_ret ret; @@ -65,8 +66,12 @@ main(void) http_exit(NULL, KHTTP_500, "Unable to parse request: %s", kcgi_strerror(parse_err)); + data_dir = config_data_dir(); + if (data_dir == NULL) + http_exit(NULL, KHTTP_500, "Data dir not configured"); + /* A bit of security cannot hurt */ - if (-1 == unveil(DATA_DIR, "r") + if (-1 == unveil(data_dir, "r") || -1 == unveil(TEMPLATE_DIR, "r") || -1 == unveil(NULL, NULL)) http_exit(&r, KHTTP_500, "Unveil failed: %s", strerror(errno)); diff --git a/url.c b/url.c index 228efeb..3e82821 100644 --- a/url.c +++ b/url.c @@ -41,10 +41,14 @@ bool check_request_path(char *path, char *suffix) { char p[PATH_MAX], resolved[PATH_MAX]; - char *rp; + char *rp, *data_dir; + + data_dir = config_data_dir(); + if (data_dir == NULL) + return false; /* build absolute path from DATA_DIR */ - if (strlcpy(p, DATA_DIR, sizeof(p)) >= sizeof(p)) + if (strlcpy(p, data_dir, sizeof(p)) >= sizeof(p)) return false; if (strlcat(p, "/", sizeof(p)) >= sizeof(p)) return false; @@ -52,9 +56,9 @@ check_request_path(char *path, char *suffix) return false; if (strlen(suffix) > 0) { /* add suffix */ - if(strlcat(p, ".", sizeof(p)) >= sizeof(p)) + if (strlcat(p, ".", sizeof(p)) >= sizeof(p)) return false; - if(strlcat(p, suffix, sizeof(p)) >= sizeof(p)) + if (strlcat(p, suffix, sizeof(p)) >= sizeof(p)) return false; } @@ -65,7 +69,7 @@ check_request_path(char *path, char *suffix) /* path must start with DATA_DIR */ rp[PATH_MAX - 1] = '\0'; - if (strstr(rp, DATA_DIR) != rp) + if (strstr(rp, data_dir) != rp) return false; return true; @@ -92,7 +96,7 @@ url_build(char *dst, size_t dst_size,...) if (path[0] == '.' && path[1] == '\0') continue; - if (path[0] != '/' && dst[w_size - 1] != '/') + if (path[0] != '/' && w_size > 0 && dst[w_size - 1] != '/') strlcat(dst, "/", dst_size); w_size = strlcat(dst, path, dst_size); -- cgit v1.2.3