[prev in list] [next in list] [prev in thread] [next in thread] 

List:       activemq-commits
Subject:    svn commit: r948196 - in
From:       tabish () apache ! org
Date:       2010-05-25 20:17:27
Message-ID: 20100525201727.4A6F323889FA () eris ! apache ! org
[Download RAW message or body]

Author: tabish
Date: Tue May 25 20:17:26 2010
New Revision: 948196

URL: http://svn.apache.org/viewvc?rev=948196&view=rev
Log:
https://issues.apache.org/activemq/browse/AMQCPP-140

Add code to allow the OpenSSLSocket to be used as either a client or a server based \
socket.  

Modified:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.cpp
  activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.h
  activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ssl/SSLSocket.h

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.cpp
                
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/de \
caf/internal/net/ssl/openssl/OpenSSLSocket.cpp?rev=948196&r1=948195&r2=948196&view=diff
 ==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.cpp \
                (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.cpp \
Tue May 25 20:17:26 2010 @@ -35,6 +35,7 @@
 #include <decaf/internal/net/ssl/openssl/OpenSSLSocketException.h>
 #include <decaf/internal/net/ssl/openssl/OpenSSLSocketInputStream.h>
 #include <decaf/internal/net/ssl/openssl/OpenSSLSocketOutputStream.h>
+#include <decaf/util/concurrent/Mutex.h>
 
 using namespace decaf;
 using namespace decaf::lang;
@@ -42,6 +43,7 @@ using namespace decaf::lang::exceptions;
 using namespace decaf::io;
 using namespace decaf::net;
 using namespace decaf::net::ssl;
+using namespace decaf::util::concurrent;
 using namespace decaf::internal;
 using namespace decaf::internal::net;
 using namespace decaf::internal::net::ssl;
@@ -64,10 +66,17 @@ namespace openssl {
 #endif
         bool needsClientAuth;
         bool wantsClientAuth;
+        bool useClientMode;
+        bool handshakeStarted;
+        bool handshakeCompleted;
+        std::string commonName;
+
+        Mutex handshakeLock;
 
     public:
 
-        SocketData() : ssl( NULL ), needsClientAuth( false ), wantsClientAuth( false \
) { +        SocketData() : ssl( NULL ), needsClientAuth( false ), wantsClientAuth( \
false ), +                       useClientMode( true ), handshakeStarted( false ), \
handshakeCompleted( false ) {  }
 
         ~SocketData() {
@@ -139,7 +148,12 @@ void OpenSSLSocket::connect( const std::
     try{
 
 #ifdef HAVE_OPENSSL
+
+        // Perform the actual Socket connection work
         SSLSocket::connect( host, port, timeout );
+
+        // If we actually connected then we can connect the Socket to an OpenSSL
+        // BIO filter so that we can use it in OpenSSL APIs.
         if( isConnected() ) {
 
             BIO* bio = BIO_new( BIO_s_socket() );
@@ -159,26 +173,9 @@ void OpenSSLSocket::connect( const std::
             BIO_set_fd( bio, (int)fd->getValue(), BIO_NOCLOSE );
             SSL_set_bio( this->data->ssl, bio, bio );
 
-            // Since we are a client we want to enforce peer verification, we set a
-            // callback so we can collect data on why a verify failed for debugging.
-            SSL_set_verify( this->data->ssl, SSL_VERIFY_PEER, \
                SocketData::verifyCallback );
-
-            int result = SSL_connect( this->data->ssl );
-
-            // Checks the error status, when things go right we still perform a \
                deeper
-            // check on the provided certificate to ensure that it matches the host \
                name
-            // that we connected to, this prevents someone from using any \
                certificate
-            // signed by a signing authority that we trust.
-            switch( SSL_get_error( this->data->ssl, result ) ) {
-                case SSL_ERROR_NONE:
-                    verifyServerCert( host );
-                    return;
-                case SSL_ERROR_SSL:
-                case SSL_ERROR_ZERO_RETURN:
-                case SSL_ERROR_SYSCALL:
-                    SSLSocket::close();
-                    throw OpenSSLSocketException( __FILE__, __LINE__ );
-            }
+            // Later when startHandshake is called we will check for this common \
name +            // in the provided certificate
+            this->data->commonName = host;
         }
 #else
         throw SocketException( __FILE__, __LINE__, "Not Supported" );
@@ -310,6 +307,123 @@ void OpenSSLSocket::setEnabledProtocols(
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+void OpenSSLSocket::startHandshake() {
+
+    if( !this->isConnected() ) {
+        throw IOException( __FILE__, __LINE__, "Socket is not connected." );
+    }
+
+    if( this->isClosed() ) {
+        throw IOException( __FILE__, __LINE__, "Socket already closed." );
+    }
+
+    try {
+
+        synchronized( &(this->data->handshakeLock ) ) {
+
+            if( this->data->handshakeStarted ) {
+                return;
+            }
+
+            this->data->handshakeStarted = true;
+
+            if( this->data->useClientMode ) {
+
+                // Since we are a client we want to enforce peer verification, we \
set a +                // callback so we can collect data on why a verify failed for \
debugging. +                SSL_set_verify( this->data->ssl, SSL_VERIFY_PEER, \
SocketData::verifyCallback ); +
+                int result = SSL_connect( this->data->ssl );
+
+                // Checks the error status, when things go right we still perform a \
deeper +                // check on the provided certificate to ensure that it \
matches the host name +                // that we connected to, this prevents someone \
from using any certificate +                // signed by a signing authority that we \
trust. +                switch( SSL_get_error( this->data->ssl, result ) ) {
+                    case SSL_ERROR_NONE:
+                        verifyServerCert( this->data->commonName );
+                        std::cout << "OpenSSLSocket::startHandshake() - Verified \
name: " +                                  << this->data->commonName << std::endl;
+                        break;
+                    case SSL_ERROR_SSL:
+                    case SSL_ERROR_ZERO_RETURN:
+                    case SSL_ERROR_SYSCALL:
+                        SSLSocket::close();
+                        throw OpenSSLSocketException( __FILE__, __LINE__ );
+                }
+
+            } else {  // We are in Server Mode.
+
+                int mode = SSL_VERIFY_NONE;
+
+                if( this->data->wantsClientAuth ) {
+                    mode = SSL_VERIFY_PEER;
+                }
+
+                if( this->data->needsClientAuth ) {
+                    mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+                }
+
+                // Since we are a client we want to enforce peer verification, we \
set a +                // callback so we can collect data on why a verify failed for \
debugging. +                SSL_set_verify( this->data->ssl, mode, \
SocketData::verifyCallback ); +
+                int result = SSL_accept( this->data->ssl );
+
+                if( result != SSL_ERROR_NONE ) {
+                    SSLSocket::close();
+                    throw OpenSSLSocketException( __FILE__, __LINE__ );
+                }
+            }
+
+            this->data->handshakeCompleted = true;
+        }
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenSSLSocket::setUseClientMode( bool value ) {
+
+    synchronized( &( this->data->handshakeLock ) ) {
+        if( this->data->handshakeStarted ) {
+            throw IllegalArgumentException(
+                __FILE__, __LINE__, "Handshake has already been started cannot \
change mode." ); +        }
+
+        this->data->useClientMode = value;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool OpenSSLSocket::getUseClientMode() const {
+    return this->data->useClientMode;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenSSLSocket::setNeedClientAuth( bool value ) {
+    this->data->needsClientAuth = value;
+    this->data->wantsClientAuth = false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool OpenSSLSocket::getNeedClientAuth() const {
+    return this->data->needsClientAuth;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenSSLSocket::setWantClientAuth( bool value ) {
+    this->data->wantsClientAuth = value;
+    this->data->needsClientAuth = false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool OpenSSLSocket::getWantClientAuth() const {
+    return this->data->wantsClientAuth;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 int OpenSSLSocket::read( unsigned char* buffer, int size, int offset, int length ) {
 
     try{
@@ -347,6 +461,11 @@ int OpenSSLSocket::read( unsigned char* 
         }
 
 #ifdef HAVE_OPENSSL
+
+        if( !this->data->handshakeCompleted ) {
+            this->startHandshake();
+        }
+
         // Read data from the socket.
         int result = SSL_read( this->data->ssl, buffer + offset, length );
 
@@ -408,6 +527,11 @@ void OpenSSLSocket::write( const unsigne
         }
 
 #ifdef HAVE_OPENSSL
+
+        if( !this->data->handshakeCompleted ) {
+            this->startHandshake();
+        }
+
         int remaining = length;
 
         while( remaining > 0 && !isClosed() ) {

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.h
                
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/de \
caf/internal/net/ssl/openssl/OpenSSLSocket.h?rev=948196&r1=948195&r2=948196&view=diff \
                ==============================================================================
                
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.h \
                (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.h \
Tue May 25 20:17:26 2010 @@ -133,6 +133,41 @@ namespace openssl {
          */
         virtual void setEnabledProtocols( const std::vector<std::string>& protocols \
);  
+        /**
+         * {@inheritDoc}
+         */
+        virtual void startHandshake();
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual void setUseClientMode( bool value );
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual bool getUseClientMode() const;
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual void setNeedClientAuth( bool value );
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual bool getNeedClientAuth() const;
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual void setWantClientAuth( bool value );
+
+        /**
+         * {@inheritDoc}
+         */
+        virtual bool getWantClientAuth() const;
+
     public:
 
         /**

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ssl/SSLSocket.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ssl/SSLSocket.h?rev=948196&r1=948195&r2=948196&view=diff
 ==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ssl/SSLSocket.h \
                (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ssl/SSLSocket.h Tue \
May 25 20:17:26 2010 @@ -124,6 +124,86 @@ namespace ssl {
          */
         virtual void setSSLParameters( const SSLParameters& value );
 
+        /**
+         * Initiates a handshake for this SSL Connection, this can be necessary for \
several reasons such +         * as using new encryption keys, or starting a new \
session. +         *
+         * When called for the first time after the socket connects this method \
blocks until the handshake +         * is completed.  The provider is not require to \
support multiple handshakes and can throw an +         * IOException to indicate an \
error. +         *
+         * @throw IOException if an I/O error occurs while performing the Handshake
+         */
+        virtual void startHandshake() = 0;
+
+        /**
+         * Determines the mode that the socket uses when a handshake is initiated, \
client or server. +         *
+         * This method must be called prior to any handshake attempts on this \
Socket, once a handshake +         * has be initiated this socket remains the the set \
mode; client or server, for the life of +         * this object.
+         *
+         * @param value
+         *      The mode setting, true for client or false for server.
+         *
+         * @throw IllegalArguementException if the handshake process has begun and \
mode is lcoked. +         */
+        virtual void setUseClientMode( bool value ) = 0;
+
+        /**
+         * Gets whether this Socket is in Client or Server mode, true indicates that \
the mode is +         * set to Client.
+         *
+         * @return true if the Socket is in Client mode, false otherwise.
+         */
+        virtual bool getUseClientMode() const = 0;
+
+        /**
+         * Sets the Socket to require that a client authenticate itself by sending a \
valid Certificate that +         * is trusted by this Server mode socket.  This \
option only applies to sockets in the Server mode. +         *
+         * If the option is enabled an the client does not provide a certificate \
then the handshake is +         * considered failed and the connection is refused.  \
Calling this method resets any previous +         * value for this option as well as \
clears any value set in the setWantClientAuth method. +         *
+         * @param value
+         *      The value indicating if a client is required to authenticate itself \
or not. +         */
+        virtual void setNeedClientAuth( bool value ) = 0;
+
+        /**
+         * Returns if this socket is configured to require client authentication, \
true means that is has +         * and that clients that failed to authenticate will \
be rejected.  This option is only useful when +         * the socket is operating in \
server mode. +         *
+         * @return true if client authentication is required.
+         */
+        virtual bool getNeedClientAuth() const = 0;
+
+        /**
+         * Sets the Socket to request that a client authenticate itself by sending a \
valid Certificate that +         * is trusted by this Server mode socket.  This \
option only applies to sockets in the Server mode. +         *
+         * If the option is enabled an the client does not provide a certificate \
then the handshake is +         * considered to have succeeded, if it does send a \
certificate and that certificate is invalid the +         * the handshake will fail.  \
Calling this method resets any previous value for this option as well +         * as \
clears any value set in the setNeedClientAuth method. +         *
+         * @param value
+         *      The value indicating if a client is requested to authenticate itself \
or not. +         */
+        virtual void setWantClientAuth( bool value ) = 0;
+
+        /**
+         * Returns if this socket is configured to request client authentication, \
true means that is has +         * and that clients that failed to authenticate will \
be rejected but that cleints that do not send +         * a certificate are not \
considered to have failed authentication.  This option is only useful when +         \
* the socket is operating in server mode. +         *
+         * @return true if client authentication is required.
+         */
+        virtual bool getWantClientAuth() const = 0;
+
     };
 
 }}}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic