Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
369ccaf1eb
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,13 +56,18 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
{
|
{
|
||||||
RequestsReceived++;
|
RequestsReceived++;
|
||||||
if (m_Auth != null && !m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader))
|
|
||||||
{
|
|
||||||
|
|
||||||
httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized;
|
if (m_Auth != null)
|
||||||
|
{
|
||||||
|
HttpStatusCode statusCode;
|
||||||
|
|
||||||
|
if (!m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader, out statusCode))
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)statusCode;
|
||||||
httpResponse.ContentType = "text/plain";
|
httpResponse.ContentType = "text/plain";
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
|
byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
@ -82,11 +83,10 @@ namespace OpenSim.Framework.ServiceAuth
|
||||||
return false;
|
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");
|
string value = requestHeaders.Get("Authorization");
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
|
@ -95,11 +95,16 @@ namespace OpenSim.Framework.ServiceAuth
|
||||||
{
|
{
|
||||||
value = value.Replace("Basic ", string.Empty);
|
value = value.Replace("Basic ", string.Empty);
|
||||||
if (Authenticate(value))
|
if (Authenticate(value))
|
||||||
|
{
|
||||||
|
statusCode = HttpStatusCode.OK;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d("WWW-Authenticate", "Basic realm = \"Asset Server\"");
|
d("WWW-Authenticate", "Basic realm = \"Asset Server\"");
|
||||||
|
|
||||||
|
statusCode = HttpStatusCode.Unauthorized;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.ServiceAuth
|
||||||
|
{
|
||||||
|
public class CompoundAuthentication : IServiceAuth
|
||||||
|
{
|
||||||
|
private List<IServiceAuth> m_authentications = new List<IServiceAuth>();
|
||||||
|
|
||||||
|
public int Count { get { return m_authentications.Count; } }
|
||||||
|
|
||||||
|
public void AddAuthenticator(IServiceAuth auth)
|
||||||
|
{
|
||||||
|
m_authentications.Add(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAuthenticator(IServiceAuth auth)
|
||||||
|
{
|
||||||
|
m_authentications.Remove(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAuthorization(NameValueCollection headers) {}
|
||||||
|
|
||||||
|
public bool Authenticate(string data)
|
||||||
|
{
|
||||||
|
return m_authentications.TrueForAll(a => a.Authenticate(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
|
||||||
|
{
|
||||||
|
foreach (IServiceAuth auth in m_authentications)
|
||||||
|
{
|
||||||
|
if (!auth.Authenticate(requestHeaders, d, out statusCode))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusCode = HttpStatusCode.OK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.Specialized;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.ServiceAuth
|
||||||
|
{
|
||||||
|
public class DisallowLlHttpRequest : IServiceAuth
|
||||||
|
{
|
||||||
|
public void AddAuthorization(NameValueCollection headers) {}
|
||||||
|
|
||||||
|
public bool Authenticate(string data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("DisallowLlHttpRequest");
|
||||||
|
|
||||||
|
if (requestHeaders["X-SecondLife-Shard"] != null)
|
||||||
|
{
|
||||||
|
statusCode = HttpStatusCode.Forbidden;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusCode = HttpStatusCode.OK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ namespace OpenSim.Framework.ServiceAuth
|
||||||
public interface IServiceAuth
|
public interface IServiceAuth
|
||||||
{
|
{
|
||||||
bool Authenticate(string data);
|
bool Authenticate(string data);
|
||||||
bool Authenticate(NameValueCollection headers, AddHeaderDelegate d);
|
bool Authenticate(NameValueCollection headers, AddHeaderDelegate d, out HttpStatusCode statusCode);
|
||||||
void AddAuthorization(NameValueCollection headers);
|
void AddAuthorization(NameValueCollection headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,26 @@ namespace OpenSim.Framework.ServiceAuth
|
||||||
{
|
{
|
||||||
public static IServiceAuth Create(IConfigSource config, string section)
|
public static IServiceAuth Create(IConfigSource config, string section)
|
||||||
{
|
{
|
||||||
|
CompoundAuthentication compoundAuth = new CompoundAuthentication();
|
||||||
|
|
||||||
|
bool allowLlHttpRequestIn
|
||||||
|
= Util.GetConfigVarFromSections<bool>(config, "AllowllHTTPRequestIn", new string[] { "Network", section }, false);
|
||||||
|
|
||||||
|
if (!allowLlHttpRequestIn)
|
||||||
|
compoundAuth.AddAuthenticator(new DisallowLlHttpRequest());
|
||||||
|
|
||||||
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", section }, "None");
|
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", section }, "None");
|
||||||
|
|
||||||
switch (authType)
|
switch (authType)
|
||||||
{
|
{
|
||||||
case "BasicHttpAuthentication":
|
case "BasicHttpAuthentication":
|
||||||
return new BasicHttpAuthentication(config, section);
|
compoundAuth.AddAuthenticator(new BasicHttpAuthentication(config, section));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compoundAuth.Count > 0)
|
||||||
|
return compoundAuth;
|
||||||
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ using log4net;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
using OpenSim.Framework.Servers;
|
using OpenSim.Framework.Servers;
|
||||||
using OpenSim.Framework.Servers.HttpServer;
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
@ -94,10 +95,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
|
||||||
public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
|
public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
|
||||||
{
|
{
|
||||||
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private object HttpListLock = new object();
|
private object HttpListLock = new object();
|
||||||
private int httpTimeout = 30000;
|
private int httpTimeout = 30000;
|
||||||
private string m_name = "HttpScriptRequests";
|
private string m_name = "HttpScriptRequests";
|
||||||
|
|
||||||
|
private OutboundUrlFilter m_outboundUrlFilter;
|
||||||
private string m_proxyurl = "";
|
private string m_proxyurl = "";
|
||||||
private string m_proxyexcepts = "";
|
private string m_proxyexcepts = "";
|
||||||
|
|
||||||
|
@ -156,7 +160,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
return UUID.Zero;
|
return UUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID StartHttpRequest(uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body)
|
public UUID StartHttpRequest(
|
||||||
|
uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body,
|
||||||
|
out HttpInitialRequestStatus status)
|
||||||
{
|
{
|
||||||
UUID reqID = UUID.Random();
|
UUID reqID = UUID.Random();
|
||||||
HttpRequestClass htc = new HttpRequestClass();
|
HttpRequestClass htc = new HttpRequestClass();
|
||||||
|
@ -233,6 +239,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
htc.RequestModule = this;
|
||||||
htc.LocalID = localID;
|
htc.LocalID = localID;
|
||||||
htc.ItemID = itemID;
|
htc.ItemID = itemID;
|
||||||
htc.Url = url;
|
htc.Url = url;
|
||||||
|
@ -243,14 +250,43 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
htc.proxyurl = m_proxyurl;
|
htc.proxyurl = m_proxyurl;
|
||||||
htc.proxyexcepts = m_proxyexcepts;
|
htc.proxyexcepts = m_proxyexcepts;
|
||||||
|
|
||||||
lock (HttpListLock)
|
// Same number as default HttpWebRequest.MaximumAutomaticRedirections
|
||||||
|
htc.MaxRedirects = 50;
|
||||||
|
|
||||||
|
if (StartHttpRequest(htc))
|
||||||
{
|
{
|
||||||
m_pendingRequests.Add(reqID, htc);
|
status = HttpInitialRequestStatus.OK;
|
||||||
|
return htc.ReqID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
|
||||||
|
return UUID.Zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
htc.Process();
|
/// <summary>
|
||||||
|
/// Would a caller to this module be allowed to make a request to the given URL?
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool CheckAllowed(Uri url)
|
||||||
|
{
|
||||||
|
return m_outboundUrlFilter.CheckAllowed(url);
|
||||||
|
}
|
||||||
|
|
||||||
return reqID;
|
public bool StartHttpRequest(HttpRequestClass req)
|
||||||
|
{
|
||||||
|
if (!CheckAllowed(new Uri(req.Url)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lock (HttpListLock)
|
||||||
|
{
|
||||||
|
m_pendingRequests.Add(req.ReqID, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Process();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopHttpRequestsForScript(UUID id)
|
public void StopHttpRequestsForScript(UUID id)
|
||||||
|
@ -326,6 +362,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
||||||
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
||||||
|
|
||||||
|
m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
|
||||||
|
|
||||||
m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
|
m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HttpRequestClass: IServiceRequest
|
public class HttpRequestClass : IServiceRequest
|
||||||
{
|
{
|
||||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
@ -380,6 +418,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
// public const int HTTP_VERBOSE_THROTTLE = 4;
|
// public const int HTTP_VERBOSE_THROTTLE = 4;
|
||||||
// public const int HTTP_CUSTOM_HEADER = 5;
|
// public const int HTTP_CUSTOM_HEADER = 5;
|
||||||
// public const int HTTP_PRAGMA_NO_CACHE = 6;
|
// public const int HTTP_PRAGMA_NO_CACHE = 6;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Module that made this request.
|
||||||
|
/// </summary>
|
||||||
|
public HttpRequestModule RequestModule { get; set; }
|
||||||
|
|
||||||
private bool _finished;
|
private bool _finished;
|
||||||
public bool Finished
|
public bool Finished
|
||||||
{
|
{
|
||||||
|
@ -412,6 +456,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
public DateTime Next;
|
public DateTime Next;
|
||||||
public string proxyurl;
|
public string proxyurl;
|
||||||
public string proxyexcepts;
|
public string proxyexcepts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of HTTP redirects that this request has been through.
|
||||||
|
/// </summary>
|
||||||
|
public int Redirects { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of HTTP redirects allowed for this request.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxRedirects { get; set; }
|
||||||
|
|
||||||
public string OutboundBody;
|
public string OutboundBody;
|
||||||
private UUID _reqID;
|
private UUID _reqID;
|
||||||
public UUID ReqID
|
public UUID ReqID
|
||||||
|
@ -419,7 +474,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
get { return _reqID; }
|
get { return _reqID; }
|
||||||
set { _reqID = value; }
|
set { _reqID = value; }
|
||||||
}
|
}
|
||||||
public WebRequest Request;
|
public HttpWebRequest Request;
|
||||||
public string ResponseBody;
|
public string ResponseBody;
|
||||||
public List<string> ResponseMetadata;
|
public List<string> ResponseMetadata;
|
||||||
public Dictionary<string, string> ResponseHeaders;
|
public Dictionary<string, string> ResponseHeaders;
|
||||||
|
@ -435,7 +490,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Request = WebRequest.Create(Url);
|
Request = (HttpWebRequest)WebRequest.Create(Url);
|
||||||
|
Request.AllowAutoRedirect = false;
|
||||||
Request.Method = HttpMethod;
|
Request.Method = HttpMethod;
|
||||||
Request.ContentType = HttpMIMEType;
|
Request.ContentType = HttpMIMEType;
|
||||||
|
|
||||||
|
@ -450,16 +506,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
// {
|
// {
|
||||||
// Request.ConnectionGroupName="Verify";
|
// Request.ConnectionGroupName="Verify";
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (!HttpPragmaNoCache)
|
if (!HttpPragmaNoCache)
|
||||||
{
|
{
|
||||||
Request.Headers.Add("Pragma", "no-cache");
|
Request.Headers.Add("Pragma", "no-cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HttpCustomHeaders != null)
|
if (HttpCustomHeaders != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < HttpCustomHeaders.Count; i += 2)
|
for (int i = 0; i < HttpCustomHeaders.Count; i += 2)
|
||||||
Request.Headers.Add(HttpCustomHeaders[i],
|
Request.Headers.Add(HttpCustomHeaders[i],
|
||||||
HttpCustomHeaders[i+1]);
|
HttpCustomHeaders[i+1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(proxyurl))
|
if (!string.IsNullOrEmpty(proxyurl))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(proxyexcepts))
|
if (!string.IsNullOrEmpty(proxyexcepts))
|
||||||
|
@ -565,8 +624,53 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
if (response != null)
|
if (response != null)
|
||||||
response.Close();
|
response.Close();
|
||||||
|
|
||||||
|
// We need to resubmit
|
||||||
|
if (
|
||||||
|
(Status == (int)HttpStatusCode.MovedPermanently
|
||||||
|
|| Status == (int)HttpStatusCode.Found
|
||||||
|
|| Status == (int)HttpStatusCode.SeeOther
|
||||||
|
|| Status == (int)HttpStatusCode.TemporaryRedirect))
|
||||||
|
{
|
||||||
|
if (Redirects >= MaxRedirects)
|
||||||
|
{
|
||||||
|
Status = (int)OSHttpStatusCode.ClientErrorJoker;
|
||||||
|
ResponseBody = "Number of redirects exceeded max redirects";
|
||||||
_finished = true;
|
_finished = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string location = response.Headers["Location"];
|
||||||
|
|
||||||
|
if (location == null)
|
||||||
|
{
|
||||||
|
Status = (int)OSHttpStatusCode.ClientErrorJoker;
|
||||||
|
ResponseBody = "HTTP redirect code but no location header";
|
||||||
|
_finished = true;
|
||||||
|
}
|
||||||
|
else if (!RequestModule.CheckAllowed(new Uri(location)))
|
||||||
|
{
|
||||||
|
Status = (int)OSHttpStatusCode.ClientErrorJoker;
|
||||||
|
ResponseBody = "URL from HTTP redirect blocked: " + location;
|
||||||
|
_finished = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = 0;
|
||||||
|
Url = response.Headers["Location"];
|
||||||
|
Redirects++;
|
||||||
|
ResponseBody = null;
|
||||||
|
|
||||||
|
// m_log.DebugFormat("Redirecting to [{0}]", Url);
|
||||||
|
|
||||||
|
Process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimeoutCallback(object state, bool timedOut)
|
private void TimeoutCallback(object state, bool timedOut)
|
||||||
|
|
|
@ -146,11 +146,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Test what happens when we get a 404 response from a call.
|
/// Test what happens when we get a 404 response from a call.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
// [Test]
|
||||||
public void Test404Response()
|
public void Test404Response()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
TestHelpers.EnableLogging();
|
||||||
|
|
||||||
if (!Util.IsPlatformMono)
|
if (!Util.IsPlatformMono)
|
||||||
Assert.Ignore("Ignoring test since can only currently run on Mono");
|
Assert.Ignore("Ignoring test since can only currently run on Mono");
|
||||||
|
|
|
@ -32,6 +32,7 @@ using System.Net;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.Imaging;
|
using OpenMetaverse.Imaging;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
@ -50,6 +51,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private IDynamicTextureManager m_textureManager;
|
private IDynamicTextureManager m_textureManager;
|
||||||
|
|
||||||
|
private OutboundUrlFilter m_outboundUrlFilter;
|
||||||
private string m_proxyurl = "";
|
private string m_proxyurl = "";
|
||||||
private string m_proxyexcepts = "";
|
private string m_proxyexcepts = "";
|
||||||
|
|
||||||
|
@ -88,8 +90,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
|
|
||||||
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
|
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
|
||||||
{
|
{
|
||||||
MakeHttpRequest(url, id);
|
return MakeHttpRequest(url, id);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
|
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
|
||||||
|
@ -110,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
|
|
||||||
public void Initialise(IConfigSource config)
|
public void Initialise(IConfigSource config)
|
||||||
{
|
{
|
||||||
|
m_outboundUrlFilter = new OutboundUrlFilter("Script dynamic texture image module", config);
|
||||||
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
||||||
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
||||||
}
|
}
|
||||||
|
@ -157,9 +159,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void MakeHttpRequest(string url, UUID requestID)
|
private bool MakeHttpRequest(string url, UUID requestID)
|
||||||
{
|
{
|
||||||
WebRequest request = HttpWebRequest.Create(url);
|
if (!m_outboundUrlFilter.CheckAllowed(new Uri(url)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||||
|
request.AllowAutoRedirect = false;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(m_proxyurl))
|
if (!string.IsNullOrEmpty(m_proxyurl))
|
||||||
{
|
{
|
||||||
|
@ -174,12 +180,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestState state = new RequestState((HttpWebRequest) request, requestID);
|
RequestState state = new RequestState(request, requestID);
|
||||||
// IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
// IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
||||||
request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
||||||
|
|
||||||
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
|
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
|
||||||
state.TimeOfRequest = (int) t.TotalSeconds;
|
state.TimeOfRequest = (int) t.TotalSeconds;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HttpRequestReturn(IAsyncResult result)
|
private void HttpRequestReturn(IAsyncResult result)
|
||||||
|
@ -195,10 +203,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
Stream stream = null;
|
Stream stream = null;
|
||||||
byte[] imageJ2000 = new byte[0];
|
byte[] imageJ2000 = new byte[0];
|
||||||
Size newSize = new Size(0, 0);
|
Size newSize = new Size(0, 0);
|
||||||
|
HttpWebResponse response = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
|
response = (HttpWebResponse)request.EndGetResponse(result);
|
||||||
if (response != null && response.StatusCode == HttpStatusCode.OK)
|
if (response != null && response.StatusCode == HttpStatusCode.OK)
|
||||||
{
|
{
|
||||||
stream = response.GetResponseStream();
|
stream = response.GetResponseStream();
|
||||||
|
@ -262,11 +271,23 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
{
|
|
||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (response != null)
|
||||||
|
response.Close();
|
||||||
|
|
||||||
|
if (
|
||||||
|
response.StatusCode == HttpStatusCode.MovedPermanently
|
||||||
|
|| response.StatusCode == HttpStatusCode.Found
|
||||||
|
|| response.StatusCode == HttpStatusCode.SeeOther
|
||||||
|
|| response.StatusCode == HttpStatusCode.TemporaryRedirect)
|
||||||
|
{
|
||||||
|
string redirectedUrl = response.Headers["Location"];
|
||||||
|
|
||||||
|
MakeHttpRequest(redirectedUrl, state.RequestID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
|
m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
|
||||||
imageJ2000.Length, state.RequestID);
|
imageJ2000.Length, state.RequestID);
|
||||||
|
|
||||||
|
@ -275,6 +296,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||||
new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
||||||
request.RequestUri, null, imageJ2000, newSize, false));
|
request.RequestUri, null, imageJ2000, newSize, false));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Nested type: RequestState
|
#region Nested type: RequestState
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
@ -41,10 +42,44 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
HTTP_PRAGMA_NO_CACHE = 6
|
HTTP_PRAGMA_NO_CACHE = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The initial status of the request before it is placed on the wire.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The request may still fail later on, in which case the normal HTTP status is set.
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum HttpInitialRequestStatus
|
||||||
|
{
|
||||||
|
OK = 1,
|
||||||
|
DISALLOWED_BY_FILTER = 2
|
||||||
|
}
|
||||||
|
|
||||||
public interface IHttpRequestModule
|
public interface IHttpRequestModule
|
||||||
{
|
{
|
||||||
UUID MakeHttpRequest(string url, string parameters, string body);
|
UUID MakeHttpRequest(string url, string parameters, string body);
|
||||||
UUID StartHttpRequest(uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts the http request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is carried out asynchronously unless it fails initial checks. Results are fetched by the script engine
|
||||||
|
/// HTTP requests module to be distributed back to scripts via a script event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The ID of the request. If the requested could not be performed then this is UUID.Zero</returns>
|
||||||
|
/// <param name="localID">Local ID of the object containing the script making the request.</param>
|
||||||
|
/// <param name="itemID">Item ID of the script making the request.</param>
|
||||||
|
/// <param name="url">Url to request.</param>
|
||||||
|
/// <param name="parameters">LSL parameters for the request.</param>
|
||||||
|
/// <param name="headers">Extra headers for the request.</param>
|
||||||
|
/// <param name="body">Body of the request.</param>
|
||||||
|
/// <param name="status">
|
||||||
|
/// Initial status of the request. If OK then the request is actually made to the URL. Subsequent status is
|
||||||
|
/// then returned via IServiceRequest when the response is asynchronously fetched.
|
||||||
|
/// </param>
|
||||||
|
UUID StartHttpRequest(
|
||||||
|
uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body,
|
||||||
|
out HttpInitialRequestStatus status);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop and remove all http requests for the given script.
|
/// Stop and remove all http requests for the given script.
|
||||||
|
|
|
@ -12240,8 +12240,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpInitialRequestStatus status;
|
||||||
UUID reqID
|
UUID reqID
|
||||||
= httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body);
|
= httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
|
||||||
|
|
||||||
|
if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
|
||||||
|
Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
|
||||||
|
|
||||||
if (reqID != UUID.Zero)
|
if (reqID != UUID.Zero)
|
||||||
return reqID.ToString();
|
return reqID.ToString();
|
||||||
|
|
Binary file not shown.
|
@ -486,6 +486,32 @@
|
||||||
;; the region ports use UDP.
|
;; the region ports use UDP.
|
||||||
; http_listener_port = 9000
|
; http_listener_port = 9000
|
||||||
|
|
||||||
|
; By default, OpenSimulator does not allow scripts to make HTTP calls to addresses on the simulator's LAN.
|
||||||
|
; See the OutboundDisallowForUserScripts parameter in OpenSimDefaults.ini for more information on this filter.
|
||||||
|
; If you need to allow scripts to make some LAN calls use the OutboundDisallowForUserScriptsExcept parameter below.
|
||||||
|
; We recommend that you do not override OutboundDisallowForUserScripts directly unless you are very sure about what you're doing.
|
||||||
|
;
|
||||||
|
; You can whitelist individual endpoints by IP or FQDN, e.g.
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScriptsExcept = 192.168.1.3:8003
|
||||||
|
;
|
||||||
|
; You can specify multiple addresses by separating them with a bar. For example,
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScriptsExcept = 192.168.1.3:8003|myinternalserver:8000
|
||||||
|
;
|
||||||
|
; If an address if given without a port number then port 80 is assumed
|
||||||
|
;
|
||||||
|
; You can also specify a network range in CIDR notation to whitelist, e.g.
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScriptsExcept = 192.168.1.0/24
|
||||||
|
;
|
||||||
|
; to whitelist all ports on addresses 192.168.1.0 to 192.168.1.255
|
||||||
|
; To specify an individual IP address use the /32 netmask
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScriptsExcept = 192.168.1.2/32
|
||||||
|
;
|
||||||
|
; See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation for more information on CIDR notation
|
||||||
|
|
||||||
;# {ExternalHostNameForLSL} {} {Hostname to use for HTTP-IN URLs. This should be reachable from the internet.} {}
|
;# {ExternalHostNameForLSL} {} {Hostname to use for HTTP-IN URLs. This should be reachable from the internet.} {}
|
||||||
;; Hostname to use in llRequestURL/llRequestSecureURL
|
;; Hostname to use in llRequestURL/llRequestSecureURL
|
||||||
;; if not defined - default machine name is being used
|
;; if not defined - default machine name is being used
|
||||||
|
|
|
@ -492,6 +492,26 @@
|
||||||
; (on Windows this mean NETBIOS name - useably only inside local network)
|
; (on Windows this mean NETBIOS name - useably only inside local network)
|
||||||
; ExternalHostNameForLSL=127.0.0.1
|
; ExternalHostNameForLSL=127.0.0.1
|
||||||
|
|
||||||
|
; Disallow the following address ranges for user scripting calls (e.g. llHttpRequest())
|
||||||
|
; This is based on http://en.wikipedia.org/wiki/Reserved_IP_addresses
|
||||||
|
; This stops users making HTTP calls to machines in the simulator's local network.
|
||||||
|
; If you need to allow some LAN calls we recommend you use OutboundDisallowForUserScriptsExcept documented in OpenSim.ini.example
|
||||||
|
; If you override OutboundDisallowForUserScripts directly you need to be very careful.
|
||||||
|
;
|
||||||
|
; Network ranges are specified in CIDR notation (http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation) with multiple entries separated by |
|
||||||
|
; To specify an individual IP address use the /32 netmask (e.g. 192.168.1.3/32)
|
||||||
|
; You can also specify individual <addr>:<port> endpoints (e.g. 192.168.1.3:8003)
|
||||||
|
; If an address if given without a port number then port 80 is assumed.
|
||||||
|
OutboundDisallowForUserScripts = 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
|
||||||
|
;
|
||||||
|
; You can also prevent all user script outgoing calls with the following override in OpenSim.ini
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScripts = 0.0.0.0/0
|
||||||
|
;
|
||||||
|
; You can also disable the blacklist entirely with an empty entry
|
||||||
|
;
|
||||||
|
; OutboundDisallowForUserScripts = ""
|
||||||
|
|
||||||
; What is reported as the "X-Secondlife-Shard"
|
; What is reported as the "X-Secondlife-Shard"
|
||||||
; Defaults to the user server url if not set
|
; Defaults to the user server url if not set
|
||||||
; The old default is "OpenSim", set here for compatibility
|
; The old default is "OpenSim", set here for compatibility
|
||||||
|
|
|
@ -153,6 +153,13 @@
|
||||||
;; Hypergrid services are not affected by this; they are publicly available
|
;; Hypergrid services are not affected by this; they are publicly available
|
||||||
;; by design.
|
;; by design.
|
||||||
|
|
||||||
|
;; By default, scripts are not allowed to call private services via llHttpRequest()
|
||||||
|
;; Such calls are detected by the X-SecondLife-Shared HTTP header
|
||||||
|
;; If you allow such calls you must be sure that they are restricted to very trusted scripters
|
||||||
|
;; (remember scripts can also be in visiting avatar attachments).
|
||||||
|
;; This can be overriden in individual private service sections if necessary
|
||||||
|
AllowllHTTPRequestIn = false
|
||||||
|
|
||||||
; * The following are for the remote console
|
; * The following are for the remote console
|
||||||
; * They have no effect for the local or basic console types
|
; * They have no effect for the local or basic console types
|
||||||
; * Leave commented to diable logins to the console
|
; * Leave commented to diable logins to the console
|
||||||
|
|
|
@ -130,6 +130,13 @@
|
||||||
;; but unprotect individual services. Username and Password can also be
|
;; but unprotect individual services. Username and Password can also be
|
||||||
;; overriden if you want to use different credentials for the different services.
|
;; overriden if you want to use different credentials for the different services.
|
||||||
|
|
||||||
|
;; By default, scripts are not allowed to call private services via llHttpRequest()
|
||||||
|
;; Such calls are detected by the X-SecondLife-Shared HTTP header
|
||||||
|
;; If you allow such calls you must be sure that they are restricted to very trusted scripters
|
||||||
|
;; (remember scripts can also be in visiting avatar attachments).
|
||||||
|
;; This can be overriden in individual private service sections if necessary
|
||||||
|
AllowllHTTPRequestIn = false
|
||||||
|
|
||||||
; * The following are for the remote console
|
; * The following are for the remote console
|
||||||
; * They have no effect for the local or basic console types
|
; * They have no effect for the local or basic console types
|
||||||
; * Leave commented to diable logins to the console
|
; * Leave commented to diable logins to the console
|
||||||
|
|
|
@ -593,6 +593,7 @@
|
||||||
|
|
||||||
<ReferencePath>../../../bin/</ReferencePath>
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
<Reference name="System"/>
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
<Reference name="System.Xml"/>
|
<Reference name="System.Xml"/>
|
||||||
<Reference name="System.Web"/>
|
<Reference name="System.Web"/>
|
||||||
<Reference name="OpenSim.Data"/>
|
<Reference name="OpenSim.Data"/>
|
||||||
|
@ -607,6 +608,7 @@
|
||||||
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
||||||
<!-- FIXME: The OpenMetaverse.dll reference can be dropped when the TransferRequestPacket reference is removed from the code -->
|
<!-- FIXME: The OpenMetaverse.dll reference can be dropped when the TransferRequestPacket reference is removed from the code -->
|
||||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
|
<Reference name="LukeSkywalker.IPNetwork" path="../../../bin/"/>
|
||||||
<Reference name="Nini" path="../../../bin/"/>
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
<Reference name="XMLRPC" path="../../../bin/"/>
|
<Reference name="XMLRPC" path="../../../bin/"/>
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
|
Loading…
Reference in New Issue