Skip to content

Commit

Permalink
Add fast path to same host logic
Browse files Browse the repository at this point in the history
Also clean up the slow path
  • Loading branch information
stuartwdouglas committed Dec 2, 2022
1 parent 9c5c1f8 commit 2ce7349
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static List<Pattern> parseAllowedOriginsRegex(Optional<List<String>> allo
* If any regular expression origins are configured, try to match on them.
* Regular expressions must begin and end with '/'
*
* @param allowedOrigins the configured regex origins.
* @param allowOriginsRegex the configured regex origins.
* @param origin the specified origin
* @return true if any configured regular expressions match the specified origin, false otherwise
*/
Expand Down Expand Up @@ -230,13 +230,37 @@ static boolean isSameOrigin(HttpServerRequest request, String origin) {

static boolean isSameOriginSlowPath(HttpServerRequest request, String origin) {
String absUriString = request.absoluteURI();
if (absUriString.startsWith(origin)) {
// Make sure that Origin URI contains scheme, host, and port.
// If no port is set in Origin URI then the request URI must not have it set either
URI baseUri = URI.create(absUriString.substring(0, origin.length()));
if (baseUri.getScheme() != null && baseUri.getHost() != null
&& (baseUri.getPort() > 0 || URI.create(absUriString).getPort() == -1)) {
return true;
//we already know the scheme is correct, as the fast path will reject that
URI baseUri = URI.create(absUriString);
URI originUri = URI.create(origin);
if (!originUri.getPath().isEmpty()) {
//origin should not contain a path component
//just reject it in this case
return false;
}
if (!baseUri.getHost().equals(originUri.getHost())) {
return false;
}
if (baseUri.getPort() == originUri.getPort()) {
return true;
}
if (baseUri.getPort() != -1 && originUri.getPort() != -1) {
//ports are explictly set
return false;
}
if (baseUri.getScheme().equals("http")) {
if (baseUri.getPort() == 80 || baseUri.getPort() == -1) {
if (originUri.getPort() == 80 || originUri.getPort() == -1) {
//port is either unset or 80
return true;
}
}
} else if (baseUri.getScheme().equals("https")) {
if (baseUri.getPort() == 443 || baseUri.getPort() == -1) {
if (originUri.getPort() == 443 || originUri.getPort() == -1) {
//port is either unset or 443
return true;
}
}
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import static io.quarkus.vertx.http.runtime.cors.CORSFilter.isConfiguredWithWildcard;
import static io.quarkus.vertx.http.runtime.cors.CORSFilter.isOriginAllowedByRegex;
import static io.quarkus.vertx.http.runtime.cors.CORSFilter.isSameOrigin;
import static io.quarkus.vertx.http.runtime.cors.CORSFilter.parseAllowedOriginsRegex;
import static io.quarkus.vertx.http.runtime.cors.CORSFilter.substringMatch;

import java.util.Arrays;
import java.util.Collections;
Expand All @@ -12,6 +14,9 @@

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import io.vertx.core.http.HttpServerRequest;

public class CORSFilterTest {

Expand All @@ -37,4 +42,46 @@ public void isOriginAllowedByRegexTest() {
Assertions.assertEquals(regexList.size(), 1);
Assertions.assertTrue(isOriginAllowedByRegex(regexList, "https://abc-123.app.mydomain.com"));
}

@Test
public void sameOriginTest() {
var request = Mockito.mock(HttpServerRequest.class);
Mockito.when(request.scheme()).thenReturn("http");
Mockito.when(request.host()).thenReturn("localhost");
Mockito.when(request.absoluteURI()).thenReturn("http://localhost");
Assertions.assertTrue(isSameOrigin(request, "http://localhost"));
Assertions.assertTrue(isSameOrigin(request, "http://localhost:80"));
Assertions.assertFalse(isSameOrigin(request, "http://localhost:8080"));
Assertions.assertFalse(isSameOrigin(request, "https://localhost"));
Mockito.when(request.host()).thenReturn("localhost:8080");
Mockito.when(request.absoluteURI()).thenReturn("http://localhost:8080");
Assertions.assertFalse(isSameOrigin(request, "http://localhost"));
Assertions.assertFalse(isSameOrigin(request, "http://localhost:80"));
Assertions.assertTrue(isSameOrigin(request, "http://localhost:8080"));
Assertions.assertFalse(isSameOrigin(request, "https://localhost:8080"));
Mockito.when(request.scheme()).thenReturn("https");
Mockito.when(request.host()).thenReturn("localhost");
Mockito.when(request.absoluteURI()).thenReturn("http://localhost");
Assertions.assertFalse(isSameOrigin(request, "http://localhost"));
Assertions.assertFalse(isSameOrigin(request, "http://localhost:443"));
Assertions.assertFalse(isSameOrigin(request, "https://localhost:8080"));
Assertions.assertTrue(isSameOrigin(request, "https://localhost"));
Mockito.when(request.host()).thenReturn("localhost:8443");
Mockito.when(request.absoluteURI()).thenReturn("https://localhost:8443");
Assertions.assertFalse(isSameOrigin(request, "http://localhost"));
Assertions.assertFalse(isSameOrigin(request, "http://localhost:80"));
Assertions.assertFalse(isSameOrigin(request, "http://localhost:8443"));
Assertions.assertTrue(isSameOrigin(request, "https://localhost:8443"));

}

@Test
public void testSubstringMatches() {
Assertions.assertTrue(substringMatch("localhost", 0, "local", false));
Assertions.assertFalse(substringMatch("localhost", 0, "local", true));
Assertions.assertFalse(substringMatch("localhost", 1, "local", false));
Assertions.assertTrue(substringMatch("localhost", 5, "host", false));
Assertions.assertTrue(substringMatch("localhost", 5, "host", true));

}
}

0 comments on commit 2ce7349

Please sign in to comment.