You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -114,13 +115,13 @@ namespace System.Net
|
||||
{
|
||||
int count = chunks.Count;
|
||||
int nread = 0;
|
||||
|
||||
var chunksForRemoving = new List<Chunk>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Chunk chunk = (Chunk) chunks [i];
|
||||
if (chunk == null)
|
||||
continue;
|
||||
|
||||
if (chunk.Offset == chunk.Bytes.Length) {
|
||||
chunks [i] = null;
|
||||
chunksForRemoving.Add(chunk);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -129,6 +130,9 @@ namespace System.Net
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var chunk in chunksForRemoving)
|
||||
chunks.Remove(chunk);
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
@@ -29,11 +29,11 @@
|
||||
|
||||
#if SECURITY_DEP
|
||||
|
||||
#if MONOTOUCH || MONODROID
|
||||
using Mono.Security.Authenticode;
|
||||
#else
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Authenticode;
|
||||
#else
|
||||
using Mono.Security.Authenticode;
|
||||
#endif
|
||||
|
||||
using System.IO;
|
||||
@@ -47,21 +47,23 @@ using System.Threading;
|
||||
namespace System.Net {
|
||||
sealed class EndPointListener
|
||||
{
|
||||
HttpListener listener;
|
||||
IPEndPoint endpoint;
|
||||
Socket sock;
|
||||
Hashtable prefixes; // Dictionary <ListenerPrefix, HttpListener>
|
||||
ArrayList unhandled; // List<ListenerPrefix> unhandled; host = '*'
|
||||
ArrayList all; // List<ListenerPrefix> all; host = '+'
|
||||
X509Certificate2 cert;
|
||||
AsymmetricAlgorithm key;
|
||||
X509Certificate cert;
|
||||
bool secure;
|
||||
Dictionary<HttpConnection, HttpConnection> unregistered;
|
||||
|
||||
public EndPointListener (IPAddress addr, int port, bool secure)
|
||||
public EndPointListener (HttpListener listener, IPAddress addr, int port, bool secure)
|
||||
{
|
||||
this.listener = listener;
|
||||
|
||||
if (secure) {
|
||||
this.secure = secure;
|
||||
LoadCertificateAndKey (addr, port);
|
||||
cert = listener.LoadCertificateAndKey (addr, port);
|
||||
}
|
||||
|
||||
endpoint = new IPEndPoint (addr, port);
|
||||
@@ -76,24 +78,8 @@ namespace System.Net {
|
||||
unregistered = new Dictionary<HttpConnection, HttpConnection> ();
|
||||
}
|
||||
|
||||
void LoadCertificateAndKey (IPAddress addr, int port)
|
||||
{
|
||||
// Actually load the certificate
|
||||
try {
|
||||
string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
|
||||
string path = Path.Combine (dirname, ".mono");
|
||||
path = Path.Combine (path, "httplistener");
|
||||
string cert_file = Path.Combine (path, String.Format ("{0}.cer", port));
|
||||
if (!File.Exists (cert_file))
|
||||
return;
|
||||
string pvk_file = Path.Combine (path, String.Format ("{0}.pvk", port));
|
||||
if (!File.Exists (pvk_file))
|
||||
return;
|
||||
cert = new X509Certificate2 (cert_file);
|
||||
key = PrivateKey.CreateFromFile (pvk_file).RSA;
|
||||
} catch {
|
||||
// ignore errors
|
||||
}
|
||||
internal HttpListener Listener {
|
||||
get { return listener; }
|
||||
}
|
||||
|
||||
static void OnAccept (object sender, EventArgs e)
|
||||
@@ -121,11 +107,11 @@ namespace System.Net {
|
||||
if (accepted == null)
|
||||
return;
|
||||
|
||||
if (epl.secure && (epl.cert == null || epl.key == null)) {
|
||||
if (epl.secure && epl.cert == null) {
|
||||
accepted.Close ();
|
||||
return;
|
||||
}
|
||||
HttpConnection conn = new HttpConnection (accepted, epl, epl.secure, epl.cert, epl.key);
|
||||
HttpConnection conn = new HttpConnection (accepted, epl, epl.secure, epl.cert);
|
||||
lock (epl.unregistered) {
|
||||
epl.unregistered [conn] = conn;
|
||||
}
|
||||
@@ -168,7 +154,7 @@ namespace System.Net {
|
||||
|
||||
string host = uri.Host;
|
||||
int port = uri.Port;
|
||||
string path = HttpUtility.UrlDecode (uri.AbsolutePath);
|
||||
string path = WebUtility.UrlDecode (uri.AbsolutePath);
|
||||
string path_slash = path [path.Length - 1] == '/' ? path : path + "/";
|
||||
|
||||
HttpListener best_match = null;
|
||||
|
@@ -107,7 +107,7 @@ namespace System.Net {
|
||||
if (p.ContainsKey (port)) {
|
||||
epl = (EndPointListener) p [port];
|
||||
} else {
|
||||
epl = new EndPointListener (addr, port, secure);
|
||||
epl = new EndPointListener (listener, addr, port, secure);
|
||||
p [port] = epl;
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,15 @@
|
||||
// (c) Copyright 2006 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
using MSI = MonoSecurity::Mono.Security.Interface;
|
||||
#else
|
||||
using MSI = Mono.Security.Interface;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
@@ -17,6 +26,7 @@ using System.Security.Cryptography.X509Certificates;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Security.Authentication;
|
||||
using Mono.Net.Security;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
@@ -1155,28 +1165,14 @@ namespace System.Net
|
||||
ChangeToSSLSocket (ref stream);
|
||||
}
|
||||
|
||||
#if SECURITY_DEP
|
||||
RemoteCertificateValidationCallback callback = delegate (object sender,
|
||||
X509Certificate certificate,
|
||||
X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors) {
|
||||
// honor any exciting callback defined on ServicePointManager
|
||||
if (ServicePointManager.ServerCertificateValidationCallback != null)
|
||||
return ServicePointManager.ServerCertificateValidationCallback (sender, certificate, chain, sslPolicyErrors);
|
||||
// otherwise provide our own
|
||||
if (sslPolicyErrors != SslPolicyErrors.None)
|
||||
throw new InvalidOperationException ("SSL authentication error: " + sslPolicyErrors);
|
||||
return true;
|
||||
};
|
||||
#endif
|
||||
|
||||
internal bool ChangeToSSLSocket (ref Stream stream) {
|
||||
#if SECURITY_DEP
|
||||
SslStream sslStream = new SslStream (stream, true, callback, null);
|
||||
//sslStream.AuthenticateAsClient (Host, this.ClientCertificates, SslProtocols.Default, false);
|
||||
//TODO: client certificates
|
||||
#if SECURITY_DEP
|
||||
var provider = MonoTlsProviderFactory.GetProviderInternal ();
|
||||
var settings = MSI.MonoTlsSettings.CopyDefaultSettings ();
|
||||
settings.UseServicePointManagerCallback = true;
|
||||
var sslStream = provider.CreateSslStream (stream, true, settings);
|
||||
sslStream.AuthenticateAsClient (requestUri.Host, null, SslProtocols.Default, false);
|
||||
stream = sslStream;
|
||||
stream = sslStream.AuthenticatedStream;
|
||||
return true;
|
||||
#else
|
||||
throw new NotImplementedException ();
|
||||
|
@@ -28,21 +28,32 @@
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
|
||||
#if MONOTOUCH || MONODROID
|
||||
using Mono.Security.Protocol.Tls;
|
||||
#else
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Protocol.Tls;
|
||||
#endif
|
||||
#if MONO_X509_ALIAS
|
||||
extern alias PrebuiltSystem;
|
||||
#endif
|
||||
|
||||
#if MONO_SECURITY_ALIAS
|
||||
using MSI = MonoSecurity::Mono.Security.Interface;
|
||||
#else
|
||||
using MSI = Mono.Security.Interface;
|
||||
#endif
|
||||
#if MONO_X509_ALIAS
|
||||
using XX509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
|
||||
#else
|
||||
using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
|
||||
#endif
|
||||
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Mono.Net.Security;
|
||||
|
||||
namespace System.Net {
|
||||
sealed class HttpConnection
|
||||
@@ -63,27 +74,35 @@ namespace System.Net {
|
||||
int reuses;
|
||||
bool context_bound;
|
||||
bool secure;
|
||||
AsymmetricAlgorithm key;
|
||||
X509Certificate cert;
|
||||
int s_timeout = 90000; // 90k ms for first request, 15k ms from then on
|
||||
Timer timer;
|
||||
IPEndPoint local_ep;
|
||||
HttpListener last_listener;
|
||||
int [] client_cert_errors;
|
||||
X509Certificate2 client_cert;
|
||||
IMonoSslStream ssl_stream;
|
||||
|
||||
public HttpConnection (Socket sock, EndPointListener epl, bool secure, X509Certificate2 cert, AsymmetricAlgorithm key)
|
||||
public HttpConnection (Socket sock, EndPointListener epl, bool secure, X509Certificate cert)
|
||||
{
|
||||
this.sock = sock;
|
||||
this.epl = epl;
|
||||
this.secure = secure;
|
||||
this.key = key;
|
||||
this.cert = cert;
|
||||
if (secure == false) {
|
||||
stream = new NetworkStream (sock, false);
|
||||
} else {
|
||||
SslServerStream ssl_stream = new SslServerStream (new NetworkStream (sock, false), cert, false, true, false);
|
||||
ssl_stream.PrivateKeyCertSelectionDelegate += OnPVKSelection;
|
||||
ssl_stream.ClientCertValidationDelegate += OnClientCertificateValidation;
|
||||
stream = ssl_stream;
|
||||
ssl_stream = epl.Listener.CreateSslStream (new NetworkStream (sock, false), false, (t, c, ch, e) => {
|
||||
if (c == null)
|
||||
return true;
|
||||
var c2 = c as X509Certificate2;
|
||||
if (c2 == null)
|
||||
c2 = new X509Certificate2 (c.GetRawCertData ());
|
||||
client_cert = c2;
|
||||
client_cert_errors = new int[] { (int)e };
|
||||
return true;
|
||||
});
|
||||
stream = ssl_stream.AuthenticatedStream;
|
||||
}
|
||||
timer = new Timer (OnTimeout, null, Timeout.Infinite, Timeout.Infinite);
|
||||
Init ();
|
||||
@@ -97,25 +116,12 @@ namespace System.Net {
|
||||
get { return client_cert; }
|
||||
}
|
||||
|
||||
bool OnClientCertificateValidation (X509Certificate certificate, int[] errors)
|
||||
{
|
||||
if (certificate == null)
|
||||
return true;
|
||||
X509Certificate2 cert = certificate as X509Certificate2;
|
||||
if (cert == null)
|
||||
cert = new X509Certificate2 (certificate.GetRawCertData ());
|
||||
client_cert = cert;
|
||||
client_cert_errors = errors;
|
||||
return true;
|
||||
}
|
||||
|
||||
AsymmetricAlgorithm OnPVKSelection (X509Certificate certificate, string targetHost)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
void Init ()
|
||||
{
|
||||
if (ssl_stream != null) {
|
||||
ssl_stream.AuthenticateAsServer (cert, true, (SslProtocols)ServicePointManager.SecurityProtocol, false);
|
||||
}
|
||||
|
||||
context_bound = false;
|
||||
i_stream = null;
|
||||
o_stream = null;
|
||||
@@ -203,8 +209,11 @@ namespace System.Net {
|
||||
// TODO: can we get this stream before reading the input?
|
||||
if (o_stream == null) {
|
||||
HttpListener listener = context.Listener;
|
||||
bool ign = (listener == null) ? true : listener.IgnoreWriteExceptions;
|
||||
o_stream = new ResponseStream (stream, context.Response, ign);
|
||||
|
||||
if(listener == null)
|
||||
return new ResponseStream (stream, context.Response, true);
|
||||
|
||||
o_stream = new ResponseStream (stream, context.Response, listener.IgnoreWriteExceptions);
|
||||
}
|
||||
return o_stream;
|
||||
}
|
||||
@@ -306,18 +315,25 @@ namespace System.Net {
|
||||
int used = 0;
|
||||
string line;
|
||||
|
||||
try {
|
||||
line = ReadLine (buffer, position, len - position, ref used);
|
||||
position += used;
|
||||
} catch {
|
||||
context.ErrorMessage = "Bad request";
|
||||
context.ErrorStatus = 400;
|
||||
return true;
|
||||
}
|
||||
while (true) {
|
||||
if (context.HaveError)
|
||||
return true;
|
||||
|
||||
if (position >= len)
|
||||
break;
|
||||
|
||||
try {
|
||||
line = ReadLine (buffer, position, len - position, ref used);
|
||||
position += used;
|
||||
} catch {
|
||||
context.ErrorMessage = "Bad request";
|
||||
context.ErrorStatus = 400;
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
if (line == "") {
|
||||
if (input_state == InputState.RequestLine)
|
||||
continue;
|
||||
@@ -338,21 +354,7 @@ namespace System.Net {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.HaveError)
|
||||
return true;
|
||||
|
||||
if (position >= len)
|
||||
break;
|
||||
try {
|
||||
line = ReadLine (buffer, position, len - position, ref used);
|
||||
position += used;
|
||||
} catch {
|
||||
context.ErrorMessage = "Bad request";
|
||||
context.ErrorStatus = 400;
|
||||
return true;
|
||||
}
|
||||
} while (line != null);
|
||||
}
|
||||
|
||||
if (used == len) {
|
||||
ms.SetLength (0);
|
||||
@@ -395,7 +397,7 @@ namespace System.Net {
|
||||
HttpListenerResponse response = context.Response;
|
||||
response.StatusCode = status;
|
||||
response.ContentType = "text/html";
|
||||
string description = HttpListenerResponse.GetStatusDescription (status);
|
||||
string description = HttpListenerResponseHelper.GetStatusDescription (status);
|
||||
string str;
|
||||
if (msg != null)
|
||||
str = String.Format ("<h1>{0} ({1})</h1>", description, msg);
|
||||
|
@@ -29,10 +29,24 @@
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Authenticode;
|
||||
using MSI = MonoSecurity::Mono.Security.Interface;
|
||||
#else
|
||||
using Mono.Security.Authenticode;
|
||||
using MSI = Mono.Security.Interface;
|
||||
#endif
|
||||
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
using Mono.Net.Security;
|
||||
|
||||
|
||||
//TODO: logging
|
||||
namespace System.Net {
|
||||
@@ -46,6 +60,10 @@ namespace System.Net {
|
||||
bool listening;
|
||||
bool disposed;
|
||||
|
||||
IMonoTlsProvider tlsProvider;
|
||||
MSI.MonoTlsSettings tlsSettings;
|
||||
X509Certificate certificate;
|
||||
|
||||
Hashtable registry; // Dictionary<HttpListenerContext,HttpListenerContext>
|
||||
ArrayList ctx_queue; // List<HttpListenerContext> ctx_queue;
|
||||
ArrayList wait_queue; // List<ListenerAsyncResult> wait_queue;
|
||||
@@ -61,6 +79,56 @@ namespace System.Net {
|
||||
auth_schemes = AuthenticationSchemes.Anonymous;
|
||||
}
|
||||
|
||||
internal HttpListener (X509Certificate certificate, IMonoTlsProvider tlsProvider, MSI.MonoTlsSettings tlsSettings)
|
||||
: this ()
|
||||
{
|
||||
this.certificate = certificate;
|
||||
this.tlsProvider = tlsProvider;
|
||||
this.tlsSettings = tlsSettings;
|
||||
}
|
||||
|
||||
internal X509Certificate LoadCertificateAndKey (IPAddress addr, int port)
|
||||
{
|
||||
lock (registry) {
|
||||
if (certificate != null)
|
||||
return certificate;
|
||||
|
||||
// Actually load the certificate
|
||||
try {
|
||||
string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
|
||||
string path = Path.Combine (dirname, ".mono");
|
||||
path = Path.Combine (path, "httplistener");
|
||||
string cert_file = Path.Combine (path, String.Format ("{0}.cer", port));
|
||||
if (!File.Exists (cert_file))
|
||||
return null;
|
||||
string pvk_file = Path.Combine (path, String.Format ("{0}.pvk", port));
|
||||
if (!File.Exists (pvk_file))
|
||||
return null;
|
||||
var cert = new X509Certificate2 (cert_file);
|
||||
cert.PrivateKey = PrivateKey.CreateFromFile (pvk_file).RSA;
|
||||
certificate = cert;
|
||||
return certificate;
|
||||
} catch {
|
||||
// ignore errors
|
||||
certificate = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal IMonoSslStream CreateSslStream (Stream innerStream, bool ownsStream, MSI.MonoRemoteCertificateValidationCallback callback)
|
||||
{
|
||||
lock (registry) {
|
||||
if (tlsProvider == null)
|
||||
tlsProvider = MonoTlsProviderFactory.GetProviderInternal ();
|
||||
if (tlsSettings == null)
|
||||
tlsSettings = MSI.MonoTlsSettings.CopyDefaultSettings ();
|
||||
if (tlsSettings.RemoteCertificateValidationCallback == null)
|
||||
tlsSettings.RemoteCertificateValidationCallback = callback;
|
||||
return tlsProvider.CreateSslStream (innerStream, ownsStream, tlsSettings);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Digest, NTLM and Negotiate require ControlPrincipal
|
||||
public AuthenticationSchemes AuthenticationSchemes {
|
||||
get { return auth_schemes; }
|
||||
@@ -349,5 +417,11 @@ namespace System.Net {
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // SECURITY_DEP
|
||||
namespace System.Net
|
||||
{
|
||||
public sealed class HttpListener
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -30,13 +30,6 @@
|
||||
|
||||
#if SECURITY_DEP
|
||||
|
||||
#if MONOTOUCH || MONODROID
|
||||
using Mono.Security.Protocol.Tls;
|
||||
#else
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Protocol.Tls;
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
@@ -45,6 +38,7 @@ using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Security.Authentication.ExtendedProtection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net;
|
||||
|
||||
namespace System.Net {
|
||||
public sealed class HttpListenerRequest
|
||||
@@ -142,10 +136,10 @@ namespace System.Net {
|
||||
foreach (string kv in components) {
|
||||
int pos = kv.IndexOf ('=');
|
||||
if (pos == -1) {
|
||||
query_string.Add (null, HttpUtility.UrlDecode (kv));
|
||||
query_string.Add (null, WebUtility.UrlDecode (kv));
|
||||
} else {
|
||||
string key = HttpUtility.UrlDecode (kv.Substring (0, pos));
|
||||
string val = HttpUtility.UrlDecode (kv.Substring (pos + 1));
|
||||
string key = WebUtility.UrlDecode (kv.Substring (0, pos));
|
||||
string val = WebUtility.UrlDecode (kv.Substring (pos + 1));
|
||||
|
||||
query_string.Add (key, val);
|
||||
}
|
||||
@@ -182,7 +176,7 @@ namespace System.Net {
|
||||
host, LocalEndPoint.Port);
|
||||
|
||||
if (!Uri.TryCreate (base_uri + path, UriKind.Absolute, out url)){
|
||||
context.ErrorMessage = "Invalid url: " + base_uri + path;
|
||||
context.ErrorMessage = WebUtility.HtmlEncode ("Invalid url: " + base_uri + path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -218,63 +218,10 @@ namespace System.Net {
|
||||
if (value < 100 || value > 999)
|
||||
throw new ProtocolViolationException ("StatusCode must be between 100 and 999.");
|
||||
status_code = value;
|
||||
status_description = GetStatusDescription (value);
|
||||
status_description = HttpListenerResponseHelper.GetStatusDescription (value);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GetStatusDescription (int code)
|
||||
{
|
||||
switch (code){
|
||||
case 100: return "Continue";
|
||||
case 101: return "Switching Protocols";
|
||||
case 102: return "Processing";
|
||||
case 200: return "OK";
|
||||
case 201: return "Created";
|
||||
case 202: return "Accepted";
|
||||
case 203: return "Non-Authoritative Information";
|
||||
case 204: return "No Content";
|
||||
case 205: return "Reset Content";
|
||||
case 206: return "Partial Content";
|
||||
case 207: return "Multi-Status";
|
||||
case 300: return "Multiple Choices";
|
||||
case 301: return "Moved Permanently";
|
||||
case 302: return "Found";
|
||||
case 303: return "See Other";
|
||||
case 304: return "Not Modified";
|
||||
case 305: return "Use Proxy";
|
||||
case 307: return "Temporary Redirect";
|
||||
case 400: return "Bad Request";
|
||||
case 401: return "Unauthorized";
|
||||
case 402: return "Payment Required";
|
||||
case 403: return "Forbidden";
|
||||
case 404: return "Not Found";
|
||||
case 405: return "Method Not Allowed";
|
||||
case 406: return "Not Acceptable";
|
||||
case 407: return "Proxy Authentication Required";
|
||||
case 408: return "Request Timeout";
|
||||
case 409: return "Conflict";
|
||||
case 410: return "Gone";
|
||||
case 411: return "Length Required";
|
||||
case 412: return "Precondition Failed";
|
||||
case 413: return "Request Entity Too Large";
|
||||
case 414: return "Request-Uri Too Long";
|
||||
case 415: return "Unsupported Media Type";
|
||||
case 416: return "Requested Range Not Satisfiable";
|
||||
case 417: return "Expectation Failed";
|
||||
case 422: return "Unprocessable Entity";
|
||||
case 423: return "Locked";
|
||||
case 424: return "Failed Dependency";
|
||||
case 500: return "Internal Server Error";
|
||||
case 501: return "Not Implemented";
|
||||
case 502: return "Bad Gateway";
|
||||
case 503: return "Service Unavailable";
|
||||
case 504: return "Gateway Timeout";
|
||||
case 505: return "Http Version Not Supported";
|
||||
case 507: return "Insufficient Storage";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public string StatusDescription {
|
||||
get { return status_description; }
|
||||
set {
|
||||
@@ -552,6 +499,64 @@ namespace System.Net {
|
||||
cookies.Add (cookie);
|
||||
}
|
||||
}
|
||||
|
||||
// do not inline into HttpListenerResponse as this recursively brings everything that's
|
||||
// reachable by IDisposable.Dispose (and that's quite a lot in this case).
|
||||
static class HttpListenerResponseHelper {
|
||||
|
||||
internal static string GetStatusDescription (int code)
|
||||
{
|
||||
switch (code){
|
||||
case 100: return "Continue";
|
||||
case 101: return "Switching Protocols";
|
||||
case 102: return "Processing";
|
||||
case 200: return "OK";
|
||||
case 201: return "Created";
|
||||
case 202: return "Accepted";
|
||||
case 203: return "Non-Authoritative Information";
|
||||
case 204: return "No Content";
|
||||
case 205: return "Reset Content";
|
||||
case 206: return "Partial Content";
|
||||
case 207: return "Multi-Status";
|
||||
case 300: return "Multiple Choices";
|
||||
case 301: return "Moved Permanently";
|
||||
case 302: return "Found";
|
||||
case 303: return "See Other";
|
||||
case 304: return "Not Modified";
|
||||
case 305: return "Use Proxy";
|
||||
case 307: return "Temporary Redirect";
|
||||
case 400: return "Bad Request";
|
||||
case 401: return "Unauthorized";
|
||||
case 402: return "Payment Required";
|
||||
case 403: return "Forbidden";
|
||||
case 404: return "Not Found";
|
||||
case 405: return "Method Not Allowed";
|
||||
case 406: return "Not Acceptable";
|
||||
case 407: return "Proxy Authentication Required";
|
||||
case 408: return "Request Timeout";
|
||||
case 409: return "Conflict";
|
||||
case 410: return "Gone";
|
||||
case 411: return "Length Required";
|
||||
case 412: return "Precondition Failed";
|
||||
case 413: return "Request Entity Too Large";
|
||||
case 414: return "Request-Uri Too Long";
|
||||
case 415: return "Unsupported Media Type";
|
||||
case 416: return "Requested Range Not Satisfiable";
|
||||
case 417: return "Expectation Failed";
|
||||
case 422: return "Unprocessable Entity";
|
||||
case 423: return "Locked";
|
||||
case 424: return "Failed Dependency";
|
||||
case 500: return "Internal Server Error";
|
||||
case 501: return "Not Implemented";
|
||||
case 502: return "Bad Gateway";
|
||||
case 503: return "Service Unavailable";
|
||||
case 504: return "Gateway Timeout";
|
||||
case 505: return "Http Version Not Supported";
|
||||
case 507: return "Insufficient Storage";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
35
mcs/class/System/System.Net/HttpListenerTimeoutManager.cs
Normal file
35
mcs/class/System/System.Net/HttpListenerTimeoutManager.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// HttpListenerTimeoutManager.cs
|
||||
//
|
||||
// Authors:
|
||||
// Marek Safar <marek.safar@gmail.com>
|
||||
//
|
||||
// Copyright (C) 2015 Xamarin Inc (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
public class HttpListenerTimeoutManager
|
||||
{
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,15 @@
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Interface;
|
||||
#else
|
||||
using Mono.Security.Interface;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Configuration;
|
||||
@@ -39,11 +48,13 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Mono.Net.Security;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
@@ -101,6 +112,11 @@ namespace System.Net
|
||||
int maxResponseHeadersLength;
|
||||
static int defaultMaxResponseHeadersLength;
|
||||
int readWriteTimeout = 300000; // ms
|
||||
IMonoTlsProvider tlsProvider;
|
||||
#if SECURITY_DEP
|
||||
MonoTlsSettings tlsSettings;
|
||||
#endif
|
||||
ServerCertValidationCallback certValidationCallback;
|
||||
|
||||
enum NtlmAuthState {
|
||||
None,
|
||||
@@ -143,6 +159,15 @@ namespace System.Net
|
||||
ThrowOnError = true;
|
||||
ResetAuthorization ();
|
||||
}
|
||||
|
||||
#if SECURITY_DEP
|
||||
internal HttpWebRequest (Uri uri, IMonoTlsProvider tlsProvider, MonoTlsSettings settings = null)
|
||||
: this (uri)
|
||||
{
|
||||
this.tlsProvider = tlsProvider;
|
||||
this.tlsSettings = settings;
|
||||
}
|
||||
#endif
|
||||
|
||||
[Obsolete ("Serialization is obsoleted for this type", false)]
|
||||
protected HttpWebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
|
||||
@@ -240,20 +265,30 @@ namespace System.Net
|
||||
method != "TRACE";
|
||||
}
|
||||
}
|
||||
|
||||
internal IMonoTlsProvider TlsProvider {
|
||||
get { return tlsProvider; }
|
||||
}
|
||||
|
||||
#if SECURITY_DEP
|
||||
internal MonoTlsSettings TlsSettings {
|
||||
get { return tlsSettings; }
|
||||
}
|
||||
#endif
|
||||
|
||||
public X509CertificateCollection ClientCertificates {
|
||||
get {
|
||||
if (certificates == null)
|
||||
certificates = new X509CertificateCollection ();
|
||||
|
||||
return certificates;
|
||||
}
|
||||
[MonoTODO]
|
||||
set {
|
||||
throw GetMustImplement ();
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
certificates = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string Connection {
|
||||
get { return webHeaders ["Connection"]; }
|
||||
set {
|
||||
@@ -666,7 +701,26 @@ namespace System.Net
|
||||
internal bool ProxyQuery {
|
||||
get { return servicePoint.UsesProxy && !servicePoint.UseConnect; }
|
||||
}
|
||||
|
||||
|
||||
internal ServerCertValidationCallback ServerCertValidationCallback {
|
||||
get { return certValidationCallback; }
|
||||
}
|
||||
|
||||
public RemoteCertificateValidationCallback ServerCertificateValidationCallback {
|
||||
get {
|
||||
if (certValidationCallback == null)
|
||||
return null;
|
||||
return certValidationCallback.ValidationCallback;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
certValidationCallback = null;
|
||||
else
|
||||
certValidationCallback = new ServerCertValidationCallback (value);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
internal ServicePoint GetServicePoint ()
|
||||
|
@@ -257,7 +257,7 @@ namespace System.Net {
|
||||
if (i == (ips.Length - 1)) {
|
||||
if (i != 0 && val >= (256 << ((3 - i) * 8)))
|
||||
return null;
|
||||
else if (val > 0x3fffffffe) // this is the last number that parses correctly with MS
|
||||
else if (val > 0xffffffff)
|
||||
return null;
|
||||
i = 3;
|
||||
} else if (val >= 0x100)
|
||||
@@ -378,8 +378,47 @@ namespace System.Net {
|
||||
return m_Family;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if NET_4_5
|
||||
|
||||
public IPAddress MapToIPv4 ()
|
||||
{
|
||||
if (AddressFamily == AddressFamily.InterNetwork)
|
||||
return this;
|
||||
if (AddressFamily != AddressFamily.InterNetworkV6)
|
||||
throw new Exception ("Only AddressFamily.InterNetworkV6 can be converted to IPv4");
|
||||
|
||||
//Test for 0000 0000 0000 0000 0000 FFFF xxxx xxxx
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (m_Numbers [i] != 0x0000)
|
||||
throw new Exception ("Address does not have the ::FFFF prefix");
|
||||
}
|
||||
if (m_Numbers [5] != 0xFFFF)
|
||||
throw new Exception ("Address does not have the ::FFFF prefix");
|
||||
|
||||
//We've got an IPv4 address
|
||||
byte [] ipv4Bytes = new byte [4];
|
||||
Buffer.BlockCopy (m_Numbers, 12, ipv4Bytes, 0, 4);
|
||||
return new IPAddress (ipv4Bytes);
|
||||
}
|
||||
|
||||
public IPAddress MapToIPv6 ()
|
||||
{
|
||||
if (AddressFamily == AddressFamily.InterNetworkV6)
|
||||
return this;
|
||||
if (AddressFamily != AddressFamily.InterNetwork)
|
||||
throw new Exception ("Only AddressFamily.InterNetworkV4 can be converted to IPv6");
|
||||
|
||||
byte [] ipv4Bytes = GetAddressBytes ();
|
||||
byte [] ipv6Bytes = new byte [16] {
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0xFF,0xFF,
|
||||
ipv4Bytes [0], ipv4Bytes [1], ipv4Bytes [2], ipv4Bytes [3]
|
||||
};
|
||||
return new IPAddress (ipv6Bytes);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Used to tell whether an address is a loopback.
|
||||
/// All IP addresses of the form 127.X.Y.Z, where X, Y, and Z are in
|
||||
|
@@ -25,11 +25,12 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Net
|
||||
namespace Mono.Net
|
||||
{
|
||||
internal class CFObject : IDisposable
|
||||
{
|
||||
|
@@ -33,6 +33,8 @@ namespace System.Net {
|
||||
public
|
||||
enum SecurityProtocolType {
|
||||
Ssl3 = 48,
|
||||
Tls = 192
|
||||
Tls = 192,
|
||||
Tls11 = 768,
|
||||
Tls12 = 3072
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ namespace System.Net
|
||||
int maxIdleTime;
|
||||
int currentConnections;
|
||||
DateTime idleSince;
|
||||
DateTime lastDnsResolve;
|
||||
Version protocolVersion;
|
||||
X509Certificate certificate;
|
||||
X509Certificate clientCertificate;
|
||||
@@ -339,37 +340,30 @@ namespace System.Net
|
||||
CheckAvailableForRecycling (out dummy);
|
||||
}
|
||||
|
||||
private bool HasTimedOut
|
||||
{
|
||||
get {
|
||||
int timeout = ServicePointManager.DnsRefreshTimeout;
|
||||
return timeout != Timeout.Infinite &&
|
||||
(lastDnsResolve + TimeSpan.FromMilliseconds (timeout)) < DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
internal IPHostEntry HostEntry
|
||||
{
|
||||
get {
|
||||
lock (hostE) {
|
||||
if (host != null)
|
||||
return host;
|
||||
|
||||
string uriHost = uri.Host;
|
||||
|
||||
// There is no need to do DNS resolution on literal IP addresses
|
||||
if (uri.HostNameType == UriHostNameType.IPv6 ||
|
||||
uri.HostNameType == UriHostNameType.IPv4) {
|
||||
if (host == null || HasTimedOut) {
|
||||
lastDnsResolve = DateTime.UtcNow;
|
||||
|
||||
if (uri.HostNameType == UriHostNameType.IPv6) {
|
||||
// Remove square brackets
|
||||
uriHost = uriHost.Substring(1,uriHost.Length-2);
|
||||
try {
|
||||
host = Dns.GetHostEntry (uriHost);
|
||||
}
|
||||
catch (Exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Creates IPHostEntry
|
||||
host = new IPHostEntry();
|
||||
host.AddressList = new IPAddress[] { IPAddress.Parse(uriHost) };
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
// Try DNS resolution on host names
|
||||
try {
|
||||
host = Dns.GetHostByName (uriHost);
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,10 +413,20 @@ namespace System.Net
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void SetCertificates (X509Certificate client, X509Certificate server)
|
||||
internal void SetServerCertificate (X509Certificate server)
|
||||
{
|
||||
certificate = server;
|
||||
clientCertificate = client;
|
||||
var cloned = server != null ? new X509Certificate (server) : null;
|
||||
var old = Interlocked.Exchange (ref certificate, cloned);
|
||||
if (old != null)
|
||||
old.Dispose ();
|
||||
}
|
||||
|
||||
internal void SetClientCertificate (X509Certificate clientCertificate)
|
||||
{
|
||||
var cloned = clientCertificate != null ? new X509Certificate (clientCertificate) : null;
|
||||
var old = Interlocked.Exchange (ref clientCertificate, cloned);
|
||||
if (old != null)
|
||||
old.Dispose ();
|
||||
}
|
||||
|
||||
internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
|
||||
|
@@ -29,22 +29,6 @@
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
|
||||
#if MONOTOUCH || MONODROID
|
||||
using Mono.Security.Protocol.Tls;
|
||||
using MSX = Mono.Security.X509;
|
||||
using Mono.Security.X509.Extensions;
|
||||
#else
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.X509.Extensions;
|
||||
using MonoSecurity::Mono.Security.Protocol.Tls;
|
||||
using MSX = MonoSecurity::Mono.Security.X509;
|
||||
#endif
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
@@ -134,12 +118,13 @@ namespace System.Net
|
||||
private static int defaultConnectionLimit = DefaultPersistentConnectionLimit;
|
||||
private static int maxServicePointIdleTime = 100000; // 100 seconds
|
||||
private static int maxServicePoints = 0;
|
||||
private static int dnsRefreshTimeout = 2 * 60 * 1000;
|
||||
private static bool _checkCRL = false;
|
||||
private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
|
||||
private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
|
||||
|
||||
static bool expectContinue = true;
|
||||
static bool useNagle;
|
||||
static RemoteCertificateValidationCallback server_cert_cb;
|
||||
static ServerCertValidationCallback server_cert_cb;
|
||||
static bool tcp_keepalive;
|
||||
static int tcp_keepalive_time;
|
||||
static int tcp_keepalive_interval;
|
||||
@@ -193,6 +178,11 @@ namespace System.Net
|
||||
set { policy = value; }
|
||||
}
|
||||
|
||||
internal static ICertificatePolicy GetLegacyCertificatePolicy ()
|
||||
{
|
||||
return policy;
|
||||
}
|
||||
|
||||
[MonoTODO("CRL checks not implemented")]
|
||||
public static bool CheckCertificateRevocationList {
|
||||
get { return _checkCRL; }
|
||||
@@ -218,14 +208,13 @@ namespace System.Net
|
||||
return new NotImplementedException ();
|
||||
}
|
||||
|
||||
[MonoTODO]
|
||||
public static int DnsRefreshTimeout
|
||||
{
|
||||
get {
|
||||
throw GetMustImplement ();
|
||||
return dnsRefreshTimeout;
|
||||
}
|
||||
set {
|
||||
throw GetMustImplement ();
|
||||
dnsRefreshTimeout = Math.Max (-1, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,24 +252,27 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
#if NET_1_0
|
||||
// we need it for SslClientStream
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
static SecurityProtocolType SecurityProtocol {
|
||||
public static SecurityProtocolType SecurityProtocol {
|
||||
get { return _securityProtocol; }
|
||||
set { _securityProtocol = value; }
|
||||
}
|
||||
|
||||
public static RemoteCertificateValidationCallback ServerCertificateValidationCallback
|
||||
{
|
||||
internal static ServerCertValidationCallback ServerCertValidationCallback {
|
||||
get { return server_cert_cb; }
|
||||
}
|
||||
|
||||
public static RemoteCertificateValidationCallback ServerCertificateValidationCallback {
|
||||
get {
|
||||
return server_cert_cb;
|
||||
if (server_cert_cb == null)
|
||||
return null;
|
||||
return server_cert_cb.ValidationCallback;
|
||||
}
|
||||
set {
|
||||
server_cert_cb = value;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
server_cert_cb = null;
|
||||
else
|
||||
server_cert_cb = new ServerCertValidationCallback (value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +286,10 @@ namespace System.Net
|
||||
set { useNagle = value; }
|
||||
}
|
||||
|
||||
internal static bool DisableStrongCrypto {
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
// Methods
|
||||
public static void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval)
|
||||
{
|
||||
@@ -378,382 +374,6 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SECURITY_DEP
|
||||
internal class ChainValidationHelper {
|
||||
object sender;
|
||||
string host;
|
||||
RemoteCertificateValidationCallback cb;
|
||||
|
||||
#if !MONOTOUCH
|
||||
static bool is_macosx = System.IO.File.Exists (OSX509Certificates.SecurityLibrary);
|
||||
static X509RevocationMode revocation_mode;
|
||||
|
||||
static ChainValidationHelper ()
|
||||
{
|
||||
revocation_mode = X509RevocationMode.NoCheck;
|
||||
try {
|
||||
string str = Environment.GetEnvironmentVariable ("MONO_X509_REVOCATION_MODE");
|
||||
if (String.IsNullOrEmpty (str))
|
||||
return;
|
||||
revocation_mode = (X509RevocationMode) Enum.Parse (typeof (X509RevocationMode), str, true);
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public ChainValidationHelper (object sender, string hostName)
|
||||
{
|
||||
this.sender = sender;
|
||||
host = hostName;
|
||||
}
|
||||
|
||||
public RemoteCertificateValidationCallback ServerCertificateValidationCallback {
|
||||
get {
|
||||
if (cb == null)
|
||||
cb = ServicePointManager.ServerCertificateValidationCallback;
|
||||
return cb;
|
||||
}
|
||||
set { cb = value; }
|
||||
}
|
||||
|
||||
// Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy
|
||||
// and the new ServerCertificateValidationCallback is not null
|
||||
internal ValidationResult ValidateChain (MSX.X509CertificateCollection certs)
|
||||
{
|
||||
// user_denied is true if the user callback is called and returns false
|
||||
bool user_denied = false;
|
||||
if (certs == null || certs.Count == 0)
|
||||
return null;
|
||||
|
||||
ICertificatePolicy policy = ServicePointManager.CertificatePolicy;
|
||||
|
||||
X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData);
|
||||
int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
|
||||
SslPolicyErrors errors = 0;
|
||||
X509Chain chain = null;
|
||||
bool result = false;
|
||||
#if MONOTOUCH
|
||||
// The X509Chain is not really usable with MonoTouch (since the decision is not based on this data)
|
||||
// However if someone wants to override the results (good or bad) from iOS then they will want all
|
||||
// the certificates that the server provided (which generally does not include the root) so, only
|
||||
// if there's a user callback, we'll create the X509Chain but won't build it
|
||||
// ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245
|
||||
if (ServerCertificateValidationCallback != null) {
|
||||
#endif
|
||||
chain = new X509Chain ();
|
||||
chain.ChainPolicy = new X509ChainPolicy ();
|
||||
#if !MONOTOUCH
|
||||
chain.ChainPolicy.RevocationMode = revocation_mode;
|
||||
#endif
|
||||
for (int i = 1; i < certs.Count; i++) {
|
||||
X509Certificate2 c2 = new X509Certificate2 (certs [i].RawData);
|
||||
chain.ChainPolicy.ExtraStore.Add (c2);
|
||||
}
|
||||
#if MONOTOUCH
|
||||
}
|
||||
#else
|
||||
try {
|
||||
if (!chain.Build (leaf))
|
||||
errors |= GetErrorsFromChain (chain);
|
||||
} catch (Exception e) {
|
||||
Console.Error.WriteLine ("ERROR building certificate chain: {0}", e);
|
||||
Console.Error.WriteLine ("Please, report this problem to the Mono team");
|
||||
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
}
|
||||
|
||||
// for OSX and iOS we're using the native API to check for the SSL server policy and host names
|
||||
if (!is_macosx) {
|
||||
if (!CheckCertificateUsage (leaf)) {
|
||||
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
|
||||
}
|
||||
|
||||
if (!CheckServerIdentity (certs [0], host)) {
|
||||
errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
|
||||
status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
// Attempt to use OSX certificates
|
||||
// Ideally we should return the SecTrustResult
|
||||
OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny;
|
||||
try {
|
||||
trustResult = OSX509Certificates.TrustEvaluateSsl (certs, host);
|
||||
// We could use the other values of trustResult to pass this extra information
|
||||
// to the .NET 2 callback for values like SecTrustResult.Confirm
|
||||
result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
|
||||
trustResult == OSX509Certificates.SecTrustResult.Unspecified);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
if (result) {
|
||||
// TrustEvaluateSsl was successful so there's no trust error
|
||||
// IOW we discard our own chain (since we trust OSX one instead)
|
||||
errors = 0;
|
||||
} else {
|
||||
// callback and DefaultCertificatePolicy needs this since 'result' is not specified
|
||||
status11 = (int) trustResult;
|
||||
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
}
|
||||
#if !MONOTOUCH
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MONODROID && SECURITY_DEP
|
||||
result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
|
||||
if (result) {
|
||||
// chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
|
||||
// Android (there are no mozroots or preinstalled root certificates),
|
||||
// thus `errors` will ALWAYS have RemoteCertificateChainErrors.
|
||||
// Android just verified the chain; clear RemoteCertificateChainErrors.
|
||||
errors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
|
||||
ServicePoint sp = null;
|
||||
HttpWebRequest req = sender as HttpWebRequest;
|
||||
if (req != null)
|
||||
sp = req.ServicePointNoLock;
|
||||
if (status11 == 0 && errors != 0)
|
||||
status11 = GetStatusFromChain (chain);
|
||||
|
||||
// pre 2.0 callback
|
||||
result = policy.CheckValidationResult (sp, leaf, req, status11);
|
||||
user_denied = !result && !(policy is DefaultCertificatePolicy);
|
||||
}
|
||||
// If there's a 2.0 callback, it takes precedence
|
||||
if (ServerCertificateValidationCallback != null) {
|
||||
result = ServerCertificateValidationCallback (sender, leaf, chain, errors);
|
||||
user_denied = !result;
|
||||
}
|
||||
return new ValidationResult (result, user_denied, status11);
|
||||
}
|
||||
|
||||
static int GetStatusFromChain (X509Chain chain)
|
||||
{
|
||||
long result = 0;
|
||||
foreach (var status in chain.ChainStatus) {
|
||||
X509ChainStatusFlags flags = status.Status;
|
||||
if (flags == X509ChainStatusFlags.NoError)
|
||||
continue;
|
||||
|
||||
// CERT_E_EXPIRED
|
||||
if ((flags & X509ChainStatusFlags.NotTimeValid) != 0) result = 0x800B0101;
|
||||
// CERT_E_VALIDITYPERIODNESTING
|
||||
else if ((flags & X509ChainStatusFlags.NotTimeNested) != 0) result = 0x800B0102;
|
||||
// CERT_E_REVOKED
|
||||
else if ((flags & X509ChainStatusFlags.Revoked) != 0) result = 0x800B010C;
|
||||
// TRUST_E_CERT_SIGNATURE
|
||||
else if ((flags & X509ChainStatusFlags.NotSignatureValid) != 0) result = 0x80096004;
|
||||
// CERT_E_WRONG_USAGE
|
||||
else if ((flags & X509ChainStatusFlags.NotValidForUsage) != 0) result = 0x800B0110;
|
||||
// CERT_E_UNTRUSTEDROOT
|
||||
else if ((flags & X509ChainStatusFlags.UntrustedRoot) != 0) result = 0x800B0109;
|
||||
// CRYPT_E_NO_REVOCATION_CHECK
|
||||
else if ((flags & X509ChainStatusFlags.RevocationStatusUnknown) != 0) result = 0x80092012;
|
||||
// CERT_E_CHAINING
|
||||
else if ((flags & X509ChainStatusFlags.Cyclic) != 0) result = 0x800B010A;
|
||||
// TRUST_E_FAIL - generic
|
||||
else if ((flags & X509ChainStatusFlags.InvalidExtension) != 0) result = 0x800B010B;
|
||||
// CERT_E_UNTRUSTEDROOT
|
||||
else if ((flags & X509ChainStatusFlags.InvalidPolicyConstraints) != 0) result = 0x800B010D;
|
||||
// TRUST_E_BASIC_CONSTRAINTS
|
||||
else if ((flags & X509ChainStatusFlags.InvalidBasicConstraints) != 0) result = 0x80096019;
|
||||
// CERT_E_INVALID_NAME
|
||||
else if ((flags & X509ChainStatusFlags.InvalidNameConstraints) != 0) result = 0x800B0114;
|
||||
// CERT_E_INVALID_NAME
|
||||
else if ((flags & X509ChainStatusFlags.HasNotSupportedNameConstraint) != 0) result = 0x800B0114;
|
||||
// CERT_E_INVALID_NAME
|
||||
else if ((flags & X509ChainStatusFlags.HasNotDefinedNameConstraint) != 0) result = 0x800B0114;
|
||||
// CERT_E_INVALID_NAME
|
||||
else if ((flags & X509ChainStatusFlags.HasNotPermittedNameConstraint) != 0) result = 0x800B0114;
|
||||
// CERT_E_INVALID_NAME
|
||||
else if ((flags & X509ChainStatusFlags.HasExcludedNameConstraint) != 0) result = 0x800B0114;
|
||||
// CERT_E_CHAINING
|
||||
else if ((flags & X509ChainStatusFlags.PartialChain) != 0) result = 0x800B010A;
|
||||
// CERT_E_EXPIRED
|
||||
else if ((flags & X509ChainStatusFlags.CtlNotTimeValid) != 0) result = 0x800B0101;
|
||||
// TRUST_E_CERT_SIGNATURE
|
||||
else if ((flags & X509ChainStatusFlags.CtlNotSignatureValid) != 0) result = 0x80096004;
|
||||
// CERT_E_WRONG_USAGE
|
||||
else if ((flags & X509ChainStatusFlags.CtlNotValidForUsage) != 0) result = 0x800B0110;
|
||||
// CRYPT_E_NO_REVOCATION_CHECK
|
||||
else if ((flags & X509ChainStatusFlags.OfflineRevocation) != 0) result = 0x80092012;
|
||||
// CERT_E_ISSUERCHAINING
|
||||
else if ((flags & X509ChainStatusFlags.NoIssuanceChainPolicy) != 0) result = 0x800B0107;
|
||||
else result = 0x800B010B; // TRUST_E_FAIL - generic
|
||||
|
||||
break; // Exit the loop on the first error
|
||||
}
|
||||
return (int) result;
|
||||
}
|
||||
#if !MONOTOUCH
|
||||
static SslPolicyErrors GetErrorsFromChain (X509Chain chain)
|
||||
{
|
||||
SslPolicyErrors errors = SslPolicyErrors.None;
|
||||
foreach (var status in chain.ChainStatus) {
|
||||
if (status.Status == X509ChainStatusFlags.NoError)
|
||||
continue;
|
||||
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
break;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
static X509KeyUsageFlags s_flags = X509KeyUsageFlags.DigitalSignature |
|
||||
X509KeyUsageFlags.KeyAgreement |
|
||||
X509KeyUsageFlags.KeyEncipherment;
|
||||
// Adapted to System 2.0+ from TlsServerCertificate.cs
|
||||
//------------------------------
|
||||
// Note: this method only works for RSA certificates
|
||||
// DH certificates requires some changes - does anyone use one ?
|
||||
static bool CheckCertificateUsage (X509Certificate2 cert)
|
||||
{
|
||||
try {
|
||||
// certificate extensions are required for this
|
||||
// we "must" accept older certificates without proofs
|
||||
if (cert.Version < 3)
|
||||
return true;
|
||||
|
||||
X509KeyUsageExtension kux = (cert.Extensions ["2.5.29.15"] as X509KeyUsageExtension);
|
||||
X509EnhancedKeyUsageExtension eku = (cert.Extensions ["2.5.29.37"] as X509EnhancedKeyUsageExtension);
|
||||
if (kux != null && eku != null) {
|
||||
// RFC3280 states that when both KeyUsageExtension and
|
||||
// ExtendedKeyUsageExtension are present then BOTH should
|
||||
// be valid
|
||||
if ((kux.KeyUsages & s_flags) == 0)
|
||||
return false;
|
||||
return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
|
||||
eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
|
||||
} else if (kux != null) {
|
||||
return ((kux.KeyUsages & s_flags) != 0);
|
||||
} else if (eku != null) {
|
||||
// Server Authentication (1.3.6.1.5.5.7.3.1) or
|
||||
// Netscape Server Gated Crypto (2.16.840.1.113730.4)
|
||||
return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
|
||||
eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
|
||||
}
|
||||
|
||||
// last chance - try with older (deprecated) Netscape extensions
|
||||
X509Extension ext = cert.Extensions ["2.16.840.1.113730.1.1"];
|
||||
if (ext != null) {
|
||||
string text = ext.NetscapeCertType (false);
|
||||
return text.IndexOf ("SSL Server Authentication", StringComparison.Ordinal) != -1;
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
|
||||
Console.Error.WriteLine ("Please, report this problem to the Mono team");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// RFC2818 - HTTP Over TLS, Section 3.1
|
||||
// http://www.ietf.org/rfc/rfc2818.txt
|
||||
//
|
||||
// 1. if present MUST use subjectAltName dNSName as identity
|
||||
// 1.1. if multiples entries a match of any one is acceptable
|
||||
// 1.2. wildcard * is acceptable
|
||||
// 2. URI may be an IP address -> subjectAltName.iPAddress
|
||||
// 2.1. exact match is required
|
||||
// 3. Use of the most specific Common Name (CN=) in the Subject
|
||||
// 3.1 Existing practice but DEPRECATED
|
||||
static bool CheckServerIdentity (MSX.X509Certificate cert, string targetHost)
|
||||
{
|
||||
try {
|
||||
MSX.X509Extension ext = cert.Extensions ["2.5.29.17"];
|
||||
// 1. subjectAltName
|
||||
if (ext != null) {
|
||||
SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (ext);
|
||||
// 1.1 - multiple dNSName
|
||||
foreach (string dns in subjectAltName.DNSNames) {
|
||||
// 1.2 TODO - wildcard support
|
||||
if (Match (targetHost, dns))
|
||||
return true;
|
||||
}
|
||||
// 2. ipAddress
|
||||
foreach (string ip in subjectAltName.IPAddresses) {
|
||||
// 2.1. Exact match required
|
||||
if (ip == targetHost)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 3. Common Name (CN=)
|
||||
return CheckDomainName (cert.SubjectName, targetHost);
|
||||
} catch (Exception e) {
|
||||
Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
|
||||
Console.Error.WriteLine ("Please, report this problem to the Mono team");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckDomainName (string subjectName, string targetHost)
|
||||
{
|
||||
string domainName = String.Empty;
|
||||
Regex search = new Regex(@"CN\s*=\s*([^,]*)");
|
||||
MatchCollection elements = search.Matches(subjectName);
|
||||
if (elements.Count == 1) {
|
||||
if (elements[0].Success)
|
||||
domainName = elements[0].Groups[1].Value.ToString();
|
||||
}
|
||||
|
||||
return Match (targetHost, domainName);
|
||||
}
|
||||
|
||||
// ensure the pattern is valid wrt to RFC2595 and RFC2818
|
||||
// http://www.ietf.org/rfc/rfc2595.txt
|
||||
// http://www.ietf.org/rfc/rfc2818.txt
|
||||
static bool Match (string hostname, string pattern)
|
||||
{
|
||||
// check if this is a pattern
|
||||
int index = pattern.IndexOf ('*');
|
||||
if (index == -1) {
|
||||
// not a pattern, do a direct case-insensitive comparison
|
||||
return (String.Compare (hostname, pattern, true, CultureInfo.InvariantCulture) == 0);
|
||||
}
|
||||
|
||||
// check pattern validity
|
||||
// A "*" wildcard character MAY be used as the left-most name component in the certificate.
|
||||
|
||||
// unless this is the last char (valid)
|
||||
if (index != pattern.Length - 1) {
|
||||
// then the next char must be a dot .'.
|
||||
if (pattern [index + 1] != '.')
|
||||
return false;
|
||||
}
|
||||
|
||||
// only one (A) wildcard is supported
|
||||
int i2 = pattern.IndexOf ('*', index + 1);
|
||||
if (i2 != -1)
|
||||
return false;
|
||||
|
||||
// match the end of the pattern
|
||||
string end = pattern.Substring (index + 1);
|
||||
int length = hostname.Length - end.Length;
|
||||
// no point to check a pattern that is longer than the hostname
|
||||
if (length <= 0)
|
||||
return false;
|
||||
|
||||
if (String.Compare (hostname, length, end, 0, end.Length, true, CultureInfo.InvariantCulture) != 0)
|
||||
return false;
|
||||
|
||||
// special case, we start with the wildcard
|
||||
if (index == 0) {
|
||||
// ensure we hostname non-matched part (start) doesn't contain a dot
|
||||
int i3 = hostname.IndexOf ('.');
|
||||
return ((i3 == -1) || (i3 >= (hostname.Length - end.Length)));
|
||||
}
|
||||
|
||||
// match the start of the pattern
|
||||
string start = pattern.Substring (0, index);
|
||||
return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,25 +28,14 @@
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if SECURITY_DEP
|
||||
|
||||
#if MONOTOUCH || MONODROID
|
||||
using Mono.Security.Protocol.Tls;
|
||||
#else
|
||||
extern alias MonoSecurity;
|
||||
using MonoSecurity::Mono.Security.Protocol.Tls;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using Mono.Net.Security;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
@@ -93,18 +82,11 @@ namespace System.Net
|
||||
NtlmAuthState connect_ntlm_auth_state;
|
||||
HttpWebRequest connect_request;
|
||||
|
||||
bool ssl;
|
||||
bool certsAvailable;
|
||||
Exception connect_exception;
|
||||
static object classLock = new object ();
|
||||
static Type sslStream;
|
||||
#if !MONOTOUCH && !MONODROID
|
||||
static PropertyInfo piClient;
|
||||
static PropertyInfo piServer;
|
||||
static PropertyInfo piTrustFailure;
|
||||
#endif
|
||||
MonoTlsStream tlsStream;
|
||||
|
||||
#if MONOTOUCH
|
||||
#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
|
||||
[System.Runtime.InteropServices.DllImport ("__Internal")]
|
||||
static extern void xamarin_start_wwan (string uri);
|
||||
#endif
|
||||
@@ -170,7 +152,7 @@ namespace System.Net
|
||||
IPHostEntry hostEntry = sPoint.HostEntry;
|
||||
|
||||
if (hostEntry == null) {
|
||||
#if MONOTOUCH
|
||||
#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
|
||||
xamarin_start_wwan (sPoint.Address.ToString ());
|
||||
hostEntry = sPoint.HostEntry;
|
||||
if (hostEntry == null) {
|
||||
@@ -178,7 +160,7 @@ namespace System.Net
|
||||
status = sPoint.UsesProxy ? WebExceptionStatus.ProxyNameResolutionFailure :
|
||||
WebExceptionStatus.NameResolutionFailure;
|
||||
return;
|
||||
#if MONOTOUCH
|
||||
#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -237,34 +219,6 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
static void EnsureSSLStreamAvailable ()
|
||||
{
|
||||
lock (classLock) {
|
||||
if (sslStream != null)
|
||||
return;
|
||||
|
||||
#if NET_2_1 && SECURITY_DEP
|
||||
sslStream = typeof (HttpsClientStream);
|
||||
#else
|
||||
// HttpsClientStream is an internal glue class in Mono.Security.dll
|
||||
sslStream = Type.GetType ("Mono.Security.Protocol.Tls.HttpsClientStream, " +
|
||||
Consts.AssemblyMono_Security, false);
|
||||
|
||||
if (sslStream == null) {
|
||||
string msg = "Missing Mono.Security.dll assembly. " +
|
||||
"Support for SSL/TLS is unavailable.";
|
||||
|
||||
throw new NotSupportedException (msg);
|
||||
}
|
||||
#endif
|
||||
#if !MONOTOUCH && !MONODROID
|
||||
piClient = sslStream.GetProperty ("SelectedClientCertificate");
|
||||
piServer = sslStream.GetProperty ("ServerCertificate");
|
||||
piTrustFailure = sslStream.GetProperty ("TrustFailure");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool CreateTunnel (HttpWebRequest request, Uri connectUri,
|
||||
Stream stream, out byte[] buffer)
|
||||
{
|
||||
@@ -439,40 +393,31 @@ namespace System.Net
|
||||
NetworkStream serverStream = new NetworkStream (socket, false);
|
||||
|
||||
if (request.Address.Scheme == Uri.UriSchemeHttps) {
|
||||
ssl = true;
|
||||
EnsureSSLStreamAvailable ();
|
||||
if (!reused || nstream == null || nstream.GetType () != sslStream) {
|
||||
#if SECURITY_DEP
|
||||
if (!reused || nstream == null || tlsStream == null) {
|
||||
byte [] buffer = null;
|
||||
if (sPoint.UseConnect) {
|
||||
bool ok = CreateTunnel (request, sPoint.Address, serverStream, out buffer);
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
#if SECURITY_DEP
|
||||
#if MONOTOUCH || MONODROID
|
||||
nstream = new HttpsClientStream (serverStream, request.ClientCertificates, request, buffer);
|
||||
#else
|
||||
object[] args = new object [4] { serverStream,
|
||||
request.ClientCertificates,
|
||||
request, buffer};
|
||||
nstream = (Stream) Activator.CreateInstance (sslStream, args);
|
||||
#endif
|
||||
SslClientStream scs = (SslClientStream) nstream;
|
||||
var helper = new ServicePointManager.ChainValidationHelper (request, request.Address.Host);
|
||||
scs.ServerCertValidation2 += new CertificateValidationCallback2 (helper.ValidateChain);
|
||||
#endif
|
||||
certsAvailable = false;
|
||||
tlsStream = new MonoTlsStream (request, serverStream);
|
||||
nstream = tlsStream.CreateStream (buffer);
|
||||
}
|
||||
// we also need to set ServicePoint.Certificate
|
||||
// and ServicePoint.ClientCertificate but this can
|
||||
// only be done later (after handshake - which is
|
||||
// done only after a read operation).
|
||||
#else
|
||||
throw new NotSupportedException ();
|
||||
#endif
|
||||
} else {
|
||||
ssl = false;
|
||||
nstream = serverStream;
|
||||
}
|
||||
} catch (Exception) {
|
||||
if (!request.Aborted)
|
||||
} catch (Exception ex) {
|
||||
if (tlsStream != null)
|
||||
status = tlsStream.ExceptionStatus;
|
||||
else if (!request.Aborted)
|
||||
status = WebExceptionStatus.ConnectFailure;
|
||||
return false;
|
||||
}
|
||||
@@ -623,21 +568,6 @@ namespace System.Net
|
||||
return (statusCode >= 200 && statusCode != 204 && statusCode != 304);
|
||||
}
|
||||
|
||||
internal void GetCertificates (Stream stream)
|
||||
{
|
||||
// here the SSL negotiation have been done
|
||||
#if SECURITY_DEP && (MONOTOUCH || MONODROID)
|
||||
HttpsClientStream s = (stream as HttpsClientStream);
|
||||
X509Certificate client = s.SelectedClientCertificate;
|
||||
X509Certificate server = s.ServerCertificate;
|
||||
#else
|
||||
X509Certificate client = (X509Certificate) piClient.GetValue (stream, null);
|
||||
X509Certificate server = (X509Certificate) piServer.GetValue (stream, null);
|
||||
#endif
|
||||
sPoint.SetCertificates (client, server);
|
||||
certsAvailable = (server != null);
|
||||
}
|
||||
|
||||
internal static void InitRead (object state)
|
||||
{
|
||||
WebConnection cnc = (WebConnection) state;
|
||||
@@ -1142,9 +1072,6 @@ namespace System.Net
|
||||
|
||||
try {
|
||||
s.Write (buffer, offset, size);
|
||||
// here SSL handshake should have been done
|
||||
if (ssl && !certsAvailable)
|
||||
GetCertificates (s);
|
||||
} catch (Exception e) {
|
||||
err_msg = e.Message;
|
||||
WebExceptionStatus wes = WebExceptionStatus.SendFailure;
|
||||
@@ -1154,19 +1081,6 @@ namespace System.Net
|
||||
return false;
|
||||
}
|
||||
|
||||
// if SSL is in use then check for TrustFailure
|
||||
if (ssl) {
|
||||
#if SECURITY_DEP && (MONOTOUCH || MONODROID)
|
||||
HttpsClientStream https = (s as HttpsClientStream);
|
||||
if (https.TrustFailure) {
|
||||
#else
|
||||
if ((bool) piTrustFailure.GetValue (s , null)) {
|
||||
#endif
|
||||
wes = WebExceptionStatus.TrustFailure;
|
||||
msg = "Trust failure";
|
||||
}
|
||||
}
|
||||
|
||||
HandleError (wes, e, msg);
|
||||
return false;
|
||||
}
|
||||
|
@@ -45,8 +45,8 @@ namespace System.Net
|
||||
int readBufferOffset;
|
||||
int readBufferSize;
|
||||
int stream_length; // -1 when CL not present
|
||||
int contentLength;
|
||||
int totalRead;
|
||||
long contentLength;
|
||||
long totalRead;
|
||||
internal long totalWritten;
|
||||
bool nextReadCalled;
|
||||
int pendingReads;
|
||||
@@ -93,10 +93,10 @@ namespace System.Net
|
||||
ReadAll ();
|
||||
}
|
||||
} catch {
|
||||
contentLength = Int32.MaxValue;
|
||||
contentLength = Int64.MaxValue;
|
||||
}
|
||||
} else {
|
||||
contentLength = Int32.MaxValue;
|
||||
contentLength = Int64.MaxValue;
|
||||
}
|
||||
|
||||
// Negative numbers?
|
||||
@@ -208,7 +208,7 @@ namespace System.Net
|
||||
internal void ForceCompletion ()
|
||||
{
|
||||
if (!nextReadCalled) {
|
||||
if (contentLength == Int32.MaxValue)
|
||||
if (contentLength == Int64.MaxValue)
|
||||
contentLength = 0;
|
||||
nextReadCalled = true;
|
||||
cnc.NextRead ();
|
||||
@@ -244,7 +244,7 @@ namespace System.Net
|
||||
int diff = readBufferSize - readBufferOffset;
|
||||
int new_size;
|
||||
|
||||
if (contentLength == Int32.MaxValue) {
|
||||
if (contentLength == Int64.MaxValue) {
|
||||
MemoryStream ms = new MemoryStream ();
|
||||
byte [] buffer = null;
|
||||
if (readBuffer != null && diff > 0) {
|
||||
@@ -264,7 +264,7 @@ namespace System.Net
|
||||
new_size = (int) ms.Length;
|
||||
contentLength = new_size;
|
||||
} else {
|
||||
new_size = contentLength - totalRead;
|
||||
new_size = (int) (contentLength - totalRead);
|
||||
b = new byte [new_size];
|
||||
if (readBuffer != null && diff > 0) {
|
||||
if (diff > new_size)
|
||||
@@ -384,8 +384,8 @@ namespace System.Net
|
||||
if (cb != null)
|
||||
cb = cb_wrapper;
|
||||
|
||||
if (contentLength != Int32.MaxValue && contentLength - totalRead < size)
|
||||
size = contentLength - totalRead;
|
||||
if (contentLength != Int64.MaxValue && contentLength - totalRead < size)
|
||||
size = (int)(contentLength - totalRead);
|
||||
|
||||
if (!read_eof) {
|
||||
result.InnerAsyncResult = cnc.BeginRead (request, buffer, offset, size, cb, result);
|
||||
|
@@ -206,8 +206,12 @@ namespace System.Net
|
||||
if (split && IsMultiValue (header)) {
|
||||
List<string> separated = null;
|
||||
foreach (var value in values) {
|
||||
if (value.IndexOf (',') < 0)
|
||||
if (value.IndexOf (',') < 0) {
|
||||
if (separated != null)
|
||||
separated.Add (value);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (separated == null) {
|
||||
separated = new List<string> (values.Length + 1);
|
||||
@@ -677,7 +681,7 @@ namespace System.Net
|
||||
return;
|
||||
|
||||
if ((info & headerRestriction.Value) != 0)
|
||||
throw new ArgumentException ("This header must be modified with the appropiate property.");
|
||||
throw new ArgumentException ("This header must be modified with the appropriate property.");
|
||||
}
|
||||
|
||||
void CheckHeaderConsistency (HeaderInfo value)
|
||||
|
@@ -40,6 +40,8 @@ using System.Net.Security;
|
||||
using System.Net.Cache;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Net;
|
||||
|
||||
#if NET_2_1
|
||||
using ConfigurationException = System.ArgumentException;
|
||||
@@ -332,6 +334,19 @@ namespace System.Net
|
||||
throw GetMustImplement ();
|
||||
}
|
||||
|
||||
// Takes an ArrayList of fileglob-formatted strings and returns an array of Regex-formatted strings
|
||||
private static string[] CreateBypassList (ArrayList al)
|
||||
{
|
||||
string[] result = al.ToArray (typeof (string)) as string[];
|
||||
for (int c = 0; c < result.Length; c++)
|
||||
{
|
||||
result [c] = "^" +
|
||||
Regex.Escape (result [c]).Replace (@"\*", ".*").Replace (@"\?", ".") +
|
||||
"$";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
[MonoTODO("Look in other places for proxy config info")]
|
||||
public static IWebProxy GetSystemWebProxy ()
|
||||
{
|
||||
@@ -375,7 +390,7 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
|
||||
return new WebProxy (strHttpProxy, bBypassOnLocal, CreateBypassList (al));
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
@@ -425,7 +440,7 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
|
||||
return new WebProxy (uri, bBypassOnLocal, CreateBypassList (al));
|
||||
} catch (UriFormatException) {
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user