n_http_cookie: reading a Cookie header (first occurrence wins) and building Set-Cookie values, with header injection and broken prefixes refused
n_http_cookie: reading a Cookie header (first occurrence wins) and building Set-Cookie values, with header injection and broken prefixes refused
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
if (!ok) {
} else {
}
}
int opt = 0;
while ((opt = getopt(argc, argv, "V:")) != -1) {
if (opt == 'V') {
} else {
return -1;
}
}
return 0;
}
static int cookie_is(
const char* header,
const char* name,
const char* want) {
size_t vl = 99;
if (!want)
return v == NULL && vl == 0;
return v && vl == strlen(want) && memcmp(v, want, vl) == 0;
}
const char*
h =
"a=first; b=x%41;a=second; c=\"q\"; bad name=1; =v; d; e = spaced ;;f=";
expect_true(
"__Host- name found",
cookie_is(
"__Host-nsid=abc123; other=1",
"__Host-nsid",
"abc123"));
}
int res = want ? (ok == TRUE && out && strcmp(out->
data, want) == 0) : (ok == FALSE && out == NULL);
if (!res)
return res;
}
memset(&c, 0, sizeof(c));
builds(&c,
"__Host-nsid=AbC-123_x; Path=/; Secure; HttpOnly; SameSite=Lax"));
builds(&c,
"__Host-nsid=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; Secure; HttpOnly; SameSite=Lax"));
expect_true(
"Max-Age and Strict",
builds(&c,
"__Host-nsid=; Max-Age=3600; Path=/; Secure; HttpOnly; SameSite=Strict"));
memset(&c, 0, sizeof(c));
expect_true(
"plain cookie with Domain, no flags",
builds(&c,
"pref=dark; Path=/a b; Domain=example.org"));
c.
value =
"a\r\nSet-Cookie: x=1";
c.
path =
"/x;Domain=evil";
c.
domain =
"evil.org; Secure";
expect_true(
"SameSite=None with Secure",
builds(&c,
"ok=ok; Secure; SameSite=None"));
expect_true(
"refused append leaves the destination", strcmp(out->
data,
"X: a=ok") == 0);
}
int main(
int argc,
char** argv) {
fprintf(stderr, "usage: %s [-V LOG_LEVEL]\n", argv[0]);
return 1;
}
return 1;
}
return 0;
}
void process_args(int argc, char **argv)
static void expect_true(const char *label, int cond)
static void test_build(void)
building Set-Cookie values
static int cookie_is(const char *header, const char *name, const char *want)
the cookie name in header has exactly the value want (NULL: absent)
static void test_read(void)
reading a Cookie header
static int builds(const N_HTTP_SET_COOKIE *c, const char *want)
build one Set-Cookie and compare
static int h(void *ctx, const N_ROUTE_MATCH *m)
a handler that does nothing (the test only routes)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_NOTICE
normal but significant condition
#define LOG_INFO
informational
int http_only
non-zero: HttpOnly
const char * value
cookie value, RFC 6265 cookie-octets only (may be "")
int secure
non-zero: Secure
const char * path
Path attribute, or NULL.
const char * name
cookie name, an RFC 9110 token
const char * domain
Domain attribute, or NULL (host-only cookie).
N_HTTP_SAMESITE same_site
SameSite attribute.
long long max_age
Max-Age in seconds; N_HTTP_COOKIE_SESSION for a session cookie; 0 deletes the cookie (Max-Age=0 plus ...
size_t n_http_cookie_count(const char *header, size_t len, const char *name)
count the pairs named name in a Cookie header value
N_HTTP_SAMESITE
SameSite attribute of a Set-Cookie.
int n_http_set_cookie_build(N_STR **out, const N_HTTP_SET_COOKIE *c)
append a Set-Cookie header value, refusing anything that could break out of an attribute or that a br...
#define N_HTTP_COOKIE_SESSION
Max-Age value meaning "session cookie": neither Max-Age nor Expires is sent.
const char * n_http_cookie_get(const char *header, size_t len, const char *name, size_t *value_len)
find a cookie in a Cookie header value (first occurrence wins)
@ N_HTTP_SAMESITE_NONE
SameSite=None, needs Secure.
@ N_HTTP_SAMESITE_STRICT
SameSite=Strict.
@ N_HTTP_SAMESITE_LAX
SameSite=Lax.
@ N_HTTP_SAMESITE_UNSET
no SameSite attribute (browser default)
what a Set-Cookie should carry
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
A box including a string and his lenght.
Common headers and low-level functions & define.
Server-side cookies: read a Cookie header, build a Set-Cookie value.
N_STR and string function declaration.