diff options
Diffstat (limited to 'cpp/src')
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
|