OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
OutboundUrlFilter.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Linq;
31 using System.Net;
32 using System.Reflection;
33 using log4net;
34 using LukeSkywalker.IPNetwork;
35 using Nini.Config;
36 
37 namespace OpenSim.Framework
38 {
39  public class OutboundUrlFilter
40  {
41  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 
43  public string Name { get; private set; }
44 
45  private List<IPNetwork> m_blacklistNetworks;
46  private List<IPEndPoint> m_blacklistEndPoints;
47 
48  private List<IPNetwork> m_blacklistExceptionNetworks;
49  private List<IPEndPoint> m_blacklistExceptionEndPoints;
50 
52  string name,
53  List<IPNetwork> blacklistNetworks, List<IPEndPoint> blacklistEndPoints,
54  List<IPNetwork> blacklistExceptionNetworks, List<IPEndPoint> blacklistExceptionEndPoints)
55  {
56  Name = name;
57 
58  m_blacklistNetworks = blacklistNetworks;
59  m_blacklistEndPoints = blacklistEndPoints;
60  m_blacklistExceptionNetworks = blacklistExceptionNetworks;
61  m_blacklistExceptionEndPoints = blacklistExceptionEndPoints;
62  }
63 
69  public OutboundUrlFilter(string name, IConfigSource config)
70  {
71  Name = name;
72 
73  string configBlacklist
74  = "0.0.0.0/8|10.0.0.0/8|100.64.0.0/10|127.0.0.0/8|169.254.0.0/16|172.16.0.0/12|192.0.0.0/24|192.0.2.0/24|192.88.99.0/24|192.168.0.0/16|198.18.0.0/15|198.51.100.0/24|203.0.113.0/24|224.0.0.0/4|240.0.0.0/4|255.255.255.255/32";
75  string configBlacklistExceptions = "";
76 
77  IConfig networkConfig = config.Configs["Network"];
78 
79  if (networkConfig != null)
80  {
81  configBlacklist = networkConfig.GetString("OutboundDisallowForUserScripts", configBlacklist);
82  configBlacklistExceptions
83  = networkConfig.GetString("OutboundDisallowForUserScriptsExcept", configBlacklistExceptions);
84  }
85 
86  m_log.DebugFormat(
87  "[OUTBOUND URL FILTER]: OutboundDisallowForUserScripts for {0} is [{1}]", Name, configBlacklist);
88  m_log.DebugFormat(
89  "[OUTBOUND URL FILTER]: OutboundDisallowForUserScriptsExcept for {0} is [{1}]", Name, configBlacklistExceptions);
90 
91  OutboundUrlFilter.ParseConfigList(
92  configBlacklist, Name, out m_blacklistNetworks, out m_blacklistEndPoints);
93  OutboundUrlFilter.ParseConfigList(
94  configBlacklistExceptions, Name, out m_blacklistExceptionNetworks, out m_blacklistExceptionEndPoints);
95  }
96 
97  private static void ParseConfigList(
98  string fullConfigEntry, string filterName, out List<IPNetwork> networks, out List<IPEndPoint> endPoints)
99  {
100  // Parse blacklist
101  string[] configBlacklistEntries
102  = fullConfigEntry.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
103 
104  configBlacklistEntries = configBlacklistEntries.Select(e => e.Trim()).ToArray();
105 
106  networks = new List<IPNetwork>();
107  endPoints = new List<IPEndPoint>();
108 
109  foreach (string configEntry in configBlacklistEntries)
110  {
111  if (configEntry.Contains("/"))
112  {
113  IPNetwork network;
114 
115  if (!IPNetwork.TryParse(configEntry, out network))
116  {
117  m_log.ErrorFormat(
118  "[OUTBOUND URL FILTER]: Entry [{0}] is invalid network for {1}", configEntry, filterName);
119 
120  continue;
121  }
122 
123  networks.Add(network);
124  }
125  else
126  {
127  Uri configEntryUri;
128 
129  if (!Uri.TryCreate("http://" + configEntry, UriKind.Absolute, out configEntryUri))
130  {
131  m_log.ErrorFormat(
132  "[OUTBOUND URL FILTER]: EndPoint entry [{0}] is invalid endpoint for {1}",
133  configEntry, filterName);
134 
135  continue;
136  }
137 
138  IPAddress[] addresses = Dns.GetHostAddresses(configEntryUri.Host);
139 
140  foreach (IPAddress addr in addresses)
141  {
142  if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
143  {
144  // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}] in config", addr);
145 
146  IPEndPoint configEntryEp = new IPEndPoint(addr, configEntryUri.Port);
147  endPoints.Add(configEntryEp);
148 
149  // m_log.DebugFormat("[OUTBOUND URL FILTER]: Added blacklist exception [{0}]", configEntryEp);
150  }
151  }
152  }
153  }
154  }
155 
165  private static bool IsInNetwork(
166  IPAddress addr, int port, List<IPNetwork> networks, List<IPEndPoint> endPoints, string filterName)
167  {
168  foreach (IPNetwork ipn in networks)
169  {
170 // m_log.DebugFormat(
171 // "[OUTBOUND URL FILTER]: Checking [{0}] against network [{1}]", addr, ipn);
172 
173  if (IPNetwork.Contains(ipn, addr))
174  {
175 // m_log.DebugFormat(
176 // "[OUTBOUND URL FILTER]: Found [{0}] in network [{1}]", addr, ipn);
177 
178  return true;
179  }
180  }
181 
182  // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);
183 
184  foreach (IPEndPoint ep in endPoints)
185  {
186 // m_log.DebugFormat(
187 // "[OUTBOUND URL FILTER]: Checking [{0}:{1}] against endpoint [{2}]",
188 // addr, port, ep);
189 
190  if (addr.Equals(ep.Address) && port == ep.Port)
191  {
192 // m_log.DebugFormat(
193 // "[OUTBOUND URL FILTER]: Found [{0}:{1}] in endpoint [{2}]", addr, port, ep);
194 
195  return true;
196  }
197  }
198 
199 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Did not find [{0}:{1}] in list", addr, port);
200 
201  return false;
202  }
203 
208  public bool CheckAllowed(Uri url)
209  {
210  bool allowed = true;
211 
212  // Check that we are permitted to make calls to this endpoint.
213  bool foundIpv4Address = false;
214 
215  IPAddress[] addresses = Dns.GetHostAddresses(url.Host);
216 
217  foreach (IPAddress addr in addresses)
218  {
219  if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
220  {
221 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);
222 
223  foundIpv4Address = true;
224 
225  // Check blacklist
226  if (OutboundUrlFilter.IsInNetwork(addr, url.Port, m_blacklistNetworks, m_blacklistEndPoints, Name))
227  {
228 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in blacklist for {1}", url, Name);
229 
230  // Check blacklist exceptions
231  allowed
232  = OutboundUrlFilter.IsInNetwork(
233  addr, url.Port, m_blacklistExceptionNetworks, m_blacklistExceptionEndPoints, Name);
234 
235 // if (allowed)
236 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in whitelist for {1}", url, Name);
237  }
238  }
239 
240  // Found at least one address in a blacklist and not a blacklist exception
241  if (!allowed)
242  return false;
243 // else
244 // m_log.DebugFormat("[OUTBOUND URL FILTER]: URL [{0}] not in blacklist for {1}", url, Name);
245  }
246 
247  // We do not know how to handle IPv6 securely yet.
248  if (!foundIpv4Address)
249  return false;
250 
251 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Allowing request [{0}]", url);
252 
253  return allowed;
254  }
255  }
256 }
bool CheckAllowed(Uri url)
Checks whether the given url is allowed by the filter.
OutboundUrlFilter(string name, List< IPNetwork > blacklistNetworks, List< IPEndPoint > blacklistEndPoints, List< IPNetwork > blacklistExceptionNetworks, List< IPEndPoint > blacklistExceptionEndPoints)
OutboundUrlFilter(string name, IConfigSource config)
Initializes a new instance of the OpenSim.Framework.OutboundUrlFilter class.