-
Notifications
You must be signed in to change notification settings - Fork 1
/
witty.patch
165 lines (153 loc) · 6.41 KB
/
witty.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
diff --git a/Changelog b/Changelog
index 6e87dcd..84137b2 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,10 @@
+24-06-2011:
+ * WApplication, WWebSession: Cookies now support 'secure' and
+ 'httpOnly' flags. 'httpOnly' now defaults to true; this may
+ affect some apps that relied on Javascript reading cookie
+ values.
+
+
30-05-2011:
* WAbstractItemView, WTreeView: fix browser memory leaks of
inline stylesheet definitions (#834)
diff --git a/src/Wt/WApplication b/src/Wt/WApplication
index faee3b6..9e55d92 100644
--- a/src/Wt/WApplication
+++ b/src/Wt/WApplication
@@ -1366,6 +1366,15 @@ public:
* By default the cookie only applies to the current path on the
* current domain. To set a proper value for domain, see also RFC2109.
*
+ * The httpOnly flag, which now defaults to true prevents the cookie from
+ * being read on the client side by Javscript. This protects it from XSS
+ * attacks.
+ *
+ * If you know you're on a https connection and the cookie is to do with
+ * security, you should set 'secure' to true. When 'secure' is set, most
+ * browsers will only send the cookie when connected via https. This can
+ * help defend against certain hack attempts.
+ *
* \if cpp
* \note %Wt provides session tracking automatically, and may be configured
* to use a cookie for this. You only need to use cookies yourself
@@ -1376,7 +1385,8 @@ public:
*/
void setCookie(const std::string& name, const std::string& value,
int maxAge, const std::string& domain = "",
- const std::string& path = "");
+ const std::string& path = "",
+ bool httpOnly=true, bool secure=false);
/*! \brief Adds an HTML meta header.
*
diff --git a/src/Wt/WApplication.C b/src/Wt/WApplication.C
index 9e7e4a0..4dd430f 100644
--- a/src/Wt/WApplication.C
+++ b/src/Wt/WApplication.C
@@ -888,9 +888,9 @@ void WApplication::setTwoPhaseRenderingThreshold(int bytes)
void WApplication::setCookie(const std::string& name, const std::string& value,
int maxAge, const std::string& domain,
- const std::string& path)
+ const std::string& path, bool httpOnly, bool secure)
{
- session_->renderer().setCookie(name, value, maxAge, domain, path);
+ session_->renderer().setCookie(name, value, maxAge, domain, path, httpOnly, secure);
}
void WApplication::addMetaHeader(const std::string& name,
diff --git a/src/web/WebRenderer.C b/src/web/WebRenderer.C
index 2442e7f..37be221 100644
--- a/src/web/WebRenderer.C
+++ b/src/web/WebRenderer.C
@@ -397,9 +397,10 @@ void WebRenderer::serveError(WebResponse& response, const std::string& message)
void WebRenderer::setCookie(const std::string name, const std::string value,
int maxAge, const std::string domain,
- const std::string path)
+ const std::string path,
+ bool httpOnly, bool secure)
{
- cookiesToSet_.push_back(Cookie(name, value, path, domain, maxAge));
+ cookiesToSet_.push_back(Cookie(name, value, path, domain, maxAge, httpOnly, secure));
}
void WebRenderer::setCaching(WebResponse& response, bool allowCache)
@@ -416,21 +417,35 @@ void WebRenderer::setCaching(WebResponse& response, bool allowCache)
void WebRenderer::setHeaders(WebResponse& response, const std::string mimeType)
{
for (unsigned i = 0; i < cookiesToSet_.size(); ++i) {
- std::string cookies;
+ //std::string cookies;
+ std::stringstream cookieStream;
std::string value = cookiesToSet_[i].value;
- cookies += Utils::urlEncode(cookiesToSet_[i].name)
- + "=" + Utils::urlEncode(value) + "; Version=1;";
- if (cookiesToSet_[i].maxAge != -1)
- cookies += " Max-Age="
- + boost::lexical_cast<std::string>(cookiesToSet_[i].maxAge) + ";";
+ cookieStream << Utils::urlEncode(cookiesToSet_[i].name)
+ << "=" << Utils::urlEncode(value) << "; Version=1;";
+ if (cookiesToSet_[i].maxAge != -1) {
+ cookieStream << " Max-Age="
+ << cookiesToSet_[i].maxAge << ";";
+ // Set the expires header calculated from the MaxAge
+ std::time_t expiresVal = std::time(NULL) + cookiesToSet_[i].maxAge;
+ std::tm* expires = std::gmtime(&expiresVal);
+ char buffer[23];
+ std::strftime(buffer, 23, "%a, %d-%b-%y %H:%M:%S", expires);
+ cookieStream << " Expires=" << buffer << "GMT;";
+ }
if (!cookiesToSet_[i].domain.empty())
- cookies += " Domain=" + cookiesToSet_[i].domain + ";";
+ cookieStream << " Domain=" << cookiesToSet_[i].domain << ";";
if (!cookiesToSet_[i].path.empty())
- cookies += " Path=" + cookiesToSet_[i].path + ";";
+ cookieStream << " Path=" << cookiesToSet_[i].path << ";";
+ if (cookiesToSet_[i].httpOnly)
+ cookieStream << " HttpOnly;";
+ if (cookiesToSet_[i].secure)
+ cookieStream << " Secure;";
+
+ std::string cookieString = cookieStream.str();
- if (!cookies.empty())
- response.addHeader("Set-Cookie", cookies);
+ if (!cookieString.empty())
+ response.addHeader("Set-Cookie", cookieString);
}
cookiesToSet_.clear();
diff --git a/src/web/WebRenderer.h b/src/web/WebRenderer.h
index 1f48335..bf9c44a 100644
--- a/src/web/WebRenderer.h
+++ b/src/web/WebRenderer.h
@@ -66,7 +66,8 @@ public:
void setCookie(const std::string name, const std::string value,
int maxAge, const std::string domain,
- const std::string path);
+ const std::string path,
+ bool httpOnly, bool secure);
bool preLearning() const { return learning_; }
void learningIncomplete();
@@ -82,9 +83,11 @@ private:
std::string path;
std::string domain;
int maxAge;
+ bool httpOnly;
+ bool secure;
- Cookie(std::string n, std::string v, std::string p, std::string d, int m)
- : name(n), value(v), path(p), domain(d), maxAge(m) { }
+ Cookie(std::string n, std::string v, std::string p, std::string d, int m, bool h, bool s)
+ : name(n), value(v), path(p), domain(d), maxAge(m), httpOnly(h), secure(s) { }
};
WebSession& session_;
diff --git a/src/web/WebSession.C b/src/web/WebSession.C
index b2afd72..6e97de1 100644
--- a/src/web/WebSession.C
+++ b/src/web/WebSession.C
@@ -2202,7 +2202,7 @@ void WebSession::generateNewSessionId()
if (controller_->configuration().sessionTracking()
== Configuration::CookiesURL) {
std::string cookieName = env_->deploymentPath();
- renderer().setCookie(cookieName, sessionId_, -1, "", "");
+ renderer().setCookie(cookieName, sessionId_, -1, "", "", true, false); // TODO: pass true at end to use secure cookies
}
}
#endif // WT_TARGET_JAVA