using Microsoft.AspNetCore.Http; using NetTools; using System; using System.Linq; using System.Net; using System.Collections.Generic; using Ablera.Serdica.Authentication.Utilities; using Ablera.Serdica.Authentication.Models.Oidc; using Ablera.Serdica.Common.Tools.Utilities; namespace Ablera.Serdica.Authority.Extensions; public static class AllowedMaskExtensions { // Lazily built the first time AllowedMaskExtensions is referenced. private static readonly IReadOnlyCollection AssociatedNetworks = ListeningNetworksRetriever.Retrieve(); public static AllowedMask? MergeWith(this AllowedMask? client, AllowedMask? global) => (client, global) switch { (null, null) => null, (null, _) => global, _ => new() { SameNetworks = client.SameNetworks ?? global?.SameNetworks, Networks = client.Networks ?? global?.Networks, Hosts = client.Hosts ?? global?.Hosts, Ports = client.Ports ?? global?.Ports } }; public static bool MatchesRemote(this AllowedMask allow, HttpContext http) { var remoteIp = http.Connection.RemoteIpAddress ?? IPAddress.None; var host = http.Request.Host.Host; var port = http.Request.Host.Port ?? 0; bool ipOk = allow.Networks == null || allow.Networks.Any(net => IPAddressRange.Parse(net).Contains(remoteIp)); bool hostOk = allow.Hosts == null || allow.Hosts.Any(h => StringComparer.OrdinalIgnoreCase.Equals(h, host)); bool portOk = allow.Ports == null || allow.Ports.Contains(port); // Same-network rule: only enforced when SameNetwork == true bool sameNetworkOk = allow.SameNetworks != true || // Flag not enabled → no restriction AssociatedNetworks == null || // Could not determine our own network AssociatedNetworks.Any(network => network.Contains(remoteIp)); return ipOk && hostOk && portOk && sameNetworkOk; } }