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;
					}
				}
Beispiel #2
0
            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);
                }
            }