public Stream PerformHandshake(Object socket) { lock(this) { // Validate the parameter and state. if(socket == null) { throw new ArgumentNullException("socket"); } int fd = Utils.GetSocketFd(socket); if(fd == -1) { throw new ArgumentException(); } if(stream != null) { throw new InvalidOperationException(); } // Allocate and set the credentials object. GNUTLSCredentials cred; if(certificate != null && privateKey != null) { cred = new GNUTLSCertificateCredentials (certificate, privateKey); } else { cred = new GNUTLSAnonCredentials(); } if(cred.Cred == IntPtr.Zero) { throw new NotSupportedException(); } // Initialize the session object. IntPtr session = IntPtr.Zero; if(isClient) { gnutls_init(ref session, (Int)2 /* GNUTLS_CLIENT */); } else { gnutls_init(ref session, (Int)1 /* GNUTLS_SERVER */); } if(session == IntPtr.Zero) { cred.Dispose(); throw new NotSupportedException(); } // Set the default priority values and then // override for the protocol specifics. gnutls_set_default_priority(session); gnutls_certificate_type_set_priority (session, new Int [] {(Int)1, (Int)2, (Int)0}); switch(protocol) { case Protocol.AutoDetect: { // The defaults are already set up for this. } break; // Note: GNUTLS does not support SSLv2, so // we use SSLv3 in that case. case Protocol.SSLv2: case Protocol.SSLv3: { gnutls_protocol_set_priority (session, new Int [] {(Int)1, (Int)0}); } break; case Protocol.TLSv1: { gnutls_protocol_set_priority (session, new Int [] {(Int)2, (Int)0}); } break; default: { // Don't know what protocol to use. gnutls_deinit(session); cred.Dispose(); throw new NotSupportedException(); } } // Set the local X.509 credentials if necessary. gnutls_credentials_set (session, (Int)(cred.CredType), cred.Cred); // Associate the socket fd with the session. gnutls_transport_set_ptr(session, new IntPtr(fd)); // Attempt to connect or accept. int result = (int)gnutls_handshake(session); if(result < 0) { gnutls_deinit(session); cred.Dispose(); throw new SecurityException (gnutls_strerror((Int)result)); } // Get the remote certificate and record it. UInt size; gnutls_datum *x509 = gnutls_certificate_get_peers (session, out size); if(x509 != null) { int length = (int)(x509->size); if(length > 0) { remoteCertificate = new byte [length]; Marshal.Copy(x509->data, remoteCertificate, 0, length); } } // Create the stream object and return it. stream = new GNUTLSStream(session, cred); return stream; } }
public Stream PerformHandshake(Object socket) { lock (this) { // Validate the parameter and state. if (socket == null) { throw new ArgumentNullException("socket"); } int fd = Utils.GetSocketFd(socket); if (fd == -1) { throw new ArgumentException(); } if (stream != null) { throw new InvalidOperationException(); } // Allocate and set the credentials object. GNUTLSCredentials cred; if (certificate != null && privateKey != null) { cred = new GNUTLSCertificateCredentials (certificate, privateKey); } else { cred = new GNUTLSAnonCredentials(); } if (cred.Cred == IntPtr.Zero) { throw new NotSupportedException(); } // Initialize the session object. IntPtr session = IntPtr.Zero; if (isClient) { gnutls_init(ref session, (Int)2 /* GNUTLS_CLIENT */); } else { gnutls_init(ref session, (Int)1 /* GNUTLS_SERVER */); } if (session == IntPtr.Zero) { cred.Dispose(); throw new NotSupportedException(); } // Set the default priority values and then // override for the protocol specifics. gnutls_set_default_priority(session); gnutls_certificate_type_set_priority (session, new Int [] { (Int)1, (Int)2, (Int)0 }); switch (protocol) { case Protocol.AutoDetect: { // The defaults are already set up for this. } break; // Note: GNUTLS does not support SSLv2, so // we use SSLv3 in that case. case Protocol.SSLv2: case Protocol.SSLv3: { gnutls_protocol_set_priority (session, new Int [] { (Int)1, (Int)0 }); } break; case Protocol.TLSv1: { gnutls_protocol_set_priority (session, new Int [] { (Int)2, (Int)0 }); } break; default: { // Don't know what protocol to use. gnutls_deinit(session); cred.Dispose(); throw new NotSupportedException(); } } // Set the local X.509 credentials if necessary. gnutls_credentials_set (session, (Int)(cred.CredType), cred.Cred); // Associate the socket fd with the session. gnutls_transport_set_ptr(session, new IntPtr(fd)); // Attempt to connect or accept. int result = (int)gnutls_handshake(session); if (result < 0) { gnutls_deinit(session); cred.Dispose(); throw new SecurityException (gnutls_strerror((Int)result)); } // Get the remote certificate and record it. UInt size; gnutls_datum *x509 = gnutls_certificate_get_peers (session, out size); if (x509 != null) { int length = (int)(x509->size); if (length > 0) { remoteCertificate = new byte [length]; Marshal.Copy(x509->data, remoteCertificate, 0, length); } } // Create the stream object and return it. stream = new GNUTLSStream(session, cred); return(stream); } }