diff --git a/src/main/java/li/cil/oc/util/InetAddressRange.java b/src/main/java/li/cil/oc/util/InetAddressRange.java index 03000a06b..3f1898cfe 100644 --- a/src/main/java/li/cil/oc/util/InetAddressRange.java +++ b/src/main/java/li/cil/oc/util/InetAddressRange.java @@ -41,7 +41,7 @@ public final class InetAddressRange { address = InetAddresses.forString(addressStr); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(String.format("Malformed address range entry '%s': Cannot extract IP address from '%s'.", - addressStr + '/' + prefixSizeStr, prefixSizeStr)); + addressStr + '/' + prefixSizeStr, addressStr)); } // Mask the bytes of the IP address. diff --git a/src/main/scala/li/cil/oc/OpenComputers.scala b/src/main/scala/li/cil/oc/OpenComputers.scala index 2a806113b..2f30be48f 100644 --- a/src/main/scala/li/cil/oc/OpenComputers.scala +++ b/src/main/scala/li/cil/oc/OpenComputers.scala @@ -61,8 +61,18 @@ object OpenComputers { CommandHandler.register(e) ThreadPoolFactory.safePools.foreach(_.newThreadPool()) - if (e.getServer.isDedicatedServer) { - if ((Settings.get.httpEnabled || Settings.get.tcpEnabled) && !Settings.get.internetFilteringRulesObserved) { + if (Settings.get.internetAccessConfigured()) { + if (Settings.get.internetFilteringRulesInvalid()) { + OpenComputers.log.warn("####################################################") + OpenComputers.log.warn("# #") + OpenComputers.log.warn("# Could not parse Internet Card filtering rules! #") + OpenComputers.log.warn("# Review the server log and adjust the filtering #") + OpenComputers.log.warn("# list to ensure it is appropriately configured. #") + OpenComputers.log.warn("# (config/OpenComputers.cfg => filteringRules) #") + OpenComputers.log.warn("# Internet access has been automatically disabled. #") + OpenComputers.log.warn("# #") + OpenComputers.log.warn("####################################################") + } else if (!Settings.get.internetFilteringRulesObserved && e.getServer.isDedicatedServer) { OpenComputers.log.warn("####################################################") OpenComputers.log.warn("# #") OpenComputers.log.warn("# It appears that you're running a dedicated #") @@ -72,6 +82,8 @@ object OpenComputers { OpenComputers.log.warn("# (config/OpenComputers.cfg => filteringRules) #") OpenComputers.log.warn("# #") OpenComputers.log.warn("####################################################") + } else { + OpenComputers.log.info(f"Successfully applied ${Settings.get.internetFilteringRules.length} Internet Card filtering rules.") } } } diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 5942d63ff..d64dfcd8f 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -487,6 +487,18 @@ class Settings(val config: Config) { val maxNetworkClientPacketDistance: Double = config.getDouble("misc.maxNetworkClientPacketDistance") max 0 val maxNetworkClientEffectPacketDistance: Double = config.getDouble("misc.maxNetworkClientEffectPacketDistance") max 0 val maxNetworkClientSoundPacketDistance: Double = config.getDouble("misc.maxNetworkClientSoundPacketDistance") max 0 + + def internetFilteringRulesInvalid(): Boolean = { + internetFilteringRules.exists(p => p.invalid()) + } + + def internetAccessConfigured(): Boolean = { + httpEnabled || tcpEnabled + } + + def internetAccessAllowed(): Boolean = { + internetAccessConfigured() && !internetFilteringRulesInvalid() + } } object Settings { diff --git a/src/main/scala/li/cil/oc/server/component/InternetCard.scala b/src/main/scala/li/cil/oc/server/component/InternetCard.scala index a9a77344b..e194216f1 100644 --- a/src/main/scala/li/cil/oc/server/component/InternetCard.scala +++ b/src/main/scala/li/cil/oc/server/component/InternetCard.scala @@ -64,6 +64,9 @@ class InternetCard extends prefab.ManagedEnvironment with DeviceInfo { def request(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { checkOwner(context) val address = args.checkString(0) + if (!Settings.get.internetAccessAllowed()) { + return result(Unit, "internet access is unavailable") + } if (!Settings.get.httpEnabled) { return result(Unit, "http requests are unavailable") } @@ -92,6 +95,9 @@ class InternetCard extends prefab.ManagedEnvironment with DeviceInfo { checkOwner(context) val address = args.checkString(0) val port = args.optInteger(1, -1) + if (!Settings.get.internetAccessAllowed()) { + return result(Unit, "internet access is unavailable") + } if (!Settings.get.tcpEnabled) { return result(Unit, "tcp connections are unavailable") } @@ -361,29 +367,33 @@ object InternetCard { } def isRequestAllowed(settings: Settings, inetAddress: InetAddress, host: String): Boolean = { - val rules = settings.internetFilteringRules - inetAddress match { - // IPv6 handling - case inet6Address: Inet6Address => - // If the IP address is an IPv6 address with an embedded IPv4 address, and the IPv4 address is blocked, - // block this request. - if (InetAddresses.hasEmbeddedIPv4ClientAddress(inet6Address)) { - val inet4in6Address = InetAddresses.getEmbeddedIPv4ClientAddress(inet6Address) - if (!rules.map(r => r.apply(inet4in6Address, host)).collectFirst({ case Some(r) => r }).getOrElse(true)) { - return false + if (!settings.internetAccessAllowed()) { + false + } else { + val rules = settings.internetFilteringRules + inetAddress match { + // IPv6 handling + case inet6Address: Inet6Address => + // If the IP address is an IPv6 address with an embedded IPv4 address, and the IPv4 address is blocked, + // block this request. + if (InetAddresses.hasEmbeddedIPv4ClientAddress(inet6Address)) { + val inet4in6Address = InetAddresses.getEmbeddedIPv4ClientAddress(inet6Address) + if (!rules.map(r => r.apply(inet4in6Address, host)).collectFirst({ case Some(r) => r }).getOrElse(true)) { + return false + } } - } - // Process address as an IPv6 address. - rules.map(r => r.apply(inet6Address, host)).collectFirst({ case Some(r) => r }).getOrElse(false) - // IPv4 handling - case inet4Address: Inet4Address => - // Process address as an IPv4 address. - rules.map(r => r.apply(inet4Address, host)).collectFirst({ case Some(r) => r }).getOrElse(false) - case _ => - // Unrecognized address type - block. - OpenComputers.log.warn("Internet Card blocked unrecognized address type: " + inetAddress.toString) - false + // Process address as an IPv6 address. + rules.map(r => r.apply(inet6Address, host)).collectFirst({ case Some(r) => r }).getOrElse(false) + // IPv4 handling + case inet4Address: Inet4Address => + // Process address as an IPv4 address. + rules.map(r => r.apply(inet4Address, host)).collectFirst({ case Some(r) => r }).getOrElse(false) + case _ => + // Unrecognized address type - block. + OpenComputers.log.warn("Internet Card blocked unrecognized address type: " + inetAddress.toString) + false + } } } diff --git a/src/main/scala/li/cil/oc/util/InternetFilteringRule.scala b/src/main/scala/li/cil/oc/util/InternetFilteringRule.scala index 83e842835..30837d7f7 100644 --- a/src/main/scala/li/cil/oc/util/InternetFilteringRule.scala +++ b/src/main/scala/li/cil/oc/util/InternetFilteringRule.scala @@ -7,7 +7,8 @@ import java.net.{Inet4Address, Inet6Address, InetAddress} import scala.collection.mutable class InternetFilteringRule(val ruleString: String) { - val validator: (InetAddress, String) => Option[Boolean] = { + private var _invalid: Boolean = false + private val validator: (InetAddress, String) => Option[Boolean] = { try { val ruleParts = ruleString.split(' ') ruleParts.head match { @@ -52,7 +53,7 @@ class InternetFilteringRule(val ruleString: String) { host == domain || addresses.exists(a => a.equals(inetAddress)) }) case "ip" => - val ipStringParts = f.split("/", 2) + val ipStringParts = filter(1).split("/", 2) if (ipStringParts.length == 2) { val ipRange = InetAddressRange.parse(ipStringParts(0), ipStringParts(1)) predicates += ((inetAddress: InetAddress, _: String) => ipRange.matches(inetAddress)) @@ -78,11 +79,14 @@ class InternetFilteringRule(val ruleString: String) { } } catch { case t: Throwable => - OpenComputers.log.warn("Invalid internet filtering rule in configuration: " + ruleString, t) - (_: InetAddress, _: String) => None + OpenComputers.log.error("Invalid Internet filteringRules rule in configuration: \"" + ruleString + "\".", t) + _invalid = true + (_: InetAddress, _: String) => Some(false) } } + def invalid(): Boolean = _invalid + def apply(inetAddress: InetAddress, host: String) = validator(inetAddress, host) }