dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/DotGNU.SSL .cvsignore,NONE,1.1 ISecur


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/DotGNU.SSL .cvsignore,NONE,1.1 ISecureSession.cs,NONE,1.1 ISecureSessionProvider.cs,NONE,1.1 Makefile.am,NONE,1.1 OpenSSL.cs,NONE,1.1 Protocol.cs,NONE,1.1 README,NONE,1.1 SSL.build,NONE,1.1 SessionProviderFactory.cs,NONE,1.1 Utils.cs,NONE,1.1
Date: Tue, 27 May 2003 06:35:32 -0400

Update of /cvsroot/dotgnu-pnet/pnetlib/DotGNU.SSL
In directory subversions:/tmp/cvs-serv3265/DotGNU.SSL

Added Files:
        .cvsignore ISecureSession.cs ISecureSessionProvider.cs 
        Makefile.am OpenSSL.cs Protocol.cs README SSL.build 
        SessionProviderFactory.cs Utils.cs 
Log Message:


Add the "DotGNU.SSL" library, wrapped around OpenSSL, for use in
"System.Net" to implement https; add the "sslfetch" sample to
demonstrate how to use it.


--- NEW FILE ---
Makefile
Makefile.in
.deps
*.dll

--- NEW FILE ---
/*
 * ISecureSession.cs - Implementation of the
 *              "DotGNU.SSL.ISecureSession" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

using System;
using System.IO;

/// <summary>
/// <para>The <see cref="T:DotGNU.SSL.ISecureSession"/> interface
/// is implemented by classes that provide secure client or server
/// session functionality to the application program.</para>
/// </summary>
public interface ISecureSession : IDisposable
{
        /// <summary>
        /// <para>Determines if this session is handling a client.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>Returns <see langword="true"/> if this session is
        /// handling a client, or <see langword="false"/> if this session
        /// is handling a server.</para>
        /// </value>
        bool IsClient { get; }

        /// <summary>
        /// <para>Get or set the X.509 certificate for the local machine.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The ASN.1 form of the certificate.</para>
        /// </value>
        ///
        /// <remarks>
        /// <para>This property must be set for server sessions, and for
        /// client sessions that perform client authentication.</para>
        /// </remarks>
        ///
        /// <exception cref="T:System.ArgumentNullException">
        /// <para>The supplied value was <see langword="null"/>.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.ArgumentException">
        /// <para>The supplied value was not a valid certificate.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.InvalidOperationException">
        /// <para>The certificate was already set previously, or
        /// the handshake has already been performed.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.ObjectDisposedException">
        /// <para>The secure session has been disposed.</para>
        /// </exception>
        byte[] Certificate { get; set; }

        /// <summary>
        /// <para>Get or set the private key for the local machine.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The ASN.1 form of the RSA private key.</para>
        /// </value>
        ///
        /// <remarks>
        /// <para>This property must be set for server sessions, and for
        /// client sessions that perform client authentication.</para>
        /// </remarks>
        ///
        /// <exception cref="T:System.ArgumentNullException">
        /// <para>The supplied value was <see langword="null"/>.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.ArgumentException">
        /// <para>The supplied value was not a valid private key.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.InvalidOperationException">
        /// <para>The private key was already set previously, or
        /// the handshake has already been performed.</para>
        /// </exception>
        ///
        /// <exception cref="T:System.ObjectDisposedException">
        /// <para>The secure session has been disposed.</para>
        /// </exception>
        byte[] PrivateKey { get; set; }

        /// <summary>
        /// <para>Get the certificate of the remote host once the
        /// secure connection has been established.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The ASN.1 form of the certificate, or <see langword="null"/>
        /// if the secure connection has not yet been established.</para>
        /// </value>
        byte[] RemoteCertificate { get; }

        /// <summary>
        /// <para>Perform the initial handshake on a
        /// <see cref="T:System.Net.Sockets.Socket"/> instance and
        /// return a stream that can be used for secure communications.</para>
        /// </summary>
        ///
        /// <param name="socket">
        /// <para>The socket to use for the underlying communications channel.
        /// </para>
        /// </param>
        ///
        /// <exception name="T:System.ArgumentNullException">
        /// <para>The <paramref name="socket"/> parameter is
        /// <see langword="null"/>.</para>
        /// </exception>
        ///
        /// <exception name="T:System.ArgumentException">
        /// <para>The <paramref name="socket"/> parameter is not a
        /// valid socket object.</para>
        /// </exception>
        ///
        /// <exception name="T:System.InvalidOperationException">
        /// <para>The handshake has already been performed.</para>
        /// </exception>
        ///
        /// <exception name="T:System.NotSupportedException">
        /// <para>The secure handshake could not be performed because
        /// the necessary provider objects could not be created.
        /// Usually this is because the provider is out of memory.</para>
        /// </exception>
        ///
        /// <exception name="T:System.ObjectDisposedException">
        /// <para>The secure session has been disposed.</para>
        /// </exception>
        ///
        /// <exception name="T:System.Security.SecurityException">
        /// <para>Some kind of security error occurred while attempting
        /// to establish the secure connection.</para>
        /// </exception>
        Stream PerformHandshake(Object socket);

        /// <summary>
        /// <para>Get the secure communications stream.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>Returns the secure communications stream, or
        /// <see langword="null"/> if the handshake has not yet
        /// been performed.</para>
        /// </value>
        Stream SecureStream { get; }

}; // interface ISecureSession

}; // namespace DotGNU.SSL

--- NEW FILE ---
/*
 * ISecureSessionProvider.cs - Implementation of the
 *              "DotGNU.SSL.ISecureSessionProvider" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

using System;

/// <summary>
/// <para>The <see cref="T:DotGNU.SSL.ISecureSessionProvider"/> interface
/// is implemented by classes that wish to provide secure session
/// functionality to the application program.</para>
/// </summary>
public interface ISecureSessionProvider
{
        /// <summary>
        /// <para>Create a new session handling object for a client,
        /// to allow it to connect to a secure server.</para>
        /// </summary>
        ///
        /// <param name="protocol">
        /// <para>Specifies the <see cref="T:DotGNU.SSL.Protocol"/> to use to
        /// connect to the server.</para>
        /// </param>
        ///
        /// <returns>
        /// <para>Returns the session object.</para>
        /// </returns>
        ///
        /// <exception cref="T:System.NotSupportedException">
        /// <para>The requested protocol is not supported.</para>
        /// </exception>
        ISecureSession CreateClientSession(Protocol protocol);

        /// <summary>
        /// <para>Create a new session handling object for a server,
        /// to allow it to process incoming requests from a secure 
client.</para>
        /// </summary>
        ///
        /// <param name="protocol">
        /// <para>Specifies the <see cref="T:DotGNU.SSL.Protocol"/> that the
        /// client is allowed to use when connecting.</para>
        /// </param>
        ///
        /// <returns>
        /// <para>Returns the session object.</para>
        /// </returns>
        ///
        /// <exception cref="T:System.NotSupportedException">
        /// <para>The requested protocol is not supported.</para>
        /// </exception>
        ISecureSession CreateServerSession(Protocol protocol);

}; // interface ISecureSessionProvider

}; // namespace DotGNU.SSL

--- NEW FILE ---

.PHONY: DotGNU.SSL.dll

all-local: DotGNU.SSL.dll

DotGNU.SSL.dll:
        "$(CSANT)" $(CSANT_FLAGS) -f SSL.build all

CLEANFILES = DotGNU.SSL.dll

pnetassembliesdir = $(libdir)/cscc/lib
pnetassemblies_DATA = DotGNU.SSL.dll

--- NEW FILE ---
/*
 * OpenSSL.cs - Implementation of the "DotGNU.SSL.OpenSSL" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

#if CONFIG_RUNTIME_INFRA

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;

// Secure session provider object that uses the OpenSSL library to
// provide the underlying security functionality.

internal sealed class OpenSSL : ISecureSessionProvider
{
        // Internal state.
        private static bool initialized = false;

        // Constructor.
        public OpenSSL()
                        {
                                // Make sure that the OpenSSL library is 
initialized.
                                lock(typeof(OpenSSL))
                                {
                                        if(!initialized)
                                        {
                                                try
                                                {
                                                        
SSL_load_error_strings();
                                                        SSL_library_init();
                                                }
                                                catch(NotImplementedException)
                                                {
                                                        // Could not find the 
functions to execute,
                                                        // so we probably don't 
have OpenSSL on this
                                                        // system or it isn't 
on the LD_LIBRARY_PATH.
                                                        throw new 
NotSupportedException();
                                                }
                                                initialized = true;
                                        }
                                }
                        }

        // Implement the ISecureSessionProvider interface.
        public ISecureSession CreateClientSession(Protocol protocol)
                        {
                                IntPtr method;
                                IntPtr ctx;

                                // Get the method handler for the protocol.
                                try
                                {
                                        switch(protocol)
                                        {
                                                case Protocol.AutoDetect:
                                                {
                                                        method = 
SSLv23_client_method();
                                                }
                                                break;
        
                                                case Protocol.SSLv2:
                                                {
                                                        method = 
SSLv2_client_method();
                                                }
                                                break;
        
                                                case Protocol.SSLv3:
                                                {
                                                        method = 
SSLv3_client_method();
                                                }
                                                break;
        
                                                case Protocol.TLSv1:
                                                {
                                                        method = 
TLSv1_client_method();
                                                }
                                                break;

                                                default:
                                                {
                                                        method = IntPtr.Zero;
                                                }
                                                break;
                                        }
                                }
                                catch(NotImplementedException)
                                {
                                        // The entry point does not exist in 
the library.
                                        method = IntPtr.Zero;
                                }
                                if(method == IntPtr.Zero)
                                {
                                        throw new NotSupportedException();
                                }

                                // Create the OpenSSL context for the session.
                                ctx = SSL_CTX_new(method);
                                if(ctx == IntPtr.Zero)
                                {
                                        throw new NotSupportedException();
                                }

                                // Wrap the context object and return it.
                                return new OpenSSLSession(ctx, true);
                        }
        public ISecureSession CreateServerSession(Protocol protocol)
                        {
                                IntPtr method;
                                IntPtr ctx;

                                // Get the method handler for the protocol.
                                try
                                {
                                        switch(protocol)
                                        {
                                                case Protocol.AutoDetect:
                                                {
                                                        method = 
SSLv23_server_method();
                                                }
                                                break;
        
                                                case Protocol.SSLv2:
                                                {
                                                        method = 
SSLv2_server_method();
                                                }
                                                break;
        
                                                case Protocol.SSLv3:
                                                {
                                                        method = 
SSLv3_server_method();
                                                }
                                                break;
        
                                                case Protocol.TLSv1:
                                                {
                                                        method = 
TLSv1_server_method();
                                                }
                                                break;

                                                default:
                                                {
                                                        method = IntPtr.Zero;
                                                }
                                                break;
                                        }
                                }
                                catch(NotImplementedException)
                                {
                                        // The entry point does not exist in 
the library.
                                        method = IntPtr.Zero;
                                }
                                if(method == IntPtr.Zero)
                                {
                                        throw new NotSupportedException();
                                }

                                // Create the OpenSSL context for the session.
                                ctx = SSL_CTX_new(method);
                                if(ctx == IntPtr.Zero)
                                {
                                        throw new NotSupportedException();
                                }

                                // Wrap the context object and return it.
                                return new OpenSSLSession(ctx, false);
                        }

        // Session handling object for OpenSSL.
        private sealed class OpenSSLSession : ISecureSession, IDisposable
        {
                // Internal state.
                private IntPtr ctx;
                private bool isClient;
                private byte[] certificate;
                private byte[] privateKey;
                private byte[] remoteCertificate;
                private OpenSSLStream stream;

                // Constructor.
                public OpenSSLSession(IntPtr ctx, bool isClient)
                                {
                                        this.ctx = ctx;
                                        this.isClient = isClient;
                                }

                // Destructor.
                ~OpenSSLSession()
                                {
                                        Dispose();
                                }

                // Implement the ISecureSession interface.
                public bool IsClient
                                {
                                        get
                                        {
                                                return isClient;
                                        }
                                }
                public byte[] Certificate
                                {
                                        get
                                        {
                                                return certificate;
                                        }
                                        set
                                        {
                                                lock(this)
                                                {
                                                        if(value == null)
                                                        {
                                                                throw new 
ArgumentNullException("value");
                                                        }
                                                        if(certificate != null)
                                                        {
                                                                throw new 
InvalidOperationException();
                                                        }
                                                        if(ctx == IntPtr.Zero)
                                                        {
                                                                throw new 
ObjectDisposedException("session");
                                                        }
                                                        certificate = value;
                                                        
if(SSL_CTX_use_certificate_ASN1
                                                                        (ctx, 
value, value.Length) == 0)
                                                        {
                                                                throw new 
ArgumentException();
                                                        }
                                                }
                                        }
                                }
                public byte[] PrivateKey
                                {
                                        get
                                        {
                                                return privateKey;
                                        }
                                        set
                                        {
                                                lock(this)
                                                {
                                                        if(value == null)
                                                        {
                                                                throw new 
ArgumentNullException("value");
                                                        }
                                                        if(privateKey != null)
                                                        {
                                                                throw new 
InvalidOperationException();
                                                        }
                                                        if(ctx == IntPtr.Zero)
                                                        {
                                                                throw new 
ObjectDisposedException("session");
                                                        }
                                                        privateKey = value;
                                                        
if(SSL_CTX_use_RSAPrivateKey_ASN1
                                                                        (ctx, 
value, value.Length) == 0)
                                                        {
                                                                throw new 
ArgumentException();
                                                        }
                                                }
                                        }
                                }
                public byte[] RemoteCertificate
                                {
                                        get
                                        {
                                                return remoteCertificate;
                                        }
                                }
                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();
                                                }
                                                if(ctx == IntPtr.Zero)
                                                {
                                                        throw new 
ObjectDisposedException("session");
                                                }

                                                // Create the SSL session 
control object.
                                                IntPtr ssl = SSL_new(ctx);
                                                if(ssl == IntPtr.Zero)
                                                {
                                                        throw new 
NotSupportedException();
                                                }

                                                // Create a socket BIO object 
and set it.
                                                IntPtr bio = BIO_new_socket(fd, 
0);
                                                if(bio == IntPtr.Zero)
                                                {
                                                        SSL_free(ssl);
                                                        throw new 
NotSupportedException();
                                                }
                                                SSL_set_bio(ssl, bio, bio);

                                                // Attempt to connect or accept.
                                                int result;
                                                if(isClient)
                                                {
                                                        result = 
SSL_connect(ssl);
                                                }
                                                else
                                                {
                                                        result = 
SSL_accept(ssl);
                                                }
                                                if(result != 1)
                                                {
                                                        SSL_free(ssl);
                                                        throw new 
SecurityException();
                                                }

                                                // Get the remote certificate 
and record it.
                                                IntPtr x509 = 
SSL_get_peer_certificate(ssl); 
                                                if(x509 != IntPtr.Zero)
                                                {
                                                        int length = 
i2d_X509(x509, IntPtr.Zero);
                                                        if(length > 0)
                                                        {
                                                                IntPtr data = 
Marshal.AllocHGlobal(length);
                                                                if(data != 
IntPtr.Zero)
                                                                {
                                                                        IntPtr 
temp = data;
                                                                        
i2d_X509(x509, ref temp);
                                                                        
remoteCertificate = new byte [length];
                                                                        
Marshal.Copy(data, remoteCertificate,
                                                                                
                 0, length);
                                                                        
Marshal.FreeHGlobal(data);
                                                                }
                                                        }
                                                        X509_free(x509);
                                                }

                                                // Create the stream object and 
return it.
                                                stream = new OpenSSLStream(ssl);
                                                return stream;
                                        }
                                }
                public Stream SecureStream
                                {
                                        get
                                        {
                                                return stream;
                                        }
                                }

                // Implement the IDisposable interface.
                public void Dispose()
                                {
                                        lock(this)
                                        {
                                                if(ctx != IntPtr.Zero)
                                                {
                                                        SSL_CTX_free(ctx);
                                                        ctx = IntPtr.Zero;
                                                }
                                        }
                                }

        }; // class OpenSSLSession

        // Stream object for managing a secure connection.
        private sealed class OpenSSLStream : Stream
        {
                // Internal state.
                private IntPtr ssl;

                // Constructor.
                public OpenSSLStream(IntPtr ssl)
                                {
                                        this.ssl = ssl;
                                }

                // Destructor.
                ~OpenSSLStream()
                                {
                                        Close();
                                }

                // Close the stream.
                public override void Close()
                                {
                                        lock(this)
                                        {
                                                if(ssl != IntPtr.Zero)
                                                {
                                                        int result = 
SSL_shutdown(ssl);
                                                        if(result == 0)
                                                        {
                                                                // 
Bi-directional shutdown is required.
                                                                result = 
SSL_shutdown(ssl);
                                                        }
                                                        SSL_free(ssl);
                                                        ssl = IntPtr.Zero;
                                                        if(result < 0)
                                                        {
                                                                // The shutdown 
failed, probably because
                                                                // there is a 
security problem with the
                                                                // data that 
was transmitted.
                                                                throw new 
SecurityException();
                                                        }
                                                }
                                        }
                                }

                // Flush the pending contents in this stream.
                public override void Flush()
                                {
                                        // Nothing to do here.
                                }

                // Read data from this stream.
                public override int Read(byte[] buffer, int offset, int count)
                                {
                                        Utils.ValidateBuffer(buffer, offset, 
count);
                                        lock(this)
                                        {
                                                if(ssl == IntPtr.Zero)
                                                {
                                                        throw new 
ObjectDisposedException("stream");
                                                }
                                                if(offset == 0)
                                                {
                                                        return SSL_read(ssl, 
buffer, count);
                                                }
                                                else
                                                {
                                                        byte[] temp = new byte 
[count];
                                                        int result = 
SSL_read(ssl, temp, count);
                                                        if(result > 0)
                                                        {
                                                                
Array.Copy(temp, 0, buffer, offset, result);
                                                        }
                                                        Array.Clear(temp, 0, 
count);
                                                        return result;
                                                }
                                        }
                                }

                // Seek to a new position within this stream.
                public override long Seek(long offset, SeekOrigin origin)
                                {
                                        throw new NotSupportedException();
                                }

                // Set the length of this stream.
                public override void SetLength(long value)
                                {
                                        throw new NotSupportedException();
                                }

                // Write a buffer of bytes to this stream.
                public override void Write(byte[] buffer, int offset, int count)
                                {
                                        Utils.ValidateBuffer(buffer, offset, 
count);
                                        lock(this)
                                        {
                                                if(ssl == IntPtr.Zero)
                                                {
                                                        throw new 
ObjectDisposedException("stream");
                                                }
                                                if(offset == 0)
                                                {
                                                        SSL_write(ssl, buffer, 
count);
                                                }
                                                else if(count > 0)
                                                {
                                                        byte[] temp = new byte 
[count];
                                                        Array.Copy(buffer, 
offset, temp, 0, count);
                                                        SSL_write(ssl, temp, 
count);
                                                        Array.Clear(temp, 0, 
count);
                                                }
                                        }
                                }

                // Determine if it is possible to read from this stream.
                public override bool CanRead
                                {
                                        get
                                        {
                                                return true;
                                        }
                                }

                // Determine if it is possible to seek within this stream.
                public override bool CanSeek
                                {
                                        get
                                        {
                                                return false;
                                        }
                                }

                // Determine if it is possible to write to this stream.
                public override bool CanWrite
                                {
                                        get
                                        {
                                                return true;
                                        }
                                }

                // Get the length of this stream.
                public override long Length
                                {
                                        get
                                        {
                                                throw new 
NotSupportedException();
                                        }
                                }

                // Get the current position within the stream.
                public override long Position
                                {
                                        get
                                        {
                                                throw new 
NotSupportedException();
                                        }
                                        set
                                        {
                                                throw new 
NotSupportedException();
                                        }
                                }

        }; // class OpenSSLStream

        // Import the functions we need from the OpenSSL library.

        [DllImport("ssl")]
        extern private static int SSL_library_init();

        [DllImport("ssl")]
        extern private static void SSL_load_error_strings();

        [DllImport("ssl")]
        extern private static IntPtr SSLv2_client_method();

        [DllImport("ssl")]
        extern private static IntPtr SSLv2_server_method();

        [DllImport("ssl")]
        extern private static IntPtr SSLv3_client_method();

        [DllImport("ssl")]
        extern private static IntPtr SSLv3_server_method();

        [DllImport("ssl")]
        extern private static IntPtr TLSv1_client_method();

        [DllImport("ssl")]
        extern private static IntPtr TLSv1_server_method();

        [DllImport("ssl")]
        extern private static IntPtr SSLv23_client_method();

        [DllImport("ssl")]
        extern private static IntPtr SSLv23_server_method();

        [DllImport("ssl")]
        extern private static IntPtr SSL_CTX_new(IntPtr method);

        [DllImport("ssl")]
        extern private static void SSL_CTX_free(IntPtr ctx);

        [DllImport("ssl")]
        extern private static int SSL_CTX_use_certificate_ASN1
                        (IntPtr ctx, byte[] d, int len);

        [DllImport("ssl")]
        extern private static int SSL_CTX_use_RSAPrivateKey_ASN1
                        (IntPtr ctx, byte[] d, int len);

        [DllImport("ssl")]
        extern private static IntPtr SSL_new(IntPtr ctx);

        [DllImport("ssl")]
        extern private static void SSL_free(IntPtr ssl);

        [DllImport("ssl")]
        extern private static void SSL_set_bio
                                (IntPtr ssl, IntPtr rbio, IntPtr wbio);

        [DllImport("ssl")]
        extern private static int SSL_connect(IntPtr ssl);

        [DllImport("ssl")]
        extern private static int SSL_accept(IntPtr ssl);

        [DllImport("ssl")]
        extern private static int SSL_shutdown(IntPtr ssl);

        [DllImport("ssl")]
        extern private static int SSL_read(IntPtr ssl, byte[] buf, int num);

        [DllImport("ssl")]
        extern private static int SSL_write(IntPtr ssl, byte[] buf, int num);

        [DllImport("ssl")]
        extern private static IntPtr SSL_get_peer_certificate(IntPtr ssl);

        [DllImport("ssl")]
        extern private static IntPtr BIO_new_socket(int sock, int close_flag);

        [DllImport("ssl")]
        extern private static int i2d_X509(IntPtr x509, IntPtr buf);

        [DllImport("ssl")]
        extern private static int i2d_X509(IntPtr x509, ref IntPtr buf);

        [DllImport("ssl")]
        extern private static void X509_free(IntPtr x509);

}; // class OpenSSL

#endif // CONFIG_RUNTIME_INFRA

}; // namespace DotGNU.SSL

--- NEW FILE ---
/*
 * Protocol.cs - Implementation of the "DotGNU.SSL.Protocol" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

/// <summary>
/// <para>The <see cref="T:DotGNU.SSL.Protocol"/> enumeration specifies
/// which protocol to use when establishing or accepting a secure
/// connection.</para>
/// </summary>
public enum Protocol
{
        /// <summary>
        /// <para>Accept any protocol, be it SSLv2, SSLv3, or TLSv1.
        /// The client and server will negotiate the best protocol.</para>
        /// </summary>
        AutoDetect,

        /// <summary>
        /// <para>Use the SSLv2 protocol only.</para>
        /// </summary>
        SSLv2,

        /// <summary>
        /// <para>Use the SSLv3 protocol only.</para>
        /// </summary>
        SSLv3,

        /// <summary>
        /// <para>Use the TLSv1 protocol only.</para>
        /// </summary>
        TLSv1

}; // enum Protocol

}; // namespace DotGNU.SSL

--- NEW FILE ---

DotGNU Session Session Library
==============================

Legal matters
-------------

The DotGNU.SSL library is distributed under the full terms of the
GNU General Public License, with the following two exemptions:

        The library may be used within pnetlib to provide "https" functionality
        via the "System.Net" namespace.  Such use does not create any
        additional obligations on user applications than pnetlib's license does.

        This library has the additional exemption that compiling, linking, 
and/or
        using OpenSSL with it is permitted.

In all other situations, the full GPL is in force.  In particular, if
you use DotGNU.SSL directly in your own application (not via "System.Net"),
then your application must be released under the GPL also.

Quick start guide
-----------------

The DotGNU.SSL library hides the details of the underlying SSL
implementation (e.g. OpenSSL) in such a way that it should be easy
to replace it with some other SSL implementation in the future.
The library can also support multiple SSL providers.

The first step in creating a secure session is to obtain a provider:

        using DotGNU.SSL;

        ISecureSessionProvider provider = SecureSessionFactory.GetProvider();

In this case, we have chosen to use the default SSL session provider.
With multiple providers, you can supply a string argument to "GetProvider"
to specify which provider you desire.

The next step is to obtain a session object from your selected provider.
There are two kinds of sessions: client and server.  We will create a
client session that uses TLS version 1:

        ISecureSession session = provider.CreateClientSession(Protocol.TLSv1);

At this point, we can set session options or can continue on to the
session handshake phase:

        Stream secureStream = session.PerformHandshake(socket);

The "socket" value must be an instance of "System.Net.Sockets.Socket".
The "PerformHandshake" method will return a new stream, that you use for
secure communications, or it will throw an exception if the handshake failed.

Once you have finished with secure communications, clean everything up
as follows:

        secureStream.Close();
        session.Dispose();

Note: "secureStream.Close()" just closes the security portions of the
session.  It doesn't close the underlying "stream" object.  You will
need to do that yourself separately.

See the "SSLSample.cs" file for a more complete example of using DotGNU.SSL.

--- NEW FILE ---
<?xml version="1.0"?>
<project name="pnetlib DotGNU.SSL" default="all">
        <target name="all">

                <!-- Build the primary DotGNU.SSL.dll library -->
                <compile output="DotGNU.SSL.dll"
                                 target="library"
                                 unsafe="true"
                                 nostdlib="true"
                                 debug="${CONFIG_DEBUG_LINES}"
                                 optimize="true">

                        <sources>
                                <includes name="**/*.cs"/>
                        </sources>

                        <references>
                                <file name="../runtime/mscorlib.dll"/>
                        </references>

                        <arg compiler="cscc" value="-Wno-empty-input"/>
                        <arg compiler="cscc" value="-fminimize-parameters"/>
                        <arg compiler="csc" value="/nowarn:626"/>
                        <arg compiler="csc" value="/nowarn:649"/>
                        <arg compiler="csc" value="/nowarn:168"/>
                        <arg compiler="csc" value="/nowarn:67"/>
                        <arg compiler="csc" value="/nowarn:169"/>
                        <arg compiler="csc" value="/nowarn:679"/>
                </compile>

        </target>
</project>

--- NEW FILE ---
/*
 * SessionProviderFactory.cs - Implementation of the
 *              "DotGNU.SSL.SessionProviderFactory" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

/// <summary>
/// <para>The <see cref="T:DotGNU.SSL.SessionProviderFactory"/> class is used
/// to get an initial <see cref="T:DotGNU.SSL.ISecureSessionProvider"/>
/// instance, with which secure sessions can be established.</para>
/// </summary>
public sealed class SessionProviderFactory
{
        // This class cannot be instantiated.
        private SessionProviderFactory() {}

        /// <summary>
        /// <para>Get a secure session provider with a specific name.</para>
        /// </summary>
        ///
        /// <param name="name">
        /// <para>The name of the provider to use, or <see langword="null"/>
        /// to get the default provider.  An example of a name might be
        /// <c>"OpenSSL"</c>.</para>
        /// </param>
        ///
        /// <returns>
        /// <para>The selected provider instance.</para>
        /// </returns>
        ///
        /// <exception cref="T:System.NotSupportedException">
        /// <para>The specified provider is not supported, or there are
        /// no secure session providers on the system.</para>
        /// </exception>
        public static ISecureSessionProvider GetProvider(String name)
                        {
                        #if CONFIG_RUNTIME_INFRA
                                if(name == null || name == "OpenSSL")
                                {
                                        // Note: the OpenSSL constructor may 
throw
                                        // NotSupportedException if the OpenSSL 
library
                                        // is not available on the underlying 
OS.
                                        return new OpenSSL();
                                }
                        #endif // CONFIG_RUNTIME_INFRA
                                throw new NotSupportedException();
                        }

        /// <summary>
        /// <para>Get the default secure session provider.</para>
        /// </summary>
        ///
        /// <returns>
        /// <para>The default provider instance.</para>
        /// </returns>
        ///
        /// <remarks>
        /// <para>This method is equivalent to <c>GetProvider(null)</c>.</para>
        /// </remarks>
        ///
        /// <exception cref="T:System.NotSupportedException">
        /// <para>There are no secure session providers on the system.</para>
        /// </exception>
        public static ISecureSessionProvider GetProvider()
                        {
                                return GetProvider(null);
                        }

        /// <summary>
        /// <para>Get the names of all session providers on the system.</para>
        /// </summary>
        ///
        /// <returns>
        /// <para>An array of session provider names.</para>
        /// </returns>
        public static String[] GetProviders()
                        {
                                return new String[] {"OpenSSL"};
                        }

}; // class SessionProviderFactory

}; // namespace DotGNU.SSL

--- NEW FILE ---
/*
 * Utils.cs - Implementation of the "DotGNU.SSL.Utils" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software, you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace DotGNU.SSL
{

using System.Reflection;

internal sealed class Utils
{
        // This class cannot be instantiated.
        private Utils() {}

        // Get the operating system file descriptor for a "Socket" object.
        // Returns -1 if the socket object doesn't have a valid descriptor.
        internal static int GetSocketFd(Object socket)
                        {
                                // This is ugly, but is needed until we get 
recursive
                                // assemblies working to break the circular 
dependency
                                // between System.Net and DotGNU.SSL.
                                if(socket == null)
                                {
                                        return -1;
                                }
                        #if CONFIG_REFLECTION
                                Object handle = socket.GetType().InvokeMember
                                                ("Handle",
                                                 BindingFlags.GetProperty |
                                                        BindingFlags.Public |
                                                        BindingFlags.Instance,
                                                 null, socket, null, null, 
null, null);
                                if(handle is IntPtr)
                                {
                                        return 
unchecked((int)(((IntPtr)handle).ToInt64()));
                                }
                        #endif
                                return -1;
                        }

        // Helper method for validating buffer arguments.
        internal static void ValidateBuffer(byte[] buffer, int offset, int 
count)
                        {
                                if(buffer == null)
                                {
                                        throw new 
ArgumentNullException("buffer");
                                }
                                else if(offset < 0 || offset > buffer.Length)
                                {
                                        throw new ArgumentOutOfRangeException();
                                }
                                else if(count < 0)
                                {
                                        throw new ArgumentOutOfRangeException();
                                }
                                else if((buffer.Length - offset) < count)
                                {
                                        throw new ArgumentException();
                                }
                        }

}; // class Utils

}; // namespace DotGNU.SSL





reply via email to

[Prev in Thread] Current Thread [Next in Thread]