summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--browse.c71
-rw-r--r--browse.h6
-rw-r--r--cgi.h8
-rw-r--r--config.h4
-rw-r--r--error.h39
-rw-r--r--http.c24
-rw-r--r--http.h16
-rw-r--r--main.c51
-rw-r--r--url.h8
10 files changed, 113 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 5489720..4e014aa 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ CC=cc
CFLAGS_DEPS != pkg-config --cflags kcgi kcgi-html
LDFLAGS_DEPS != pkg-config --libs kcgi kcgi-html
-CFLAGS=-g -W -Wall -Wextra $(CFLAGS_DEPS)
+CFLAGS=-g -W -Wall -Wextra -DLOG_INFO $(CFLAGS_DEPS)
LDFLAGS=-static $(LDFLAGS_DEPS)
all: main
diff --git a/browse.c b/browse.c
index 577183f..f12ed70 100644
--- a/browse.c
+++ b/browse.c
@@ -71,7 +71,7 @@ build_browse_url(struct kreq * r, char *url, size_t url_size, const char *file)
return url_build(url, url_size, 4, r->pname, page_name, r->path, file);
}
-int
+void
browse(struct kreq * r)
{
struct dirent *dir;
@@ -82,58 +82,53 @@ browse(struct kreq * r)
struct khtmlreq html;
/* check that the requested URL can be safely processed */
- if (strlen(r->path) >= URL_LENGTH_MAX) {
- http_open(r, KHTTP_414);
- return VAULT_URI_ERROR;
- }
- if (!check_request_path(r->path)) {
- http_open(r, KHTTP_400);
- return VAULT_URI_ERROR;
- }
+ if (!check_request_path(r->path))
+ http_exit(r, KHTTP_400, "browse: Invalid request path");
+ if (strlen(r->path) >= URL_LENGTH_MAX)
+ http_exit(r, KHTTP_414, NULL);
+
/* list requested directory content */
url_size = url_build(current_dir, URL_LENGTH_MAX, 2, DATA_DIR, r->path);
- if (url_size == 0) {
- http_open(r, KHTTP_404);
- return VAULT_IO_ERROR;
- } else if (url_size >= URL_LENGTH_MAX) {
- http_open(r, KHTTP_414);
- return VAULT_URI_ERROR;
- }
+ if (url_size == 0)
+ http_exit(r, KHTTP_404, "browse: Unable to build data path");
+ if (url_size >= URL_LENGTH_MAX)
+ http_exit(r, KHTTP_414, NULL);
data_dir = opendir(current_dir);
- if (NULL == data_dir) {
- http_open(r, KHTTP_404);
- return VAULT_IO_ERROR;
- }
+ if (NULL == data_dir)
+ http_exit(r, KHTTP_404, NULL);
+
http_open(r, KHTTP_200);
- K_OK(khtml_open(&html, r, 0));
+ K_OK(khtml_open(&html, r, 0), r);
/* build basic html page */
- K_OK(khtml_elem(&html, KELEM_DOCTYPE));
- K_OK(khtml_elem(&html, KELEM_HEAD));
- K_OK(khtml_attr(&html, KELEM_META, KATTR_CHARSET, "utf-8", KATTR__MAX));
- K_OK(khtml_elem(&html, KELEM_HTML));
- K_OK(khtml_elem(&html, KELEM_BODY));
- K_OK(khtml_elem(&html, KELEM_P));
- K_OK(khtml_puts(&html, "/"));
- K_OK(khtml_closeelem(&html, 1));
+ K_OK(khtml_elem(&html, KELEM_DOCTYPE), r);
+ K_OK(khtml_elem(&html, KELEM_HEAD), r);
+ K_OK(khtml_attr(&html, KELEM_META, KATTR_CHARSET, "utf-8", KATTR__MAX),
+ r);
+ K_OK(khtml_elem(&html, KELEM_HTML), r);
+ K_OK(khtml_elem(&html, KELEM_BODY), r);
+ K_OK(khtml_elem(&html, KELEM_P), r);
+ K_OK(khtml_puts(&html, "/"), r);
+ K_OK(khtml_closeelem(&html, 1), r);
- K_OK(khtml_elem(&html, KELEM_UL));
+ K_OK(khtml_elem(&html, KELEM_UL), r);
while ((dir = readdir(data_dir)) != NULL) {
/* ignore special . and .. folders */
file_name = dir->d_name;
if (strcmp(".", file_name) == 0 || strcmp("..", file_name) == 0)
continue;
url_size = build_browse_url(r, url, URL_LENGTH_MAX, file_name);
- if (url_size == 0 || url_size >= URL_LENGTH_MAX)
+ if (url_size == 0 || url_size >= URL_LENGTH_MAX) {
+ kutil_warn(r, NULL, "browse: Detected URL overflow: %s", url);
continue;
- K_OK(khtml_elem(&html, KELEM_LI));
- K_OK(khtml_attr(&html, KELEM_A, KATTR_HREF, url, KATTR__MAX));
- K_OK(khtml_puts(&html, dir->d_name));
- K_OK(khtml_closeelem(&html, 2));
+ }
+ K_OK(khtml_elem(&html, KELEM_LI), r);
+ K_OK(khtml_attr(&html, KELEM_A, KATTR_HREF, url, KATTR__MAX),
+ r);
+ K_OK(khtml_puts(&html, dir->d_name), r);
+ K_OK(khtml_closeelem(&html, 2), r);
}
- K_OK(khtml_close(&html));
+ K_OK(khtml_close(&html), r);
closedir(data_dir);
-
- return VAULT_SUCCESS;
}
diff --git a/browse.h b/browse.h
index 3d34d94..a4f0583 100644
--- a/browse.h
+++ b/browse.h
@@ -36,9 +36,9 @@
#define BROWSE_URL "browse"
/*
- * browse page allows to browse through the folder hierarchy under DATA_DIR,
- * returns 0 in case of success, an error code otherwise
+ * Print a browse page that allows to browse through the folder hierarchy.
+ * The KCGI request is required.
*/
-int browse (struct kreq *);
+void browse(struct kreq *);
#endif /* VAULT_BROWSE_H */
diff --git a/cgi.h b/cgi.h
index 25988f3..aff6bdf 100644
--- a/cgi.h
+++ b/cgi.h
@@ -33,9 +33,9 @@
#include <kcgi.h>
-#include "error.h"
-
-#define K_OK(kcgi_call) if(kcgi_call != KCGI_OK) \
- return VAULT_CGI_ERROR
+#define K_OK(kcgi_call, r) \
+if(kcgi_call != KCGI_OK) { \
+ kutil_warn(r, NULL, "Unexpected CGI error"); \
+}
#endif /* VAULT_CGI_H */
diff --git a/config.h b/config.h
index 0db9f43..4b1ade5 100644
--- a/config.h
+++ b/config.h
@@ -32,6 +32,6 @@
#define VAULT_CONFIG_H
#define DATA_DIR "/var/www/vault-data"
+#define LOG_FILE "/var/log/vault.log"
-#endif /* VAULT_CONFIG_H */
-
+#endif /* VAULT_CONFIG_H */
diff --git a/error.h b/error.h
deleted file mode 100644
index ce96418..0000000
--- a/error.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2023, Vincent Douillet <vincent@vdouillet.fr>
- *
- * 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.
- */
-
-#ifndef VAULT_ERROR_H
-#define VAULT_ERROR_H
-
-#define VAULT_SUCCESS 0
-#define VAULT_CGI_ERROR 1
-#define VAULT_IO_ERROR 2
-#define VAULT_URI_ERROR 3
-
-#endif /* VAULT_ERROR_H */
diff --git a/http.c b/http.c
index 1f7b85b..d0fcbe8 100644
--- a/http.c
+++ b/http.c
@@ -28,6 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include "http.h"
@@ -39,3 +41,25 @@ http_open(struct kreq * r, enum khttp code)
khttp_head(r, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[r->mime]);
khttp_body(r);
}
+
+void
+http_exit(struct kreq * r, enum khttp code, char *content,...)
+{
+ va_list args;
+
+ printf("Status: %s\n", khttps[code]);
+ printf("Content-Type: text/plain\n");
+ printf("\n");
+
+ if (content == NULL)
+ printf("%s", khttps[code]);
+ else {
+ va_start(args, content);
+ vprintf(content, args);
+ va_end(args);
+ }
+
+ va_start(args, content);
+ kutil_verr(r, NULL, content, args);
+ va_end(args);
+}
diff --git a/http.h b/http.h
index e28b2b2..daee438 100644
--- a/http.h
+++ b/http.h
@@ -34,8 +34,20 @@
#include <kcgi.h>
/*
- * Initialize headers and start the document body with the provided http code
+ * Initialize headers and start the document body with the provided http code.
+ * The KCGI request and khttp code are both required.
*/
-void http_open(struct kreq *, enum khttp);
+void http_open(struct kreq *, enum khttp);
+
+/*
+ * Send a plain text error response.
+ * The KCGI request can be NULL.
+ * The khttp code is required.
+ * The error string can be NULL, in this case the http code is printed in plain
+ * text form instead.
+ *
+ * This function exits with EXIT_FAILURE. It never returns.
+ */
+void http_exit(struct kreq *, enum khttp, char *,...);
#endif /* VAULT_HTTP_H */
diff --git a/main.c b/main.c
index 6b54a5e..eab7bca 100644
--- a/main.c
+++ b/main.c
@@ -28,11 +28,14 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "browse.h"
#include "cgi.h"
+#include "config.h"
#include "http.h"
enum page {
@@ -47,46 +50,40 @@ static const char *const pages[PAGE__MAX] = {
int
main(void)
{
- int page_ret_val;
+ enum kcgi_err parse_err;
struct kreq r;
- K_OK(khttp_parse(&r, NULL, 0, pages, PAGE__MAX, PAGE_BROWSE));
+ if (kutil_openlog(LOG_FILE) == 0)
+ http_exit(NULL, KHTTP_500, "Unable to open %s", LOG_FILE);
+
+ parse_err = khttp_parse(&r, NULL, 0, pages, PAGE__MAX, PAGE_BROWSE);
+ if (parse_err != KCGI_OK)
+ http_exit(NULL, KHTTP_500, "Unable to parse request: %s",
+ kcgi_strerror(parse_err));
+
+ /* A bit of security cannot hurt */
+ if (-1 == pledge("stdio rpath wpath cpath", NULL))
+ http_exit(&r, KHTTP_500, "Pledge failed: %s", strerror(errno));
/*
* Make sure basic request parameters are as expected : GET or POST,
* valid page and HTML document
*/
-
- if (r.method != KMETHOD_GET && r.method != KMETHOD_POST) {
- http_open(&r, KHTTP_405);
- khttp_free(&r);
- return EXIT_SUCCESS;
- } else if (r.mime != KMIME_TEXT_HTML) {
- http_open(&r, KHTTP_406); /* Not Acceptable */
- khttp_free(&r);
- return EXIT_SUCCESS;
- } else if (r.page == PAGE__MAX) {
- http_open(&r, KHTTP_404);
- khttp_free(&r);
- return EXIT_SUCCESS;
- }
- if (-1 == pledge("stdio rpath", NULL)) {
- khttp_free(&r);
- return EXIT_FAILURE;
- }
- /*
- * TODO error happens here if(-1 == unveil(DATA_DIR, "r")) { ret_val
- * = EXIT_FAILURE; goto FAIL_HTML; }
- */
+ if (r.method != KMETHOD_GET && r.method != KMETHOD_POST)
+ http_exit(&r, KHTTP_405, NULL);
+ if (r.mime != KMIME_TEXT_HTML)
+ http_exit(&r, KHTTP_406, NULL); /* Not Acceptable */
+ if (r.page == PAGE__MAX)
+ http_exit(&r, KHTTP_404, NULL);
switch (r.page) {
case PAGE_BROWSE:
- page_ret_val = browse(&r);
+ browse(&r);
break;
default:
- abort();
+ http_exit(&r, KHTTP_404, NULL);
}
khttp_free(&r);
- return page_ret_val;
+ return EXIT_SUCCESS;
}
diff --git a/url.h b/url.h
index b60f548..49b0aa1 100644
--- a/url.h
+++ b/url.h
@@ -35,6 +35,14 @@
/*
* Build an URL from the provided components.
+ * The first argument is the destination buffer where the URL will be written.
+ * It is required.
+ * The second argument is the size of the destination buffer. It is required.
+ * The third argument is the number of URL components provided in the following
+ * vargs.
+ * Returns the number of characters written to the destination buffer. If it
+ * is equal to the destination buffer size, it means the buffer was too small
+ * and the resulting URL has been truncated.
*/
size_t
url_build(char *, size_t, int,...);