Hello Atsushi,

On Thu, 2007-08-23 at 16:04 +0900, Atsushi Eno wrote:
> Hello,
> 
> I have created a System.Net.Security.SslStream implementation, which
> is based on Mono.Security.Protocol.Tls.

Nice work :)

> It requires some Makefile changes (due to cyclic dependency foo).

This is kind of strange as System.dll (v2) already depends on
Mono.Security.dll

> I have also created a few port of Mono.Security sample tools (which
> are found in Mono.Security/Test/tools) to verify SslStream behavior.
> 
> There are some issues (grep MonoTODO and FIXME) e.g. it requires
> X509Certificate2 due to certificate population in Mono.Security
> (I doubt that it could be solved without changing Mono.Security
> internals).

a few things inline

> If it looks good I'll check it in svn (probably port of those
> "tools" as well).
> 
> Atsushi Eno
> plain text document attachment (sslstream.patch)
> Index: Makefile
> ===================================================================
> --- Makefile  (revision 84522)
> +++ Makefile  (working copy)
> @@ -40,6 +40,8 @@
>  SECURITY_DEP_FILE := $(wildcard ../lib/$(PROFILE)/$(SECURITY_DEP))
>  CONFIGURATION_DEP := System.Configuration.dll
>  CONFIGURATION_DEP_FILE := $(wildcard ../lib/$(PROFILE)/$(CONFIGURATION_DEP))
> +PREBUILT_DEP := System.dll
> +PREBUILT_DEP_FILE := $(wildcard ../lib/$(PROFILE)/$(PREBUILT_DEP))
>  CYCLIC_DEPS += $(SECURITY_DEP) $(CONFIGURATION_DEP)
>  CYCLIC_DEP_FILES += $(SECURITY_DEP_FILE) $(CONFIGURATION_DEP_FILE)
>  LIB_MCS_FLAGS = -nowarn:618 -d:CONFIGURATION_2_0 -unsafe 
> $(RESOURCE_FILES:%=-resource:%)
> @@ -95,10 +97,14 @@
>  endif
>  
>  ifdef CONFIGURATION_DEP_FILE
> -LIB_MCS_FLAGS += -define:CONFIGURATION_DEP -r:$(CONFIGURATION_DEP) 
> -r:PrebuiltSystem=$(topdir)/class/lib/$(PROFILE)/System.dll
> +LIB_MCS_FLAGS += -define:CONFIGURATION_DEP -r:$(CONFIGURATION_DEP)
>  $(the_lib): $(CONFIGURATION_DEP_FILE)
>  endif
>  
> +ifdef PREBUILT_DEP_FILE
> +LIB_MCS_FLAGS += -r:PrebuiltSystem=$(topdir)/class/lib/$(PROFILE)/System.dll
> +endif
> +
>  $(test_lib): $(test_lib).config $(TEST_RESOURCES)
>  
>  $(test_lib).config: Test/test-config-file
> Index: System.Net.Security/SslStream.cs
> ===================================================================
> --- System.Net.Security/SslStream.cs  (revision 84522)
> +++ System.Net.Security/SslStream.cs  (working copy)
> @@ -3,9 +3,10 @@
>  //
>  // Authors:
>  //   Tim Coleman ([EMAIL PROTECTED])
> +//   Atsushi Enomoto ([EMAIL PROTECTED])
>  //
>  // Copyright (C) Tim Coleman, 2004
> -// (c) 2004 Novell, Inc. (http://www.novell.com)
> +// (c) 2004,2007 Novell, Inc. (http://www.novell.com)
>  //
>  
>  //
> @@ -29,7 +30,8 @@
>  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>  //
>  
> -#if NET_2_0 
> +#if NET_2_0 && SECURITY_DEP
> +extern alias PrebuiltSystem;
>  
>  using System;
>  using System.IO;
> @@ -37,44 +39,61 @@
>  using System.Security.Authentication;
>  using System.Security.Cryptography.X509Certificates;
>  using System.Security.Principal;
> +using System.Security.Cryptography;
> +using Mono.Security.Protocol.Tls;
>  
> +using CipherAlgorithmType = 
> System.Security.Authentication.CipherAlgorithmType;
> +using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
> +using ExchangeAlgorithmType = 
> System.Security.Authentication.ExchangeAlgorithmType;
> +
> +using MonoCipherAlgorithmType = 
> Mono.Security.Protocol.Tls.CipherAlgorithmType;
> +using MonoHashAlgorithmType = Mono.Security.Protocol.Tls.HashAlgorithmType;
> +using MonoExchangeAlgorithmType = 
> Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
> +using MonoSecurityProtocolType = 
> Mono.Security.Protocol.Tls.SecurityProtocolType;
> +
> +using X509CertificateCollection = 
> PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
> +
>  namespace System.Net.Security 
>  {
> +     [MonoLimitation ("Non-X509Certificate2 certificate is not supported")]

The original X509Certificate is busted, design-wise, wrt to the private
key.

>       public class SslStream : AuthenticatedStream
>       {
>               #region Fields
>  
> -             int readTimeout;
> -             int writeTimeout;
> +             int read_timeout;
> +             int write_timeout;
> +             SslStreamBase ssl_stream;
> +             RemoteCertificateValidationCallback validation_callback;
> +             LocalCertificateSelectionCallback selection_callback;
>  
>               #endregion // Fields
>  
>               #region Constructors
>  
> -             [MonoTODO]
>               public SslStream (Stream innerStream)
> -                     : base (innerStream, false)
> +                     : this (innerStream, false)
>               {
>               }
>  
> -             [MonoTODO]
>               public SslStream (Stream innerStream, bool leaveStreamOpen)
>                       : base (innerStream, leaveStreamOpen)
>               {
>               }
> -#if SECURITY_DEP
> -             [MonoTODO]
> +
> +             [MonoTODO ("certValidationCallback is not passed X509Chain and 
> SslPolicyErrors correctly")]
>               public SslStream (Stream innerStream, bool leaveStreamOpen, 
> RemoteCertificateValidationCallback certValidationCallback)
> -                     : base (innerStream, leaveStreamOpen)
> +                     : this (innerStream, leaveStreamOpen, 
> certValidationCallback, null)
>               {
>               }
>  
> -             [MonoTODO]
> +             [MonoTODO ("certValidationCallback is not passed X509Chain and 
> SslPolicyErrors correctly")]
>               public SslStream (Stream innerStream, bool leaveStreamOpen, 
> RemoteCertificateValidationCallback certValidationCallback, 
> LocalCertificateSelectionCallback certSelectionCallback)
>                       : base (innerStream, leaveStreamOpen)
>               {
> +                     // they are nullable.
> +                     validation_callback = certValidationCallback;
> +                     selection_callback = certSelectionCallback;
>               }
> -#endif
>               #endregion // Constructors
>  
>               #region Properties
> @@ -87,231 +106,420 @@
>                       get { return InnerStream.CanSeek; }
>               }
>  
> -             [MonoTODO]
>               public override bool CanTimeout {
> -                     get { throw new NotImplementedException (); }
> +                     get { return InnerStream.CanTimeout; }
>               }
>  
>               public override bool CanWrite {
>                       get { return InnerStream.CanWrite; }
>               }
>  
> -             [MonoTODO]
> -             public virtual bool CheckCertRevocationStatus {
> -                     get { throw new NotImplementedException (); }
> +             public override long Length {
> +                     get { return InnerStream.Length; }
>               }
>  
> -             [MonoTODO]
> -             public virtual CipherAlgorithmType CipherAlgorithm  {
> -                     get { throw new NotImplementedException (); }
> +             public override long Position {
> +                     get { return InnerStream.Position; }
> +                     set {
> +                             throw new NotSupportedException ("This stream 
> does not support seek operations");
> +                     }
>               }
>  
> -             [MonoTODO]
> -             public virtual int CipherStrength  {
> -                     get { throw new NotImplementedException (); }
> -             }
> +             // AuthenticatedStream overrides
>  
> -             [MonoTODO]
> -             public virtual HashAlgorithmType HashAlgorithm  {
> -                     get { throw new NotImplementedException (); }
> -             }
> -
> -             [MonoTODO]
> -             public virtual int HashStrength  {
> -                     get { throw new NotImplementedException (); }
> -             }
> -
> -             [MonoTODO]
>               public override bool IsAuthenticated { 
> -                     get { throw new NotImplementedException (); }
> +                     get { return ssl_stream != null; }
>               }
>  
> -             [MonoTODO]
>               public override bool IsEncrypted { 
> -                     get { throw new NotImplementedException (); }
> +                     get { return IsAuthenticated; }
>               }
>  
> -             [MonoTODO]
>               public override bool IsMutuallyAuthenticated { 
> -                     get { throw new NotImplementedException (); }
> +                     get { return IsAuthenticated && (IsServer ? 
> RemoteCertificate != null : LocalCertificate != null); }
>               }
>  
> -             [MonoTODO]
>               public override bool IsServer { 
> -                     get { throw new NotImplementedException (); }
> +                     get { return ssl_stream is SslServerStream; }
>               }
>  
> -             [MonoTODO]
>               public override bool IsSigned { 
> -                     get { throw new NotImplementedException (); }
> +                     get { return IsAuthenticated; }
>               }
>  
> -             [MonoTODO]
> -             public virtual ExchangeAlgorithmType KeyExchangeAlgorithm { 
> -                     get { throw new NotImplementedException (); }
> +             [MonoTODO ("The property exists but not supported")]

Since it's an override over Stream.ReadTimeout can't the original (base)
do the job ?

> +             public override int ReadTimeout {
> +                     get { return read_timeout; }
> +                     set { read_timeout = value; }
>               }
>  
> -             [MonoTODO]
> -             public virtual int KeyExchangeStrength { 
> -                     get { throw new NotImplementedException (); }
> +             [MonoTODO ("The property exists but not supported")]

same

> +             public override int WriteTimeout {
> +                     get { return write_timeout; }
> +                     set { write_timeout = value; }
>               }
>  
> -             public override long Length {
> -                     get { return InnerStream.Length; }
> +             // SslStream
> +
> +             public virtual bool CheckCertRevocationStatus {
> +                     get {
> +                             if (!IsAuthenticated)
> +                                     return false;
> +
> +                             return ssl_stream.CheckCertRevocationStatus;
> +                     }
>               }
>  
> -             [MonoTODO]
> -             public virtual X509Certificate LocalCertificate {
> -                     get { throw new NotImplementedException (); }
> +             public virtual CipherAlgorithmType CipherAlgorithm  {
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             switch (ssl_stream.CipherAlgorithm) {
> +                             case MonoCipherAlgorithmType.Des:
> +                                     return CipherAlgorithmType.Des;
> +                             case MonoCipherAlgorithmType.None:
> +                                     return CipherAlgorithmType.None;
> +                             case MonoCipherAlgorithmType.Rc2:
> +                                     return CipherAlgorithmType.Rc2;
> +                             case MonoCipherAlgorithmType.Rc4:
> +                                     return CipherAlgorithmType.Rc4;
> +                             case MonoCipherAlgorithmType.SkipJack:
> +                                     break;
> +                             case MonoCipherAlgorithmType.TripleDes:
> +                                     return CipherAlgorithmType.TripleDes;
> +                             case MonoCipherAlgorithmType.Rijndael:
> +                                     switch (ssl_stream.CipherStrength) {
> +                                     case 128:
> +                                             return 
> CipherAlgorithmType.Aes128;
> +                                     case 192:
> +                                             return 
> CipherAlgorithmType.Aes192;
> +                                     case 256:
> +                                             return 
> CipherAlgorithmType.Aes256;
> +                                     }
> +                                     break;
> +                             }
> +
> +                             throw new InvalidOperationException ("Not 
> supported cipher algorithm is in use. It is likely a bug in SslStream.");
> +                     }
>               }
>  
> -             public override long Position {
> -                     get { return InnerStream.Position; }
> -                     set { InnerStream.Position = value; }
> +             public virtual int CipherStrength  {
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             return ssl_stream.CipherStrength;
> +                     }
>               }
>  
> -             public override int ReadTimeout {
> -                     get { return readTimeout; }
> -                     set { readTimeout = value; }
> +             public virtual HashAlgorithmType HashAlgorithm  {
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             switch (ssl_stream.HashAlgorithm) {
> +                             case MonoHashAlgorithmType.Md5:
> +                                     return HashAlgorithmType.Md5;
> +                             case MonoHashAlgorithmType.None:
> +                                     return HashAlgorithmType.None;
> +                             case MonoHashAlgorithmType.Sha1:
> +                                     return HashAlgorithmType.Sha1;
> +                             }
> +
> +                             throw new InvalidOperationException ("Not 
> supported hash algorithm is in use. It is likely a bug in SslStream.");
> +                     }
>               }
>  
> -             [MonoTODO]
> +             public virtual int HashStrength  {
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             return ssl_stream.HashStrength;
> +                     }
> +             }
> +
> +             public virtual ExchangeAlgorithmType KeyExchangeAlgorithm { 
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             switch (ssl_stream.KeyExchangeAlgorithm) {
> +                             case MonoExchangeAlgorithmType.DiffieHellman:
> +                                     return 
> ExchangeAlgorithmType.DiffieHellman;
> +                             case MonoExchangeAlgorithmType.Fortezza:
> +                                     break;
> +                             case MonoExchangeAlgorithmType.None:
> +                                     return ExchangeAlgorithmType.None;
> +                             case MonoExchangeAlgorithmType.RsaKeyX:
> +                                     return ExchangeAlgorithmType.RsaKeyX;
> +                             case MonoExchangeAlgorithmType.RsaSign:
> +                                     return ExchangeAlgorithmType.RsaSign;
> +                             }
> +
> +                             throw new InvalidOperationException ("Not 
> supported exchange algorithm is in use. It is likely a bug in SslStream.");
> +                     }
> +             }
> +
> +             public virtual int KeyExchangeStrength { 
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             return ssl_stream.KeyExchangeStrength;
> +                     }
> +             }
> +
> +             public virtual X509Certificate LocalCertificate {
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             return IsServer ? ssl_stream.ServerCertificate 
> : ((SslClientStream) ssl_stream).SelectedClientCertificate;
> +                     }
> +             }
> +
>               public virtual X509Certificate RemoteCertificate {
> -                     get { throw new NotImplementedException (); }
> +                     get {
> +                             CheckConnectionAuthenticated ();
> +
> +                             return !IsServer ? ssl_stream.ServerCertificate 
> : ((SslServerStream) ssl_stream).ClientCertificate;
> +                     }
>               }
>  
> -             [MonoTODO]
>               public virtual SslProtocols SslProtocol {
> -                     get { throw new NotImplementedException (); }
> -             }
> +                     get {
> +                             CheckConnectionAuthenticated ();
>  
> -             public override int WriteTimeout {
> -                     get { return writeTimeout; }
> -                     set { writeTimeout = value; }
> +                             switch (ssl_stream.SecurityProtocol) {
> +                             case MonoSecurityProtocolType.Default:
> +                                     return SslProtocols.Default;
> +                             case MonoSecurityProtocolType.Ssl2:
> +                                     return SslProtocols.Ssl2;
> +                             case MonoSecurityProtocolType.Ssl3:
> +                                     return SslProtocols.Ssl3;
> +                             case MonoSecurityProtocolType.Tls:
> +                                     return SslProtocols.Tls;
> +                             }
> +
> +                             throw new InvalidOperationException ("Not 
> supported SSL/TLS protocol is in use. It is likely a bug in SslStream.");
> +                     }
>               }
>  
>               #endregion // Properties
>  
>               #region Methods
>  
> -             [MonoTODO]
> +             AsymmetricAlgorithm GetPrivateKey (X509Certificate cert, string 
> targetHost)
> +             {
> +                     // FIXME: what can I do for non-X509Certificate2 ?
nothing, MS can't do much either. It will find a private key *if* the
X509Certificate exists in the CryptoAPI key store (associated to the
certificate store) but the X509Store class (2.0) deals with
X509Certificate2 so...
> +                     X509Certificate2 cert2 = cert as X509Certificate2;
> +                     return cert2 != null ? cert2.PrivateKey : null;
> +             }
> +
> +             X509Certificate OnCertificateSelection 
> (X509CertificateCollection clientCerts, X509Certificate serverCert, string 
> targetHost, X509CertificateCollection serverRequestedCerts)
> +             {
> +                     string [] acceptableIssuers = new string 
> [serverRequestedCerts != null ? serverRequestedCerts.Count : 0];
> +                     for (int i = 0; i < acceptableIssuers.Length; i++)
> +                             acceptableIssuers [i] = serverRequestedCerts 
> [i].GetIssuerName ();
> +                     return selection_callback (this, targetHost, 
> clientCerts, serverCert, acceptableIssuers);
> +             }
> +
>               public virtual IAsyncResult BeginAuthenticateAsClient (string 
> targetHost, AsyncCallback asyncCallback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     return BeginAuthenticateAsClient (targetHost, new 
> X509CertificateCollection (), SslProtocols.Tls, false, asyncCallback, 
> asyncState);
>               }
>  
> -             [MonoTODO]
>               public virtual IAsyncResult BeginAuthenticateAsClient (string 
> targetHost, X509CertificateCollection clientCertificates, SslProtocols 
> sslProtocolType, bool checkCertificateRevocation, AsyncCallback 
> asyncCallback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     if (IsAuthenticated)
> +                             throw new InvalidOperationException ("This 
> SslStream is already authenticated");
> +
> +                     SslClientStream s = new SslClientStream (InnerStream,  
> targetHost, !LeaveInnerStreamOpen, GetMonoSslProtocol (sslProtocolType), 
> clientCertificates);
> +                     s.CheckCertRevocationStatus = 
> checkCertificateRevocation;
> +
> +                     // Due to the Mono.Security internal, it cannot reuse
> +                     // the delegated argument, as Mono.Security creates 
> +                     // another instance of X509Certificate which lacks 
> +                     // private key but is filled the private key via this
> +                     // delegate.
this could be changed, in the 2.0 profile, as the Mono.Security version
of X509Certificate is private-key aware.
> 
> +                     s.PrivateKeyCertSelectionDelegate = delegate 
> (X509Certificate cert, string host) {
> +                             string hash = cert.GetCertHashString ();
> +                             // ... so, we cannot use the delegate argument.
> +                             foreach (X509Certificate cc in 
> clientCertificates) {
> +                                     if (cc.GetCertHashString () != hash)
> +                                             continue;
> +                                     X509Certificate2 cert2 = cc as 
> X509Certificate2;
> +                                     cert2 = cert2 ?? new X509Certificate2 
> (cc);
> +                                     return cert2.PrivateKey;
> +                             }
> +                             return null;
> +                     };
> +
> +                     if (validation_callback != null)

The X509Chain inside System.dll is more RFC3280 compliant than the
(older) one provided in Mono.Security.dll and should be used.

> +                             s.ServerCertValidationDelegate = delegate 
> (X509Certificate cert, int [] certErrors) {
> +                                     // FIXME: X509Chain is not provided
> +                                     // FIXME: SslPolicyErrors is incomplete
> +                                     SslPolicyErrors errors = 
> certErrors.Length > 0 ? SslPolicyErrors.RemoteCertificateChainErrors : 
> SslPolicyErrors.None;
> +                                     return validation_callback (this, cert, 
> null, errors);
> +                             };
> +                     if (selection_callback != null)
> +                             s.ClientCertSelectionDelegate = 
> OnCertificateSelection;
> +
> +                     ssl_stream = s;
> +
> +                     return BeginWrite (new byte [0], 0, 0, asyncCallback, 
> asyncState);
>               }
>  
> -             [MonoTODO]
>               public override IAsyncResult BeginRead (byte[] buffer, int 
> offset, int count, AsyncCallback asyncCallback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     return ssl_stream.BeginRead (buffer, offset, count, 
> asyncCallback, asyncState);
>               }
>  
> -             [MonoTODO]
>               public virtual IAsyncResult BeginAuthenticateAsServer 
> (X509Certificate serverCertificate, AsyncCallback callback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     return BeginAuthenticateAsServer (serverCertificate, 
> false, SslProtocols.Tls, false, callback, asyncState);
>               }
>  
> -             [MonoTODO]
>               public virtual IAsyncResult BeginAuthenticateAsServer 
> (X509Certificate serverCertificate, bool clientCertificateRequired, 
> SslProtocols sslProtocolType, bool checkCertificateRevocation, AsyncCallback 
> callback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     if (IsAuthenticated)
> +                             throw new InvalidOperationException ("This 
> SslStream is already authenticated");
> +
> +                     SslServerStream s = new SslServerStream (InnerStream, 
> serverCertificate, clientCertificateRequired, !LeaveInnerStreamOpen, 
> GetMonoSslProtocol (sslProtocolType));
> +                     s.CheckCertRevocationStatus = 
> checkCertificateRevocation;
> +                     // Due to the Mono.Security internal, it cannot reuse
> +                     // the delegated argument, as Mono.Security creates 
> +                     // another instance of X509Certificate which lacks 
> +                     // private key but is filled the private key via this
> +                     // delegate.
same
> +                     s.PrivateKeyCertSelectionDelegate = delegate 
> (X509Certificate cert, string targetHost) {
> +                             // ... so, we cannot use the delegate argument.
> +                             X509Certificate2 cert2 = serverCertificate as 
> X509Certificate2 ?? new X509Certificate2 (serverCertificate);
> +                             return cert2 != null ? cert2.PrivateKey : null;
> +                     };
> +
> +                     if (validation_callback != null)
> +                             s.ClientCertValidationDelegate = delegate 
> (X509Certificate cert, int [] certErrors) {
> +                                     // FIXME: X509Chain is not provided
> +                                     // FIXME: SslPolicyErrors is incomplete
> +                                     SslPolicyErrors errors = 
> certErrors.Length > 0 ? SslPolicyErrors.RemoteCertificateChainErrors : 
> SslPolicyErrors.None;
> +                                     return validation_callback (this, cert, 
> null, errors);
> +                             };
> +
> +                     ssl_stream = s;
> +
> +                     return BeginRead (new byte [0], 0, 0, callback, 
> asyncState);
>               }
>  
> -             [MonoTODO]
> +             MonoSecurityProtocolType GetMonoSslProtocol (SslProtocols ms)
> +             {
> +                     switch (ms) {
> +                     case SslProtocols.Ssl2:
> +                             return MonoSecurityProtocolType.Ssl2;
> +                     case SslProtocols.Ssl3:
> +                             return MonoSecurityProtocolType.Ssl3;
> +                     case SslProtocols.Tls:
> +                             return MonoSecurityProtocolType.Tls;
> +                     default:
> +                             return MonoSecurityProtocolType.Default;
> +                     }
> +             }
> +
>               public override IAsyncResult BeginWrite (byte[] buffer, int 
> offset, int count, AsyncCallback asyncCallback, object asyncState)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     return ssl_stream.BeginWrite (buffer, offset, count, 
> asyncCallback, asyncState);
>               }
>  
> -             [MonoTODO]
>               public virtual void AuthenticateAsClient (string targetHost)
>               {
> -                     throw new NotImplementedException ();
> +                     AuthenticateAsClient (targetHost, new 
> X509CertificateCollection (), SslProtocols.Tls, false);
>               }
>  
> -             [MonoTODO]
>               public virtual void AuthenticateAsClient (string targetHost, 
> X509CertificateCollection clientCertificates, SslProtocols sslProtocolType, 
> bool checkCertificateRevocation)
>               {
> -                     throw new NotImplementedException ();
> +                     EndAuthenticateAsClient (BeginAuthenticateAsClient (
> +                             targetHost, clientCertificates, 
> sslProtocolType, checkCertificateRevocation, null, null));
>               }
>  
> -             [MonoTODO]
>               public virtual void AuthenticateAsServer (X509Certificate 
> serverCertificate)
>               {
> -                     throw new NotImplementedException ();
> +                     AuthenticateAsServer (serverCertificate, false, 
> SslProtocols.Tls, false);
>               }
>  
> -             [MonoTODO]
>               public virtual void AuthenticateAsServer (X509Certificate 
> serverCertificate, bool clientCertificateRequired, SslProtocols 
> sslProtocolType, bool checkCertificateRevocation)
>               {
> -                     throw new NotImplementedException ();
> +                     EndAuthenticateAsServer (BeginAuthenticateAsServer (
> +                             serverCertificate, clientCertificateRequired, 
> sslProtocolType, checkCertificateRevocation, null, null));
>               }
>  
> -             [MonoTODO]
>               protected override void Dispose (bool disposing)
>               {
> +                     if (disposing) {
> +                             if (ssl_stream != null)
> +                                     ssl_stream.Dispose ();
> +                             ssl_stream = null;
> +                     }
>                       base.Dispose (disposing);
>               }
>  
> -             [MonoTODO]
>               public virtual void EndAuthenticateAsClient (IAsyncResult 
> asyncResult)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     if (CanRead)
> +                             ssl_stream.EndRead (asyncResult);
> +                     else
> +                             ssl_stream.EndWrite (asyncResult);
>               }
>  
> -             [MonoTODO]
> -             public override int EndRead (IAsyncResult asyncResult)
> +             public virtual void EndAuthenticateAsServer (IAsyncResult 
> asyncResult)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     if (CanRead)
> +                             ssl_stream.EndRead (asyncResult);
> +                     else
> +                             ssl_stream.EndWrite (asyncResult);
>               }
>  
> -             [MonoTODO]
> -             public virtual void EndAuthenticateAsServer (IAsyncResult 
> asyncResult)
> +             public override int EndRead (IAsyncResult asyncResult)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     return ssl_stream.EndRead (asyncResult);
>               }
>  
> -             [MonoTODO]
>               public override void EndWrite (IAsyncResult asyncResult)
>               {
> -                     throw new NotImplementedException ();
> +                     CheckConnectionAuthenticated ();
> +
> +                     ssl_stream.EndWrite (asyncResult);
>               }
>  
> -             [MonoTODO]
>               public override void Flush ()
>               {
> +                     CheckConnectionAuthenticated ();
> +
>                       InnerStream.Flush ();
>               }
>  
> -             [MonoTODO]
>               public override int Read (byte[] buffer, int offset, int count)
>               {
> -                     throw new NotImplementedException ();
> +                     return EndRead (BeginRead (buffer, offset, count, null, 
> null));
>               }
>  
> -             [MonoTODO]
>               public override long Seek (long offset, SeekOrigin origin)
>               {
> -                     throw new NotImplementedException ();
> +                     throw new NotSupportedException ("This stream does not 
> support seek operations");
>               }
>  
> -             [MonoTODO]
>               public override void SetLength (long value)
>               {
> -                     throw new NotImplementedException ();
> +                     InnerStream.SetLength (value);
>               }
>  
> -             [MonoTODO]
>               public override void Write (byte[] buffer, int offset, int 
> count)
>               {
> -                     throw new NotImplementedException ();
> +                     EndWrite (BeginWrite (buffer, offset, count, null, 
> null));
>               }
>  
>               public void Write (byte[] buffer)
> @@ -319,6 +527,12 @@
>                       Write (buffer, 0, buffer.Length);
>               }
>  
> +             void CheckConnectionAuthenticated ()
> +             {
> +                     if (!IsAuthenticated)
> +                             throw new InvalidOperationException ("This 
> operation is invalid until it is successfully authenticated");
> +             }
> +
>               #endregion // Methods
>       }
>  }
> Index: System.Net.Security/LocalCertificateSelectionCallback.cs
> ===================================================================
> --- System.Net.Security/LocalCertificateSelectionCallback.cs  (revision 84522)
> +++ System.Net.Security/LocalCertificateSelectionCallback.cs  (working copy)
> @@ -29,10 +29,13 @@
>  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>  //
>  
> -#if NET_2_0 
> +#if NET_2_0 && SECURITY_DEP
> +extern alias PrebuiltSystem;
>  
>  using System.Security.Cryptography.X509Certificates;
>  
> +using X509CertificateCollection = 
> PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
> +
>  namespace System.Net.Security 
>  {
>       public delegate X509Certificate LocalCertificateSelectionCallback (
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to