diff options
author | Adam Chlipala <adam@chlipala.net> | 2013-10-10 14:48:43 -0400 |
---|---|---|
committer | Adam Chlipala <adam@chlipala.net> | 2013-10-10 14:48:43 -0400 |
commit | 08ab929c8600abeeab5089b4a3278cf342ba78a2 (patch) | |
tree | 840fda1a34691b79e391b85265ec99f44696e415 /src | |
parent | aca2cc2ad63fac78d80f9f0a367edd81261be25e (diff) |
Take proper account of signatures changing during page generation
Diffstat (limited to 'src')
-rw-r--r-- | src/c/urweb.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/src/c/urweb.c b/src/c/urweb.c index 88361a87..e4aff33b 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -471,6 +471,8 @@ struct uw_context { int amInitializing; char error_message[ERROR_BUF_LEN]; + + int usedSig, needsResig; }; size_t uw_headers_max = SIZE_MAX; @@ -546,6 +548,9 @@ uw_context uw_init(int id, void *logger_data, uw_logger log_debug) { ctx->amInitializing = 0; + ctx->usedSig = 0; + ctx->needsResig = 0; + return ctx; } @@ -624,6 +629,8 @@ void uw_reset_keep_error_message(uw_context ctx) { ctx->queryString = NULL; ctx->nextId = 0; ctx->amInitializing = 0; + ctx->usedSig = 0; + ctx->needsResig = 0; } void uw_reset_keep_request(uw_context ctx) { @@ -3083,6 +3090,11 @@ uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) { return NULL; } +static void set_cookie(uw_context ctx) { + if (ctx->usedSig) + ctx->needsResig = 1; +} + uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v, uw_Basis_time *expires, uw_Basis_bool secure) { uw_write_header(ctx, "Set-Cookie: "); uw_write_header(ctx, c); @@ -3105,6 +3117,7 @@ uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_str if (secure) uw_write_header(ctx, "; secure"); uw_write_header(ctx, "\r\n"); + set_cookie(ctx); return uw_unit_v; } @@ -3115,6 +3128,7 @@ uw_unit uw_Basis_clear_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_s uw_write_header(ctx, "=; path="); uw_write_header(ctx, prefix); uw_write_header(ctx, "; " THE_PAST "\r\n"); + set_cookie(ctx); return uw_unit_v; } @@ -3192,8 +3206,32 @@ int uw_rollback(uw_context ctx, int will_retry) { static const char begin_xhtml[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">"; +extern int uw_hash_blocksize; + +static const char sig_intro[] = "<input type=\"hidden\" name=\"Sig\" value=\""; + +static char *find_sig(char *haystack) { + int i; + char *s = strstr(haystack, sig_intro); + + if (!s || strlen(haystack) - (s - haystack) - (sizeof sig_intro - 1) < uw_hash_blocksize*2+1) + return NULL; + + s += sizeof sig_intro - 1; + + for (i = 0; i < uw_hash_blocksize*2; ++i) + if (!isxdigit((int)s[i])) + return NULL; + + if (s[i] != '"') + return NULL; + + return s; +} + void uw_commit(uw_context ctx) { int i; + char *sig; if (uw_has_error(ctx)) { uw_rollback(ctx, 0); @@ -3316,6 +3354,18 @@ void uw_commit(uw_context ctx) { } } } + + if (ctx->needsResig) { + sig = find_sig(ctx->page.start); + if (sig) { + char *realsig = ctx->app->cookie_sig(ctx); + + do { + memcpy(sig, realsig, 2*uw_hash_blocksize); + sig = find_sig(sig); + } while (sig); + } + } } @@ -3561,8 +3611,6 @@ uw_Basis_string uw_unnull(uw_Basis_string s) { return s ? s : ""; } -extern int uw_hash_blocksize; - uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) { uw_Basis_string r = uw_malloc(ctx, 2 * uw_hash_blocksize + 1); int i; @@ -3591,6 +3639,7 @@ int uw_streq(uw_Basis_string s1, uw_Basis_string s2) { } uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { + ctx->usedSig = 1; return ctx->app->cookie_sig(ctx); } |