diff --git a/lnm/include/lnm/http/loop.h b/lnm/include/lnm/http/loop.h index 867a93e..8a199e7 100644 --- a/lnm/include/lnm/http/loop.h +++ b/lnm/include/lnm/http/loop.h @@ -83,6 +83,8 @@ lnm_err lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route); lnm_err lnm_http_loop_run(lnm_http_loop *hl, uint16_t port); +void lnm_http_loop_set_api_key(lnm_http_loop *hl, const char *api_key); + /** * Represents what state an HTTP loop request is currently in. */ @@ -115,6 +117,7 @@ typedef struct lnm_http_loop_gctx { lnm_http_ctx_init_fn ctx_init; lnm_http_ctx_reset_fn ctx_reset; lnm_http_ctx_free_fn ctx_free; + const char *api_key; void *c; } lnm_http_loop_gctx; @@ -130,4 +133,6 @@ typedef struct lnm_http_loop_ctx { lnm_http_step_err lnm_http_loop_step_body_to_buf(lnm_http_conn *conn); +lnm_http_step_err lnm_http_loop_step_auth(lnm_http_conn *conn); + #endif diff --git a/lnm/src/http/lnm_http_loop.c b/lnm/src/http/lnm_http_loop.c index 6cd7d53..0b9b812 100644 --- a/lnm/src/http/lnm_http_loop.c +++ b/lnm/src/http/lnm_http_loop.c @@ -126,3 +126,8 @@ lnm_err lnm_http_loop_run(lnm_http_loop *hl, uint16_t port) { LNM_RES(lnm_loop_setup(hl, port)); return lnm_loop_run(hl); } + +void lnm_http_loop_set_api_key(lnm_http_loop *hl, const char *api_key) { + lnm_http_loop_gctx *gctx = hl->gctx; + gctx->api_key = api_key; +} diff --git a/lnm/src/http/lnm_http_loop_steps.c b/lnm/src/http/lnm_http_loop_steps.c index fde3d70..2552e09 100644 --- a/lnm/src/http/lnm_http_loop_steps.c +++ b/lnm/src/http/lnm_http_loop_steps.c @@ -1,5 +1,6 @@ #include +#include "lnm/http/consts.h" #include "lnm/http/loop.h" #include "lnm/loop.h" @@ -22,3 +23,22 @@ lnm_http_step_err lnm_http_loop_step_body_to_buf(lnm_http_conn *conn) { ? lnm_http_step_err_done : lnm_http_step_err_io_needed; } + +lnm_http_step_err lnm_http_loop_step_auth(lnm_http_conn *conn) { + lnm_http_loop_ctx *ctx = conn->ctx; + + // If there's no API key, requests are always authorized + bool authorized = ctx->g->api_key == NULL; + + const char *value; + size_t value_len; + + if (!authorized && lnm_http_req_header_get_s(&value, &value_len, &ctx->req, + "X-Api-Key") == lnm_err_ok) { + authorized = (value_len == strlen(ctx->g->api_key)) && + (memcmp(value, ctx->g->api_key, value_len) == 0); + } + + ctx->res.status = authorized ? ctx->res.status : lnm_http_status_unauthorized; + return authorized ? lnm_http_step_err_done : lnm_http_step_err_res; +} diff --git a/src/main.c b/src/main.c index 3af1d2f..04bff84 100644 --- a/src/main.c +++ b/src/main.c @@ -7,13 +7,14 @@ #include "lander.h" #include "log.h" -lnm_http_loop *loop_init(lander_gctx *gctx) { +lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) { lnm_http_loop *hl; lnm_http_step *step = NULL; lnm_http_route *route; lnm_http_loop_init(&hl, gctx, lander_ctx_init, (lnm_http_ctx_reset_fn)lander_ctx_reset, (lnm_http_ctx_free_fn)lander_ctx_free); + lnm_http_loop_set_api_key(hl, api_key); lnm_http_step_init(&step, lander_get_index); lnm_http_route_init_literal(&route, lnm_http_method_get, "/", step); @@ -23,28 +24,32 @@ lnm_http_loop *loop_init(lander_gctx *gctx) { lnm_http_route_init_regex(&route, lnm_http_method_get, "^/([^/]+)$", 1, step); lnm_http_loop_route_add(hl, route); - lnm_http_step_init(&step, lander_post_redirect); + lnm_http_step_init(&step, lnm_http_loop_step_auth); lnm_http_route_init_regex(&route, lnm_http_method_post, "^/s(l?)/([^/]*)$", 2, step); + lnm_http_step_append(&step, step, lander_post_redirect); lnm_http_step_append(&step, step, lnm_http_loop_step_body_to_buf); lnm_http_step_append(&step, step, lander_post_redirect_body_to_attr); lnm_http_loop_route_add(hl, route); - lnm_http_step_init(&step, lander_post_paste); + lnm_http_step_init(&step, lnm_http_loop_step_auth); lnm_http_route_init_regex(&route, lnm_http_method_post, "^/p(l?)/([^/]*)$", 2, step); + lnm_http_step_append(&step, step, lander_post_paste); lnm_http_step_append(&step, step, lander_stream_body_to_entry); lnm_http_loop_route_add(hl, route); - lnm_http_step_init(&step, lander_post_file); + lnm_http_step_init(&step, lnm_http_loop_step_auth); lnm_http_route_init_regex(&route, lnm_http_method_post, "^/f(l?)/([^/]*)$", 2, step); + lnm_http_step_append(&step, step, lander_post_file); lnm_http_step_append(&step, step, lander_stream_body_to_entry); lnm_http_loop_route_add(hl, route); - lnm_http_step_init(&step, lander_remove_entry); + lnm_http_step_init(&step, lnm_http_loop_step_auth); lnm_http_route_init_regex(&route, lnm_http_method_delete, "^/([^/]+)$", 1, step); + lnm_http_step_append(&step, step, lander_remove_entry); lnm_http_loop_route_add(hl, route); return hl; @@ -89,7 +94,7 @@ int main() { } info("Store loaded containing %lu entries", lsm_store_size(c_gctx->store)); - lnm_http_loop *hl = loop_init(c_gctx); + lnm_http_loop *hl = loop_init(c_gctx, api_key); lnm_http_loop_run(hl, port); /* http_loop *hl = http_loop_init( */