Moved chain building and validation from Mono.Security to System
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / SslStreamBase.cs
index d236029c3e92196c61f1e470fbdebfd0249da8ac..f347ccb2bdf72f6e32c170de56b59e468f05f6a5 100644 (file)
@@ -1,6 +1,6 @@
 // Transport Security Layer (TLS)
 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
-
+// Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -39,6 +39,8 @@ namespace Mono.Security.Protocol.Tls
                
                #region Fields
 
+               static ManualResetEvent record_processing = new ManualResetEvent (true);
+
                private const int WaitTimeOut = 5 * 60 * 1000;
 
                internal Stream innerStream;
@@ -183,6 +185,8 @@ namespace Mono.Security.Protocol.Tls
                                                                                                                        X509CertificateCollection serverRequestedCertificates);
 
                internal abstract bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors);
+               internal abstract ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection);
+               internal abstract bool HaveRemoteValidation2Callback { get; }
 
                internal abstract AsymmetricAlgorithm OnLocalPrivateKeySelection(X509Certificate certificate, string targetHost);
 
@@ -203,6 +207,11 @@ namespace Mono.Security.Protocol.Tls
                        return OnRemoteCertificateValidation(certificate, errors);
                }
 
+               internal ValidationResult RaiseRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
+               {
+                       return OnRemoteCertificateValidation2 (collection);
+               }
+
                internal AsymmetricAlgorithm RaiseLocalPrivateKeySelection(
                        X509Certificate certificate,
                        string targetHost)
@@ -225,7 +234,7 @@ namespace Mono.Security.Protocol.Tls
                        {
                                if (this.context.HandshakeState == HandshakeState.Finished)
                                {
-                                       return this.context.Cipher.CipherAlgorithmType;
+                                       return this.context.Current.Cipher.CipherAlgorithmType;
                                }
 
                                return CipherAlgorithmType.None;
@@ -238,7 +247,7 @@ namespace Mono.Security.Protocol.Tls
                        {
                                if (this.context.HandshakeState == HandshakeState.Finished)
                                {
-                                       return this.context.Cipher.EffectiveKeyBits;
+                                       return this.context.Current.Cipher.EffectiveKeyBits;
                                }
 
                                return 0;
@@ -251,7 +260,7 @@ namespace Mono.Security.Protocol.Tls
                        {
                                if (this.context.HandshakeState == HandshakeState.Finished)
                                {
-                                       return this.context.Cipher.HashAlgorithmType;
+                                       return this.context.Current.Cipher.HashAlgorithmType;
                                }
 
                                return HashAlgorithmType.None;
@@ -264,7 +273,7 @@ namespace Mono.Security.Protocol.Tls
                        {
                                if (this.context.HandshakeState == HandshakeState.Finished)
                                {
-                                       return this.context.Cipher.HashSize * 8;
+                                       return this.context.Current.Cipher.HashSize * 8;
                                }
 
                                return 0;
@@ -290,7 +299,7 @@ namespace Mono.Security.Protocol.Tls
                        {
                                if (this.context.HandshakeState == HandshakeState.Finished)
                                {
-                                       return this.context.Cipher.ExchangeAlgorithmType;
+                                       return this.context.Current.Cipher.ExchangeAlgorithmType;
                                }
 
                                return ExchangeAlgorithmType.None;
@@ -569,6 +578,9 @@ namespace Mono.Security.Protocol.Tls
                        return asyncResult;
                }
 
+               // bigger than max record length for SSL/TLS
+               private byte[] recbuf = new byte[16384];
+
                private void InternalBeginRead(InternalAsyncResult asyncResult)
                {
                        try
@@ -602,9 +614,6 @@ namespace Mono.Security.Protocol.Tls
                                }
                                else if (!this.context.ConnectionEnd)
                                {
-                                       // bigger than max record length for SSL/TLS
-                                       byte[] recbuf = new byte[16384];
-
                                        // this will read data from the network until we have (at least) one
                                        // record to send back to the caller
                                        this.innerStream.BeginRead(recbuf, 0, recbuf.Length,
@@ -899,7 +908,7 @@ namespace Mono.Security.Protocol.Tls
 
                public override void Close()
                {
-                       ((IDisposable)this).Dispose();
+                       base.Close ();
                }
 
                public override void Flush()
@@ -946,6 +955,7 @@ namespace Mono.Security.Protocol.Tls
 
                        lock (this.read) {
                                try {
+                                       record_processing.Reset ();
                                        // do we already have some decrypted data ?
                                        if (this.inputBuffer.Position > 0) {
                                                // or maybe we used all the buffer before ?
@@ -953,8 +963,10 @@ namespace Mono.Security.Protocol.Tls
                                                        this.inputBuffer.SetLength (0);
                                                } else {
                                                        int n = this.inputBuffer.Read (buffer, offset, count);
-                                                       if (n > 0)
+                                                       if (n > 0) {
+                                                               record_processing.Set ();
                                                                return n;
+                                                       }
                                                }
                                        }
 
@@ -965,7 +977,16 @@ namespace Mono.Security.Protocol.Tls
                                                        needMoreData = false;
                                                        // if we loop, then it either means we need more data
                                                        byte[] recbuf = new byte[16384];
-                                                       int n = innerStream.Read (recbuf, 0, recbuf.Length);
+                                                       int n = 0;
+                                                       if (count == 1) {
+                                                               int value = innerStream.ReadByte ();
+                                                               if (value >= 0) {
+                                                                       recbuf[0] = (byte) value;
+                                                                       n = 1;
+                                                               }
+                                                       } else {
+                                                               n = innerStream.Read (recbuf, 0, recbuf.Length);
+                                                       }
                                                        if (n > 0) {
                                                                // Add the new received data to the waiting data
                                                                if ((recordStream.Length > 0) && (recordStream.Position != recordStream.Length))
@@ -973,12 +994,12 @@ namespace Mono.Security.Protocol.Tls
                                                                recordStream.Write (recbuf, 0, n);
                                                        } else {
                                                                // or that the read operation is done (lost connection in the case of a network stream).
+                                                               record_processing.Set ();
                                                                return 0;
                                                        }
                                                }
 
                                                bool dataToReturn = false;
-                                               long pos = recordStream.Position;
 
                                                recordStream.Position = 0;
                                                byte[] record = null;
@@ -1022,7 +1043,9 @@ namespace Mono.Security.Protocol.Tls
                                                        if (dataToReturn) {
                                                                // we have record(s) to return -or- no more available to read from network
                                                                // reset position for further reading
-                                                               return this.inputBuffer.Read (buffer, offset, count);
+                                                               int i = inputBuffer.Read (buffer, offset, count);
+                                                               record_processing.Set ();
+                                                               return i;
                                                        }
                                                }
                                        }
@@ -1036,7 +1059,6 @@ namespace Mono.Security.Protocol.Tls
                                        throw new IOException("IO exception during read.", ex);
                                }
                        }
-                       return 0;
                }
 
                public override long Seek(long offset, SeekOrigin origin)
@@ -1145,13 +1167,7 @@ namespace Mono.Security.Protocol.Tls
                        this.Dispose(false);
                }
 
-               public void Dispose()
-               {
-                       this.Dispose(true);
-                       GC.SuppressFinalize(this);
-               }
-
-               protected virtual void Dispose(bool disposing)
+               protected override void Dispose (bool disposing)
                {
                        if (!this.disposed)
                        {
@@ -1177,6 +1193,7 @@ namespace Mono.Security.Protocol.Tls
                                }
 
                                this.disposed = true;
+                               base.Dispose (disposing);
                        }
                }