📄 tls.cpp
字号:
//%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.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#include <Pegasus/Common/Socket.h>#include <Pegasus/Common/Tracer.h>#include <Pegasus/Common/SSLContextRep.h>#include <Pegasus/Common/SSLContext.h>#include <Pegasus/Common/MessageLoader.h>#include <Pegasus/Common/FileSystem.h>#include "TLS.h"#ifdef PEGASUS_OS_ZOS#include "SocketzOS_inline.h"#endif//// use the following definitions only if SSL is available//#ifdef PEGASUS_HAS_SSLPEGASUS_NAMESPACE_BEGIN//// Basic SSL socket//SSLSocket::SSLSocket( SocketHandle socket, SSLContext * sslcontext, ReadWriteSem * sslContextObjectLock) : _SSLConnection(0), _socket(socket), _SSLContext(sslcontext), _sslContextObjectLock(sslContextObjectLock), _SSLCallbackInfo(0), _certificateVerified(false){ PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::SSLSocket()"); _sslReadErrno = 0; // // create the SSLConnection area // if (!( _SSLConnection = SSL_new(_SSLContext->_rep->getContext() ))) { PEG_METHOD_EXIT(); 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(); 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::timedWrite( const void* ptr, Uint32 size, Uint32 socketWriteTimeout){ PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::timedWrite()"); Sint32 bytesWritten = 0; Sint32 totalBytesWritten = 0; Boolean socketTimedOut = false; Uint32 selreturn = 0; while (1) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: (w) "); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, SSL_state_string_long(_SSLConnection) ); bytesWritten = SSL_write(_SSLConnection, (char *)ptr, size); // Some data written this cycle ? // Add it to the total amount of written data. if (bytesWritten > 0) { totalBytesWritten += bytesWritten; socketTimedOut = false; } // All data written ? return amount of data written if ((Uint32)bytesWritten == size) { // exit the while loop break; } // If data has been written partially, we resume writing data // this also accounts for the case of a signal interrupt // (i.e. errno = EINTR) if (bytesWritten > 0) { size -= bytesWritten; ptr = (void *)((char *)ptr + bytesWritten); continue; } // Something went wrong, SSL return with everything not > 0 is an error if (bytesWritten <= 0) { // if we already waited for the socket to get ready, bail out if (socketTimedOut) { // bytesWritten contains the error indication PEG_METHOD_EXIT(); return bytesWritten; } // just interrupted by a signal, try again#ifdef PEGASUS_OS_TYPE_WINDOWS if (WSAGetLastError() == WSAEINTR) continue;#else if (errno == EINTR) continue;#endif // socket not ready ...#ifdef PEGASUS_OS_TYPE_WINDOWS if (WSAGetLastError() == WSAEWOULDBLOCK)#else if (errno == EAGAIN || errno == EWOULDBLOCK)#endif { fd_set fdwrite; // max. timeout seconds waiting for the socket to get ready struct timeval tv = {socketWriteTimeout , 0 }; FD_ZERO(&fdwrite); FD_SET(_socket, &fdwrite); selreturn = select(FD_SETSIZE, NULL, &fdwrite, NULL, &tv); if (selreturn == 0) socketTimedOut = true; // ran out of time continue; } // bytesWritten contains the error indication PEG_METHOD_EXIT(); return bytesWritten; } } PEG_METHOD_EXIT(); return totalBytesWritten;}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()) { 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"); } X509_free(client_cert); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -