Issue #1396 - correcting Cookie name verification step

This commit is contained in:
Joakim Erdfelt 2017-03-15 16:56:22 -07:00
parent 77bd0a66b8
commit ff3db3653e
2 changed files with 94 additions and 12 deletions

View File

@ -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*&lt;any CHAR except CTLs or separators&gt;
* CHAR = &lt;any US-ASCII character (octets 0 - 127)&gt;
* CTL = &lt;any US-ASCII control character
* (octets 0 - 31) and DEL (127)&gt;
* separators = "(" | ")" | "&lt;" | "&gt;" | "@"
* | "," | ";" | ":" | "\" | &lt;"&gt;
* | "/" | "[" | "]" | "?" | "="
* | "{" | "}" | 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
*

View File

@ -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();