summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorAnthony Neal <aneal@zeroc.com>2002-02-15 15:36:54 +0000
committerAnthony Neal <aneal@zeroc.com>2002-02-15 15:36:54 +0000
commit99cec34e98a3f6c5a861e5770219f7785ba29456 (patch)
treef363e279380b5d78bb4cb480637c6174bb37e9a6 /cpp/src
parentbug fix for command-line arg parsing (diff)
downloadice-99cec34e98a3f6c5a861e5770219f7785ba29456.tar.bz2
ice-99cec34e98a3f6c5a861e5770219f7785ba29456.tar.xz
ice-99cec34e98a3f6c5a861e5770219f7785ba29456.zip
Added functionality for certificate verification, and certificate
verifiers. Added implementation of Base64 encoding to IceUtil. Added the RSA Certificate abstraction and RSA Certificate Generation class. Installed initial hooks into Glacier for certificate generation.
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Glacier/GlacierI.cpp58
-rw-r--r--cpp/src/Glacier/GlacierI.h5
-rw-r--r--cpp/src/Ice/SslCertificateVerifier.cpp20
-rw-r--r--cpp/src/Ice/SslCertificateVerifier.h39
-rw-r--r--cpp/src/Ice/SslCertificateVerifierF.h39
-rw-r--r--cpp/src/Ice/SslCertificateVerifierOpenSSL.cpp44
-rw-r--r--cpp/src/Ice/SslCertificateVerifierOpenSSL.h50
-rw-r--r--cpp/src/Ice/SslConnection.cpp11
-rw-r--r--cpp/src/Ice/SslConnection.h18
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSL.cpp146
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSL.h35
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSLClient.cpp6
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSLClient.h2
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSLF.h42
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSLServer.cpp6
-rw-r--r--cpp/src/Ice/SslConnectionOpenSSLServer.h2
-rw-r--r--cpp/src/Ice/SslFactory.cpp33
-rw-r--r--cpp/src/Ice/SslFactory.h16
-rw-r--r--cpp/src/Ice/SslRSACertificateGen.cpp253
-rw-r--r--cpp/src/Ice/SslRSAKeyPair.cpp181
-rw-r--r--cpp/src/Ice/SslSystem.cpp55
-rw-r--r--cpp/src/Ice/SslSystem.h24
-rw-r--r--cpp/src/Ice/SslSystemOpenSSL.cpp415
-rw-r--r--cpp/src/Ice/SslSystemOpenSSL.h2
-rw-r--r--cpp/src/Ice/ice.dsp64
-rw-r--r--cpp/src/IceUtil/Base64.cpp265
-rw-r--r--cpp/src/IceUtil/iceutil.dsp8
27 files changed, 1429 insertions, 410 deletions
diff --git a/cpp/src/Glacier/GlacierI.cpp b/cpp/src/Glacier/GlacierI.cpp
index 31402be91f3..463339d9bf6 100644
--- a/cpp/src/Glacier/GlacierI.cpp
+++ b/cpp/src/Glacier/GlacierI.cpp
@@ -10,7 +10,8 @@
#include <IceUtil/UUID.h>
#include <Glacier/GlacierI.h>
-#include <fcntl.h>
+#include <fcntl.h>
+#include <Ice/SslRSAKeyPair.h>
//#include <sys/wait.h>
#ifdef WIN32
@@ -19,7 +20,10 @@
using namespace std;
using namespace Ice;
-using namespace Glacier;
+using namespace Glacier;
+
+using IceSecurity::Ssl::OpenSSL::RSAKeyPairPtr;
+
Glacier::StarterI::StarterI(const CommunicatorPtr& communicator) :
_communicator(communicator),
@@ -27,6 +31,16 @@ Glacier::StarterI::StarterI(const CommunicatorPtr& communicator) :
_properties(_communicator->getProperties())
{
_traceLevel = atoi(_properties->getProperty("Glacier.Trace.Starter").c_str());
+
+ // Set up the Certificate Generation context
+ _certContext.setCountry(_properties->getProperty("Glacier.Starter.Certificate.Country"));
+ _certContext.setStateProvince(_properties->getProperty("Glacier.Starter.Certificate.StateProvince"));
+ _certContext.setLocality(_properties->getProperty("Glacier.Starter.Certificate.Locality"));
+ _certContext.setOrganization(_properties->getProperty("Glacier.Starter.Certificate.Organization"));
+ _certContext.setOrgainizationalUnit(_properties->getProperty("Glacier.Starter.Certificate.OranizationalUnit"));
+ _certContext.setCommonName(_properties->getProperty("Glacier.Starter.Certificate.CommonName"));
+ _certContext.setBitStrength(atoi(_properties->getProperty("Glacier.Starter.Certificate.BitStrength").c_str()));
+ _certContext.setSecondsValid(atol(_properties->getProperty("Glacier.Starter.Certificate.SecondsValid").c_str()));
}
void
@@ -49,7 +63,45 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con
//
// TODO: userId/password check
//
-
+
+ //
+ // Create a certificate for the Client and the Router
+ //
+ RSAKeyPairPtr clientKeyPair = _certificateGenerator.generate(_certContext);
+ RSAKeyPairPtr routerKeyPair = _certificateGenerator.generate(_certContext);
+
+ // NOTE: These will probably be returned from this method, I would assume.
+ ByteSeq clientPrivateKey;
+ ByteSeq clientCertificate;
+ ByteSeq routerCertificate;
+
+ clientKeyPair.keyToByteSeq(clientPrivateKey);
+ clientKeyPair.certToByteSeq(clientCertificate);
+ routerKeyPair.certToByteSeq(routerCertificate);
+
+ // routerPrivateKeyBase64 and routerCertificateBase64 are passed to the
+ // router as the values for the properties
+ // * Ice.Security.Ssl.Overrides.Server.RSA.PrivateKey
+ // * Ice.Security.Ssl.Overrides.Server.RSA.Certificate
+ // respectively.
+ //
+ // If the router is to act as a client to the Client as well, then
+ // these values should also be passed into the router as the properties
+ // * Ice.Security.Ssl.Overrides.Client.RSA.PrivateKey
+ // * Ice.Security.Ssl.Overrides.Client.RSA.Certificate
+ // respectively.
+ //
+ // The value of clientCertificateBase64 should be passed in to the router
+ // in the property
+ // * Glacier.Router.ClientCertificate
+ string routerPrivateKeyBase64;
+ string routerCertificateBase64;
+ string clientCertificateBase64;
+
+ routerKeyPair.keyToBase64(routerPrivateKeyBase64);
+ routerKeyPair.certToBase64(routerCertificateBase64);
+ clientKeyPair.certToBase64(clientCertificateBase64);
+
//
// Start a router
//
diff --git a/cpp/src/Glacier/GlacierI.h b/cpp/src/Glacier/GlacierI.h
index f28d542f560..455701dd486 100644
--- a/cpp/src/Glacier/GlacierI.h
+++ b/cpp/src/Glacier/GlacierI.h
@@ -12,6 +12,7 @@
#define GLACIER_GLACIER_I_H
#include <Ice/Ice.h>
+#include <Ice/SslRSACertificateGen.h>
#include <Glacier/Glacier.h>
namespace Glacier
@@ -32,7 +33,9 @@ private:
Ice::CommunicatorPtr _communicator;
Ice::LoggerPtr _logger;
Ice::PropertiesPtr _properties;
- int _traceLevel;
+ int _traceLevel;
+ RSACertificateGenContext _certContext;
+ RSACertificateGen _certificateGenerator;
};
}
diff --git a/cpp/src/Ice/SslCertificateVerifier.cpp b/cpp/src/Ice/SslCertificateVerifier.cpp
new file mode 100644
index 00000000000..064bd0a6fcf
--- /dev/null
+++ b/cpp/src/Ice/SslCertificateVerifier.cpp
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/SslCertificateVerifier.h>
+
+void ::IceInternal::incRef(::IceSecurity::Ssl::CertificateVerifier* p) { p->__incRef(); }
+void ::IceInternal::decRef(::IceSecurity::Ssl::CertificateVerifier* p) { p->__decRef(); }
+
+IceSecurity::Ssl::CertificateVerifier::~CertificateVerifier()
+{
+}
+
+
diff --git a/cpp/src/Ice/SslCertificateVerifier.h b/cpp/src/Ice/SslCertificateVerifier.h
new file mode 100644
index 00000000000..c93d7b56c8a
--- /dev/null
+++ b/cpp/src/Ice/SslCertificateVerifier.h
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#ifndef ICE_SSL_CERTIFICATE_VERIFIER_H
+#define ICE_SSL_CERTIFICATE_VERIFIER_H
+
+#include <IceUtil/Shared.h>
+#include <Ice/SslCertificateVerifierF.h>
+
+namespace IceSecurity
+{
+
+namespace Ssl
+{
+
+using IceUtil::Shared;
+
+class CertificateVerifier : public Shared
+{
+
+public:
+ virtual ~CertificateVerifier();
+
+};
+
+}
+
+}
+
+#endif
+
+
diff --git a/cpp/src/Ice/SslCertificateVerifierF.h b/cpp/src/Ice/SslCertificateVerifierF.h
new file mode 100644
index 00000000000..26e91ccd9f2
--- /dev/null
+++ b/cpp/src/Ice/SslCertificateVerifierF.h
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#ifndef ICE_SSL_CERTIFICATE_VERIFIER_F_H
+#define ICE_SSL_CERTIFICATE_VERIFIER_F_H
+
+#include <Ice/Handle.h>
+
+namespace IceSecurity
+{
+
+namespace Ssl
+{
+
+class CertificateVerifier;
+typedef IceInternal::Handle<CertificateVerifier> CertificateVerifierPtr;
+
+}
+
+}
+
+namespace IceInternal
+{
+
+void incRef(::IceSecurity::Ssl::CertificateVerifier*);
+void decRef(::IceSecurity::Ssl::CertificateVerifier*);
+
+}
+
+#endif
+
+
diff --git a/cpp/src/Ice/SslCertificateVerifierOpenSSL.cpp b/cpp/src/Ice/SslCertificateVerifierOpenSSL.cpp
new file mode 100644
index 00000000000..faaeccffd61
--- /dev/null
+++ b/cpp/src/Ice/SslCertificateVerifierOpenSSL.cpp
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/SslCertificateVerifierOpenSSL.h>
+
+IceSecurity::Ssl::OpenSSL::CertificateVerifier::~CertificateVerifier()
+{
+}
+
+int
+IceSecurity::Ssl::OpenSSL::DefaultCertificateVerifier::verify(int preVerifyOkay,
+ X509_STORE_CTX* x509StoreContext,
+ SSL* sslConnection)
+{
+ //
+ // Default verification steps.
+ //
+
+ int verifyError = X509_STORE_CTX_get_error(x509StoreContext);
+ int errorDepth = X509_STORE_CTX_get_error_depth(x509StoreContext);
+ int verifyDepth = SSL_get_verify_depth(sslConnection);
+
+ // Verify Depth was set
+ if (verifyError != X509_V_OK)
+ {
+ // If we have no errors so far, and the certificate chain is too long
+ if ((verifyDepth != -1) && (verifyDepth < errorDepth))
+ {
+ verifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+
+ // If we have ANY errors, we bail out.
+ preVerifyOkay = 0;
+ }
+
+ return preVerifyOkay;
+}
diff --git a/cpp/src/Ice/SslCertificateVerifierOpenSSL.h b/cpp/src/Ice/SslCertificateVerifierOpenSSL.h
new file mode 100644
index 00000000000..edbd5f5209e
--- /dev/null
+++ b/cpp/src/Ice/SslCertificateVerifierOpenSSL.h
@@ -0,0 +1,50 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#ifndef ICE_SSL_CERTIFICATE_VERIFIER_OPENSSL_H
+#define ICE_SSL_CERTIFICATE_VERIFIER_OPENSSL_H
+
+#include <Ice/SslCertificateVerifier.h>
+#include <openssl/ssl.h>
+
+namespace IceSecurity
+{
+
+namespace Ssl
+{
+
+namespace OpenSSL
+{
+
+class CertificateVerifier : public IceSecurity::Ssl::CertificateVerifier
+{
+
+public:
+ virtual ~CertificateVerifier();
+
+ virtual int verify(int, X509_STORE_CTX*, SSL*) = 0;
+};
+
+class DefaultCertificateVerifier : public CertificateVerifier
+{
+
+public:
+ virtual int verify(int, X509_STORE_CTX*, SSL*);
+};
+
+}
+
+}
+
+}
+
+#endif
+
+
diff --git a/cpp/src/Ice/SslConnection.cpp b/cpp/src/Ice/SslConnection.cpp
index 1cd95218b24..1c490682323 100644
--- a/cpp/src/Ice/SslConnection.cpp
+++ b/cpp/src/Ice/SslConnection.cpp
@@ -12,4 +12,13 @@
void ::IceInternal::incRef(::IceSecurity::Ssl::Connection* p) { p->__incRef(); }
void ::IceInternal::decRef(::IceSecurity::Ssl::Connection* p) { p->__decRef(); }
-
+
+IceSecurity::Ssl::Connection::Connection(const CertificateVerifierPtr& certificateVerifier) :
+ _certificateVerifier(certificateVerifier)
+{
+}
+
+IceSecurity::Ssl::Connection::~Connection()
+{
+}
+
diff --git a/cpp/src/Ice/SslConnection.h b/cpp/src/Ice/SslConnection.h
index dec02ce6085..1a75f11ca95 100644
--- a/cpp/src/Ice/SslConnection.h
+++ b/cpp/src/Ice/SslConnection.h
@@ -15,7 +15,8 @@
#include <Ice/Buffer.h>
#include <Ice/TraceLevelsF.h>
#include <Ice/LoggerF.h>
-#include <Ice/SslConnectionF.h>
+#include <Ice/SslConnectionF.h>
+#include <Ice/SslCertificateVerifierF.h>
namespace IceSecurity
{
@@ -30,17 +31,20 @@ using Ice::LoggerPtr;
class Connection : public Shared
{
-public:
-
- virtual ~Connection() { };
-
+public:
+ Connection(const CertificateVerifierPtr&);
+ virtual ~Connection();
+
virtual void shutdown() = 0;
virtual int read(Buffer&, int) = 0;
virtual int write(Buffer&, int) = 0;
- virtual void setTrace(TraceLevelsPtr) = 0;
- virtual void setLogger(LoggerPtr) = 0;
+ virtual void setTrace(const TraceLevelsPtr&) = 0;
+ virtual void setLogger(const LoggerPtr&) = 0;
+
+protected:
+ CertificateVerifierPtr _certificateVerifier;
};
}
diff --git a/cpp/src/Ice/SslConnectionOpenSSL.cpp b/cpp/src/Ice/SslConnectionOpenSSL.cpp
index c2a90e42d76..28db8c164e0 100644
--- a/cpp/src/Ice/SslConnectionOpenSSL.cpp
+++ b/cpp/src/Ice/SslConnectionOpenSSL.cpp
@@ -26,7 +26,9 @@
#include <Ice/SslFactory.h>
#include <Ice/SslConnection.h>
#include <Ice/SslConnectionOpenSSL.h>
-#include <Ice/SslSystemOpenSSL.h>
+#include <Ice/SslSystemOpenSSL.h>
+#include <Ice/SslCertificateVerifierOpenSSL.h>
+#include <Ice/SslOpenSSLUtils.h>
#include <Ice/TraceLevels.h>
#include <Ice/Logger.h>
@@ -42,12 +44,24 @@ using IceSecurity::Ssl::SystemPtr;
////////////////////////////////
////////// Connection //////////
////////////////////////////////
+
+//
+// Static Member Initialization
+//
+IceSecurity::Ssl::OpenSSL::SslConnectionMap IceSecurity::Ssl::OpenSSL::Connection::_connectionMap;
+::IceUtil::Mutex IceSecurity::Ssl::OpenSSL::Connection::_connectionRepositoryMutex;
//
// Public Methods
//
-IceSecurity::Ssl::OpenSSL::Connection::Connection(SSL* sslConnection, const SystemPtr& system) :
+void ::IceInternal::incRef(::IceSecurity::Ssl::OpenSSL::Connection* p) { p->__incRef(); }
+void ::IceInternal::decRef(::IceSecurity::Ssl::OpenSSL::Connection* p) { p->__decRef(); }
+
+IceSecurity::Ssl::OpenSSL::Connection::Connection(const CertificateVerifierPtr& certificateVerifier,
+ SSL* sslConnection,
+ const SystemPtr& system) :
+ IceSecurity::Ssl::Connection(certificateVerifier),
_sslConnection(sslConnection),
_system(system)
{
@@ -61,7 +75,10 @@ IceSecurity::Ssl::OpenSSL::Connection::Connection(SSL* sslConnection, const Syst
_initWantWrite = 0;
// None configured, default to indicated timeout
- _handshakeReadTimeout = 0;
+ _handshakeReadTimeout = 0;
+
+ // Set up the SSL to be able to refer back to our connection object.
+ addConnection(_sslConnection, this);
}
IceSecurity::Ssl::OpenSSL::Connection::~Connection()
@@ -70,6 +87,7 @@ IceSecurity::Ssl::OpenSSL::Connection::~Connection()
if (_sslConnection != 0)
{
+ removeConnection(_sslConnection);
Factory::removeSystemHandle(_sslConnection);
SSL_free(_sslConnection);
_sslConnection = 0;
@@ -108,6 +126,110 @@ IceSecurity::Ssl::OpenSSL::Connection::shutdown()
ICE_METHOD_RET("OpenSSL::Connection::shutdown()");
}
+void
+IceSecurity::Ssl::OpenSSL::Connection::setTrace(const TraceLevelsPtr& traceLevels)
+{
+ _traceLevels = traceLevels;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::Connection::setLogger(const LoggerPtr& traceLevels)
+{
+ _logger = traceLevels;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::Connection::setHandshakeReadTimeout(int timeout)
+{
+ _handshakeReadTimeout = timeout;
+}
+
+IceSecurity::Ssl::OpenSSL::ConnectionPtr
+IceSecurity::Ssl::OpenSSL::Connection::getConnection(SSL* sslPtr)
+{
+ IceUtil::Mutex::Lock sync(_connectionRepositoryMutex);
+
+ assert(sslPtr);
+
+ Connection* connection = _connectionMap[sslPtr];
+
+ assert(connection);
+
+ return ConnectionPtr(connection);
+}
+
+int
+IceSecurity::Ssl::OpenSSL::Connection::verifyCertificate(int preVerifyOkay, X509_STORE_CTX* x509StoreContext)
+{
+ // Get the verifier, make sure it is for OpenSSL connections
+ IceSecurity::Ssl::OpenSSL::CertificateVerifier* verifier;
+ verifier = dynamic_cast<IceSecurity::Ssl::OpenSSL::CertificateVerifier*>(_certificateVerifier.get());
+
+ // Check to make sure we have a proper verifier for the operation.
+ if (!verifier)
+ {
+ // TODO: Throw exception here
+ // throw SslIncorrectVerifierTypeException(__FILE__, __LINE__);
+ return 0;
+ }
+
+ // Use the verifier to verify the certificate
+ preVerifyOkay = verifier->verify(preVerifyOkay, x509StoreContext, _sslConnection);
+
+ // Only if ICE_PROTOCOL level logging is on do we worry about this.
+ if (ICE_SECURITY_LEVEL_PROTOCOL)
+ {
+ char buf[256];
+
+ X509* err_cert = X509_STORE_CTX_get_current_cert(x509StoreContext);
+ int verifyError = X509_STORE_CTX_get_error(x509StoreContext);
+ int depth = X509_STORE_CTX_get_error_depth(x509StoreContext);
+
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+
+ ostringstream outStringStream;
+
+ outStringStream << "depth = " << depth << ":" << buf << endl;
+
+ if (!preVerifyOkay)
+ {
+ outStringStream << "verify error: num = " << verifyError << " : "
+ << X509_verify_cert_error_string(verifyError) << endl;
+
+ }
+
+ switch (verifyError)
+ {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ {
+ X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof(buf));
+ outStringStream << "issuer = " << buf << endl;
+ break;
+ }
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ {
+ outStringStream << "notBefore = " << getASN1time(X509_get_notBefore(err_cert)) << endl;
+ break;
+ }
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ {
+ outStringStream << "notAfter = " << getASN1time(X509_get_notAfter(err_cert)) << endl;
+ break;
+ }
+ }
+
+ outStringStream << "verify return = " << preVerifyOkay << endl;
+
+ ICE_PROTOCOL(outStringStream.str());
+ }
+
+ return preVerifyOkay;
+}
+
//
// Protected Methods
//
@@ -709,7 +831,23 @@ IceSecurity::Ssl::OpenSSL::Connection::sslGetErrors()
return errorMessage;
}
-
+
+void
+IceSecurity::Ssl::OpenSSL::Connection::addConnection(SSL* sslPtr, Connection* connection)
+{
+ assert(sslPtr);
+ assert(connection);
+ _connectionMap[sslPtr] = connection;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::Connection::removeConnection(SSL* sslPtr)
+{
+ IceUtil::Mutex::Lock sync(_connectionRepositoryMutex);
+ assert(sslPtr);
+ _connectionMap.erase(sslPtr);
+}
+
void
IceSecurity::Ssl::OpenSSL::Connection::showCertificateChain(BIO* bio)
{
diff --git a/cpp/src/Ice/SslConnectionOpenSSL.h b/cpp/src/Ice/SslConnectionOpenSSL.h
index c46699549a3..c0eb5cd182b 100644
--- a/cpp/src/Ice/SslConnectionOpenSSL.h
+++ b/cpp/src/Ice/SslConnectionOpenSSL.h
@@ -11,10 +11,13 @@
#ifndef ICE_SSL_CONNECTION_OPENSSL_H
#define ICE_SSL_CONNECTION_OPENSSL_H
+#include <map>
#include <openssl/ssl.h>
#include <IceUtil/Mutex.h>
#include <Ice/SslConnection.h>
-#include <Ice/SslSystemF.h>
+#include <Ice/SslSystemF.h>
+#include <Ice/SslConnectionOpenSSLF.h>
+#include <Ice/SslCertificateVerifierF.h>
namespace IceSecurity
{
@@ -27,7 +30,7 @@ namespace OpenSSL
using namespace Ice;
using namespace std;
-
+
class SafeFlag
{
public:
@@ -106,12 +109,19 @@ private:
bool _ownHandshake;
SafeFlag& _flag;
};
-
+
+// NOTE: This is a mapping from SSL* to Connection*, for use with the verifyCallback.
+// I have purposely not used ConnectionPtr here, as connections register themselves
+// with this map on construction and unregister themselves in the destructor. If
+// this map used ConnectionPtr, Connection instances would never destruct as there
+// would always be a reference to them from the map.
+typedef map<SSL*, Connection*> SslConnectionMap;
+
class Connection : public IceSecurity::Ssl::Connection
{
public:
- Connection(SSL*, const SystemPtr&);
+ Connection(const CertificateVerifierPtr&, SSL*, const SystemPtr&);
virtual ~Connection();
virtual void shutdown();
@@ -121,10 +131,15 @@ public:
virtual int init(int timeout = 0) = 0;
- void setTrace(TraceLevelsPtr traceLevels) { _traceLevels = traceLevels; };
- void setLogger(LoggerPtr traceLevels) { _logger = traceLevels; };
+ void setTrace(const TraceLevelsPtr& traceLevels);
+ void setLogger(const LoggerPtr& traceLevels);
- void setHandshakeReadTimeout(int timeout) { _handshakeReadTimeout = timeout; };
+ void setHandshakeReadTimeout(int timeout);
+
+ static ConnectionPtr getConnection(SSL*);
+
+ // Callback from OpenSSL for purposes of certificate verification
+ int verifyCertificate(int, X509_STORE_CTX*);
protected:
@@ -152,6 +167,9 @@ protected:
// Retrieves errors from the OpenSSL library.
string sslGetErrors();
+
+ static void addConnection(SSL*, Connection*);
+ static void removeConnection(SSL*);
virtual void showConnectionInfo() = 0;
@@ -164,6 +182,9 @@ protected:
void showClientCAList(BIO*, const char*);
void setLastError(int errorCode) { _lastError = errorCode; };
+
+ static SslConnectionMap _connectionMap;
+ static ::IceUtil::Mutex _connectionRepositoryMutex;
// Pointer to the OpenSSL Connection structure.
SSL* _sslConnection;
diff --git a/cpp/src/Ice/SslConnectionOpenSSLClient.cpp b/cpp/src/Ice/SslConnectionOpenSSLClient.cpp
index 58e43fa8fb5..a6278cd717f 100644
--- a/cpp/src/Ice/SslConnectionOpenSSLClient.cpp
+++ b/cpp/src/Ice/SslConnectionOpenSSLClient.cpp
@@ -37,8 +37,10 @@ using std::dec;
// Public Methods
//
-IceSecurity::Ssl::OpenSSL::ClientConnection::ClientConnection(SSL* connection, const SystemPtr& system) :
- Connection(connection, system)
+IceSecurity::Ssl::OpenSSL::ClientConnection::ClientConnection(const CertificateVerifierPtr& certificateVerifier,
+ SSL* connection,
+ const SystemPtr& system) :
+ Connection(certificateVerifier, connection, system)
{
}
diff --git a/cpp/src/Ice/SslConnectionOpenSSLClient.h b/cpp/src/Ice/SslConnectionOpenSSLClient.h
index da16597f798..9faa82df08a 100644
--- a/cpp/src/Ice/SslConnectionOpenSSLClient.h
+++ b/cpp/src/Ice/SslConnectionOpenSSLClient.h
@@ -30,7 +30,7 @@ class ClientConnection : public Connection
{
public:
- ClientConnection(SSL*, const SystemPtr&);
+ ClientConnection(const CertificateVerifierPtr&, SSL*, const SystemPtr&);
virtual ~ClientConnection();
virtual void shutdown();
virtual int init(int timeout = 0);
diff --git a/cpp/src/Ice/SslConnectionOpenSSLF.h b/cpp/src/Ice/SslConnectionOpenSSLF.h
new file mode 100644
index 00000000000..c5f23022411
--- /dev/null
+++ b/cpp/src/Ice/SslConnectionOpenSSLF.h
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#ifndef ICE_SSL_CONNECTION_OPENSSL_F_H
+#define ICE_SSL_CONNECTION_OPENSSL_F_H
+
+#include <Ice/Handle.h>
+
+namespace IceSecurity
+{
+
+namespace Ssl
+{
+
+namespace OpenSSL
+{
+
+class Connection;
+typedef IceInternal::Handle<Connection> ConnectionPtr;
+
+}
+
+}
+
+}
+
+namespace IceInternal
+{
+
+void incRef(::IceSecurity::Ssl::OpenSSL::Connection*);
+void decRef(::IceSecurity::Ssl::OpenSSL::Connection*);
+
+}
+
+#endif
diff --git a/cpp/src/Ice/SslConnectionOpenSSLServer.cpp b/cpp/src/Ice/SslConnectionOpenSSLServer.cpp
index d58e797e1c9..66e3816a8ff 100644
--- a/cpp/src/Ice/SslConnectionOpenSSLServer.cpp
+++ b/cpp/src/Ice/SslConnectionOpenSSLServer.cpp
@@ -38,8 +38,10 @@ using std::dec;
// Public Methods
//
-IceSecurity::Ssl::OpenSSL::ServerConnection::ServerConnection(SSL* connection, const SystemPtr& system) :
- Connection(connection, system)
+IceSecurity::Ssl::OpenSSL::ServerConnection::ServerConnection(const CertificateVerifierPtr& certificateVerifier,
+ SSL* connection,
+ const SystemPtr& system) :
+ Connection(certificateVerifier, connection, system)
{
}
diff --git a/cpp/src/Ice/SslConnectionOpenSSLServer.h b/cpp/src/Ice/SslConnectionOpenSSLServer.h
index 7498a186551..c24e703aafb 100644
--- a/cpp/src/Ice/SslConnectionOpenSSLServer.h
+++ b/cpp/src/Ice/SslConnectionOpenSSLServer.h
@@ -30,7 +30,7 @@ class ServerConnection : public Connection
{
public:
- ServerConnection(SSL*, const SystemPtr&);
+ ServerConnection(const CertificateVerifierPtr&, SSL*, const SystemPtr&);
virtual ~ServerConnection();
virtual void shutdown();
virtual int init(int timeout = 0);
diff --git a/cpp/src/Ice/SslFactory.cpp b/cpp/src/Ice/SslFactory.cpp
index 63ac8f9899d..2210a146d8c 100644
--- a/cpp/src/Ice/SslFactory.cpp
+++ b/cpp/src/Ice/SslFactory.cpp
@@ -35,18 +35,17 @@ namespace IceSecurity
namespace Ssl
{
-
-extern "C"
-{
- void lockingCallback(int, int, const char*, int);
-}
-
// Static member instantiations.
IceUtil::Mutex Factory::_systemRepositoryMutex;
SystemMap Factory::_systemRepository;
SslHandleSystemMap Factory::_sslHandleSystemRepository;
int Factory::_evict = 0;
+extern "C"
+{
+ void lockingCallback(int, int, const char*, int);
+}
+
class SslLockKeeper
{
@@ -83,9 +82,8 @@ void IceSecurity::Ssl::lockingCallback(int mode, int type, const char *file, int
}
}
-
IceSecurity::Ssl::SystemPtr
-IceSecurity::Ssl::Factory::getSystem(string& systemIdentifier)
+IceSecurity::Ssl::Factory::getSystem(const string& systemIdentifier)
{
IceUtil::Mutex::Lock sync(_systemRepositoryMutex);
@@ -145,7 +143,6 @@ IceSecurity::Ssl::Factory::getSystemFromHandle(void* sslHandle)
return system;
}
-
void
IceSecurity::Ssl::Factory::reapSystems()
{
@@ -194,3 +191,21 @@ IceSecurity::Ssl::Factory::reapSystems()
}
}
+void
+IceSecurity::Ssl::setSystemCertificateVerifier(const string& systemIdentifier,
+ CertificateVerifierType verifierType,
+ const CertificateVerifierPtr& certificateVerifier)
+{
+ SystemPtr sslSystem = Factory::getSystem(systemIdentifier);
+
+ if ((verifierType == Client) || (verifierType == ClientServer))
+ {
+ sslSystem->setClientCertificateVerifier(certificateVerifier);
+ }
+
+ if ((verifierType == Server) || (verifierType == ClientServer))
+ {
+ sslSystem->setServerCertificateVerifier(certificateVerifier);
+ }
+}
+
diff --git a/cpp/src/Ice/SslFactory.h b/cpp/src/Ice/SslFactory.h
index 6216c0c7ad3..cd56012d201 100644
--- a/cpp/src/Ice/SslFactory.h
+++ b/cpp/src/Ice/SslFactory.h
@@ -14,7 +14,8 @@
#include <string>
#include <map>
#include <IceUtil/Mutex.h>
-#include <Ice/SslSystemF.h>
+#include <Ice/SslSystemF.h>
+#include <Ice/SslCertificateVerifierF.h>
namespace IceSecurity
{
@@ -38,7 +39,7 @@ class Factory
{
public:
- static SystemPtr getSystem(string&);
+ static SystemPtr getSystem(const string&);
// System Handle related methods
static void addSystemHandle(void*, const SystemPtr&);
@@ -53,6 +54,17 @@ private:
static void reapSystems();
};
+
+typedef enum
+{
+ None = 0,
+ Client,
+ Server,
+ ClientServer
+} CertificateVerifierType;
+
+
+void setSystemCertificateVerifier(const string&, CertificateVerifierType, const CertificateVerifierPtr&);
}
diff --git a/cpp/src/Ice/SslRSACertificateGen.cpp b/cpp/src/Ice/SslRSACertificateGen.cpp
new file mode 100644
index 00000000000..64f2cf16eff
--- /dev/null
+++ b/cpp/src/Ice/SslRSACertificateGen.cpp
@@ -0,0 +1,253 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IceUtil/Config.h>
+#include <Ice/SslRSACertificateGen.h>
+#include <Ice/SslJanitors.h>
+#include <Ice/SslRSAKeyPair.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+using std::string;
+using std::back_inserter;
+
+using namespace IceSecurity::Ssl::OpenSSL;
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::minutesToSeconds(long minutes)
+{
+ return minutes * 60L;
+}
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::hoursToSeconds(long hours)
+{
+ return minutesToSeconds(hours * 60L);
+}
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::daysToSeconds(long days)
+{
+ return hoursToSeconds(days * 24L);
+}
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::weeksToSeconds(long weeks)
+{
+ return daysToSeconds(weeks * 7L);
+}
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::yearsToSeconds(long years)
+{
+ return weeksToSeconds(years * 365L);
+}
+
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::RSACertificateGenContext() :
+ _modulusLength(0),
+ _secondsValid(0)
+{
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setCountry(const string& country)
+{
+ _country = country;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setStateProvince(const string& stateProvince)
+{
+ _stateProvince = stateProvince;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setLocality(const string& locality)
+{
+ _locality = locality;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setOrganization(const string& organization)
+{
+ _organization = organization;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setOrgainizationalUnit(const string& organizationalUnit)
+{
+ _organizationalUnit = organizationalUnit;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setCommonName(const string& commonName)
+{
+ _commonName = commonName;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setBitStrength(int bitStrength)
+{
+ _modulusLength = bitStrength;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::setSecondsValid(long secondsValid)
+{
+ _secondsValid = secondsValid;
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getCountry() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_country.c_str()));
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getStateProvince() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_stateProvince.c_str()));
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getLocality() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_locality.c_str()));
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getOrganization() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_organization.c_str()));
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getOrgainizationalUnit() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_organizationalUnit.c_str()));
+}
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getCommonName() const
+{
+ return reinterpret_cast<unsigned char *>(const_cast<char*>(_commonName.c_str()));
+}
+
+int
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getModulusLength() const
+{
+ return _modulusLength;
+}
+
+long
+IceSecurity::Ssl::OpenSSL::RSACertificateGenContext::getSecondsValid() const
+{
+ return _secondsValid;
+}
+
+IceSecurity::Ssl::OpenSSL::RSACertificateGen::RSACertificateGen()
+{
+ ERR_load_crypto_strings();
+}
+
+IceSecurity::Ssl::OpenSSL::RSACertificateGen::~RSACertificateGen()
+{
+}
+
+IceSecurity::Ssl::OpenSSL::RSAKeyPair*
+IceSecurity::Ssl::OpenSSL::RSACertificateGen::generate(const RSACertificateGenContext& context)
+{
+ // Generate an RSA key pair.
+ RSAJanitor rsaJanitor(RSA_generate_key(context.getModulusLength(), RSA_F4, 0, 0));
+ RSA* rsaKeyPair = rsaJanitor.get();
+
+ assert(rsaKeyPair);
+
+ // Do this if we already have an RSA*
+ EVP_PKEYJanitor evpPkeyJanitor(EVP_PKEY_new());
+ EVP_PKEY* pkey = evpPkeyJanitor.get();
+ assert(pkey);
+ EVP_PKEY_assign_RSA(pkey, rsaKeyPair);
+
+ // The RSA structure now belongs (temporarily) to the EVP_PKEY
+ rsaJanitor.clear();
+
+ // Create a signing request
+ X509_REQJanitor x509ReqJanitor(X509_REQ_new());
+ X509_REQ* signingRequest = x509ReqJanitor.get();
+ assert(signingRequest);
+
+ X509Janitor x509Janitor(X509_new());
+ X509* x509SelfSigned = x509Janitor.get();
+ assert(x509SelfSigned);
+
+ // Set version to V3
+ assert(X509_set_version(x509SelfSigned, 2));
+
+ ASN1_INTEGER_set(X509_get_serialNumber(x509SelfSigned), 0);
+
+ // NOTE: This is wierd. It looks like, for some reason, that the typedef of
+ // X509_NAME gets lost in this code module. I am using the straight struct
+ // here because X509_NAME isn't here.
+
+ // X509_NAME* subjectName = X509_REQ_get_subject_name(signingRequest);
+ struct X509_name_st* subjectName = X509_REQ_get_subject_name(signingRequest);
+
+ // Set valid time period
+ X509_gmtime_adj(X509_get_notBefore(x509SelfSigned), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509SelfSigned), context.getSecondsValid());
+
+ // Set up subject/issuer name
+ X509_NAME_add_entry_by_txt(subjectName, "C", MBSTRING_ASC, context.getCountry(), -1, -1, 0);
+ X509_NAME_add_entry_by_txt(subjectName, "ST", MBSTRING_ASC, context.getStateProvince(), -1, -1, 0);
+ X509_NAME_add_entry_by_txt(subjectName, "L", MBSTRING_ASC, context.getLocality(), -1, -1, 0);
+ X509_NAME_add_entry_by_txt(subjectName, "O", MBSTRING_ASC, context.getOrganization(), -1, -1, 0);
+ X509_NAME_add_entry_by_txt(subjectName, "OU", MBSTRING_ASC, context.getOrgainizationalUnit(), -1, -1, 0);
+ X509_NAME_add_entry_by_txt(subjectName, "CN", MBSTRING_ASC, context.getCommonName(), -1, -1, 0);
+
+ // Self signed - set issuer and subject names identical
+ X509_set_issuer_name(x509SelfSigned, subjectName);
+ X509_set_subject_name(x509SelfSigned, subjectName);
+
+ // Set the public key in the self signed certificate from the request.
+ X509_set_pubkey(x509SelfSigned, pkey);
+
+ // Sign the public key using an MD5 digest
+ if (!X509_sign(x509SelfSigned, pkey, EVP_md5()))
+ {
+ // TODO: Throw exception here.
+ // throw CertificateSigningException(__FILE__, __LINE__);
+ return 0;
+ }
+
+ // Verify the Signature (paranoia)
+ if (!X509_REQ_verify(signingRequest, pkey))
+ {
+ // TODO: Throw exception here (signature verification)
+ // throw CertificateSignatureException(__FILE__, __LINE__);
+ return 0;
+ }
+
+ // Nasty Hack: Getting the pkey to let go of our rsaKeyPair - we own that.
+ pkey->pkey.ptr = 0;
+
+ // Constructing our object.
+ RSAKeyPair* keyPairPtr = new RSAKeyPair(rsaKeyPair, x509SelfSigned);
+
+ // Don't let them clean up, we're keeping those around.
+ rsaJanitor.clear();
+ x509Janitor.clear();
+
+ return keyPairPtr;
+}
+
+
+
+
diff --git a/cpp/src/Ice/SslRSAKeyPair.cpp b/cpp/src/Ice/SslRSAKeyPair.cpp
new file mode 100644
index 00000000000..c6af6b75767
--- /dev/null
+++ b/cpp/src/Ice/SslRSAKeyPair.cpp
@@ -0,0 +1,181 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IceUtil/Config.h>
+#include <IceUtil/Base64.h>
+#include <Ice/SslRSAKeyPair.h>
+#include <assert.h>
+
+void ::IceInternal::incRef(::IceSecurity::Ssl::OpenSSL::RSAKeyPair* p) { p->__incRef(); }
+void ::IceInternal::decRef(::IceSecurity::Ssl::OpenSSL::RSAKeyPair* p) { p->__decRef(); }
+
+using std::back_inserter;
+using std::string;
+using IceUtil::Base64;
+
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::RSAKeyPair(const string& key, const string& cert)
+{
+ _privateKey = 0;
+ _publicKey = 0;
+
+ ByteSeq keySeq = Base64::decode(key);
+ ByteSeq certSeq = Base64::decode(cert);
+
+ byteSeqToKey(keySeq);
+ byteSeqToCert(certSeq);
+}
+
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::RSAKeyPair(const ByteSeq& keySeq, const ByteSeq& certSeq)
+{
+ _privateKey = 0;
+ _publicKey = 0;
+ byteSeqToKey(keySeq);
+ byteSeqToCert(certSeq);
+}
+
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::~RSAKeyPair()
+{
+ RSA_free(_privateKey);
+ X509_free(_publicKey);
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::keyToBase64(string& b64Key)
+{
+ ByteSeq keySeq;
+ keyToByteSeq(keySeq);
+ b64Key = Base64::encode(keySeq);
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::certToBase64(string& b64Cert)
+{
+ ByteSeq certSeq;
+ certToByteSeq(certSeq);
+ b64Cert = Base64::encode(certSeq);
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::keyToByteSeq(ByteSeq& keySeq)
+{
+ assert(_privateKey);
+
+ // Output the Private Key to a char buffer
+ unsigned int privKeySize = i2d_RSAPrivateKey(_privateKey, 0);
+
+ assert(privKeySize > 0);
+
+ unsigned char* privateKeyBuffer = new unsigned char[privKeySize];
+
+ // We have to do this because i2d_RSAPrivateKey changes the pointer.
+ unsigned char* privKeyBuff = privateKeyBuffer;
+ i2d_RSAPrivateKey(_privateKey, &privKeyBuff);
+
+ ucharToByteSeq(privateKeyBuffer, privKeySize, keySeq);
+
+ delete []privateKeyBuffer;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::certToByteSeq(ByteSeq& certSeq)
+{
+ assert(_publicKey);
+
+ // Output the Public Key to a char buffer
+ unsigned int pubKeySize = i2d_X509(_publicKey, 0);
+
+ assert(pubKeySize > 0);
+
+ unsigned char* publicKeyBuffer = new unsigned char[pubKeySize];
+
+ // We have to do this because i2d_X509_PUBKEY changes the pointer.
+ unsigned char* pubKeyBuff = publicKeyBuffer;
+ int retSize = i2d_X509(_publicKey, &pubKeyBuff);
+
+ ucharToByteSeq(publicKeyBuffer, pubKeySize, certSeq);
+
+ delete []publicKeyBuffer;
+}
+
+RSA*
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::getRSAPrivateKey() const
+{
+ return _privateKey;
+}
+
+X509*
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::getX509PublicKey() const
+{
+ return _publicKey;
+}
+
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::RSAKeyPair(RSA* rsa, X509* x509) :
+ _privateKey(rsa),
+ _publicKey(x509)
+{
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::byteSeqToKey(const ByteSeq& keySeq)
+{
+ unsigned char* privateKeyBuffer = byteSeqToUChar(keySeq);
+ assert(privateKeyBuffer);
+
+ unsigned char* privKeyBuff = privateKeyBuffer;
+ unsigned char** privKeyBuffpp = &privKeyBuff;
+ RSA** rsapp = &_privateKey;
+
+ _privateKey = d2i_RSAPrivateKey(rsapp, privKeyBuffpp, (long)keySeq.size());
+ assert(_privateKey);
+
+ delete []privateKeyBuffer;
+}
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::byteSeqToCert(const ByteSeq& certSeq)
+{
+ unsigned char* publicKeyBuffer = byteSeqToUChar(certSeq);
+ assert(publicKeyBuffer);
+
+ // We have to do this because d2i_X509 changes the pointer.
+ unsigned char* pubKeyBuff = publicKeyBuffer;
+ unsigned char** pubKeyBuffpp = &pubKeyBuff;
+
+ X509** x509pp = &_publicKey;
+
+ _publicKey = d2i_X509(x509pp, pubKeyBuffpp, (long)certSeq.size());
+ assert(_publicKey);
+
+ delete []publicKeyBuffer;
+}
+
+
+void
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::ucharToByteSeq(unsigned char* ucharBuffer, int length, ByteSeq& destBuffer)
+{
+ destBuffer.reserve(length);
+ std::copy(ucharBuffer, (ucharBuffer + length), back_inserter(destBuffer));
+}
+
+
+unsigned char*
+IceSecurity::Ssl::OpenSSL::RSAKeyPair::byteSeqToUChar(const ByteSeq& sequence)
+{
+ int seqSize = sequence.size();
+
+ assert(seqSize > 0);
+
+ unsigned char* ucharSeq = new unsigned char[seqSize];
+ unsigned char* ucharPtr = ucharSeq;
+ std::copy(sequence.begin(), sequence.end(), ucharPtr);
+
+ return ucharSeq;
+}
+
diff --git a/cpp/src/Ice/SslSystem.cpp b/cpp/src/Ice/SslSystem.cpp
index c1b5a1fff03..1a18ebb5087 100644
--- a/cpp/src/Ice/SslSystem.cpp
+++ b/cpp/src/Ice/SslSystem.cpp
@@ -11,10 +11,63 @@
#include <string>
#include <Ice/SslSystem.h>
-using namespace std;
+using namespace std;
+using IceSecurity::Ssl::CertificateVerifierPtr;
void ::IceInternal::incRef(::IceSecurity::Ssl::System* p) { p->__incRef(); }
void ::IceInternal::decRef(::IceSecurity::Ssl::System* p) { p->__decRef(); }
+
+//
+// Public Methods
+//
+
+void
+IceSecurity::Ssl::System::setServerCertificateVerifier(const CertificateVerifierPtr& serverVerifier)
+{
+ _serverVerifier = serverVerifier;
+}
+
+void
+IceSecurity::Ssl::System::setClientCertificateVerifier(const CertificateVerifierPtr& clientVerifier)
+{
+ _clientVerifier = clientVerifier;
+}
+
+void
+IceSecurity::Ssl::System::setTrace(const TraceLevelsPtr& traceLevels)
+{
+ _traceLevels = traceLevels;
+}
+
+bool
+IceSecurity::Ssl::System::isTraceSet() const
+{
+ return _traceLevels;
+}
+
+void
+IceSecurity::Ssl::System::setLogger(const LoggerPtr& traceLevels)
+{
+ _logger = traceLevels;
+}
+
+bool
+IceSecurity::Ssl::System::isLoggerSet() const
+{
+ return _logger;
+}
+
+void
+IceSecurity::Ssl::System::setProperties(const PropertiesPtr& properties)
+{
+ _properties = properties;
+}
+
+bool
+IceSecurity::Ssl::System::isPropertiesSet() const
+{
+ return _properties;
+}
//
// Protected Methods
diff --git a/cpp/src/Ice/SslSystem.h b/cpp/src/Ice/SslSystem.h
index f73df892bf8..ae8b596a5c7 100644
--- a/cpp/src/Ice/SslSystem.h
+++ b/cpp/src/Ice/SslSystem.h
@@ -15,7 +15,8 @@
#include <IceUtil/Shared.h>
#include <Ice/SslConnectionF.h>
#include <Ice/Properties.h>
-#include <Ice/SslSystemF.h>
+#include <Ice/SslSystemF.h>
+#include <Ice/SslCertificateVerifierF.h>
#include <Ice/TraceLevels.h>
#include <Ice/LoggerF.h>
@@ -42,16 +43,19 @@ public:
virtual void shutdown() = 0;
virtual Connection* createServerConnection(int) = 0;
- virtual Connection* createClientConnection(int) = 0;
+ virtual Connection* createClientConnection(int) = 0;
+
+ virtual void setServerCertificateVerifier(const CertificateVerifierPtr&);
+ virtual void setClientCertificateVerifier(const CertificateVerifierPtr&);
- void setTrace(TraceLevelsPtr traceLevels) { _traceLevels = traceLevels; };
- bool isTraceSet() const { return _traceLevels; };
+ void setTrace(const TraceLevelsPtr&);
+ bool isTraceSet() const;
- void setLogger(LoggerPtr traceLevels) { _logger = traceLevels; };
- bool isLoggerSet() const { return _logger; };
+ void setLogger(const LoggerPtr&);
+ bool isLoggerSet() const;
- void setProperties(PropertiesPtr properties) { _properties = properties; };
- bool isPropertiesSet() const { return _properties; };
+ void setProperties(const PropertiesPtr&);
+ bool isPropertiesSet() const;
protected:
@@ -60,7 +64,9 @@ protected:
TraceLevelsPtr _traceLevels;
LoggerPtr _logger;
- PropertiesPtr _properties;
+ PropertiesPtr _properties;
+ CertificateVerifierPtr _clientVerifier;
+ CertificateVerifierPtr _serverVerifier;
friend class Factory;
};
diff --git a/cpp/src/Ice/SslSystemOpenSSL.cpp b/cpp/src/Ice/SslSystemOpenSSL.cpp
index d2828615af3..734bb5ecfbd 100644
--- a/cpp/src/Ice/SslSystemOpenSSL.cpp
+++ b/cpp/src/Ice/SslSystemOpenSSL.cpp
@@ -33,7 +33,10 @@
#include <Ice/SecurityException.h>
#include <Ice/SslConnectionOpenSSLClient.h>
#include <Ice/SslConnectionOpenSSLServer.h>
-#include <Ice/SslConfig.h>
+#include <Ice/SslConfig.h>
+#include <Ice/SslRSAKeyPair.h>
+#include <Ice/SslJanitors.h>
+#include <Ice/SslCertificateVerifierOpenSSL.h>
#include <Ice/TraceLevels.h>
#include <Ice/Logger.h>
@@ -92,158 +95,6 @@ Ice::LoggerPtr System::_globalLogger = 0;
using IceSecurity::Ssl::OpenSSL::ContextException;
using IceSecurity::Ssl::SystemPtr;
-//
-// NOTE: The following (mon, getGeneralizedTime, getUTCTime and getASN1time are routines that
-// have been abducted from the OpenSSL X509 library, and modified to work with the STL
-// basic_string template.
-
-static const char *mon[12]=
-{
- "Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"
-};
-
-string
-getGeneralizedTime(ASN1_GENERALIZEDTIME *tm)
-{
- char buf[30];
- char *v;
- int gmt=0;
- int i;
- int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
-
- i = tm->length;
- v = (char *) tm->data;
-
- if (i < 12)
- {
- goto err;
- }
-
- if (v[i-1] == 'Z')
- {
- gmt=1;
- }
-
- for (i=0; i<12; i++)
- {
- if ((v[i] > '9') || (v[i] < '0'))
- {
- goto err;
- }
- }
-
- y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] - '0');
- M = (v[4] - '0') * 10 + (v[5] - '0');
-
- if ((M > 12) || (M < 1))
- {
- goto err;
- }
-
- d = (v[6] - '0') * 10 + (v[7] - '0');
- h = (v[8] - '0') * 10 + (v[9] - '0');
- m = (v[10] - '0') * 10 + (v[11] - '0');
-
- if ((v[12] >= '0') && (v[12] <= '9') &&
- (v[13] >= '0') && (v[13] <= '9'))
- {
- s = (v[12] - '0') * 10 + (v[13] - '0');
- }
-
- sprintf(buf, "%s %2d %02d:%02d:%02d %d%s", mon[M-1], d, h, m, s, y, (gmt)?" GMT":"");
- return string(buf);
-
-err:
- return string("Bad time value");
-}
-
-string
-getUTCTime(ASN1_UTCTIME *tm)
-{
- char buf[30];
- char *v;
- int gmt=0;
- int i;
- int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
-
- i = tm->length;
- v = (char *) tm->data;
-
- if (i < 10)
- {
- goto err;
- }
-
- if (v[i-1] == 'Z')
- {
- gmt=1;
- }
-
- for (i = 0; i < 10; i++)
- {
- if ((v[i] > '9') || (v[i] < '0'))
- {
- goto err;
- }
- }
-
- y = (v[0] - '0') * 10 + (v[1] - '0');
-
- if (y < 50)
- {
- y+=100;
- }
-
- M = (v[2] - '0') * 10 + (v[3] - '0');
-
- if ((M > 12) || (M < 1))
- {
- goto err;
- }
-
- d = (v[4] - '0') * 10 + (v[5] - '0');
- h = (v[6] - '0') * 10 + (v[7] - '0');
- m = (v[8] - '0') * 10 + (v[9] - '0');
-
- if ((v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
- {
- s = (v[10] - '0') * 10 + (v[11] - '0');
- }
-
- sprintf(buf, "%s %2d %02d:%02d:%02d %d%s", mon[M-1], d, h, m, s, y+1900, (gmt)?" GMT":"");
- return string(buf);
-
-err:
- return string("Bad time value");
-}
-
-string
-getASN1time(ASN1_TIME *tm)
-{
- string theTime;
-
- switch (tm->type)
- {
- case V_ASN1_UTCTIME :
- {
- theTime = getUTCTime(tm);
- }
-
- case V_ASN1_GENERALIZEDTIME :
- {
- theTime = getGeneralizedTime(tm);
- }
-
- default :
- {
- theTime = "Bad time value";
- }
- }
-
- return theTime;
-}
-
extern "C"
{
@@ -252,7 +103,8 @@ tmpRSACallback(SSL *s, int isExport, int keyLength)
{
IceSecurity::Ssl::SystemPtr sslSystem = IceSecurity::Ssl::Factory::getSystemFromHandle(s);
- IceSecurity::Ssl::OpenSSL::System* openSslSystem = dynamic_cast<IceSecurity::Ssl::OpenSSL::System*>(sslSystem.get());
+ IceSecurity::Ssl::OpenSSL::System* openSslSystem = 0;
+ openSslSystem = dynamic_cast<IceSecurity::Ssl::OpenSSL::System*>(sslSystem.get());
RSA* rsaKey = openSslSystem->getRSAKey(s, isExport, keyLength);
@@ -264,7 +116,8 @@ tmpDHCallback(SSL *s, int isExport, int keyLength)
{
IceSecurity::Ssl::SystemPtr sslSystem = IceSecurity::Ssl::Factory::getSystemFromHandle(s);
- IceSecurity::Ssl::OpenSSL::System* openSslSystem = dynamic_cast<IceSecurity::Ssl::OpenSSL::System*>(sslSystem.get());
+ IceSecurity::Ssl::OpenSSL::System* openSslSystem = 0;
+ openSslSystem = dynamic_cast<IceSecurity::Ssl::OpenSSL::System*>(sslSystem.get());
DH* dh = openSslSystem->getDHParams(s, isExport, keyLength);
@@ -275,71 +128,16 @@ tmpDHCallback(SSL *s, int isExport, int keyLength)
int
verifyCallback(int ok, X509_STORE_CTX *ctx)
{
- X509* err_cert = X509_STORE_CTX_get_current_cert(ctx);
- int verifyError = X509_STORE_CTX_get_error(ctx);
- int depth = X509_STORE_CTX_get_error_depth(ctx);
-
- // If we have no errors so far, and the certificate chain is too long
- if ((verifyError != X509_V_OK) && (10 < depth))
- {
- verifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;
- }
-
- if (verifyError != X509_V_OK)
- {
- // If we have ANY errors, we bail out.
- ok = 0;
- }
-
- // Only if ICE_PROTOCOL level logging is on do we worry about this.
- if (ICE_SECURITY_LEVEL_PROTOCOL_GLOBAL)
- {
- char buf[256];
-
- X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
-
- ostringstream outStringStream;
-
- outStringStream << "depth = " << depth << ":" << buf << endl;
-
- if (!ok)
- {
- outStringStream << "verify error: num = " << verifyError << " : "
- << X509_verify_cert_error_string(verifyError) << endl;
-
- }
-
- switch (verifyError)
- {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- {
- X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, sizeof(buf));
- outStringStream << "issuer = " << buf << endl;
- break;
- }
-
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- {
- outStringStream << "notBefore =" << getASN1time(X509_get_notBefore(ctx->current_cert)) << endl;
- break;
- }
-
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- {
- outStringStream << "notAfter =" << getASN1time(X509_get_notAfter(ctx->current_cert)) << endl;
- break;
- }
- }
-
- outStringStream << "verify return = " << ok << endl;
-
- IceSecurity::Ssl::OpenSSL::System::_globalLogger->trace(
- IceSecurity::Ssl::OpenSSL::System::_globalTraceLevels->securityCat, outStringStream.str());
- }
-
- return ok;
+ // Tricky method to get access to our connection. I would use SSL_get_ex_data() to get
+ // the Connection object, if only I had some way to retrieve the index of the object
+ // in this function. Hence, we have to invent our own reference system here.
+ SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+ IceSecurity::Ssl::OpenSSL::ConnectionPtr connection = 0;
+ connection = IceSecurity::Ssl::OpenSSL::Connection::getConnection(ssl);
+ assert(connection);
+
+ // Call the connection, get it to perform the verification.
+ return connection->verifyCertificate(ok, ctx);
}
// This code duplicates functionality that existed in the BIO library of
@@ -531,7 +329,7 @@ IceSecurity::Ssl::OpenSSL::System::createServerConnection(int socket)
// Set the Accept Connection state for this connection.
SSL_set_accept_state(sslConnection);
- Connection* connection = new ServerConnection(sslConnection, SystemPtr(this));
+ Connection* connection = new ServerConnection(_serverVerifier, sslConnection, SystemPtr(this));
commonConnectionSetup(connection);
@@ -562,7 +360,7 @@ IceSecurity::Ssl::OpenSSL::System::createClientConnection(int socket)
// Set the Connect Connection state for this connection.
SSL_set_connect_state(sslConnection);
- Connection* connection = new ClientConnection(sslConnection, SystemPtr(this));
+ Connection* connection = new ClientConnection(_clientVerifier, sslConnection, SystemPtr(this));
commonConnectionSetup(connection);
@@ -842,6 +640,11 @@ IceSecurity::Ssl::OpenSSL::System::System()
_randSeeded = 0;
_sslServerContext = 0;
_sslClientContext = 0;
+
+ // Here we create a default verifier, which does very little other
+ // than check the verification depth. This can be overridden.
+ _clientVerifier = new DefaultCertificateVerifier();
+ _serverVerifier = _clientVerifier;
SSL_load_error_strings();
@@ -912,8 +715,8 @@ IceSecurity::Ssl::OpenSSL::System::initClient(GeneralConfig& general,
setKeyCert(_sslClientContext, baseCerts.getRSACert(), privateRSAKey, publicRSAKey);
// Process the DSA Certificate
- string privateDSAKey = _properties->getProperty("Ice.Security.Ssl.Overrides.Client.DSA.PrivateKey");
- string publicDSAKey = _properties->getProperty("Ice.Security.Ssl.Overrides.Client.DSA.Certificate");
+ string privateDSAKey; // = _properties->getProperty("Ice.Security.Ssl.Overrides.Client.DSA.PrivateKey");
+ string publicDSAKey; // = _properties->getProperty("Ice.Security.Ssl.Overrides.Client.DSA.Certificate");
setKeyCert(_sslClientContext, baseCerts.getDSACert(), privateDSAKey, publicDSAKey);
// Set the DH key agreement parameters.
@@ -965,8 +768,8 @@ IceSecurity::Ssl::OpenSSL::System::initServer(GeneralConfig& general,
setKeyCert(_sslServerContext, baseCerts.getRSACert(), privateRSAKey, publicRSAKey);
// Process the DSA Certificate
- string privateDSAKey = _properties->getProperty("Ice.Security.Ssl.Overrides.Server.DSA.PrivateKey");
- string publicDSAKey = _properties->getProperty("Ice.Security.Ssl.Overrides.Server.DSA.Certificate");
+ string privateDSAKey; // = _properties->getProperty("Ice.Security.Ssl.Overrides.Server.DSA.PrivateKey");
+ string publicDSAKey; // = _properties->getProperty("Ice.Security.Ssl.Overrides.Server.DSA.Certificate");
setKeyCert(_sslServerContext, baseCerts.getDSACert(), privateDSAKey, publicDSAKey);
// Set the DH key agreement parameters.
@@ -988,8 +791,8 @@ IceSecurity::Ssl::OpenSSL::System::initServer(GeneralConfig& general,
SSL_CTX_set_verify(_sslServerContext, general.getVerifyMode(), verifyCallback);
// Set the certificate verify depth
- SSL_CTX_set_verify_depth(_sslServerContext, general.getVerifyDepth());
-
+ SSL_CTX_set_verify_depth(_sslServerContext, general.getVerifyDepth());
+
// Set the default context for the SSL system (can be overridden if needed) [SERVER ONLY].
SSL_CTX_set_session_id_context(_sslServerContext,
reinterpret_cast<const unsigned char *>(_sessionContext.c_str()),
@@ -1145,22 +948,35 @@ IceSecurity::Ssl::OpenSSL::System::addKeyCert(SSL_CTX* sslContext,
ICE_METHOD_RET("OpenSSL::System::addKeyCert()");
}
-X509*
-IceSecurity::Ssl::OpenSSL::System::byteSeqToX509(ByteSeq& byteSeq)
+void
+IceSecurity::Ssl::OpenSSL::System::addKeyCert(SSL_CTX* sslContext,
+ const string& privateKey,
+ const string& publicKey)
{
- // Create a BIO that reads directly from our ByteSeq!
- // NOTE: The reinterpret_cast is required, nasty OpenSSL hack!
- BIO* memoryBio = BIO_new_mem_buf(reinterpret_cast<void *>(byteSeq.begin()), byteSeq.size());
+ ICE_METHOD_INV("OpenSSL::System::addKeyCert()");
- X509* x509 = PEM_read_bio_X509(memoryBio, 0, 0, 0);
+ string privKey = privateKey;
- if (!x509)
+ if (privKey.empty())
{
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB);
+ ICE_WARNING("No private key specified - using the certificate.");
+ privKey = publicKey;
+ }
+
+ // Make a key pair based on the Base64 encoded strings
+ RSAKeyPair keyPair(privateKey, publicKey);
+
+ // Janitors to ensure that everything gets cleaned up properly
+ RSAJanitor rsaJanitor(keyPair.getRSAPrivateKey());
+ X509Janitor x509Janitor(keyPair.getX509PublicKey());
+
+ // Set which Public Key file to use.
+ if (SSL_CTX_use_certificate(sslContext, x509Janitor.get()) <= 0)
+ {
ContextException contextEx(__FILE__, __LINE__);
- contextEx._message = "Unable to load Public Key from memory buffer.";
+ contextEx._message = "Unable to set certificate from memory.";
string sslError = sslGetErrors();
if (!sslError.empty())
@@ -1169,33 +985,17 @@ IceSecurity::Ssl::OpenSSL::System::byteSeqToX509(ByteSeq& byteSeq)
contextEx._message += sslError;
}
-
ICE_EXCEPTION(contextEx._message);
throw contextEx;
}
- BIO_free(memoryBio);
-
- return x509;
-}
-
-RSA*
-IceSecurity::Ssl::OpenSSL::System::byteSeqToKey(ByteSeq& byteSeq)
-{
- // Create a BIO that reads directly from our ByteSeq!
- // NOTE: The reinterpret_cast is required, nasty OpenSSL hack!
- BIO* memoryBio = BIO_new_mem_buf(reinterpret_cast<void *>(byteSeq.begin()), byteSeq.size());
-
- RSA* rsa = PEM_read_bio_RSAPrivateKey(memoryBio, 0, 0, 0);
-
- if (!rsa)
+ // Set which Private Key file to use.
+ if (SSL_CTX_use_RSAPrivateKey(sslContext, rsaJanitor.get()) <= 0)
{
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
-
ContextException contextEx(__FILE__, __LINE__);
- contextEx._message = "Unable to load Private Key from memory buffer.";
+ contextEx._message = "Unable to set private key from memory.";
string sslError = sslGetErrors();
if (!sslError.empty())
@@ -1204,112 +1004,11 @@ IceSecurity::Ssl::OpenSSL::System::byteSeqToKey(ByteSeq& byteSeq)
contextEx._message += sslError;
}
-
ICE_EXCEPTION(contextEx._message);
throw contextEx;
}
-
- BIO_free(memoryBio);
-
- return rsa;
-}
-
-void
-IceSecurity::Ssl::OpenSSL::System::addKeyCert(SSL_CTX* sslContext,
- const string& privateKey,
- const string& publicKey)
-{
- ICE_METHOD_INV("OpenSSL::System::addKeyCert()");
-
- string privKey = privateKey;
-
- if (privKey.empty())
- {
- ICE_WARNING("No private key specified - using the certificate.");
-
- privKey = publicKey;
- }
-
- //
- // Convert the strings containing the Key (Private Key) and Certificate (Public Key)
- // into byte sequences.
- //
- ByteSeq publicKeyByteSeq;
- ByteSeq privateKeyByteSeq;
-
- publicKeyByteSeq.reserve(privateKey.size());
- privateKeyByteSeq.reserve(publicKey.size());
-
- std::copy(privateKey.begin(), privateKey.end(), back_inserter(privateKeyByteSeq));
- std::copy(publicKey.begin(), publicKey.end(), back_inserter(publicKeyByteSeq));
-
- X509* x509 = 0;
- RSA* rsa = 0;
-
- try
- {
- // These methods should throw exceptions if they can't perform the conversion.
- x509 = byteSeqToX509(publicKeyByteSeq);
- rsa = byteSeqToKey(privateKeyByteSeq);
-
- // Set which Public Key file to use.
- if (SSL_CTX_use_certificate(sslContext, x509) <= 0)
- {
- ContextException contextEx(__FILE__, __LINE__);
-
- contextEx._message = "Unable to set certificate from memory.";
- string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- contextEx._message += "\n";
- contextEx._message += sslError;
- }
-
-
- ICE_EXCEPTION(contextEx._message);
-
- throw contextEx;
- }
-
- // Set which Private Key file to use.
- if (SSL_CTX_use_RSAPrivateKey(sslContext, rsa) <= 0)
- {
- ContextException contextEx(__FILE__, __LINE__);
-
- contextEx._message = "Unable to set private key from memory.";
- string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- contextEx._message += "\n";
- contextEx._message += sslError;
- }
-
- ICE_EXCEPTION(contextEx._message);
-
- throw contextEx;
- }
- }
- catch (...)
- {
- if (x509)
- {
- X509_free(x509);
- }
-
- if (rsa)
- {
- RSA_free(rsa);
- }
-
- throw;
- }
-
- X509_free(x509);
- RSA_free(rsa);
-
+
// Check to see if the Private and Public keys that have been
// set against the SSL context match up.
if (!SSL_CTX_check_private_key(sslContext))
diff --git a/cpp/src/Ice/SslSystemOpenSSL.h b/cpp/src/Ice/SslSystemOpenSSL.h
index beaa682a631..970d8a2b30c 100644
--- a/cpp/src/Ice/SslSystemOpenSSL.h
+++ b/cpp/src/Ice/SslSystemOpenSSL.h
@@ -153,8 +153,6 @@ private:
void processCertificate(SSL_CTX*, const CertificateDesc&);
void addKeyCert(SSL_CTX*, const CertificateFile&, const CertificateFile&);
- X509* byteSeqToX509(ByteSeq&);
- RSA* byteSeqToKey(ByteSeq&);
void addKeyCert(SSL_CTX*, const string&, const string&);
SSL_CTX* createContext(SslProtocol);
diff --git a/cpp/src/Ice/ice.dsp b/cpp/src/Ice/ice.dsp
index 855020d2652..10f9ed1483a 100644
--- a/cpp/src/Ice/ice.dsp
+++ b/cpp/src/Ice/ice.dsp
@@ -308,6 +308,14 @@ SOURCE=.\SslCertificateDesc.cpp
# End Source File
# Begin Source File
+SOURCE=.\SslCertificateVerifier.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslCertificateVerifierOpenSSL.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\SslConfig.cpp
# End Source File
# Begin Source File
@@ -344,6 +352,22 @@ SOURCE=.\SslGeneralConfig.cpp
# End Source File
# Begin Source File
+SOURCE=.\SslJanitors.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslOpenSSLUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslRSACertificateGen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslRSAKeyPair.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\SslSystem.cpp
# End Source File
# Begin Source File
@@ -776,6 +800,18 @@ SOURCE=.\SslCertificateDesc.h
# End Source File
# Begin Source File
+SOURCE=.\SslCertificateVerifier.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslCertificateVerifierF.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslCertificateVerifierOpenSSL.h
+# End Source File
+# Begin Source File
+
SOURCE=.\SslConfig.h
# End Source File
# Begin Source File
@@ -796,6 +832,10 @@ SOURCE=.\SslConnectionOpenSSLClient.h
# End Source File
# Begin Source File
+SOURCE=.\SslConnectionOpenSSLF.h
+# End Source File
+# Begin Source File
+
SOURCE=.\SslConnectionOpenSSLServer.h
# End Source File
# Begin Source File
@@ -812,6 +852,30 @@ SOURCE=.\SslGeneralConfig.h
# End Source File
# Begin Source File
+SOURCE=.\SslJanitors.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SslOpenSSLUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Ice\SslRSACertificateGen.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Ice\SslRSACertificateGenF.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Ice\SslRSAKeyPair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Ice\SslRSAKeyPairF.h
+# End Source File
+# Begin Source File
+
SOURCE=.\SslSystem.h
# End Source File
# Begin Source File
diff --git a/cpp/src/IceUtil/Base64.cpp b/cpp/src/IceUtil/Base64.cpp
new file mode 100644
index 00000000000..7f65da07865
--- /dev/null
+++ b/cpp/src/IceUtil/Base64.cpp
@@ -0,0 +1,265 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IceUtil/Base64.h>
+#include <iostream>
+
+using namespace std;
+
+string
+IceUtil::Base64::encode(const ByteSeq& plainSeq)
+{
+ string retval;
+
+ if (plainSeq.size() == 0)
+ {
+ return retval;
+ }
+
+ // Reserve enough space for the returned base64 string
+ long base64Bytes = (((plainSeq.size() * 4L) / 3L) + 1L);
+ long newlineBytes = (((base64Bytes * 2L) / 76L) + 1L);
+ long totalBytes = base64Bytes + newlineBytes;
+
+ retval.reserve(totalBytes);
+
+ unsigned char by1 = 0;
+ unsigned char by2 = 0;
+ unsigned char by3 = 0;
+ unsigned char by4 = 0;
+ unsigned char by5 = 0;
+ unsigned char by6 = 0;
+ unsigned char by7 = 0;
+
+ for (unsigned int i = 0; i < plainSeq.size(); i += 3)
+ {
+ by1 = plainSeq[i];
+ by2 = 0;
+ by3 = 0;
+
+ if ((i + 1) < plainSeq.size())
+ {
+ by2 = plainSeq[i+1];
+ }
+
+ if ((i + 2) < plainSeq.size())
+ {
+ by3 = plainSeq[i+2];
+ }
+
+ by4 = by1 >> 2;
+ by5 = ((by1 & 0x3) << 4) | (by2 >> 4);
+ by6 = ((by2 & 0xf) << 2) | (by3 >> 6);
+ by7 = by3 & 0x3f;
+
+ retval += encode(by4);
+ retval += encode(by5);
+
+ if ((i + 1) < plainSeq.size())
+ {
+ retval += encode(by6);
+ }
+ else
+ {
+ retval += "=";
+ }
+
+ if ((i + 2) < plainSeq.size())
+ {
+ retval += encode(by7);
+ }
+ else
+ {
+ retval += "=";
+ }
+ }
+
+ string outString;
+ outString.reserve(totalBytes);
+ string::iterator iter = retval.begin();
+
+ while ((retval.end() - iter) > 76)
+ {
+ copy(iter, iter+76, back_inserter(outString));
+ outString += "\r\n";
+ iter += 76;
+ }
+
+ copy(iter, retval.end(), back_inserter(outString));
+
+ return outString;
+}
+
+IceUtil::ByteSeq
+IceUtil::Base64::decode(const string& _str)
+{
+ string str;
+
+ for (unsigned int j = 0; j < _str.length(); j++)
+ {
+ if (isBase64(_str[j]))
+ {
+ str += _str[j];
+ }
+ }
+
+ ByteSeq retval;
+
+ if (str.length() == 0)
+ {
+ return retval;
+ }
+
+ // Figure out how long the final sequence is going to be.
+ long lines = _str.size() / 78;
+ long totalBytes = (lines * 76) + (((_str.size() - (lines * 78)) * 3) / 4);
+
+ retval.reserve(totalBytes);
+
+ unsigned char by1 = 0;
+ unsigned char by2 = 0;
+ unsigned char by3 = 0;
+ unsigned char by4 = 0;
+
+ char c1, c2, c3, c4;
+
+ for (unsigned int i = 0; i < str.length(); i += 4)
+ {
+ c1='A';
+ c2='A';
+ c3='A';
+ c4='A';
+
+ c1 = str[i];
+
+ if ((i + 1) < str.length())
+ {
+ c2 = str[i+1];
+ }
+
+ if ((i + 2) < str.length())
+ {
+ c3 = str[i+2];
+ }
+
+ if ((i + 3) < str.length())
+ {
+ c4 = str[i+3];
+ }
+
+ by1 = decode(c1);
+ by2 = decode(c2);
+ by3 = decode(c3);
+ by4 = decode(c4);
+
+ retval.push_back((by1 << 2) | (by2 >> 4));
+
+ if (c3 != '=')
+ {
+ retval.push_back(((by2 & 0xf) << 4) | (by3 >> 2));
+ }
+
+ if (c4 != '=')
+ {
+ retval.push_back(((by3 & 0x3) << 6) | by4);
+ }
+ }
+
+ return retval;
+}
+
+char
+IceUtil::Base64::encode(unsigned char uc)
+{
+ if (uc < 26)
+ {
+ return 'A'+uc;
+ }
+
+ if (uc < 52)
+ {
+ return 'a'+(uc-26);
+ }
+
+ if (uc < 62)
+ {
+ return '0'+(uc-52);
+ }
+
+ if (uc == 62)
+ {
+ return '+';
+ }
+
+ return '/';
+}
+
+unsigned char
+IceUtil::Base64::decode(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ {
+ return c - 'A';
+ }
+
+ if (c >= 'a' && c <= 'z')
+ {
+ return c - 'a' + 26;
+ }
+
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0' + 52;
+ }
+
+ if (c == '+')
+ {
+ return 62;
+ }
+
+ return 63;
+}
+
+
+bool
+IceUtil::Base64::isBase64(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ {
+ return true;
+ }
+
+ if (c >= 'a' && c <= 'z')
+ {
+ return true;
+ }
+
+ if (c >= '0' && c <= '9')
+ {
+ return true;
+ }
+
+ if (c == '+')
+ {
+ return true;
+ }
+
+ if (c == '/')
+ {
+ return true;
+ }
+
+ if (c == '=')
+ {
+ return true;
+ }
+
+ return false;
+}
diff --git a/cpp/src/IceUtil/iceutil.dsp b/cpp/src/IceUtil/iceutil.dsp
index de63136a9a4..8f3c5261c04 100644
--- a/cpp/src/IceUtil/iceutil.dsp
+++ b/cpp/src/IceUtil/iceutil.dsp
@@ -104,6 +104,10 @@ PostBuild_Cmds=copy Debug\iceutil001d.* ..\..\lib
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=.\Base64.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\Cond.cpp
# End Source File
# Begin Source File
@@ -140,6 +144,10 @@ SOURCE=.\UUID.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
+SOURCE=..\..\include\IceUtil\Base64.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\IceUtil\Cond.h
# End Source File
# Begin Source File