diff options
author | Sebastien Pouliot <sebastien@ximian.com> | 2005-02-02 21:25:16 +0300 |
---|---|---|
committer | Sebastien Pouliot <sebastien@ximian.com> | 2005-02-02 21:25:16 +0300 |
commit | 3d9acd1dd40910d19e8d3f7e69196579a80709a8 (patch) | |
tree | 2091e771e6335024d7bd4b08af4e1b4f15f2166c /mcs | |
parent | 8b9597e2dcb8aba0ff41517f54a9a2719b241bc1 (diff) |
2005-02-02 Sebastien Pouliot <sebastien@ximian.com>
* SslClientStream.cs: Throw exception when we receive a null record.
* RecordProtocol.cs: Added code to avoid blocking and endless loops
if the data is incomplete or missing - even in the case the server
side doesn't close the connection (see new cutcli tool).
svn path=/trunk/mcs/; revision=39997
Diffstat (limited to 'mcs')
3 files changed, 105 insertions, 26 deletions
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog index bc8ffe4dbce..2a41f6d0937 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog @@ -1,3 +1,10 @@ +2005-02-02 Sebastien Pouliot <sebastien@ximian.com> + + * SslClientStream.cs: Throw exception when we receive a null record. + * RecordProtocol.cs: Added code to avoid blocking and endless loops + if the data is incomplete or missing - even in the case the server + side doesn't close the connection (see new cutcli tool). + 2004-12-15 Sebastien Pouliot <sebastien@ximian.com> * CipherSuite.cs: Removed unused MD5 and SHA1 instances created in diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs index 155e02be93f..412ca23a60e 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs @@ -24,9 +24,11 @@ using System; using System.Collections; -using System.IO; +using System.IO;
+using System.Net.Sockets; using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.X509Certificates;
+using System.Threading; using Mono.Security.Protocol.Tls.Handshake; @@ -70,7 +72,31 @@ namespace Mono.Security.Protocol.Tls #endregion - #region Reveive Record Methods + #region Reveive Record Methods
+
+ internal const int Timeout = 1000;
+
+ internal bool WaitForData ()
+ {
+ // problem: NetworkStream.ReadByte blocks until a byte is received
+ // and (maybe) no byte will ever be received
+ if (this.innerStream is NetworkStream)
+ {
+ NetworkStream ns = (this.innerStream as NetworkStream);
+ int delay = 10;
+ while (delay < Timeout)
+ {
+ if (ns.DataAvailable)
+ return true;
+ Thread.Sleep (delay);
+ delay *= 2;
+ }
+ // nothing to see, move along
+ return false;
+ }
+ // we assume other type of stream have their own timeout capabilities
+ return true;
+ } public byte[] ReceiveRecord() { @@ -79,20 +105,25 @@ namespace Mono.Security.Protocol.Tls throw new TlsException( AlertDescription.InternalError, "The session is finished and it's no longer valid."); - } - - // Try to read the Record Content Type - int type = this.innerStream.ReadByte(); + }
+
+ if (!WaitForData ())
+ {
+ return null;
+ }
+
+ // Try to read the Record Content Type
+ int type = this.innerStream.ReadByte (); if (type == -1) - { + {
return null; - } + }
// Set last handshake message received to None this.context.LastHandshakeMsg = HandshakeType.ClientHello; - ContentType contentType = (ContentType)type; - byte[] buffer = this.ReadRecordBuffer(type); + ContentType contentType = (ContentType)type;
+ byte[] buffer = this.ReadRecordBuffer (type); TlsStream message = new TlsStream(buffer); @@ -173,13 +204,19 @@ namespace Mono.Security.Protocol.Tls } private byte[] ReadClientHelloV2() - { - int msgLength = this.innerStream.ReadByte(); - byte[] message = new byte [msgLength]; - this.innerStream.Read (message, 0, msgLength); - - int msgType = message [0]; - if (msgType != 1) + {
+ int msgType = -1;
+ byte[] message = null;
+ + int msgLength = this.innerStream.ReadByte();
+ if (msgLength > 0)
+ {
+ message = new byte [msgLength];
+ if (this.innerStream.Read (message, 0, msgLength) == msgLength)
+ msgType = message [0];
+ }
+ + if ((msgType != 1) || (message.Length < 9)) { throw new TlsException(AlertDescription.DecodeError); } @@ -229,6 +266,19 @@ namespace Mono.Security.Protocol.Tls this.context.ProtocolNegotiated = true; return message; + }
+
+ private bool Wait (ref int delay)
+ {
+ if (delay < 10)
+ delay = 10;
+
+ if (delay >= Timeout)
+ return false;
+
+ Thread.Sleep (delay);
+ delay *= 2;
+ return true;
} private byte[] ReadStandardRecordBuffer() @@ -239,9 +289,21 @@ namespace Mono.Security.Protocol.Tls // Read Record data int received = 0; byte[] buffer = new byte[length]; + int n = 0; while (received != length) { - received += this.innerStream.Read(buffer, received, buffer.Length - received); + int incoming = this.innerStream.Read(buffer, received, buffer.Length - received);
+ // we risk an infinite loop is data isn't available
+ if (incoming == 0)
+ {
+ if (!Wait (ref n))
+ throw new TlsException (AlertLevel.Fatal, AlertDescription.CloseNotify);
+ }
+ else
+ {
+ n = 0; // reset
+ }
+ received += incoming;
} // Check that the message has a valid protocol version @@ -258,8 +320,11 @@ namespace Mono.Security.Protocol.Tls private short ReadShort() { - byte[] b = new byte[2]; - this.innerStream.Read(b, 0, b.Length); + byte[] b = new byte[2];
+ if (this.innerStream.Read (b, 0, b.Length) != 2)
+ {
+ throw new TlsException (AlertLevel.Fatal, AlertDescription.DecodeError);
+ } short val = BitConverter.ToInt16(b, 0); diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs index ed99efe0257..926fb7af5b1 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs @@ -688,7 +688,7 @@ namespace Mono.Security.Protocol.Tls */ internal void NegotiateHandshake() - { + {
lock (this) { try @@ -707,8 +707,11 @@ namespace Mono.Security.Protocol.Tls // Read server response while (this.context.LastHandshakeMsg != HandshakeType.ServerHelloDone) { - // Read next record - this.protocol.ReceiveRecord(); + // Read next record
+ if (this.protocol.ReceiveRecord () == null)
+ {
+ throw new TlsException (AlertLevel.Fatal, AlertDescription.CloseNotify);
+ } } // Send client certificate if requested @@ -737,8 +740,12 @@ namespace Mono.Security.Protocol.Tls { // If all goes well this will process messages: // Change Cipher Spec - // Server finished - this.protocol.ReceiveRecord(); + // Server finished
+ // Read next record
+ if (this.protocol.ReceiveRecord () == null)
+ {
+ throw new TlsException (AlertLevel.Fatal, AlertDescription.CloseNotify);
+ }
} // Clear Key Info |