You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
80
mcs/class/System/ReferenceSources/Internal.cs
Normal file
80
mcs/class/System/ReferenceSources/Internal.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -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";
|
||||
|
12
mcs/class/System/ReferenceSources/SR2.cs
Normal file
12
mcs/class/System/ReferenceSources/SR2.cs
Normal 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";
|
||||
}
|
53
mcs/class/System/ReferenceSources/SSPIConfiguration.cs
Normal file
53
mcs/class/System/ReferenceSources/SSPIConfiguration.cs
Normal 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
|
208
mcs/class/System/ReferenceSources/SSPISafeHandles.cs
Normal file
208
mcs/class/System/ReferenceSources/SSPISafeHandles.cs
Normal 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
|
311
mcs/class/System/ReferenceSources/SSPIWrapper.cs
Normal file
311
mcs/class/System/ReferenceSources/SSPIWrapper.cs
Normal 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
|
141
mcs/class/System/ReferenceSources/SslStream.cs
Normal file
141
mcs/class/System/ReferenceSources/SslStream.cs
Normal 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
|
41
mcs/class/System/ReferenceSources/_SecureChannel.cs
Normal file
41
mcs/class/System/ReferenceSources/_SecureChannel.cs
Normal 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
|
141
mcs/class/System/ReferenceSources/_SslState.cs
Normal file
141
mcs/class/System/ReferenceSources/_SslState.cs
Normal 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
|
230
mcs/class/System/ReferenceSources/_SslStream.cs
Normal file
230
mcs/class/System/ReferenceSources/_SslStream.cs
Normal 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
|
Reference in New Issue
Block a user