Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:25

0001 #include "CondCore/CondDB/interface/FileUtils.h"
0002 #include "CondCore/CondDB/interface/Exception.h"
0003 #include "CondCore/CondDB/interface/Auth.h"
0004 #include "RelationalAccess/AuthenticationCredentials.h"
0005 #include "CoralCommon/Cipher.h"
0006 #include "RelationalAccess/AuthenticationServiceException.h"
0007 #include "CoralKernel/IPropertyManager.h"
0008 #include "CoralKernel/Property.h"
0009 #include "CoralKernel/Context.h"
0010 #include "CondCore/CondDB/interface/CoralServiceMacros.h"
0011 #include "Utilities/Xerces/interface/Xerces.h"
0012 #include "xercesc/parsers/XercesDOMParser.hpp"
0013 #include "xercesc/framework/MemBufInputSource.hpp"
0014 #include "xercesc/dom/DOM.hpp"
0015 #include "xercesc/sax/HandlerBase.hpp"
0016 #include "xercesc/util/XMLString.hpp"
0017 #include "xercesc/util/PlatformUtils.hpp"
0018 #include "XMLAuthenticationService.h"
0019 
0020 #include <cstdlib>
0021 #include <fcntl.h>
0022 #include <filesystem>
0023 #include <fstream>
0024 #include <memory>
0025 #include <sys/stat.h>
0026 
0027 #include "CoralBase/MessageStream.h"
0028 
0029 constexpr char XML_AUTHENTICATION_FILE[] = "authentication.xml";
0030 
0031 cond::XMLAuthenticationService::DataSourceEntry::DataSourceEntry(const std::string& serviceName,
0032                                                                  const std::string& connectionName)
0033     : m_serviceName(serviceName),
0034       m_connectionName(connectionName),
0035       m_default(new coral::AuthenticationCredentials(serviceName)),
0036       m_data() {}
0037 
0038 cond::XMLAuthenticationService::DataSourceEntry::~DataSourceEntry() {
0039   delete m_default;
0040   for (std::map<std::string, coral::AuthenticationCredentials*>::iterator iData = m_data.begin(); iData != m_data.end();
0041        ++iData)
0042     delete iData->second;
0043 }
0044 
0045 void cond::XMLAuthenticationService::DataSourceEntry::appendCredentialItem(const std::string& item,
0046                                                                            const std::string& value) {
0047   m_default->registerItem(item, value);
0048 }
0049 
0050 void cond::XMLAuthenticationService::DataSourceEntry::appendCredentialItemForRole(const std::string& item,
0051                                                                                   const std::string& value,
0052                                                                                   const std::string& role) {
0053   std::map<std::string, coral::AuthenticationCredentials*>::iterator iRole = m_data.find(role);
0054   if (iRole == m_data.end()) {
0055     iRole = m_data.insert(std::make_pair(role, new coral::AuthenticationCredentials(m_serviceName))).first;
0056   }
0057   iRole->second->registerItem(item, value);
0058 }
0059 
0060 const coral::IAuthenticationCredentials& cond::XMLAuthenticationService::DataSourceEntry::credentials() const {
0061   return *m_default;
0062 }
0063 
0064 const coral::IAuthenticationCredentials& cond::XMLAuthenticationService::DataSourceEntry::credentials(
0065     const std::string& role) const {
0066   /**
0067   std::map< std::string, coral::AuthenticationCredentials* >::const_iterator iRole = m_data.find( role );
0068   if ( iRole == m_data.end() )
0069     throw coral::UnknownRoleException( m_serviceName,
0070                                        m_connectionName,
0071                                        role );
0072   return *( iRole->second );
0073   **/
0074   return *m_default;
0075 }
0076 
0077 cond::XMLAuthenticationService::XMLAuthenticationService::XMLAuthenticationService(const std::string& key)
0078     : coral::Service(key), m_isInitialized(false), m_inputFileName(""), m_data(), m_mutexLock(), m_callbackID(0) {
0079   boost::function1<void, std::string> cb(std::bind(
0080       &cond::XMLAuthenticationService::XMLAuthenticationService::setAuthenticationPath, this, std::placeholders::_1));
0081 
0082   coral::Property* pm = dynamic_cast<coral::Property*>(
0083       coral::Context::instance().PropertyManager().property(auth::COND_AUTH_PATH_PROPERTY));
0084   if (pm) {
0085     setAuthenticationPath(pm->get());
0086     m_callbackID = pm->registerCallback(cb);
0087   }
0088 }
0089 
0090 cond::XMLAuthenticationService::XMLAuthenticationService::~XMLAuthenticationService() {
0091   for (std::map<std::string, cond::XMLAuthenticationService::DataSourceEntry*>::iterator iConnection = m_data.begin();
0092        iConnection != m_data.end();
0093        ++iConnection)
0094     delete iConnection->second;
0095 }
0096 
0097 void cond::XMLAuthenticationService::XMLAuthenticationService::setAuthenticationPath(const std::string& inputPath) {
0098   std::filesystem::path AuthPath(inputPath);
0099   if (std::filesystem::is_directory(AuthPath)) {
0100     AuthPath /= std::filesystem::path(XML_AUTHENTICATION_FILE);
0101   }
0102 
0103   m_inputFileName = AuthPath.string();
0104   reset();
0105 }
0106 
0107 bool cond::XMLAuthenticationService::XMLAuthenticationService::processFile(const std::string& inputFileName) {
0108   coral::MessageStream log("cond::XMLAuthenticationService::processFile");
0109   //std::cout<< "Processing file \""<< inputFileName<<"\"" <<std::endl;
0110   bool result = true;
0111 
0112   cond::FileReader inputFile;
0113   std::string cont("");
0114   try {
0115     inputFile.read(inputFileName);
0116     cont = inputFile.content();
0117   } catch (const cond::Exception& exc) {
0118     log << coral::Error << "File \"" << inputFileName << "\" not found." << std::string(exc.what())
0119         << coral::MessageStream::endmsg;
0120     return false;
0121   }
0122 
0123   std::filesystem::path filePath(inputFileName);
0124   std::string name = filePath.filename().string();
0125 
0126   /**
0127   if(name!=XML_AUTHENTICATION_FILE){
0128     cond::DecodingKey key;
0129     try{
0130       key.readUserKeyString(cont);
0131       log << coral::Debug << "Decoding content of file \""<< key.dataSource()<<"\""<<coral::MessageStream::endmsg;
0132       cond::FileReader dataFile;
0133       dataFile.read(key.dataSource());
0134       cont = dataFile.content();
0135       cont = coral::Cipher::decode(cont,key.key());      
0136     } catch (const cond::Exception& exc){
0137       log << coral::Error << std::string(exc.what())<<coral::MessageStream::endmsg;
0138       return false;
0139     }
0140     
0141   } else {
0142     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0143     log<<coral::Debug<< "Authentication file is expected standard XML."<<coral::MessageStream::endmsg;
0144   }
0145   **/
0146 
0147   xercesc::MemBufInputSource* memBufInputSource = nullptr;
0148 
0149   try {
0150     xercesc::XercesDOMParser parser;
0151     parser.setValidationScheme(xercesc::XercesDOMParser::Val_Always);
0152     parser.setDoNamespaces(true);
0153 
0154     xercesc::HandlerBase errorHandler;
0155     parser.setErrorHandler(&errorHandler);
0156 
0157     const char* bufferId = "InMemoryDocument";
0158     const char* buffer = cont.c_str();
0159 
0160     memBufInputSource = new xercesc::MemBufInputSource((const XMLByte*)buffer, strlen(buffer), bufferId, false);
0161 
0162     parser.parse(*memBufInputSource);
0163 
0164     xercesc::DOMDocument* document = parser.getDocument();
0165 
0166     XMLCh tempStr[20];
0167     xercesc::XMLString::transcode("connection", tempStr, 19);
0168 
0169     xercesc::DOMNodeList* connectionList = document->getElementsByTagName(tempStr);
0170 
0171     if (connectionList) {
0172       XMLSize_t numberOfConnections = connectionList->getLength();
0173 
0174       for (XMLSize_t iConnection = 0; iConnection < numberOfConnections; ++iConnection) {
0175         xercesc::DOMNode* connectionNode = connectionList->item(iConnection);
0176 
0177         if (connectionNode) {
0178           char* connectionName =
0179               xercesc::XMLString::transcode(connectionNode->getAttributes()->item(0)->getNodeValue());
0180           std::string sConnectionName = connectionName;
0181           xercesc::XMLString::release(&connectionName);
0182 
0183           // Locate the credential
0184           cond::XMLAuthenticationService::DataSourceEntry* credential = nullptr;
0185           std::map<std::string, cond::XMLAuthenticationService::DataSourceEntry*>::iterator iConnection =
0186               m_data.find(sConnectionName);
0187           if (iConnection != m_data.end()) {
0188             credential = iConnection->second;
0189             // Issue a warning here.
0190             //coral::MessageStream log( this, this->name(),seal::Msg::Verbose );
0191             log << coral::Debug << "Credential parameters for connection string \"" << sConnectionName
0192                 << "\" have already been defined. Only new elements are appended, while existing will be ignored."
0193                 << coral::MessageStream::endmsg;
0194           } else {
0195             credential = new cond::XMLAuthenticationService::DataSourceEntry(this->name(), sConnectionName);
0196             m_data.insert(std::make_pair(sConnectionName, credential));
0197           }
0198 
0199           xercesc::DOMNodeList* parameterList = connectionNode->getChildNodes();
0200 
0201           if (parameterList) {
0202             XMLSize_t numberOfParameters = parameterList->getLength();
0203 
0204             for (XMLSize_t iParameter = 0; iParameter < numberOfParameters; ++iParameter) {
0205               xercesc::DOMNode* parameterNode = parameterList->item(iParameter);
0206 
0207               if (parameterNode && parameterNode->getNodeType() == xercesc::DOMNode::ELEMENT_NODE) {
0208                 char* nodeName = xercesc::XMLString::transcode(parameterNode->getNodeName());
0209                 std::string sNodeName = nodeName;
0210                 xercesc::XMLString::release(&nodeName);
0211 
0212                 if (sNodeName == "parameter") {  // The default parameters
0213                   char* parameterName =
0214                       xercesc::XMLString::transcode(parameterNode->getAttributes()->item(0)->getNodeValue());
0215                   std::string sParameterName = parameterName;
0216                   xercesc::XMLString::release(&parameterName);
0217                   char* parameterValue =
0218                       xercesc::XMLString::transcode(parameterNode->getAttributes()->item(1)->getNodeValue());
0219                   std::string sParameterValue = parameterValue;
0220                   xercesc::XMLString::release(&parameterValue);
0221 
0222                   credential->appendCredentialItem(sParameterName, sParameterValue);
0223                 } else if (sNodeName == "role") {  // A role
0224                   char* roleName =
0225                       xercesc::XMLString::transcode(parameterNode->getAttributes()->item(0)->getNodeValue());
0226                   std::string sRoleName = roleName;
0227                   xercesc::XMLString::release(&roleName);
0228 
0229                   // Retrieve the parameters for the role
0230                   xercesc::DOMNodeList* roleParameterList = parameterNode->getChildNodes();
0231 
0232                   if (roleParameterList) {
0233                     XMLSize_t numberOfRoleParameters = roleParameterList->getLength();
0234 
0235                     for (XMLSize_t iRoleParameter = 0; iRoleParameter < numberOfRoleParameters; ++iRoleParameter) {
0236                       xercesc::DOMNode* roleParameterNode = roleParameterList->item(iRoleParameter);
0237                       if (roleParameterNode && roleParameterNode->getNodeType() == xercesc::DOMNode::ELEMENT_NODE) {
0238                         char* roleNodeName = xercesc::XMLString::transcode(roleParameterNode->getNodeName());
0239                         std::string sRoleNodeName = roleNodeName;
0240                         xercesc::XMLString::release(&roleNodeName);
0241 
0242                         if (sRoleNodeName == "parameter") {
0243                           char* roleParameterName = xercesc::XMLString::transcode(
0244                               roleParameterNode->getAttributes()->item(0)->getNodeValue());
0245                           std::string sRoleParameterName = roleParameterName;
0246                           xercesc::XMLString::release(&roleParameterName);
0247                           char* roleParameterValue = xercesc::XMLString::transcode(
0248                               roleParameterNode->getAttributes()->item(1)->getNodeValue());
0249                           std::string sRoleParameterValue = roleParameterValue;
0250                           xercesc::XMLString::release(&roleParameterValue);
0251 
0252                           credential->appendCredentialItemForRole(sRoleParameterName, sRoleParameterValue, sRoleName);
0253                         }
0254                       }
0255                     }
0256                   }
0257                 }
0258               }
0259             }
0260           }
0261         }
0262       }
0263     }
0264 
0265     parser.reset();
0266   } catch (const xercesc::XMLException& toCatch) {
0267     char* message = xercesc::XMLString::transcode(toCatch.getMessage());
0268     //coral::MessageStream log( this, this->name(),coral::Msg::Verbose );
0269     //log << coral::Msg::Error << message << coral::flush;
0270     log << coral::Error << std::string(message) << coral::MessageStream::endmsg;
0271     xercesc::XMLString::release(&message);
0272     result = false;
0273   } catch (const xercesc::DOMException& toCatch) {
0274     char* message = xercesc::XMLString::transcode(toCatch.msg);
0275     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0276     //log << seal::Msg::Error << message << seal::flush;
0277     log << coral::Error << std::string(message) << coral::MessageStream::endmsg;
0278     xercesc::XMLString::release(&message);
0279     result = false;
0280   } catch (const xercesc::SAXException& toCatch) {
0281     char* message = xercesc::XMLString::transcode(toCatch.getMessage());
0282     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0283     //log << seal::Msg::Error << message << seal::flush;
0284     log << coral::Error << std::string(message) << coral::MessageStream::endmsg;
0285     xercesc::XMLString::release(&message);
0286     result = false;
0287   } catch (...) {
0288     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0289     //log << seal::Msg::Error << "Unexpected Exception parsing file \"" << inputFileName << "\"" << seal::flush;
0290     log << coral::Error << "Unexpected Exception parsing file \"" << inputFileName << "\""
0291         << coral::MessageStream::endmsg;
0292     result = false;
0293   }
0294   if (memBufInputSource)
0295     delete memBufInputSource;
0296   return result;
0297 }
0298 
0299 bool cond::XMLAuthenticationService::XMLAuthenticationService::initialize() {
0300   coral::MessageStream log("cond::XMLAuthenticationService::initialize");
0301   std::set<std::string> inputFileNames = this->verifyFileName();
0302   if (inputFileNames.empty()) {
0303     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0304     //std::cout<< "Could not open \"" << m_inputFileName << "\" for reading" << std::endl;
0305     log << coral::Debug << "Could not open \"" << m_inputFileName << "\" for reading" << coral::MessageStream::endmsg;
0306     return false;
0307   }
0308 
0309   try {
0310     cms::concurrency::xercesInitialize();
0311   } catch (const xercesc::XMLException& toCatch) {
0312     char* message = xercesc::XMLString::transcode(toCatch.getMessage());
0313     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0314     //log << seal::Msg::Error << message << seal::flush;
0315     log << coral::Error << std::string(message) << coral::MessageStream::endmsg;
0316     xercesc::XMLString::release(&message);
0317     return false;
0318   }
0319 
0320   bool result = false;
0321   for (std::set<std::string>::const_reverse_iterator iFileName = inputFileNames.rbegin();
0322        iFileName != inputFileNames.rend();
0323        ++iFileName) {
0324     if (this->processFile(*iFileName)) {
0325       result = true;
0326     }
0327   }
0328 
0329   cms::concurrency::xercesTerminate();
0330 
0331   m_isInitialized = result;
0332   if (!m_isInitialized)
0333     reset();
0334   return result;
0335 }
0336 
0337 void cond::XMLAuthenticationService::XMLAuthenticationService::reset() {
0338   for (std::map<std::string, cond::XMLAuthenticationService::DataSourceEntry*>::iterator iConnection = m_data.begin();
0339        iConnection != m_data.end();
0340        ++iConnection)
0341     delete iConnection->second;
0342   m_data.clear();
0343   m_isInitialized = false;
0344 }
0345 
0346 const coral::IAuthenticationCredentials& cond::XMLAuthenticationService::XMLAuthenticationService::credentials(
0347     const std::string& connectionString) const {
0348   boost::mutex::scoped_lock lock(m_mutexLock);
0349   if (!m_isInitialized) {
0350     const_cast<cond::XMLAuthenticationService::XMLAuthenticationService*>(this)->initialize();
0351   }
0352   std::map<std::string, cond::XMLAuthenticationService::DataSourceEntry*>::const_iterator iConnection =
0353       m_data.find(connectionString);
0354   if (iConnection == m_data.end())
0355     throw coral::UnknownConnectionException(this->name(), connectionString);
0356   return iConnection->second->credentials();
0357 }
0358 
0359 const coral::IAuthenticationCredentials& cond::XMLAuthenticationService::XMLAuthenticationService::credentials(
0360     const std::string& connectionString, const std::string& role) const {
0361   boost::mutex::scoped_lock lock(m_mutexLock);
0362   if (!m_isInitialized) {
0363     const_cast<cond::XMLAuthenticationService::XMLAuthenticationService*>(this)->initialize();
0364   }
0365   std::map<std::string, cond::XMLAuthenticationService::DataSourceEntry*>::const_iterator iConnection =
0366       m_data.find(connectionString);
0367   if (iConnection == m_data.end())
0368     throw coral::UnknownConnectionException(this->name(), connectionString);
0369   return iConnection->second->credentials(role);
0370 }
0371 
0372 std::set<std::string> cond::XMLAuthenticationService::XMLAuthenticationService::verifyFileName() {
0373   coral::MessageStream log("cond::XMLAuthenticationService::verifyFileName");
0374   std::set<std::string> fileNames;
0375 
0376   // Try the file name as is...
0377   std::filesystem::path filePath(m_inputFileName);
0378   if (std::filesystem::exists(m_inputFileName)) {
0379     if (std::filesystem::is_directory(m_inputFileName)) {
0380       //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
0381       log << coral::Error << "Provided path \"" << m_inputFileName << "\" is a directory."
0382           << coral::MessageStream::endmsg;
0383       return fileNames;
0384     }
0385     std::filesystem::path fullPath = filePath.lexically_normal();
0386     fileNames.insert(fullPath.string());
0387     if (filePath.is_absolute())
0388       return fileNames;
0389   }
0390 
0391   // Try to find other files in the path variable
0392   const char* thePathVariable = std::getenv("CORAL_AUTH_PATH");
0393   if (!thePathVariable)
0394     return fileNames;
0395   log << coral::Debug << "File \"" << m_inputFileName
0396       << "\" not found in the current directory. Trying in the search path." << coral::MessageStream::endmsg;
0397 
0398   std::string searchPath(thePathVariable);
0399   //std::cout<<"searchPath "<<searchPath<<std::endl;
0400   if (std::filesystem::exists(searchPath)) {
0401     if (!std::filesystem::is_directory(searchPath)) {
0402       log << coral::Debug << "Search path \"" << searchPath << "\" is not a directory." << coral::MessageStream::endmsg;
0403       return fileNames;
0404     }
0405     std::filesystem::path fullPath(searchPath);
0406     fullPath /= filePath;
0407     fileNames.insert(fullPath.string());
0408   } else {
0409     log << coral::Debug << "Search path \"" << searchPath << "\" does not exist." << coral::MessageStream::endmsg;
0410     return fileNames;
0411   }
0412 
0413   return fileNames;
0414 }
0415 
0416 DEFINE_CORALSERVICE(cond::XMLAuthenticationService::XMLAuthenticationService, "COND/Services/XMLAuthenticationService");