commit db31f37ab01030e9233ce1c981b763a0c035727d
parent 9e5e698e4b74a39f601dc1610cb7fb37c4bae56c
Author: Joris Vink <joris@coders.se>
Date: Tue, 3 Mar 2020 11:28:16 +0100
Add a "return" configuration option.
This hooks into the existing redirection framework but allows you
to quickly deny certain paths with a 403 or other status code.
The snippet below would for example declare a filemap served from 'www'
directory but denying all access to the files under the 'data' directory:
filemap / www
deny /data 403
Diffstat:
src/config.c | | | 33 | +++++++++++++++++++++++++++++++++ |
src/http.c | | | 48 | ++++++++++++++++++++++++++++++------------------ |
2 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/src/config.c b/src/config.c
@@ -110,6 +110,7 @@ static int configure_client_verify_depth(char *);
#if !defined(KORE_NO_HTTP)
static int configure_route(char *);
static int configure_filemap(char *);
+static int configure_return(char *);
static int configure_redirect(char *);
static int configure_static_handler(char *);
static int configure_dynamic_handler(char *);
@@ -192,6 +193,7 @@ static struct {
{ "route", configure_route},
{ "filemap", configure_filemap },
{ "redirect", configure_redirect },
+ { "return", configure_return },
{ "static", configure_static_handler },
{ "dynamic", configure_dynamic_handler },
{ "accesslog", configure_accesslog },
@@ -1031,6 +1033,37 @@ configure_route(char *options)
}
static int
+configure_return(char *options)
+{
+ char *argv[3];
+ int elm, status, err;
+
+ if (current_domain == NULL) {
+ printf("return outside of domain context\n");
+ return (KORE_RESULT_ERROR);
+ }
+
+ elm = kore_split_string(options, " ", argv, 3);
+ if (elm != 2) {
+ printf("missing parameters for return\n");
+ return (KORE_RESULT_ERROR);
+ }
+
+ status = kore_strtonum(argv[1], 10, 400, 600, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("invalid status code on return (%s)\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (!http_redirect_add(current_domain, argv[0], status, NULL)) {
+ printf("invalid regex on return path\n");
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+static int
configure_redirect(char *options)
{
char *argv[4];
diff --git a/src/http.c b/src/http.c
@@ -1500,7 +1500,11 @@ http_redirect_add(struct kore_domain *dom, const char *path, int status,
}
rdr->status = status;
- rdr->target = kore_strdup(target);
+
+ if (target != NULL)
+ rdr->target = kore_strdup(target);
+ else
+ rdr->target = NULL;
TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
@@ -1525,34 +1529,42 @@ http_check_redirect(struct http_request *req, struct kore_domain *dom)
if (rdr == NULL)
return (KORE_RESULT_ERROR);
+ uri = NULL;
kore_buf_init(&location, 128);
- kore_buf_appendf(&location, "%s", rdr->target);
- if (req->query_string != NULL) {
- kore_buf_replace_string(&location, "$qs",
- req->query_string, strlen(req->query_string));
- }
+ if (rdr->target) {
+ kore_buf_appendf(&location, "%s", rdr->target);
- /* Starts at 1 to skip the full path. */
- for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
- if (req->cgroups[idx].rm_so == -1 ||
- req->cgroups[idx].rm_eo == -1)
- break;
+ if (req->query_string != NULL) {
+ kore_buf_replace_string(&location, "$qs",
+ req->query_string, strlen(req->query_string));
+ }
+
+ /* Starts at 1 to skip the full path. */
+ for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
+ if (req->cgroups[idx].rm_so == -1 ||
+ req->cgroups[idx].rm_eo == -1)
+ break;
+
+ (void)snprintf(key, sizeof(key), "$%d", idx);
- (void)snprintf(key, sizeof(key), "$%d", idx);
+ kore_buf_replace_string(&location, key,
+ req->path + req->cgroups[idx].rm_so,
+ req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
+ }
- kore_buf_replace_string(&location, key,
- req->path + req->cgroups[idx].rm_so,
- req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
+ uri = kore_buf_stringify(&location, NULL);
}
- uri = kore_buf_stringify(&location, NULL);
+ if (uri)
+ http_response_header(req, "location", uri);
- http_response_header(req, "location", uri);
http_response(req, rdr->status, NULL, 0);
-
kore_buf_cleanup(&location);
+ if (dom->accesslog)
+ kore_accesslog(req);
+
return (KORE_RESULT_OK);
}