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
0068
0069
0070
0071
0072
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
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
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
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
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
0190
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") {
0213 char* parameterName =
0214 xercesc::XMLString::transcode(parameterNode->getAttributes()->item(0)->getNodeValue());
0215 std::string sParameterName = parameterName;
0216 xercesc::XMLString::release(¶meterName);
0217 char* parameterValue =
0218 xercesc::XMLString::transcode(parameterNode->getAttributes()->item(1)->getNodeValue());
0219 std::string sParameterValue = parameterValue;
0220 xercesc::XMLString::release(¶meterValue);
0221
0222 credential->appendCredentialItem(sParameterName, sParameterValue);
0223 } else if (sNodeName == "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
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
0269
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
0276
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
0283
0284 log << coral::Error << std::string(message) << coral::MessageStream::endmsg;
0285 xercesc::XMLString::release(&message);
0286 result = false;
0287 } catch (...) {
0288
0289
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
0304
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
0314
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
0377 std::filesystem::path filePath(m_inputFileName);
0378 if (std::filesystem::exists(m_inputFileName)) {
0379 if (std::filesystem::is_directory(m_inputFileName)) {
0380
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
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
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");