// - Loads the channel parameters
        // - Optionally verifies the Remote Certificate
        // - Sets HandshakeCompleted flag
        // - Sets the guarding event if other thread is waiting for
        //   handshake completion
        //
        // - Returns false if failed to verify the Remote Cert
        //
        private bool CompleteHandshake(ref ProtocolToken alertToken)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
            }

            _context.ProcessHandshakeSuccess();

            if (!_context.VerifyRemoteCertificate(_sslAuthenticationOptions.CertValidationDelegate, ref alertToken))
            {
                _handshakeCompleted = false;

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this, false);
                }
                return(false);
            }

            _handshakeCompleted = true;

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this, true);
            }
            return(true);
        }
Exemple #2
0
        //
        // Only processing SEC_I_RENEGOTIATE.
        //
        private int ProcessReadErrorCode(SecurityStatusPal errorCode, byte[] buffer, int offset, int count, byte[] extraBuffer)
        {
            // ERROR - examine what kind
            ProtocolToken message = new ProtocolToken(null, errorCode);

            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(this) + "::***Processing an error Status = " + message.Status.ToString());
            }

            if (message.Renegotiate)
            {
                _SslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return(-1);
            }

            if (message.CloseConnection)
            {
                _SslState.FinishRead(null);
                return(0);
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
        //
        // Client side starts here, but server also loops through this method.
        //
        private void SendBlob(byte[] incoming, int count)
        {
            ProtocolToken message = _context.NextMessage(incoming, 0, count);

            _securityStatus = message.Status;

            if (message.Size != 0)
            {
                if (_context.IsServer && _CachedSession == CachedSessionStatus.Unknown)
                {
                    //
                    //[Schannel] If the first call to ASC returns a token less than 200 bytes,
                    //           then it's a reconnect (a handshake based on a cache entry).
                    //
                    _CachedSession = message.Size < 200 ? CachedSessionStatus.IsCached : CachedSessionStatus.IsNotCached;
                }

                if (_framing == Framing.Unified)
                {
                    _framing = DetectFraming(message.Payload, message.Payload.Length);
                }

                InnerStream.Write(message.Payload, 0, message.Size);
            }

            CheckCompletionBeforeNextReceive(message);
        }
        //
        // This will check and logically complete / fail the auth handshake.
        //
        private void CheckCompletionBeforeNextReceive(ProtocolToken message)
        {
            if (message.Failed)
            {
                SendAuthResetSignal(null, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_auth_SSPI, message.GetException())));
                return;
            }
            else if (message.Done)
            {
                ProtocolToken alertToken = null;

                if (!CompleteHandshake(ref alertToken))
                {
                    SendAuthResetSignal(alertToken, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_ssl_io_cert_validation, null)));
                    return;
                }

                // Release waiting IO if any. Presumably it should not throw.
                // Otherwise application may get not expected type of the exception.
                FinishHandshake(null);
                return;
            }

            ReceiveBlob(message.Payload);
        }
Exemple #5
0
        internal void BeginShutdown(LazyAsyncResult lazyResult)
        {
            HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest(lazyResult);

            if (Interlocked.Exchange(ref _NestedWrite, 1) == 1)
            {
                throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginShutdown" : "Shutdown"), "shutdown"));
            }

            bool failed = false;

            try
            {
                ProtocolToken message = _SslState.CreateShutdownMessage();
                asyncRequest.SetNextRequest(HandshakeProtocolState.Shutdown, message, _ResumeHandshakeWriteCallback);

                StartHandshakeWrite(asyncRequest);
            } catch (Exception e) {
                _SslState.FinishWrite();
                failed = true;
                throw;
            } finally {
                if (failed)
                {
                    _NestedWrite = 0;
                }
            }
        }
Exemple #6
0
 private void CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
 {
     if (message.Failed)
     {
         this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), message.GetException()));
     }
     else if (message.Done && !this._PendingReHandshake)
     {
         if (this.CheckWin9xCachedSession())
         {
             this._PendingReHandshake = true;
             this.Win9xSessionRestarted();
             this.ForceAuthentication(false, null, asyncRequest);
         }
         else if (!this.CompleteHandshake())
         {
             this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_ssl_io_cert_validation"), null));
         }
         else
         {
             this.FinishHandshake(null, asyncRequest);
         }
     }
     else
     {
         this.StartReceiveBlob(message.Payload, asyncRequest);
     }
 }
Exemple #7
0
        internal void BeginRenegotiate(LazyAsyncResult lazyResult)
        {
            HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest(lazyResult);

            if (Interlocked.Exchange(ref _NestedWrite, 1) == 1)
            {
                throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRenegotiate" : "Renegotiate"), "renegotiate"));
            }

            bool failed = false;

            try
            {
                if (_SslState.IsServer)
                {
                    ProtocolToken message = _SslState.CreateHelloRequestMessage();
                    asyncRequest.SetNextRequest(HandshakeProtocolState.SendHelloRequest, message, _ResumeHandshakeWriteCallback);
                }
                else
                {
                    asyncRequest.SetNextRequest(HandshakeProtocolState.ClientRenegotiation, null, _ResumeHandshakeWriteCallback);
                }

                StartHandshakeWrite(asyncRequest);
            } catch (Exception e) {
                _SslState.FinishWrite();
                failed = true;
                throw;
            } finally {
                if (failed)
                {
                    _NestedWrite = 0;
                }
            }
        }
Exemple #8
0
        private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            ProtocolToken message = new ProtocolToken(null, status);

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, $"***Processing an error Status = {message.Status}");
            }

            if (message.Renegotiate)
            {
                _sslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return(-1);
            }

            if (message.CloseConnection)
            {
                _sslState.FinishRead(null);
                asyncRequest?.CompleteUser(0);

                return(0);
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
Exemple #9
0
        private async ValueTask <ProtocolToken> ReceiveBlobAsync <TIOAdapter>(TIOAdapter adapter)
            where TIOAdapter : ISslIOAdapter
        {
            int readBytes = await FillHandshakeBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false);

            if (readBytes == 0)
            {
                throw new IOException(SR.net_io_eof);
            }

            if (_framing == Framing.Unified || _framing == Framing.Unknown)
            {
                _framing = DetectFraming(_handshakeBuffer.ActiveReadOnlySpan);
            }

            int frameSize = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan);

            if (frameSize < 0)
            {
                throw new IOException(SR.net_frame_read_size);
            }

            if (_handshakeBuffer.ActiveLength < frameSize)
            {
                await FillHandshakeBufferAsync(adapter, frameSize).ConfigureAwait(false);
            }

            ProtocolToken token = _context.NextMessage(_handshakeBuffer.ActiveReadOnlySpan.Slice(0, frameSize));

            _handshakeBuffer.Discard(frameSize);

            return(token);
        }
Exemple #10
0
        //
        // Only processing SEC_I_RENEGOTIATE.
        //
        private int ProcessReadErrorCode(Interop.SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            // ERROR - examine what kind
            ProtocolToken message = new ProtocolToken(null, errorCode);

            GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::***Processing an error Status = " + message.Status.ToString());

            if (message.Renegotiate)
            {
                _SslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return(-1);
            }

            if (message.CloseConnection)
            {
                _SslState.FinishRead(null);
                if (asyncRequest != null)
                {
                    asyncRequest.CompleteUser((object)0);
                }

                return(0);
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
        //
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback);
            }

            // We loop to this method from the callback
            // If the last chunk was just completed from async callback (count < 0), we complete user request
            if (count >= 0)
            {
                byte[] outBuffer = null;
                do
                {
                    // request a write IO slot
                    if (_SslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // operation is async and has been queued, return.
                        return;
                    }

                    int            chunkBytes = Math.Min(count, _SslState.MaxDataSize);
                    int            encryptedBytes;
                    SecurityStatus errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (errorCode != SecurityStatus.OK)
                    {
                        //
                        ProtocolToken message = new ProtocolToken(null, errorCode);
                        throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException());
                    }

                    if (asyncRequest != null)
                    {
                        // prepare for the next request
                        asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, _ResumeAsyncWriteCallback);
                        IAsyncResult ar = _SslState.InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, _WriteCallback, asyncRequest);
                        if (!ar.CompletedSynchronously)
                        {
                            return;
                        }
                        _SslState.InnerStream.EndWrite(ar);
                    }
                    else
                    {
                        _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                    }
                    offset += chunkBytes;
                    count  -= chunkBytes;

                    // release write IO slot
                    _SslState.FinishWrite();
                } while (count != 0);
            }

            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser();
            }
        }
        internal async Task ForceAuthenticationAsync(bool receiveFirst, byte[] buffer, CancellationToken cancellationToken)
        {
            _framing = Framing.Unknown;
            ProtocolToken message;
            SslReadAsync  adapter = new SslReadAsync(this, cancellationToken);

            if (!receiveFirst)
            {
                message = _context.NextMessage(buffer, 0, (buffer == null ? 0 : buffer.Length));
                if (message.Failed)
                {
                    // tracing done in NextMessage()
                    throw new AuthenticationException(SR.net_auth_SSPI, message.GetException());
                }

                await InnerStream.WriteAsync(message.Payload, cancellationToken).ConfigureAwait(false);
            }

            do
            {
                message = await ReceiveBlobAsync(adapter, buffer, cancellationToken).ConfigureAwait(false);

                if (message.Size > 0)
                {
                    // If there is message send it out even if call failed. It may contain TLS Alert.
                    await InnerStream.WriteAsync(message.Payload, cancellationToken).ConfigureAwait(false);
                }

                if (message.Failed)
                {
                    throw new AuthenticationException(SR.net_auth_SSPI, message.GetException());
                }
            } while (message.Status.ErrorCode != SecurityStatusPalErrorCode.OK);

            ProtocolToken alertToken = null;

            if (!CompleteHandshake(ref alertToken))
            {
                SendAuthResetSignal(alertToken, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_ssl_io_cert_validation, null)));
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Log.SspiSelectedCipherSuite(nameof(ForceAuthenticationAsync),
                                                           SslProtocol,
                                                           CipherAlgorithm,
                                                           CipherStrength,
                                                           HashAlgorithm,
                                                           HashStrength,
                                                           KeyExchangeAlgorithm,
                                                           KeyExchangeStrength);
            }
        }
        //
        //  This is to reset auth state on remote side.
        //  If this write succeeds we will allow auth retrying.
        //
        private void SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
        {
            SetException(exception.SourceException);

            if (message == null || message.Size == 0)
            {
                //
                // We don't have an alert to send so cannot retry and fail prematurely.
                //
                exception.Throw();
            }

            InnerStream.Write(message.Payload, 0, message.Size);

            exception.Throw();
        }
Exemple #14
0
 private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
 {
     if (asyncRequest != null)
     {
         asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback);
     }
     if (count >= 0)
     {
         byte[] outBuffer = null;
         do
         {
             int num2;
             if (this._SslState.CheckEnqueueWrite(asyncRequest))
             {
                 return;
             }
             int            num       = Math.Min(count, this._SslState.MaxDataSize);
             SecurityStatus errorCode = this._SslState.EncryptData(buffer, offset, num, ref outBuffer, out num2);
             if (errorCode != SecurityStatus.OK)
             {
                 ProtocolToken token = new ProtocolToken(null, errorCode);
                 throw new IOException(SR.GetString("net_io_encrypt"), token.GetException());
             }
             if (asyncRequest != null)
             {
                 asyncRequest.SetNextRequest(buffer, offset + num, count - num, _ResumeAsyncWriteCallback);
                 IAsyncResult asyncResult = this._SslState.InnerStream.BeginWrite(outBuffer, 0, num2, _WriteCallback, asyncRequest);
                 if (!asyncResult.CompletedSynchronously)
                 {
                     return;
                 }
                 this._SslState.InnerStream.EndWrite(asyncResult);
             }
             else
             {
                 this._SslState.InnerStream.Write(outBuffer, 0, num2);
             }
             offset += num;
             count  -= num;
             this._SslState.FinishWrite();
         }while (count != 0);
     }
     if (asyncRequest != null)
     {
         asyncRequest.CompleteUser();
     }
 }
        //
        internal ProtocolToken NextMessage(byte[] incoming, int offset, int count)
        {
            GlobalLog.Enter("SecureChannel#" + Logging.HashString(this) + "::NextMessage");
            byte[]            nextmsg   = null;
            SecurityStatusPal errorCode = GenerateToken(incoming, offset, count, ref nextmsg);

            if (!_serverMode && errorCode == SecurityStatusPal.CredentialsNeeded)
            {
                GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::NextMessage() returned SecurityStatusPal.CredentialsNeeded");
                SetRefreshCredentialNeeded();
                errorCode = GenerateToken(incoming, offset, count, ref nextmsg);
            }

            ProtocolToken token = new ProtocolToken(nextmsg, errorCode);

            GlobalLog.Leave("SecureChannel#" + Logging.HashString(this) + "::NextMessage", token.ToString());
            return(token);
        }
        private async ValueTask <ProtocolToken> ReceiveBlobAsync <TIOAdapter>(TIOAdapter adapter)
            where TIOAdapter : ISslIOAdapter
        {
            ResetReadBuffer();
            int readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false);

            if (readBytes == 0)
            {
                throw new IOException(SR.net_io_eof);
            }

            if (_framing == Framing.Unified || _framing == Framing.Unknown)
            {
                _framing = DetectFraming(_internalBuffer, readBytes);
            }

            int payloadBytes = GetRemainingFrameSize(_internalBuffer, _internalOffset, readBytes);

            if (payloadBytes < 0)
            {
                throw new IOException(SR.net_frame_read_size);
            }

            int frameSize = SecureChannel.ReadHeaderSize + payloadBytes;

            if (readBytes < frameSize)
            {
                readBytes = await FillBufferAsync(adapter, frameSize).ConfigureAwait(false);

                Debug.Assert(readBytes >= 0);
                if (readBytes == 0)
                {
                    throw new IOException(SR.net_io_eof);
                }
            }

            ProtocolToken token = _context.NextMessage(_internalBuffer, _internalOffset, frameSize);

            ConsumeBufferedBytes(frameSize);

            return(token);
        }
Exemple #17
0
        private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            ProtocolToken token = new ProtocolToken(null, errorCode);

            if (token.Renegotiate)
            {
                this._SslState.ReplyOnReAuthentication(extraBuffer);
                return(-1);
            }
            if (!token.CloseConnection)
            {
                throw new IOException(SR.GetString("net_io_decrypt"), token.GetException());
            }
            this._SslState.FinishRead(null);
            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser(0);
            }
            return(0);
        }
Exemple #18
0
 private void StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
 {
     if ((message == null) || (message.Size == 0))
     {
         throw exception;
     }
     if (asyncRequest == null)
     {
         this.InnerStream.Write(message.Payload, 0, message.Size);
     }
     else
     {
         asyncRequest.AsyncState = exception;
         IAsyncResult asyncResult = this.InnerStream.BeginWrite(message.Payload, 0, message.Size, _WriteCallback, asyncRequest);
         if (!asyncResult.CompletedSynchronously)
         {
             return;
         }
         this.InnerStream.EndWrite(asyncResult);
     }
     throw exception;
 }
Exemple #19
0
        private void StartSendBlob(byte[] incoming, int count, AsyncProtocolRequest asyncRequest)
        {
            ProtocolToken message = this.Context.NextMessage(incoming, 0, count);

            this._SecurityStatus = message.Status;
            if (message.Size != 0)
            {
                if (this.Context.IsServer && (this._CachedSession == CachedSessionStatus.Unknown))
                {
                    this._CachedSession = (message.Size < 200) ? CachedSessionStatus.IsCached : CachedSessionStatus.IsNotCached;
                }
                if (this._Framing == Framing.Unified)
                {
                    this._Framing = this.DetectFraming(message.Payload, message.Payload.Length);
                }
                if (((message.Done && this._ForceBufferingLastHandshakePayload) && ((this.InnerStream.GetType() == typeof(NetworkStream)) && !this._PendingReHandshake)) && !this.CheckWin9xCachedSession())
                {
                    this._LastPayload = message.Payload;
                }
                else if (asyncRequest == null)
                {
                    this.InnerStream.Write(message.Payload, 0, message.Size);
                }
                else
                {
                    asyncRequest.AsyncState = message;
                    IAsyncResult asyncResult = this.InnerStream.BeginWrite(message.Payload, 0, message.Size, _WriteCallback, asyncRequest);
                    if (!asyncResult.CompletedSynchronously)
                    {
                        return;
                    }
                    this.InnerStream.EndWrite(asyncResult);
                }
            }
            this.CheckCompletionBeforeNextReceive(message, asyncRequest);
        }
Exemple #20
0
 private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest)
 {
     if (count == 0)
     {
         throw new AuthenticationException(SR.GetString("net_auth_eof"), null);
     }
     if (this._PendingReHandshake)
     {
         int            offset    = 0;
         SecurityStatus errorCode = this.PrivateDecryptData(buffer, ref offset, ref count);
         if (errorCode == SecurityStatus.OK)
         {
             Exception exception = this.EnqueueOldKeyDecryptedData(buffer, offset, count);
             if (exception != null)
             {
                 this.StartSendAuthResetSignal(null, asyncRequest, exception);
                 return;
             }
             this._Framing = Framing.None;
             this.StartReceiveBlob(buffer, asyncRequest);
             return;
         }
         if (errorCode != SecurityStatus.Renegotiate)
         {
             ProtocolToken token = new ProtocolToken(null, errorCode);
             this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), token.GetException()));
             return;
         }
         this._PendingReHandshake = false;
         if (offset != 0)
         {
             Buffer.BlockCopy(buffer, offset, buffer, 0, count);
         }
     }
     this.StartSendBlob(buffer, count, asyncRequest);
 }
Exemple #21
0
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback);
            }

            // We loop to this method from the callback.
            // If the last chunk was just completed from async callback (count < 0), we complete user request.
            if (count >= 0)
            {
                byte[] outBuffer = null;
                if (_pinnableOutputBufferInUse == null)
                {
                    if (_pinnableOutputBuffer == null)
                    {
                        _pinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer();
                    }

                    _pinnableOutputBufferInUse = buffer;
                    outBuffer = _pinnableOutputBuffer;
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }
                }
                else
                {
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count);
                    }
                }

                do
                {
                    if (count == 0 && !SslStreamPal.CanEncryptEmptyMessage)
                    {
                        // If it's an empty message and the PAL doesn't support that,
                        // we're done.
                        break;
                    }

                    // Request a write IO slot.
                    if (_sslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // Operation is async and has been queued, return.
                        return;
                    }

                    int chunkBytes = Math.Min(count, _sslState.MaxDataSize);
                    int encryptedBytes;
                    SecurityStatusPal status = _sslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
                    {
                        // Re-handshake status is not supported.
                        ProtocolToken message = new ProtocolToken(null, status);
                        throw new IOException(SR.net_io_encrypt, message.GetException());
                    }

                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer",
                                                                         this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }

                    if (asyncRequest != null)
                    {
                        // Prepare for the next request.
                        asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback);
                        Task t = _sslState.InnerStream.WriteAsync(outBuffer, 0, encryptedBytes);
                        if (t.IsCompleted)
                        {
                            t.GetAwaiter().GetResult();
                        }
                        else
                        {
                            IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
                            if (!ar.CompletedSynchronously)
                            {
                                return;
                            }
                            TaskToApm.End(ar);
                        }
                    }
                    else
                    {
                        _sslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                    }

                    offset += chunkBytes;
                    count  -= chunkBytes;

                    // Release write IO slot.
                    _sslState.FinishWrite();
                } while (count != 0);
            }

            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser();
            }

            if (buffer == _pinnableOutputBufferInUse)
            {
                _pinnableOutputBufferInUse = null;
                if (PinnableBufferCacheEventSource.Log.IsEnabled())
                {
                    PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode());
                }
            }
        }
Exemple #22
0
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback);
            }

            // We loop to this method from the callback.
            // If the last chunk was just completed from async callback (count < 0), we complete user request.
            if (count >= 0 )
            {
                byte[] outBuffer = null;
                if (_pinnableOutputBufferInUse == null)
                {
                    if (_pinnableOutputBuffer == null)
                    {
                        _pinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer();
                    }

                    _pinnableOutputBufferInUse = buffer;
                    outBuffer = _pinnableOutputBuffer;
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }
                }
                else
                {
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count);
                    }
                }

                do
                {
                    // Request a write IO slot.
                    if (_sslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // Operation is async and has been queued, return.
                        return;
                    }

                    int chunkBytes = Math.Min(count, _sslState.MaxDataSize);
                    int encryptedBytes;
                    SecurityStatusPal status = _sslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
                    {
                        // Re-handshake status is not supported.
                        ProtocolToken message = new ProtocolToken(null, status);
                        throw new IOException(SR.net_io_encrypt, message.GetException());
                    }

                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer",
                            this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }

                    if (asyncRequest != null)
                    {
                        // Prepare for the next request.
                        asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback);
                        IAsyncResult ar = _sslState.InnerStreamAPM.BeginWrite(outBuffer, 0, encryptedBytes, s_writeCallback, asyncRequest);
                        if (!ar.CompletedSynchronously)
                        {
                            return;
                        }

                        _sslState.InnerStreamAPM.EndWrite(ar);

                    }
                    else
                    {
                        _sslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                    }

                    offset += chunkBytes;
                    count -= chunkBytes;

                    // Release write IO slot.
                    _sslState.FinishWrite();

                } while (count != 0);
            }

            if (asyncRequest != null) 
            {
                asyncRequest.CompleteUser();
            }

            if (buffer == _pinnableOutputBufferInUse)
            {
                _pinnableOutputBufferInUse = null;
                if (PinnableBufferCacheEventSource.Log.IsEnabled())
                {
                    PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode());
                }
            }
        }
Exemple #23
0
 public void SetNextRequest(HandshakeProtocolState state, ProtocolToken message, HandshakeProtocolCallback callback)
 {
     State   = state;
     Message = message;
     SetNextRequest(null, 0, 0, (r) => callback((HandshakeProtocolRequest)r));
 }
Exemple #24
0
        // - Loads the channel parameters
        // - Optionally verifies the Remote Certificate
        // - Sets HandshakeCompleted flag
        // - Sets the guarding event if other thread is waiting for
        //   handshake completion
        //
        // - Returns false if failed to verify the Remote Cert
        //
        private bool CompleteHandshake(ref ProtocolToken alertToken)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Enter(this);

            Context.ProcessHandshakeSuccess();

            if (!Context.VerifyRemoteCertificate(_certValidationDelegate, ref alertToken))
            {
                _handshakeCompleted = false;
                _certValidationFailed = true;

                if (NetEventSource.IsEnabled) NetEventSource.Exit(this, false);
                return false;
            }

            _certValidationFailed = false;
            _handshakeCompleted = true;

            if (NetEventSource.IsEnabled) NetEventSource.Exit(this, true);
            return true;
        }
Exemple #25
0
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback);
            }

            // We loop to this method from the callback.
            // If the last chunk was just completed from async callback (count < 0), we complete user request.
            if (count >= 0)
            {
                byte[] outBuffer = null;
                if (_PinnableOutputBufferInUse == null)
                {
                    if (_PinnableOutputBuffer == null)
                    {
                        _PinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer();
                    }

                    _PinnableOutputBufferInUse = buffer;
                    outBuffer = _PinnableOutputBuffer;
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }
                }
                else
                {
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count);
                    }
                }

                do
                {
                    // Request a write IO slot.
                    if (_SslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // Operation is async and has been queued, return.
                        return;
                    }

                    int chunkBytes = Math.Min(count, _SslState.MaxDataSize);
                    int encryptedBytes;
                    Interop.SecurityStatus errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (errorCode != Interop.SecurityStatus.OK)
                    {
                        ProtocolToken message = new ProtocolToken(null, errorCode);
                        throw new IOException(SR.net_io_encrypt, message.GetException());
                    }

                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer",
                                                                         this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }

                    if (asyncRequest != null)
                    {
                        // Prepare for the next request.
                        asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback);
                        IAsyncResult ar = _SslState.InnerStreamAPM.BeginWrite(outBuffer, 0, encryptedBytes, s_writeCallback, asyncRequest);
                        if (!ar.CompletedSynchronously)
                        {
                            return;
                        }

                        _SslState.InnerStreamAPM.EndWrite(ar);
                    }
                    else
                    {
                        _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                    }

                    offset += chunkBytes;
                    count  -= chunkBytes;

                    // Release write IO slot.
                    _SslState.FinishWrite();
                } while (count != 0);
            }

            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser();
            }

            if (buffer == _PinnableOutputBufferInUse)
            {
                _PinnableOutputBufferInUse = null;
                if (PinnableBufferCacheEventSource.Log.IsEnabled())
                {
                    PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode());
                }
            }
        }
Exemple #26
0
        /*++
            VerifyRemoteCertificate - Validates the content of a Remote Certificate

            checkCRL if true, checks the certificate revocation list for validity.
            checkCertName, if true checks the CN field of the certificate
        --*/

        //This method validates a remote certificate.
        //SECURITY: The scenario is allowed in semitrust StorePermission is asserted for Chain.Build
        //          A user callback has unique signature so it is safe to call it under permission assert.
        //
        internal bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ref ProtocolToken alertToken)
        {
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Enter("SecureChannel#" + LoggingHash.HashString(this) + "::VerifyRemoteCertificate");
            }

            SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;

            // We don't catch exceptions in this method, so it's safe for "accepted" be initialized with true.
            bool success = false;
            X509Chain chain = null;
            X509Certificate2 remoteCertificateEx = null;

            try
            {
                X509Certificate2Collection remoteCertificateStore;
                remoteCertificateEx = CertificateValidationPal.GetRemoteCertificate(_securityContext, out remoteCertificateStore);
                _isRemoteCertificateAvailable = remoteCertificateEx != null;

                if (remoteCertificateEx == null)
                {
                    if (GlobalLog.IsEnabled)
                    {
                        GlobalLog.Leave("SecureChannel#" + LoggingHash.HashString(this) + "::VerifyRemoteCertificate (no remote cert)", (!_remoteCertRequired).ToString());
                    }
                    sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                }
                else
                {
                    chain = new X509Chain();
                    chain.ChainPolicy.RevocationMode = _checkCertRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck;
                    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
                    if (remoteCertificateStore != null)
                    {
                        chain.ChainPolicy.ExtraStore.AddRange(remoteCertificateStore);
                    }

                    sslPolicyErrors |= CertificateValidationPal.VerifyCertificateProperties(
                        chain,
                        remoteCertificateEx,
                        _checkCertName,
                        _serverMode,
                        _hostName);
                }

                if (remoteCertValidationCallback != null)
                {
                    success = remoteCertValidationCallback(_hostName, remoteCertificateEx, chain, sslPolicyErrors);
                }
                else
                {
                    if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable && !_remoteCertRequired)
                    {
                        success = true;
                    }
                    else
                    {
                        success = (sslPolicyErrors == SslPolicyErrors.None);
                    }
                }

                if (SecurityEventSource.Log.IsEnabled())
                {
                    LogCertificateValidation(remoteCertValidationCallback, sslPolicyErrors, success, chain);
                }

                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("Cert Validation, remote cert = " + (remoteCertificateEx == null ? "<null>" : remoteCertificateEx.ToString(true)));
                }

                if (!success)
                {
                    alertToken = CreateFatalHandshakeAlertToken(sslPolicyErrors, chain);
                }
            }
            finally
            {
                // At least on Win2k server the chain is found to have dependencies on the original cert context.
                // So it should be closed first.
                if (chain != null)
                {
                    chain.Dispose();
                }

                if (remoteCertificateEx != null)
                {
                    remoteCertificateEx.Dispose();
                }
            }

            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Leave("SecureChannel#" + LoggingHash.HashString(this) + "::VerifyRemoteCertificate", success.ToString());
            }

            return success;
        }
Exemple #27
0
        //
        // Only processing SEC_I_RENEGOTIATE.
        //
        private int ProcessReadErrorCode(SecurityStatusPal errorCode, byte[] buffer, int offset, int count, byte[] extraBuffer)
        {
            // ERROR - examine what kind
            ProtocolToken message = new ProtocolToken(null, errorCode);

            GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::***Processing an error Status = " + message.Status.ToString());

            if (message.Renegotiate)
            {
                _SslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return -1;
            }

            if (message.CloseConnection)
            {
                _SslState.FinishRead(null);
                return 0;
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
Exemple #28
0
        private void StartWriting(byte[] buffer, int offset, int count)
        {
            // We loop to this method from the callback.
            // If the last chunk was just completed from async callback (count < 0), we complete user request.
            if (count >= 0)
            {
                byte[] outBuffer = null;
                if (_PinnableOutputBufferInUse == null)
                {
                    if (_PinnableOutputBuffer == null)
                    {
                        _PinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer();
                    }

                    _PinnableOutputBufferInUse = buffer;
                    outBuffer = _PinnableOutputBuffer;
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }
                }
                else
                {
                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count);
                    }
                }

                do
                {
                    // Request a write IO slot.
                    if (_SslState.CheckEnqueueWrite(null))
                    {
                        // Operation is async and has been queued, return.
                        return;
                    }

                    int chunkBytes = Math.Min(count, _SslState.MaxDataSize);
                    int encryptedBytes;
                    SecurityStatusPal errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (errorCode != SecurityStatusPal.OK)
                    {
                        ProtocolToken message = new ProtocolToken(null, errorCode);
                        throw new IOException(SR.net_io_encrypt, message.GetException());
                    }

                    if (PinnableBufferCacheEventSource.Log.IsEnabled())
                    {
                        PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer",
                            this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
                    }

                    _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes);

                    offset += chunkBytes;
                    count -= chunkBytes;

                    // Release write IO slot.
                    _SslState.FinishWrite();
                } while (count != 0);
            }

            if (buffer == _PinnableOutputBufferInUse)
            {
                _PinnableOutputBufferInUse = null;
                if (PinnableBufferCacheEventSource.Log.IsEnabled())
                {
                    PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode());
                }
            }
        }
Exemple #29
0
			public void SetNextRequest (HandshakeProtocolState state, ProtocolToken message, HandshakeProtocolCallback callback)
			{
				State = state;
				Message = message;
				SetNextRequest (null, 0, 0, (r) => callback ((HandshakeProtocolRequest)r));
			}
Exemple #30
0
        // - Loads the channel parameters
        // - Optionally verifies the Remote Certificate
        // - Sets HandshakeCompleted flag
        // - Sets the guarding event if other thread is waiting for
        //   handshake completion
        //
        // - Returns false if failed to verify the Remote Cert
        //
        private bool CompleteHandshake(ref ProtocolToken alertToken)
        {
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Enter("CompleteHandshake");
            }

            Context.ProcessHandshakeSuccess();

            if (!Context.VerifyRemoteCertificate(_certValidationDelegate, ref alertToken))
            {
                _handshakeCompleted = false;
                _certValidationFailed = true;

                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Leave("CompleteHandshake", false);
                }

                return false;
            }

            _certValidationFailed = false;
            _handshakeCompleted = true;

            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Leave("CompleteHandshake", true);
            }

            return true;
        }
        //
        //
        //
        private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest)
        {
            if (count == 0)
            {
                // EOF received
                throw new AuthenticationException(SR.GetString(SR.net_auth_eof), null);
            }

            if (_PendingReHandshake)
            {
                int offset = 0;
                SecurityStatus status = PrivateDecryptData(buffer, ref offset, ref count);

                if (status == SecurityStatus.OK)
                {
                    Exception e = EnqueueOldKeyDecryptedData(buffer, offset, count);
                    if (e != null)
                    {
                        StartSendAuthResetSignal(null, asyncRequest, e);
                        return;
                    }
                    // Again, forget about framing we can get a new one at any time
                    _Framing = Framing.None;
                    StartReceiveBlob(buffer, asyncRequest);
                    return;
                }
                else if (status != SecurityStatus.Renegotiate)
                {
                    // fail re-handshake
                    ProtocolToken message = new ProtocolToken(null, status);
                    StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString(SR.net_auth_SSPI), message.GetException()));
                    return;
                }

                // Got it, now we should expect only handshake messages
                _PendingReHandshake = false;
                if (offset != 0)
                {
                    Buffer.BlockCopy(buffer, offset, buffer, 0, count);
                }
            }
            StartSendBlob(buffer, count, asyncRequest);
        }
 private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload)
 {
     List<BufferOffsetSize> list = null;
     SecurityStatus oK = SecurityStatus.OK;
     foreach (BufferOffsetSize size in buffers)
     {
         int num2;
         int count = Math.Min(size.Size, this._SslState.MaxDataSize);
         byte[] outBuffer = null;
         oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2);
         if (oK != SecurityStatus.OK)
         {
             break;
         }
         if ((count != size.Size) || (list != null))
         {
             if (list == null)
             {
                 list = new List<BufferOffsetSize>(buffers.Length * ((size.Size / count) + 1));
                 if (lastHandshakePayload != null)
                 {
                     list.Add(new BufferOffsetSize(lastHandshakePayload, false));
                 }
                 foreach (BufferOffsetSize size2 in buffers)
                 {
                     if (size2 == size)
                     {
                         break;
                     }
                     list.Add(size2);
                 }
             }
             list.Add(new BufferOffsetSize(outBuffer, 0, num2, false));
             while ((size.Size -= count) != 0)
             {
                 size.Offset += count;
                 count = Math.Min(size.Size, this._SslState.MaxDataSize);
                 oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2);
                 if (oK != SecurityStatus.OK)
                 {
                     break;
                 }
                 list.Add(new BufferOffsetSize(outBuffer, 0, num2, false));
             }
         }
         else
         {
             size.Buffer = outBuffer;
             size.Offset = 0;
             size.Size = num2;
         }
         if (oK != SecurityStatus.OK)
         {
             break;
         }
     }
     if (oK != SecurityStatus.OK)
     {
         ProtocolToken token = new ProtocolToken(null, oK);
         throw new IOException(SR.GetString("net_io_encrypt"), token.GetException());
     }
     if (list != null)
     {
         buffers = list.ToArray();
         return buffers;
     }
     if (lastHandshakePayload != null)
     {
         BufferOffsetSize[] destinationArray = new BufferOffsetSize[buffers.Length + 1];
         Array.Copy(buffers, 0, destinationArray, 1, buffers.Length);
         destinationArray[0] = new BufferOffsetSize(lastHandshakePayload, false);
         buffers = destinationArray;
     }
     return buffers;
 }
Exemple #33
0
        //
        // This will check and logically complete / fail the auth handshake.
        //
        private void CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
        {
            if (message.Failed)
            {
                StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_auth_SSPI, message.GetException())));
                return;
            }
            else if (message.Done && !_pendingReHandshake)
            {
                if (!CompleteHandshake())
                {
                    StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_ssl_io_cert_validation, null)));
                    return;
                }

                // Release waiting IO if any. Presumably it should not throw.
                // Otherwise application may get not expected type of the exception.
                FinishHandshake(null, asyncRequest);
                return;
            }

            StartReceiveBlob(message.Payload, asyncRequest);
        }
Exemple #34
0
        //
        //  This is to reset auth state on remote side.
        //  If this write succeeds we will allow auth retrying.
        //
        private void StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
        {
            if (message == null || message.Size == 0)
            {
                //
                // We don't have an alert to send so cannot retry and fail prematurely.
                //
                exception.Throw();
            }

            if (asyncRequest == null)
            {
                InnerStream.Write(message.Payload, 0, message.Size);
            }
            else
            {
                asyncRequest.AsyncState = exception;
                IAsyncResult ar = InnerStreamAPM.BeginWrite(message.Payload, 0, message.Size, s_writeCallback, asyncRequest);
                if (!ar.CompletedSynchronously)
                {
                    return;
                }
                InnerStreamAPM.EndWrite(ar);
            }

            exception.Throw();
        }
Exemple #35
0
        private ProtocolToken GenerateAlertToken()
        {
            byte[] nextmsg = null;

            SecurityStatusPal status;
            status = GenerateToken(null, 0, 0, ref nextmsg);

            ProtocolToken token = new ProtocolToken(nextmsg, status);

            return token;
        }
Exemple #36
0
        //
        internal ProtocolToken NextMessage(byte[] incoming, int offset, int count)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Enter(this);

            byte[] nextmsg = null;
            SecurityStatusPal status = GenerateToken(incoming, offset, count, ref nextmsg);

            if (!_serverMode && status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded)
            {
                if (NetEventSource.IsEnabled) NetEventSource.Info(this, "NextMessage() returned SecurityStatusPal.CredentialsNeeded");

                SetRefreshCredentialNeeded();
                status = GenerateToken(incoming, offset, count, ref nextmsg);
            }

            ProtocolToken token = new ProtocolToken(nextmsg, status);
            if (NetEventSource.IsEnabled) NetEventSource.Exit(this, token);
            return token;
        }
Exemple #37
0
        private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload)
        {
            List <BufferOffsetSize> list = null;
            SecurityStatus          oK   = SecurityStatus.OK;

            foreach (BufferOffsetSize size in buffers)
            {
                int    num2;
                int    count     = Math.Min(size.Size, this._SslState.MaxDataSize);
                byte[] outBuffer = null;
                oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2);
                if (oK != SecurityStatus.OK)
                {
                    break;
                }
                if ((count != size.Size) || (list != null))
                {
                    if (list == null)
                    {
                        list = new List <BufferOffsetSize>(buffers.Length * ((size.Size / count) + 1));
                        if (lastHandshakePayload != null)
                        {
                            list.Add(new BufferOffsetSize(lastHandshakePayload, false));
                        }
                        foreach (BufferOffsetSize size2 in buffers)
                        {
                            if (size2 == size)
                            {
                                break;
                            }
                            list.Add(size2);
                        }
                    }
                    list.Add(new BufferOffsetSize(outBuffer, 0, num2, false));
                    while ((size.Size -= count) != 0)
                    {
                        size.Offset += count;
                        count        = Math.Min(size.Size, this._SslState.MaxDataSize);
                        oK           = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2);
                        if (oK != SecurityStatus.OK)
                        {
                            break;
                        }
                        list.Add(new BufferOffsetSize(outBuffer, 0, num2, false));
                    }
                }
                else
                {
                    size.Buffer = outBuffer;
                    size.Offset = 0;
                    size.Size   = num2;
                }
                if (oK != SecurityStatus.OK)
                {
                    break;
                }
            }
            if (oK != SecurityStatus.OK)
            {
                ProtocolToken token = new ProtocolToken(null, oK);
                throw new IOException(SR.GetString("net_io_encrypt"), token.GetException());
            }
            if (list != null)
            {
                buffers = list.ToArray();
                return(buffers);
            }
            if (lastHandshakePayload != null)
            {
                BufferOffsetSize[] destinationArray = new BufferOffsetSize[buffers.Length + 1];
                Array.Copy(buffers, 0, destinationArray, 1, buffers.Length);
                destinationArray[0] = new BufferOffsetSize(lastHandshakePayload, false);
                buffers             = destinationArray;
            }
            return(buffers);
        }
Exemple #38
0
        private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            ProtocolToken message = new ProtocolToken(null, status);
            if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"***Processing an error Status = {message.Status}");

            if (message.Renegotiate)
            {
                _sslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return -1;
            }

            if (message.CloseConnection)
            {
                _sslState.FinishRead(null);
                if (asyncRequest != null)
                {
                    asyncRequest.CompleteUser((object)0);
                }

                return 0;
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
        // reAuthenticationData is only used on Windows in case of renegotiation.
        private async Task ForceAuthenticationAsync <TIOAdapter>(TIOAdapter adapter, bool receiveFirst, byte[] reAuthenticationData, bool isApm = false)
            where TIOAdapter : ISslIOAdapter
        {
            _framing = Framing.Unknown;
            ProtocolToken message;

            if (reAuthenticationData == null)
            {
                // prevent nesting only when authentication functions are called explicitly. e.g. handle renegotiation tansparently.
                if (Interlocked.Exchange(ref _nestedAuth, 1) == 1)
                {
                    throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, isApm ? "BeginAuthenticate" : "Authenticate", "authenticate"));
                }
            }

            try
            {
                if (!receiveFirst)
                {
                    message = _context.NextMessage(reAuthenticationData, 0, (reAuthenticationData == null ? 0 : reAuthenticationData.Length));
                    if (message.Size > 0)
                    {
                        await adapter.WriteAsync(message.Payload, 0, message.Size).ConfigureAwait(false);
                    }

                    if (message.Failed)
                    {
                        // tracing done in NextMessage()
                        throw new AuthenticationException(SR.net_auth_SSPI, message.GetException());
                    }
                }

                do
                {
                    message = await ReceiveBlobAsync(adapter).ConfigureAwait(false);

                    if (message.Size > 0)
                    {
                        // If there is message send it out even if call failed. It may contain TLS Alert.
                        await adapter.WriteAsync(message.Payload, 0, message.Size).ConfigureAwait(false);
                    }

                    if (message.Failed)
                    {
                        throw new AuthenticationException(SR.net_auth_SSPI, message.GetException());
                    }
                } while (message.Status.ErrorCode != SecurityStatusPalErrorCode.OK);

                ProtocolToken alertToken = null;
                if (!CompleteHandshake(ref alertToken))
                {
                    SendAuthResetSignal(alertToken, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_ssl_io_cert_validation, null)));
                }
            }
            finally
            {
                if (reAuthenticationData == null)
                {
                    _nestedAuth = 0;
                }
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Log.SspiSelectedCipherSuite(nameof(ForceAuthenticationAsync),
                                                           SslProtocol,
                                                           CipherAlgorithm,
                                                           CipherStrength,
                                                           HashAlgorithm,
                                                           HashStrength,
                                                           KeyExchangeAlgorithm,
                                                           KeyExchangeStrength);
            }
        }
 private void CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
 {
     if (message.Failed)
     {
         this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), message.GetException()));
     }
     else if (message.Done && !this._PendingReHandshake)
     {
         if (this.CheckWin9xCachedSession())
         {
             this._PendingReHandshake = true;
             this.Win9xSessionRestarted();
             this.ForceAuthentication(false, null, asyncRequest);
         }
         else if (!this.CompleteHandshake())
         {
             this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_ssl_io_cert_validation"), null));
         }
         else
         {
             this.FinishHandshake(null, asyncRequest);
         }
     }
     else
     {
         this.StartReceiveBlob(message.Payload, asyncRequest);
     }
 }
 private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
 {
     ProtocolToken token = new ProtocolToken(null, errorCode);
     if (token.Renegotiate)
     {
         this._SslState.ReplyOnReAuthentication(extraBuffer);
         return -1;
     }
     if (!token.CloseConnection)
     {
         throw new IOException(SR.GetString("net_io_decrypt"), token.GetException());
     }
     this._SslState.FinishRead(null);
     if (asyncRequest != null)
     {
         asyncRequest.CompleteUser(0);
     }
     return 0;
 }
Exemple #42
0
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback);
            }

            // We loop to this method from the callback.
            // If the last chunk was just completed from async callback (count < 0), we complete user request.
            if (count >= 0)
            {
                do
                {
                    if (count == 0 && !SslStreamPal.CanEncryptEmptyMessage)
                    {
                        // If it's an empty message and the PAL doesn't support that,
                        // we're done.
                        break;
                    }

                    // Request a write IO slot.
                    if (_sslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // Operation is async and has been queued, return.
                        return;
                    }

                    int    chunkBytes   = Math.Min(count, _sslState.MaxDataSize);
                    byte[] rentedBuffer = ArrayPool <byte> .Shared.Rent(chunkBytes + FrameOverhead);

                    byte[] outBuffer      = rentedBuffer;
                    int    encryptedBytes = 0;

                    SecurityStatusPal status = _sslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
                    {
                        // Re-handshake status is not supported.
                        ProtocolToken message = new ProtocolToken(null, status);
                        ArrayPool <byte> .Shared.Return(rentedBuffer);

                        throw new IOException(SR.net_io_encrypt, message.GetException());
                    }

                    if (asyncRequest != null)
                    {
                        // Prepare for the next request.
                        asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback);
                        Task t = _sslState.InnerStream.WriteAsync(outBuffer, 0, encryptedBytes);
                        if (t.IsCompleted)
                        {
                            ArrayPool <byte> .Shared.Return(rentedBuffer);

                            t.GetAwaiter().GetResult();
                        }
                        else
                        {
                            t = t.ContinueWith(s_freeWriteBufferCallback, rentedBuffer, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
                            IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
                            if (!ar.CompletedSynchronously)
                            {
                                return;
                            }
                            TaskToApm.End(ar);
                        }
                    }
                    else
                    {
                        try
                        {
                            _sslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                        }
                        finally
                        {
                            ArrayPool <byte> .Shared.Return(rentedBuffer);
                        }
                    }

                    offset += chunkBytes;
                    count  -= chunkBytes;

                    // Release write IO slot.
                    _sslState.FinishWrite();
                } while (count != 0);
            }

            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser();
            }
        }
Exemple #43
0
        //
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback);
            }

            // We loop to this method from the callback
            // If the last chunk was just completed from async callback (count < 0), we complete user request
            if (count >= 0 )
            {
                byte[] outBuffer = null;
                do
                {
                    // request a write IO slot
                    if (_SslState.CheckEnqueueWrite(asyncRequest))
                    {
                        // operation is async and has been queued, return.
                        return;
                    }

                    int chunkBytes = Math.Min(count, _SslState.MaxDataSize);
                    int encryptedBytes;
                    SecurityStatus errorCode =  _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes);
                    if (errorCode != SecurityStatus.OK)
                    {
                        //
                        ProtocolToken message = new ProtocolToken(null, errorCode);
                        throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException());
                    }

                    if (asyncRequest != null)
                    {
                        // prepare for the next request
                        asyncRequest.SetNextRequest(buffer, offset+chunkBytes, count-chunkBytes, _ResumeAsyncWriteCallback);
                        IAsyncResult ar = _SslState.InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, _WriteCallback, asyncRequest);
                        if (!ar.CompletedSynchronously)
                        {
                            return;
                        }
                        _SslState.InnerStream.EndWrite(ar);

                    }
                    else
                    {
                        _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes);
                    }
                    offset += chunkBytes;
                    count  -= chunkBytes;

                    // release write IO slot
                    _SslState.FinishWrite();

                } while (count != 0);
            }

            if (asyncRequest != null) {
                asyncRequest.CompleteUser();
            }
        }
 private void StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
 {
     if ((message == null) || (message.Size == 0))
     {
         throw exception;
     }
     if (asyncRequest == null)
     {
         this.InnerStream.Write(message.Payload, 0, message.Size);
     }
     else
     {
         asyncRequest.AsyncState = exception;
         IAsyncResult asyncResult = this.InnerStream.BeginWrite(message.Payload, 0, message.Size, _WriteCallback, asyncRequest);
         if (!asyncResult.CompletedSynchronously)
         {
             return;
         }
         this.InnerStream.EndWrite(asyncResult);
     }
     throw exception;
 }
        //
        // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual
        // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones.
        // Returns the same array that is encrypted or a new array of encrypted buffers.
        //
        private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload)
        {

            List<BufferOffsetSize> arrayList = null;
            SecurityStatus status = SecurityStatus.OK;

            foreach(BufferOffsetSize buffer in buffers)
            {
                int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize);

                byte[] outBuffer = null;
                int    outSize;

                status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize);
                if (status != SecurityStatus.OK)
                    break;

                if (chunkBytes != buffer.Size || arrayList != null)
                {
                    if (arrayList == null)
                    {
                        arrayList = new List<BufferOffsetSize>(buffers.Length * (buffer.Size/chunkBytes+1));
                        if (lastHandshakePayload != null)
                            arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false));

                        foreach(BufferOffsetSize oldBuffer in buffers)
                        {
                            if (oldBuffer == buffer)
                                break;
                            arrayList.Add(oldBuffer);
                        }
                    }
                    arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false));
                    while ((buffer.Size-=chunkBytes) != 0)
                    {
                        buffer.Offset += chunkBytes;
                        chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize);
                        outBuffer = null;
                        status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize);
                        if (status != SecurityStatus.OK)
                            break;
                        arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false));
                    }
                }
                else
                {
                    buffer.Buffer = outBuffer;
                    buffer.Offset = 0;
                    buffer.Size   = outSize;
                }
                if (status != SecurityStatus.OK)
                    break;
            }

            if (status != SecurityStatus.OK)
            {
                //
                ProtocolToken message = new ProtocolToken(null, status);
                throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException());
            }

            if (arrayList != null)
                buffers = arrayList.ToArray();
            else if (lastHandshakePayload != null)
            {
                BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length+1];
                Array.Copy(buffers, 0, result, 1, buffers.Length);
                result[0] = new BufferOffsetSize(lastHandshakePayload, false);
                buffers = result;
            }

            return buffers;
        }
Exemple #46
0
        //
        // Only processing SEC_I_RENEGOTIATE.
        //
        private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            ProtocolToken message = new ProtocolToken(null, status);

            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(this) + "::***Processing an error Status = " + message.Status.ToString());
            }

            if (message.Renegotiate)
            {
                _sslState.ReplyOnReAuthentication(extraBuffer);

                // Loop on read.
                return -1;
            }

            if (message.CloseConnection)
            {
                _sslState.FinishRead(null);
                if (asyncRequest != null)
                {
                    asyncRequest.CompleteUser((object)0);
                }

                return 0;
            }

            throw new IOException(SR.net_io_decrypt, message.GetException());
        }
        //
        // Codes we process (Anything else - fail)
        //
        // - SEC_I_RENEGOTIATE
        //
        private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
        {
            // ERROR - examine what kind
            ProtocolToken message = new ProtocolToken(null, errorCode);

            GlobalLog.Print("SecureChannel#" + ValidationHelper.HashString(this) + "::***Processing an error Status = " + message.Status.ToString());

            if (message.Renegotiate)
            {
                _SslState.ReplyOnReAuthentication(extraBuffer);
                // loop on read
                return -1;
            }
            if (message.CloseConnection) {
                _SslState.FinishRead(null);
                if (asyncRequest != null)
                {
                    asyncRequest.CompleteUser((object)0);
                }
                return 0;
            }
            // Otherwise bail out.
            throw new IOException(SR.GetString(SR.net_io_decrypt), message.GetException());
        }
 private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest)
 {
     if (count == 0)
     {
         throw new AuthenticationException(SR.GetString("net_auth_eof"), null);
     }
     if (this._PendingReHandshake)
     {
         int offset = 0;
         SecurityStatus errorCode = this.PrivateDecryptData(buffer, ref offset, ref count);
         if (errorCode == SecurityStatus.OK)
         {
             Exception exception = this.EnqueueOldKeyDecryptedData(buffer, offset, count);
             if (exception != null)
             {
                 this.StartSendAuthResetSignal(null, asyncRequest, exception);
                 return;
             }
             this._Framing = Framing.None;
             this.StartReceiveBlob(buffer, asyncRequest);
             return;
         }
         if (errorCode != SecurityStatus.Renegotiate)
         {
             ProtocolToken token = new ProtocolToken(null, errorCode);
             this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), token.GetException()));
             return;
         }
         this._PendingReHandshake = false;
         if (offset != 0)
         {
             Buffer.BlockCopy(buffer, offset, buffer, 0, count);
         }
     }
     this.StartSendBlob(buffer, count, asyncRequest);
 }
        private async ValueTask <int> ReadAsyncInternal <TReadAdapter>(TReadAdapter adapter, Memory <byte> buffer)
            where TReadAdapter : ISslReadAdapter
        {
            if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(ReadAsync), "read"));
            }

            while (true)
            {
                int copyBytes;
                if (_decryptedBytesCount != 0)
                {
                    copyBytes = CopyDecryptedData(buffer);

                    _sslState.FinishRead(null);
                    _nestedRead = 0;

                    return(copyBytes);
                }

                copyBytes = await adapter.LockAsync(buffer).ConfigureAwait(false);

                try
                {
                    if (copyBytes > 0)
                    {
                        return(copyBytes);
                    }

                    ResetReadBuffer();
                    int readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false);

                    if (readBytes == 0)
                    {
                        return(0);
                    }

                    int payloadBytes = _sslState.GetRemainingFrameSize(_internalBuffer, _internalOffset, readBytes);
                    if (payloadBytes < 0)
                    {
                        throw new IOException(SR.net_frame_read_size);
                    }

                    readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize + payloadBytes).ConfigureAwait(false);

                    if (readBytes < 0)
                    {
                        throw new IOException(SR.net_frame_read_size);
                    }

                    // 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);

                    // 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 (_decryptedBytesCount != 0)
                        {
                            extraBuffer = new byte[_decryptedBytesCount];
                            Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount);

                            _decryptedBytesCount = 0;
                        }

                        ProtocolToken message = new ProtocolToken(null, status);
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(null, $"***Processing an error Status = {message.Status}");
                        }

                        if (message.Renegotiate)
                        {
                            if (!_sslState._sslAuthenticationOptions.AllowRenegotiation)
                            {
                                throw new IOException(SR.net_ssl_io_renego);
                            }

                            _sslState.ReplyOnReAuthentication(extraBuffer);

                            // Loop on read.
                            return(-1);
                        }

                        if (message.CloseConnection)
                        {
                            _sslState.FinishRead(null);
                            return(0);
                        }

                        throw new IOException(SR.net_io_decrypt, message.GetException());
                    }
                }
                catch (Exception e)
                {
                    _sslState.FinishRead(null);

                    if (e is IOException)
                    {
                        throw;
                    }

                    throw new IOException(SR.net_io_read, e);
                }
                finally
                {
                    _nestedRead = 0;
                }
            }
        }
Exemple #50
0
        private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest)
        {
            if (count == 0)
            {
                // EOF received.
                throw new AuthenticationException(SR.net_auth_eof, null);
            }

            if (_pendingReHandshake)
            {
                int offset = 0;
                SecurityStatusPal status = PrivateDecryptData(buffer, ref offset, ref count);

                if (status.ErrorCode == SecurityStatusPalErrorCode.OK)
                {
                    Exception e = EnqueueOldKeyDecryptedData(buffer, offset, count);
                    if (e != null)
                    {
                        StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(e));
                        return;
                    }

                    _Framing = Framing.Unknown;
                    StartReceiveBlob(buffer, asyncRequest);
                    return;
                }
                else if (status.ErrorCode != SecurityStatusPalErrorCode.Renegotiate)
                {
                    // Fail re-handshake.
                    ProtocolToken message = new ProtocolToken(null, status);
                    StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_auth_SSPI, message.GetException())));
                    return;
                }

                // We expect only handshake messages from now.
                _pendingReHandshake = false;
                if (offset != 0)
                {
                    Buffer.BlockCopy(buffer, offset, buffer, 0, count);
                }
            }
            StartSendBlob(buffer, count, asyncRequest);
        }
        private Task WriteSingleChunk <TWriteAdapter>(TWriteAdapter writeAdapter, ReadOnlyMemory <byte> buffer)
            where TWriteAdapter : struct, ISslWriteAdapter
        {
            // Request a write IO slot.
            Task ioSlot = writeAdapter.LockAsync();

            if (!ioSlot.IsCompletedSuccessfully)
            {
                // Operation is async and has been queued, return.
                return(WaitForWriteIOSlot(writeAdapter, ioSlot, buffer));
            }

            byte[] rentedBuffer = ArrayPool <byte> .Shared.Rent(buffer.Length + FrameOverhead);

            byte[] outBuffer = rentedBuffer;

            SecurityStatusPal status = _sslState.EncryptData(buffer, ref outBuffer, out int encryptedBytes);

            if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
            {
                // Re-handshake status is not supported.
                ArrayPool <byte> .Shared.Return(rentedBuffer);

                ProtocolToken message = new ProtocolToken(null, status);
                return(Task.FromException(new IOException(SR.net_io_encrypt, message.GetException())));
            }

            Task t = writeAdapter.WriteAsync(outBuffer, 0, encryptedBytes);

            if (t.IsCompletedSuccessfully)
            {
                ArrayPool <byte> .Shared.Return(rentedBuffer);

                _sslState.FinishWrite();
                return(t);
            }
            else
            {
                return(CompleteAsync(t, rentedBuffer));
            }

            async Task WaitForWriteIOSlot(TWriteAdapter wAdapter, Task lockTask, ReadOnlyMemory <byte> buff)
            {
                await lockTask.ConfigureAwait(false);

                await WriteSingleChunk(wAdapter, buff).ConfigureAwait(false);
            }

            async Task CompleteAsync(Task writeTask, byte[] bufferToReturn)
            {
                try
                {
                    await writeTask.ConfigureAwait(false);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(bufferToReturn);

                    _sslState.FinishWrite();
                }
            }
        }
Exemple #52
0
        //
        // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual
        // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones.
        // Returns the same array that is encrypted or a new array of encrypted buffers.
        //
        private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload)
        {
            List <BufferOffsetSize> arrayList = null;
            SecurityStatus          status    = SecurityStatus.OK;

            foreach (BufferOffsetSize buffer in buffers)
            {
                int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize);

                byte[] outBuffer = null;
                int    outSize;

                status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize);
                if (status != SecurityStatus.OK)
                {
                    break;
                }

                if (chunkBytes != buffer.Size || arrayList != null)
                {
                    if (arrayList == null)
                    {
                        arrayList = new List <BufferOffsetSize>(buffers.Length * (buffer.Size / chunkBytes + 1));
                        if (lastHandshakePayload != null)
                        {
                            arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false));
                        }

                        foreach (BufferOffsetSize oldBuffer in buffers)
                        {
                            if (oldBuffer == buffer)
                            {
                                break;
                            }
                            arrayList.Add(oldBuffer);
                        }
                    }
                    arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false));
                    while ((buffer.Size -= chunkBytes) != 0)
                    {
                        buffer.Offset += chunkBytes;
                        chunkBytes     = Math.Min(buffer.Size, _SslState.MaxDataSize);
                        outBuffer      = null;
                        status         = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize);
                        if (status != SecurityStatus.OK)
                        {
                            break;
                        }
                        arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false));
                    }
                }
                else
                {
                    buffer.Buffer = outBuffer;
                    buffer.Offset = 0;
                    buffer.Size   = outSize;
                }
                if (status != SecurityStatus.OK)
                {
                    break;
                }
            }

            if (status != SecurityStatus.OK)
            {
                //
                ProtocolToken message = new ProtocolToken(null, status);
                throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException());
            }

            if (arrayList != null)
            {
                buffers = arrayList.ToArray();
            }
            else if (lastHandshakePayload != null)
            {
                BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length + 1];
                Array.Copy(buffers, 0, result, 1, buffers.Length);
                result[0] = new BufferOffsetSize(lastHandshakePayload, false);
                buffers   = result;
            }

            return(buffers);
        }
Exemple #53
0
        //
        internal ProtocolToken NextMessage(byte[] incoming, int offset, int count) {
            GlobalLog.Enter("SecureChannel#" + ValidationHelper.HashString(this) + "::NextMessage");
            byte[] nextmsg = null;
            SecurityStatus errorCode = GenerateToken(incoming, offset, count, ref nextmsg);

            if (!m_ServerMode && errorCode == SecurityStatus.CredentialsNeeded)
            {
                GlobalLog.Print("SecureChannel#" + ValidationHelper.HashString(this) + "::NextMessage() returned SecurityStatus.CredentialsNeeded");
                SetRefreshCredentialNeeded();
                errorCode = GenerateToken(incoming, offset, count, ref nextmsg);
            }
            ProtocolToken token = new ProtocolToken(nextmsg, errorCode);
            GlobalLog.Leave("SecureChannel#" + ValidationHelper.HashString(this) + "::NextMessage", token.ToString());
            return token;
        }
Exemple #54
0
        //
        internal ProtocolToken NextMessage(byte[] incoming, int offset, int count)
        {
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Enter("SecureChannel#" + LoggingHash.HashString(this) + "::NextMessage");
            }

            byte[] nextmsg = null;
            SecurityStatusPal status = GenerateToken(incoming, offset, count, ref nextmsg);

            if (!_serverMode && status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(this) + "::NextMessage() returned SecurityStatusPal.CredentialsNeeded");
                }

                SetRefreshCredentialNeeded();
                status = GenerateToken(incoming, offset, count, ref nextmsg);
            }

            ProtocolToken token = new ProtocolToken(nextmsg, status);
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Leave("SecureChannel#" + LoggingHash.HashString(this) + "::NextMessage", token.ToString());
            }
            return token;
        }
 private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
 {
     if (asyncRequest != null)
     {
         asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback);
     }
     if (count >= 0)
     {
         byte[] outBuffer = null;
         do
         {
             int num2;
             if (this._SslState.CheckEnqueueWrite(asyncRequest))
             {
                 return;
             }
             int num = Math.Min(count, this._SslState.MaxDataSize);
             SecurityStatus errorCode = this._SslState.EncryptData(buffer, offset, num, ref outBuffer, out num2);
             if (errorCode != SecurityStatus.OK)
             {
                 ProtocolToken token = new ProtocolToken(null, errorCode);
                 throw new IOException(SR.GetString("net_io_encrypt"), token.GetException());
             }
             if (asyncRequest != null)
             {
                 asyncRequest.SetNextRequest(buffer, offset + num, count - num, _ResumeAsyncWriteCallback);
                 IAsyncResult asyncResult = this._SslState.InnerStream.BeginWrite(outBuffer, 0, num2, _WriteCallback, asyncRequest);
                 if (!asyncResult.CompletedSynchronously)
                 {
                     return;
                 }
                 this._SslState.InnerStream.EndWrite(asyncResult);
             }
             else
             {
                 this._SslState.InnerStream.Write(outBuffer, 0, num2);
             }
             offset += num;
             count -= num;
             this._SslState.FinishWrite();
         }
         while (count != 0);
     }
     if (asyncRequest != null)
     {
         asyncRequest.CompleteUser();
     }
 }