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

@@ -0,0 +1,80 @@
//
// Internal.cs
//
// Author:
// Martin Baulig <martin.baulig@xamarin.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.
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
namespace System.Net.Security
{
//From Schannel.h
[Flags]
internal enum SchProtocols
{
Zero = 0,
PctClient = 0x00000002,
PctServer = 0x00000001,
Pct = (PctClient | PctServer),
Ssl2Client = 0x00000008,
Ssl2Server = 0x00000004,
Ssl2 = (Ssl2Client | Ssl2Server),
Ssl3Client = 0x00000020,
Ssl3Server = 0x00000010,
Ssl3 = (Ssl3Client | Ssl3Server),
Tls10Client = 0x00000080,
Tls10Server = 0x00000040,
Tls10 = (Tls10Client | Tls10Server),
Tls11Client = 0x00000200,
Tls11Server = 0x00000100,
Tls11 = (Tls11Client | Tls11Server),
Tls12Client = 0x00000800,
Tls12Server = 0x00000400,
Tls12 = (Tls12Client | Tls12Server),
Ssl3Tls = (Ssl3 | Tls10),
UniClient = unchecked((int)0x80000000),
UniServer = 0x40000000,
Unified = (UniClient | UniServer),
ClientMask = (PctClient | Ssl2Client | Ssl3Client | Tls10Client | Tls11Client | Tls12Client | UniClient),
ServerMask = (PctServer | Ssl2Server | Ssl3Server | Tls10Server | Tls11Server | Tls12Server | UniServer)
}
//From Schannel.h
[StructLayout (LayoutKind.Sequential)]
internal class SslConnectionInfo
{
public readonly int Protocol;
public readonly int DataCipherAlg;
public readonly int DataKeySize;
public readonly int DataHashAlg;
public readonly int DataHashKeySize;
public readonly int KeyExchangeAlg;
public readonly int KeyExchKeySize;
internal SslConnectionInfo (int protocol)
{
Protocol = protocol;
}
}
}

View File

@@ -1,3 +1,4 @@
#if !MONO_FEATURE_NEW_TLS
using System.Diagnostics;
namespace System.Net {
@@ -28,6 +29,9 @@ namespace System.Net {
internal static void Exit(TraceSource traceSource, object obj, string method, object retObject) {
}
internal static void PrintInfo(TraceSource traceSource, object obj, string method, string msg) {
}
internal static void PrintWarning(TraceSource traceSource, object obj, string method, string msg) {
}
}
@@ -40,4 +44,5 @@ namespace System.Net {
}
#endif
}
}
#endif

View File

@@ -61,6 +61,7 @@ partial class SR
public const string UnterminatedBracket="Unterminated [] set.";
public const string UnterminatedComment="Unterminated (?#...) comment.";
public const string ArgumentNull_Array = "ArgumentNull_Array";
public const string ArgumentNull_ArrayWithNullElements = "ArgumentNull_ArrayWithNullElements";
public const string Arg_ArrayPlusOffTooSmall = "Arg_ArrayPlusOffTooSmall";
public const string Arg_InsufficientSpace = "Arg_InsufficientSpace";
@@ -74,6 +75,7 @@ partial class SR
public const string Argument_AddingDuplicate = "Argument_AddingDuplicate";
public const string Argument_ImplementIComparable = "Argument_ImplementIComparable";
public const string Argument_InvalidOffLen = "Argument_InvalidOffLen";
public const string Argument_InvalidThreshold = "Argument_InvalidThreshold";
public const string ExternalLinkedListNode = "ExternalLinkedListNode";
public const string InvalidOperation_CannotRemoveFromStackOrQueue = "InvalidOperation_CannotRemoveFromStackOrQueue";
public const string InvalidOperation_EmptyCollection = "InvalidOperation_EmptyCollection";
@@ -83,6 +85,7 @@ partial class SR
public const string InvalidOperation_EnumFailedVersion = "InvalidOperation_EnumFailedVersion";
public const string InvalidOperation_EnumNotStarted = "InvalidOperation_EnumNotStarted";
public const string InvalidOperation_EnumOpCantHappen = "InvalidOperation_EnumOpCantHappen";
public const string InvalidOperation_HCCountOverflow = "InvalidOperation_HCCountOverflow";
public const string Invalid_Array_Type = "Invalid_Array_Type";
public const string LinkedListEmpty = "LinkedListEmpty";
public const string LinkedListNodeIsAttached = "LinkedListNodeIsAttached";

View File

@@ -0,0 +1,12 @@
//
// Resource strings referenced by the code.
//
// Copyright 2014 Xamarin Inc
//
// Mono-specific additions, which are not in SR.cs.
//
partial class SR
{
public const string mono_net_io_shutdown = "mono_net_io_shutdown";
public const string mono_net_io_renegotiate = "mono_net_io_renegotiate";
}

View File

@@ -0,0 +1,53 @@
//
// SSPIConfiguration.cs
//
// Author:
// Martin Baulig <martin.baulig@xamarin.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.
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MonoSecurity::Mono.Security.Interface;
#else
using Mono.Security.Interface;
#endif
using Mono.Net.Security;
namespace System.Net.Security
{
internal interface SSPIConfiguration
{
IMonoTlsProvider Provider {
get;
}
MonoTlsSettings Settings {
get;
}
IMonoTlsEventSink EventSink {
get;
}
}
}
#endif

View File

@@ -0,0 +1,208 @@
//
// SafeHandles.cs
//
// Author:
// Martin Baulig <martin.baulig@xamarin.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.
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using IMonoTlsContext = MonoSecurity::Mono.Security.Interface.IMonoTlsContext;
#else
using IMonoTlsContext = Mono.Security.Interface.IMonoTlsContext;
#endif
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
namespace System.Net.Security
{
class DummySafeHandle : SafeHandle
{
protected DummySafeHandle ()
: base ((IntPtr)(-1), true)
{
}
protected override bool ReleaseHandle ()
{
return true;
}
public override bool IsInvalid {
get { return handle == (IntPtr)(-1); }
}
}
class SafeFreeCertContext : DummySafeHandle
{
}
class SafeFreeCredentials : DummySafeHandle
{
SecureCredential credential;
public X509Certificate2 Certificate {
get {
if (IsInvalid)
throw new ObjectDisposedException ("Certificate");
return credential.certificate;
}
}
public SafeFreeCredentials (SecureCredential credential)
{
this.credential = credential;
bool success = true;
DangerousAddRef (ref success);
}
public override bool IsInvalid {
get {
return credential.certificate == null;
}
}
protected override bool ReleaseHandle ()
{
credential.Clear ();
return base.ReleaseHandle ();
}
}
class SafeDeleteContext : DummySafeHandle
{
IMonoTlsContext context;
public IMonoTlsContext Context {
get {
if (IsInvalid)
throw new ObjectDisposedException ("TlsContext");
return context;
}
}
public SafeDeleteContext (IMonoTlsContext context)
{
this.context = context;
}
public override bool IsInvalid {
get {
return context == null || !context.IsValid;
}
}
protected override bool ReleaseHandle ()
{
context.Dispose ();
context = null;
return base.ReleaseHandle ();
}
}
struct SecureCredential
{
public const int CurrentVersion = 0x4;
[Flags]
public enum Flags
{
Zero = 0,
NoSystemMapper = 0x02,
NoNameCheck = 0x04,
ValidateManual = 0x08,
NoDefaultCred = 0x10,
ValidateAuto = 0x20,
UseStrongCrypto = 0x00400000
}
int version;
internal X509Certificate2 certificate;
SchProtocols protocols;
EncryptionPolicy policy;
public SecureCredential (int version, X509Certificate2 certificate, SecureCredential.Flags flags, SchProtocols protocols, EncryptionPolicy policy)
{
this.version = version;
this.certificate = certificate;
this.protocols = protocols;
this.policy = policy;
}
public void Clear ()
{
certificate = null;
}
}
internal class SafeCredentialReference : DummySafeHandle
{
//
// Static cache will return the target handle if found the reference in the table.
//
internal SafeFreeCredentials _Target;
//
//
internal static SafeCredentialReference CreateReference (SafeFreeCredentials target)
{
SafeCredentialReference result = new SafeCredentialReference (target);
if (result.IsInvalid)
return null;
return result;
}
private SafeCredentialReference (SafeFreeCredentials target)
: base ()
{
// Bumps up the refcount on Target to signify that target handle is statically cached so
// its dispose should be postponed
bool b = false;
try {
target.DangerousAddRef (ref b);
} catch {
if (b) {
target.DangerousRelease ();
b = false;
}
} finally {
if (b) {
_Target = target;
SetHandle (new IntPtr (0)); // make this handle valid
}
}
}
override protected bool ReleaseHandle ()
{
SafeFreeCredentials target = _Target;
if (target != null)
target.DangerousRelease ();
_Target = null;
return true;
}
}
}
#endif

View File

@@ -0,0 +1,311 @@
//
// SSPIWrapper.cs
//
// Author:
// Martin Baulig <martin.baulig@xamarin.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.
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
#endif
#if MONO_X509_ALIAS
extern alias PrebuiltSystem;
#endif
#if MONO_SECURITY_ALIAS
using MX = MonoSecurity::Mono.Security.X509;
using MonoSecurity::Mono.Security.Interface;
#else
using MX = Mono.Security.X509;
using 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.Runtime.InteropServices;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
using MNS = Mono.Net.Security;
namespace System.Net.Security
{
internal class SSPIInterface
{
public IMonoTlsContext Context {
get;
private set;
}
public IMonoTlsEventSink EventSink {
get;
private set;
}
public SSPIInterface (IMonoTlsContext context, IMonoTlsEventSink eventSink)
{
Context = context;
EventSink = eventSink;
}
}
internal static class GlobalSSPI
{
internal static SSPIInterface Create (string hostname, bool serverMode, SchProtocols protocolFlags, X509Certificate serverCertificate, XX509CertificateCollection clientCertificates,
bool remoteCertRequired, bool checkCertName, bool checkCertRevocationStatus, EncryptionPolicy encryptionPolicy,
LocalCertSelectionCallback certSelectionDelegate, RemoteCertValidationCallback remoteValidationCallback, SSPIConfiguration userConfig)
{
if (userConfig.Settings != null && remoteValidationCallback != null)
throw new InvalidOperationException ();
var context = userConfig.Provider.CreateTlsContext (
hostname, serverMode, (TlsProtocols)protocolFlags, serverCertificate, clientCertificates,
remoteCertRequired, checkCertName, checkCertRevocationStatus,
(MonoEncryptionPolicy)encryptionPolicy, userConfig.Settings);
return new SSPIInterface (context, userConfig.EventSink);
}
}
/*
* SSPIWrapper _is a _class that provides a managed implementation of the equivalent
* _class _in Microsofts .NET Framework.
*
* The SSPIWrapper class is used by the TLS/SSL stack to implement both the
* protocol handshake as well as the encryption and decryption of messages.
*
* Microsoft's implementation of this class is merely a P/Invoke wrapper
* around the native SSPI APIs on Windows. This implementation instead,
* provides a managed implementation that uses the cross platform Mono.Security
* to provide the equivalent functionality.
*
* Ideally, this should be abstracted with a different name, and decouple
* the naming from the SSPIWrapper name, but this allows Mono to reuse
* the .NET code with minimal changes.
*
* The "internal" methods here are the API that is consumed by the class
* libraries.
*/
internal static class SSPIWrapper
{
static void SetCredentials (SSPIInterface secModule, SafeFreeCredentials credentials)
{
if (credentials != null && !credentials.IsInvalid) {
if (!secModule.Context.HasCredentials && credentials.Certificate != null) {
var cert = new X509Certificate2 (credentials.Certificate.RawData);
secModule.Context.SetCertificate (cert, credentials.Certificate.PrivateKey);
}
bool success = true;
credentials.DangerousAddRef (ref success);
}
}
/*
* @safecontext is null on the first use, but it will become non-null for invocations
* where the connection is being re-negotiated.
*
*/
internal static int AcceptSecurityContext (SSPIInterface secModule, ref SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, ContextFlags inFlags, Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
if (endianness != Endianness.Native)
throw new NotSupportedException ();
if (safeContext == null) {
if (credentials == null || credentials.IsInvalid)
return (int)SecurityStatus.CredentialsNeeded;
secModule.Context.Initialize (secModule.EventSink);
safeContext = new SafeDeleteContext (secModule.Context);
}
SetCredentials (secModule, credentials);
var incoming = GetInputBuffer (inputBuffer);
IBufferOffsetSize outgoing;
var retval = (int)safeContext.Context.GenerateNextToken (incoming, out outgoing);
UpdateOutput (outgoing, outputBuffer);
return retval;
}
internal static int InitializeSecurityContext (SSPIInterface secModule, ref SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
if (inputBuffer != null)
throw new InvalidOperationException ();
if (safeContext == null) {
secModule.Context.Initialize (secModule.EventSink);
safeContext = new SafeDeleteContext (secModule.Context);
}
return InitializeSecurityContext (secModule, credentials, ref safeContext, targetName, inFlags, endianness, null, outputBuffer, ref outFlags);
}
internal static int InitializeSecurityContext (SSPIInterface secModule, SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
if (endianness != Endianness.Native)
throw new NotSupportedException ();
SetCredentials (secModule, credentials);
SecurityBuffer inputBuffer = null;
if (inputBuffers != null) {
if (inputBuffers.Length != 2 || inputBuffers [1].type != BufferType.Empty)
throw new NotSupportedException ();
inputBuffer = inputBuffers [0];
}
var incoming = GetInputBuffer (inputBuffer);
IBufferOffsetSize outgoing = null;
var retval = (int)safeContext.Context.GenerateNextToken (incoming, out outgoing);
UpdateOutput (outgoing, outputBuffer);
return retval;
}
internal static int EncryptMessage (SSPIInterface secModule, SafeDeleteContext safeContext, SecurityBuffer securityBuffer, uint sequenceNumber)
{
var incoming = GetInputBuffer (securityBuffer);
var retval = (int)safeContext.Context.EncryptMessage (ref incoming);
UpdateOutput (incoming, securityBuffer);
return retval;
}
internal static int DecryptMessage (SSPIInterface secModule, SafeDeleteContext safeContext, SecurityBuffer securityBuffer, uint sequenceNumber)
{
var incoming = GetInputBuffer (securityBuffer);
var retval = (int)safeContext.Context.DecryptMessage (ref incoming);
UpdateOutput (incoming, securityBuffer);
return retval;
}
internal static byte[] CreateShutdownMessage (SSPIInterface secModule, SafeDeleteContext safeContext)
{
return safeContext.Context.CreateCloseNotify ();
}
internal static byte[] CreateHelloRequestMessage (SSPIInterface secModule, SafeDeleteContext safeContext)
{
return safeContext.Context.CreateHelloRequest ();
}
internal static bool IsClosed (SSPIInterface secModule, SafeDeleteContext safeContext)
{
return safeContext.Context.ReceivedCloseNotify;
}
internal static SafeFreeCredentials AcquireCredentialsHandle (SSPIInterface SecModule, string package, CredentialUse intent, SecureCredential scc)
{
return new SafeFreeCredentials (scc);
}
public static ChannelBinding QueryContextChannelBinding (SSPIInterface SecModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute)
{
return null;
}
internal static X509Certificate2 GetRemoteCertificate (SafeDeleteContext safeContext, out X509Certificate2Collection remoteCertificateStore)
{
XX509CertificateCollection monoCollection;
if (safeContext == null || safeContext.IsInvalid) {
remoteCertificateStore = null;
return null;
}
var monoCert = safeContext.Context.GetRemoteCertificate (out monoCollection);
if (monoCert == null) {
remoteCertificateStore = null;
return null;
}
remoteCertificateStore = new X509Certificate2Collection ();
foreach (var cert in monoCollection) {
remoteCertificateStore.Add (cert);
}
return (X509Certificate2)monoCert;
}
internal static bool CheckRemoteCertificate (SafeDeleteContext safeContext)
{
return safeContext.Context.VerifyRemoteCertificate ();
}
internal static MonoTlsConnectionInfo GetMonoConnectionInfo (SSPIInterface SecModule, SafeDeleteContext securityContext)
{
return securityContext.Context.GetConnectionInfo ();
}
internal static SslConnectionInfo GetConnectionInfo (SSPIInterface SecModule, SafeDeleteContext securityContext)
{
var info = securityContext.Context.GetConnectionInfo ();
if (info == null)
return null;
return new SslConnectionInfo ((int)info.ProtocolVersion);
}
class InputBuffer : IBufferOffsetSize
{
public byte[] Buffer {
get;
private set;
}
public int Offset {
get;
private set;
}
public int Size {
get;
private set;
}
public InputBuffer (byte[] buffer, int offset, int size)
{
Buffer = buffer;
Offset = offset;
Size = size;
}
}
static IBufferOffsetSize GetInputBuffer (SecurityBuffer incoming)
{
return incoming != null ? new InputBuffer (incoming.token, incoming.offset, incoming.size) : null;
}
static void UpdateOutput (IBufferOffsetSize buffer, SecurityBuffer outputBuffer)
{
if (buffer != null) {
outputBuffer.token = buffer.Buffer;
outputBuffer.offset = buffer.Offset;
outputBuffer.size = buffer.Size;
outputBuffer.type = BufferType.Token;
} else {
outputBuffer.token = null;
outputBuffer.size = outputBuffer.offset = 0;
outputBuffer.type = BufferType.Empty;
}
}
}
}
#endif

View File

@@ -0,0 +1,141 @@
//
// Mono-specific additions to Microsoft's SslStream.cs
//
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MonoSecurity::Mono.Security.Interface;
#else
using Mono.Security.Interface;
#endif
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using MNS = Mono.Net.Security;
namespace System.Net.Security
{
using System.Net.Sockets;
using System.IO;
partial class SslStream : IMonoTlsEventSink
{
#if SECURITY_DEP
SSPIConfiguration _Configuration;
internal SslStream (Stream innerStream, bool leaveInnerStreamOpen, EncryptionPolicy encryptionPolicy, MonoTlsProvider provider, MonoTlsSettings settings)
: base (innerStream, leaveInnerStreamOpen)
{
if (encryptionPolicy != EncryptionPolicy.RequireEncryption && encryptionPolicy != EncryptionPolicy.AllowNoEncryption && encryptionPolicy != EncryptionPolicy.NoEncryption)
throw new ArgumentException (SR.GetString (SR.net_invalid_enum, "EncryptionPolicy"), "encryptionPolicy");
var validationHelper = MNS.ChainValidationHelper.CloneWithCallbackWrapper (provider, ref settings, myUserCertValidationCallbackWrapper);
LocalCertSelectionCallback selectionCallback = null;
if (validationHelper.HasCertificateSelectionCallback)
selectionCallback = validationHelper.SelectClientCertificate;
var internalProvider = new MNS.Private.MonoTlsProviderWrapper (provider);
_Configuration = new MyConfiguration (internalProvider, settings, this);
_SslState = new SslState (innerStream, null, selectionCallback, encryptionPolicy, _Configuration);
}
/*
* Mono-specific version of 'userCertValidationCallbackWrapper'; we're called from ChainValidationHelper.ValidateChain() here.
*
* Since we're built without the PrebuiltSystem alias, we can't use 'SslPolicyErrors' here. This prevents us from creating a subclass of 'ChainValidationHelper'
* as well as providing a custom 'ServerCertValidationCallback'.
*/
bool myUserCertValidationCallbackWrapper (ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors)
{
m_RemoteCertificateOrBytes = certificate == null ? null : certificate.GetRawCertData ();
if (callback == null) {
if (!_SslState.RemoteCertRequired)
sslPolicyErrors &= ~MonoSslPolicyErrors.RemoteCertificateNotAvailable;
return (sslPolicyErrors == MonoSslPolicyErrors.None);
}
return MNS.ChainValidationHelper.InvokeCallback (callback, this, certificate, chain, sslPolicyErrors);
}
class MyConfiguration : SSPIConfiguration
{
MNS.IMonoTlsProvider provider;
MonoTlsSettings settings;
IMonoTlsEventSink eventSink;
public MyConfiguration (MNS.IMonoTlsProvider provider, MonoTlsSettings settings, IMonoTlsEventSink eventSink)
{
this.provider = provider;
this.settings = settings;
this.eventSink = eventSink;
}
public MNS.IMonoTlsProvider Provider {
get { return provider; }
}
public MonoTlsSettings Settings {
get { return settings; }
}
public IMonoTlsEventSink EventSink {
get { return eventSink; }
}
}
#endif
internal bool IsClosed {
get { return _SslState.IsClosed; }
}
internal Exception LastError {
get { return lastError; }
}
#region IMonoTlsEventSink
Exception lastError;
void IMonoTlsEventSink.Error (Exception exception)
{
Interlocked.CompareExchange<Exception> (ref lastError, exception, null);
}
void IMonoTlsEventSink.ReceivedCloseNotify ()
{
}
#endregion
internal IAsyncResult BeginShutdown (AsyncCallback asyncCallback, object asyncState)
{
return _SslState.BeginShutdown (asyncCallback, asyncState);
}
internal void EndShutdown (IAsyncResult asyncResult)
{
_SslState.EndShutdown (asyncResult);
}
internal IAsyncResult BeginRenegotiate (AsyncCallback asyncCallback, object asyncState)
{
return _SslState.BeginRenegotiate (asyncCallback, asyncState);
}
internal void EndRenegotiate (IAsyncResult asyncResult)
{
_SslState.EndRenegotiate (asyncResult);
}
internal X509Certificate InternalLocalCertificate {
get { return _SslState.InternalLocalCertificate; }
}
internal MonoTlsConnectionInfo GetMonoConnectionInfo ()
{
return _SslState.GetMonoConnectionInfo ();
}
}
}
#endif

View File

@@ -0,0 +1,41 @@
//
// Mono-specific additions to Microsoft's _SecureChannel.cs
//
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MonoSecurity::Mono.Security.Interface;
#else
using Mono.Security.Interface;
#endif
namespace System.Net.Security
{
partial class SecureChannel
{
internal MonoTlsConnectionInfo GetMonoConnectionInfo ()
{
return SSPIWrapper.GetMonoConnectionInfo (m_SecModule, m_SecurityContext);
}
internal ProtocolToken CreateShutdownMessage ()
{
var buffer = SSPIWrapper.CreateShutdownMessage (m_SecModule, m_SecurityContext);
return new ProtocolToken (buffer, SecurityStatus.ContinueNeeded);
}
internal ProtocolToken CreateHelloRequestMessage ()
{
var buffer = SSPIWrapper.CreateHelloRequestMessage (m_SecModule, m_SecurityContext);
return new ProtocolToken (buffer, SecurityStatus.ContinueNeeded);
}
internal bool IsClosed {
get {
if (m_SecModule == null || m_SecurityContext == null || m_SecurityContext.IsClosed)
return true;
return SSPIWrapper.IsClosed (m_SecModule, m_SecurityContext);
}
}
}
}
#endif

View File

@@ -0,0 +1,141 @@
//
// Mono-specific additions to Microsoft's _SslState.cs
//
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MonoSecurity::Mono.Security.Interface;
#else
using Mono.Security.Interface;
#endif
namespace System.Net.Security
{
using System.IO;
using System.Threading;
using System.Net.Sockets;
partial class SslState
{
int _SentShutdown;
internal MonoTlsConnectionInfo GetMonoConnectionInfo ()
{
return Context.GetMonoConnectionInfo ();
}
internal bool IsClosed {
get { return Context.IsClosed; }
}
internal ProtocolToken CreateShutdownMessage ()
{
return Context.CreateShutdownMessage ();
}
internal ProtocolToken CreateHelloRequestMessage ()
{
return Context.CreateHelloRequestMessage ();
}
internal IAsyncResult BeginShutdown (AsyncCallback asyncCallback, object asyncState)
{
var shutdownResult = new ShutdownAsyncResult (this, asyncState, asyncCallback);
if (Interlocked.CompareExchange (ref _SentShutdown, 1, 0) == 1) {
shutdownResult.InvokeCallback ();
return shutdownResult;
}
try
{
CheckThrow (false);
shutdownResult.SentShutdown = true;
SecureStream.BeginShutdown (shutdownResult);
return shutdownResult;
} catch (Exception e) {
if (e is IOException)
throw;
throw new IOException (SR.GetString (SR.mono_net_io_shutdown), e);
}
}
internal void EndShutdown (IAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException ("asyncResult");
var shutdownResult = asyncResult as ShutdownAsyncResult;
if (shutdownResult == null)
throw new ArgumentException (SR.GetString (SR.net_io_async_result, asyncResult.GetType ().FullName), "asyncResult");
if (shutdownResult.SentShutdown)
SecureStream.EndShutdown (shutdownResult);
}
internal IAsyncResult BeginRenegotiate (AsyncCallback asyncCallback, object asyncState)
{
var lazyResult = new LazyAsyncResult (this, asyncState, asyncCallback);
if (Interlocked.Exchange (ref _NestedAuth, 1) == 1)
throw new InvalidOperationException (SR.GetString (SR.net_io_invalidnestedcall, "BeginRenegotiate", "renegotiate"));
if (Interlocked.CompareExchange (ref _PendingReHandshake, 1, 0) == 1)
throw new InvalidOperationException (SR.GetString (SR.net_io_invalidnestedcall, "BeginRenegotiate", "renegotiate"));
try {
CheckThrow (false);
SecureStream.BeginRenegotiate (lazyResult);
return lazyResult;
} catch (Exception e) {
_NestedAuth = 0;
if (e is IOException)
throw;
throw new IOException (SR.GetString (SR.mono_net_io_renegotiate), e);
}
}
internal void EndRenegotiate (IAsyncResult result)
{
if (result == null)
throw new ArgumentNullException ("asyncResult");
LazyAsyncResult lazyResult = result as LazyAsyncResult;
if (lazyResult == null)
throw new ArgumentException (SR.GetString (SR.net_io_async_result, result.GetType ().FullName), "asyncResult");
if (Interlocked.Exchange (ref _NestedAuth, 0) == 0)
throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndRenegotiate"));
SecureStream.EndRenegotiate (lazyResult);
}
internal bool CheckEnqueueHandshakeWrite (byte[] buffer, AsyncProtocolRequest asyncRequest)
{
return CheckEnqueueHandshake (buffer, asyncRequest);
}
internal void StartReHandshake (AsyncProtocolRequest asyncRequest)
{
if (IsServer) {
byte[] buffer = null;
if (CheckEnqueueHandshakeRead (ref buffer, asyncRequest))
return;
StartReceiveBlob (buffer, asyncRequest);
return;
}
ForceAuthentication (false, null, asyncRequest);
}
class ShutdownAsyncResult : LazyAsyncResult
{
public bool SentShutdown;
internal ShutdownAsyncResult (SslState instance, object userState, AsyncCallback callback)
: base (instance, userState, callback)
{
}
}
}
}
#endif

View File

@@ -0,0 +1,230 @@
//
// Mono-specific additions to Microsoft's _SslStream.cs
//
#if MONO_FEATURE_NEW_TLS && SECURITY_DEP
namespace System.Net.Security
{
using System.IO;
using System.Threading;
using System.Net.Sockets;
partial class _SslStream
{
static readonly AsyncCallback _HandshakeWriteCallback = new AsyncCallback (HandshakeWriteCallback);
static readonly HandshakeProtocolCallback _ResumeHandshakeWriteCallback = new HandshakeProtocolCallback (ResumeHandshakeWriteCallback);
internal void BeginShutdown (LazyAsyncResult lazyResult)
{
HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest (lazyResult);
if (Interlocked.Exchange (ref _NestedWrite, 1) == 1)
throw new NotSupportedException (SR.GetString (SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginShutdown" : "Shutdown"), "shutdown"));
bool failed = false;
try
{
ProtocolToken message = _SslState.CreateShutdownMessage ();
asyncRequest.SetNextRequest (HandshakeProtocolState.Shutdown, message, _ResumeHandshakeWriteCallback);
StartHandshakeWrite (asyncRequest);
} catch (Exception e) {
_SslState.FinishWrite ();
failed = true;
throw;
} finally {
if (failed)
_NestedWrite = 0;
}
}
internal void EndShutdown (LazyAsyncResult lazyResult)
{
if (Interlocked.Exchange (ref _NestedWrite, 0) == 0)
throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndShutdown"));
// No "artificial" timeouts implemented so far, InnerStream controls timeout.
lazyResult.InternalWaitForCompletion ();
if (lazyResult.Result is Exception) {
if (lazyResult.Result is IOException)
throw (Exception)lazyResult.Result;
throw new IOException (SR.GetString (SR.mono_net_io_shutdown), (Exception)lazyResult.Result);
}
}
internal void BeginRenegotiate (LazyAsyncResult lazyResult)
{
HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest (lazyResult);
if (Interlocked.Exchange (ref _NestedWrite, 1) == 1)
throw new NotSupportedException (SR.GetString (SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRenegotiate" : "Renegotiate"), "renegotiate"));
bool failed = false;
try
{
if (_SslState.IsServer) {
ProtocolToken message = _SslState.CreateHelloRequestMessage ();
asyncRequest.SetNextRequest (HandshakeProtocolState.SendHelloRequest, message, _ResumeHandshakeWriteCallback);
} else {
asyncRequest.SetNextRequest (HandshakeProtocolState.ClientRenegotiation, null, _ResumeHandshakeWriteCallback);
}
StartHandshakeWrite (asyncRequest);
} catch (Exception e) {
_SslState.FinishWrite ();
failed = true;
throw;
} finally {
if (failed)
_NestedWrite = 0;
}
}
internal void EndRenegotiate (LazyAsyncResult lazyResult)
{
if (Interlocked.Exchange (ref _NestedWrite, 0) == 0)
throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndRenegotiate"));
// No "artificial" timeouts implemented so far, InnerStream controls timeout.
lazyResult.InternalWaitForCompletion();
if (lazyResult.Result is Exception) {
if (lazyResult.Result is IOException)
throw (Exception)lazyResult.Result;
throw new IOException (SR.GetString (SR.mono_net_io_renegotiate), (Exception)lazyResult.Result);
}
}
void StartHandshakeWrite (HandshakeProtocolRequest asyncRequest)
{
byte[] buffer = null;
if (asyncRequest.Message != null) {
buffer = asyncRequest.Message.Payload;
if (buffer.Length != asyncRequest.Message.Size) {
buffer = new byte [asyncRequest.Message.Size];
Buffer.BlockCopy (asyncRequest.Message.Payload, 0, buffer, 0, buffer.Length);
}
}
switch (asyncRequest.State) {
case HandshakeProtocolState.ClientRenegotiation:
case HandshakeProtocolState.ServerRenegotiation:
_SslState.StartReHandshake (asyncRequest);
return;
case HandshakeProtocolState.SendHelloRequest:
if (_SslState.CheckEnqueueHandshakeWrite (buffer, asyncRequest)) {
// operation is async and has been queued, return.
return;
}
break;
case HandshakeProtocolState.Shutdown:
if (_SslState.CheckEnqueueWrite (asyncRequest)) {
// operation is async and has been queued, return.
return;
}
break;
default:
throw new InvalidOperationException ();
}
if (_SslState.LastPayload != null)
throw new InvalidOperationException ();
// prepare for the next request
IAsyncResult ar = ((NetworkStream)_SslState.InnerStream).BeginWrite (buffer, 0, buffer.Length, _HandshakeWriteCallback, asyncRequest);
if (!ar.CompletedSynchronously)
return;
HandshakeWriteCallback (asyncRequest, ar);
}
static void HandshakeWriteCallback (IAsyncResult transportResult)
{
if (transportResult.CompletedSynchronously)
return;
HandshakeProtocolRequest asyncRequest = (HandshakeProtocolRequest)transportResult.AsyncState;
SslState sslState = (SslState)asyncRequest.AsyncObject;
sslState.SecureStream.HandshakeWriteCallback (asyncRequest, transportResult);
}
void HandshakeWriteCallback (HandshakeProtocolRequest asyncRequest, IAsyncResult transportResult)
{
try {
_SslState.InnerStream.EndWrite (transportResult);
} catch (Exception e) {
_SslState.FinishWrite ();
if (!asyncRequest.IsUserCompleted) {
asyncRequest.CompleteWithError (e);
return;
}
throw;
}
if (asyncRequest.State == HandshakeProtocolState.SendHelloRequest) {
asyncRequest.SetNextRequest (HandshakeProtocolState.ServerRenegotiation, null, _ResumeHandshakeWriteCallback);
StartHandshakeWrite (asyncRequest);
return;
}
try {
_SslState.FinishWrite ();
asyncRequest.CompleteUser ();
} catch (Exception e) {
if (!asyncRequest.IsUserCompleted) {
asyncRequest.CompleteWithError (e);
return;
}
throw;
}
}
static void ResumeHandshakeWriteCallback (HandshakeProtocolRequest asyncRequest)
{
try {
((_SslStream)asyncRequest.AsyncObject).StartHandshakeWrite (asyncRequest);
} catch (Exception e) {
if (asyncRequest.IsUserCompleted) {
// This will throw on a worker thread.
throw;
}
((_SslStream)asyncRequest.AsyncObject)._SslState.FinishWrite ();
asyncRequest.CompleteWithError (e);
}
}
delegate void HandshakeProtocolCallback (HandshakeProtocolRequest asyncRequest);
enum HandshakeProtocolState {
None,
Shutdown,
SendHelloRequest,
ServerRenegotiation,
ClientRenegotiation
}
class HandshakeProtocolRequest : AsyncProtocolRequest
{
public ProtocolToken Message;
public HandshakeProtocolState State;
public HandshakeProtocolRequest (LazyAsyncResult userAsyncResult)
: base (userAsyncResult)
{
State = HandshakeProtocolState.None;
}
public void SetNextRequest (HandshakeProtocolState state, ProtocolToken message, HandshakeProtocolCallback callback)
{
State = state;
Message = message;
SetNextRequest (null, 0, 0, (r) => callback ((HandshakeProtocolRequest)r));
}
}
}
}
#endif