Skip to content

Commit f4ada98

Browse files
committed
[UNDERTOW-2149] - cookie config paths fix on UNDERTOW-2082
1 parent 15e5454 commit f4ada98

File tree

5 files changed

+620
-7
lines changed

5 files changed

+620
-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
@@ -72,7 +72,9 @@
7272
import java.nio.channels.Channel;
7373
import java.nio.channels.FileChannel;
7474
import java.util.ArrayDeque;
75+
import java.util.ArrayList;
7576
import java.util.Deque;
77+
import java.util.List;
7678
import java.util.Map;
7779
import java.util.Set;
7880
import java.util.TreeMap;
@@ -1184,18 +1186,93 @@ public HttpServerExchange setRequestCookie(final Cookie cookie) {
11841186
}
11851187

11861188
public Cookie getRequestCookie(final String name) {
1189+
return getRequestCookie(name, null);
1190+
}
1191+
1192+
public Cookie getRequestCookie(final String name, final String path) {
11871193
if (name == null) return null;
1194+
final List<Cookie> optionsToMatch = new ArrayList<>();
11881195
for (Cookie cookie : requestCookies()) {
11891196
if (name.equals(cookie.getName())) {
1190-
// TODO: QUESTION: Shouldn't we check instead of just name also
1191-
// TODO requestPath (stored in this exchange request path) and
1192-
// TODO: domain (stored in Host HTTP header).
1193-
return cookie;
1197+
optionsToMatch.add(cookie);
1198+
}
1199+
}
1200+
return matchCookieDetails(optionsToMatch, path);
1201+
}
1202+
1203+
/**
1204+
* Match path and domain of cookies to those present in request. This method will match cookies against exchange request path
1205+
* and once potential pool is identified it will try to find best match based either on supplied 'path' argument
1206+
* @param optionsToMatch
1207+
* @param path - prefix of request path that will be a base for match( or request path). May be <b>null</b>.
1208+
*/
1209+
private Cookie matchCookieDetails(final List<Cookie> optionsToMatch, String path) {
1210+
//NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4
1211+
//NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.3
1212+
// NOTE: Its possible to receive request "/sub" with cookies "/" and "/sub" -
1213+
//we should return longest match if path is not directly specified
1214+
//NOTE: order in request is not guaranteed by UA
1215+
final String requestPath = this.getRequestPath();
1216+
if(path == null) {
1217+
path = requestPath;
1218+
} else {
1219+
//path must be a prefix or match request
1220+
if(!requestPath.startsWith(path)) {
1221+
return null;
1222+
}
1223+
}
1224+
Cookie potentialReturn = null;
1225+
for (final Cookie c : optionsToMatch) {
1226+
if (cookiePathMatch(c, path) && cookieDomainMatch(c)) {
1227+
if(potentialReturn == null) {
1228+
potentialReturn = c;
1229+
} else {
1230+
// at this point length of path is a factor only
1231+
if (computeCookiePath(c).length() > computeCookiePath(potentialReturn).length()) {
1232+
potentialReturn = c;
1233+
}
1234+
}
1235+
1236+
if(computeCookiePath(potentialReturn).equals(path)) {
1237+
//it wont get better
1238+
return potentialReturn;
1239+
}
11941240
}
11951241
}
1196-
return null;
1242+
return potentialReturn;
11971243
}
11981244

1245+
private String computeCookiePath(final Cookie c) {
1246+
//NOTE: this is shady, seems like default is used if no value is present, though UAs should not send cookies to wrong url:
1247+
//5.2 https://www.ietf.org/rfc/rfc2109.txt
1248+
if (c.getPath() != null) {
1249+
return c.getPath();
1250+
} else {
1251+
// NOTE: assume no Path == '/'
1252+
// NOTE: possibly compute as UA would
1253+
return "/";
1254+
}
1255+
}
1256+
1257+
private boolean cookiePathMatch(final Cookie c, final String requestPath) {
1258+
final String cookiePath = computeCookiePath(c);
1259+
if(requestPath == null) {
1260+
return false;
1261+
}
1262+
if( requestPath.equals(cookiePath)) {
1263+
return true;
1264+
}
1265+
1266+
if(requestPath.startsWith(cookiePath) && (cookiePath.charAt(cookiePath.length()-1) == '/' || requestPath.charAt(cookiePath.length()) == '/')) {
1267+
return true;
1268+
}
1269+
return false;
1270+
}
1271+
1272+
private boolean cookieDomainMatch(Cookie c) {
1273+
//TODO: https://issues.redhat.com/browse/UNDERTOW-2261
1274+
return true;
1275+
}
11991276
/**
12001277
* Returns unmodifiable enumeration of request cookies.
12011278
* @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)