You've already forked linux-packaging-mono
Imported Upstream version 5.8.0.22
Former-commit-id: df344e34b07851d296efb3e6604c8db42b6f7aa3
This commit is contained in:
parent
5f4a27cc8a
commit
7d05485754
@@ -1,16 +0,0 @@
|
||||
sspicli.dll!AcceptSecurityContext
|
||||
sspicli.dll!AcquireCredentialsHandleW
|
||||
sspicli.dll!ApplyControlToken
|
||||
sspicli.dll!CompleteAuthToken
|
||||
sspicli.dll!DecryptMessage
|
||||
sspicli.dll!DeleteSecurityContext
|
||||
sspicli.dll!EncryptMessage
|
||||
sspicli.dll!EnumerateSecurityPackagesW
|
||||
sspicli.dll!FreeContextBuffer
|
||||
sspicli.dll!FreeCredentialsHandle
|
||||
sspicli.dll!InitializeSecurityContextW
|
||||
sspicli.dll!QueryContextAttributesW
|
||||
sspicli.dll!QuerySecurityContextToken
|
||||
sspicli.dll!SetContextAttributesW
|
||||
sspicli.dll!SspiEncodeStringsAsAuthIdentity
|
||||
sspicli.dll!SspiFreeAuthIdentity
|
||||
@@ -20,6 +20,7 @@ namespace System.Net.Security
|
||||
{
|
||||
// When reading a frame from the wire first read this many bytes for the header.
|
||||
internal const int ReadHeaderSize = 5;
|
||||
|
||||
private SafeFreeCredentials _credentialsHandle;
|
||||
private SafeDeleteContext _securityContext;
|
||||
private readonly string _destination;
|
||||
@@ -35,7 +36,7 @@ namespace System.Net.Security
|
||||
private X509Certificate _selectedClientCertificate;
|
||||
private bool _isRemoteCertificateAvailable;
|
||||
|
||||
private readonly X509CertificateCollection _clientCertificates;
|
||||
private X509CertificateCollection _clientCertificates;
|
||||
private LocalCertSelectionCallback _certSelectionDelegate;
|
||||
|
||||
// These are the MAX encrypt buffer output sizes, not the actual sizes.
|
||||
@@ -48,8 +49,8 @@ namespace System.Net.Security
|
||||
|
||||
private bool _refreshCredentialNeeded;
|
||||
|
||||
private readonly Oid _serverAuthOid = new Oid("1.3.6.1.5.5.7.3.1");
|
||||
private readonly Oid _clientAuthOid = new Oid("1.3.6.1.5.5.7.3.2");
|
||||
private readonly Oid _serverAuthOid = new Oid("1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.1");
|
||||
private readonly Oid _clientAuthOid = new Oid("1.3.6.1.5.5.7.3.2", "1.3.6.1.5.5.7.3.2");
|
||||
|
||||
internal SecureChannel(string hostname, bool serverMode, SslProtocols sslProtocols, X509Certificate serverCertificate, X509CertificateCollection clientCertificates, bool remoteCertRequired, bool checkCertName,
|
||||
bool checkCertRevocationStatus, EncryptionPolicy encryptionPolicy, LocalCertSelectionCallback certSelectionDelegate)
|
||||
@@ -141,14 +142,6 @@ namespace System.Net.Security
|
||||
}
|
||||
}
|
||||
|
||||
internal X509CertificateCollection ClientCertificates
|
||||
{
|
||||
get
|
||||
{
|
||||
return _clientCertificates;
|
||||
}
|
||||
}
|
||||
|
||||
internal int HeaderSize
|
||||
{
|
||||
get
|
||||
@@ -383,7 +376,11 @@ namespace System.Net.Security
|
||||
{
|
||||
X509Certificate2Collection dummyCollection;
|
||||
remoteCert = CertificateValidationPal.GetRemoteCertificate(_securityContext, out dummyCollection);
|
||||
clientCertificate = _certSelectionDelegate(_hostName, ClientCertificates, remoteCert, issuers);
|
||||
if (_clientCertificates == null)
|
||||
{
|
||||
_clientCertificates = new X509CertificateCollection();
|
||||
}
|
||||
clientCertificate = _certSelectionDelegate(_hostName, _clientCertificates, remoteCert, issuers);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -406,7 +403,7 @@ namespace System.Net.Security
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ClientCertificates.Count == 0)
|
||||
if (_clientCertificates == null || _clientCertificates.Count == 0)
|
||||
{
|
||||
if (NetEventSource.IsEnabled) NetEventSource.Log.NoDelegateNoClientCert(this);
|
||||
|
||||
@@ -422,7 +419,7 @@ namespace System.Net.Security
|
||||
{
|
||||
// This is where we attempt to restart a session by picking the FIRST cert from the collection.
|
||||
// Otherwise it is either server sending a client cert request or the session is renegotiated.
|
||||
clientCertificate = ClientCertificates[0];
|
||||
clientCertificate = _clientCertificates[0];
|
||||
sessionRestartAttempt = true;
|
||||
if (clientCertificate != null)
|
||||
{
|
||||
|
||||
@@ -120,11 +120,6 @@ namespace System.Net.Security
|
||||
throw new ArgumentNullException(nameof(serverCertificate));
|
||||
}
|
||||
|
||||
if (clientCertificates == null)
|
||||
{
|
||||
clientCertificates = new X509CertificateCollection();
|
||||
}
|
||||
|
||||
if (targetHost.Length == 0)
|
||||
{
|
||||
targetHost = "?" + Interlocked.Increment(ref s_uniqueNameInteger).ToString(NumberFormatInfo.InvariantInfo);
|
||||
@@ -239,14 +234,6 @@ namespace System.Net.Security
|
||||
}
|
||||
}
|
||||
|
||||
internal bool DataAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsAuthenticated && (SecureStream.DataAvailable || _queuedReadCount != 0);
|
||||
}
|
||||
}
|
||||
|
||||
internal CipherAlgorithmType CipherAlgorithm
|
||||
{
|
||||
get
|
||||
@@ -894,7 +881,7 @@ namespace System.Net.Security
|
||||
_Framing = DetectFraming(buffer, readBytes);
|
||||
}
|
||||
|
||||
int restBytes = GetRemainingFrameSize(buffer, readBytes);
|
||||
int restBytes = GetRemainingFrameSize(buffer, 0, readBytes);
|
||||
|
||||
if (restBytes < 0)
|
||||
{
|
||||
@@ -1676,9 +1663,9 @@ namespace System.Net.Security
|
||||
|
||||
//
|
||||
// This is called from SslStream class too.
|
||||
internal int GetRemainingFrameSize(byte[] buffer, int dataSize)
|
||||
internal int GetRemainingFrameSize(byte[] buffer, int offset, int dataSize)
|
||||
{
|
||||
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, buffer, dataSize);
|
||||
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, buffer, offset, dataSize);
|
||||
|
||||
int payloadSize = -1;
|
||||
switch (_Framing)
|
||||
@@ -1691,16 +1678,16 @@ namespace System.Net.Security
|
||||
}
|
||||
// Note: Cannot detect version mismatch for <= SSL2
|
||||
|
||||
if ((buffer[0] & 0x80) != 0)
|
||||
if ((buffer[offset] & 0x80) != 0)
|
||||
{
|
||||
// Two bytes
|
||||
payloadSize = (((buffer[0] & 0x7f) << 8) | buffer[1]) + 2;
|
||||
payloadSize = (((buffer[offset] & 0x7f) << 8) | buffer[offset + 1]) + 2;
|
||||
payloadSize -= dataSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Three bytes
|
||||
payloadSize = (((buffer[0] & 0x3f) << 8) | buffer[1]) + 3;
|
||||
payloadSize = (((buffer[offset] & 0x3f) << 8) | buffer[offset + 1]) + 3;
|
||||
payloadSize -= dataSize;
|
||||
}
|
||||
|
||||
@@ -1711,7 +1698,7 @@ namespace System.Net.Security
|
||||
throw new System.IO.IOException(SR.net_ssl_io_frame);
|
||||
}
|
||||
|
||||
payloadSize = ((buffer[3] << 8) | buffer[4]) + 5;
|
||||
payloadSize = ((buffer[offset + 3] << 8) | buffer[offset + 4]) + 5;
|
||||
payloadSize -= dataSize;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace System.Net.Security
|
||||
//
|
||||
public virtual IAsyncResult BeginAuthenticateAsClient(string targetHost, AsyncCallback asyncCallback, object asyncState)
|
||||
{
|
||||
return BeginAuthenticateAsClient(targetHost, new X509CertificateCollection(), SecurityProtocol.SystemDefaultSecurityProtocols, false,
|
||||
return BeginAuthenticateAsClient(targetHost, null, SecurityProtocol.SystemDefaultSecurityProtocols, false,
|
||||
asyncCallback, asyncState);
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace System.Net.Security
|
||||
#region Synchronous methods
|
||||
public virtual void AuthenticateAsClient(string targetHost)
|
||||
{
|
||||
AuthenticateAsClient(targetHost, new X509CertificateCollection(), SecurityProtocol.SystemDefaultSecurityProtocols, false);
|
||||
AuthenticateAsClient(targetHost, null, SecurityProtocol.SystemDefaultSecurityProtocols, false);
|
||||
}
|
||||
|
||||
public virtual void AuthenticateAsClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation)
|
||||
@@ -226,44 +226,63 @@ namespace System.Net.Security
|
||||
#endregion
|
||||
|
||||
#region Task-based async public methods
|
||||
public virtual Task AuthenticateAsClientAsync(string targetHost)
|
||||
{
|
||||
return Task.Factory.FromAsync(BeginAuthenticateAsClient, EndAuthenticateAsClient, targetHost, null);
|
||||
}
|
||||
public virtual Task AuthenticateAsClientAsync(string targetHost) =>
|
||||
Task.Factory.FromAsync(
|
||||
(arg1, callback, state) => ((SslStream)state).BeginAuthenticateAsClient(arg1, callback, state),
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsClient(iar),
|
||||
targetHost,
|
||||
this);
|
||||
|
||||
public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation)
|
||||
{
|
||||
return AuthenticateAsClientAsync(targetHost, clientCertificates, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation);
|
||||
}
|
||||
public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation) =>
|
||||
Task.Factory.FromAsync(
|
||||
(arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsClient(arg1, arg2, SecurityProtocol.SystemDefaultSecurityProtocols, arg3, callback, state),
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsClient(iar),
|
||||
targetHost, clientCertificates, checkCertificateRevocation,
|
||||
this);
|
||||
|
||||
public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
|
||||
{
|
||||
return Task.Factory.FromAsync((callback, state) => BeginAuthenticateAsClient(targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, callback, state), EndAuthenticateAsClient, null);
|
||||
var beginMethod = checkCertificateRevocation ? (Func<string, X509CertificateCollection, SslProtocols, AsyncCallback, object, IAsyncResult>)
|
||||
((arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsClient(arg1, arg2, arg3, true, callback, state)) :
|
||||
((arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsClient(arg1, arg2, arg3, false, callback, state));
|
||||
return Task.Factory.FromAsync(
|
||||
beginMethod,
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsClient(iar),
|
||||
targetHost, clientCertificates, enabledSslProtocols,
|
||||
this);
|
||||
}
|
||||
|
||||
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate)
|
||||
{
|
||||
return Task.Factory.FromAsync(BeginAuthenticateAsServer, EndAuthenticateAsServer, serverCertificate, null);
|
||||
}
|
||||
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate) =>
|
||||
Task.Factory.FromAsync(
|
||||
(arg1, callback, state) => ((SslStream)state).BeginAuthenticateAsServer(arg1, callback, state),
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsServer(iar),
|
||||
serverCertificate,
|
||||
this);
|
||||
|
||||
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation)
|
||||
{
|
||||
return AuthenticateAsServerAsync(serverCertificate, clientCertificateRequired, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation);
|
||||
}
|
||||
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation) =>
|
||||
Task.Factory.FromAsync(
|
||||
(arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsServer(arg1, arg2, SecurityProtocol.SystemDefaultSecurityProtocols, arg3, callback, state),
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsServer(iar),
|
||||
serverCertificate, clientCertificateRequired, checkCertificateRevocation,
|
||||
this);
|
||||
|
||||
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
|
||||
{
|
||||
|
||||
return Task.Factory.FromAsync((callback, state) => BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, callback, state), EndAuthenticateAsServer, null);
|
||||
}
|
||||
|
||||
public virtual Task ShutdownAsync()
|
||||
{
|
||||
var beginMethod = checkCertificateRevocation ? (Func<X509Certificate, bool, SslProtocols, AsyncCallback, object, IAsyncResult>)
|
||||
((arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsServer(arg1, arg2, arg3, true, callback, state)) :
|
||||
((arg1, arg2, arg3, callback, state) => ((SslStream)state).BeginAuthenticateAsServer(arg1, arg2, arg3, false, callback, state));
|
||||
return Task.Factory.FromAsync(
|
||||
(callback, state) => BeginShutdown(callback, state),
|
||||
EndShutdown,
|
||||
null);
|
||||
beginMethod,
|
||||
iar => ((SslStream)iar.AsyncState).EndAuthenticateAsServer(iar),
|
||||
serverCertificate, clientCertificateRequired, enabledSslProtocols,
|
||||
this);
|
||||
}
|
||||
|
||||
public virtual Task ShutdownAsync() =>
|
||||
Task.Factory.FromAsync(
|
||||
(callback, state) => ((SslStream)state).BeginShutdown(callback, state),
|
||||
iar => ((SslStream)iar.AsyncState).EndShutdown(iar),
|
||||
this);
|
||||
#endregion
|
||||
|
||||
public override bool IsAuthenticated
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace System.Net.Security
|
||||
private int _internalOffset;
|
||||
private int _internalBufferCount;
|
||||
|
||||
private int _decryptedBytesOffset;
|
||||
private int _decryptedBytesCount;
|
||||
|
||||
internal SslStreamInternal(SslState sslState)
|
||||
{
|
||||
if (PinnableBufferCacheEventSource.Log.IsEnabled())
|
||||
@@ -50,6 +53,9 @@ namespace System.Net.Security
|
||||
}
|
||||
|
||||
_sslState = sslState;
|
||||
|
||||
_decryptedBytesOffset = 0;
|
||||
_decryptedBytesCount = 0;
|
||||
}
|
||||
|
||||
// If we have a read buffer from the pinnable cache, return it.
|
||||
@@ -96,10 +102,10 @@ namespace System.Net.Security
|
||||
// If there's any data in the buffer, take one byte, and we're done.
|
||||
try
|
||||
{
|
||||
if (InternalBufferCount > 0)
|
||||
if (_decryptedBytesCount > 0)
|
||||
{
|
||||
int b = InternalBuffer[InternalOffset];
|
||||
SkipBytes(1);
|
||||
int b = InternalBuffer[_decryptedBytesOffset++];
|
||||
_decryptedBytesCount--;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -210,11 +216,6 @@ namespace System.Net.Security
|
||||
}
|
||||
}
|
||||
|
||||
internal bool DataAvailable
|
||||
{
|
||||
get { return InternalBufferCount != 0; }
|
||||
}
|
||||
|
||||
private byte[] InternalBuffer
|
||||
{
|
||||
get
|
||||
@@ -223,40 +224,13 @@ namespace System.Net.Security
|
||||
}
|
||||
}
|
||||
|
||||
private int InternalOffset
|
||||
private void EnsureInternalBufferSize(int newSize)
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private int InternalBufferCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalBufferCount;
|
||||
}
|
||||
}
|
||||
|
||||
private void SkipBytes(int decrCount)
|
||||
{
|
||||
_internalOffset += decrCount;
|
||||
_internalBufferCount -= decrCount;
|
||||
}
|
||||
|
||||
//
|
||||
// This will set the internal offset to "curOffset" and ensure internal buffer.
|
||||
// If not enough, reallocate and copy up to "curOffset".
|
||||
//
|
||||
private void EnsureInternalBufferSize(int curOffset, int addSize)
|
||||
{
|
||||
if (_internalBuffer == null || _internalBuffer.Length < addSize + curOffset)
|
||||
if (_internalBuffer == null || _internalBuffer.Length < newSize)
|
||||
{
|
||||
bool wasPinnable = _internalBufferFromPinnableCache;
|
||||
byte[] saved = _internalBuffer;
|
||||
|
||||
int newSize = addSize + curOffset;
|
||||
if (newSize <= PinnableReadBufferSize)
|
||||
{
|
||||
if (PinnableBufferCacheEventSource.Log.IsEnabled())
|
||||
@@ -278,9 +252,9 @@ namespace System.Net.Security
|
||||
_internalBuffer = new byte[newSize];
|
||||
}
|
||||
|
||||
if (saved != null && curOffset != 0)
|
||||
if (saved != null && _internalBufferCount != 0)
|
||||
{
|
||||
Buffer.BlockCopy(saved, 0, _internalBuffer, 0, curOffset);
|
||||
Buffer.BlockCopy(saved, _internalOffset, _internalBuffer, 0, _internalBufferCount);
|
||||
}
|
||||
|
||||
if (wasPinnable)
|
||||
@@ -288,8 +262,15 @@ namespace System.Net.Security
|
||||
s_PinnableReadBufferCache.FreeBuffer(saved);
|
||||
}
|
||||
}
|
||||
_internalOffset = curOffset;
|
||||
_internalBufferCount = curOffset + addSize;
|
||||
else if (_internalOffset > 0 && _internalBufferCount > 0)
|
||||
{
|
||||
// We have buffered data at a non-zero offset.
|
||||
// To maximize the buffer space available for the next read,
|
||||
// copy the existing data down to the beginning of the buffer.
|
||||
Buffer.BlockCopy(_internalBuffer, _internalOffset, _internalBuffer, 0, _internalBufferCount);
|
||||
}
|
||||
|
||||
_internalOffset = 0;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -497,6 +478,171 @@ namespace System.Net.Security
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the buffer up to the minimum specified size (or more, if possible).
|
||||
// Returns 0 if EOF on initial read, otherwise throws on EOF.
|
||||
// Returns minSize on success.
|
||||
private int FillBuffer(int minSize)
|
||||
{
|
||||
Debug.Assert(_internalOffset == 0);
|
||||
Debug.Assert(minSize > _internalBufferCount);
|
||||
|
||||
int initialCount = _internalBufferCount;
|
||||
do
|
||||
{
|
||||
int bytes = _sslState.InnerStream.Read(InternalBuffer, _internalBufferCount, InternalBuffer.Length - _internalBufferCount);
|
||||
if (bytes == 0)
|
||||
{
|
||||
if (_internalBufferCount != initialCount)
|
||||
{
|
||||
// We read some bytes, but not as many as we expected, so throw.
|
||||
throw new IOException(SR.net_io_eof);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_internalBufferCount += bytes;
|
||||
} while (_internalBufferCount < minSize);
|
||||
|
||||
return minSize;
|
||||
}
|
||||
|
||||
// Fill the buffer up to the minimum specified size (or more, if possible).
|
||||
// Returns 0 if EOF on initial read, otherwise throws on EOF.
|
||||
// Returns minSize on success.
|
||||
public async Task<int> FillBufferAsync(int minSize)
|
||||
{
|
||||
Debug.Assert(_internalOffset == 0);
|
||||
Debug.Assert(minSize > _internalBufferCount);
|
||||
|
||||
int initialCount = _internalBufferCount;
|
||||
do
|
||||
{
|
||||
int bytes = await _sslState.InnerStream.ReadAsync(InternalBuffer, _internalBufferCount, InternalBuffer.Length - _internalBufferCount, CancellationToken.None).ConfigureAwait(false);
|
||||
if (bytes == 0)
|
||||
{
|
||||
if (_internalBufferCount != initialCount)
|
||||
{
|
||||
// We read some bytes, but not as many as we expected, so throw.
|
||||
throw new IOException(SR.net_io_eof);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_internalBufferCount += bytes;
|
||||
} while (_internalBufferCount < minSize);
|
||||
|
||||
return minSize;
|
||||
}
|
||||
|
||||
private static void CompleteFromCompletedTask(Task<int> task, AsyncProtocolRequest asyncRequest)
|
||||
{
|
||||
Debug.Assert(task.IsCompleted);
|
||||
if (task.IsCompletedSuccessfully)
|
||||
{
|
||||
asyncRequest.CompleteRequest(task.Result);
|
||||
}
|
||||
else if (task.IsFaulted)
|
||||
{
|
||||
asyncRequest.CompleteUserWithError(task.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
asyncRequest.CompleteUserWithError(new OperationCanceledException());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if pending, false if completed
|
||||
private static bool TaskToAsyncProtocolRequest(Task<int> task, AsyncProtocolRequest asyncRequest, AsyncProtocolCallback asyncCallback, out int result)
|
||||
{
|
||||
// Parameters other than asyncCallback are not used
|
||||
asyncRequest.SetNextRequest(null, 0, 0, asyncCallback);
|
||||
|
||||
if (task.IsCompleted)
|
||||
{
|
||||
CompleteFromCompletedTask(task, asyncRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
task.ContinueWith((t, s) => CompleteFromCompletedTask(t, (AsyncProtocolRequest)s),
|
||||
asyncRequest,
|
||||
CancellationToken.None,
|
||||
TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
if (asyncRequest.MustCompleteSynchronously)
|
||||
{
|
||||
result = asyncRequest.Result;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private int EnsureBufferedBytes(int minSize, AsyncProtocolRequest asyncRequest, AsyncProtocolCallback asyncCallback)
|
||||
{
|
||||
if (_internalBufferCount >= minSize)
|
||||
{
|
||||
return minSize;
|
||||
}
|
||||
|
||||
EnsureInternalBufferSize(minSize);
|
||||
|
||||
int bytesRead;
|
||||
if (asyncRequest != null)
|
||||
{
|
||||
if (TaskToAsyncProtocolRequest(
|
||||
FillBufferAsync(minSize),
|
||||
asyncRequest,
|
||||
asyncCallback,
|
||||
out bytesRead))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesRead = FillBuffer(minSize);
|
||||
}
|
||||
|
||||
Debug.Assert(bytesRead == 0 || bytesRead == minSize);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
private void ConsumeBufferedBytes(int byteCount)
|
||||
{
|
||||
Debug.Assert(byteCount >= 0);
|
||||
Debug.Assert(byteCount <= _internalBufferCount);
|
||||
|
||||
_internalOffset += byteCount;
|
||||
_internalBufferCount -= byteCount;
|
||||
|
||||
if (_internalBufferCount == 0)
|
||||
{
|
||||
// No remaining buffered bytes, so reset the offset to the beginning for the next read.
|
||||
_internalOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int CopyDecryptedData(byte[] buffer, int offset, int count)
|
||||
{
|
||||
Debug.Assert(_decryptedBytesCount > 0);
|
||||
|
||||
int copyBytes = _decryptedBytesCount > count ? count : _decryptedBytesCount;
|
||||
if (copyBytes != 0)
|
||||
{
|
||||
Buffer.BlockCopy(InternalBuffer, _decryptedBytesOffset, buffer, offset, copyBytes);
|
||||
|
||||
_decryptedBytesOffset += copyBytes;
|
||||
_decryptedBytesCount -= copyBytes;
|
||||
}
|
||||
|
||||
return copyBytes;
|
||||
}
|
||||
|
||||
//
|
||||
// Combined sync/async read method. For sync request asyncRequest==null.
|
||||
//
|
||||
@@ -517,15 +663,9 @@ namespace System.Net.Security
|
||||
|
||||
try
|
||||
{
|
||||
int copyBytes;
|
||||
if (InternalBufferCount != 0)
|
||||
if (_decryptedBytesCount != 0)
|
||||
{
|
||||
copyBytes = InternalBufferCount > count ? count : InternalBufferCount;
|
||||
if (copyBytes != 0)
|
||||
{
|
||||
Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes);
|
||||
SkipBytes(copyBytes);
|
||||
}
|
||||
int copyBytes = CopyDecryptedData(buffer, offset, count);
|
||||
|
||||
asyncRequest?.CompleteUser(copyBytes);
|
||||
|
||||
@@ -562,9 +702,9 @@ namespace System.Net.Security
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (InternalBufferCount != 0)
|
||||
if (_decryptedBytesCount != 0)
|
||||
{
|
||||
NetEventSource.Fail(this, $"Previous frame was not consumed. InternalBufferCount: {InternalBufferCount}");
|
||||
NetEventSource.Fail(this, $"Previous frame was not consumed. _decryptedBytesCount: {_decryptedBytesCount}");
|
||||
}
|
||||
|
||||
do
|
||||
@@ -597,33 +737,13 @@ namespace System.Net.Security
|
||||
|
||||
private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
|
||||
{
|
||||
int readBytes = 0;
|
||||
|
||||
//
|
||||
// Always pass InternalBuffer for SSPI "in place" decryption.
|
||||
// A user buffer can be shared by many threads in that case decryption/integrity check may fail cause of data corruption.
|
||||
//
|
||||
|
||||
// Reset internal buffer for a new frame.
|
||||
EnsureInternalBufferSize(0, SecureChannel.ReadHeaderSize);
|
||||
|
||||
if (asyncRequest != null)
|
||||
int readBytes = EnsureBufferedBytes(SecureChannel.ReadHeaderSize, asyncRequest, s_readHeaderCallback);
|
||||
if (readBytes == -1)
|
||||
{
|
||||
asyncRequest.SetNextRequest(InternalBuffer, 0, SecureChannel.ReadHeaderSize, s_readHeaderCallback);
|
||||
FixedSizeReader.ReadPacketAsync(_sslState.InnerStream, asyncRequest);
|
||||
|
||||
if (!asyncRequest.MustCompleteSynchronously)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
readBytes = asyncRequest.Result;
|
||||
Debug.Assert(asyncRequest != null);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
readBytes = FixedSizeReader.ReadPacket(_sslState.InnerStream, InternalBuffer, 0, SecureChannel.ReadHeaderSize);
|
||||
}
|
||||
|
||||
|
||||
return StartFrameBody(readBytes, buffer, offset, count, asyncRequest);
|
||||
}
|
||||
|
||||
@@ -631,40 +751,27 @@ namespace System.Net.Security
|
||||
{
|
||||
if (readBytes == 0)
|
||||
{
|
||||
//EOF : Reset the buffer as we did not read anything into it.
|
||||
SkipBytes(InternalBufferCount);
|
||||
// EOF
|
||||
asyncRequest?.CompleteUser(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now readBytes is a payload size.
|
||||
readBytes = _sslState.GetRemainingFrameSize(InternalBuffer, readBytes);
|
||||
Debug.Assert(readBytes == SecureChannel.ReadHeaderSize);
|
||||
|
||||
if (readBytes < 0)
|
||||
int payloadBytes = _sslState.GetRemainingFrameSize(InternalBuffer, _internalOffset, readBytes);
|
||||
if (payloadBytes < 0)
|
||||
{
|
||||
throw new IOException(SR.net_frame_read_size);
|
||||
}
|
||||
|
||||
EnsureInternalBufferSize(SecureChannel.ReadHeaderSize, readBytes);
|
||||
|
||||
if (asyncRequest != null)
|
||||
readBytes = EnsureBufferedBytes(SecureChannel.ReadHeaderSize + payloadBytes, asyncRequest, s_readFrameCallback);
|
||||
if (readBytes == -1)
|
||||
{
|
||||
asyncRequest.SetNextRequest(InternalBuffer, SecureChannel.ReadHeaderSize, readBytes, s_readFrameCallback);
|
||||
|
||||
FixedSizeReader.ReadPacketAsync(_sslState.InnerStream, asyncRequest);
|
||||
|
||||
if (!asyncRequest.MustCompleteSynchronously)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
readBytes = asyncRequest.Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
readBytes = FixedSizeReader.ReadPacket(_sslState.InnerStream, InternalBuffer, SecureChannel.ReadHeaderSize, readBytes);
|
||||
Debug.Assert(asyncRequest != null);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Debug.Assert(readBytes == 0 || readBytes == SecureChannel.ReadHeaderSize + payloadBytes);
|
||||
|
||||
return ProcessFrameBody(readBytes, buffer, offset, count, asyncRequest);
|
||||
}
|
||||
@@ -680,57 +787,46 @@ namespace System.Net.Security
|
||||
throw new IOException(SR.net_io_eof);
|
||||
}
|
||||
|
||||
// Set readBytes to total number of received bytes.
|
||||
readBytes += SecureChannel.ReadHeaderSize;
|
||||
// At this point, readBytes contains the size of the header plus body.
|
||||
// Set _decrytpedBytesOffset/Count to the current frame we have (including header)
|
||||
// DecryptData will decrypt in-place and modify these to point to the actual decrypted data, which may be smaller.
|
||||
_decryptedBytesOffset = _internalOffset;
|
||||
_decryptedBytesCount = readBytes;
|
||||
SecurityStatusPal status = _sslState.DecryptData(InternalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount);
|
||||
|
||||
// Decrypt into internal buffer, change "readBytes" to count now _Decrypted Bytes_.
|
||||
int data_offset = 0;
|
||||
|
||||
SecurityStatusPal status = _sslState.DecryptData(InternalBuffer, ref data_offset, ref readBytes);
|
||||
// Treat the bytes we just decrypted as consumed
|
||||
// Note, we won't do another buffer read until the decrypted bytes are processed
|
||||
ConsumeBufferedBytes(readBytes);
|
||||
|
||||
if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
|
||||
{
|
||||
byte[] extraBuffer = null;
|
||||
if (readBytes != 0)
|
||||
if (_decryptedBytesCount != 0)
|
||||
{
|
||||
extraBuffer = new byte[readBytes];
|
||||
Buffer.BlockCopy(InternalBuffer, data_offset, extraBuffer, 0, readBytes);
|
||||
extraBuffer = new byte[_decryptedBytesCount];
|
||||
Buffer.BlockCopy(InternalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount);
|
||||
|
||||
_decryptedBytesCount = 0;
|
||||
}
|
||||
|
||||
// Reset internal buffer count.
|
||||
SkipBytes(InternalBufferCount);
|
||||
return ProcessReadErrorCode(status, buffer, offset, count, asyncRequest, extraBuffer);
|
||||
return ProcessReadErrorCode(status, asyncRequest, extraBuffer);
|
||||
}
|
||||
|
||||
|
||||
if (readBytes == 0 && count != 0)
|
||||
if (_decryptedBytesCount == 0)
|
||||
{
|
||||
// Read again since remote side has sent encrypted 0 bytes.
|
||||
SkipBytes(InternalBufferCount);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Decrypted data start from "data_offset" offset, the total count can be shrunk after decryption.
|
||||
EnsureInternalBufferSize(0, data_offset + readBytes);
|
||||
SkipBytes(data_offset);
|
||||
|
||||
if (readBytes > count)
|
||||
{
|
||||
readBytes = count;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, readBytes);
|
||||
|
||||
// This will adjust both the remaining internal buffer count and the offset.
|
||||
SkipBytes(readBytes);
|
||||
int copyBytes = CopyDecryptedData(buffer, offset, count);
|
||||
|
||||
_sslState.FinishRead(null);
|
||||
asyncRequest?.CompleteUser(readBytes);
|
||||
asyncRequest?.CompleteUser(copyBytes);
|
||||
|
||||
return readBytes;
|
||||
return copyBytes;
|
||||
}
|
||||
|
||||
private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
|
||||
private int ProcessReadErrorCode(SecurityStatusPal status, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
|
||||
{
|
||||
ProtocolToken message = new ProtocolToken(null, status);
|
||||
if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"***Processing an error Status = {message.Status}");
|
||||
|
||||
@@ -154,9 +154,8 @@ namespace System.Net.Security
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(offset == 0, "Expected offset 0 when decrypting");
|
||||
Debug.Assert(ReferenceEquals(input, output), "Expected input==output when decrypting");
|
||||
resultSize = Interop.OpenSsl.Decrypt(scHandle, input, size, out errorCode);
|
||||
resultSize = Interop.OpenSsl.Decrypt(scHandle, input, offset, size, out errorCode);
|
||||
}
|
||||
|
||||
switch (errorCode)
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace System.Net.Security.Tests
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task CertificateValidationClientServer_EndToEnd_Ok(bool useClientSelectionCallback)
|
||||
{
|
||||
IPEndPoint endPoint = new IPEndPoint(IPAddress.IPv6Loopback, 0);
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace System.Net.Security.Tests
|
||||
public class CertificateValidationRemoteServer
|
||||
{
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task CertificateValidationRemoteServer_EndToEnd_Ok()
|
||||
{
|
||||
using (var client = new TcpClient(AddressFamily.InterNetwork))
|
||||
|
||||
@@ -25,14 +25,12 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ClientAsyncAuthenticate_ServerRequireEncryption_ConnectWithEncryption()
|
||||
{
|
||||
await ClientAsyncSslHelper(EncryptionPolicy.RequireEncryption);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ClientAsyncAuthenticate_ServerNoEncryption_NoConnect()
|
||||
{
|
||||
await Assert.ThrowsAsync<IOException>(() => ClientAsyncSslHelper(EncryptionPolicy.NoEncryption));
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ClientDefaultEncryption_ServerRequireEncryption_ConnectWithEncryption()
|
||||
{
|
||||
using (var serverRequireEncryption = new DummyTcpServer(
|
||||
@@ -76,7 +75,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ClientDefaultEncryption_ServerNoEncryption_NoConnect()
|
||||
{
|
||||
using (var serverNoEncryption = new DummyTcpServer(
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace System.Net.Security.Tests
|
||||
public class LoggingTest : RemoteExecutorTestBase
|
||||
{
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework | TargetFrameworkMonikers.UapAot, "NetEventSource is only part of .NET Core")] //"https://github.com/dotnet/corefx/issues/19379"
|
||||
[ActiveIssue(20470, TargetFrameworkMonikers.UapAot)]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "NetEventSource is only part of .NET Core.")]
|
||||
public void EventSource_ExistsWithCorrectId()
|
||||
{
|
||||
Type esType = typeof(SslStream).Assembly.GetType("System.Net.NetEventSource", throwOnError: true, ignoreCase: false);
|
||||
@@ -25,7 +26,8 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "NetEventSource is only part of .NET Core")]
|
||||
[ActiveIssue(20470, TargetFrameworkMonikers.UapAot)]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "NetEventSource is only part of .NET Core.")]
|
||||
public void EventSource_EventsRaisedAsExpected()
|
||||
{
|
||||
RemoteInvoke(() =>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Test.Common;
|
||||
using System.Security.Principal;
|
||||
@@ -67,12 +68,12 @@ namespace System.Net.Security.Tests
|
||||
Assert.Equal("NTLM", clientIdentity.AuthenticationType);
|
||||
|
||||
Assert.Equal(true, clientIdentity.IsAuthenticated);
|
||||
|
||||
IdentityValidator.AssertIsCurrentIdentity(clientIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public void NegotiateStream_StreamToStream_Authentication_TargetName_Success()
|
||||
{
|
||||
string targetName = "testTargetName";
|
||||
@@ -122,6 +123,7 @@ namespace System.Net.Security.Tests
|
||||
Assert.Equal("NTLM", clientIdentity.AuthenticationType);
|
||||
|
||||
Assert.Equal(true, clientIdentity.IsAuthenticated);
|
||||
|
||||
IdentityValidator.AssertIsCurrentIdentity(clientIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace System.Net.Security.Tests
|
||||
{
|
||||
private const string Krb5ConfigFile = "/etc/krb5.conf";
|
||||
private const string KDestroyCmd = "kdestroy";
|
||||
private const string SudoCommand = "sudo";
|
||||
private const string ScriptName = "setup-kdc.sh";
|
||||
private const string ScriptUninstallArgs = "--uninstall --yes";
|
||||
private const string ScriptInstallArgs = "--password {0} --yes";
|
||||
@@ -103,16 +102,14 @@ namespace System.Net.Security.Tests
|
||||
|
||||
private static int RunSetupScript(string args = null)
|
||||
{
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo();
|
||||
|
||||
// since ProcessStartInfo does not support Verb, we use sudo as
|
||||
// the program to be run
|
||||
startInfo.FileName = SudoCommand;
|
||||
startInfo.Arguments = string.Format("bash {0} {1}", ScriptName, args);
|
||||
using (Process kdcSetup = Process.Start(startInfo))
|
||||
try
|
||||
{
|
||||
kdcSetup.WaitForExit();
|
||||
return kdcSetup.ExitCode;
|
||||
return AdminHelpers.RunAsSudo($"bash {ScriptName} {args}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Could not find the file
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task SslStreamConstructor_BadEncryptionPolicy_ThrowException()
|
||||
{
|
||||
using (var _remoteServer = new DummyTcpServer(
|
||||
@@ -32,7 +31,7 @@ namespace System.Net.Security.Tests
|
||||
{
|
||||
await client.ConnectAsync(_remoteServer.RemoteEndPoint.Address, _remoteServer.RemoteEndPoint.Port);
|
||||
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
AssertExtensions.Throws<ArgumentException>("encryptionPolicy", () =>
|
||||
{
|
||||
SslStream sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, (EncryptionPolicy)100);
|
||||
});
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ServerNoEncryption_ClientRequireEncryption_NoConnect()
|
||||
{
|
||||
using (var serverNoEncryption = new DummyTcpServer(
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ServerRequireEncryption_ClientRequireEncryption_ConnectWithEncryption()
|
||||
{
|
||||
using (var serverRequireEncryption = new DummyTcpServer(
|
||||
@@ -54,7 +53,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ServerRequireEncryption_ClientAllowNoEncryption_ConnectWithEncryption()
|
||||
{
|
||||
using (var serverRequireEncryption = new DummyTcpServer(
|
||||
@@ -75,7 +73,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[ConditionalFact(nameof(SupportsNullEncryption))]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task ServerRequireEncryption_ClientNoEncryption_NoConnect()
|
||||
{
|
||||
using (var serverRequireEncryption = new DummyTcpServer(
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace System.Security.Authentication.ExtendedProtection.Tests
|
||||
[InlineData("")]
|
||||
public void Constructor_CollectionContainsNullOrEmpty_Throws(string item)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new ServiceNameCollection(new[] { item }));
|
||||
Assert.Throws<ArgumentException>(() => new ServiceNameCollection(new[] { "first", item }));
|
||||
Assert.Throws<ArgumentException>(() => new ServiceNameCollection(new[] { item, "second" }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => new ServiceNameCollection(new[] { item }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => new ServiceNameCollection(new[] { "first", item }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => new ServiceNameCollection(new[] { item, "second" }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -124,7 +124,7 @@ namespace System.Security.Authentication.ExtendedProtection.Tests
|
||||
{
|
||||
ICollection collection = new ServiceNameCollection(new[] { "first", "second" });
|
||||
int[] destination = new int[collection.Count - 1];
|
||||
Assert.Throws<ArgumentException>(() => collection.CopyTo(destination, 0));
|
||||
AssertExtensions.Throws<ArgumentException>("destinationArray", "", () => collection.CopyTo(destination, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -133,7 +133,7 @@ namespace System.Security.Authentication.ExtendedProtection.Tests
|
||||
ICollection collection = new ServiceNameCollection(new[] { "first", "second" });
|
||||
int[] destination = new int[collection.Count];
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => collection.CopyTo(destination, -1));
|
||||
Assert.Throws<ArgumentException>(() => collection.CopyTo(destination, destination.Length));
|
||||
AssertExtensions.Throws<ArgumentException>("destinationArray", "", () => collection.CopyTo(destination, destination.Length));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -185,8 +185,8 @@ namespace System.Security.Authentication.ExtendedProtection.Tests
|
||||
public void Merge_NullOrEmptyString_Throws()
|
||||
{
|
||||
var collection = new ServiceNameCollection(new[] { "first", "second" });
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge((string)null));
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge(string.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge((string)null));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge(string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -227,16 +227,16 @@ namespace System.Security.Authentication.ExtendedProtection.Tests
|
||||
public void Merge_EnumerableContainingNullOrEmpty_Throws(string item)
|
||||
{
|
||||
var collection = new ServiceNameCollection(new[] { "first", "second" });
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge(new[] { item }));
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge(new[] { "third", item }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge(new[] { item }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge(new[] { "third", item }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Merge_NonStringEnumerable_Throws()
|
||||
{
|
||||
var collection = new ServiceNameCollection(new[] { "first", "second" });
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge(new[] { 3 }));
|
||||
Assert.Throws<ArgumentException>(() => collection.Merge(new[] { new object() }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge(new[] { 3 }));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => collection.Merge(new[] { new object() }));
|
||||
}
|
||||
|
||||
public static object[][] MergeCollectionsTestData =
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public void SslStream_StreamToStream_Authentication_IncorrectServerName_Fail()
|
||||
{
|
||||
VirtualNetwork network = new VirtualNetwork();
|
||||
@@ -142,7 +141,6 @@ namespace System.Net.Security.Tests
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public void SslStream_StreamToStream_LargeWrites_Sync_Success(bool randomizedData)
|
||||
{
|
||||
VirtualNetwork network = new VirtualNetwork();
|
||||
@@ -189,7 +187,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task SslStream_StreamToStream_Successive_ClientWrite_Async_Success()
|
||||
{
|
||||
byte[] recvBuf = new byte[_sampleMsg.Length];
|
||||
@@ -255,7 +252,6 @@ namespace System.Net.Security.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "https://github.com/dotnet/corefx/issues/19379")]
|
||||
public async Task SslStream_StreamToStream_WriteAsync_ReadByte_Success()
|
||||
{
|
||||
VirtualNetwork network = new VirtualNetwork();
|
||||
|
||||
@@ -13,167 +13,158 @@ namespace System.Net.Security.Tests
|
||||
{
|
||||
using Configuration = System.Net.Test.Common.Configuration;
|
||||
|
||||
public class SslStreamSystemDefaultTest
|
||||
public abstract class SslStreamSystemDefaultTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task SslStream_DefaultTlsConfigurationSync_Ok()
|
||||
protected readonly SslStream _clientStream;
|
||||
protected readonly SslStream _serverStream;
|
||||
|
||||
public SslStreamSystemDefaultTest()
|
||||
{
|
||||
using (var test = new SyncTest())
|
||||
var network = new VirtualNetwork();
|
||||
var clientNet = new VirtualNetworkStream(network, isServer:false);
|
||||
var serverNet = new VirtualNetworkStream(network, isServer: true);
|
||||
|
||||
_clientStream = new SslStream(clientNet, false, ClientCertCallback);
|
||||
_serverStream = new SslStream(serverNet, false, ServerCertCallback);
|
||||
}
|
||||
|
||||
protected abstract Task AuthenticateClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, SslProtocols? protocols = null);
|
||||
protected abstract Task AuthenticateServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, SslProtocols? protocols = null);
|
||||
|
||||
[ActiveIssue(7812, TestPlatforms.Windows)]
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData(SslProtocols.None, null)]
|
||||
[InlineData(null, SslProtocols.None)]
|
||||
[InlineData(SslProtocols.None, SslProtocols.None)]
|
||||
[InlineData(null, SslProtocols.Tls11)]
|
||||
[InlineData(SslProtocols.Tls11, null)]
|
||||
[InlineData(null, SslProtocols.Tls12)]
|
||||
[InlineData(SslProtocols.Tls12, null)]
|
||||
[InlineData(SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, null)]
|
||||
[InlineData(null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12)]
|
||||
public async Task ClientAndServer_OneOrBothUseDefault_Ok(SslProtocols? clientProtocols, SslProtocols? serverProtocols)
|
||||
{
|
||||
X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate();
|
||||
string serverHost = serverCertificate.GetNameInfo(X509NameType.SimpleName, false);
|
||||
var clientCertificates = new X509CertificateCollection();
|
||||
clientCertificates.Add(Configuration.Certificates.GetClientCertificate());
|
||||
|
||||
var tasks = new Task[2];
|
||||
tasks[0] = AuthenticateClientAsync(serverHost, clientCertificates, checkCertificateRevocation: false, protocols: clientProtocols);
|
||||
tasks[1] = AuthenticateServerAsync(serverCertificate, clientCertificateRequired: true, checkCertificateRevocation: false, protocols: serverProtocols);
|
||||
await await Task.WhenAny(tasks);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
if (PlatformDetection.IsWindows && PlatformDetection.WindowsVersion >= 10)
|
||||
{
|
||||
await test.RunTest();
|
||||
Assert.True(_clientStream.HashAlgorithm == HashAlgorithmType.Sha256 ||
|
||||
_clientStream.HashAlgorithm == HashAlgorithmType.Sha384 ||
|
||||
_clientStream.HashAlgorithm == HashAlgorithmType.Sha512);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SslStream_DefaultTlsConfigurationApm_Ok()
|
||||
private bool ClientCertCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
using (var test = new ApmTest())
|
||||
switch (sslPolicyErrors)
|
||||
{
|
||||
await test.RunTest();
|
||||
case SslPolicyErrors.None:
|
||||
case SslPolicyErrors.RemoteCertificateChainErrors:
|
||||
case SslPolicyErrors.RemoteCertificateNameMismatch:
|
||||
return true;
|
||||
case SslPolicyErrors.RemoteCertificateNotAvailable:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SslStream_DefaultTlsConfigurationAsync_Ok()
|
||||
private bool ServerCertCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
using (var test = new AsyncTest())
|
||||
switch (sslPolicyErrors)
|
||||
{
|
||||
await test.RunTest();
|
||||
case SslPolicyErrors.None:
|
||||
case SslPolicyErrors.RemoteCertificateChainErrors:
|
||||
case SslPolicyErrors.RemoteCertificateNameMismatch:
|
||||
return true;
|
||||
case SslPolicyErrors.RemoteCertificateNotAvailable:
|
||||
// https://technet.microsoft.com/en-us/library/hh831771.aspx#BKMK_Changes2012R2
|
||||
// Starting with Windows 8, the "Management of trusted issuers for client authentication" has changed:
|
||||
// The behavior to send the Trusted Issuers List by default is off.
|
||||
//
|
||||
// In Windows 7 the Trusted Issuers List is sent within the Server Hello TLS record. This list is built
|
||||
// by the server using certificates from the Trusted Root Authorities certificate store.
|
||||
// The client side will use the Trusted Issuers List, if not empty, to filter proposed certificates.
|
||||
return PlatformDetection.IsWindows7 && !Capability.IsTrustedRootCertificateInstalled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class TestBase : IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
protected SslStream _clientStream;
|
||||
protected SslStream _serverStream;
|
||||
|
||||
public TestBase()
|
||||
{
|
||||
var network = new VirtualNetwork();
|
||||
var clientNet = new VirtualNetworkStream(network, false);
|
||||
var serverNet = new VirtualNetworkStream(network, true);
|
||||
|
||||
_clientStream = new SslStream(clientNet, false, ClientCertCallback);
|
||||
_serverStream = new SslStream(serverNet, false, ServerCertCallback);
|
||||
}
|
||||
|
||||
public async Task RunTest()
|
||||
{
|
||||
X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate();
|
||||
string serverHost = serverCertificate.GetNameInfo(X509NameType.SimpleName, false);
|
||||
X509CertificateCollection clientCertificates = new X509CertificateCollection();
|
||||
clientCertificates.Add(Configuration.Certificates.GetClientCertificate());
|
||||
|
||||
var tasks = new Task[2];
|
||||
tasks[0] = AuthenticateClient(serverHost, clientCertificates, checkCertificateRevocation: false);
|
||||
tasks[1] = AuthenticateServer(serverCertificate, clientCertificateRequired: true, checkCertificateRevocation: false);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
if (PlatformDetection.IsWindows && PlatformDetection.WindowsVersion >= 10)
|
||||
{
|
||||
Assert.True(_clientStream.HashAlgorithm == HashAlgorithmType.Sha256 ||
|
||||
_clientStream.HashAlgorithm == HashAlgorithmType.Sha384 ||
|
||||
_clientStream.HashAlgorithm == HashAlgorithmType.Sha512);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ClientCertCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
switch (sslPolicyErrors)
|
||||
{
|
||||
case SslPolicyErrors.None:
|
||||
case SslPolicyErrors.RemoteCertificateChainErrors:
|
||||
case SslPolicyErrors.RemoteCertificateNameMismatch:
|
||||
return true;
|
||||
case SslPolicyErrors.RemoteCertificateNotAvailable:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ServerCertCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
switch (sslPolicyErrors)
|
||||
{
|
||||
case SslPolicyErrors.None:
|
||||
case SslPolicyErrors.RemoteCertificateChainErrors:
|
||||
case SslPolicyErrors.RemoteCertificateNameMismatch:
|
||||
return true;
|
||||
case SslPolicyErrors.RemoteCertificateNotAvailable:
|
||||
// https://technet.microsoft.com/en-us/library/hh831771.aspx#BKMK_Changes2012R2
|
||||
// Starting with Windows 8, the "Management of trusted issuers for client authentication" has changed:
|
||||
// The behavior to send the Trusted Issuers List by default is off.
|
||||
//
|
||||
// In Windows 7 the Trusted Issuers List is sent within the Server Hello TLS record. This list is built
|
||||
// by the server using certificates from the Trusted Root Authorities certificate store.
|
||||
// The client side will use the Trusted Issuers List, if not empty, to filter proposed certificates.
|
||||
return PlatformDetection.IsWindows7 && !Capability.IsTrustedRootCertificateInstalled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Task AuthenticateClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
|
||||
|
||||
protected abstract Task AuthenticateServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_clientStream != null)
|
||||
{
|
||||
_clientStream.Dispose();
|
||||
}
|
||||
|
||||
if (_serverStream != null)
|
||||
{
|
||||
_serverStream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SyncTest : TestBase
|
||||
{
|
||||
protected override Task AuthenticateClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation)
|
||||
{
|
||||
return Task.Run( () => { _clientStream.AuthenticateAsClient(targetHost, clientCertificates, checkCertificateRevocation); });
|
||||
}
|
||||
|
||||
protected override Task AuthenticateServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation)
|
||||
{
|
||||
return Task.Run( () => { _serverStream.AuthenticateAsServer(serverCertificate, clientCertificateRequired, checkCertificateRevocation); });
|
||||
}
|
||||
}
|
||||
|
||||
public class ApmTest : TestBase
|
||||
{
|
||||
protected override Task AuthenticateClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(callback, state) => _clientStream.BeginAuthenticateAsClient(targetHost, clientCertificates, checkCertificateRevocation, callback, state),
|
||||
_clientStream.EndAuthenticateAsClient,
|
||||
state:null);
|
||||
}
|
||||
|
||||
protected override Task AuthenticateServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(callback, state) => _serverStream.BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, checkCertificateRevocation, callback, state),
|
||||
_serverStream.EndAuthenticateAsServer,
|
||||
state:null);
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncTest : TestBase
|
||||
{
|
||||
protected override Task AuthenticateClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation)
|
||||
{
|
||||
return _clientStream.AuthenticateAsClientAsync(targetHost, clientCertificates, checkCertificateRevocation);
|
||||
}
|
||||
|
||||
protected override Task AuthenticateServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation)
|
||||
{
|
||||
return _serverStream.AuthenticateAsServerAsync(serverCertificate, clientCertificateRequired, checkCertificateRevocation);
|
||||
}
|
||||
_clientStream?.Dispose();
|
||||
_serverStream?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SyncSslStreamSystemDefaultTest : SslStreamSystemDefaultTest
|
||||
{
|
||||
protected override Task AuthenticateClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (protocols.HasValue)
|
||||
{
|
||||
_clientStream.AuthenticateAsClient(targetHost, clientCertificates, protocols.Value, checkCertificateRevocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
_clientStream.AuthenticateAsClient(targetHost, clientCertificates, checkCertificateRevocation);
|
||||
}
|
||||
});
|
||||
|
||||
protected override Task AuthenticateServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (protocols.HasValue)
|
||||
{
|
||||
_serverStream.AuthenticateAsServer(serverCertificate, clientCertificateRequired, protocols.Value, checkCertificateRevocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
_serverStream.AuthenticateAsServer(serverCertificate, clientCertificateRequired, checkCertificateRevocation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public sealed class ApmSslStreamSystemDefaultTest : SslStreamSystemDefaultTest
|
||||
{
|
||||
protected override Task AuthenticateClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
Task.Factory.FromAsync(
|
||||
(callback, state) => protocols.HasValue ?
|
||||
_clientStream.BeginAuthenticateAsClient(targetHost, clientCertificates, protocols.Value, checkCertificateRevocation, callback, state) :
|
||||
_clientStream.BeginAuthenticateAsClient(targetHost, clientCertificates, checkCertificateRevocation, callback, state),
|
||||
_clientStream.EndAuthenticateAsClient,
|
||||
state: null);
|
||||
|
||||
protected override Task AuthenticateServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
Task.Factory.FromAsync(
|
||||
(callback, state) => protocols.HasValue ?
|
||||
_serverStream.BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, protocols.Value, checkCertificateRevocation, callback, state) :
|
||||
_serverStream.BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, checkCertificateRevocation, callback, state),
|
||||
_serverStream.EndAuthenticateAsServer,
|
||||
state: null);
|
||||
}
|
||||
|
||||
public sealed class AsyncSslStreamSystemDefaultTest : SslStreamSystemDefaultTest
|
||||
{
|
||||
protected override Task AuthenticateClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
protocols.HasValue ?
|
||||
_clientStream.AuthenticateAsClientAsync(targetHost, clientCertificates, protocols.Value, checkCertificateRevocation) :
|
||||
_clientStream.AuthenticateAsClientAsync(targetHost, clientCertificates, checkCertificateRevocation);
|
||||
|
||||
protected override Task AuthenticateServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, SslProtocols? protocols) =>
|
||||
protocols.HasValue ?
|
||||
_serverStream.AuthenticateAsServerAsync(serverCertificate, clientCertificateRequired, protocols.Value, checkCertificateRevocation) :
|
||||
_serverStream.AuthenticateAsServerAsync(serverCertificate, clientCertificateRequired, checkCertificateRevocation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<PropertyGroup Condition=" '$(TargetsUnix)' == 'true' ">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Unix-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Unix-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Windows_NT-Debug|AnyCPU'" />
|
||||
@@ -19,6 +20,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Unix-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-OSX-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-OSX-Release|AnyCPU'" />
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="NotifyReadVirtualNetworkStream.cs" />
|
||||
<Compile Include="DummyTcpServer.cs" />
|
||||
@@ -95,7 +97,7 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)'=='netcoreapp'">
|
||||
<!-- TODO #13070: Add net463 to the condition after the TFM gets updated to the actual .Net 4.6.3.-->
|
||||
<!-- TODO #13070: Add net463 to the condition after the TFM gets updated to the actual .Net 4.7-->
|
||||
<Compile Include="SslStreamAlertsTest.cs" />
|
||||
<Compile Include="SslStreamEKUTest.cs" />
|
||||
<Compile Include="SslStreamSchSendAuxRecordTest.cs" />
|
||||
@@ -107,12 +109,6 @@
|
||||
<Compile Include="$(CommonTestPath)\System\Diagnostics\Tracing\TestEventListener.cs">
|
||||
<Link>Common\System\Diagnostics\Tracing\TestEventListener.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonTestPath)\System\Diagnostics\RemoteExecutorTestBase.cs">
|
||||
<Link>Common\System\Diagnostics\RemoteExecutorTestBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonTestPath)\System\IO\FileCleanupTestBase.cs">
|
||||
<Link>Common\System\IO\FileCleanupTestBase.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' ">
|
||||
<Compile Include="IdentityValidator.Windows.cs" />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user