Imported Upstream version 4.3.2.467

Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
Xamarin Public Jenkins
2016-02-22 11:00:01 -05:00
parent f302175246
commit f3e3aab35a
4097 changed files with 122406 additions and 82300 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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 ();

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View 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

View File

@@ -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 ()

View File

@@ -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

View File

@@ -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
{

View File

@@ -33,6 +33,8 @@ namespace System.Net {
public
enum SecurityProtocolType {
Ssl3 = 48,
Tls = 192
Tls = 192,
Tls11 = 768,
Tls12 = 3072
}
}

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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