📄 sslcontext.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.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#ifdef PEGASUS_HAS_SSL#include <Pegasus/Common/Config.h>#include "Network.h"#define OPENSSL_NO_KRB5 1#include <openssl/err.h>#include <openssl/ssl.h>#include <openssl/rand.h>#else#define SSL_CTX void#endif // end of PEGASUS_HAS_SSL#include <Pegasus/Common/Socket.h>#include <Pegasus/Common/Tracer.h>#include <Pegasus/Common/FileSystem.h>#include <time.h>#include <Pegasus/Common/MessageLoader.h>#include <Pegasus/Common/Formatter.h>#include "SSLContext.h"#include "SSLContextRep.h"#ifdef PEGASUS_OS_OS400#include "SSLWrapperOS400.h"#endif//// Typedef's for OpenSSL callback functions.//extern "C"{ typedef void (* CRYPTO_SET_LOCKING_CALLBACK)(int, int, const char *, int); typedef unsigned long (* CRYPTO_SET_ID_CALLBACK)(void);};typedef struct x509_store_ctx_st X509_STORE_CTX;typedef struct Timestamp{ char year[4]; char month[2]; char day[2]; char hour[2]; char minutes[2]; char seconds[2]; char dot; char microSeconds[6]; char plusOrMinus; char utcOffset[3]; char padding[3];} Timestamp_t;PEGASUS_USING_STD;PEGASUS_NAMESPACE_BEGINconst int SSLCallbackInfo::SSL_CALLBACK_INDEX = 0;//// use the following definitions only if SSL is available//#ifdef PEGASUS_HAS_SSL// Mutex for SSL locks which will get initialized by AutoArrayPtr constructor.AutoArrayPtr<Mutex> SSLContextRep::_sslLocks;// Mutex for _countRep.Mutex SSLContextRep::_countRepMutex;// Initialise _count for SSLContextRep objects.int SSLContextRep::_countRep = 0;//// Convert ASN1_UTCTIME to CIMDateTime//CIMDateTime getDateTime(const ASN1_UTCTIME *utcTime){ struct tm time; int offset; Timestamp_t timeStamp; char tempString[80]; char plusOrMinus = '+'; unsigned char* utcTimeData = utcTime->data; memset(&time, '\0', sizeof(time));#define g2(p) ( ( (p)[0] - '0' ) * 10 + (p)[1] - '0' ) if (utcTime->type == V_ASN1_GENERALIZEDTIME) { time.tm_year = g2(utcTimeData) * 100; utcTimeData += 2; // Remaining data is equivalent to ASN1_UTCTIME type time.tm_year += g2(utcTimeData); } else { time.tm_year = g2(utcTimeData); if (time.tm_year < 50) { time.tm_year += 2000; } else { time.tm_year += 1900; } } time.tm_mon = g2(utcTimeData + 2) - 1; time.tm_mday = g2(utcTimeData + 4); time.tm_hour = g2(utcTimeData + 6); time.tm_min = g2(utcTimeData + 8); time.tm_sec = g2(utcTimeData + 10); if (utcTimeData[12] == 'Z') { offset = 0; } else { offset = g2(utcTimeData + 13) * 60 + g2(utcTimeData + 15); if (utcTimeData[12] == '-') { plusOrMinus = '-'; } }#undef g2 memset((void *)&timeStamp, 0, sizeof(Timestamp_t)); // Format the date. sprintf((char *) &timeStamp,"%04d%02d%02d%02d%02d%02d.%06d%04d", time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, 0, offset); timeStamp.plusOrMinus = plusOrMinus; CIMDateTime dateTime; dateTime.clear(); strcpy(tempString, (char *)&timeStamp); dateTime.set(tempString); return dateTime;}//// Static class used to define C++ callback functions for OpenSSL.//class SSLCallback{public: static int verificationCallback( int preVerifyOk, X509_STORE_CTX* ctx); static int verificationCRLCallback( int ok, X509_STORE_CTX* ctx, X509_STORE* sslCRLStore);};//// Callback function that is called by the OpenSSL library. This function// checks whether the certificate is listed in any of the CRL's//// return 1 if revoked, 0 otherwise//int SSLCallback::verificationCRLCallback( int ok, X509_STORE_CTX* ctx, X509_STORE* sslCRLStore){ PEG_METHOD_ENTER(TRC_SSL, "SSLCallback::verificationCRLCallback"); char buf[1024]; //check whether a CRL store was specified if (sslCRLStore == NULL) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: CRL store is NULL"); PEG_METHOD_EXIT(); return 0; } //get the current certificate info X509* currentCert; X509_NAME* issuerName; X509_NAME* subjectName; ASN1_INTEGER* serialNumber; currentCert = X509_STORE_CTX_get_current_cert(ctx); subjectName = X509_get_subject_name(currentCert); issuerName = X509_get_issuer_name(currentCert); serialNumber = X509_get_serialNumber(currentCert); //log certificate information //this is information in the "public" key, so it does no harm to log it X509_NAME_oneline(issuerName, buf, sizeof(buf)); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Certificate Data: Issuer/Subject"); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, buf); X509_NAME_oneline(subjectName, buf, sizeof(buf)); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, buf); //initialize the CRL store X509_STORE_CTX crlStoreCtx; X509_STORE_CTX_init(&crlStoreCtx, sslCRLStore, NULL, NULL); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Initialized CRL store"); //attempt to get a CRL issued by the certificate's issuer X509_OBJECT obj; if (X509_STORE_get_by_subject( &crlStoreCtx, X509_LU_CRL, issuerName, &obj) <= 0) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: No CRL by that issuer"); PEG_METHOD_EXIT(); return 0; } X509_STORE_CTX_cleanup(&crlStoreCtx); //get CRL X509_CRL* crl = obj.data.crl; if (crl == NULL) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL is null"); PEG_METHOD_EXIT(); return 0; } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Found CRL by that issuer"); } //get revoked certificates STACK_OF(X509_REVOKED)* revokedCerts = NULL; revokedCerts = X509_CRL_get_REVOKED(crl); int numRevoked = sk_X509_REVOKED_num(revokedCerts); Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: Number of certificates revoked by the issuer %d\n", numRevoked); //check whether the subject's certificate is revoked X509_REVOKED* revokedCert = NULL; for (int i = 0; i < sk_X509_REVOKED_num(revokedCerts); i++) { revokedCert = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i); //a matching serial number indicates revocation if (ASN1_INTEGER_cmp(revokedCert->serialNumber, serialNumber) == 0) { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2, "---> SSL: Certificate is revoked"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); PEG_METHOD_EXIT(); return 1; } } PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Certificate is not revoked at this level"); PEG_METHOD_EXIT(); return 0;}//// Callback function that is called by the OpenSSL library. This function// extracts X509 certficate information and pass that on to client application// callback function.// We HAVE to build the certificate in all cases since it's needed to get// the associated username out of the repository later in the transaction.//int SSLCallback::verificationCallback(int preVerifyOk, X509_STORE_CTX* ctx){ PEG_METHOD_ENTER(TRC_SSL, "SSLCallback::callback()"); char buf[256]; X509 *currentCert; SSL *ssl; int verifyError = X509_V_OK; int revoked = -1; Tracer::trace(TRC_SSL, Tracer::LEVEL4, "--->SSL: Preverify Error %d", verifyError); // // get the verification callback info specific to each SSL connection // ssl = (SSL*) X509_STORE_CTX_get_ex_data( ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); SSLCallbackInfo* exData = (SSLCallbackInfo*) SSL_get_ex_data( ssl, SSLCallbackInfo::SSL_CALLBACK_INDEX);#ifdef PEGASUS_ENABLE_SSL_CRL_VERIFICATION // // Check to see if a CRL path is defined // if (exData->_rep->crlStore != NULL) { revoked = verificationCRLCallback( preVerifyOk,ctx,exData->_rep->crlStore); Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL callback returned %d", revoked); if (revoked) //with the SSL callbacks '0' indicates failure { PEG_METHOD_EXIT(); return 0; } } Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL callback returned %d", revoked);#endif // // get the current certificate // currentCert = X509_STORE_CTX_get_current_cert(ctx); // // get the default verification error code // int errorCode = X509_STORE_CTX_get_error(ctx); // // get the depth of certificate chain // int depth = X509_STORE_CTX_get_error_depth(ctx); // // get the version on the certificate // long version = X509_get_version(currentCert); // // get the serial number of the certificate // long serialNumber = ASN1_INTEGER_get(X509_get_serialNumber(currentCert)); // // get the validity of the certificate // CIMDateTime notBefore = getDateTime(X509_get_notBefore(currentCert)); CIMDateTime notAfter = getDateTime(X509_get_notAfter(currentCert)); // // get the subject name on the certificate // X509_NAME_oneline(X509_get_subject_name(currentCert), buf, 256); String subjectName = String(buf); // // get the default verification error string // String errorStr = String(X509_verify_cert_error_string(errorCode)); // // log the error string if the default verification was failed // if (!preVerifyOk) { Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: certificate default verification error: %s", (const char*)errorStr.getCString()); } // // get the issuer name on the certificate //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -