You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@ -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)
|
||||
|
Reference in New Issue
Block a user