Issue #1396 - correcting Cookie name verification step
This commit is contained in:
parent
77bd0a66b8
commit
ff3db3653e
|
@ -259,8 +259,7 @@ public class Response implements HttpServletResponse
|
|||
|
||||
// Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting
|
||||
// Per RFC6265, Cookie.name follows RFC2616 Section 2.2 token rules
|
||||
if(isQuoteNeededForCookie(name))
|
||||
throw new IllegalArgumentException("Cookie name not RFC6265 compliant");
|
||||
assertRFC2616Token("RFC6265 Cookie name", name);
|
||||
// Ensure that Per RFC6265, Cookie.value follows syntax rules
|
||||
assertRFC6265CookieValue(value);
|
||||
|
||||
|
@ -364,6 +363,54 @@ public class Response implements HttpServletResponse
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Per RFC2616: Section 2.2, a token follows these syntax rules
|
||||
* <pre>
|
||||
* token = 1*<any CHAR except CTLs or separators>
|
||||
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
* CTL = <any US-ASCII control character
|
||||
* (octets 0 - 31) and DEL (127)>
|
||||
* separators = "(" | ")" | "<" | ">" | "@"
|
||||
* | "," | ";" | ":" | "\" | <">
|
||||
* | "/" | "[" | "]" | "?" | "="
|
||||
* | "{" | "}" | SP | HT
|
||||
* </pre>
|
||||
* @param value the value to test
|
||||
* @throws IllegalArgumentException if the value is invalid per spec
|
||||
*/
|
||||
public static void assertRFC2616Token(String scope, String value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int valueLen = value.length();
|
||||
if (valueLen == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < valueLen; i++)
|
||||
{
|
||||
char c = value.charAt(i);
|
||||
|
||||
// 0x00 - 0x1F are low order control characters
|
||||
// 0x7F is the DEL control character
|
||||
if ((c <= 0x1F) || (c == 0x7F))
|
||||
throw new IllegalArgumentException(scope + ": Control characters not allowed in RFC2616 token");
|
||||
if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
|
||||
|| c == ',' || c == ';' || c == ':' || c == '\\' || c == '"'
|
||||
|| c == '/' || c == '[' || c == ']' || c == '?' || c == '='
|
||||
|| c == '{' || c == '}' || c == ' ')
|
||||
{
|
||||
throw new IllegalArgumentException(scope + ": RFC2616 token may not contain separator character: [" + c + "]");
|
||||
}
|
||||
if (c >= 0x80)
|
||||
throw new IllegalArgumentException(scope + ": RFC2616 token characters restricted to US-ASCII range: 0x" + Integer.toHexString(c));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a set cookie value
|
||||
*
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
@ -78,6 +79,7 @@ import org.eclipse.jetty.server.session.SessionHandler;
|
|||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
|
@ -1185,15 +1187,31 @@ public class ResponseTest
|
|||
assertEquals("everything=value;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
fields.clear();
|
||||
|
||||
try
|
||||
String badNameExamples[] = {
|
||||
"\"name\"",
|
||||
"name\t",
|
||||
"na me",
|
||||
"name\u0082",
|
||||
"na\tme",
|
||||
"na;me",
|
||||
"{name}",
|
||||
"[name]",
|
||||
"\""
|
||||
};
|
||||
|
||||
for (String badNameExample : badNameExamples)
|
||||
{
|
||||
response.addSetRFC6265Cookie("ev erything","va lue","do main","pa th",1,true,true);
|
||||
}
|
||||
catch(IllegalArgumentException ex)
|
||||
{
|
||||
assertThat(ex.getMessage(),Matchers.containsString("RFC6265"));
|
||||
fields.clear();
|
||||
try
|
||||
{
|
||||
response.addSetRFC6265Cookie(badNameExample, "value", null, "/", 1, true, true);
|
||||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
// System.err.printf("%s: %s%n", ex.getClass().getSimpleName(), ex.getMessage());
|
||||
assertThat("Testing bad name: [" + badNameExample + "]", ex.getMessage(),
|
||||
allOf(containsString("RFC6265"), containsString("RFC2616")));
|
||||
}
|
||||
}
|
||||
|
||||
String badValueExamples[] = {
|
||||
|
@ -1219,11 +1237,27 @@ public class ResponseTest
|
|||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
// System.err.printf("%s: %s%n", ex.getClass().getSimpleName(), ex.getMessage());
|
||||
assertThat("Testing bad value [" + badValueExample + "]", ex.getMessage(), Matchers.containsString("RFC6265"));
|
||||
}
|
||||
}
|
||||
|
||||
String goodNameExamples[] = {
|
||||
"name",
|
||||
"n.a.m.e",
|
||||
"na-me",
|
||||
"+name",
|
||||
"na*me",
|
||||
"na$me",
|
||||
"#name"
|
||||
};
|
||||
|
||||
fields.clear();
|
||||
for (String goodNameExample : goodNameExamples)
|
||||
{
|
||||
fields.clear();
|
||||
response.addSetRFC6265Cookie(goodNameExample, "value", null, "/", 1, true, true);
|
||||
// should not throw an exception
|
||||
}
|
||||
|
||||
String goodValueExamples[] = {
|
||||
"value",
|
||||
|
@ -1239,6 +1273,7 @@ public class ResponseTest
|
|||
{
|
||||
fields.clear();
|
||||
response.addSetRFC6265Cookie("name", goodValueExample, null, "/", 1, true, true);
|
||||
// should not throw an exception
|
||||
}
|
||||
|
||||
fields.clear();
|
||||
|
@ -1256,7 +1291,7 @@ public class ResponseTest
|
|||
response.addSetRFC6265Cookie("foo","bob","domain",null,-1,false,false);
|
||||
assertThat(fields.get("Set-Cookie"), Matchers.startsWith("name=value"));
|
||||
}
|
||||
|
||||
|
||||
private Response getResponse()
|
||||
{
|
||||
_channel.recycle();
|
||||
|
|
Loading…
Reference in New Issue