GetException() 공개 정적인 메소드

public static GetException ( SecurityStatusPal status ) : Exception
status SecurityStatusPal
리턴 Exception
예제 #1
0
        // This will initiate renegotiation or PHA for Tls1.3
        private async Task RenegotiateAsync <TIOAdapter>(CancellationToken cancellationToken)
            where TIOAdapter : IReadWriteAdapter
        {
            if (Interlocked.Exchange(ref _nestedAuth, 1) == 1)
            {
                throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, "authenticate"));
            }

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

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

            try
            {
                if (_buffer.ActiveLength > 0)
                {
                    throw new InvalidOperationException(SR.net_ssl_renegotiate_buffer);
                }

                _sslAuthenticationOptions !.RemoteCertRequired = true;
                _isRenego = true;


                SecurityStatusPal status = Renegotiate(out byte[]? nextmsg);

                if (nextmsg is { Length : > 0 })
                {
                    await TIOAdapter.WriteAsync(InnerStream, nextmsg, 0, nextmsg.Length, cancellationToken).ConfigureAwait(false);

                    await TIOAdapter.FlushAsync(InnerStream, cancellationToken).ConfigureAwait(false);
                }

                if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
                {
                    if (status.ErrorCode == SecurityStatusPalErrorCode.NoRenegotiation)
                    {
                        // Peer does not want to renegotiate. That should keep session usable.
                        return;
                    }

                    throw SslStreamPal.GetException(status);
                }

                _buffer.EnsureAvailableSpace(InitialHandshakeBufferSize);

                ProtocolToken message;
                do
                {
                    message = await ReceiveBlobAsync <TIOAdapter>(cancellationToken).ConfigureAwait(false);

                    if (message.Size > 0)
                    {
                        await TIOAdapter.WriteAsync(InnerStream, message.Payload !, 0, message.Size, cancellationToken).ConfigureAwait(false);

                        await TIOAdapter.FlushAsync(InnerStream, cancellationToken).ConfigureAwait(false);
                    }
                }while (message.Status.ErrorCode == SecurityStatusPalErrorCode.ContinueNeeded);

                CompleteHandshake(_sslAuthenticationOptions !);
            }
예제 #2
0
        private async ValueTask <int> ReadAsyncInternal <TIOAdapter>(TIOAdapter adapter, Memory <byte> buffer)
            where TIOAdapter : ISslIOAdapter
        {
            if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(SslStream.ReadAsync), "read"));
            }

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

                        return(copyBytes);
                    }

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

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

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

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

                    int payloadBytes = GetFrameSize(new ReadOnlySpan <byte>(_internalBuffer, _internalOffset, readBytes));
                    if (payloadBytes < 0)
                    {
                        throw new IOException(SR.net_frame_read_size);
                    }

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

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

                    // 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  = payloadBytes;
                    SecurityStatusPal status = DecryptData();

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

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

                        if (status.ErrorCode == SecurityStatusPalErrorCode.Renegotiate)
                        {
                            if (!_sslAuthenticationOptions.AllowRenegotiation)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Fail(this, "Renegotiation was requested but it is disallowed");
                                }
                                throw new IOException(SR.net_ssl_io_renego);
                            }

                            await ReplyOnReAuthenticationAsync(adapter, extraBuffer).ConfigureAwait(false);

                            // Loop on read.
                            continue;
                        }

                        if (status.ErrorCode == SecurityStatusPalErrorCode.ContextExpired)
                        {
                            return(0);
                        }

                        throw new IOException(SR.net_io_decrypt, SslStreamPal.GetException(status));
                    }
                }
            }
            catch (Exception e)
            {
                if (e is IOException || (e is OperationCanceledException && adapter.CancellationToken.IsCancellationRequested))
                {
                    throw;
                }

                throw new IOException(SR.net_io_read, e);
            }
            finally
            {
                _nestedRead = 0;
            }
        }
예제 #3
0
 internal Exception GetException()
 {
     // If it's not done, then there's got to be an error, even if it's
     // a Handshake message up, and we only have a Warning message.
     return(this.Done ? null : SslStreamPal.GetException(Status));
 }
예제 #4
0
        private ValueTask WriteSingleChunk <TIOAdapter>(TIOAdapter writeAdapter, ReadOnlyMemory <byte> buffer)
            where TIOAdapter : struct, ISslIOAdapter
        {
            // Request a write IO slot.
            Task ioSlot = writeAdapter.WriteLockAsync();

            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 = EncryptData(buffer, ref outBuffer, out int encryptedBytes);

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

                return(new ValueTask(Task.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(new IOException(SR.net_io_encrypt, SslStreamPal.GetException(status))))));
            }

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

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

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

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

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

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

                    FinishWrite();
                }
            }
        }
        private async ValueTask <int> ReadAsyncInternal <TIOAdapter>(TIOAdapter adapter, Memory <byte> buffer)
            where TIOAdapter : ISslIOAdapter
        {
            if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
            {
                throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(SslStream.ReadAsync), "read"));
            }

            try
            {
                while (true)
                {
                    if (_decryptedBytesCount != 0)
                    {
                        return(CopyDecryptedData(buffer));
                    }

                    int copyBytes = await adapter.ReadLockAsync(buffer).ConfigureAwait(false);

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

                    ResetReadBuffer();

                    // Read the next frame header.
                    if (_internalBufferCount < SecureChannel.ReadHeaderSize)
                    {
                        // We don't have enough bytes buffered, so issue an initial read to try to get enough.  This is
                        // done in this method both to better consolidate error handling logic (the first read is the special
                        // case that needs to differentiate reading 0 from > 0, and everything else needs to throw if it
                        // doesn't read enough), and to minimize the chances that in the common case the FillBufferAsync
                        // helper needs to yield and allocate a state machine.
                        int readBytes = await adapter.ReadAsync(_internalBuffer.AsMemory(_internalBufferCount)).ConfigureAwait(false);

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

                        _internalBufferCount += readBytes;
                        if (_internalBufferCount < SecureChannel.ReadHeaderSize)
                        {
                            await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false);
                        }
                    }
                    Debug.Assert(_internalBufferCount >= SecureChannel.ReadHeaderSize);

                    // Parse the frame header to determine the payload size (which includes the header size).
                    int payloadBytes = GetFrameSize(_internalBuffer.AsSpan(_internalOffset));
                    if (payloadBytes < 0)
                    {
                        throw new IOException(SR.net_frame_read_size);
                    }

                    // Read in the rest of the payload if we don't have it.
                    if (_internalBufferCount < payloadBytes)
                    {
                        await FillBufferAsync(adapter, payloadBytes).ConfigureAwait(false);
                    }

                    // 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  = payloadBytes;
                    SecurityStatusPal status = DecryptData();

                    // Treat the bytes we just decrypted as consumed
                    // Note, we won't do another buffer read until the decrypted bytes are processed
                    ConsumeBufferedBytes(payloadBytes);

                    if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
                    {
                        byte[] extraBuffer = null;
                        if (_decryptedBytesCount != 0)
                        {
                            extraBuffer = new byte[_decryptedBytesCount];
                            Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount);

                            _decryptedBytesCount = 0;
                        }

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

                        if (status.ErrorCode == SecurityStatusPalErrorCode.Renegotiate)
                        {
                            if (!_sslAuthenticationOptions.AllowRenegotiation)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Fail(this, "Renegotiation was requested but it is disallowed");
                                }
                                throw new IOException(SR.net_ssl_io_renego);
                            }

                            await ReplyOnReAuthenticationAsync(adapter, extraBuffer).ConfigureAwait(false);

                            // Loop on read.
                            continue;
                        }

                        if (status.ErrorCode == SecurityStatusPalErrorCode.ContextExpired)
                        {
                            return(0);
                        }

                        throw new IOException(SR.net_io_decrypt, SslStreamPal.GetException(status));
                    }
                }
            }
            catch (Exception e)
            {
                if (e is IOException || (e is OperationCanceledException && adapter.CancellationToken.IsCancellationRequested))
                {
                    throw;
                }

                throw new IOException(SR.net_io_read, e);
            }
            finally
            {
                _nestedRead = 0;
            }
        }