Skip to content

Commit

Permalink
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueWall committed Mar 4, 2015
2 parents 9921c24 + 3255335 commit 369ccaf
Show file tree
Hide file tree
Showing 18 changed files with 683 additions and 48 deletions.
256 changes: 256 additions & 0 deletions OpenSim/Framework/Communications/OutboundUrlFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using log4net;
using LukeSkywalker.IPNetwork;
using Nini.Config;

namespace OpenSim.Framework.Communications
{
public class OutboundUrlFilter
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

public string Name { get; private set; }

private List<IPNetwork> m_blacklistNetworks;
private List<IPEndPoint> m_blacklistEndPoints;

private List<IPNetwork> m_blacklistExceptionNetworks;
private List<IPEndPoint> m_blacklistExceptionEndPoints;

public OutboundUrlFilter(
string name,
List<IPNetwork> blacklistNetworks, List<IPEndPoint> blacklistEndPoints,
List<IPNetwork> blacklistExceptionNetworks, List<IPEndPoint> blacklistExceptionEndPoints)
{
Name = name;

m_blacklistNetworks = blacklistNetworks;
m_blacklistEndPoints = blacklistEndPoints;
m_blacklistExceptionNetworks = blacklistExceptionNetworks;
m_blacklistExceptionEndPoints = blacklistExceptionEndPoints;
}

/// <summary>
/// Initializes a new instance of the <see cref="OpenSim.Framework.Communications.OutboundUrlFilter"/> class.
/// </summary>
/// <param name="name">Name of the filter for logging purposes.</param>
/// <param name="config">Filter configuration</param>
public OutboundUrlFilter(string name, IConfigSource config)
{
Name = name;

string configBlacklist
= "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";
string configBlacklistExceptions = "";

IConfig networkConfig = config.Configs["Network"];

if (networkConfig != null)
{
configBlacklist = networkConfig.GetString("OutboundDisallowForUserScripts", configBlacklist);
configBlacklistExceptions
= networkConfig.GetString("OutboundDisallowForUserScriptsExcept", configBlacklistExceptions);
}

m_log.DebugFormat(
"[OUTBOUND URL FILTER]: OutboundDisallowForUserScripts for {0} is [{1}]", Name, configBlacklist);
m_log.DebugFormat(
"[OUTBOUND URL FILTER]: OutboundDisallowForUserScriptsExcept for {0} is [{1}]", Name, configBlacklistExceptions);

OutboundUrlFilter.ParseConfigList(
configBlacklist, Name, out m_blacklistNetworks, out m_blacklistEndPoints);
OutboundUrlFilter.ParseConfigList(
configBlacklistExceptions, Name, out m_blacklistExceptionNetworks, out m_blacklistExceptionEndPoints);
}

private static void ParseConfigList(
string fullConfigEntry, string filterName, out List<IPNetwork> networks, out List<IPEndPoint> endPoints)
{
// Parse blacklist
string[] configBlacklistEntries
= fullConfigEntry.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

configBlacklistEntries = configBlacklistEntries.Select(e => e.Trim()).ToArray();

networks = new List<IPNetwork>();
endPoints = new List<IPEndPoint>();

foreach (string configEntry in configBlacklistEntries)
{
if (configEntry.Contains("/"))
{
IPNetwork network;

if (!IPNetwork.TryParse(configEntry, out network))
{
m_log.ErrorFormat(
"[OUTBOUND URL FILTER]: Entry [{0}] is invalid network for {1}", configEntry, filterName);

continue;
}

networks.Add(network);
}
else
{
Uri configEntryUri;

if (!Uri.TryCreate("http://" + configEntry, UriKind.Absolute, out configEntryUri))
{
m_log.ErrorFormat(
"[OUTBOUND URL FILTER]: EndPoint entry [{0}] is invalid endpoint for {1}",
configEntry, filterName);

continue;
}

IPAddress[] addresses = Dns.GetHostAddresses(configEntryUri.Host);

foreach (IPAddress addr in addresses)
{
if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}] in config", addr);

IPEndPoint configEntryEp = new IPEndPoint(addr, configEntryUri.Port);
endPoints.Add(configEntryEp);

// m_log.DebugFormat("[OUTBOUND URL FILTER]: Added blacklist exception [{0}]", configEntryEp);
}
}
}
}
}

/// <summary>
/// Determines if an url is in a list of networks and endpoints.
/// </summary>
/// <returns></returns>
/// <param name="url">IP address</param>
/// <param name="port"></param>
/// <param name="networks">Networks.</param>
/// <param name="endPoints">End points.</param>
/// <param name="filterName">Filter name.</param>
private static bool IsInNetwork(
IPAddress addr, int port, List<IPNetwork> networks, List<IPEndPoint> endPoints, string filterName)
{
foreach (IPNetwork ipn in networks)
{
// m_log.DebugFormat(
// "[OUTBOUND URL FILTER]: Checking [{0}] against network [{1}]", addr, ipn);

if (IPNetwork.Contains(ipn, addr))
{
// m_log.DebugFormat(
// "[OUTBOUND URL FILTER]: Found [{0}] in network [{1}]", addr, ipn);

return true;
}
}

// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);

foreach (IPEndPoint ep in endPoints)
{
// m_log.DebugFormat(
// "[OUTBOUND URL FILTER]: Checking [{0}:{1}] against endpoint [{2}]",
// addr, port, ep);

if (addr.Equals(ep.Address) && port == ep.Port)
{
// m_log.DebugFormat(
// "[OUTBOUND URL FILTER]: Found [{0}:{1}] in endpoint [{2}]", addr, port, ep);

return true;
}
}

// m_log.DebugFormat("[OUTBOUND URL FILTER]: Did not find [{0}:{1}] in list", addr, port);

return false;
}

/// <summary>
/// Checks whether the given url is allowed by the filter.
/// </summary>
/// <returns></returns>
public bool CheckAllowed(Uri url)
{
bool allowed = true;

// Check that we are permitted to make calls to this endpoint.
bool foundIpv4Address = false;

IPAddress[] addresses = Dns.GetHostAddresses(url.Host);

foreach (IPAddress addr in addresses)
{
if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);

foundIpv4Address = true;

// Check blacklist
if (OutboundUrlFilter.IsInNetwork(addr, url.Port, m_blacklistNetworks, m_blacklistEndPoints, Name))
{
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in blacklist for {1}", url, Name);

// Check blacklist exceptions
allowed
= OutboundUrlFilter.IsInNetwork(
addr, url.Port, m_blacklistExceptionNetworks, m_blacklistExceptionEndPoints, Name);

// if (allowed)
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in whitelist for {1}", url, Name);
}
}

// Found at least one address in a blacklist and not a blacklist exception
if (!allowed)
return false;
// else
// m_log.DebugFormat("[OUTBOUND URL FILTER]: URL [{0}] not in blacklist for {1}", url, Name);
}

// We do not know how to handle IPv6 securely yet.
if (!foundIpv4Address)
return false;

// m_log.DebugFormat("[OUTBOUND URL FILTER]: Allowing request [{0}]", url);

return allowed;
}
}
}
15 changes: 10 additions & 5 deletions OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,17 @@ public virtual byte[] Handle(
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
RequestsReceived++;
if (m_Auth != null && !m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader))

if (m_Auth != null)
{

httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized;
httpResponse.ContentType = "text/plain";
return new byte[0];
HttpStatusCode statusCode;

if (!m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader, out statusCode))
{
httpResponse.StatusCode = (int)statusCode;
httpResponse.ContentType = "text/plain";
return new byte[0];
}
}

byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
Expand Down
25 changes: 15 additions & 10 deletions OpenSim/Framework/ServiceAuth/BasicHttpAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Reflection;

using Nini.Config;
Expand Down Expand Up @@ -82,24 +83,28 @@ public bool Authenticate(string data)
return false;
}

public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d)
public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
{
//m_log.DebugFormat("[HTTP BASIC AUTH]: Authenticate in {0}", remove_me);
if (requestHeaders != null)
// m_log.DebugFormat("[HTTP BASIC AUTH]: Authenticate in {0}", "BasicHttpAuthentication");

string value = requestHeaders.Get("Authorization");
if (value != null)
{
string value = requestHeaders.Get("Authorization");
if (value != null)
value = value.Trim();
if (value.StartsWith("Basic "))
{
value = value.Trim();
if (value.StartsWith("Basic "))
value = value.Replace("Basic ", string.Empty);
if (Authenticate(value))
{
value = value.Replace("Basic ", string.Empty);
if (Authenticate(value))
return true;
statusCode = HttpStatusCode.OK;
return true;
}
}
}

d("WWW-Authenticate", "Basic realm = \"Asset Server\"");

statusCode = HttpStatusCode.Unauthorized;
return false;
}
}
Expand Down
Loading

0 comments on commit 369ccaf

Please sign in to comment.