aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs192
1 files changed, 170 insertions, 22 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index e431042..d7e5123 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -32,6 +32,7 @@ using System.Collections.Specialized;
32using System.IO; 32using System.IO;
33using System.Net; 33using System.Net;
34using System.Net.Sockets; 34using System.Net.Sockets;
35using System.Net.Security;
35using System.Security.Cryptography.X509Certificates; 36using System.Security.Cryptography.X509Certificates;
36using System.Reflection; 37using System.Reflection;
37using System.Globalization; 38using System.Globalization;
@@ -43,10 +44,11 @@ using log4net;
43using Nwc.XmlRpc; 44using Nwc.XmlRpc;
44using OpenMetaverse.StructuredData; 45using OpenMetaverse.StructuredData;
45using CoolHTTPListener = HttpServer.HttpListener; 46using CoolHTTPListener = HttpServer.HttpListener;
46using HttpListener=System.Net.HttpListener; 47using HttpListener = System.Net.HttpListener;
47using LogPrio=HttpServer.LogPrio; 48using LogPrio = HttpServer.LogPrio;
48using OpenSim.Framework.Monitoring; 49using OpenSim.Framework.Monitoring;
49using System.IO.Compression; 50using System.IO.Compression;
51using System.Security.Cryptography;
50 52
51namespace OpenSim.Framework.Servers.HttpServer 53namespace OpenSim.Framework.Servers.HttpServer
52{ 54{
@@ -107,19 +109,26 @@ namespace OpenSim.Framework.Servers.HttpServer
107 new Dictionary<string, WebSocketRequestDelegate>(); 109 new Dictionary<string, WebSocketRequestDelegate>();
108 110
109 protected uint m_port; 111 protected uint m_port;
110 protected uint m_sslport;
111 protected bool m_ssl; 112 protected bool m_ssl;
112 private X509Certificate2 m_cert; 113 private X509Certificate2 m_cert;
113 protected bool m_firstcaps = true;
114 protected string m_SSLCommonName = ""; 114 protected string m_SSLCommonName = "";
115 protected List<string> m_certNames = new List<string>();
116 protected List<string> m_certIPs = new List<string>();
117 protected string m_certCN= "";
118 protected RemoteCertificateValidationCallback m_certificateValidationCallback = null;
115 119
116 protected IPAddress m_listenIPAddress = IPAddress.Any; 120 protected IPAddress m_listenIPAddress = IPAddress.Any;
117 121
118 public PollServiceRequestManager PollServiceRequestManager { get; private set; } 122 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
119 123
124 public string Protocol
125 {
126 get { return m_ssl ? "https://" : "http://"; }
127 }
128
120 public uint SSLPort 129 public uint SSLPort
121 { 130 {
122 get { return m_sslport; } 131 get { return m_port; }
123 } 132 }
124 133
125 public string SSLCommonName 134 public string SSLCommonName
@@ -148,27 +157,151 @@ namespace OpenSim.Framework.Servers.HttpServer
148 m_port = port; 157 m_port = port;
149 } 158 }
150 159
151 public BaseHttpServer(uint port, bool ssl) : this (port) 160 private void load_cert(string CPath, string CPass)
152 { 161 {
153 m_ssl = ssl; 162 try
163 {
164 m_cert = new X509Certificate2(CPath, CPass);
165 X509Extension ext = m_cert.Extensions["2.5.29.17"];
166 if(ext != null)
167 {
168 AsnEncodedData asndata = new AsnEncodedData(ext.Oid, ext.RawData);
169 string datastr = asndata.Format(true);
170 string[] lines = datastr.Split(new char[] {'\n','\r'});
171 foreach(string s in lines)
172 {
173 if(String.IsNullOrEmpty(s))
174 continue;
175 string[] parts = s.Split(new char[] {'='});
176 if(String.IsNullOrEmpty(parts[0]))
177 continue;
178 string entryName = parts[0].Replace(" ","");
179 if(entryName == "DNSName")
180 m_certNames.Add(parts[1]);
181 else if(entryName == "IPAddress")
182 m_certIPs.Add(parts[1]);
183 }
184 }
185 m_certCN = m_cert.GetNameInfo(X509NameType.SimpleName, false);
186 }
187 catch
188 {
189 throw new Exception("SSL cert load error");
190 }
154 } 191 }
155 192
156 public BaseHttpServer(uint port, bool ssl, uint sslport, string CN) : this (port, ssl) 193 public BaseHttpServer(uint port, bool ssl, string CN, string CPath, string CPass)
157 { 194 {
158 if (m_ssl) 195 m_port = port;
196 if (ssl)
159 { 197 {
160 m_sslport = sslport; 198 if(string.IsNullOrEmpty(CPath))
199 throw new Exception("invalid main http server cert path");
200
201 if(Uri.CheckHostName(CN) == UriHostNameType.Unknown)
202 throw new Exception("invalid main http server CN (ExternalHostName)");
203
204 m_certNames.Clear();
205 m_certIPs.Clear();
206 m_certCN= "";
207
208 m_ssl = true;
209 load_cert(CPath, CPass);
210
211 if(!CheckSSLCertHost(CN))
212 throw new Exception("invalid main http server CN (ExternalHostName)");
213
214 m_SSLCommonName = CN;
215
216 if(m_cert.Issuer == m_cert.Subject )
217 m_log.Warn("Self signed certificate. Clients need to allow this (some viewers debug option NoVerifySSLcert must be set to true");
161 } 218 }
219 else
220 m_ssl = false;
162 } 221 }
163 222
164 public BaseHttpServer(uint port, bool ssl, string CPath, string CPass) : this (port, ssl) 223 public BaseHttpServer(uint port, bool ssl, string CPath, string CPass)
165 { 224 {
166 if (m_ssl) 225 m_port = port;
226 if (ssl)
167 { 227 {
168 m_cert = new X509Certificate2(CPath, CPass); 228 load_cert(CPath, CPass);
229 if(m_cert.Issuer == m_cert.Subject )
230 m_log.Warn("Self signed certificate. Http clients need to allow this");
231 m_ssl = true;
232 }
233 else
234 m_ssl = false;
235 }
236
237 static bool MatchDNS (string hostname, string dns)
238 {
239 int indx = dns.IndexOf ('*');
240 if (indx == -1)
241 return (String.Compare(hostname, dns, true, CultureInfo.InvariantCulture) == 0);
242
243 int dnslen = dns.Length;
244 dnslen--;
245 if(indx == dnslen)
246 return true; // just * ?
247
248 if(indx > dnslen - 2)
249 return false; // 2 short ?
250
251 if (dns[indx + 1] != '.')
252 return false;
253
254 int indx2 = dns.IndexOf ('*', indx + 1);
255 if (indx2 != -1)
256 return false; // there can only be one;
257
258 string end = dns.Substring(indx + 1);
259 int hostlen = hostname.Length;
260 int endlen = end.Length;
261 int length = hostlen - endlen;
262 if (length <= 0)
263 return false;
264
265 if (String.Compare(hostname, length, end, 0, endlen, true, CultureInfo.InvariantCulture) != 0)
266 return false;
267
268 if (indx == 0)
269 {
270 indx2 = hostname.IndexOf ('.');
271 return ((indx2 == -1) || (indx2 >= length));
272 }
273
274 string start = dns.Substring (0, indx);
275 return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
276 }
277
278 public bool CheckSSLCertHost(string hostname)
279 {
280 UriHostNameType htype = Uri.CheckHostName(hostname);
281
282 if(htype == UriHostNameType.Unknown || htype == UriHostNameType.Basic)
283 return false;
284 if(htype == UriHostNameType.Dns)
285 {
286 foreach(string name in m_certNames)
287 {
288 if(MatchDNS(hostname, name))
289 return true;
290 }
291 if(MatchDNS(hostname, m_certCN))
292 return true;
293 }
294 else
295 {
296 foreach(string ip in m_certIPs)
297 {
298 if (String.Compare(hostname, ip, true, CultureInfo.InvariantCulture) != 0)
299 return true;
300 }
169 } 301 }
170 }
171 302
303 return false;
304 }
172 /// <summary> 305 /// <summary>
173 /// Add a stream handler to the http server. If the handler already exists, then nothing happens. 306 /// Add a stream handler to the http server. If the handler already exists, then nothing happens.
174 /// </summary> 307 /// </summary>
@@ -461,7 +594,7 @@ namespace OpenSim.Framework.Servers.HttpServer
461 } 594 }
462 595
463 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 596 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
464 resp.ReuseContext = true; 597// resp.ReuseContext = true;
465// resp.ReuseContext = false; 598// resp.ReuseContext = false;
466 HandleRequest(req, resp); 599 HandleRequest(req, resp);
467 600
@@ -1098,6 +1231,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1098 1231
1099 if (gridproxy) 1232 if (gridproxy)
1100 xmlRprcRequest.Params.Add("gridproxy"); // Param[4] 1233 xmlRprcRequest.Params.Add("gridproxy"); // Param[4]
1234
1235 // reserve this for
1236 // ... by Fumi.Iseki for DTLNSLMoneyServer
1237 // BUT make its presence possible to detect/parse
1238 string rcn = request.IHttpClientContext.SSLCommonName;
1239 if(!string.IsNullOrWhiteSpace(rcn))
1240 {
1241 rcn = "SSLCN:" + rcn;
1242 xmlRprcRequest.Params.Add(rcn); // Param[4] or Param[5]
1243 }
1244
1101 try 1245 try
1102 { 1246 {
1103 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); 1247 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
@@ -1804,7 +1948,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1804*/ 1948*/
1805 // disable this things 1949 // disable this things
1806 response.KeepAlive = false; 1950 response.KeepAlive = false;
1807 response.ReuseContext = false; 1951 // response.ReuseContext = false;
1808 1952
1809 // Cross-Origin Resource Sharing with simple requests 1953 // Cross-Origin Resource Sharing with simple requests
1810 if (responsedata.ContainsKey("access_control_allow_origin")) 1954 if (responsedata.ContainsKey("access_control_allow_origin"))
@@ -1906,7 +2050,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1906 2050
1907 public void Start() 2051 public void Start()
1908 { 2052 {
1909 Start(true); 2053 Start(true,true);
1910 } 2054 }
1911 2055
1912 /// <summary> 2056 /// <summary>
@@ -1916,7 +2060,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1916 /// If true then poll responses are performed asynchronsly. 2060 /// If true then poll responses are performed asynchronsly.
1917 /// Option exists to allow regression tests to perform processing synchronously. 2061 /// Option exists to allow regression tests to perform processing synchronously.
1918 /// </param> 2062 /// </param>
1919 public void Start(bool performPollResponsesAsync) 2063 public void Start(bool performPollResponsesAsync, bool runPool)
1920 { 2064 {
1921 m_log.InfoFormat( 2065 m_log.InfoFormat(
1922 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 2066 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1945,6 +2089,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1945 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/"); 2089 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
1946 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); 2090 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
1947 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert); 2091 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert);
2092 if(m_certificateValidationCallback != null)
2093 m_httpListener2.CertificateValidationCallback = m_certificateValidationCallback;
1948 m_httpListener2.ExceptionThrown += httpServerException; 2094 m_httpListener2.ExceptionThrown += httpServerException;
1949 m_httpListener2.LogWriter = httpserverlog; 2095 m_httpListener2.LogWriter = httpserverlog;
1950 } 2096 }
@@ -1954,9 +2100,11 @@ namespace OpenSim.Framework.Servers.HttpServer
1954 m_httpListener2.Start(64); 2100 m_httpListener2.Start(64);
1955 2101
1956 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 2102 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1957 2103 if(runPool)
1958 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000); 2104 {
1959 PollServiceRequestManager.Start(); 2105 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
2106 PollServiceRequestManager.Start();
2107 }
1960 2108
1961 HTTPDRunning = true; 2109 HTTPDRunning = true;
1962 2110
@@ -1970,7 +2118,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1970 catch (Exception e) 2118 catch (Exception e)
1971 { 2119 {
1972 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message); 2120 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message);
1973 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + ", " + m_sslport + "?"); 2121 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + "?");
1974 2122
1975 // We want this exception to halt the entire server since in current configurations we aren't too 2123 // We want this exception to halt the entire server since in current configurations we aren't too
1976 // useful without inbound HTTP. 2124 // useful without inbound HTTP.