Skip to content

Commit 5994876

Browse files
committed
[UNDERTOW-2149] - cookie config paths fix on UNDERTOW-2082
1 parent c5d6800 commit 5994876

File tree

5 files changed

+595
-7
lines changed

5 files changed

+595
-7
lines changed

core/src/main/java/io/undertow/server/HttpServerExchange.java

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@
7373
import java.nio.channels.Channel;
7474
import java.nio.channels.FileChannel;
7575
import java.util.ArrayDeque;
76+
import java.util.ArrayList;
7677
import java.util.Deque;
78+
import java.util.List;
7779
import java.util.Map;
7880
import java.util.Set;
7981
import java.util.TreeMap;
@@ -1226,18 +1228,93 @@ public HttpServerExchange setRequestCookie(final Cookie cookie) {
12261228
}
12271229

12281230
public Cookie getRequestCookie(final String name) {
1231+
return getRequestCookie(name, null);
1232+
}
1233+
1234+
public Cookie getRequestCookie(final String name, final String path) {
12291235
if (name == null) return null;
1236+
final List<Cookie> optionsToMatch = new ArrayList<>();
12301237
for (Cookie cookie : requestCookies()) {
12311238
if (name.equals(cookie.getName())) {
1232-
// TODO: QUESTION: Shouldn't we check instead of just name also
1233-
// TODO requestPath (stored in this exchange request path) and
1234-
// TODO: domain (stored in Host HTTP header).
1235-
return cookie;
1239+
optionsToMatch.add(cookie);
1240+
}
1241+
}
1242+
return matchCookieDetails(optionsToMatch, path);
1243+
}
1244+
1245+
/**
1246+
* Match path and domain of cookies to those present in request. This method will match cookies against exchange request path
1247+
* and once potential pool is identified it will try to find best match based either on supplied 'path' argument
1248+
* @param optionsToMatch
1249+
* @param path - prefix of request path that will be a base for match( or request path). May be <b>null</b>.
1250+
*/
1251+
private Cookie matchCookieDetails(final List<Cookie> optionsToMatch, String path) {
1252+
//NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4
1253+
//NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.3
1254+
//NOTE: Its possible to receive request "/sub" with cookies "/" and "/sub" -
1255+
//we should return longest match if path is not directly specified
1256+
//NOTE: order in request is not guaranteed by UA
1257+
final String requestPath = this.getRequestPath();
1258+
if(path == null) {
1259+
path = requestPath;
1260+
} else {
1261+
//path must be a prefix or match request
1262+
if(!requestPath.startsWith(path)) {
1263+
return null;
1264+
}
1265+
}
1266+
Cookie potentialReturn = null;
1267+
for (final Cookie c : optionsToMatch) {
1268+
if (cookiePathMatch(c, path) && cookieDomainMatch(c)) {
1269+
if(potentialReturn == null) {
1270+
potentialReturn = c;
1271+
} else {
1272+
// at this point length of path is a factor only
1273+
if (computeCookiePath(c).length() > computeCookiePath(potentialReturn).length()) {
1274+
potentialReturn = c;
1275+
}
1276+
}
1277+
1278+
if(computeCookiePath(potentialReturn).equals(path)) {
1279+
//it wont get better
1280+
return potentialReturn;
1281+
}
12361282
}
12371283
}
1238-
return null;
1284+
return potentialReturn;
12391285
}
12401286

1287+
private String computeCookiePath(final Cookie c) {
1288+
//NOTE: this is shady, seems like default is used if no value is present, though UAs should not send cookies to wrong url:
1289+
//5.2 https://www.ietf.org/rfc/rfc2109.txt
1290+
if (c.getPath() != null) {
1291+
return c.getPath();
1292+
} else {
1293+
// NOTE: assume no Path == '/'
1294+
// NOTE: possibly compute as UA would
1295+
return "/";
1296+
}
1297+
}
1298+
1299+
private boolean cookiePathMatch(final Cookie c, final String requestPath) {
1300+
final String cookiePath = computeCookiePath(c);
1301+
if(requestPath == null) {
1302+
return false;
1303+
}
1304+
if( requestPath.equals(cookiePath)) {
1305+
return true;
1306+
}
1307+
1308+
if(requestPath.startsWith(cookiePath) && (cookiePath.charAt(cookiePath.length()-1) == '/' || requestPath.charAt(cookiePath.length()) == '/')) {
1309+
return true;
1310+
}
1311+
return false;
1312+
}
1313+
1314+
private boolean cookieDomainMatch(Cookie c) {
1315+
//TODO: https://issues.redhat.com/browse/UNDERTOW-2261
1316+
return true;
1317+
}
12411318
/**
12421319
* Returns unmodifiable enumeration of request cookies.
12431320
* @return A read-only enumeration of request cookies

core/src/main/java/io/undertow/server/session/SessionCookieConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void clearSession(final HttpServerExchange exchange, final String session
8080

8181
@Override
8282
public String findSessionId(final HttpServerExchange exchange) {
83-
final Cookie cookie = exchange.getRequestCookie(cookieName);
83+
final Cookie cookie = exchange.getRequestCookie(cookieName, path);
8484
if (cookie != null) {
8585
UndertowLogger.SESSION_LOGGER.tracef("Found session cookie session id %s on %s", cookie, exchange);
8686
return cookie.getValue();

0 commit comments

Comments
 (0)