You've already forked linux-packaging-mono
Imported Upstream version 6.8.0.73
Former-commit-id: d18deab1b47cfd3ad8cba82b3f37d00eec2170af
This commit is contained in:
parent
bceda29824
commit
73ee7591e8
@ -604,6 +604,7 @@ public class Tests : TestsBase, ITest2
|
||||
if_property_stepping();
|
||||
fixed_size_array();
|
||||
test_new_exception_filter();
|
||||
test_async_debug_generics();
|
||||
return 3;
|
||||
}
|
||||
|
||||
@ -903,6 +904,17 @@ public class Tests : TestsBase, ITest2
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.NoInlining)]
|
||||
public static void test_async_debug_generics () {
|
||||
ExecuteAsync_Broken<object>().Wait ();
|
||||
}
|
||||
|
||||
async static Task<T> ExecuteAsync_Broken<T>()
|
||||
{
|
||||
await Task.Delay(2);
|
||||
return default;
|
||||
}
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.NoInlining)]
|
||||
public static void inspect_enumerator_in_generic_struct() {
|
||||
TestEnumeratorInsideGenericStruct<String, String> generic_struct = new TestEnumeratorInsideGenericStruct<String, String>(new KeyValuePair<string, string>("0", "f1"));
|
||||
|
@ -1 +1 @@
|
||||
2bccbb137b170a01de42625d65883e868c508913
|
||||
52da50a45dbfc7510ab393f4a443ee0caae46b7b
|
@ -139,6 +139,7 @@ namespace Mono.Attach
|
||||
else {
|
||||
writer.Write ((sbyte)PrimitiveType.PRIM_TYPE_STRING);
|
||||
writer.Write (s);
|
||||
writer.Write ((byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,33 +43,16 @@ namespace Mono.Messaging.RabbitMQ {
|
||||
public class RabbitMQMessagingProvider : IMessagingProvider {
|
||||
|
||||
private int txCounter = 0;
|
||||
private readonly uint localIp;
|
||||
private readonly Guid localId;
|
||||
private readonly MessagingContextPool contextPool;
|
||||
|
||||
public RabbitMQMessagingProvider ()
|
||||
{
|
||||
localIp = GetLocalIP ();
|
||||
localId = Guid.NewGuid ();
|
||||
contextPool = new MessagingContextPool (new MessageFactory (this),
|
||||
CreateConnection);
|
||||
}
|
||||
|
||||
private static uint GetLocalIP ()
|
||||
{
|
||||
String strHostName = Dns.GetHostName ();
|
||||
IPHostEntry ipEntry = Dns.GetHostByName (strHostName);
|
||||
foreach (IPAddress ip in ipEntry.AddressList) {
|
||||
if (AddressFamily.InterNetwork == ip.AddressFamily) {
|
||||
byte[] addr = ip.GetAddressBytes ();
|
||||
uint localIP = 0;
|
||||
for (int i = 0; i < 4 && i < addr.Length; i++) {
|
||||
localIP += (uint) (addr[i] << 8 * (3 - i));
|
||||
}
|
||||
return localIP;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public IMessage CreateMessage ()
|
||||
{
|
||||
return new MessageBase ();
|
||||
@ -78,7 +61,7 @@ namespace Mono.Messaging.RabbitMQ {
|
||||
public IMessageQueueTransaction CreateMessageQueueTransaction ()
|
||||
{
|
||||
Interlocked.Increment (ref txCounter);
|
||||
string txId = localIp.ToString () + txCounter.ToString ();
|
||||
string txId = localId.ToString () + "_" + txCounter.ToString ();
|
||||
|
||||
return new RabbitMQMessageQueueTransaction (txId, contextPool);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ Mono.Unix/UnixPathTest.cs
|
||||
Mono.Unix/UnixSignalTest.cs
|
||||
Mono.Unix/UnixUserTest.cs
|
||||
Mono.Unix.Android/TestHelper.cs
|
||||
Mono.Unix.Native/OFDLockTest.cs
|
||||
Mono.Unix.Native/RealTimeSignumTests.cs
|
||||
Mono.Unix.Native/SocketTest.cs
|
||||
Mono.Unix.Native/StdlibTest.cs
|
||||
|
@ -1 +1 @@
|
||||
6cc67dda4b894bb3ef0dffdc49ae8e816665c012
|
||||
c9eb750d22227382cc4989053d328c0e7fc0bc79
|
133
mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs
Normal file
133
mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs
Normal file
@ -0,0 +1,133 @@
|
||||
//
|
||||
// Tests for FcntlCommand.F_OFD_{GETLK,SETLK,SETLKW}
|
||||
//
|
||||
// Authors:
|
||||
// Steffen Kiess (kiess@ki4.de)
|
||||
//
|
||||
// Copyright (C) 2019 Steffen Kiess
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Mono.Unix;
|
||||
using Mono.Unix.Native;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace MonoTests.Mono.Unix.Native
|
||||
{
|
||||
[TestFixture, Category ("NotDotNet"), Category ("NotOnWindows"), Category ("NotOnMac")]
|
||||
public class OFDLockTest {
|
||||
|
||||
string TempFolder;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp ()
|
||||
{
|
||||
TempFolder = Path.Combine (Path.GetTempPath (), this.GetType ().FullName);
|
||||
|
||||
if (Directory.Exists (TempFolder))
|
||||
Directory.Delete (TempFolder, true);
|
||||
|
||||
Directory.CreateDirectory (TempFolder);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (Directory.Exists (TempFolder))
|
||||
Directory.Delete (TempFolder, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOFDLock ()
|
||||
{
|
||||
int fd1 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR | OpenFlags.O_CREAT | OpenFlags.O_EXCL, FilePermissions.DEFFILEMODE);
|
||||
if (fd1 < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
int fd2 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR);
|
||||
if (fd2 < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
int fd3 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR);
|
||||
if (fd3 < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
// Get read lock for first 100 bytes on fd1
|
||||
var flock1 = new Flock {
|
||||
l_type = LockType.F_RDLCK,
|
||||
l_whence = SeekFlags.SEEK_SET,
|
||||
l_start = 0,
|
||||
l_len = 100,
|
||||
};
|
||||
if (Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLKW, ref flock1) < 0) {
|
||||
// Old kernels and non-linux systems should return EINVAL
|
||||
if (Stdlib.GetLastError () == Errno.EINVAL)
|
||||
Assert.Ignore ("F_OFD_SETLKW does not seem to be supported.");
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
}
|
||||
|
||||
// Get read lock for first 100 bytes on fd2
|
||||
var flock2 = new Flock {
|
||||
l_type = LockType.F_RDLCK,
|
||||
l_whence = SeekFlags.SEEK_SET,
|
||||
l_start = 0,
|
||||
l_len = 100,
|
||||
};
|
||||
if (Syscall.fcntl (fd2, FcntlCommand.F_OFD_SETLK, ref flock2) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
// Get write lock for remaining bytes on fd1
|
||||
var flock3 = new Flock {
|
||||
l_type = LockType.F_WRLCK,
|
||||
l_whence = SeekFlags.SEEK_SET,
|
||||
l_start = 100,
|
||||
l_len = 0,
|
||||
};
|
||||
if (Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLK, ref flock3) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
// Close fd3, should not release lock
|
||||
if (Syscall.close (fd3) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
// Get lock status for byte 150 from fd2
|
||||
var flock4 = new Flock {
|
||||
l_type = LockType.F_RDLCK,
|
||||
l_whence = SeekFlags.SEEK_SET,
|
||||
l_start = 150,
|
||||
l_len = 1,
|
||||
};
|
||||
if (Syscall.fcntl (fd2, FcntlCommand.F_OFD_GETLK, ref flock4) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
// There should be a conflicting write lock
|
||||
Assert.AreEqual (LockType.F_WRLCK, flock4.l_type);
|
||||
|
||||
// Get write byte 0 on fd1, should fail with EAGAIN
|
||||
var flock5 = new Flock {
|
||||
l_type = LockType.F_WRLCK,
|
||||
l_whence = SeekFlags.SEEK_SET,
|
||||
l_start = 0,
|
||||
l_len = 1,
|
||||
};
|
||||
var res = Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLK, ref flock5);
|
||||
Assert.AreEqual (-1, res);
|
||||
Assert.AreEqual (Errno.EAGAIN, Stdlib.GetLastError ());
|
||||
|
||||
if (Syscall.close (fd1) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
if (Syscall.close (fd2) < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
||||
// Local Variables:
|
||||
// tab-width: 4
|
||||
// c-basic-offset: 4
|
||||
// indent-tabs-mode: t
|
||||
// End:
|
@ -172,6 +172,7 @@ namespace Mono.Profiler.Log {
|
||||
Debugger = 13,
|
||||
Handle = 14,
|
||||
Ephemeron = 15,
|
||||
Toggleref = 16,
|
||||
}
|
||||
|
||||
// mono/profiler/log.h : MonoProfilerMonitorEvent
|
||||
|
@ -96,14 +96,6 @@ namespace Mono.Security.Interface
|
||||
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509CertificateCollection certificates);
|
||||
}
|
||||
|
||||
internal interface ICertificateValidator2 : ICertificateValidator
|
||||
{
|
||||
/*
|
||||
* Internal use only.
|
||||
*/
|
||||
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain);
|
||||
}
|
||||
|
||||
public static class CertificateValidationHelper
|
||||
{
|
||||
const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
|
||||
|
@ -42,59 +42,11 @@ namespace Mono.Security.Interface
|
||||
get;
|
||||
}
|
||||
|
||||
void AuthenticateAsClient (string targetHost);
|
||||
|
||||
void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
|
||||
|
||||
void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
void EndAuthenticateAsClient (IAsyncResult asyncResult);
|
||||
|
||||
void AuthenticateAsServer (X509Certificate serverCertificate);
|
||||
|
||||
void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
|
||||
|
||||
void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
void EndAuthenticateAsServer (IAsyncResult asyncResult);
|
||||
|
||||
Task AuthenticateAsClientAsync (string targetHost);
|
||||
|
||||
Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
|
||||
|
||||
Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
|
||||
|
||||
Task AuthenticateAsServerAsync (X509Certificate serverCertificate);
|
||||
|
||||
Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
|
||||
|
||||
Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
|
||||
|
||||
int Read (byte[] buffer, int offset, int count);
|
||||
|
||||
void Write (byte[] buffer);
|
||||
|
||||
void Write (byte[] buffer, int offset, int count);
|
||||
|
||||
IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
int EndRead (IAsyncResult asyncResult);
|
||||
|
||||
IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState);
|
||||
|
||||
void EndWrite (IAsyncResult asyncResult);
|
||||
Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken);
|
||||
|
||||
Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken);
|
||||
|
||||
@ -215,12 +167,5 @@ namespace Mono.Security.Interface
|
||||
|
||||
Task RenegotiateAsync (CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
interface IMonoSslStream2 : IMonoSslStream
|
||||
{
|
||||
Task AuthenticateAsClientAsync (IMonoSslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken);
|
||||
|
||||
Task AuthenticateAsServerAsync (IMonoSslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,10 +121,6 @@ namespace Mono.Security.Interface
|
||||
Stream innerStream, bool leaveInnerStreamOpen,
|
||||
MonoTlsSettings settings = null);
|
||||
|
||||
internal abstract IMonoSslStream CreateSslStreamInternal (
|
||||
SslStream sslStream, Stream innerStream, bool leaveInnerStreamOpen,
|
||||
MonoTlsSettings settings);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Native Certificate Implementation
|
||||
@ -133,34 +129,6 @@ namespace Mono.Security.Interface
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
internal virtual X509Certificate2Impl GetNativeCertificate (
|
||||
byte[] data, string password, X509KeyStorageFlags flags)
|
||||
{
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
internal virtual X509Certificate2Impl GetNativeCertificate (
|
||||
X509Certificate certificate)
|
||||
{
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Certificate Validation
|
||||
/*
|
||||
* If @serverMode is true, then we're a server and want to validate a certificate
|
||||
* that we received from a client.
|
||||
*
|
||||
* On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built.
|
||||
*
|
||||
* Returns `true` if certificate validation has been performed and `false` to invoke the
|
||||
* default system validator.
|
||||
*/
|
||||
internal abstract bool ValidateCertificate (
|
||||
ICertificateValidator2 validator, string targetHost, bool serverMode,
|
||||
X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain,
|
||||
ref MonoSslPolicyErrors errors, ref int status11);
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
|
@ -183,9 +183,10 @@ namespace Mono.Security.Interface
|
||||
* - 1: everything up until May 2018
|
||||
* - 2: the new ServicePointScheduler changes have landed
|
||||
* - 3: full support for Client Certificates
|
||||
* - 4: Legacy TLS Removal
|
||||
*
|
||||
*/
|
||||
internal const int InternalVersion = 3;
|
||||
internal const int InternalVersion = 4;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -1,149 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
|
||||
//
|
||||
// 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;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
using Mono.Security.Protocol.Tls;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsClientCertificate : HandshakeMessage
|
||||
{
|
||||
private bool clientCertSelected;
|
||||
private X509Certificate clientCert;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public TlsClientCertificate(Context context)
|
||||
: base(context, HandshakeType.Certificate)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public X509Certificate ClientCertificate {
|
||||
get {
|
||||
if (!clientCertSelected)
|
||||
{
|
||||
GetClientCertificate ();
|
||||
clientCertSelected = true;
|
||||
}
|
||||
return clientCert;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
this.Reset();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
private void GetClientCertificate ()
|
||||
{
|
||||
// TODO: Client certificate selection is unfinished
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
// note: the server may ask for mutual authentication
|
||||
// but may not require it (i.e. it can be optional).
|
||||
if (context.ClientSettings.Certificates != null &&
|
||||
context.ClientSettings.Certificates.Count > 0)
|
||||
{
|
||||
clientCert = context.SslStream.RaiseClientCertificateSelection(
|
||||
this.Context.ClientSettings.Certificates,
|
||||
new X509Certificate(this.Context.ServerSettings.Certificates[0].RawData),
|
||||
this.Context.ClientSettings.TargetHost,
|
||||
null);
|
||||
// Note: the application code can raise it's
|
||||
// own exception to stop the connection too.
|
||||
}
|
||||
|
||||
// Update the selected client certificate
|
||||
context.ClientSettings.ClientCertificate = clientCert;
|
||||
}
|
||||
|
||||
private void SendCertificates ()
|
||||
{
|
||||
TlsStream chain = new TlsStream ();
|
||||
|
||||
X509Certificate currentCert = this.ClientCertificate;
|
||||
while (currentCert != null) {
|
||||
byte[] rawCert = currentCert.GetRawCertData ();
|
||||
chain.WriteInt24 (rawCert.Length);
|
||||
chain.Write(rawCert);
|
||||
currentCert = FindParentCertificate (currentCert);
|
||||
}
|
||||
this.WriteInt24 ((int)chain.Length);
|
||||
this.Write (chain.ToArray ());
|
||||
}
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
if (this.ClientCertificate != null) {
|
||||
SendCertificates ();
|
||||
} else {
|
||||
// an Alert warning for NoCertificate (41)
|
||||
// should be sent from here - but that would
|
||||
// break the current message handling
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
if (this.ClientCertificate != null) {
|
||||
SendCertificates ();
|
||||
} else {
|
||||
// return message with empty certificate (see 7.4.6 in RFC2246)
|
||||
this.WriteInt24 (0);
|
||||
}
|
||||
}
|
||||
|
||||
private X509Certificate FindParentCertificate (X509Certificate cert)
|
||||
{
|
||||
#pragma warning disable 618
|
||||
// This certificate is the root certificate
|
||||
if (cert.GetName () == cert.GetIssuerName ())
|
||||
return null;
|
||||
|
||||
foreach (X509Certificate certificate in this.Context.ClientSettings.Certificates) {
|
||||
if (certificate.GetName () == cert.GetIssuerName ())
|
||||
return certificate;
|
||||
}
|
||||
return null;
|
||||
#pragma warning restore 618
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
|
||||
//
|
||||
// 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;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using Mono.Security.Cryptography;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsClientCertificateVerify : HandshakeMessage
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public TlsClientCertificateVerify(Context context)
|
||||
: base(context, HandshakeType.CertificateVerify)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
this.Reset();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
AsymmetricAlgorithm privKey = null;
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
privKey = context.SslStream.RaisePrivateKeySelection(
|
||||
context.ClientSettings.ClientCertificate,
|
||||
context.ClientSettings.TargetHost);
|
||||
|
||||
if (privKey == null)
|
||||
{
|
||||
throw new TlsException(AlertDescription.UserCancelled, "Client certificate Private Key unavailable.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SslHandshakeHash hash = new SslHandshakeHash(context.MasterSecret);
|
||||
hash.TransformFinalBlock(
|
||||
context.HandshakeMessages.ToArray(),
|
||||
0,
|
||||
(int)context.HandshakeMessages.Length);
|
||||
|
||||
// CreateSignature uses ((RSA)privKey).DecryptValue which is not implemented
|
||||
// in RSACryptoServiceProvider. Other implementations likely implement DecryptValue
|
||||
// so we will try the CreateSignature method.
|
||||
byte[] signature = null;
|
||||
if (!(privKey is RSACryptoServiceProvider))
|
||||
{
|
||||
try
|
||||
{
|
||||
signature = hash.CreateSignature((RSA)privKey);
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{ }
|
||||
}
|
||||
// If DecryptValue is not implemented, then try to export the private
|
||||
// key and let the RSAManaged class do the DecryptValue
|
||||
if (signature == null)
|
||||
{
|
||||
// RSAManaged of the selected ClientCertificate
|
||||
// (at this moment the first one)
|
||||
RSA rsa = this.getClientCertRSA((RSA)privKey);
|
||||
|
||||
// Write message
|
||||
signature = hash.CreateSignature(rsa);
|
||||
}
|
||||
this.Write((short)signature.Length);
|
||||
this.Write(signature, 0, signature.Length);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
AsymmetricAlgorithm privKey = null;
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
privKey = context.SslStream.RaisePrivateKeySelection(
|
||||
context.ClientSettings.ClientCertificate,
|
||||
context.ClientSettings.TargetHost);
|
||||
|
||||
if (privKey == null)
|
||||
{
|
||||
throw new TlsException(AlertDescription.UserCancelled, "Client certificate Private Key unavailable.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute handshake messages hash
|
||||
MD5SHA1 hash = new MD5SHA1();
|
||||
hash.ComputeHash(
|
||||
context.HandshakeMessages.ToArray(),
|
||||
0,
|
||||
(int)context.HandshakeMessages.Length);
|
||||
|
||||
// CreateSignature uses ((RSA)privKey).DecryptValue which is not implemented
|
||||
// in RSACryptoServiceProvider. Other implementations likely implement DecryptValue
|
||||
// so we will try the CreateSignature method.
|
||||
byte[] signature = null;
|
||||
if (!(privKey is RSACryptoServiceProvider))
|
||||
{
|
||||
try
|
||||
{
|
||||
signature = hash.CreateSignature((RSA)privKey);
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{ }
|
||||
}
|
||||
// If DecryptValue is not implemented, then try to export the private
|
||||
// key and let the RSAManaged class do the DecryptValue
|
||||
if (signature == null)
|
||||
{
|
||||
// RSAManaged of the selected ClientCertificate
|
||||
// (at this moment the first one)
|
||||
RSA rsa = this.getClientCertRSA((RSA)privKey);
|
||||
|
||||
// Write message
|
||||
signature = hash.CreateSignature(rsa);
|
||||
}
|
||||
this.Write((short)signature.Length);
|
||||
this.Write(signature, 0, signature.Length);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
private RSA getClientCertRSA(RSA privKey)
|
||||
{
|
||||
RSAParameters rsaParams = new RSAParameters();
|
||||
RSAParameters privateParams = privKey.ExportParameters(true);
|
||||
|
||||
// for RSA m_publickey contains 2 ASN.1 integers
|
||||
// the modulus and the public exponent
|
||||
ASN1 pubkey = new ASN1 (this.Context.ClientSettings.Certificates[0].GetPublicKey());
|
||||
ASN1 modulus = pubkey [0];
|
||||
if ((modulus == null) || (modulus.Tag != 0x02))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ASN1 exponent = pubkey [1];
|
||||
if (exponent.Tag != 0x02)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
rsaParams.Modulus = this.getUnsignedBigInteger(modulus.Value);
|
||||
rsaParams.Exponent = exponent.Value;
|
||||
|
||||
// Set private key parameters
|
||||
rsaParams.D = privateParams.D;
|
||||
rsaParams.DP = privateParams.DP;
|
||||
rsaParams.DQ = privateParams.DQ;
|
||||
rsaParams.InverseQ = privateParams.InverseQ;
|
||||
rsaParams.P = privateParams.P;
|
||||
rsaParams.Q = privateParams.Q;
|
||||
|
||||
// BUG: MS BCL 1.0 can't import a key which
|
||||
// isn't the same size as the one present in
|
||||
// the container.
|
||||
int keySize = (rsaParams.Modulus.Length << 3);
|
||||
RSAManaged rsa = new RSAManaged(keySize);
|
||||
rsa.ImportParameters (rsaParams);
|
||||
|
||||
return (RSA)rsa;
|
||||
}
|
||||
|
||||
private byte[] getUnsignedBigInteger(byte[] integer)
|
||||
{
|
||||
if (integer [0] == 0x00)
|
||||
{
|
||||
// this first byte is added so we're sure it's an unsigned integer
|
||||
// however we can't feed it into RSAParameters or DSAParameters
|
||||
int length = integer.Length - 1;
|
||||
byte[] uinteger = new byte [length];
|
||||
Buffer.BlockCopy (integer, 1, uinteger, 0, length);
|
||||
return uinteger;
|
||||
}
|
||||
else
|
||||
{
|
||||
return integer;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
// Copyright (C) 2006 Novell, Inc (http://www.novell.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;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Mono.Security.Cryptography;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsClientFinished : HandshakeMessage
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public TlsClientFinished(Context context)
|
||||
: base(context, HandshakeType.Finished)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
this.Reset();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
static private byte[] Ssl3Marker = new byte [4] { 0x43, 0x4c, 0x4e, 0x54 };
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
// Compute handshake messages hashes
|
||||
HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
|
||||
|
||||
byte[] data = this.Context.HandshakeMessages.ToArray ();
|
||||
hash.TransformBlock (data, 0, data.Length, data, 0);
|
||||
hash.TransformBlock (Ssl3Marker, 0, Ssl3Marker.Length, Ssl3Marker, 0);
|
||||
// hack to avoid memory allocation
|
||||
hash.TransformFinalBlock (CipherSuite.EmptyArray, 0, 0);
|
||||
|
||||
this.Write (hash.Hash);
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
// Compute handshake messages hash
|
||||
HashAlgorithm hash = new MD5SHA1();
|
||||
|
||||
// note: we could call HashAlgorithm.ComputeHash(Stream) but that would allocate (on Mono)
|
||||
// a 4096 bytes buffer to process the hash - which is bigger than HandshakeMessages
|
||||
byte[] data = this.Context.HandshakeMessages.ToArray ();
|
||||
byte[] digest = hash.ComputeHash (data, 0, data.Length);
|
||||
|
||||
// Write message
|
||||
Write(this.Context.Write.Cipher.PRF(this.Context.MasterSecret, "client finished", digest, 12));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
|
||||
//
|
||||
// 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;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsClientHello : HandshakeMessage
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private byte[] random;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public TlsClientHello(Context context)
|
||||
: base(context, HandshakeType.ClientHello)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
base.Update();
|
||||
|
||||
context.ClientRandom = random;
|
||||
context.ClientHelloProtocol = this.Context.Protocol;
|
||||
|
||||
random = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
// Client Version
|
||||
this.Write(this.Context.Protocol);
|
||||
|
||||
// Random bytes - Unix time + Radom bytes [28]
|
||||
TlsStream clientRandom = new TlsStream();
|
||||
clientRandom.Write(this.Context.GetUnixTime());
|
||||
clientRandom.Write(this.Context.GetSecureRandomBytes(28));
|
||||
this.random = clientRandom.ToArray();
|
||||
clientRandom.Reset();
|
||||
|
||||
this.Write(this.random);
|
||||
|
||||
// Session id
|
||||
// Check if we have a cache session we could reuse
|
||||
this.Context.SessionId = ClientSessionCache.FromHost (this.Context.ClientSettings.TargetHost);
|
||||
if (this.Context.SessionId != null)
|
||||
{
|
||||
this.Write((byte)this.Context.SessionId.Length);
|
||||
if (this.Context.SessionId.Length > 0)
|
||||
{
|
||||
this.Write(this.Context.SessionId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write((byte)0);
|
||||
}
|
||||
|
||||
// Write length of Cipher suites
|
||||
this.Write((short)(this.Context.SupportedCiphers.Count*2));
|
||||
|
||||
// Write Supported Cipher suites
|
||||
for (int i = 0; i < this.Context.SupportedCiphers.Count; i++)
|
||||
{
|
||||
this.Write((short)this.Context.SupportedCiphers[i].Code);
|
||||
}
|
||||
|
||||
// Compression methods length
|
||||
this.Write((byte)1);
|
||||
|
||||
// Compression methods ( 0 = none )
|
||||
this.Write((byte)this.Context.CompressionMethod);
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
ProcessAsSsl3 ();
|
||||
|
||||
// If applicable add the "server_name" extension to the hello message
|
||||
// http://www.ietf.org/rfc/rfc3546.txt
|
||||
string host = Context.ClientSettings.TargetHost;
|
||||
// Our TargetHost might be an address (not a host *name*) - see bug #8553
|
||||
// RFC3546 -> Literal IPv4 and IPv6 addresses are not permitted in "HostName".
|
||||
IPAddress addr;
|
||||
if (IPAddress.TryParse (host, out addr))
|
||||
return;
|
||||
|
||||
TlsStream extensions = new TlsStream ();
|
||||
byte[] server_name = System.Text.Encoding.UTF8.GetBytes (host);
|
||||
extensions.Write ((short) 0x0000); // ExtensionType: server_name (0)
|
||||
extensions.Write ((short) (server_name.Length + 5)); // ServerNameList (length)
|
||||
extensions.Write ((short) (server_name.Length + 3)); // ServerName (length)
|
||||
extensions.Write ((byte) 0x00); // NameType: host_name (0)
|
||||
extensions.Write ((short) server_name.Length); // HostName (length)
|
||||
extensions.Write (server_name); // HostName (UTF8)
|
||||
this.Write ((short) extensions.Length);
|
||||
this.Write (extensions.ToArray ());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
// Copyright (C) 2006 Novell, Inc (http://www.novell.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;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Mono.Security.Cryptography;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsClientKeyExchange : HandshakeMessage
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public TlsClientKeyExchange (Context context) :
|
||||
base(context, HandshakeType.ClientKeyExchange)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
// a large chunk of code is common to both SSL3 and TLS1
|
||||
// SSL3 doesn't send the length of the buffer
|
||||
ProcessCommon (false);
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
// a large chunk of code is common to both SSL3 and TLS1
|
||||
// TLS1 does send the length of the buffer
|
||||
ProcessCommon (true);
|
||||
}
|
||||
|
||||
public void ProcessCommon (bool sendLength)
|
||||
{
|
||||
// Compute pre master secret
|
||||
byte[] preMasterSecret = this.Context.Negotiating.Cipher.CreatePremasterSecret ();
|
||||
|
||||
// Create a new RSA key
|
||||
RSA rsa = null;
|
||||
if (this.Context.ServerSettings.ServerKeyExchange)
|
||||
{
|
||||
// this is the case for "exportable" ciphers
|
||||
rsa = new RSAManaged ();
|
||||
rsa.ImportParameters (this.Context.ServerSettings.RsaParameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
rsa = this.Context.ServerSettings.CertificateRSA;
|
||||
}
|
||||
|
||||
// Encrypt premaster_sercret
|
||||
RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter (rsa);
|
||||
|
||||
// Write the preMasterSecret encrypted
|
||||
byte[] buffer = formatter.CreateKeyExchange (preMasterSecret);
|
||||
if (sendLength)
|
||||
this.Write ((short) buffer.Length);
|
||||
this.Write (buffer);
|
||||
|
||||
// Create master secret
|
||||
this.Context.Negotiating.Cipher.ComputeMasterSecret (preMasterSecret);
|
||||
|
||||
// Create keys
|
||||
this.Context.Negotiating.Cipher.ComputeKeys ();
|
||||
|
||||
// Clear resources
|
||||
rsa.Clear ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,450 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
// Copyright (C) 2004, 2006-2010 Novell, Inc (http://www.novell.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;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Security.Cryptography;
|
||||
using X509Cert = System.Security.Cryptography.X509Certificates;
|
||||
|
||||
using Mono.Security.X509;
|
||||
using Mono.Security.X509.Extensions;
|
||||
|
||||
using Mono.Security.Interface;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsServerCertificate : HandshakeMessage
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private X509CertificateCollection certificates;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public TlsServerCertificate(Context context, byte[] buffer)
|
||||
: base(context, HandshakeType.Certificate, buffer)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
this.Context.ServerSettings.Certificates = this.certificates;
|
||||
this.Context.ServerSettings.UpdateCertificateRSA();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
this.ProcessAsTls1();
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
this.certificates = new X509CertificateCollection();
|
||||
|
||||
int readed = 0;
|
||||
int length = this.ReadInt24();
|
||||
|
||||
while (readed < length)
|
||||
{
|
||||
// Read certificate length
|
||||
int certLength = ReadInt24();
|
||||
|
||||
// Increment readed
|
||||
readed += 3;
|
||||
|
||||
if (certLength > 0)
|
||||
{
|
||||
// Read certificate data
|
||||
byte[] buffer = this.ReadBytes(certLength);
|
||||
|
||||
// Create a new X509 Certificate
|
||||
X509Certificate certificate = new X509Certificate(buffer);
|
||||
certificates.Add(certificate);
|
||||
|
||||
readed += certLength;
|
||||
|
||||
DebugHelper.WriteLine(
|
||||
String.Format("Server Certificate {0}", certificates.Count),
|
||||
buffer);
|
||||
}
|
||||
}
|
||||
|
||||
this.validateCertificates(certificates);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
// Note: this method only works for RSA certificates
|
||||
// DH certificates requires some changes - does anyone use one ?
|
||||
private bool checkCertificateUsage (X509Certificate cert)
|
||||
{
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
// certificate extensions are required for this
|
||||
// we "must" accept older certificates without proofs
|
||||
if (cert.Version < 3)
|
||||
return true;
|
||||
|
||||
KeyUsages ku = KeyUsages.none;
|
||||
switch (context.Negotiating.Cipher.ExchangeAlgorithmType)
|
||||
{
|
||||
case ExchangeAlgorithmType.RsaSign:
|
||||
ku = KeyUsages.digitalSignature;
|
||||
break;
|
||||
case ExchangeAlgorithmType.RsaKeyX:
|
||||
ku = KeyUsages.keyEncipherment;
|
||||
break;
|
||||
case ExchangeAlgorithmType.DiffieHellman:
|
||||
ku = KeyUsages.keyAgreement;
|
||||
break;
|
||||
case ExchangeAlgorithmType.Fortezza:
|
||||
return false; // unsupported certificate type
|
||||
}
|
||||
|
||||
KeyUsageExtension kux = null;
|
||||
ExtendedKeyUsageExtension eku = null;
|
||||
|
||||
X509Extension xtn = cert.Extensions ["2.5.29.15"];
|
||||
if (xtn != null)
|
||||
kux = new KeyUsageExtension (xtn);
|
||||
|
||||
xtn = cert.Extensions ["2.5.29.37"];
|
||||
if (xtn != null)
|
||||
eku = new ExtendedKeyUsageExtension (xtn);
|
||||
|
||||
if ((kux != null) && (eku != null))
|
||||
{
|
||||
// RFC3280 states that when both KeyUsageExtension and
|
||||
// ExtendedKeyUsageExtension are present then BOTH should
|
||||
// be valid
|
||||
if (!kux.Support (ku))
|
||||
return false;
|
||||
return (eku.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.1") ||
|
||||
eku.KeyPurpose.Contains ("2.16.840.1.113730.4.1"));
|
||||
}
|
||||
else if (kux != null)
|
||||
{
|
||||
return kux.Support (ku);
|
||||
}
|
||||
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.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.1") ||
|
||||
eku.KeyPurpose.Contains ("2.16.840.1.113730.4.1"));
|
||||
}
|
||||
|
||||
// last chance - try with older (deprecated) Netscape extensions
|
||||
xtn = cert.Extensions ["2.16.840.1.113730.1.1"];
|
||||
if (xtn != null)
|
||||
{
|
||||
NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension (xtn);
|
||||
return ct.Support (NetscapeCertTypeExtension.CertTypes.SslServer);
|
||||
}
|
||||
|
||||
// if the CN=host (checked later) then we assume this is meant for SSL/TLS
|
||||
// e.g. the new smtp.gmail.com certificate
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validateCertificates(X509CertificateCollection certificates)
|
||||
{
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
AlertDescription description = AlertDescription.BadCertificate;
|
||||
|
||||
#if INSIDE_SYSTEM
|
||||
// This helps the linker to remove a lot of validation code that will never be used since
|
||||
// System.dll will, for OSX and iOS, uses the operating system X.509 certificate validations
|
||||
RemoteValidation (context, description);
|
||||
#else
|
||||
if (context.SslStream.HaveRemoteValidation2Callback)
|
||||
RemoteValidation (context, description);
|
||||
else
|
||||
LocalValidation (context, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RemoteValidation (ClientContext context, AlertDescription description)
|
||||
{
|
||||
ValidationResult res = context.SslStream.RaiseServerCertificateValidation2 (certificates);
|
||||
if (res.Trusted)
|
||||
return;
|
||||
|
||||
long error = res.ErrorCode;
|
||||
switch (error) {
|
||||
case 0x800B0101:
|
||||
description = AlertDescription.CertificateExpired;
|
||||
break;
|
||||
case 0x800B010A:
|
||||
description = AlertDescription.UnknownCA;
|
||||
break;
|
||||
case 0x800B0109:
|
||||
description = AlertDescription.UnknownCA;
|
||||
break;
|
||||
default:
|
||||
description = AlertDescription.CertificateUnknown;
|
||||
break;
|
||||
}
|
||||
string err = String.Format ("Invalid certificate received from server. Error code: 0x{0:x}", error);
|
||||
throw new TlsException (description, err);
|
||||
}
|
||||
|
||||
void LocalValidation (ClientContext context, AlertDescription description)
|
||||
{
|
||||
// the leaf is the web server certificate
|
||||
X509Certificate leaf = certificates [0];
|
||||
X509Cert.X509Certificate cert = new X509Cert.X509Certificate (leaf.RawData);
|
||||
|
||||
ArrayList errors = new ArrayList();
|
||||
|
||||
// SSL specific check - not all certificates can be
|
||||
// used to server-side SSL some rules applies after
|
||||
// all ;-)
|
||||
if (!checkCertificateUsage (leaf))
|
||||
{
|
||||
// WinError.h CERT_E_PURPOSE 0x800B0106
|
||||
errors.Add ((int)-2146762490);
|
||||
}
|
||||
|
||||
// SSL specific check - does the certificate match
|
||||
// the host ?
|
||||
if (!checkServerIdentity (leaf))
|
||||
{
|
||||
// WinError.h CERT_E_CN_NO_MATCH 0x800B010F
|
||||
errors.Add ((int)-2146762481);
|
||||
}
|
||||
|
||||
// Note: building and verifying a chain can take much time
|
||||
// so we do it last (letting simple things fails first)
|
||||
|
||||
// Note: In TLS the certificates MUST be in order (and
|
||||
// optionally include the root certificate) so we're not
|
||||
// building the chain using LoadCertificate (it's faster)
|
||||
|
||||
// Note: IIS doesn't seem to send the whole certificate chain
|
||||
// but only the server certificate :-( it's assuming that you
|
||||
// already have this chain installed on your computer. duh!
|
||||
// http://groups.google.ca/groups?q=IIS+server+certificate+chain&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=85058s%24avd%241%40nnrp1.deja.com&rnum=3
|
||||
|
||||
// we must remove the leaf certificate from the chain
|
||||
X509CertificateCollection chain = new X509CertificateCollection (certificates);
|
||||
chain.Remove (leaf);
|
||||
X509Chain verify = new X509Chain (chain);
|
||||
|
||||
bool result = false;
|
||||
|
||||
try
|
||||
{
|
||||
result = verify.Build (leaf);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
switch (verify.Status)
|
||||
{
|
||||
case X509ChainStatusFlags.InvalidBasicConstraints:
|
||||
// WinError.h TRUST_E_BASIC_CONSTRAINTS 0x80096019
|
||||
errors.Add ((int)-2146869223);
|
||||
break;
|
||||
|
||||
case X509ChainStatusFlags.NotSignatureValid:
|
||||
// WinError.h TRUST_E_BAD_DIGEST 0x80096010
|
||||
errors.Add ((int)-2146869232);
|
||||
break;
|
||||
|
||||
case X509ChainStatusFlags.NotTimeNested:
|
||||
// WinError.h CERT_E_VALIDITYPERIODNESTING 0x800B0102
|
||||
errors.Add ((int)-2146762494);
|
||||
break;
|
||||
|
||||
case X509ChainStatusFlags.NotTimeValid:
|
||||
// WinError.h CERT_E_EXPIRED 0x800B0101
|
||||
description = AlertDescription.CertificateExpired;
|
||||
errors.Add ((int)-2146762495);
|
||||
break;
|
||||
|
||||
case X509ChainStatusFlags.PartialChain:
|
||||
// WinError.h CERT_E_CHAINING 0x800B010A
|
||||
description = AlertDescription.UnknownCA;
|
||||
errors.Add ((int)-2146762486);
|
||||
break;
|
||||
|
||||
case X509ChainStatusFlags.UntrustedRoot:
|
||||
// WinError.h CERT_E_UNTRUSTEDROOT 0x800B0109
|
||||
description = AlertDescription.UnknownCA;
|
||||
errors.Add ((int)-2146762487);
|
||||
break;
|
||||
|
||||
default:
|
||||
// unknown error
|
||||
description = AlertDescription.CertificateUnknown;
|
||||
errors.Add ((int)verify.Status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int[] certificateErrors = (int[])errors.ToArray(typeof(int));
|
||||
|
||||
if (!context.SslStream.RaiseServerCertificateValidation(
|
||||
cert,
|
||||
certificateErrors))
|
||||
{
|
||||
throw new TlsException(
|
||||
description,
|
||||
"Invalid certificate received from server.");
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
private bool checkServerIdentity (X509Certificate cert)
|
||||
{
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
string targetHost = context.ClientSettings.TargetHost;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private bool checkDomainName(string subjectName)
|
||||
{
|
||||
ClientContext context = (ClientContext)this.Context;
|
||||
|
||||
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 (context.ClientSettings.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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
|
||||
//
|
||||
// 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;
|
||||
using System.Text;
|
||||
using Mono.Security;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsServerCertificateRequest : HandshakeMessage
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private ClientCertificateType[] certificateTypes;
|
||||
private string[] distinguisedNames;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public TlsServerCertificateRequest(Context context, byte[] buffer)
|
||||
: base(context, HandshakeType.CertificateRequest, buffer)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
this.Context.ServerSettings.CertificateTypes = this.certificateTypes;
|
||||
this.Context.ServerSettings.DistinguisedNames = this.distinguisedNames;
|
||||
this.Context.ServerSettings.CertificateRequest = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
this.ProcessAsTls1();
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
// Read requested certificate types
|
||||
int typesCount = this.ReadByte();
|
||||
|
||||
this.certificateTypes = new ClientCertificateType[typesCount];
|
||||
|
||||
for (int i = 0; i < typesCount; i++)
|
||||
{
|
||||
this.certificateTypes[i] = (ClientCertificateType)this.ReadByte();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read requested certificate authorities (Distinguised Names)
|
||||
*
|
||||
* Name ::= SEQUENCE OF RelativeDistinguishedName
|
||||
*
|
||||
* RelativeDistinguishedName ::= SET OF AttributeValueAssertion
|
||||
*
|
||||
* AttributeValueAssertion ::= SEQUENCE {
|
||||
* attributeType OBJECT IDENTIFIER
|
||||
* attributeValue ANY }
|
||||
*/
|
||||
if (this.ReadInt16() != 0)
|
||||
{
|
||||
ASN1 rdn = new ASN1(this.ReadBytes(this.ReadInt16()));
|
||||
|
||||
distinguisedNames = new string[rdn.Count];
|
||||
|
||||
for (int i = 0; i < rdn.Count; i++)
|
||||
{
|
||||
// element[0] = attributeType
|
||||
// element[1] = attributeValue
|
||||
ASN1 element = new ASN1(rdn[i].Value);
|
||||
|
||||
distinguisedNames[i] = Encoding.UTF8.GetString(element[1].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
// Transport Security Layer (TLS)
|
||||
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
|
||||
// Copyright (C) 2006 Novell, Inc (http://www.novell.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;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Mono.Security.Cryptography;
|
||||
|
||||
namespace Mono.Security.Protocol.Tls.Handshake.Client
|
||||
{
|
||||
internal class TlsServerFinished : HandshakeMessage
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public TlsServerFinished(Context context, byte[] buffer)
|
||||
: base(context, HandshakeType.Finished, buffer)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Hahdshake is finished
|
||||
this.Context.HandshakeState = HandshakeState.Finished;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
static private byte[] Ssl3Marker = new byte [4] { 0x53, 0x52, 0x56, 0x52 };
|
||||
|
||||
protected override void ProcessAsSsl3()
|
||||
{
|
||||
// Compute handshake messages hashes
|
||||
HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
|
||||
|
||||
byte[] data = this.Context.HandshakeMessages.ToArray ();
|
||||
hash.TransformBlock (data, 0, data.Length, data, 0);
|
||||
hash.TransformBlock (Ssl3Marker, 0, Ssl3Marker.Length, Ssl3Marker, 0);
|
||||
// hack to avoid memory allocation
|
||||
hash.TransformFinalBlock (CipherSuite.EmptyArray, 0, 0);
|
||||
|
||||
byte[] serverHash = this.ReadBytes((int)Length);
|
||||
byte[] clientHash = hash.Hash;
|
||||
|
||||
// Check server prf against client prf
|
||||
if (!Compare (clientHash, serverHash))
|
||||
{
|
||||
// TODO: Review that selected alert is correct
|
||||
throw new TlsException(AlertDescription.InsuficientSecurity, "Invalid ServerFinished message received.");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessAsTls1()
|
||||
{
|
||||
byte[] serverPRF = this.ReadBytes((int)Length);
|
||||
HashAlgorithm hash = new MD5SHA1();
|
||||
|
||||
// note: we could call HashAlgorithm.ComputeHash(Stream) but that would allocate (on Mono)
|
||||
// a 4096 bytes buffer to process the hash - which is bigger than HandshakeMessages
|
||||
byte[] data = this.Context.HandshakeMessages.ToArray ();
|
||||
byte[] digest = hash.ComputeHash (data, 0, data.Length);
|
||||
|
||||
byte[] clientPRF = this.Context.Current.Cipher.PRF(this.Context.MasterSecret, "server finished", digest, 12);
|
||||
|
||||
// Check server prf against client prf
|
||||
if (!Compare (clientPRF, serverPRF))
|
||||
{
|
||||
throw new TlsException("Invalid ServerFinished message received.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user