aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/urweb.h1
-rw-r--r--src/c/urweb.c17
-rw-r--r--src/cjr_print.sml2
3 files changed, 19 insertions, 1 deletions
diff --git a/include/urweb.h b/include/urweb.h
index 9b68179a..1b10583f 100644
--- a/include/urweb.h
+++ b/include/urweb.h
@@ -230,6 +230,7 @@ uw_unit uw_Basis_setHeader(uw_context, uw_Basis_string name, uw_Basis_string val
uw_Basis_string uw_unnull(uw_Basis_string);
uw_Basis_string uw_Basis_makeSigString(uw_context, uw_Basis_string);
+int uw_streq(uw_Basis_string, uw_Basis_string);
uw_Basis_string uw_Basis_sigString(uw_context, uw_unit);
uw_Basis_string uw_Basis_fileName(uw_context, uw_Basis_file);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 238b27e2..4d2de1dd 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -3455,6 +3455,23 @@ uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) {
return r;
}
+/* This bit of crafty code is intended to prevent GCC from performing
+ * optimizations that would enable timing attacks. See:
+ * http://www.impredicative.com/pipermail/ur/2011-July/000659.html
+ */
+int uw_streq(uw_Basis_string s1, uw_Basis_string s2) {
+ int i, x = 0, len1 = strlen(s1);
+
+ if (len1 != strlen(s2)) return 0;
+
+ for (i = 0; i < len1; ++i) {
+ __asm__ __volatile__ ("");
+ x |= s1[i] ^ s2[i];
+ }
+
+ return x == 0;
+}
+
uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) {
return ctx->app->cookie_sig(ctx);
}
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index 79d7e7da..340ac9f5 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2634,7 +2634,7 @@ fun p_file env (ds, ps) =
newline,
string "if (sig == NULL) uw_error(ctx, FATAL, \"Missing cookie signature\");",
newline,
- string "if (strcmp(sig, uw_cookie_sig(ctx)))",
+ string "if (!uw_streq(sig, uw_cookie_sig(ctx)))",
newline,
box [string "uw_error(ctx, FATAL, \"Wrong cookie signature\");",
newline],