[pgsqlclient-checkins] pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls ClientC
Status: Inactive
Brought to you by:
carlosga_fb
From: <car...@us...> - 2004-02-23 12:30:03
|
Update of /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31028 Modified Files: CipherSuite.cs ClientRecordProtocol.cs RecordProtocol.cs SslClientStream.cs SslServerStream.cs Added Files: ClientContext.cs Context.cs ServerContext.cs ServerRecordProtocol.cs Removed Files: TlsContext.cs Log Message: 2004-02-23 Carlos Guzman Alvarez <car...@te...> * Mono.Security.Protocol.Tls/TlsContext.cs: - Removed file, implementation is now present in: Context.cs ClientContext.cs ServerContext.cs * Mono.Security.Protocol.Tls/Context.cs: * Mono.Security.Protocol.Tls/ClientContext.cs: * Mono.Security.Protocol.Tls/ServerContext.cs: * Mono.Security.Protocol.Tls/ServerRecordProtocol.cs: - New classes. * Mono.Security.Protocol.Tls/SslServerStream.cs: - Added implementation for properties, and read/write methods as in SslClientStream. - doHandshake method is not implemented yet. * Mono.Security.Protocol.Tls/SslClientStream.cs: * Mono.Security.Protocol.Tls/RecordProtocol.cs: - Added changes for make use of the new Context implementation. --- NEW FILE: ClientContext.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; namespace Mono.Security.Protocol.Tls { internal class ClientContext : Context { #region Fields private SslClientStream sslStream; private short clientHelloProtocol; private bool helloDone; #endregion #region Properties public SslClientStream SslStream { get { return this.sslStream; } } public bool HelloDone { get { return helloDone; } set { helloDone = value; } } public short ClientHelloProtocol { get { return this.clientHelloProtocol; } set { this.clientHelloProtocol = value; } } #endregion #region Constructors public ClientContext( SslClientStream stream, SecurityProtocolType securityProtocolType, string targetHost, X509CertificateCollection clientCertificates) : base(securityProtocolType) { this.sslStream = stream; this.ClientSettings.Certificates = clientCertificates; this.ClientSettings.TargetHost = targetHost; } #endregion } } --- NEW FILE: Context.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.Text; using System.Collections; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Mono.Security.Cryptography; using Mono.Security.Protocol.Tls.Alerts; using Mono.Security.Protocol.Tls.Handshake; namespace Mono.Security.Protocol.Tls { internal abstract class Context { #region Internal Constants internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14 internal const short TLS1_PROTOCOL_CODE = (0x03 << 8) | 0x01; internal const short SSL3_PROTOCOL_CODE = (0x03 << 8) | 0x00; internal const long UNIX_BASE_TICKS = 621355968000000000; #endregion #region Fields // Protocol version private SecurityProtocolType securityProtocol; // Sesison ID private byte[] sessionId; // Compression method private SecurityCompressionType compressionMethod; // Information sent and request by the server in the Handshake protocol private TlsServerSettings serverSettings; // Client configuration private TlsClientSettings clientSettings; // Cipher suite information private CipherSuite cipher; private TlsCipherSuiteCollection supportedCiphers; // Misc private bool isActual; private bool handshakeFinished; private bool connectionEnd; private bool protocolNegotiated; // Sequence numbers private long writeSequenceNumber; private long readSequenceNumber; // Random data private byte[] clientRandom; private byte[] serverRandom; private byte[] randomCS; private byte[] randomSC; // Key information private byte[] masterSecret; private byte[] clientWriteMAC; private byte[] serverWriteMAC; private byte[] clientWriteKey; private byte[] serverWriteKey; private byte[] clientWriteIV; private byte[] serverWriteIV; // Handshake hashes private TlsStream handshakeMessages; // Secure Random generator private RandomNumberGenerator random; #endregion #region Properties public bool ProtocolNegotiated { get { return this.protocolNegotiated; } set { this.protocolNegotiated = value; } } public SecurityProtocolType SecurityProtocol { get { if ((this.securityProtocol & SecurityProtocolType.Tls) == SecurityProtocolType.Tls || (this.securityProtocol & SecurityProtocolType.Default) == SecurityProtocolType.Default) { return SecurityProtocolType.Tls; } else { if ((this.securityProtocol & SecurityProtocolType.Ssl3) == SecurityProtocolType.Ssl3) { return SecurityProtocolType.Ssl3; } } throw new NotSupportedException("Unsupported security protocol type"); } set { this.securityProtocol = value; } } public SecurityProtocolType SecurityProtocolFlags { get { return this.securityProtocol; } } public short Protocol { get { switch (this.SecurityProtocol) { case SecurityProtocolType.Tls: case SecurityProtocolType.Default: return Context.TLS1_PROTOCOL_CODE; case SecurityProtocolType.Ssl3: return Context.SSL3_PROTOCOL_CODE; case SecurityProtocolType.Ssl2: default: throw new NotSupportedException("Unsupported security protocol type"); } } } public byte[] SessionId { get { return this.sessionId; } set { this.sessionId = value; } } public SecurityCompressionType CompressionMethod { get { return this.compressionMethod; } set { this.compressionMethod = value; } } public TlsServerSettings ServerSettings { get { return this.serverSettings; } set { this.serverSettings = value; } } public TlsClientSettings ClientSettings { get { return this.clientSettings; } set { this.clientSettings = value; } } public bool IsActual { get { return this.isActual; } set { this.isActual = value; } } public bool HandshakeFinished { get { return handshakeFinished; } set { handshakeFinished = value; } } public bool ConnectionEnd { get { return this.connectionEnd; } set { this.connectionEnd = value; } } public CipherSuite Cipher { get { return this.cipher; } set { this.cipher = value; } } public TlsCipherSuiteCollection SupportedCiphers { get { return supportedCiphers; } set { supportedCiphers = value; } } public TlsStream HandshakeMessages { get { return this.handshakeMessages; } } public long WriteSequenceNumber { get { return this.writeSequenceNumber; } set { this.writeSequenceNumber = value; } } public long ReadSequenceNumber { get { return this.readSequenceNumber; } set { this.readSequenceNumber = value; } } public byte[] ClientRandom { get { return this.clientRandom; } set { this.clientRandom = value; } } public byte[] ServerRandom { get { return this.serverRandom; } set { this.serverRandom = value; } } public byte[] RandomCS { get { return this.randomCS; } set { this.randomCS = value; } } public byte[] RandomSC { get { return this.randomSC; } set { this.randomSC = value; } } public byte[] MasterSecret { get { return this.masterSecret; } set { this.masterSecret = value; } } public byte[] ClientWriteMAC { get { return this.clientWriteMAC; } set { this.clientWriteMAC = value; } } public byte[] ServerWriteMAC { get { return this.serverWriteMAC; } set { this.serverWriteMAC = value; } } public byte[] ClientWriteKey { get { return this.clientWriteKey; } set { this.clientWriteKey = value; } } public byte[] ServerWriteKey { get { return this.serverWriteKey; } set { this.serverWriteKey = value; } } public byte[] ClientWriteIV { get { return this.clientWriteIV; } set { this.clientWriteIV = value; } } public byte[] ServerWriteIV { get { return this.serverWriteIV; } set { this.serverWriteIV = value; } } #endregion #region Constructors public Context(SecurityProtocolType securityProtocolType) { this.SecurityProtocol = securityProtocolType; this.compressionMethod = SecurityCompressionType.None; this.serverSettings = new TlsServerSettings(); this.clientSettings = new TlsClientSettings(); this.handshakeMessages = new TlsStream(); this.sessionId = null; this.random = RandomNumberGenerator.Create(); } #endregion #region Methods public int GetUnixTime() { DateTime now = DateTime.UtcNow; return (int)(now.Ticks - UNIX_BASE_TICKS / TimeSpan.TicksPerSecond); } public byte[] GetSecureRandomBytes(int count) { byte[] secureBytes = new byte[count]; this.random.GetNonZeroBytes(secureBytes); return secureBytes; } public void ClearKeyInfo() { // Clear Master Secret this.masterSecret = null; // Clear client and server random this.clientRandom = null; this.serverRandom = null; this.randomCS = null; this.randomSC = null; // Clear client keys this.clientWriteKey = null; this.clientWriteIV = null; // Clear server keys this.serverWriteKey = null; this.serverWriteIV = null; // Clear MAC keys if protocol is different than Ssl3 if (this.securityProtocol != SecurityProtocolType.Ssl3) { this.clientWriteMAC = null; this.serverWriteMAC = null; } } public SecurityProtocolType DecodeProtocolCode(short code) { switch (code) { case Context.TLS1_PROTOCOL_CODE: return SecurityProtocolType.Tls; case Context.SSL3_PROTOCOL_CODE: return SecurityProtocolType.Ssl3; default: throw new NotSupportedException("Unsupported security protocol type"); } } #endregion #region Exception Methods public TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc) { return CreateException(TlsAlert.GetAlertMessage(alertDesc)); } public TlsException CreateException(string format, params object[] args) { StringBuilder message = new StringBuilder(); message.AppendFormat(format, args); return CreateException(message.ToString()); } public TlsException CreateException(string message) { return new TlsException(message); } #endregion } } --- NEW FILE: ServerContext.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; namespace Mono.Security.Protocol.Tls { internal class ServerContext : Context { #region Fields private SslServerStream sslStream; private bool clientCertificateRequired; #endregion #region Properties public SslServerStream SslStream { get { return this.sslStream; } } public bool ClientCertificateRequired { get { return this.clientCertificateRequired; } } #endregion #region Constructors public ServerContext( SslServerStream stream, SecurityProtocolType securityProtocolType, X509Certificate serverCertificate, bool clientCertificateRequired) : base(securityProtocolType) { this.sslStream = stream; this.clientCertificateRequired = clientCertificateRequired; // this.ServerSettings.Certificates.Add(serverCertificate); } #endregion } } --- NEW FILE: ServerRecordProtocol.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.IO; using Mono.Security.Protocol.Tls.Alerts; using Mono.Security.Protocol.Tls.Handshake; using Mono.Security.Protocol.Tls.Handshake.Server; namespace Mono.Security.Protocol.Tls { internal class ServerRecordProtocol : RecordProtocol { #region Constructors public ServerRecordProtocol( Stream innerStream, ServerContext context) : base(innerStream, context) { } #endregion #region Send Messages public override void SendRecord(TlsHandshakeType type) { // Create the record message TlsHandshakeMessage msg = this.createServerHandshakeMessage(type); // Write record this.SendRecord(msg.ContentType, msg.EncodeMessage()); // Update session msg.Update(); // Reset message contents msg.Reset(); } #endregion #region Handshake Processing Methods protected override void ProcessHandshakeMessage(TlsStream handMsg) { TlsHandshakeType handshakeType = (TlsHandshakeType)handMsg.ReadByte(); TlsHandshakeMessage message = null; // Read message length int length = handMsg.ReadInt24(); // Read message data byte[] data = new byte[length]; handMsg.Read(data, 0, length); // Create and process the server message message = this.createClientHandshakeMessage(handshakeType, data); // Update session if (message != null) { message.Update(); } } #endregion #region Server Handshake Message Factories private TlsHandshakeMessage createClientHandshakeMessage( TlsHandshakeType type, byte[] buffer) { switch (type) { case TlsHandshakeType.ClientHello: return new TlsClientHello(this.context, buffer); case TlsHandshakeType.Certificate: return new TlsClientCertificate(this.context, buffer); case TlsHandshakeType.ClientKeyExchange: return new TlsClientKeyExchange(this.context, buffer); case TlsHandshakeType.CertificateVerify: return new TlsClientCertificateVerify(this.context, buffer); case TlsHandshakeType.Finished: return new TlsClientFinished(this.context, buffer); default: throw this.context.CreateException("Unknown server handshake message received ({0})", type.ToString()); } } private TlsHandshakeMessage createServerHandshakeMessage( TlsHandshakeType type) { switch (type) { case TlsHandshakeType.HelloRequest: this.SendRecord(TlsHandshakeType.ClientHello); return null; case TlsHandshakeType.ServerHello: return new TlsServerHello(this.context); case TlsHandshakeType.Certificate: return new TlsServerCertificate(this.context); case TlsHandshakeType.ServerKeyExchange: return new TlsServerKeyExchange(this.context); case TlsHandshakeType.CertificateRequest: return new TlsServerCertificateRequest(this.context); case TlsHandshakeType.ServerHelloDone: return new TlsServerHelloDone(this.context); case TlsHandshakeType.Finished: return new TlsServerFinished(this.context); default: throw new InvalidOperationException("Unknown server handshake message type: " + type.ToString() ); } } #endregion } } Index: CipherSuite.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** CipherSuite.cs 20 Feb 2004 18:13:53 -0000 1.4 --- CipherSuite.cs 23 Feb 2004 12:15:58 -0000 1.5 *************** *** 58,62 **** private byte ivSize; private byte blockSize; ! private TlsContext context; private SymmetricAlgorithm encryptionAlgorithm; private ICryptoTransform encryptionCipher; --- 58,62 ---- private byte ivSize; private byte blockSize; ! private Context context; private SymmetricAlgorithm encryptionAlgorithm; private ICryptoTransform encryptionCipher; *************** *** 195,199 **** } ! public TlsContext Context { get { return this.context; } --- 195,199 ---- } ! public Context Context { get { return this.context; } *************** *** 353,357 **** public byte[] CreatePremasterSecret() { ! TlsStream stream = new TlsStream(); // Write protocol version --- 353,358 ---- public byte[] CreatePremasterSecret() { ! TlsStream stream = new TlsStream(); ! ClientContext context = (ClientContext)this.Context; // Write protocol version *************** *** 359,363 **** // the ClientHello message, that can be different than the actual // protocol version ! stream.Write(this.Context.ClientHelloProtocol); // Generate random bytes --- 360,364 ---- // the ClientHello message, that can be different than the actual // protocol version ! stream.Write(context.ClientHelloProtocol); // Generate random bytes Index: ClientRecordProtocol.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls/ClientRecordProtocol.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ClientRecordProtocol.cs 19 Feb 2004 13:54:09 -0000 1.1 --- ClientRecordProtocol.cs 23 Feb 2004 12:16:08 -0000 1.2 *************** *** 38,42 **** public ClientRecordProtocol( Stream innerStream, ! TlsContext context) : base(innerStream, context) { } --- 38,42 ---- public ClientRecordProtocol( Stream innerStream, ! ClientContext context) : base(innerStream, context) { } *************** *** 91,95 **** #region Client Handshake Message Factories ! private TlsHandshakeMessage createClientHandshakeMessage(TlsHandshakeType type) { switch (type) --- 91,96 ---- #region Client Handshake Message Factories ! private TlsHandshakeMessage createClientHandshakeMessage( ! TlsHandshakeType type) { switch (type) *************** *** 115,119 **** } ! private TlsHandshakeMessage createServerHandshakeMessage(TlsHandshakeType type, byte[] buffer) { switch (type) --- 116,121 ---- } ! private TlsHandshakeMessage createServerHandshakeMessage( ! TlsHandshakeType type, byte[] buffer) { switch (type) Index: RecordProtocol.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RecordProtocol.cs 20 Feb 2004 18:13:53 -0000 1.3 --- RecordProtocol.cs 23 Feb 2004 12:16:08 -0000 1.4 *************** *** 37,42 **** #region Fields ! protected Stream innerStream; ! protected TlsContext context; #endregion --- 37,42 ---- #region Fields ! protected Stream innerStream; ! protected Context context; #endregion *************** *** 50,54 **** } ! public TlsContext Context { get { return this.context; } --- 50,54 ---- } ! public Context Context { get { return this.context; } *************** *** 60,64 **** #region Constructors ! public RecordProtocol(Stream innerStream, TlsContext context) { this.innerStream = innerStream; --- 60,64 ---- #region Constructors ! public RecordProtocol(Stream innerStream, Context context) { this.innerStream = innerStream; *************** *** 109,114 **** // Check that the message has a valid protocol version ! if (protocol != this.context.Protocol && ! this.context.HelloDone) { throw this.context.CreateException("Invalid protocol version on message received from server"); --- 109,113 ---- // Check that the message has a valid protocol version ! if (protocol != this.context.Protocol && this.context.ProtocolNegotiated) { throw this.context.CreateException("Invalid protocol version on message received from server"); *************** *** 269,275 **** byte[] fragment; ! if ((count - position) > TlsContext.MAX_FRAGMENT_SIZE) { ! fragmentLength = TlsContext.MAX_FRAGMENT_SIZE; } else --- 268,274 ---- byte[] fragment; ! if ((count - position) > Context.MAX_FRAGMENT_SIZE) { ! fragmentLength = Context.MAX_FRAGMENT_SIZE; } else Index: SslClientStream.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** SslClientStream.cs 20 Feb 2004 18:13:53 -0000 1.12 --- SslClientStream.cs 23 Feb 2004 12:16:08 -0000 1.13 *************** *** 30,34 **** using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; - using System.Threading; using Mono.Security.Protocol.Tls.Alerts; --- 30,33 ---- *************** *** 72,76 **** private Stream innerStream; private BufferedStream inputBuffer; ! private TlsContext context; private ClientRecordProtocol protocol; private bool ownsStream; --- 71,75 ---- private Stream innerStream; private BufferedStream inputBuffer; ! private ClientContext context; private ClientRecordProtocol protocol; private bool ownsStream; *************** *** 349,357 **** } ! this.context = new TlsContext( this, securityProtocolType, targetHost, clientCertificates); this.inputBuffer = new BufferedStream(new MemoryStream()); this.innerStream = stream; --- 348,357 ---- } ! this.context = new ClientContext( this, securityProtocolType, targetHost, clientCertificates); + this.inputBuffer = new BufferedStream(new MemoryStream()); this.innerStream = stream; *************** *** 525,535 **** buffer, offset, count, callback, state); } ! catch (TlsException ex) { ! throw new IOException("The authentication or decryption has failed.", ex); } ! catch (Exception ex) { ! throw new IOException("IO exception during read.", ex); } } --- 525,535 ---- buffer, offset, count, callback, state); } ! catch (TlsException) { ! throw new IOException("The authentication or decryption has failed."); } ! catch (Exception) { ! throw new IOException("IO exception during read."); } } *************** *** 598,601 **** --- 598,602 ---- { // Send the buffer as a TLS record + byte[] record = this.protocol.EncodeRecord( TlsContentType.ApplicationData, buffer, offset, count); *************** *** 604,614 **** record, 0, record.Length, callback, state); } ! catch (TlsException ex) { throw new IOException("The authentication or decryption has failed."); } ! catch (Exception ex) { ! throw new IOException("IO exception during Write.", ex); } } --- 605,615 ---- record, 0, record.Length, callback, state); } ! catch (TlsException) { throw new IOException("The authentication or decryption has failed."); } ! catch (Exception) { ! throw new IOException("IO exception during Write."); } } Index: SslServerStream.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls/SslServerStream.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** SslServerStream.cs 10 Feb 2004 09:43:42 -0000 1.1 --- SslServerStream.cs 23 Feb 2004 12:16:08 -0000 1.2 *************** *** 24,39 **** using System; using System.IO; using System.Security.Cryptography.X509Certificates; namespace Mono.Security.Protocol.Tls { public class SslServerStream : Stream, IDisposable { #region Fields ! private Stream innerStream; ! private bool disposed; ! private bool ownsStream; #endregion --- 24,59 ---- using System; + using System.Collections; using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; + using Mono.Security.Protocol.Tls.Alerts; + namespace Mono.Security.Protocol.Tls { public class SslServerStream : Stream, IDisposable { + #region Internal Events + + internal event CertificateValidationCallback ClientCertValidation; + + #endregion + #region Fields ! private CertificateValidationCallback clientCertValidationDelegate; ! ! private ServerRecordProtocol protocol; ! private BufferedStream inputBuffer; ! private ServerContext context; ! private Stream innerStream; ! private bool disposed; ! private bool ownsStream; ! private bool checkCertRevocationStatus; ! private object read; ! private object write; #endregion *************** *** 73,129 **** public bool CheckCertRevocationStatus { ! get { throw new NotSupportedException(); } ! set { throw new NotSupportedException(); } } public CipherAlgorithmType CipherAlgorithm { ! get { throw new NotSupportedException(); } } ! public int CipherStrength { ! get { throw new NotSupportedException(); } } public X509Certificate ClientCertificate { ! get { throw new NotSupportedException(); } ! } ! ! public CertificateValidationCallback ClientCertValidationDelegate ! { ! get { throw new NotSupportedException(); } ! set { throw new NotSupportedException(); } ! } public HashAlgorithmType HashAlgorithm { ! get { throw new NotSupportedException(); } } public int HashStrength { ! get { throw new NotSupportedException(); } } public int KeyExchangeStrength { ! get { throw new NotSupportedException(); } } public ExchangeAlgorithmType KeyExchangeAlgorithm { ! get { throw new NotSupportedException(); } } public SecurityProtocolType SecurityProtocol { ! get { throw new NotSupportedException(); } } public X509Certificate ServerCertificate { ! get { throw new NotSupportedException(); } } --- 93,237 ---- public bool CheckCertRevocationStatus { ! get { return this.checkCertRevocationStatus ; } ! set { this.checkCertRevocationStatus = value; } } public CipherAlgorithmType CipherAlgorithm { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.Cipher.CipherAlgorithmType; ! } ! ! return CipherAlgorithmType.None; ! } } ! public int CipherStrength { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.Cipher.EffectiveKeyBits; ! } ! ! return 0; ! } } public X509Certificate ClientCertificate { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.ClientSettings.ClientCertificate; ! } + return null; + } + } + public HashAlgorithmType HashAlgorithm { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.Cipher.HashAlgorithmType; ! } ! ! return HashAlgorithmType.None; ! } } public int HashStrength { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.Cipher.HashSize * 8; ! } ! ! return 0; ! } } public int KeyExchangeStrength { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.ServerSettings.Certificates[0].RSA.KeySize; ! } ! ! return 0; ! } } public ExchangeAlgorithmType KeyExchangeAlgorithm { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.Cipher.ExchangeAlgorithmType; ! } ! ! return ExchangeAlgorithmType.None; ! } } public SecurityProtocolType SecurityProtocol { ! get ! { ! if (this.context.HandshakeFinished) ! { ! return this.context.SecurityProtocol; ! } ! ! return 0; ! } } public X509Certificate ServerCertificate { ! get ! { ! if (this.context.HandshakeFinished) ! { ! if (this.context.ServerSettings.Certificates != null && ! this.context.ServerSettings.Certificates.Count > 0) ! { ! return new X509Certificate(this.context.ServerSettings.Certificates[0].RawData); ! } ! } ! ! return null; ! } ! } ! ! #endregion ! ! #region Callback Properties ! ! public CertificateValidationCallback ClientCertValidationDelegate ! { ! get { return this.clientCertValidationDelegate; } ! set ! { ! if (this.ClientCertValidation != null) ! { ! this.ClientCertValidation -= this.clientCertValidationDelegate; ! } ! this.clientCertValidationDelegate = value; ! this.ClientCertValidation += this.clientCertValidationDelegate; ! } } *************** *** 132,157 **** #region Constructors ! public SslServerStream(Stream stream, X509Certificate serverCertificate) { - throw new NotSupportedException(); } public SslServerStream( ! Stream stream, X509Certificate serverCertificate, ! bool clientCertificateRequired, ! bool ownsStream) { - throw new NotSupportedException(); } public SslServerStream( ! Stream stream, ! X509Certificate serverCertificate, ! bool clientCertificateRequired, ! bool ownsStream, ! SecurityProtocolType securityProtocolType) { ! throw new NotSupportedException(); } --- 240,295 ---- #region Constructors ! public SslServerStream( ! Stream stream, ! X509Certificate serverCertificate) : this( ! stream, ! serverCertificate, ! false, ! false, ! SecurityProtocolType.Default) { } public SslServerStream( ! Stream stream, X509Certificate serverCertificate, ! bool clientCertificateRequired, ! bool ownsStream): this( ! stream, ! serverCertificate, ! clientCertificateRequired, ! ownsStream, ! SecurityProtocolType.Default) { } public SslServerStream( ! Stream stream, ! X509Certificate serverCertificate, ! bool clientCertificateRequired, ! bool ownsStream, ! SecurityProtocolType securityProtocolType) { ! if (stream == null) ! { ! throw new ArgumentNullException("stream is null."); ! } ! if (!stream.CanRead || !stream.CanWrite) ! { ! throw new ArgumentNullException("stream is not both readable and writable."); ! } ! ! this.context = new ServerContext( ! this, ! securityProtocolType, ! serverCertificate, ! clientCertificateRequired); ! ! this.inputBuffer = new BufferedStream(new MemoryStream()); ! this.innerStream = stream; ! this.ownsStream = ownsStream; ! this.read = String.Empty; ! this.write = String.Empty; ! this.protocol = new ServerRecordProtocol(innerStream, context); } *************** *** 183,186 **** --- 321,331 ---- if (this.innerStream != null) { + if (this.context.HandshakeFinished) + { + // Write close notify + TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this.context); + this.protocol.SendAlert(alert); + } + if (this.ownsStream) { *************** *** 191,194 **** --- 336,344 ---- this.ownsStream = false; this.innerStream = null; + if (this.ClientCertValidation != null) + { + this.ClientCertValidation -= this.clientCertValidationDelegate; + } + this.clientCertValidationDelegate = null; } *************** *** 202,258 **** public override IAsyncResult BeginRead( ! byte[] buffer, ! int offset, ! int count, ! AsyncCallback asyncCallback, ! object asyncState) { ! throw new NotSupportedException(); } public override IAsyncResult BeginWrite( ! byte[] buffer, ! int offset, ! int count, ! AsyncCallback asyncCallback, ! object asyncState) { ! throw new NotSupportedException(); ! } ! public override void Close() ! { ! throw new NotSupportedException(); } public override int EndRead(IAsyncResult asyncResult) { ! throw new NotSupportedException(); } public override void EndWrite(IAsyncResult asyncResult) { ! throw new NotSupportedException(); } public override void Flush() { ! if (this.disposed) ! { ! throw new ObjectDisposedException("The NetworkStream is closed."); ! } } public int Read(byte[] buffer) { ! throw new NotSupportedException(); } ! public override int Read( ! byte[] buffer, ! int offset, ! int count) { ! throw new NotSupportedException(); } --- 352,572 ---- public override IAsyncResult BeginRead( ! byte[] buffer, ! int offset, ! int count, ! AsyncCallback callback, ! object state) { ! this.checkDisposed(); ! ! if (buffer == null) ! { ! throw new ArgumentNullException("buffer is a null reference."); ! } ! if (offset < 0) ! { ! throw new ArgumentOutOfRangeException("offset is less than 0."); ! } ! if (offset > buffer.Length) ! { ! throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); ! } ! if (count < 0) ! { ! throw new ArgumentOutOfRangeException("count is less than 0."); ! } ! if (count > (buffer.Length - offset)) ! { ! throw new ArgumentOutOfRangeException("count is less than the length of buffer minus the value of the offset parameter."); ! } ! ! lock (this) ! { ! if (!this.context.HandshakeFinished) ! { ! this.doHandshake(); // Handshake negotiation ! } ! } ! ! IAsyncResult asyncResult; ! ! lock (this.read) ! { ! try ! { ! // If actual buffer is full readed reset it ! if (this.inputBuffer.Position == this.inputBuffer.Length && ! this.inputBuffer.Length > 0) ! { ! this.resetBuffer(); ! } ! ! if (!this.context.ConnectionEnd) ! { ! // Check if we have space in the middle buffer ! // if not Read next TLS record and update the inputBuffer ! while ((this.inputBuffer.Length - this.inputBuffer.Position) < count) ! { ! // Read next record and write it into the inputBuffer ! long position = this.inputBuffer.Position; ! byte[] record = this.protocol.ReceiveRecord(); ! ! if (record != null && record.Length > 0) ! { ! // Write new data to the inputBuffer ! this.inputBuffer.Seek(0, SeekOrigin.End); ! this.inputBuffer.Write(record, 0, record.Length); ! ! // Restore buffer position ! this.inputBuffer.Seek(position, SeekOrigin.Begin); ! } ! else ! { ! if (record == null) ! { ! break; ! } ! } ! ! // TODO: Review if we need to check the Length ! // property of the innerStream for other types ! // of streams, to check that there are data available ! // for read ! if (this.innerStream is NetworkStream && ! !((NetworkStream)this.innerStream).DataAvailable) ! { ! break; ! } ! } ! } ! ! asyncResult = this.inputBuffer.BeginRead( ! buffer, offset, count, callback, state); ! } ! catch (TlsException) ! { ! throw new IOException("The authentication or decryption has failed."); ! } ! catch (Exception) ! { ! throw new IOException("IO exception during read."); ! } ! } ! ! return asyncResult; } public override IAsyncResult BeginWrite( ! byte[] buffer, ! int offset, ! int count, ! AsyncCallback callback, ! object state) { ! this.checkDisposed(); ! if (buffer == null) ! { ! throw new ArgumentNullException("buffer is a null reference."); ! } ! if (offset < 0) ! { ! throw new ArgumentOutOfRangeException("offset is less than 0."); ! } ! if (offset > buffer.Length) ! { ! throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); ! } ! if (count < 0) ! { ! throw new ArgumentOutOfRangeException("count is less than 0."); ! } ! if (count > (buffer.Length - offset)) ! { ! throw new ArgumentOutOfRangeException("count is less than the length of buffer minus the value of the offset parameter."); ! } ! ! lock (this) ! { ! if (!this.context.HandshakeFinished) ! { ! // Start handshake negotiation ! this.doHandshake(); ! } ! } ! ! IAsyncResult asyncResult; ! ! lock (this.write) ! { ! try ! { ! // Send the buffer as a TLS record ! ! byte[] record = this.protocol.EncodeRecord( ! TlsContentType.ApplicationData, buffer, offset, count); ! ! asyncResult = this.innerStream.BeginWrite( ! record, 0, record.Length, callback, state); ! } ! catch (TlsException) ! { ! throw new IOException("The authentication or decryption has failed."); ! } ! catch (Exception) ! { ! throw new IOException("IO exception during Write."); ! } ! } ! ! return asyncResult; } public override int EndRead(IAsyncResult asyncResult) { ! this.checkDisposed(); ! ! if (asyncResult == null) ! { ! throw new ArgumentNullException("asyncResult is null or was not obtained by calling BeginRead."); ! } ! ! return this.inputBuffer.EndRead(asyncResult); } public override void EndWrite(IAsyncResult asyncResult) { ! this.checkDisposed(); ! ! if (asyncResult == null) ! { ! throw new ArgumentNullException("asyncResult is null or was not obtained by calling BeginRead."); ! } ! ! this.innerStream.EndWrite (asyncResult); ! } ! ! public override void Close() ! { ! ((IDisposable)this).Dispose(); } public override void Flush() { ! this.checkDisposed(); ! ! this.innerStream.Flush(); } public int Read(byte[] buffer) { ! return this.Read(buffer, 0, buffer.Length); } ! public override int Read(byte[] buffer, int offset, int count) { ! IAsyncResult res = this.BeginRead(buffer, offset, count, null, null); ! ! return this.EndRead(res); } *************** *** 261,265 **** throw new NotSupportedException(); } ! public override void SetLength(long value) { --- 575,579 ---- throw new NotSupportedException(); } ! public override void SetLength(long value) { *************** *** 269,281 **** public void Write(byte[] buffer) { ! throw new NotSupportedException(); } ! public override void Write( ! byte[] buffer, ! int offset, ! int count) { ! throw new NotSupportedException(); } --- 583,657 ---- public void Write(byte[] buffer) { ! this.Write(buffer, 0, buffer.Length); } ! public override void Write(byte[] buffer, int offset, int count) { ! IAsyncResult res = this.BeginWrite (buffer, offset, count, null, null); ! ! this.EndWrite(res); ! } ! ! #endregion ! ! #region Misc Methods ! ! private void resetBuffer() ! { ! this.inputBuffer.SetLength(0); ! this.inputBuffer.Position = 0; ! } ! ! private void checkDisposed() ! { ! if (this.disposed) ! { ! throw new ObjectDisposedException("The SslClientStream is closed."); ! } ! } ! ! #endregion ! ! #region Handsake Methods ! ! /* ! Client Server ! ! ClientHello --------> ! ServerHello ! Certificate* ! ServerKeyExchange* ! CertificateRequest* ! <-------- ServerHelloDone ! Certificate* ! ClientKeyExchange ! CertificateVerify* ! [ChangeCipherSpec] ! Finished --------> ! [ChangeCipherSpec] ! <-------- Finished ! Application Data <-------> Application Data ! ! Fig. 1 - Message flow for a full handshake ! */ ! ! private void doHandshake() ! { ! try ! { ! #warning "Implement server handshake logic" ! ! // Obtain supported cipher suites ! this.context.SupportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(this.context.SecurityProtocol); ! ! // Clear Key Info ! this.context.ClearKeyInfo(); ! ! throw new NotSupportedException(); ! } ! catch ! { ! throw new IOException("The authentication or decryption has failed."); ! } } --- TlsContext.cs DELETED --- |