using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net; namespace TorControlLibrary { public class ExitPolicy { public ExitPolicy() { } public ExitPolicy(String policy) { ParsePolicy(policy); } public void ParsePolicy(String policy) { int count = 0; StringReader sr = new StringReader(policy); while (true) { String line = sr.ReadLine(); if (String.IsNullOrEmpty(line)) break; Policy.Add(count++, new PolicyLine(line)); } } public Boolean IsAcceptableDestination(IPEndPoint destination) { return checkAddress((UInt32)System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt32(destination.Address.GetAddressBytes(), 0)), (UInt16)destination.Port); } public Boolean IsAcceptableDestination(IPAddress address, UInt16 port) { return checkAddress((UInt32)System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt32(address.GetAddressBytes(), 0)), port); } private Boolean checkAddress(UInt32 address, UInt16 port) { //the first match dictates the appropriate action for (int i = 0; i < Policy.Count; i++) { if (Policy[i].AddressRangeStart <= address && Policy[i].AddressRangeEnd >= address) if (Policy[i].PortRangeStart <= port && Policy[i].PortRangeEnd >= port) return Policy[i].Action.Equals("accept"); } return false; } private SortedList Policy = new SortedList(); class PolicyLine { public PolicyLine(String line) { Int32 ptr = line.IndexOf(' '); Action = line.Substring(0, ptr); ptr++; //Address String address = line.Substring(ptr, line.IndexOf(':') - ptr); if (address.Equals("*")) { AddressRangeStart = UInt32.MinValue; AddressRangeEnd = UInt32.MaxValue; } else { if (address.Contains("/")) { //range String[] rangeParts = address.Split('/'); System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse(rangeParts[0]); UInt32 mask = ((UInt32)0xFFFFFFFF << (32 - Int32.Parse(rangeParts[1]))); AddressRangeStart = BitConverter.ToUInt32(ipAddress.GetAddressBytes(), 0); //Cast to int to avoid long overload AddressRangeStart = (UInt32)System.Net.IPAddress.HostToNetworkOrder((int)AddressRangeStart); AddressRangeEnd = AddressRangeStart | ~(UInt32)mask; } else { //Single IP System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse(address); AddressRangeStart = BitConverter.ToUInt32(ipAddress.GetAddressBytes(),0); AddressRangeEnd = BitConverter.ToUInt32(ipAddress.GetAddressBytes(), 0); } } //Port ptr = line.IndexOf(':') + 1; String port = line.Substring(ptr); if (port.Equals("*")) { PortRangeStart = UInt16.MinValue; PortRangeEnd = UInt16.MaxValue; } else { if (port.Contains("-")) { //range String[] portParts = port.Split('-'); PortRangeStart = UInt16.Parse(portParts[0]); PortRangeEnd = UInt16.Parse(portParts[1]); } else { PortRangeStart = UInt16.Parse(port); PortRangeEnd = UInt16.Parse(port); } } } public String Action { get; set; } public UInt32 AddressRangeStart { get; set; } public UInt32 AddressRangeEnd { get; set; } public UInt16 PortRangeStart { get; set; } public UInt16 PortRangeEnd { get; set; } } } }