Imported Upstream version 5.16.0.100

Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-08-07 15:19:03 +00:00
parent 0a9828183b
commit 7d7f676260
4419 changed files with 170950 additions and 90273 deletions

View File

@ -54,9 +54,9 @@ namespace Mono.AppleTls
X509Certificate remoteCertificate;
X509Certificate localClientCertificate;
MonoTlsConnectionInfo connectionInfo;
bool havePeerTrust;
bool isAuthenticated;
bool handshakeFinished;
bool renegotiating;
int handshakeStarted;
bool closed;
@ -66,20 +66,16 @@ namespace Mono.AppleTls
Exception lastException;
public AppleTlsContext (
MobileAuthenticatedStream parent, bool serverMode, string targetHost,
SSA.SslProtocols enabledProtocols, X509Certificate serverCertificate,
X509CertificateCollection clientCertificates, bool askForClientCert)
: base (parent, serverMode, targetHost, enabledProtocols,
serverCertificate, clientCertificates, askForClientCert)
public AppleTlsContext (MobileAuthenticatedStream parent, MonoSslAuthenticationOptions options)
: base (parent, options)
{
handle = GCHandle.Alloc (this, GCHandleType.Weak);
readFunc = NativeReadCallback;
writeFunc = NativeWriteCallback;
if (IsServer) {
if (serverCertificate == null)
throw new ArgumentNullException ("serverCertificate");
if (LocalServerCertificate == null)
throw new ArgumentNullException (nameof (LocalServerCertificate));
}
}
@ -123,6 +119,12 @@ namespace Mono.AppleTls
case SslStatus.Protocol:
throw new TlsException (AlertDescription.ProtocolVersion);
case SslStatus.PeerNoRenegotiation:
throw new TlsException (AlertDescription.NoRenegotiation);
case SslStatus.PeerUnexpectedMsg:
throw new TlsException (AlertDescription.UnexpectedMessage);
default:
throw new TlsException (AlertDescription.InternalError, "Unknown Secure Transport error `{0}'.", status);
}
@ -143,6 +145,24 @@ namespace Mono.AppleTls
InitializeConnection ();
/*
* SecureTransport is bugged OS X 10.5.8+ - renegotiation after
* calling SetCertificate() will not work.
*
* We also cannot change options after the handshake has started,
* so if you want to request a client certificate, it will happen
* both during the initial handshake and during renegotiation.
*
* You may check 'SslStream.IsAuthenticated' (which will be false
* during the initial handshake) from within your
* 'LocalCertificateSelectionCallback' and return null to have the
* callback invoked again during renegotiation.
*
* However, the first time your selection callback returns a client
* certificate, that certificate will be used for the rest of the
* session.
*/
SetSessionOption (SslSessionOption.BreakOnCertRequested, true);
SetSessionOption (SslSessionOption.BreakOnClientAuth, true);
SetSessionOption (SslSessionOption.BreakOnServerAuth, true);
@ -172,7 +192,7 @@ namespace Mono.AppleTls
public override bool ProcessHandshake ()
{
if (handshakeFinished)
if (handshakeFinished && !renegotiating)
throw new NotSupportedException ("Handshake already finished.");
while (true) {
@ -183,33 +203,31 @@ namespace Mono.AppleTls
CheckStatusAndThrow (status, SslStatus.WouldBlock, SslStatus.PeerAuthCompleted, SslStatus.PeerClientCertRequested);
if (status == SslStatus.PeerAuthCompleted) {
RequirePeerTrust ();
EvaluateTrust ();
} else if (status == SslStatus.PeerClientCertRequested) {
RequirePeerTrust ();
if (remoteCertificate == null)
throw new TlsException (AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server.");
localClientCertificate = SelectClientCertificate (remoteCertificate, null);
if (localClientCertificate == null)
continue;
clientIdentity = AppleCertificateHelper.GetIdentity (localClientCertificate);
if (clientIdentity == null)
throw new TlsException (AlertDescription.CertificateUnknown);
SetCertificate (clientIdentity, new SecCertificate [0]);
ClientCertificateRequested ();
} else if (status == SslStatus.WouldBlock) {
return false;
} else if (status == SslStatus.Success) {
Debug ("Handshake complete!");
handshakeFinished = true;
renegotiating = false;
return true;
}
}
}
void RequirePeerTrust ()
void ClientCertificateRequested ()
{
if (!havePeerTrust) {
EvaluateTrust ();
havePeerTrust = true;
}
EvaluateTrust ();
var acceptableIssuers = CopyDistinguishedNames ();
localClientCertificate = SelectClientCertificate (acceptableIssuers);
if (localClientCertificate == null)
return;
clientIdentity = AppleCertificateHelper.GetIdentity (localClientCertificate);
if (clientIdentity == null)
throw new TlsException (AlertDescription.CertificateUnknown);
SetCertificate (clientIdentity, new SecCertificate [0]);
}
void EvaluateTrust ()
@ -279,18 +297,25 @@ namespace Mono.AppleTls
result = SSLSetConnection (Handle, GCHandle.ToIntPtr (handle));
CheckStatusAndThrow (result);
/*
* If 'EnabledProtocols' is zero, then we use the system default values.
*
* In CoreFX, 'ServicePointManager.SecurityProtocol' defaults to
* 'SecurityProtocolType.SystemDefault', which is zero.
*/
if ((EnabledProtocols & SSA.SslProtocols.Tls) != 0)
MinProtocol = SslProtocol.Tls_1_0;
else if ((EnabledProtocols & SSA.SslProtocols.Tls11) != 0)
MinProtocol = SslProtocol.Tls_1_1;
else
else if ((EnabledProtocols & SSA.SslProtocols.Tls12) != 0)
MinProtocol = SslProtocol.Tls_1_2;
if ((EnabledProtocols & SSA.SslProtocols.Tls12) != 0)
MaxProtocol = SslProtocol.Tls_1_2;
else if ((EnabledProtocols & SSA.SslProtocols.Tls11) != 0)
MaxProtocol = SslProtocol.Tls_1_1;
else
else if ((EnabledProtocols & SSA.SslProtocols.Tls) != 0)
MaxProtocol = SslProtocol.Tls_1_0;
if (Settings != null && Settings.EnabledCiphers != null) {
@ -300,14 +325,33 @@ namespace Mono.AppleTls
SetEnabledCiphers (ciphers);
}
if (AskForClientCertificate)
if (IsServer && AskForClientCertificate)
SetClientSideAuthenticate (SslAuthenticate.Try);
if (IsServer && Settings?.ClientCertificateIssuers != null) {
Debug ("Set client certificate issuers.");
foreach (var issuer in Settings.ClientCertificateIssuers) {
AddDistinguishedName (issuer);
}
}
IPAddress address;
if (!IsServer && !string.IsNullOrEmpty (TargetHost) &&
!IPAddress.TryParse (TargetHost, out address)) {
PeerDomainName = ServerName;
}
if (Options.AllowRenegotiation && IsRenegotiationSupported ())
SetSessionOption (SslSessionOption.AllowRenegotiation, true);
}
static bool IsRenegotiationSupported ()
{
#if MONOTOUCH
return false;
#else
return Environment.OSVersion.Version >= new Version (16, 6);
#endif
}
void InitializeSession ()
@ -457,6 +501,13 @@ namespace Mono.AppleTls
}
}
SslSessionState GetSessionState ()
{
var value = SslSessionState.Invalid;
var result = SSLGetSessionState (Handle, ref value);
return result == SslStatus.Success ? value : SslSessionState.Invalid;
}
[DllImport (SecurityLibrary)]
extern unsafe static /* OSStatus */ SslStatus SSLGetPeerID (/* SSLContextRef */ IntPtr context, /* const void** */ out IntPtr peerID, /* size_t* */ out IntPtr peerIDLen);
@ -665,6 +716,43 @@ namespace Mono.AppleTls
return (value == IntPtr.Zero) ? null : new SecTrust (value, true);
}
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ SslStatus SSLAddDistinguishedName (/* SSLContextRef */ IntPtr context, /* const void * */ byte[] derDN, /* size_t */ IntPtr derDNLen);
void AddDistinguishedName (string name)
{
var dn = new X500DistinguishedName (name);
var bytes = dn.RawData;
var result = SSLAddDistinguishedName (Handle, bytes, (IntPtr)bytes.Length);
CheckStatusAndThrow (result);
}
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ SslStatus SSLCopyDistinguishedNames (/* SSLContextRef */ IntPtr context, /* CFArrayRef _Nullable * */ out IntPtr names);
string[] CopyDistinguishedNames ()
{
IntPtr arrayPtr;
var result = SSLCopyDistinguishedNames (Handle, out arrayPtr);
CheckStatusAndThrow (result);
if (arrayPtr == IntPtr.Zero)
return new string[0];
using (var array = new CFArray (arrayPtr, true)) {
var names = new string [array.Count];
for (int i = 0; i < array.Count; i++) {
using (var data = new CFData (array[i], false)) {
var buffer = new byte [(int)data.Length];
Marshal.Copy (data.Bytes, buffer, 0, buffer.Length);
var dn = new X500DistinguishedName (buffer);
names[i] = dn.Name;
}
}
return names;
}
}
#endregion
#region IO Functions
@ -802,7 +890,19 @@ namespace Mono.AppleTls
return (0, false);
}
CheckStatusAndThrow (status, SslStatus.WouldBlock, SslStatus.ClosedGraceful);
CheckStatusAndThrow (status, SslStatus.WouldBlock, SslStatus.ClosedGraceful,
SslStatus.PeerAuthCompleted, SslStatus.PeerClientCertRequested);
if (status == SslStatus.PeerAuthCompleted) {
Debug ($"Renegotiation complete: {GetSessionState ()}");
EvaluateTrust ();
return (0, true);
} else if (status == SslStatus.PeerClientCertRequested) {
Debug ($"Renegotiation asked for client certificate: {GetSessionState ()}");
ClientCertificateRequested ();
return (0, true);
}
var wantMore = status == SslStatus.WouldBlock;
return ((int)processed, wantMore);
} catch (Exception ex) {
@ -834,7 +934,16 @@ namespace Mono.AppleTls
Debug ("Write done: {0} {1}", status, processed);
CheckStatusAndThrow (status, SslStatus.WouldBlock);
CheckStatusAndThrow (status, SslStatus.WouldBlock,
SslStatus.PeerAuthCompleted, SslStatus.PeerClientCertRequested);
if (status == SslStatus.PeerAuthCompleted) {
Debug ($"Renegotiation complete: {GetSessionState ()}");
EvaluateTrust ();
} else if (status == SslStatus.PeerClientCertRequested) {
Debug ($"Renegotiation asked for client certificate: {GetSessionState ()}");
ClientCertificateRequested ();
}
var wantMore = status == SslStatus.WouldBlock;
return ((int)processed, wantMore);
@ -843,6 +952,28 @@ namespace Mono.AppleTls
}
}
#if !MONOTOUCH
// Available on macOS 10.12+ and iOS 10.0+.
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ SslStatus SSLReHandshake (/* SSLContextRef */ IntPtr context);
#endif
public override bool CanRenegotiate => IsServer && IsRenegotiationSupported ();
public override void Renegotiate ()
{
#if MONOTOUCH
throw new NotSupportedException ();
#else
if (!CanRenegotiate)
throw new NotSupportedException ();
var status = SSLReHandshake (Handle);
CheckStatusAndThrow (status);
renegotiating = true;
#endif
}
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ SslStatus SSLClose (/* SSLContextRef */ IntPtr context);
@ -851,6 +982,11 @@ namespace Mono.AppleTls
closed = true;
}
public override bool PendingRenegotiation ()
{
return GetSessionState () == SslSessionState.Handshake;
}
#endregion
protected override void Dispose (bool disposing)