mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-09-05 11:57:56 +00:00
HTTP rules now allow filtering by port
This commit is contained in:
@@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1G
|
|||||||
mod_version=1.92.0
|
mod_version=1.92.0
|
||||||
|
|
||||||
# Minecraft properties
|
# Minecraft properties
|
||||||
mc_version=1.16.3
|
mc_version=1.16.2
|
||||||
mappings_version=31
|
mappings_version=31
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
20
patchwork.md
20
patchwork.md
@@ -53,3 +53,23 @@ Fix additional `-` in docs
|
|||||||
|
|
||||||
Why isn't this automatically stripped! Bad squid.
|
Why isn't this automatically stripped! Bad squid.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
275ca58a82c627128a145a8754cbe32568536bd9
|
||||||
|
HTTP rules now allow filtering by port
|
||||||
|
|
||||||
|
The HTTP filtering system becomes even more complex! Though in this
|
||||||
|
case, it's pretty minimal, and definitely worth doing.
|
||||||
|
|
||||||
|
For instance, the following rule will allow connecting to localhost on
|
||||||
|
port :8080.
|
||||||
|
|
||||||
|
[[http.rules]]
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 8080
|
||||||
|
action = "allow"
|
||||||
|
|
||||||
|
# Other rules as before.
|
||||||
|
|
||||||
|
Closes #540
|
||||||
|
```
|
@@ -126,10 +126,10 @@ public final class ComputerCraft implements ModInitializer {
|
|||||||
|
|
||||||
public static List<AddressRule> buildHttpRulesFromConfig(String[] blacklist, String[] whitelist) {
|
public static List<AddressRule> buildHttpRulesFromConfig(String[] blacklist, String[] whitelist) {
|
||||||
return Stream.concat(Stream.of(blacklist)
|
return Stream.concat(Stream.of(blacklist)
|
||||||
.map(x -> AddressRule.parse(x, Action.DENY.toPartial()))
|
.map( x -> AddressRule.parse( x, null, Action.DENY.toPartial()))
|
||||||
.filter(Objects::nonNull),
|
.filter(Objects::nonNull),
|
||||||
Stream.of(whitelist)
|
Stream.of(whitelist)
|
||||||
.map(x -> AddressRule.parse(x, Action.ALLOW.toPartial()))
|
.map( x -> AddressRule.parse( x, null, Action.ALLOW.toPartial()))
|
||||||
.filter(Objects::nonNull))
|
.filter(Objects::nonNull))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
@@ -21,14 +21,14 @@ public class CheckUrl extends Resource<CheckUrl> {
|
|||||||
private static final String EVENT = "http_check";
|
private static final String EVENT = "http_check";
|
||||||
private final IAPIEnvironment environment;
|
private final IAPIEnvironment environment;
|
||||||
private final String address;
|
private final String address;
|
||||||
private final String host;
|
private final URI uri;
|
||||||
private Future<?> future;
|
private Future<?> future;
|
||||||
|
|
||||||
public CheckUrl(ResourceGroup<CheckUrl> limiter, IAPIEnvironment environment, String address, URI uri) {
|
public CheckUrl(ResourceGroup<CheckUrl> limiter, IAPIEnvironment environment, String address, URI uri) {
|
||||||
super(limiter);
|
super(limiter);
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.host = uri.getHost();
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -45,8 +45,9 @@ public class CheckUrl extends Resource<CheckUrl> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InetSocketAddress netAddress = NetworkUtils.getAddress(this.host, 80, false);
|
boolean ssl = uri.getScheme().equalsIgnoreCase( "https" );
|
||||||
NetworkUtils.getOptions(this.host, netAddress);
|
InetSocketAddress netAddress = NetworkUtils.getAddress( uri, ssl );
|
||||||
|
NetworkUtils.getOptions( uri.getHost(), netAddress );
|
||||||
|
|
||||||
if (this.tryClose()) {
|
if (this.tryClose()) {
|
||||||
this.environment.queueEvent(EVENT, this.address, true);
|
this.environment.queueEvent(EVENT, this.address, true);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
package dan200.computercraft.core.apis.http;
|
package dan200.computercraft.core.apis.http;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
@@ -94,6 +95,21 @@ public final class NetworkUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
|
||||||
|
*
|
||||||
|
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
|
||||||
|
*
|
||||||
|
* @param uri The URI to fetch.
|
||||||
|
* @param ssl Whether to connect with SSL. This is used to find the default port if not otherwise specified.
|
||||||
|
* @return The resolved address.
|
||||||
|
* @throws HTTPRequestException If the host is not malformed.
|
||||||
|
*/
|
||||||
|
public static InetSocketAddress getAddress( URI uri, boolean ssl ) throws HTTPRequestException
|
||||||
|
{
|
||||||
|
return getAddress( uri.getHost(), uri.getPort(), ssl );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link InetSocketAddress} from the resolved {@code host} and port.
|
* Create a {@link InetSocketAddress} from the resolved {@code host} and port.
|
||||||
*
|
*
|
||||||
@@ -125,7 +141,7 @@ public final class NetworkUtils {
|
|||||||
* @throws HTTPRequestException If the host is not permitted
|
* @throws HTTPRequestException If the host is not permitted
|
||||||
*/
|
*/
|
||||||
public static Options getOptions(String host, InetSocketAddress address) throws HTTPRequestException {
|
public static Options getOptions(String host, InetSocketAddress address) throws HTTPRequestException {
|
||||||
Options options = AddressRule.apply(ComputerCraft.httpRules, host, address.getAddress());
|
Options options = AddressRule.apply( ComputerCraft.httpRules, host, address );
|
||||||
if (options.action == Action.DENY) {
|
if (options.action == Action.DENY) {
|
||||||
throw new HTTPRequestException("Domain not permitted");
|
throw new HTTPRequestException("Domain not permitted");
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ package dan200.computercraft.core.apis.http.options;
|
|||||||
|
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@@ -26,15 +27,22 @@ public final class AddressRule {
|
|||||||
public static final int WEBSOCKET_MESSAGE = 128 * 1024;
|
public static final int WEBSOCKET_MESSAGE = 128 * 1024;
|
||||||
private final HostRange ip;
|
private final HostRange ip;
|
||||||
private final Pattern domainPattern;
|
private final Pattern domainPattern;
|
||||||
|
private final Integer port;
|
||||||
private final PartialOptions partial;
|
private final PartialOptions partial;
|
||||||
private AddressRule(@Nullable HostRange ip, @Nullable Pattern domainPattern, @Nonnull PartialOptions partial) {
|
private AddressRule(
|
||||||
|
@Nullable HostRange ip,
|
||||||
|
@Nullable Pattern domainPattern,
|
||||||
|
@Nullable Integer port,
|
||||||
|
@Nonnull PartialOptions partial )
|
||||||
|
{
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.domainPattern = domainPattern;
|
this.domainPattern = domainPattern;
|
||||||
this.partial = partial;
|
this.partial = partial;
|
||||||
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AddressRule parse(String filter, @Nonnull PartialOptions partial) {
|
public static AddressRule parse( String filter, @Nullable Integer port, @Nonnull PartialOptions partial ) {
|
||||||
int cidr = filter.indexOf('/');
|
int cidr = filter.indexOf('/');
|
||||||
if (cidr >= 0) {
|
if (cidr >= 0) {
|
||||||
String addressStr = filter.substring(0, cidr);
|
String addressStr = filter.substring(0, cidr);
|
||||||
@@ -73,14 +81,14 @@ public final class AddressRule {
|
|||||||
size -= 8;
|
size -= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AddressRule(new HostRange(minBytes, maxBytes), null, partial);
|
return new AddressRule(new HostRange(minBytes, maxBytes), null, port, partial);
|
||||||
} else {
|
} else {
|
||||||
Pattern pattern = Pattern.compile("^\\Q" + filter.replaceAll("\\*", "\\\\E.*\\\\Q") + "\\E$");
|
Pattern pattern = Pattern.compile("^\\Q" + filter.replaceAll("\\*", "\\\\E.*\\\\Q") + "\\E$");
|
||||||
return new AddressRule(null, pattern, partial);
|
return new AddressRule(null, pattern, port, partial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Options apply(Iterable<? extends AddressRule> rules, String domain, InetAddress address) {
|
public static Options apply(Iterable<? extends AddressRule> rules, String domain, InetSocketAddress address) {
|
||||||
PartialOptions options = null;
|
PartialOptions options = null;
|
||||||
boolean hasMany = false;
|
boolean hasMany = false;
|
||||||
|
|
||||||
@@ -109,10 +117,13 @@ public final class AddressRule {
|
|||||||
* Determine whether the given address matches a series of patterns.
|
* Determine whether the given address matches a series of patterns.
|
||||||
*
|
*
|
||||||
* @param domain The domain to match
|
* @param domain The domain to match
|
||||||
* @param address The address to check.
|
* @param socketAddress The address to check.
|
||||||
* @return Whether it matches any of these patterns.
|
* @return Whether it matches any of these patterns.
|
||||||
*/
|
*/
|
||||||
private boolean matches(String domain, InetAddress address) {
|
private boolean matches(String domain, InetSocketAddress socketAddress) {
|
||||||
|
InetAddress address = socketAddress.getAddress();
|
||||||
|
if( port != null && port != socketAddress.getPort() ) return false;
|
||||||
|
|
||||||
if (this.domainPattern != null) {
|
if (this.domainPattern != null) {
|
||||||
if (this.domainPattern.matcher(domain)
|
if (this.domainPattern.matcher(domain)
|
||||||
.matches()) {
|
.matches()) {
|
||||||
|
@@ -9,6 +9,8 @@ package dan200.computercraft.core.apis.http.options;
|
|||||||
public class AddressRuleConfig {
|
public class AddressRuleConfig {
|
||||||
// TODO haha config is gone, do fix
|
// TODO haha config is gone, do fix
|
||||||
|
|
||||||
|
// TODO FIGURE OUT WHY THE HELL THE PREVIOUS GUY HAD TO COMMENT THIS OUT
|
||||||
|
|
||||||
// public static UnmodifiableConfig makeRule( String host, Action action )
|
// public static UnmodifiableConfig makeRule( String host, Action action )
|
||||||
// {
|
// {
|
||||||
// CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new );
|
// CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new );
|
||||||
@@ -39,17 +41,19 @@ public class AddressRuleConfig {
|
|||||||
// {
|
// {
|
||||||
// String hostObj = get( builder, "host", String.class ).orElse( null );
|
// String hostObj = get( builder, "host", String.class ).orElse( null );
|
||||||
// return hostObj != null && checkEnum( builder, "action", Action.class )
|
// return hostObj != null && checkEnum( builder, "action", Action.class )
|
||||||
|
// && check( builder, "port", Number.class )
|
||||||
// && check( builder, "timeout", Number.class )
|
// && check( builder, "timeout", Number.class )
|
||||||
// && check( builder, "max_upload", Number.class )
|
// && check( builder, "max_upload", Number.class )
|
||||||
// && check( builder, "max_download", Number.class )
|
// && check( builder, "max_download", Number.class )
|
||||||
// && check( builder, "websocket_message", Number.class )
|
// && check( builder, "websocket_message", Number.class )
|
||||||
// && AddressRule.parse( hostObj, PartialOptions.DEFAULT ) != null;
|
// && AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @Nullable
|
// @Nullable
|
||||||
// public static AddressRule parseRule( UnmodifiableConfig builder )
|
// public static AddressRule parseRule( UnmodifiableConfig builder )
|
||||||
// {
|
// {
|
||||||
// String hostObj = get( builder, "host", String.class ).orElse( null );
|
// String hostObj = get( builder, "host", String.class ).orElse( null );
|
||||||
|
// Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
|
||||||
// if( hostObj == null ) return null;
|
// if( hostObj == null ) return null;
|
||||||
//
|
//
|
||||||
// Action action = getEnum( builder, "action", Action.class ).orElse( null );
|
// Action action = getEnum( builder, "action", Action.class ).orElse( null );
|
||||||
@@ -66,7 +70,7 @@ public class AddressRuleConfig {
|
|||||||
// websocketMessage
|
// websocketMessage
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// return AddressRule.parse( hostObj, options );
|
// return AddressRule.parse( hostObj, port, options );
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// private static <T> boolean check( UnmodifiableConfig config, String field, Class<T> klass )
|
// private static <T> boolean check( UnmodifiableConfig config, String field, Class<T> klass )
|
||||||
|
@@ -131,7 +131,7 @@ public class HttpRequest extends Resource<HttpRequest> {
|
|||||||
try {
|
try {
|
||||||
boolean ssl = uri.getScheme()
|
boolean ssl = uri.getScheme()
|
||||||
.equalsIgnoreCase("https");
|
.equalsIgnoreCase("https");
|
||||||
InetSocketAddress socketAddress = NetworkUtils.getAddress(uri.getHost(), uri.getPort(), ssl);
|
InetSocketAddress socketAddress = NetworkUtils.getAddress(uri, ssl);
|
||||||
Options options = NetworkUtils.getOptions(uri.getHost(), socketAddress);
|
Options options = NetworkUtils.getOptions(uri.getHost(), socketAddress);
|
||||||
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;
|
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;
|
||||||
|
|
||||||
|
@@ -117,7 +117,7 @@ public class Websocket extends Resource<Websocket> {
|
|||||||
boolean ssl = this.uri.getScheme()
|
boolean ssl = this.uri.getScheme()
|
||||||
.equalsIgnoreCase("wss");
|
.equalsIgnoreCase("wss");
|
||||||
|
|
||||||
InetSocketAddress socketAddress = NetworkUtils.getAddress(this.uri.getHost(), this.uri.getPort(), ssl);
|
InetSocketAddress socketAddress = NetworkUtils.getAddress(uri, ssl);
|
||||||
Options options = NetworkUtils.getOptions(this.uri.getHost(), socketAddress);
|
Options options = NetworkUtils.getOptions(this.uri.getHost(), socketAddress);
|
||||||
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;
|
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;
|
||||||
|
|
||||||
|
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dan200.computercraft.core.apis.http.options;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class AddressRuleTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void matchesPort()
|
||||||
|
{
|
||||||
|
Iterable<AddressRule> rules = Collections.singletonList( AddressRule.parse(
|
||||||
|
"127.0.0.1", 8080,
|
||||||
|
new PartialOptions( Action.ALLOW, null, null, null, null )
|
||||||
|
) );
|
||||||
|
|
||||||
|
assertEquals( apply( rules, "localhost", 8080 ).action, Action.ALLOW );
|
||||||
|
assertEquals( apply( rules, "localhost", 8081 ).action, Action.DENY );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Options apply( Iterable<AddressRule> rules, String host, int port )
|
||||||
|
{
|
||||||
|
return AddressRule.apply( rules, host, new InetSocketAddress( host, port ) );
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user