2#define _POSIX_C_SOURCE 200809L
11#define CWIST_CSRF_COOKIE_NAME "csrf_token"
12#define CWIST_CSRF_TOKEN_BYTES 32
13#define CWIST_CSRF_TOKEN_CHARS (CWIST_CSRF_TOKEN_BYTES * 2)
32static char *csrf_generate_token(
void) {
35 if (fd < 0)
return NULL;
37 while (
got <
sizeof(bytes)) {
48 static const char hex[] =
"0123456789abcdef";
51 for (
size_t i = 0;
i <
sizeof(bytes); ++
i) {
66static bool csrf_equal(
const char *
a,
const char *b) {
67 if (!
a || !b)
return false;
84static int hex_value(
unsigned char c) {
85 if (
c >=
'0' &&
c <=
'9')
return c -
'0';
86 if (
c >=
'a' &&
c <=
'f')
return c -
'a' + 10;
87 if (
c >=
'A' &&
c <=
'F')
return c -
'A' + 10;
109 while (pos < len && body[pos] !=
'&') ++pos;
116 const char *value =
eq ?
eq + 1 :
"";
122 unsigned char c = (
unsigned char)value[
i];
126 int hi = hex_value((
unsigned char)value[
i + 1]);
127 int lo = hex_value((
unsigned char)value[
i + 2]);
128 if (hi < 0 || lo < 0) {
189 char *
token = csrf_generate_token();
196 csrf_issue_cookie(req, res,
token);
198 if (csrf_safe_method(req->
method))
207 if (csrf_safe_method(req->
method)) {
213 char *
form = header ?
NULL : csrf_form_value(req);
214 bool valid = csrf_equal(header ? header :
form,
cookie);
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
char * cwist_strdup(const char *src)
Duplicate a string using libttak-backed storage.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
HTTP cookie parsing and construction helpers.
const char * cwist_cookie_get(cwist_query_map *map, const char *name)
Get a cookie value by name from a parsed map.
int cwist_cookie_set(cwist_http_response *res, const char *name, const char *value, const cwist_cookie_options *opts)
Add a Set-Cookie header to the response.
void cwist_cookie_parse(cwist_query_map *map, const char *header)
Parse a Cookie header value into a query-style map.
cwist_error_t cwist_sstring_assign(cwist_sstring *str, const char *data)
Assign a C string.
#define CWIST_CSRF_TOKEN_BYTES
cwist_middleware_func cwist_mw_csrf(cwist_app *app)
Create the CSRF protection middleware.
#define CWIST_CSRF_COOKIE_NAME
#define CWIST_CSRF_TOKEN_CHARS
const char * cwist_csrf_token(cwist_http_request *req)
Get the CSRF token associated with a request.
CSRF protection via double-submit cookie pattern.
char * cwist_http_header_get(cwist_http_header_node *head, const char *key)
Find a header value by key.
@ CWIST_HTTP_INTERNAL_ERROR
cwist_query_map * cwist_query_map_create(void)
Create a new query map.
void cwist_query_map_destroy(cwist_query_map *map)
Destroy a query map.
Main Application Context.
Options for setting a response cookie.
char * csrf_token
CSRF token populated by csrf middleware.
struct cwist_app * app
Owning app context (if any).
cwist_http_header_node * headers
cwist_http_method_t method
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
cwist_http_status_t status_code
char * data
Access directly only when raw handling is necessary.
void(* cwist_handler_func)(cwist_http_request *req, cwist_http_response *res)
Function pointer type for HTTP route handlers.
void(* cwist_middleware_func)(cwist_http_request *req, cwist_http_response *res, cwist_handler_func next)
Middleware type that receives req/res pair and the next stage in the chain.