diff options
Diffstat (limited to 'clients/web.h')
| -rw-r--r-- | clients/web.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/clients/web.h b/clients/web.h new file mode 100644 index 0000000..a652498 --- /dev/null +++ b/clients/web.h @@ -0,0 +1,100 @@ +#ifndef BOKF_WEB_H +#define BOKF_WEB_H + +#include <stddef.h> +#include <stdint.h> + +#include "util.h" + +/* Pure parts of bokfweb, the login gate in front of the browser terminal: + HTTP request parsing, form and cookie decoding, HTML escaping, the + session store and the per-address login limiter. Unit-tested in + tests/test_web.c; bokfweb.c adds sockets and the bokfd calls. */ + +#define WEB_MAX_REQUEST 8192 + +struct web_req { + char method[8]; + char path[256]; /* without the query */ + char query[256]; + char cookie[512]; + char forwarded_for[64]; + char forwarded_uri[512]; + const char *body; /* points into the parsed buffer */ + size_t body_len; +}; + +/* Parses one HTTP/1.x request in buf[0..n). Returns 0 when complete + (headers and Content-Length bytes of body), 1 when more bytes are + needed, -1 when malformed or too large. */ +int web_parse_request(const char *buf, size_t n, struct web_req *r); + +/* Value of key in an application/x-www-form-urlencoded string (also a + query string), decoded ('+' and %XX). 0 when found, -1 otherwise; a + value that does not fit or decodes to a NUL byte counts as not found. */ +int web_form_get(const char *form, size_t len, const char *key, char *out, + size_t cap); + +/* Value of cookie `name` in a Cookie header. 0 when found. */ +int web_cookie_get(const char *header, const char *name, char *out, + size_t cap); + +/* Appends s to b with & < > " ' escaped. */ +void web_html_escape(struct buf *b, const char *s); + +/* Whether s is a non-empty token of [A-Za-z0-9_-] only (cookie values and + handles are generated that way; anything else is rejected unread). */ +int web_token_ok(const char *s); + +/* --- sessions: cookie token -> bokfd session, plus the terminal handle */ + +#define WEB_MAX_SESSIONS 64 +#define WEB_SESSION_TTL (12 * 3600) /* absolute; bokfd's idle TTL applies too */ + +struct web_session { + char token[64]; /* the cookie value */ + char handle[64]; /* goes into the terminal URL (?arg=) */ + char bokf[128]; /* bokfd session id */ + char user[64]; + int64_t created; +}; + +struct web_store { + struct web_session s[WEB_MAX_SESSIONS]; +}; + +/* Adds a session with fresh random token and handle; the oldest session is + replaced when the store is full. Returns it, or NULL when the random + source fails. */ +struct web_session *web_store_add(struct web_store *st, const char *bokf, + const char *user, int64_t now); +/* The live session with this cookie token / terminal handle, or NULL. */ +struct web_session *web_store_by_token(struct web_store *st, + const char *token, int64_t now); +struct web_session *web_store_by_handle(struct web_store *st, + const char *handle, int64_t now); +void web_store_del(struct web_session *s); + +/* --- failed-login limiter per client address */ + +#define WEB_RL_SLOTS 256 +#define WEB_RL_MAX_FAILS 5 +#define WEB_RL_WINDOW 900 + +struct web_rl_entry { + char addr[64]; + int fails; + int64_t window_end; +}; + +struct web_rl { + struct web_rl_entry e[WEB_RL_SLOTS]; +}; + +/* Seconds until addr may try again, 0 when it may try now. */ +int64_t web_rl_blocked(const struct web_rl *rl, const char *addr, + int64_t now); +void web_rl_fail(struct web_rl *rl, const char *addr, int64_t now); +void web_rl_ok(struct web_rl *rl, const char *addr); + +#endif |
