private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { ProtocolToken message = new ProtocolToken(null, status); if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"***Processing an error Status = {message.Status}"); } if (message.Renegotiate) { _sslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _sslState.FinishRead(null); asyncRequest?.CompleteUser(0); return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); }
// // Only processing SEC_I_RENEGOTIATE. // private int ProcessReadErrorCode(SecurityStatusPal errorCode, byte[] buffer, int offset, int count, byte[] extraBuffer) { // ERROR - examine what kind ProtocolToken message = new ProtocolToken(null, errorCode); if (GlobalLog.IsEnabled) { GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(this) + "::***Processing an error Status = " + message.Status.ToString()); } if (message.Renegotiate) { _SslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _SslState.FinishRead(null); return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); }
// // Only processing SEC_I_RENEGOTIATE. // private int ProcessReadErrorCode(Interop.SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { // ERROR - examine what kind ProtocolToken message = new ProtocolToken(null, errorCode); GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::***Processing an error Status = " + message.Status.ToString()); if (message.Renegotiate) { _SslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _SslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser((object)0); } return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); }
// private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (asyncRequest != null) { asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback); } // We loop to this method from the callback // If the last chunk was just completed from async callback (count < 0), we complete user request if (count >= 0) { byte[] outBuffer = null; do { // request a write IO slot if (_SslState.CheckEnqueueWrite(asyncRequest)) { // operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _SslState.MaxDataSize); int encryptedBytes; SecurityStatus errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (errorCode != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, errorCode); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (asyncRequest != null) { // prepare for the next request asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, _ResumeAsyncWriteCallback); IAsyncResult ar = _SslState.InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, _WriteCallback, asyncRequest); if (!ar.CompletedSynchronously) { return; } _SslState.InnerStream.EndWrite(ar); } else { _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes); } offset += chunkBytes; count -= chunkBytes; // release write IO slot _SslState.FinishWrite(); } while (count != 0); } if (asyncRequest != null) { asyncRequest.CompleteUser(); } }
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(); } }
private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { ProtocolToken token = new ProtocolToken(null, errorCode); if (token.Renegotiate) { this._SslState.ReplyOnReAuthentication(extraBuffer); return(-1); } if (!token.CloseConnection) { throw new IOException(SR.GetString("net_io_decrypt"), token.GetException()); } this._SslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser(0); } return(0); }
private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest) { if (count == 0) { throw new AuthenticationException(SR.GetString("net_auth_eof"), null); } if (this._PendingReHandshake) { int offset = 0; SecurityStatus errorCode = this.PrivateDecryptData(buffer, ref offset, ref count); if (errorCode == SecurityStatus.OK) { Exception exception = this.EnqueueOldKeyDecryptedData(buffer, offset, count); if (exception != null) { this.StartSendAuthResetSignal(null, asyncRequest, exception); return; } this._Framing = Framing.None; this.StartReceiveBlob(buffer, asyncRequest); return; } if (errorCode != SecurityStatus.Renegotiate) { ProtocolToken token = new ProtocolToken(null, errorCode); this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), token.GetException())); return; } this._PendingReHandshake = false; if (offset != 0) { Buffer.BlockCopy(buffer, offset, buffer, 0, count); } } this.StartSendBlob(buffer, count, asyncRequest); }
// // This will check and logically complete / fail the auth handshake. // private void CheckCompletionBeforeNextReceive(ProtocolToken message) { if (message.Failed) { SendAuthResetSignal(null, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_auth_SSPI, message.GetException()))); return; } else if (message.Done) { ProtocolToken alertToken = null; if (!CompleteHandshake(ref alertToken)) { SendAuthResetSignal(alertToken, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_ssl_io_cert_validation, null))); return; } // Release waiting IO if any. Presumably it should not throw. // Otherwise application may get not expected type of the exception. FinishHandshake(null); return; } ReceiveBlob(message.Payload); }
private Task WriteSingleChunk <TWriteAdapter>(TWriteAdapter writeAdapter, ReadOnlyMemory <byte> buffer) where TWriteAdapter : struct, ISslWriteAdapter { // Request a write IO slot. Task ioSlot = writeAdapter.LockAsync(); if (!ioSlot.IsCompletedSuccessfully) { // Operation is async and has been queued, return. return(WaitForWriteIOSlot(writeAdapter, ioSlot, buffer)); } byte[] rentedBuffer = ArrayPool <byte> .Shared.Rent(buffer.Length + FrameOverhead); byte[] outBuffer = rentedBuffer; SecurityStatusPal status = _sslState.EncryptData(buffer, ref outBuffer, out int encryptedBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { // Re-handshake status is not supported. ArrayPool <byte> .Shared.Return(rentedBuffer); ProtocolToken message = new ProtocolToken(null, status); return(Task.FromException(new IOException(SR.net_io_encrypt, message.GetException()))); } Task t = writeAdapter.WriteAsync(outBuffer, 0, encryptedBytes); if (t.IsCompletedSuccessfully) { ArrayPool <byte> .Shared.Return(rentedBuffer); _sslState.FinishWrite(); return(t); } else { return(CompleteAsync(t, rentedBuffer)); } async Task WaitForWriteIOSlot(TWriteAdapter wAdapter, Task lockTask, ReadOnlyMemory <byte> buff) { await lockTask.ConfigureAwait(false); await WriteSingleChunk(wAdapter, buff).ConfigureAwait(false); } async Task CompleteAsync(Task writeTask, byte[] bufferToReturn) { try { await writeTask.ConfigureAwait(false); } finally { ArrayPool <byte> .Shared.Return(bufferToReturn); _sslState.FinishWrite(); } } }
private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest) { if (count == 0) { // EOF received. throw new AuthenticationException(SR.net_auth_eof, null); } if (_pendingReHandshake) { int offset = 0; SecurityStatusPal status = PrivateDecryptData(buffer, ref offset, ref count); if (status.ErrorCode == SecurityStatusPalErrorCode.OK) { Exception e = EnqueueOldKeyDecryptedData(buffer, offset, count); if (e != null) { StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(e)); return; } _Framing = Framing.Unknown; StartReceiveBlob(buffer, asyncRequest); return; } else if (status.ErrorCode != SecurityStatusPalErrorCode.Renegotiate) { // Fail re-handshake. ProtocolToken message = new ProtocolToken(null, status); StartSendAuthResetSignal(null, asyncRequest, ExceptionDispatchInfo.Capture(new AuthenticationException(SR.net_auth_SSPI, message.GetException()))); return; } // We expect only handshake messages from now. _pendingReHandshake = false; if (offset != 0) { Buffer.BlockCopy(buffer, offset, buffer, 0, count); } } StartSendBlob(buffer, count, asyncRequest); }
private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (asyncRequest != null) { asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback); } // We loop to this method from the callback. // If the last chunk was just completed from async callback (count < 0), we complete user request. if (count >= 0) { byte[] outBuffer = null; if (_PinnableOutputBufferInUse == null) { if (_PinnableOutputBuffer == null) { _PinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer(); } _PinnableOutputBufferInUse = buffer; outBuffer = _PinnableOutputBuffer; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } } else { if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count); } } do { // Request a write IO slot. if (_SslState.CheckEnqueueWrite(asyncRequest)) { // Operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _SslState.MaxDataSize); int encryptedBytes; Interop.SecurityStatus errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (errorCode != Interop.SecurityStatus.OK) { ProtocolToken message = new ProtocolToken(null, errorCode); throw new IOException(SR.net_io_encrypt, message.GetException()); } if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer", this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } if (asyncRequest != null) { // Prepare for the next request. asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback); IAsyncResult ar = _SslState.InnerStreamAPM.BeginWrite(outBuffer, 0, encryptedBytes, s_writeCallback, asyncRequest); if (!ar.CompletedSynchronously) { return; } _SslState.InnerStreamAPM.EndWrite(ar); } else { _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes); } offset += chunkBytes; count -= chunkBytes; // Release write IO slot. _SslState.FinishWrite(); } while (count != 0); } if (asyncRequest != null) { asyncRequest.CompleteUser(); } if (buffer == _PinnableOutputBufferInUse) { _PinnableOutputBufferInUse = null; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode()); } } }
// // 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()); }
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(); } }
// // // private void ProcessReceivedBlob(byte[] buffer, int count, AsyncProtocolRequest asyncRequest) { if (count == 0) { // EOF received throw new AuthenticationException(SR.GetString(SR.net_auth_eof), null); } if (_PendingReHandshake) { int offset = 0; SecurityStatus status = PrivateDecryptData(buffer, ref offset, ref count); if (status == SecurityStatus.OK) { Exception e = EnqueueOldKeyDecryptedData(buffer, offset, count); if (e != null) { StartSendAuthResetSignal(null, asyncRequest, e); return; } // Again, forget about framing we can get a new one at any time _Framing = Framing.None; StartReceiveBlob(buffer, asyncRequest); return; } else if (status != SecurityStatus.Renegotiate) { // fail re-handshake ProtocolToken message = new ProtocolToken(null, status); StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString(SR.net_auth_SSPI), message.GetException())); return; } // Got it, now we should expect only handshake messages _PendingReHandshake = false; if (offset != 0) { Buffer.BlockCopy(buffer, offset, buffer, 0, count); } } StartSendBlob(buffer, count, asyncRequest); }
private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { ProtocolToken token = new ProtocolToken(null, errorCode); if (token.Renegotiate) { this._SslState.ReplyOnReAuthentication(extraBuffer); return -1; } if (!token.CloseConnection) { throw new IOException(SR.GetString("net_io_decrypt"), token.GetException()); } this._SslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser(0); } return 0; }
private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List<BufferOffsetSize> list = null; SecurityStatus oK = SecurityStatus.OK; foreach (BufferOffsetSize size in buffers) { int num2; int count = Math.Min(size.Size, this._SslState.MaxDataSize); byte[] outBuffer = null; oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } if ((count != size.Size) || (list != null)) { if (list == null) { list = new List<BufferOffsetSize>(buffers.Length * ((size.Size / count) + 1)); if (lastHandshakePayload != null) { list.Add(new BufferOffsetSize(lastHandshakePayload, false)); } foreach (BufferOffsetSize size2 in buffers) { if (size2 == size) { break; } list.Add(size2); } } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); while ((size.Size -= count) != 0) { size.Offset += count; count = Math.Min(size.Size, this._SslState.MaxDataSize); oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); } } else { size.Buffer = outBuffer; size.Offset = 0; size.Size = num2; } if (oK != SecurityStatus.OK) { break; } } if (oK != SecurityStatus.OK) { ProtocolToken token = new ProtocolToken(null, oK); throw new IOException(SR.GetString("net_io_encrypt"), token.GetException()); } if (list != null) { buffers = list.ToArray(); return buffers; } if (lastHandshakePayload != null) { BufferOffsetSize[] destinationArray = new BufferOffsetSize[buffers.Length + 1]; Array.Copy(buffers, 0, destinationArray, 1, buffers.Length); destinationArray[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = destinationArray; } return buffers; }
private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (asyncRequest != null) { asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback); } // We loop to this method from the callback. // If the last chunk was just completed from async callback (count < 0), we complete user request. if (count >= 0) { do { if (count == 0 && !SslStreamPal.CanEncryptEmptyMessage) { // If it's an empty message and the PAL doesn't support that, // we're done. break; } // Request a write IO slot. if (_sslState.CheckEnqueueWrite(asyncRequest)) { // Operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _sslState.MaxDataSize); byte[] rentedBuffer = ArrayPool <byte> .Shared.Rent(chunkBytes + FrameOverhead); byte[] outBuffer = rentedBuffer; int encryptedBytes = 0; SecurityStatusPal status = _sslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { // Re-handshake status is not supported. ProtocolToken message = new ProtocolToken(null, status); ArrayPool <byte> .Shared.Return(rentedBuffer); throw new IOException(SR.net_io_encrypt, message.GetException()); } if (asyncRequest != null) { // Prepare for the next request. asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback); Task t = _sslState.InnerStream.WriteAsync(outBuffer, 0, encryptedBytes); if (t.IsCompleted) { ArrayPool <byte> .Shared.Return(rentedBuffer); t.GetAwaiter().GetResult(); } else { t = t.ContinueWith(s_freeWriteBufferCallback, rentedBuffer, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest); if (!ar.CompletedSynchronously) { return; } TaskToApm.End(ar); } } else { try { _sslState.InnerStream.Write(outBuffer, 0, encryptedBytes); } finally { ArrayPool <byte> .Shared.Return(rentedBuffer); } } offset += chunkBytes; count -= chunkBytes; // Release write IO slot. _sslState.FinishWrite(); } while (count != 0); } if (asyncRequest != null) { asyncRequest.CompleteUser(); } }
private void CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) { if (message.Failed) { this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_auth_SSPI"), message.GetException())); } else if (message.Done && !this._PendingReHandshake) { if (this.CheckWin9xCachedSession()) { this._PendingReHandshake = true; this.Win9xSessionRestarted(); this.ForceAuthentication(false, null, asyncRequest); } else if (!this.CompleteHandshake()) { this.StartSendAuthResetSignal(null, asyncRequest, new AuthenticationException(SR.GetString("net_ssl_io_cert_validation"), null)); } else { this.FinishHandshake(null, asyncRequest); } } else { this.StartReceiveBlob(message.Payload, asyncRequest); } }
// private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (asyncRequest != null) { asyncRequest.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback); } // We loop to this method from the callback // If the last chunk was just completed from async callback (count < 0), we complete user request if (count >= 0 ) { byte[] outBuffer = null; do { // request a write IO slot if (_SslState.CheckEnqueueWrite(asyncRequest)) { // operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _SslState.MaxDataSize); int encryptedBytes; SecurityStatus errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (errorCode != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, errorCode); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (asyncRequest != null) { // prepare for the next request asyncRequest.SetNextRequest(buffer, offset+chunkBytes, count-chunkBytes, _ResumeAsyncWriteCallback); IAsyncResult ar = _SslState.InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, _WriteCallback, asyncRequest); if (!ar.CompletedSynchronously) { return; } _SslState.InnerStream.EndWrite(ar); } else { _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes); } offset += chunkBytes; count -= chunkBytes; // release write IO slot _SslState.FinishWrite(); } while (count != 0); } if (asyncRequest != null) { asyncRequest.CompleteUser(); } }
private void StartWriting(byte[] buffer, int offset, int count) { // We loop to this method from the callback. // If the last chunk was just completed from async callback (count < 0), we complete user request. if (count >= 0) { byte[] outBuffer = null; if (_PinnableOutputBufferInUse == null) { if (_PinnableOutputBuffer == null) { _PinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer(); } _PinnableOutputBufferInUse = buffer; outBuffer = _PinnableOutputBuffer; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } } else { if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count); } } do { // Request a write IO slot. if (_SslState.CheckEnqueueWrite(null)) { // Operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _SslState.MaxDataSize); int encryptedBytes; SecurityStatusPal errorCode = _SslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (errorCode != SecurityStatusPal.OK) { ProtocolToken message = new ProtocolToken(null, errorCode); throw new IOException(SR.net_io_encrypt, message.GetException()); } if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer", this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } _SslState.InnerStream.Write(outBuffer, 0, encryptedBytes); offset += chunkBytes; count -= chunkBytes; // Release write IO slot. _SslState.FinishWrite(); } while (count != 0); } if (buffer == _PinnableOutputBufferInUse) { _PinnableOutputBufferInUse = null; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode()); } } }
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()); } } }
private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List <BufferOffsetSize> list = null; SecurityStatus oK = SecurityStatus.OK; foreach (BufferOffsetSize size in buffers) { int num2; int count = Math.Min(size.Size, this._SslState.MaxDataSize); byte[] outBuffer = null; oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } if ((count != size.Size) || (list != null)) { if (list == null) { list = new List <BufferOffsetSize>(buffers.Length * ((size.Size / count) + 1)); if (lastHandshakePayload != null) { list.Add(new BufferOffsetSize(lastHandshakePayload, false)); } foreach (BufferOffsetSize size2 in buffers) { if (size2 == size) { break; } list.Add(size2); } } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); while ((size.Size -= count) != 0) { size.Offset += count; count = Math.Min(size.Size, this._SslState.MaxDataSize); oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); } } else { size.Buffer = outBuffer; size.Offset = 0; size.Size = num2; } if (oK != SecurityStatus.OK) { break; } } if (oK != SecurityStatus.OK) { ProtocolToken token = new ProtocolToken(null, oK); throw new IOException(SR.GetString("net_io_encrypt"), token.GetException()); } if (list != null) { buffers = list.ToArray(); return(buffers); } if (lastHandshakePayload != null) { BufferOffsetSize[] destinationArray = new BufferOffsetSize[buffers.Length + 1]; Array.Copy(buffers, 0, destinationArray, 1, buffers.Length); destinationArray[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = destinationArray; } return(buffers); }
private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (asyncRequest != null) { asyncRequest.SetNextRequest(buffer, offset, count, s_resumeAsyncWriteCallback); } // We loop to this method from the callback. // If the last chunk was just completed from async callback (count < 0), we complete user request. if (count >= 0) { byte[] outBuffer = null; if (_pinnableOutputBufferInUse == null) { if (_pinnableOutputBuffer == null) { _pinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer(); } _pinnableOutputBufferInUse = buffer; outBuffer = _pinnableOutputBuffer; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", this.GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } } else { if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", this.GetHashCode(), count); } } do { if (count == 0 && !SslStreamPal.CanEncryptEmptyMessage) { // If it's an empty message and the PAL doesn't support that, // we're done. break; } // Request a write IO slot. if (_sslState.CheckEnqueueWrite(asyncRequest)) { // Operation is async and has been queued, return. return; } int chunkBytes = Math.Min(count, _sslState.MaxDataSize); int encryptedBytes; SecurityStatusPal status = _sslState.EncryptData(buffer, offset, chunkBytes, ref outBuffer, out encryptedBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { // Re-handshake status is not supported. ProtocolToken message = new ProtocolToken(null, status); throw new IOException(SR.net_io_encrypt, message.GetException()); } if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer", this.GetHashCode(), encryptedBytes, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer)); } if (asyncRequest != null) { // Prepare for the next request. asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback); Task t = _sslState.InnerStream.WriteAsync(outBuffer, 0, encryptedBytes); if (t.IsCompleted) { t.GetAwaiter().GetResult(); } else { IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest); if (!ar.CompletedSynchronously) { return; } TaskToApm.End(ar); } } else { _sslState.InnerStream.Write(outBuffer, 0, encryptedBytes); } offset += chunkBytes; count -= chunkBytes; // Release write IO slot. _sslState.FinishWrite(); } while (count != 0); } if (asyncRequest != null) { asyncRequest.CompleteUser(); } if (buffer == _pinnableOutputBufferInUse) { _pinnableOutputBufferInUse = null; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", this.GetHashCode()); } } }
// // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones. // Returns the same array that is encrypted or a new array of encrypted buffers. // private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List<BufferOffsetSize> arrayList = null; SecurityStatus status = SecurityStatus.OK; foreach(BufferOffsetSize buffer in buffers) { int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); byte[] outBuffer = null; int outSize; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) break; if (chunkBytes != buffer.Size || arrayList != null) { if (arrayList == null) { arrayList = new List<BufferOffsetSize>(buffers.Length * (buffer.Size/chunkBytes+1)); if (lastHandshakePayload != null) arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false)); foreach(BufferOffsetSize oldBuffer in buffers) { if (oldBuffer == buffer) break; arrayList.Add(oldBuffer); } } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); while ((buffer.Size-=chunkBytes) != 0) { buffer.Offset += chunkBytes; chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); outBuffer = null; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) break; arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); } } else { buffer.Buffer = outBuffer; buffer.Offset = 0; buffer.Size = outSize; } if (status != SecurityStatus.OK) break; } if (status != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, status); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (arrayList != null) buffers = arrayList.ToArray(); else if (lastHandshakePayload != null) { BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length+1]; Array.Copy(buffers, 0, result, 1, buffers.Length); result[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = result; } return buffers; }
// // 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); }
// // Codes we process (Anything else - fail) // // - SEC_I_RENEGOTIATE // private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { // ERROR - examine what kind ProtocolToken message = new ProtocolToken(null, errorCode); GlobalLog.Print("SecureChannel#" + ValidationHelper.HashString(this) + "::***Processing an error Status = " + message.Status.ToString()); if (message.Renegotiate) { _SslState.ReplyOnReAuthentication(extraBuffer); // loop on read return -1; } if (message.CloseConnection) { _SslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser((object)0); } return 0; } // Otherwise bail out. throw new IOException(SR.GetString(SR.net_io_decrypt), message.GetException()); }
// // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones. // Returns the same array that is encrypted or a new array of encrypted buffers. // private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List <BufferOffsetSize> arrayList = null; SecurityStatus status = SecurityStatus.OK; foreach (BufferOffsetSize buffer in buffers) { int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); byte[] outBuffer = null; int outSize; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) { break; } if (chunkBytes != buffer.Size || arrayList != null) { if (arrayList == null) { arrayList = new List <BufferOffsetSize>(buffers.Length * (buffer.Size / chunkBytes + 1)); if (lastHandshakePayload != null) { arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false)); } foreach (BufferOffsetSize oldBuffer in buffers) { if (oldBuffer == buffer) { break; } arrayList.Add(oldBuffer); } } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); while ((buffer.Size -= chunkBytes) != 0) { buffer.Offset += chunkBytes; chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); outBuffer = null; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) { break; } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); } } else { buffer.Buffer = outBuffer; buffer.Offset = 0; buffer.Size = outSize; } if (status != SecurityStatus.OK) { break; } } if (status != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, status); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (arrayList != null) { buffers = arrayList.ToArray(); } else if (lastHandshakePayload != null) { BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length + 1]; Array.Copy(buffers, 0, result, 1, buffers.Length); result[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = result; } return(buffers); }
private async ValueTask <int> ReadAsyncInternal <TReadAdapter>(TReadAdapter adapter, Memory <byte> buffer) where TReadAdapter : ISslReadAdapter { if (Interlocked.Exchange(ref _nestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(ReadAsync), "read")); } while (true) { int copyBytes; if (_decryptedBytesCount != 0) { copyBytes = CopyDecryptedData(buffer); _sslState.FinishRead(null); _nestedRead = 0; return(copyBytes); } copyBytes = await adapter.LockAsync(buffer).ConfigureAwait(false); try { if (copyBytes > 0) { return(copyBytes); } ResetReadBuffer(); int readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); if (readBytes == 0) { return(0); } int payloadBytes = _sslState.GetRemainingFrameSize(_internalBuffer, _internalOffset, readBytes); if (payloadBytes < 0) { throw new IOException(SR.net_frame_read_size); } readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize + payloadBytes).ConfigureAwait(false); if (readBytes < 0) { throw new IOException(SR.net_frame_read_size); } // At this point, readBytes contains the size of the header plus body. // Set _decrytpedBytesOffset/Count to the current frame we have (including header) // DecryptData will decrypt in-place and modify these to point to the actual decrypted data, which may be smaller. _decryptedBytesOffset = _internalOffset; _decryptedBytesCount = readBytes; SecurityStatusPal status = _sslState.DecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount); // Treat the bytes we just decrypted as consumed // Note, we won't do another buffer read until the decrypted bytes are processed ConsumeBufferedBytes(readBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { byte[] extraBuffer = null; if (_decryptedBytesCount != 0) { extraBuffer = new byte[_decryptedBytesCount]; Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount); _decryptedBytesCount = 0; } ProtocolToken message = new ProtocolToken(null, status); if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"***Processing an error Status = {message.Status}"); } if (message.Renegotiate) { if (!_sslState._sslAuthenticationOptions.AllowRenegotiation) { throw new IOException(SR.net_ssl_io_renego); } _sslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _sslState.FinishRead(null); return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); } } catch (Exception e) { _sslState.FinishRead(null); if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { _nestedRead = 0; } } }
// // Only processing SEC_I_RENEGOTIATE. // private int ProcessReadErrorCode(SecurityStatusPal errorCode, byte[] buffer, int offset, int count, byte[] extraBuffer) { // ERROR - examine what kind ProtocolToken message = new ProtocolToken(null, errorCode); GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::***Processing an error Status = " + message.Status.ToString()); if (message.Renegotiate) { _SslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return -1; } if (message.CloseConnection) { _SslState.FinishRead(null); return 0; } throw new IOException(SR.net_io_decrypt, message.GetException()); }
private int ProcessReadErrorCode(SecurityStatusPal status, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer) { ProtocolToken message = new ProtocolToken(null, status); if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"***Processing an error Status = {message.Status}"); if (message.Renegotiate) { _sslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return -1; } if (message.CloseConnection) { _sslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser((object)0); } return 0; } throw new IOException(SR.net_io_decrypt, message.GetException()); }