Return to TLS.cpp CVS log | Up to [Pegasus] / pegasus / src / Pegasus / Common |
File: [Pegasus] / pegasus / src / Pegasus / Common / TLS.cpp
(download)
Revision: 1.51, Tue Mar 14 02:06:21 2006 UTC (18 years, 3 months ago) by sushma.fernandes Branch: MAIN CVS Tags: TASK-PEP250_RPMProvider-root, TASK-PEP250_RPMProvider-merged_out_to_branch, TASK-PEP250_RPMProvider-merged_out_from_trunk, TASK-PEP250_RPMProvider-merged_in_to_trunk, TASK-PEP250_RPMProvider-merged_in_from_branch, TASK-PEP250_RPMProvider-branch, TASK-PEP245_CimErrorInfrastructure-root, TASK-PEP245_CimErrorInfrastructure-merged_out_to_branch, TASK-PEP245_CimErrorInfrastructure-merged_out_from_trunk, TASK-PEP245_CimErrorInfrastructure-merged_in_to_trunk, TASK-PEP245_CimErrorInfrastructure-merged_in_from_branch, TASK-PEP245_CimErrorInfrastructure-branch, TASK-PEP241_OpenPegasusStressTests-root, TASK-PEP241_OpenPegasusStressTests-merged_out_to_branch, TASK-PEP241_OpenPegasusStressTests-merged_out_from_trunk, TASK-PEP241_OpenPegasusStressTests-merged_in_to_trunk, TASK-PEP241_OpenPegasusStressTests-merged_in_from_branch, TASK-PEP241_OpenPegasusStressTests-branch, TASK-BUG4011_WinLocalConnect-root, TASK-BUG4011_WinLocalConnect-merged_out_to_branch, TASK-BUG4011_WinLocalConnect-merged_out_from_trunk, TASK-BUG4011_WinLocalConnect-merged_in_to_trunk, TASK-BUG4011_WinLocalConnect-merged_in_from_branch, TASK-BUG4011_WinLocalConnect-branch Changes since 1.50: +6 -2 lines BUG#: 4878 TITLE: Allow SSL CRL functionality to be optionally disabled DESCRIPTION: Added a build-time configuration setting PEGASUS_ENABLE_SSL_CRL_VERIFICATION. Updated the ssltrustmgr, CertificateProvider, Config and SSLContext components. |
//%2006//////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation, The Open Group. // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; Symantec Corporation; The Open Group. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //============================================================================== // // Author: Markus Mueller (sedgewick_de@yahoo.de) // // Modified By: // Bapu Patil, Hewlett-Packard Company ( bapu_patil@hp.com ) // Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com) // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com) // Heather Sterling, IBM (hsterl@us.ibm.com) // Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for PEP#101 // David Dillard, Symantec Corp. (david_dillard@symantec.com) // Carol Ann Krug Graves, Hewlett-Packard Company // (carolann_graves@hp.com) // Aruran, IBM (ashanmug@in.ibm.com) for Bug# 4549 // //%///////////////////////////////////////////////////////////////////////////// #include <Pegasus/Common/Socket.h> #include <Pegasus/Common/Tracer.h> #include <Pegasus/Common/SSLContextRep.h> #include <Pegasus/Common/SSLContext.h> #include <Pegasus/Common/IPC.h> #include <Pegasus/Common/MessageLoader.h> //l10n #include <Pegasus/Common/FileSystem.h> #include "TLS.h" // // use the following definitions only if SSL is available // #ifdef PEGASUS_HAS_SSL PEGASUS_NAMESPACE_BEGIN // // Basic SSL socket // SSLSocket::SSLSocket( PEGASUS_SOCKET socket, SSLContext * sslcontext, ReadWriteSem * sslContextObjectLock, Boolean exportConnection) : _SSLConnection(0), _socket(socket), _SSLContext(sslcontext), _sslContextObjectLock(sslContextObjectLock), _SSLCallbackInfo(0), _certificateVerified(false), _exportConnection(exportConnection) { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::SSLSocket()"); _sslReadErrno = 0; // // create the SSLConnection area // if (!( _SSLConnection = SSL_new(_SSLContext->_rep->getContext() ))) { PEG_METHOD_EXIT(); //l10n //throw( SSLException("Could not get SSL Connection Area")); MessageLoaderParms parms("Common.TLS.COULD_NOT_GET_SSL_CONNECTION_AREA", "Could not get SSL Connection Area"); throw SSLException(parms); } // This try/catch block is necessary so that we can free the SSL Connection // Area if any exceptions are thrown. try { // // set the verification callback data // //we are only storing one set of data, so we can just use index 0, this is defined in SSLContext.h //int index = SSL_get_ex_new_index(0, (void*)"pegasus", NULL, NULL, NULL); // // Create a new callback info for each new connection // _SSLCallbackInfo.reset(new SSLCallbackInfo(_SSLContext->getSSLCertificateVerifyFunction() #ifdef PEGASUS_ENABLE_SSL_CRL_VERIFICATION , _SSLContext->getCRLStore())); #else )); #endif if (SSL_set_ex_data(_SSLConnection, SSLCallbackInfo::SSL_CALLBACK_INDEX, _SSLCallbackInfo.get())) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "--->SSL: Set callback info"); } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "--->SSL: Error setting callback info"); } // // and connect the active socket with the ssl operation // if (!(SSL_set_fd(_SSLConnection, _socket) )) { PEG_METHOD_EXIT(); //l10n //throw( SSLException("Could not link socket to SSL Connection")); MessageLoaderParms parms("Common.TLS.COULD_NOT_LINK_SOCKET", "Could not link socket to SSL Connection"); throw SSLException(parms); } } catch(...) { SSL_free(_SSLConnection); throw; } PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Created SSL socket"); PEG_METHOD_EXIT(); } SSLSocket::~SSLSocket() { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::~SSLSocket()"); SSL_free(_SSLConnection); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Deleted SSL socket"); PEG_METHOD_EXIT(); } Boolean SSLSocket::incompleteReadOccurred(Sint32 retCode) { Sint32 err = SSL_get_error(_SSLConnection, retCode); Tracer::trace(TRC_SSL, Tracer::LEVEL4, "In SSLSocket::incompleteReadOccurred : err = %d", err); return ((err == SSL_ERROR_SYSCALL) && (_sslReadErrno == EAGAIN || _sslReadErrno == EINTR)) || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE; } Sint32 SSLSocket::read(void* ptr, Uint32 size) { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::read()"); Sint32 rc; PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: (r) "); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, SSL_state_string_long(_SSLConnection) ); rc = SSL_read(_SSLConnection, (char *)ptr, size); _sslReadErrno = errno; PEG_METHOD_EXIT(); return rc; } Sint32 SSLSocket::write( const void* ptr, Uint32 size) { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::write()"); Sint32 rc; PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: (w) "); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, SSL_state_string_long(_SSLConnection) ); rc = SSL_write(_SSLConnection, (char *)ptr, size); PEG_METHOD_EXIT(); return rc; } void SSLSocket::close() { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::close()"); SSL_shutdown(_SSLConnection); Socket::close(_socket); PEG_METHOD_EXIT(); } void SSLSocket::enableBlocking() { Socket::enableBlocking(_socket); } void SSLSocket::disableBlocking() { Socket::disableBlocking(_socket); } void SSLSocket::initializeInterface() { Socket::initializeInterface(); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: initialized SSL"); } void SSLSocket::uninitializeInterface() { Socket::uninitializeInterface(); } Sint32 SSLSocket::accept() { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::accept()"); Sint32 ssl_rc,ssl_rsn; //ATTN: these methods get implicitly done with the SSL_accept call //SSL_do_handshake(_SSLConnection); //SSL_set_accept_state(_SSLConnection); // Make sure the SSLContext object is not updated during this operation. ReadLock rlock(*_sslContextObjectLock); ssl_rc = SSL_accept(_SSLConnection); if (ssl_rc < 0) { ssl_rsn = SSL_get_error(_SSLConnection, ssl_rc); Tracer::trace(TRC_SSL, Tracer::LEVEL3, "---> SSL: Not accepted %d", ssl_rsn ); if ((ssl_rsn == SSL_ERROR_WANT_READ) || (ssl_rsn == SSL_ERROR_WANT_WRITE)) { PEG_METHOD_EXIT(); return 0; } else { PEG_METHOD_EXIT(); return -1; } } else if (ssl_rc == 0) { ssl_rsn = SSL_get_error(_SSLConnection, ssl_rc); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "Shutdown SSL_accept()"); Tracer::trace(TRC_SSL, Tracer::LEVEL4, "Error Code: %d", ssl_rsn ); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "Error string: " + String(ERR_error_string(ssl_rc, NULL))); PEG_METHOD_EXIT(); return -1; } PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Accepted"); // // If peer certificate verification is enabled or request received on // export connection, get the peer certificate and verify the trust // store validation result. // if (_SSLContext->isPeerVerificationEnabled() || _exportConnection) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "Attempting to certify client"); // // get client's certificate // X509 * client_cert = SSL_get_peer_certificate(_SSLConnection); if (client_cert != NULL) { // // get certificate verification result // int verifyResult = SSL_get_verify_result(_SSLConnection); Tracer::trace(TRC_SSL, Tracer::LEVEL3, "Verification Result: %d", verifyResult ); if (verifyResult == X509_V_OK) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2, "---> SSL: Client Certificate verified."); // // set flag to indicate that the certificate was verified in // the trust store. // _certificateVerified = true; } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2, "---> SSL: Client Certificate not verified"); // // On export connection, do not continue if the // certificate is not verified. // if (_exportConnection) { X509_free(client_cert); PEG_METHOD_EXIT(); return -1; } } X509_free(client_cert); } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Client not certified, no certificate received"); // // On export connection, do not continue if peer certificate // is not received // if (_exportConnection) { PEG_METHOD_EXIT(); return -1; } } } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Client certification disabled"); } PEG_METHOD_EXIT(); return 1; } Sint32 SSLSocket::connect() { PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::connect()"); Sint32 ssl_rc,ssl_rsn; SSL_set_connect_state(_SSLConnection); redo_connect: ssl_rc = SSL_connect(_SSLConnection); if (ssl_rc < 0) { ssl_rsn = SSL_get_error(_SSLConnection, ssl_rc); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Not connected " + ssl_rsn ); if ((ssl_rsn == SSL_ERROR_WANT_READ) || (ssl_rsn == SSL_ERROR_WANT_WRITE)) { goto redo_connect; } else { PEG_METHOD_EXIT(); return -1; } } else if (ssl_rc == 0) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Shutdown SSL_connect()"); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "Error string: " + String(ERR_error_string(ssl_rc, NULL))); PEG_METHOD_EXIT(); return -1; } PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Connected"); if (_SSLContext->isPeerVerificationEnabled()) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "Attempting to verify server certificate."); X509 * server_cert = SSL_get_peer_certificate(_SSLConnection); if (server_cert != NULL) { // // Do not check the verification result using SSL_get_verify_result here to see whether or not to continue. // The prepareForCallback does not reset the verification result, so it will still contain the original error. // If the client chose to override the default error in the callback and return true, we got here and // should proceed with the transaction. Otherwise, the handshake was already terminated. // if (SSL_get_verify_result(_SSLConnection) == X509_V_OK) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "--->SSL: Server Certificate verified."); } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "--->SSL: Server Certificate not verified, but the callback overrode the default error."); } X509_free (server_cert); } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "-->SSL: Server not certified, no certificate received."); PEG_METHOD_EXIT(); return -1; } } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Server certification disabled"); } PEG_METHOD_EXIT(); return ssl_rc; } Boolean SSLSocket::isPeerVerificationEnabled() { return (_SSLContext->isPeerVerificationEnabled()); } Array<SSLCertificateInfo*> SSLSocket::getPeerCertificateChain() { Array<SSLCertificateInfo*> peerCertificate; if (_SSLCallbackInfo.get()) { peerCertificate = _SSLCallbackInfo->_rep->peerCertificate; } return peerCertificate; } Boolean SSLSocket::isCertificateVerified() { return _certificateVerified; } // // MP_Socket (Multi-purpose Socket class) // MP_Socket::MP_Socket(PEGASUS_SOCKET socket) : _socket(socket), _isSecure(false) {} MP_Socket::MP_Socket( PEGASUS_SOCKET socket, SSLContext * sslcontext, ReadWriteSem * sslContextObjectLock, Boolean exportConnection) { PEG_METHOD_ENTER(TRC_SSL, "MP_Socket::MP_Socket()"); if (sslcontext != NULL) { _isSecure = true; _sslsock = new SSLSocket( socket, sslcontext, sslContextObjectLock, exportConnection); } else { _isSecure = false; _socket = socket; } PEG_METHOD_EXIT(); } MP_Socket::~MP_Socket() { PEG_METHOD_ENTER(TRC_SSL, "MP_Socket::~MP_Socket()"); if (_isSecure) { delete _sslsock; } PEG_METHOD_EXIT(); } Boolean MP_Socket::isSecure() {return _isSecure;} Boolean MP_Socket::incompleteReadOccurred(Sint32 retCode) { if (_isSecure) return(_sslsock->incompleteReadOccurred(retCode)); return (retCode <= 0); } PEGASUS_SOCKET MP_Socket::getSocket() { if (_isSecure) return _sslsock->getSocket(); else return _socket; } Sint32 MP_Socket::read(void * ptr, Uint32 size) { if (_isSecure) return _sslsock->read(ptr,size); else return Socket::read(_socket,ptr,size); } Sint32 MP_Socket::write(const void * ptr, Uint32 size) { if (_isSecure) return _sslsock->write(ptr,size); else return Socket::write(_socket,ptr,size); } void MP_Socket::close() { if (_isSecure) _sslsock->close(); else Socket::close(_socket); } void MP_Socket::enableBlocking() { if (_isSecure) _sslsock->enableBlocking(); else Socket::enableBlocking(_socket); } void MP_Socket::disableBlocking() { if (_isSecure) _sslsock->disableBlocking(); else Socket::disableBlocking(_socket); } Sint32 MP_Socket::accept() { if (_isSecure) { return (_sslsock->accept()); } return 1; } Sint32 MP_Socket::connect() { if (_isSecure) if (_sslsock->connect() < 0) return -1; return 0; } Boolean MP_Socket::isPeerVerificationEnabled() { if (_isSecure) { return (_sslsock->isPeerVerificationEnabled()); } return false; } Array<SSLCertificateInfo*> MP_Socket::getPeerCertificateChain() { Array<SSLCertificateInfo*> peerCertificate; if (_isSecure) { peerCertificate = _sslsock->getPeerCertificateChain(); } return peerCertificate; } Boolean MP_Socket::isCertificateVerified() { if (_isSecure) { return (_sslsock->isCertificateVerified()); } return false; } PEGASUS_NAMESPACE_END #else PEGASUS_NAMESPACE_BEGIN MP_Socket::MP_Socket(PEGASUS_SOCKET socket) : _socket(socket), _isSecure(false) {} MP_Socket::MP_Socket( PEGASUS_SOCKET socket, SSLContext * sslcontext, ReadWriteSem * sslContextObjectLock, Boolean exportConnection) : _socket(socket), _isSecure(false) {} MP_Socket::~MP_Socket() {} Boolean MP_Socket::isSecure() {return _isSecure;} Boolean MP_Socket::incompleteReadOccurred(Sint32 retCode) { return (retCode <= 0); } PEGASUS_SOCKET MP_Socket::getSocket() { return _socket; } Sint32 MP_Socket::read(void * ptr, Uint32 size) { return Socket::read(_socket,ptr,size); } Sint32 MP_Socket::write(const void * ptr, Uint32 size) { return Socket::write(_socket,ptr,size); } void MP_Socket::close() { Socket::close(_socket); } void MP_Socket::enableBlocking() { Socket::enableBlocking(_socket); } void MP_Socket::disableBlocking() { Socket::disableBlocking(_socket); } Sint32 MP_Socket::accept() { return 1; } Sint32 MP_Socket::connect() { return 0; } Boolean MP_Socket::isPeerVerificationEnabled() { return false; } Array<SSLCertificateInfo*> MP_Socket::getPeerCertificateChain() { // // Return empty array // return Array<SSLCertificateInfo*>(); } Boolean MP_Socket::isCertificateVerified() { return false; } PEGASUS_NAMESPACE_END #endif // end of PEGASUS_HAS_SSL
No CVS admin address has been configured |
Powered by ViewCVS 0.9.2 |