Example #1
0
 //
 //
 internal IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
 {
     BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
     AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult);
     ProcessRead(buffer, offset, count, asyncRequest );
     return bufferResult;
 }
Example #2
0
        //
        // Combined [....]/async read method. For [....] requet asyncRequest==null
        // There is a little overheader because we need to pass buffer/offset/count used only in [....].
        // Still the benefit is that we have a common [....]/async code path.
        //
        private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            ValidateParameters(buffer, offset, count);

            if (Interlocked.Exchange(ref _NestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null? "BeginRead":"Read"), "read"));
            }

            bool failed = false;

            try
            {
                int copyBytes;
                if (InternalBufferCount != 0)
                {
                    copyBytes = InternalBufferCount > count? count: InternalBufferCount;
                    if (copyBytes != 0)
                    {
                        Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes);
                        DecrementInternalBufferCount(copyBytes);
                    }
                    if (asyncRequest != null)
                    {
                        asyncRequest.CompleteUser((object)copyBytes);
                    }
                    return(copyBytes);
                }
                // going into real IO
                return(StartReading(buffer, offset, count, asyncRequest));
            }
            catch (Exception e)
            {
                _SslState.FinishRead(null);
                failed = true;
                if (e is IOException)
                {
                    throw;
                }
                throw new IOException(SR.GetString(SR.net_io_read), e);
            }
            finally
            {
                // if [....] request or exception
                if (asyncRequest == null || failed)
                {
                    _NestedRead = 0;
                }
            }
        }
Example #3
0
 //
 // This is used in a rare situation when async Read is resumed from completed handshake
 //
 private static void ResumeAsyncReadCallback(AsyncProtocolRequest request)
 {
     try {
         ((_SslStream)request.AsyncObject).StartReading(request.Buffer, request.Offset, request.Count, request);
     }
     catch (Exception e) {
         if (request.IsUserCompleted)
         {
             // This will throw on a worker thread.
             throw;
         }
         ((_SslStream)request.AsyncObject)._SslState.FinishRead(null);
         request.CompleteWithError(e);
     }
 }
Example #4
0
        private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int num2;

            this.ValidateParameters(buffer, offset, count);
            if (Interlocked.Exchange(ref this._NestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", new object[] { (asyncRequest != null) ? "BeginRead" : "Read", "read" }));
            }
            bool flag = false;

            try
            {
                if (this.InternalBufferCount != 0)
                {
                    int num = (this.InternalBufferCount > count) ? count : this.InternalBufferCount;
                    if (num != 0)
                    {
                        Buffer.BlockCopy(this.InternalBuffer, this.InternalOffset, buffer, offset, num);
                        this.DecrementInternalBufferCount(num);
                    }
                    if (asyncRequest != null)
                    {
                        asyncRequest.CompleteUser(num);
                    }
                    return(num);
                }
                num2 = this.StartReading(buffer, offset, count, asyncRequest);
            }
            catch (Exception exception)
            {
                this._SslState.FinishRead(null);
                flag = true;
                if (exception is IOException)
                {
                    throw;
                }
                throw new IOException(SR.GetString("net_io_read"), exception);
            }
            finally
            {
                if ((asyncRequest == null) || flag)
                {
                    this._NestedRead = 0;
                }
            }
            return(num2);
        }
Example #5
0
        //
        // Combined sync/async read method. For sync request asyncRequest==null.
        //
        private int ProcessRead(byte[] buffer, int offset, int count, BufferAsyncResult asyncResult)
        {
            ValidateParameters(buffer, offset, count);

            if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncResult != null ? "BeginRead" : "Read"), "read"));
            }

            // If this is an async operation, get the AsyncProtocolRequest to use.
            // We do this only after we verify we're the sole write operation in flight.
            AsyncProtocolRequest asyncRequest = GetOrCreateProtocolRequest(ref _readProtocolRequest, asyncResult);

            bool failed = false;

            try
            {
                if (_decryptedBytesCount != 0)
                {
                    int copyBytes = CopyDecryptedData(buffer, offset, count);

                    asyncRequest?.CompleteUser(copyBytes);

                    return(copyBytes);
                }

                return(StartReading(buffer, offset, count, asyncRequest));
            }
            catch (Exception e)
            {
                _sslState.FinishRead(null);
                failed = true;

                if (e is IOException)
                {
                    throw;
                }

                throw new IOException(SR.net_io_read, e);
            }
            finally
            {
                if (asyncRequest == null || failed)
                {
                    _nestedRead = 0;
                }
            }
        }
        private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            // 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
                {
                    int chunkBytes = Math.Min(count, NegoState.MaxWriteDataSize);
                    int encryptedBytes;

                    try
                    {
                        encryptedBytes = _negoState.EncryptData(buffer, offset, chunkBytes, ref outBuffer);
                    }
                    catch (Exception e)
                    {
                        throw new IOException(SR.net_io_encrypt, e);
                    }

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

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

                    offset += chunkBytes;
                    count  -= chunkBytes;
                } while (count != 0);
            }

            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser();
            }
        }
Example #7
0
        internal void StartReHandshake(AsyncProtocolRequest asyncRequest)
        {
            if (IsServer)
            {
                byte[] buffer = null;
                if (CheckEnqueueHandshakeRead(ref buffer, asyncRequest))
                {
                    return;
                }

                StartReceiveBlob(buffer, asyncRequest);
                return;
            }

            ForceAuthentication(false, null, asyncRequest);
        }
Example #8
0
 private static void CompleteFromCompletedTask(Task <int> task, AsyncProtocolRequest asyncRequest)
 {
     Debug.Assert(task.IsCompleted);
     if (task.IsCompletedSuccessfully)
     {
         asyncRequest.CompleteRequest(task.Result);
     }
     else if (task.IsFaulted)
     {
         asyncRequest.CompleteUserWithError(task.Exception.InnerException);
     }
     else
     {
         asyncRequest.CompleteUserWithError(new OperationCanceledException());
     }
 }
Example #9
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();
     }
 }
Example #10
0
        private static void WriteCallback(IAsyncResult transportResult)
        {
            if (transportResult.CompletedSynchronously)
            {
                return;
            }

            if (!(transportResult.AsyncState is AsyncProtocolRequest))
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Assert("SslStream::WriteCallback | State type is wrong, expected AsyncProtocolRequest.");
                }

                Debug.Fail("SslStream::WriteCallback|State type is wrong, expected AsyncProtocolRequest.");
            }

            AsyncProtocolRequest asyncRequest = (AsyncProtocolRequest)transportResult.AsyncState;

            var sslStream = (SslStreamInternal)asyncRequest.AsyncObject;

            try
            {
                sslStream._sslState.InnerStreamAPM.EndWrite(transportResult);
                sslStream._sslState.FinishWrite();

                if (asyncRequest.Count == 0)
                {
                    // This was the last chunk.
                    asyncRequest.Count = -1;
                }

                sslStream.StartWriting(asyncRequest.Buffer, asyncRequest.Offset, asyncRequest.Count, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                sslStream._sslState.FinishWrite();
                asyncRequest.CompleteWithError(e);
            }
        }
Example #11
0
        private static void PartialFrameCallback(AsyncProtocolRequest asyncRequest)
        {
            SslState asyncObject = (SslState)asyncRequest.AsyncObject;

            try
            {
                asyncObject.StartReadFrame(asyncRequest.Buffer, asyncRequest.Result, asyncRequest);
            }
            catch (Exception exception)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    throw;
                }
                asyncObject.FinishHandshake(exception, asyncRequest);
            }
        }
        //
        // Combined sync/async read method. For sync request asyncRequest==null.
        // There is a little overhead because we need to pass buffer/offset/count used only in sync.
        // Still the benefit is that we have a common sync/async code path.
        //
        private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            ValidateParameters(buffer, offset, count);

            if (Interlocked.Exchange(ref _NestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRead" : "Read"), "read"));
            }

            bool failed = false;

            try
            {
                if (InternalBufferCount != 0)
                {
                    int copyBytes = InternalBufferCount > count ? count : InternalBufferCount;
                    if (copyBytes != 0)
                    {
                        Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes);
                        DecrementInternalBufferCount(copyBytes);
                    }
                    asyncRequest?.CompleteUser(copyBytes);
                    return(copyBytes);
                }

                // Performing actual I/O.
                return(StartReading(buffer, offset, count, asyncRequest));
            }
            catch (Exception e)
            {
                failed = true;
                if (e is IOException)
                {
                    throw;
                }
                throw new IOException(SR.net_io_read, e);
            }
            finally
            {
                if (asyncRequest == null || failed)
                {
                    _NestedRead = 0;
                }
            }
        }
Example #13
0
 private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
 {
     if (this._SslState.LastPayload != null)
     {
         BufferOffsetSize[] buffers = new BufferOffsetSize[] { new BufferOffsetSize(buffer, offset, count, false) };
         if (asyncRequest != null)
         {
             this.ProcessWrite(buffers, new SplitWriteAsyncProtocolRequest(asyncRequest.UserAsyncResult));
         }
         else
         {
             this.ProcessWrite(buffers, null);
         }
     }
     else
     {
         this.ValidateParameters(buffer, offset, count);
         if (Interlocked.Exchange(ref this._NestedWrite, 1) == 1)
         {
             throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", new object[] { (asyncRequest != null) ? "BeginWrite" : "Write", "write" }));
         }
         bool flag = false;
         try
         {
             this.StartWriting(buffer, offset, count, asyncRequest);
         }
         catch (Exception exception)
         {
             this._SslState.FinishWrite();
             flag = true;
             if (exception is IOException)
             {
                 throw;
             }
             throw new IOException(SR.GetString("net_io_write"), exception);
         }
         finally
         {
             if ((asyncRequest == null) || flag)
             {
                 this._NestedWrite = 0;
             }
         }
     }
 }
Example #14
0
 private void FinishHandshake(Exception e, AsyncProtocolRequest asyncRequest)
 {
     try
     {
         lock (this)
         {
             if (e != null)
             {
                 this.SetException(e);
             }
             this.FinishHandshakeRead(0);
             if (Interlocked.CompareExchange(ref this._LockWriteState, 0, 2) == 3)
             {
                 this._LockWriteState = 1;
                 object state = this._QueuedWriteStateRequest;
                 if (state != null)
                 {
                     this._QueuedWriteStateRequest = null;
                     if (state is LazyAsyncResult)
                     {
                         ((LazyAsyncResult)state).InvokeCallback();
                     }
                     else
                     {
                         ThreadPool.QueueUserWorkItem(new WaitCallback(this.CompleteRequestWaitCallback), state);
                     }
                 }
             }
         }
     }
     finally
     {
         if (asyncRequest != null)
         {
             if (e != null)
             {
                 asyncRequest.CompleteWithError(e);
             }
             else
             {
                 asyncRequest.CompleteUser();
             }
         }
     }
 }
Example #15
0
        internal void ReplyOnReAuthentication(byte[] buffer)
        {
            lock (this)
            {
                this._LockReadState = 2;
                if (this._PendingReHandshake)
                {
                    this.FinishRead(buffer);
                    return;
                }
            }
            AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(new LazyAsyncResult(this, null, new AsyncCallback(this.RehandshakeCompleteCallback)))
            {
                Buffer = buffer
            };

            this.ForceAuthentication(false, buffer, asyncRequest);
        }
Example #16
0
        //
        // This is used in a rare situation when async Write is resumed from completed handshake.
        //
        private static void ResumeAsyncWriteCallback(AsyncProtocolRequest asyncRequest)
        {
            try
            {
                ((SslStreamInternal)asyncRequest.AsyncObject).StartWriting(asyncRequest.Buffer, asyncRequest.Offset, asyncRequest.Count, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                ((SslStreamInternal)asyncRequest.AsyncObject)._sslState.FinishWrite();
                asyncRequest.CompleteUserWithError(e);
            }
        }
Example #17
0
        //
        // To avoid recursion when decrypted 0 bytes this method will loop until a decrypted result at least 1 byte.
        //
        private int StartReading(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int result = 0;

            if (InternalBufferCount != 0)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.AssertFormat("SslStream::StartReading()|Previous frame was not consumed. InternalBufferCount:{0}", InternalBufferCount);
                }

                Debug.Fail("SslStream::StartReading()|Previous frame was not consumed. InternalBufferCount:" + InternalBufferCount);
            }

            do
            {
                if (asyncRequest != null)
                {
                    asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncReadCallback);
                }

                int copyBytes = _sslState.CheckEnqueueRead(buffer, offset, count, asyncRequest);
                if (copyBytes == 0)
                {
                    // Queued but not completed!
                    return(0);
                }

                if (copyBytes != -1)
                {
                    if (asyncRequest != null)
                    {
                        asyncRequest.CompleteUser((object)copyBytes);
                    }

                    return(copyBytes);
                }
            }
            // When we read -1 bytes means we have decrypted 0 bytes or rehandshaking, need looping.
            while ((result = StartFrameHeader(buffer, offset, count, asyncRequest)) == -1);

            return(result);
        }
Example #18
0
        //
        // Need read frame size first
        //
        private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int readBytes = 0;

            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(_ReadHeader, 0, _ReadHeader.Length, _ReadCallback);
                _FrameReader.AsyncReadPacket(asyncRequest);
                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return(0);
                }
                readBytes = asyncRequest.Result;
            }
            else
            {
                readBytes = _FrameReader.ReadPacket(_ReadHeader, 0, _ReadHeader.Length);
            }
            return(StartFrameBody(readBytes, buffer, offset, count, asyncRequest));
        }
Example #19
0
 private static void ReadHeaderCallback(AsyncProtocolRequest asyncRequest)
 {
     try
     {
         _SslStream        asyncObject     = (_SslStream)asyncRequest.AsyncObject;
         BufferAsyncResult userAsyncResult = (BufferAsyncResult)asyncRequest.UserAsyncResult;
         if (-1 == asyncObject.StartFrameBody(asyncRequest.Result, userAsyncResult.Buffer, userAsyncResult.Offset, userAsyncResult.Count, asyncRequest))
         {
             asyncObject.StartReading(userAsyncResult.Buffer, userAsyncResult.Offset, userAsyncResult.Count, asyncRequest);
         }
     }
     catch (Exception exception)
     {
         if (asyncRequest.IsUserCompleted)
         {
             throw;
         }
         asyncRequest.CompleteWithError(exception);
     }
 }
Example #20
0
        private static void WriteCallback(IAsyncResult transportResult)
        {
            if (transportResult.CompletedSynchronously)
            {
                return;
            }

            if (!(transportResult.AsyncState is AsyncProtocolRequest))
            {
                NetEventSource.Fail(transportResult, "State type is wrong, expected AsyncProtocolRequest.");
            }

            AsyncProtocolRequest asyncRequest = (AsyncProtocolRequest)transportResult.AsyncState;

            var sslStream = (SslStreamInternal)asyncRequest.AsyncObject;

            try
            {
                TaskToApm.End(transportResult);
                sslStream._sslState.FinishWrite();

                if (asyncRequest.Count == 0)
                {
                    // This was the last chunk.
                    asyncRequest.Count = -1;
                }

                sslStream.StartWriting(asyncRequest.Buffer, asyncRequest.Offset, asyncRequest.Count, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                sslStream._sslState.FinishWrite();
                asyncRequest.CompleteUserWithError(e);
            }
        }
Example #21
0
        private void StartReadFrame(byte[] buffer, int readBytes, AsyncProtocolRequest asyncRequest)
        {
            if (readBytes == 0)
            {
                throw new IOException(SR.GetString("net_auth_eof"));
            }
            if (this._Framing == Framing.None)
            {
                this._Framing = this.DetectFraming(buffer, readBytes);
            }
            int remainingFrameSize = this.GetRemainingFrameSize(buffer, readBytes);

            if (remainingFrameSize < 0)
            {
                throw new IOException(SR.GetString("net_ssl_io_frame"));
            }
            if (remainingFrameSize == 0)
            {
                throw new AuthenticationException(SR.GetString("net_auth_eof"), null);
            }
            buffer = EnsureBufferSize(buffer, readBytes, readBytes + remainingFrameSize);
            if (asyncRequest == null)
            {
                remainingFrameSize = this._Reader.ReadPacket(buffer, readBytes, remainingFrameSize);
            }
            else
            {
                asyncRequest.SetNextRequest(buffer, readBytes, remainingFrameSize, _ReadFrameCallback);
                this._Reader.AsyncReadPacket(asyncRequest);
                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return;
                }
                remainingFrameSize = asyncRequest.Result;
                if (remainingFrameSize == 0)
                {
                    readBytes = 0;
                }
            }
            this.ProcessReceivedBlob(buffer, readBytes + remainingFrameSize, asyncRequest);
        }
Example #22
0
        private static void ReadFrameCallback(AsyncProtocolRequest asyncRequest)
        {
            SslState asyncObject = (SslState)asyncRequest.AsyncObject;

            try
            {
                if (asyncRequest.Result == 0)
                {
                    asyncRequest.Offset = 0;
                }
                asyncObject.ProcessReceivedBlob(asyncRequest.Buffer, asyncRequest.Offset + asyncRequest.Result, asyncRequest);
            }
            catch (Exception exception)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    throw;
                }
                asyncObject.FinishHandshake(exception, asyncRequest);
            }
        }
Example #23
0
        private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int readBytes = 0;

            this.EnsureInternalBufferSize(0, this._SslState.HeaderSize);
            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(this.InternalBuffer, 0, this._SslState.HeaderSize, _ReadHeaderCallback);
                this._Reader.AsyncReadPacket(asyncRequest);
                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return(0);
                }
                readBytes = asyncRequest.Result;
            }
            else
            {
                readBytes = this._Reader.ReadPacket(this.InternalBuffer, 0, this._SslState.HeaderSize);
            }
            return(this.StartFrameBody(readBytes, buffer, offset, count, asyncRequest));
        }
Example #24
0
        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
        {
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) {
#endif
            _NegoState.CheckThrow(true);

            if (!_NegoState.CanGetSecureStream)
            {
                return(InnerStream.BeginRead(buffer, offset, count, asyncCallback, asyncState));
            }

            BufferAsyncResult bufferResult    = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
            AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult);
            ProcessRead(buffer, offset, count, asyncRequest);
            return(bufferResult);

#if DEBUG
        }
#endif
        }
Example #25
0
        private AsyncProtocolRequest GetOrCreateProtocolRequest(ref AsyncProtocolRequest aprField, LazyAsyncResult asyncResult)
        {
            AsyncProtocolRequest request = null;

            if (asyncResult != null)
            {
                // SslStreamInternal supports only a single read and a single write operation at a time.
                // As such, we can cache and reuse the AsyncProtocolRequest object that's used throughout
                // the implementation.
                request = aprField;
                if (request != null)
                {
                    request.Reset(asyncResult);
                }
                else
                {
                    aprField = request = new AsyncProtocolRequest(asyncResult);
                }
            }
            return(request);
        }
Example #26
0
        //
        // Sync write method.
        //
        private void ProcessWrite(byte[] buffer, int offset, int count, LazyAsyncResult asyncResult)
        {
            _sslState.CheckThrow(authSuccessCheck: true, shutdownCheck: true);
            ValidateParameters(buffer, offset, count);

            if (Interlocked.Exchange(ref _nestedWrite, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, "Write", "write"));
            }

            // If this is an async operation, get the AsyncProtocolRequest to use.
            // We do this only after we verify we're the sole write operation in flight.
            AsyncProtocolRequest asyncRequest = GetOrCreateProtocolRequest(ref _writeProtocolRequest, asyncResult);

            bool failed = false;

            try
            {
                StartWriting(buffer, offset, count, asyncRequest);
            }
            catch (Exception e)
            {
                _sslState.FinishWrite();

                failed = true;
                if (e is IOException)
                {
                    throw;
                }

                throw new IOException(SR.net_io_write, e);
            }
            finally
            {
                if (asyncRequest == null || failed)
                {
                    _nestedWrite = 0;
                }
            }
        }
 private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
 {
     if (count >= 0)
     {
         byte[] outBuffer = null;
         do
         {
             int num2;
             int num = Math.Min(count, 0xfc00);
             try
             {
                 num2 = this._NegoState.EncryptData(buffer, offset, num, ref outBuffer);
             }
             catch (Exception exception)
             {
                 throw new IOException(SR.GetString("net_io_encrypt"), exception);
             }
             if (asyncRequest != null)
             {
                 asyncRequest.SetNextRequest(buffer, offset + num, count - num, null);
                 IAsyncResult asyncResult = base.InnerStream.BeginWrite(outBuffer, 0, num2, _WriteCallback, asyncRequest);
                 if (!asyncResult.CompletedSynchronously)
                 {
                     return;
                 }
                 base.InnerStream.EndWrite(asyncResult);
             }
             else
             {
                 base.InnerStream.Write(outBuffer, 0, num2);
             }
             offset += num;
             count  -= num;
         }while (count != 0);
     }
     if (asyncRequest != null)
     {
         asyncRequest.CompleteUser();
     }
 }
Example #28
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;
 }
Example #29
0
 internal void FinishRead(byte[] renegotiateBuffer)
 {
     if (Interlocked.CompareExchange(ref this._LockReadState, 0, 4) == 2)
     {
         lock (this)
         {
             LazyAsyncResult result = this._QueuedReadStateRequest as LazyAsyncResult;
             if (result != null)
             {
                 this._QueuedReadStateRequest = null;
                 result.InvokeCallback(renegotiateBuffer);
             }
             else
             {
                 AsyncProtocolRequest state = (AsyncProtocolRequest)this._QueuedReadStateRequest;
                 state.Buffer = renegotiateBuffer;
                 this._QueuedReadStateRequest = null;
                 ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncResumeHandshakeRead), state);
             }
         }
     }
 }
Example #30
0
        //
        // To avoid recursion when decrypted 0 bytes this method will loop until a decrypted result at least 1 byte.
        //
        private int StartReading(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int result = 0;

            if (InternalBufferCount != 0)
            {
                NetEventSource.Fail(this, $"Previous frame was not consumed. InternalBufferCount: {InternalBufferCount}");
            }

            do
            {
                if (asyncRequest != null)
                {
                    asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncReadCallback);
                }

                int copyBytes = _sslState.CheckEnqueueRead(buffer, offset, count, asyncRequest);
                if (copyBytes == 0)
                {
                    // Queued but not completed!
                    return(0);
                }

                if (copyBytes != -1)
                {
                    if (asyncRequest != null)
                    {
                        asyncRequest.CompleteUser((object)copyBytes);
                    }

                    return(copyBytes);
                }
            }
            // When we read -1 bytes means we have decrypted 0 bytes or rehandshaking, need looping.
            while ((result = StartFrameHeader(buffer, offset, count, asyncRequest)) == -1);

            return(result);
        }
Example #31
0
 //
 //
 private static void ReadFrameCallback(AsyncProtocolRequest asyncRequest)
 {
     // Async ONLY completion
     try
     {
         _SslStream        sslStream    = (_SslStream)asyncRequest.AsyncObject;
         BufferAsyncResult bufferResult = (BufferAsyncResult)asyncRequest.UserAsyncResult;
         if (-1 == sslStream.ProcessFrameBody(asyncRequest.Result, bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest))
         {
             // in case we decrypted 0 bytes start another reading.
             sslStream.StartReading(bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest);
         }
     }
     catch (Exception e)
     {
         if (asyncRequest.IsUserCompleted)
         {
             // This will throw on a worker thread.
             throw;
         }
         asyncRequest.CompleteWithError(e);
     }
 }
Example #32
0
        // Returns:
        // true  - operation queued
        // false - operation can proceed
        private bool CheckEnqueueHandshake(byte[] buffer, AsyncProtocolRequest asyncRequest)
        {
            LazyAsyncResult lazyResult = null;

            lock (this)
            {
                if (_lockWriteState == LockPendingWrite)
                {
                    return false;
                }

                int lockState = Interlocked.Exchange(ref _lockWriteState, LockHandshake);
                if (lockState != LockWrite)
                {
                    // Proceed with handshake.
                    return false;
                }

                if (asyncRequest != null)
                {
                    asyncRequest.Buffer = buffer;
                    _queuedWriteStateRequest = asyncRequest;
                    return true;
                }

                lazyResult = new LazyAsyncResult(null, null, /*must be*/null);
                _queuedWriteStateRequest = lazyResult;
            }
            lazyResult.InternalWaitForCompletion();
            return false;
        }
Example #33
0
        // Returns: 
        // true  - operation queued
        // false - operation can proceed
        internal bool CheckEnqueueWrite(AsyncProtocolRequest asyncRequest)
        {
            // Clear previous request.
            _queuedWriteStateRequest = null;
            int lockState = Interlocked.CompareExchange(ref _lockWriteState, LockWrite, LockNone);
            if (lockState != LockHandshake)
            {
                // Proceed with write.
                return false;
            }

            LazyAsyncResult lazyResult = null;
            lock (this)
            {
                if (_lockWriteState != LockHandshake)
                {
                    // Handshake has completed before we grabbed the lock.
                    CheckThrow(true);
                    return false;
                }

                _lockWriteState = LockPendingWrite;

                // Still pending, wait or enqueue.
                if (asyncRequest != null)
                {
                    _queuedWriteStateRequest = asyncRequest;
                    return true;
                }

                lazyResult = new LazyAsyncResult(null, null, /*must be */null);
                _queuedWriteStateRequest = lazyResult;
            }

            // Need to exit from lock before waiting.
            lazyResult.InternalWaitForCompletion();
            CheckThrow(true);
            return false;
        }
Example #34
0
        // Returns:
        // -1    - proceed
        // 0     - queued
        // X     - some bytes are ready, no need for IO
        internal int CheckEnqueueRead(byte[] buffer, int offset, int count, AsyncProtocolRequest request)
        {
            int lockState = Interlocked.CompareExchange(ref _lockReadState, LockRead, LockNone);

            if (lockState != LockHandshake)
            {
                // Proceed, no concurrent handshake is ongoing so no need for a lock.
                return CheckOldKeyDecryptedData(buffer, offset, count);
            }

            LazyAsyncResult lazyResult = null;
            lock (this)
            {
                int result = CheckOldKeyDecryptedData(buffer, offset, count);
                if (result != -1)
                {
                    return result;
                }

                // Check again under lock.
                if (_lockReadState != LockHandshake)
                {
                    // The other thread has finished before we grabbed the lock.
                    _lockReadState = LockRead;
                    return -1;
                }

                _lockReadState = LockPendingRead;

                if (request != null)
                {
                    // Request queued.
                    _queuedReadStateRequest = request;
                    return 0;
                }
                lazyResult = new LazyAsyncResult(null, null, /*must be */ null);
                _queuedReadStateRequest = lazyResult;
            }
            // Need to exit from lock before waiting.
            lazyResult.InternalWaitForCompletion();
            lock (this)
            {
                return CheckOldKeyDecryptedData(buffer, offset, count);
            }
        }
Example #35
0
        private bool CheckEnqueueHandshakeRead(ref byte[] buffer, AsyncProtocolRequest request)
        {
            LazyAsyncResult lazyResult = null;
            lock (this)
            {
                if (_lockReadState == LockPendingRead)
                {
                    return false;
                }

                int lockState = Interlocked.Exchange(ref _lockReadState, LockHandshake);
                if (lockState != LockRead)
                {
                    return false;
                }

                if (request != null)
                {
                    _queuedReadStateRequest = request;
                    return true;
                }

                lazyResult = new LazyAsyncResult(null, null, /*must be */ null);
                _queuedReadStateRequest = lazyResult;
            }

            // Need to exit from lock before waiting.
            lazyResult.InternalWaitForCompletion();
            buffer = (byte[])lazyResult.Result;
            return false;
        }
Example #36
0
        //
        //
        private static void ReadFrameCallback(AsyncProtocolRequest asyncRequest)
        {
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Print("SslState::ReadFrameCallback()");
            }

            // Async ONLY completion.
            SslState sslState = (SslState)asyncRequest.AsyncObject;
            try
            {
                if (asyncRequest.Result == 0)
                {
                    //EOF received: will fail.
                    asyncRequest.Offset = 0;
                }

                sslState.ProcessReceivedBlob(asyncRequest.Buffer, asyncRequest.Offset + asyncRequest.Result, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                sslState.FinishHandshake(e, asyncRequest);
            }
        }
Example #37
0
        private static void PartialFrameCallback(AsyncProtocolRequest asyncRequest)
        {
            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Print("SslState::PartialFrameCallback()");
            }

            // Async ONLY completion.
            SslState sslState = (SslState)asyncRequest.AsyncObject;
            try
            {
                sslState.StartReadFrame(asyncRequest.Buffer, asyncRequest.Result, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                sslState.FinishHandshake(e, asyncRequest);
            }
        }
Example #38
0
        //
        // Client side starts here, but server also loops through this method.
        //
        private void StartSendBlob(byte[] incoming, int count, AsyncProtocolRequest asyncRequest)
        {
            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);
                }

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

                    InnerStreamAPM.EndWrite(ar);
                }
            }

            CheckCompletionBeforeNextReceive(message, asyncRequest);
        }
Example #39
0
        //
        // This is used to reply on re-handshake when received SEC_I_RENEGOTIATE on Read().
        //
        internal void ReplyOnReAuthentication(byte[] buffer)
        {
            lock (this)
            {
                // Note we are already inside the read, so checking for already going concurrent handshake.
                _lockReadState = LockHandshake;

                if (_pendingReHandshake)
                {
                    // A concurrent handshake is pending, resume.
                    FinishRead(buffer);
                    return;
                }
            }

            // Start rehandshake from here.

            // Forcing async mode.  The caller will queue another Read as soon as we return using its preferred
            // calling convention, which will be woken up when the handshake completes.  The callback is just
            // to capture any SocketErrors that happen during the handshake so they can be surfaced from the Read.
            AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(new LazyAsyncResult(this, null, new AsyncCallback(RehandshakeCompleteCallback)));
            // Buffer contains a result from DecryptMessage that will be passed to ISC/ASC
            asyncRequest.Buffer = buffer;
            ForceAuthentication(false, buffer, asyncRequest);
        }
Example #40
0
        //
        // Combined sync/async read method. For sync requet asyncRequest==null.
        //
        private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            ValidateParameters(buffer, offset, count);

            if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncRequest!=null? "BeginRead":"Read"), "read"));
            }

            bool failed = false;

            try
            {
                int copyBytes;
                if (InternalBufferCount != 0)
                {
                    copyBytes = InternalBufferCount > count ? count : InternalBufferCount;
                    if (copyBytes != 0)
                    {
                        Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes);
                        SkipBytes(copyBytes);
                    }
                    
                    if (asyncRequest != null) {
                        asyncRequest.CompleteUser((object) copyBytes);
                    }
                    
                    return copyBytes;
                }

                return StartReading(buffer, offset, count, asyncRequest);
            }
            catch (Exception e)
            {
                _sslState.FinishRead(null);
                failed = true;

                if (e is IOException)
                {
                    throw;
                }

                throw new IOException(SR.net_io_read, e);
            }
            finally
            {
                if (asyncRequest == null || failed)
                {
                    _nestedRead = 0;
                }
            }
        }
Example #41
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());
                }
            }
        }
Example #42
0
		internal void StartReHandshake (AsyncProtocolRequest asyncRequest)
		{
			if (IsServer) {
				byte[] buffer = null;
				if (CheckEnqueueHandshakeRead (ref buffer, asyncRequest))
					return;

				StartReceiveBlob (buffer, asyncRequest);
				return;
			}

			ForceAuthentication (false, null, asyncRequest);
		}
Example #43
0
        //
        // To avoid recursion when decrypted 0 bytes this method will loop until a decrypted result at least 1 byte.
        //
        private int StartReading(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int result = 0;

            if (InternalBufferCount != 0)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.AssertFormat("SslStream::StartReading()|Previous frame was not consumed. InternalBufferCount:{0}", InternalBufferCount);
                }

                Debug.Fail("SslStream::StartReading()|Previous frame was not consumed. InternalBufferCount:" + InternalBufferCount);
            }

            do
            {
                if (asyncRequest != null)
                {
                    asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncReadCallback);
                }

                int copyBytes = _sslState.CheckEnqueueRead(buffer, offset, count, asyncRequest);
                if (copyBytes == 0)
                {
                    // Queued but not completed!
                    return 0;
                }

                if (copyBytes != -1)
                {
                    if (asyncRequest != null)
                    {
                        asyncRequest.CompleteUser((object)copyBytes);
                    }

                    return copyBytes;
                }
            }

            // When we read -1 bytes means we have decrypted 0 bytes or rehandshaking, need looping.
            while ((result = StartFrameHeader(buffer, offset, count, asyncRequest)) == -1);

            return result;
        }
Example #44
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);
        }
Example #45
0
        //
        // Server side starts here, but client also loops through this method.
        //
        private void StartReceiveBlob(byte[] buffer, AsyncProtocolRequest asyncRequest)
        {
            if (_pendingReHandshake)
            {
                if (CheckEnqueueHandshakeRead(ref buffer, asyncRequest))
                {
                    return;
                }

                if (!_pendingReHandshake)
                {
                    // Renegotiate: proceed to the next step.
                    ProcessReceivedBlob(buffer, buffer.Length, asyncRequest);
                    return;
                }
            }

            //This is first server read.
            buffer = EnsureBufferSize(buffer, 0, SecureChannel.ReadHeaderSize);

            int readBytes = 0;
            if (asyncRequest == null)
            {
                readBytes = _reader.ReadPacket(buffer, 0, SecureChannel.ReadHeaderSize);
            }
            else
            {
                asyncRequest.SetNextRequest(buffer, 0, SecureChannel.ReadHeaderSize, s_partialFrameCallback);
                _reader.AsyncReadPacket(asyncRequest);
                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return;
                }

                readBytes = asyncRequest.Result;
            }

            StartReadFrame(buffer, readBytes, asyncRequest);
        }
Example #46
0
        private void FinishHandshake(Exception e, AsyncProtocolRequest asyncRequest)
        {
            try
            {
                lock (this)
                {
                    if (e != null)
                    {
                        SetException(e);
                    }

                    // Release read if any.
                    FinishHandshakeRead(LockNone);

                    // If there is a pending write we want to keep it's lock state.
                    int lockState = Interlocked.CompareExchange(ref _lockWriteState, LockNone, LockHandshake);
                    if (lockState != LockPendingWrite)
                    {
                        return;
                    }

                    _lockWriteState = LockWrite;
                    object obj = _queuedWriteStateRequest;
                    if (obj == null)
                    {
                        // We finished before Write has grabbed the lock.
                        return;
                    }

                    _queuedWriteStateRequest = null;

                    if (obj is LazyAsyncResult)
                    {
                        // Sync write is waiting on other thread.
                        ((LazyAsyncResult)obj).InvokeCallback();
                    }
                    else
                    {
                        // Async write is pending, start it on other thread.
                        // Consider: we could start it in on this thread but that will delay THIS handshake completion
                        ThreadPool.QueueUserWorkItem(new WaitCallback(CompleteRequestWaitCallback), obj);
                    }
                }
            }
            finally
            {
                if (asyncRequest != null)
                {
                    if (e != null)
                    {
                        asyncRequest.CompleteWithError(e);
                    }
                    else
                    {
                        asyncRequest.CompleteUser();
                    }
                }
            }
        }
Example #47
0
        //
        // This method assumes that a SSPI context is already in a good shape.
        // For example it is either a fresh context or already authenticated context that needs renegotiation.
        //
        internal void ProcessAuthentication(LazyAsyncResult lazyResult)
        {
            if (Interlocked.Exchange(ref _nestedAuth, 1) == 1)
            {
                throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, lazyResult == null ? "BeginAuthenticate" : "Authenticate", "authenticate"));
            }

            try
            {
                CheckThrow(false);
                AsyncProtocolRequest asyncRequest = null;
                if (lazyResult != null)
                {
                    asyncRequest = new AsyncProtocolRequest(lazyResult);
                    asyncRequest.Buffer = null;
#if DEBUG
                    lazyResult._debugAsyncChain = asyncRequest;
#endif
                }

                //  A trick to discover and avoid cached sessions.
                _CachedSession = CachedSessionStatus.Unknown;

                ForceAuthentication(Context.IsServer, null, asyncRequest);

                // Not aync so the connection is completed at this point.
                if (lazyResult == null && SecurityEventSource.Log.IsEnabled())
                {
                    SecurityEventSource.Log.SspiSelectedCipherSuite("ProcessAuthentication",
                        SslProtocol,
                        CipherAlgorithm,
                        CipherStrength,
                        HashAlgorithm,
                        HashStrength,
                        KeyExchangeAlgorithm,
                        KeyExchangeStrength);
                }
            }
            catch (Exception)
            {
                // If an exception emerges synchronously, the asynchronous operation was not
                // initiated, so no operation is in progress.
                _nestedAuth = 0;
                throw;
            }
            finally
            {
                // For synchronous operations, the operation has completed.
                if (lazyResult == null)
                {
                    _nestedAuth = 0;
                }
            }
        }
Example #48
0
        private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            int readBytes = 0;

            //
            // Always pass InternalBuffer for SSPI "in place" decryption.
            // A user buffer can be shared by many threads in that case decryption/integrity check may fail cause of data corruption.
            //

            // Reset internal buffer for a new frame.
            EnsureInternalBufferSize(0, SecureChannel.ReadHeaderSize);

            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(InternalBuffer, 0, SecureChannel.ReadHeaderSize, s_readHeaderCallback);
                _reader.AsyncReadPacket(asyncRequest);

                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return 0;
                }

                readBytes = asyncRequest.Result;
            }
            else
            {
                readBytes = _reader.ReadPacket(InternalBuffer, 0, SecureChannel.ReadHeaderSize);
            }

            return StartFrameBody(readBytes, buffer, offset, count, asyncRequest);
        }
Example #49
0
        //
        // This method attempts to start authentication.
        // Incoming buffer is either null or is the result of "renegotiate" decrypted message
        // If write is in progress the method will either wait or be put on hold
        //
        private void ForceAuthentication(bool receiveFirst, byte[] buffer, AsyncProtocolRequest asyncRequest)
        {
            if (CheckEnqueueHandshake(buffer, asyncRequest))
            {
                // Async handshake is enqueued and will resume later.
                return;
            }
            // Either Sync handshake is ready to go or async handshake won the race over write.

            // This will tell that we don't know the framing yet (what SSL version is)
            _Framing = Framing.Unknown;

            try
            {
                if (receiveFirst)
                {
                    // Listen for a client blob.
                    StartReceiveBlob(buffer, asyncRequest);
                }
                else
                {
                    // We start with the first blob.
                    StartSendBlob(buffer, (buffer == null ? 0 : buffer.Length), asyncRequest);
                }
            }
            catch (Exception e)
            {
                // Failed auth, reset the framing if any.
                _Framing = Framing.Unknown;
                _handshakeCompleted = false;

                if (SetException(e).SourceException == e)
                {
                    throw;
                }
                else
                {
                    _exception.Throw();
                }
            }
            finally
            {
                if (_exception != null)
                {
                    // This a failed handshake. Release waiting IO if any.
                    FinishHandshake(null, null);
                }
            }
        }
Example #50
0
        private int StartFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (readBytes == 0)
            {
                //EOF : Reset the buffer as we did not read anything into it.
                SkipBytes(InternalBufferCount);
                if (asyncRequest != null)
                {
                    asyncRequest.CompleteUser((object)0);
                }
                
                return 0;
            }

            // Now readBytes is a payload size.
            readBytes = _sslState.GetRemainingFrameSize(InternalBuffer, readBytes);

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

            EnsureInternalBufferSize(SecureChannel.ReadHeaderSize, readBytes);

            if (asyncRequest != null)
            {
                asyncRequest.SetNextRequest(InternalBuffer, SecureChannel.ReadHeaderSize, readBytes, s_readFrameCallback);

                _reader.AsyncReadPacket(asyncRequest);

                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return 0;
                }
                
                readBytes = asyncRequest.Result;
            }
            else
            {
                readBytes = _reader.ReadPacket(InternalBuffer, SecureChannel.ReadHeaderSize, readBytes);
            }
            
            return ProcessFrameBody(readBytes, buffer, offset, count, asyncRequest);
        }
Example #51
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);
        }
Example #52
0
        //
        // This is used in a rare situation when async Write is resumed from completed handshake.
        //
        private static void ResumeAsyncWriteCallback(AsyncProtocolRequest asyncRequest)
        {
            try
            {
                ((SslStreamInternal)asyncRequest.AsyncObject).StartWriting(asyncRequest.Buffer, asyncRequest.Offset, asyncRequest.Count, asyncRequest);
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                ((SslStreamInternal)asyncRequest.AsyncObject)._sslState.FinishWrite();
                asyncRequest.CompleteWithError(e);
            }
        }
Example #53
0
        //
        private void StartReadFrame(byte[] buffer, int readBytes, AsyncProtocolRequest asyncRequest)
        {
            if (readBytes == 0)
            {
                // EOF received
                throw new IOException(SR.net_auth_eof);
            }

            if (_Framing == Framing.Unknown)
            {
                _Framing = DetectFraming(buffer, readBytes);
            }

            int restBytes = GetRemainingFrameSize(buffer, readBytes);

            if (restBytes < 0)
            {
                throw new IOException(SR.net_ssl_io_frame);
            }

            if (restBytes == 0)
            {
                // EOF received
                throw new AuthenticationException(SR.net_auth_eof, null);
            }

            buffer = EnsureBufferSize(buffer, readBytes, readBytes + restBytes);

            if (asyncRequest == null)
            {
                restBytes = _reader.ReadPacket(buffer, readBytes, restBytes);
            }
            else
            {
                asyncRequest.SetNextRequest(buffer, readBytes, restBytes, s_readFrameCallback);
                _reader.AsyncReadPacket(asyncRequest);
                if (!asyncRequest.MustCompleteSynchronously)
                {
                    return;
                }

                restBytes = asyncRequest.Result;
                if (restBytes == 0)
                {
                    //EOF received: fail.
                    readBytes = 0;
                }
            }
            ProcessReceivedBlob(buffer, readBytes + restBytes, asyncRequest);
        }
Example #54
0
        private static void ReadFrameCallback(AsyncProtocolRequest asyncRequest)
        {
            try
            {
                SslStreamInternal sslStream = (SslStreamInternal)asyncRequest.AsyncObject;
                BufferAsyncResult bufferResult = (BufferAsyncResult)asyncRequest.UserAsyncResult;
                if (-1 == sslStream.ProcessFrameBody(asyncRequest.Result, bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest))
                {
                    // in case we decrypted 0 bytes start another reading.
                    sslStream.StartReading(bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest);
                }
            }
            catch (Exception e)
            {
                if (asyncRequest.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                asyncRequest.CompleteWithError(e);
            }
        }
Example #55
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();
        }
Example #56
0
		internal bool CheckEnqueueHandshakeWrite (byte[] buffer, AsyncProtocolRequest asyncRequest)
		{
			return CheckEnqueueHandshake (buffer, asyncRequest);
		}
Example #57
0
        //
        // readBytes == SSL Data Payload size on input or 0 on EOF.
        //
        private int ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
        {
            if (readBytes == 0)
            {
                // EOF
                throw new IOException(SR.net_io_eof);
            }

            // Set readBytes to total number of received bytes.
            readBytes += SecureChannel.ReadHeaderSize;

            // Decrypt into internal buffer, change "readBytes" to count now _Decrypted Bytes_.
            int data_offset = 0;

            SecurityStatusPal status = _sslState.DecryptData(InternalBuffer, ref data_offset, ref readBytes);

            if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
            {
                byte[] extraBuffer = null;
                if (readBytes != 0)
                {
                    extraBuffer = new byte[readBytes];
                    Buffer.BlockCopy(InternalBuffer, data_offset, extraBuffer, 0, readBytes);
                }

                // Reset internal buffer count.
                SkipBytes(InternalBufferCount);
                return ProcessReadErrorCode(status, buffer, offset, count, asyncRequest, extraBuffer);
            }


            if (readBytes == 0 && count != 0)
            {
                // Read again since remote side has sent encrypted 0 bytes.
                SkipBytes(InternalBufferCount);
                return -1;
            }

            // Decrypted data start from "data_offset" offset, the total count can be shrunk after decryption.
            EnsureInternalBufferSize(0, data_offset + readBytes);
            SkipBytes(data_offset);

            if (readBytes > count)
            {
                readBytes = count;
            }

            Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, readBytes);

            // This will adjust both the remaining internal buffer count and the offset.
            SkipBytes(readBytes);

            _sslState.FinishRead(null);
            if (asyncRequest != null)
            {
                asyncRequest.CompleteUser((object)readBytes);
            }

            return readBytes;
        }
Example #58
0
        //
        // This is used in a rare situation when async Read is resumed from completed handshake.
        //
        private static void ResumeAsyncReadCallback(AsyncProtocolRequest request)
        {
            try
            {
                ((SslStreamInternal)request.AsyncObject).StartReading(request.Buffer, request.Offset, request.Count, request);
            }
            catch (Exception e)
            {
                if (request.IsUserCompleted)
                {
                    // This will throw on a worker thread.
                    throw;
                }

                ((SslStreamInternal)request.AsyncObject)._sslState.FinishRead(null);
                request.CompleteWithError(e);
            }
        }
Example #59
0
        //
        //
        private IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
        {
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
                _negoState.CheckThrow(true);

                if (!_negoState.CanGetSecureStream)
                {
                    return InnerStream.BeginWrite(buffer, offset, count, asyncCallback, asyncState);
                }

                BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, true, asyncState, asyncCallback);
                AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult);

                ProcessWrite(buffer, offset, count, asyncRequest);
                return bufferResult;
#if DEBUG
            }
#endif
        }
Example #60
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());
        }