Go to the documentation of this file.00001
00002 #include "CondCore/DBCommon/interface/FileUtils.h"
00003 #include "CondCore/DBCommon/interface/Exception.h"
00004 #include "CondCore/DBCommon/interface/Auth.h"
00005 #include "RelationalAccess/AuthenticationCredentials.h"
00006 #include "CoralCommon/Cipher.h"
00007 #include "RelationalAccess/AuthenticationServiceException.h"
00008 #include "CoralKernel/IPropertyManager.h"
00009 #include "CoralKernel/Property.h"
00010 #include "CoralKernel/Context.h"
00011 #include "CondCore/DBCommon/interface/CoralServiceMacros.h"
00012 #include "xercesc/parsers/XercesDOMParser.hpp"
00013 #include "xercesc/framework/MemBufInputSource.hpp"
00014 #include "xercesc/dom/DOM.hpp"
00015 #include "xercesc/sax/HandlerBase.hpp"
00016 #include "xercesc/util/XMLString.hpp"
00017 #include "xercesc/util/PlatformUtils.hpp"
00018 #include "XMLAuthenticationService.h"
00019
00020 #include <memory>
00021 #include <cstdlib>
00022 #include <fstream>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 #include <boost/filesystem.hpp>
00026 #include <boost/version.hpp>
00027 #include <boost/bind.hpp>
00028
00029 #include "CoralBase/MessageStream.h"
00030
00031 constexpr char XML_AUTHENTICATION_FILE[] = "authentication.xml";
00032
00033 cond::XMLAuthenticationService::DataSourceEntry::DataSourceEntry( const std::string& serviceName,
00034 const std::string& connectionName ):
00035 m_serviceName( serviceName ),
00036 m_connectionName( connectionName ),
00037 m_default( new coral::AuthenticationCredentials( serviceName ) ),
00038 m_data()
00039 {}
00040
00041 cond::XMLAuthenticationService::DataSourceEntry::~DataSourceEntry()
00042 {
00043 delete m_default;
00044 for ( std::map< std::string, coral::AuthenticationCredentials* >::iterator iData = m_data.begin();
00045 iData != m_data.end(); ++iData )
00046 delete iData->second;
00047 }
00048
00049 void
00050 cond::XMLAuthenticationService::DataSourceEntry::appendCredentialItem( const std::string& item,
00051 const std::string& value )
00052 {
00053 m_default->registerItem( item, value );
00054 }
00055
00056 void
00057 cond::XMLAuthenticationService::DataSourceEntry::appendCredentialItemForRole( const std::string& item,
00058 const std::string& value,
00059 const std::string& role )
00060 {
00061 std::map< std::string, coral::AuthenticationCredentials* >::iterator iRole = m_data.find( role );
00062 if ( iRole == m_data.end() ) {
00063 iRole = m_data.insert( std::make_pair( role, new coral::AuthenticationCredentials( m_serviceName ) ) ).first;
00064 }
00065 iRole->second->registerItem( item, value );
00066 }
00067
00068 const coral::IAuthenticationCredentials&
00069 cond::XMLAuthenticationService::DataSourceEntry::credentials() const
00070 {
00071 return *m_default;
00072 }
00073
00074 const coral::IAuthenticationCredentials&
00075 cond::XMLAuthenticationService::DataSourceEntry::credentials( const std::string& role ) const
00076 {
00085 return *m_default;
00086 }
00087
00088 cond::XMLAuthenticationService::XMLAuthenticationService::XMLAuthenticationService( const std::string& key )
00089 : coral::Service( key ),
00090 m_isInitialized( false ),
00091 m_inputFileName( "" ),
00092 m_data(),
00093 m_mutexLock(),
00094 m_callbackID(0)
00095 {
00096 boost::function1<void, std::string> cb(boost::bind(&cond::XMLAuthenticationService::XMLAuthenticationService::setAuthenticationPath, this, _1));
00097
00098 coral::Property* pm = dynamic_cast<coral::Property*>(coral::Context::instance().PropertyManager().property(Auth::COND_AUTH_PATH_PROPERTY));
00099 if(pm){
00100 setAuthenticationPath( pm->get() );
00101 m_callbackID = pm->registerCallback(cb);
00102 }
00103 }
00104
00105 cond::XMLAuthenticationService::XMLAuthenticationService::~XMLAuthenticationService()
00106 {
00107 for ( std::map< std::string, cond::XMLAuthenticationService::DataSourceEntry* >::iterator iConnection = m_data.begin();
00108 iConnection != m_data.end(); ++iConnection ) delete iConnection->second;
00109 }
00110
00111 void
00112 cond::XMLAuthenticationService::XMLAuthenticationService::setAuthenticationPath( const std::string& inputPath )
00113 {
00114 boost::filesystem::path boostAuthPath( inputPath );
00115 if(boost::filesystem::is_directory(boostAuthPath)){
00116 boostAuthPath /= boost::filesystem::path(XML_AUTHENTICATION_FILE);
00117 }
00118
00119 m_inputFileName = boostAuthPath.string();
00120 reset();
00121 }
00122
00123 bool
00124 cond::XMLAuthenticationService::XMLAuthenticationService::processFile( const std::string& inputFileName )
00125 {
00126 coral::MessageStream log("cond::XMLAuthenticationService::processFile");
00127
00128 bool result = true;
00129
00130 cond::FileReader inputFile;
00131 std::string cont("");
00132 try{
00133 inputFile.read(inputFileName);
00134 cont = inputFile.content();
00135 } catch (const cond::Exception& exc){
00136 log << coral::Error << "File \"" << inputFileName << "\" not found."<<std::string(exc.what())<<coral::MessageStream::endmsg;
00137 return false;
00138 }
00139
00140
00141 boost::filesystem::path filePath( inputFileName );
00142 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 47
00143 std::string name = filePath.filename().string();
00144 #else
00145 std::string name = filePath.leaf();
00146 #endif
00147
00168 xercesc::MemBufInputSource* memBufInputSource = 0;
00169
00170 try
00171 {
00172 xercesc::XercesDOMParser parser;
00173 parser.setValidationScheme( xercesc::XercesDOMParser::Val_Always );
00174 parser.setDoNamespaces( true );
00175
00176 xercesc::HandlerBase errorHandler;
00177 parser.setErrorHandler( &errorHandler );
00178
00179
00180 const char* bufferId="InMemoryDocument";
00181 const char* buffer = cont.c_str();
00182
00183 memBufInputSource = new xercesc::MemBufInputSource( (const XMLByte*)buffer,strlen(buffer),bufferId,false );
00184
00185 parser.parse(*memBufInputSource);
00186
00187 xercesc::DOMDocument* document = parser.getDocument();
00188
00189 XMLCh tempStr[20];
00190 xercesc::XMLString::transcode( "connection", tempStr, 19);
00191
00192 xercesc::DOMNodeList* connectionList = document->getElementsByTagName( tempStr );
00193
00194 if ( connectionList )
00195 {
00196 XMLSize_t numberOfConnections = connectionList->getLength();
00197
00198 for ( XMLSize_t iConnection = 0; iConnection < numberOfConnections; ++iConnection )
00199 {
00200 xercesc::DOMNode* connectionNode = connectionList->item( iConnection );
00201
00202 if ( connectionNode )
00203 {
00204 char* connectionName = xercesc::XMLString::transcode( connectionNode->getAttributes()->item( 0 )->getNodeValue() );
00205 std::string sConnectionName = connectionName;
00206 xercesc::XMLString::release( &connectionName );
00207
00208
00209 cond::XMLAuthenticationService::DataSourceEntry* credential = 0;
00210 std::map< std::string, cond::XMLAuthenticationService::DataSourceEntry* >::iterator iConnection = m_data.find( sConnectionName );
00211 if ( iConnection != m_data.end() ) {
00212 credential = iConnection->second;
00213
00214
00215 log<<coral::Debug<<"Credential parameters for connection string \""
00216 << sConnectionName
00217 << "\" have already been defined. Only new elements are appended, while existing will be ignored."
00218 << coral::MessageStream::endmsg;
00219 } else {
00220 credential = new cond::XMLAuthenticationService::DataSourceEntry( this->name(), sConnectionName );
00221 m_data.insert( std::make_pair( sConnectionName, credential ) );
00222 }
00223
00224 xercesc::DOMNodeList* parameterList = connectionNode->getChildNodes();
00225
00226 if ( parameterList )
00227 {
00228 XMLSize_t numberOfParameters = parameterList->getLength();
00229
00230 for ( XMLSize_t iParameter = 0; iParameter < numberOfParameters; ++iParameter )
00231 {
00232 xercesc::DOMNode* parameterNode = parameterList->item( iParameter );
00233
00234 if ( parameterNode && parameterNode->getNodeType() == xercesc::DOMNode::ELEMENT_NODE )
00235 {
00236 char* nodeName = xercesc::XMLString::transcode( parameterNode->getNodeName() );
00237 std::string sNodeName = nodeName;
00238 xercesc::XMLString::release( &nodeName );
00239
00240 if ( sNodeName == "parameter" ) {
00241 char* parameterName = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00242 std::string sParameterName = parameterName;
00243 xercesc::XMLString::release( ¶meterName );
00244 char* parameterValue = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 1 )->getNodeValue() );
00245 std::string sParameterValue = parameterValue;
00246 xercesc::XMLString::release( ¶meterValue );
00247
00248 credential->appendCredentialItem( sParameterName, sParameterValue );
00249 }
00250 else if ( sNodeName == "role" ) {
00251 char* roleName = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00252 std::string sRoleName = roleName;
00253 xercesc::XMLString::release( &roleName );
00254
00255
00256 xercesc::DOMNodeList* roleParameterList = parameterNode->getChildNodes();
00257
00258
00259 if ( roleParameterList )
00260 {
00261 XMLSize_t numberOfRoleParameters = roleParameterList->getLength();
00262
00263 for ( XMLSize_t iRoleParameter = 0; iRoleParameter < numberOfRoleParameters; ++iRoleParameter )
00264 {
00265 xercesc::DOMNode* roleParameterNode = roleParameterList->item( iRoleParameter );
00266 if ( roleParameterNode && roleParameterNode->getNodeType() == xercesc::DOMNode::ELEMENT_NODE )
00267 {
00268 char* roleNodeName = xercesc::XMLString::transcode( roleParameterNode->getNodeName() );
00269 std::string sRoleNodeName = roleNodeName;
00270 xercesc::XMLString::release( &roleNodeName );
00271
00272 if ( sRoleNodeName == "parameter" ) {
00273 char* roleParameterName = xercesc::XMLString::transcode( roleParameterNode->getAttributes()->item( 0 )->getNodeValue() );
00274 std::string sRoleParameterName = roleParameterName;
00275 xercesc::XMLString::release( &roleParameterName );
00276 char* roleParameterValue = xercesc::XMLString::transcode( roleParameterNode->getAttributes()->item( 1 )->getNodeValue() );
00277 std::string sRoleParameterValue = roleParameterValue;
00278 xercesc::XMLString::release( &roleParameterValue );
00279
00280 credential->appendCredentialItemForRole( sRoleParameterName, sRoleParameterValue, sRoleName );
00281 }
00282 }
00283 }
00284 }
00285 }
00286 }
00287 }
00288 }
00289 }
00290 }
00291 }
00292
00293 parser.reset();
00294 }
00295 catch ( const xercesc::XMLException& toCatch )
00296 {
00297 char* message = xercesc::XMLString::transcode( toCatch.getMessage() );
00298
00299
00300 log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00301 xercesc::XMLString::release( &message );
00302 result = false;
00303 }
00304 catch ( const xercesc::DOMException& toCatch )
00305 {
00306 char* message = xercesc::XMLString::transcode( toCatch.msg );
00307
00308
00309 log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00310 xercesc::XMLString::release( &message );
00311 result = false;
00312 }
00313 catch ( const xercesc::SAXException& toCatch )
00314 {
00315 char* message = xercesc::XMLString::transcode( toCatch.getMessage() );
00316
00317
00318 log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00319 xercesc::XMLString::release( &message );
00320 result = false;
00321 }
00322 catch (...){
00323
00324
00325 log<<coral::Error<<"Unexpected Exception parsing file \"" << inputFileName << "\"" <<coral::MessageStream::endmsg;
00326 result = false;
00327 }
00328 if(memBufInputSource) delete memBufInputSource;
00329 return result;
00330 }
00331
00332
00333 bool
00334 cond::XMLAuthenticationService::XMLAuthenticationService::initialize()
00335 {
00336 coral::MessageStream log("cond::XMLAuthenticationService::initialize");
00337 std::set< std::string > inputFileNames = this->verifyFileName();
00338 if ( inputFileNames.empty() )
00339 {
00340
00341
00342 log<<coral::Debug<<"Could not open \"" << m_inputFileName << "\" for reading" <<coral::MessageStream::endmsg;
00343 return false;
00344 }
00345
00346 try
00347 {
00348 xercesc::XMLPlatformUtils::Initialize();
00349 }
00350 catch ( const xercesc::XMLException& toCatch )
00351 {
00352 char* message = xercesc::XMLString::transcode( toCatch.getMessage() );
00353
00354
00355 log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00356 xercesc::XMLString::release( &message );
00357 return false;
00358 }
00359
00360 bool result = false;
00361 for ( std::set< std::string >::const_reverse_iterator iFileName = inputFileNames.rbegin();
00362 iFileName != inputFileNames.rend(); ++iFileName ) {
00363 if ( this->processFile( *iFileName ) ) {
00364 result = true;
00365 }
00366 }
00367
00368 xercesc::XMLPlatformUtils::Terminate();
00369
00370 m_isInitialized = result;
00371 if(!m_isInitialized) reset();
00372 return result;
00373 }
00374
00375 void cond::XMLAuthenticationService::XMLAuthenticationService::reset(){
00376 for ( std::map< std::string, cond::XMLAuthenticationService::DataSourceEntry* >::iterator iConnection = m_data.begin();
00377 iConnection != m_data.end(); ++iConnection ) delete iConnection->second;
00378 m_data.clear();
00379 m_isInitialized = false;
00380 }
00381
00382
00383
00384 const coral::IAuthenticationCredentials&
00385 cond::XMLAuthenticationService::XMLAuthenticationService::credentials( const std::string& connectionString ) const
00386 {
00387 boost::mutex::scoped_lock lock(m_mutexLock);
00388 if ( ! m_isInitialized ) {
00389 const_cast< cond::XMLAuthenticationService::XMLAuthenticationService* >( this )->initialize();
00390 }
00391 std::map< std::string, cond::XMLAuthenticationService::DataSourceEntry* >::const_iterator iConnection = m_data.find( connectionString );
00392 if ( iConnection == m_data.end() )
00393 throw coral::UnknownConnectionException( this->name(), connectionString );
00394 return iConnection->second->credentials();
00395 }
00396
00397
00398 const coral::IAuthenticationCredentials&
00399 cond::XMLAuthenticationService::XMLAuthenticationService::credentials( const std::string& connectionString,
00400 const std::string& role ) const
00401 {
00402 boost::mutex::scoped_lock lock(m_mutexLock);
00403 if ( ! m_isInitialized ) {
00404 const_cast< cond::XMLAuthenticationService::XMLAuthenticationService* >( this )->initialize();
00405 }
00406 std::map< std::string, cond::XMLAuthenticationService::DataSourceEntry* >::const_iterator iConnection = m_data.find( connectionString );
00407 if ( iConnection == m_data.end() )
00408 throw coral::UnknownConnectionException( this->name(), connectionString );
00409 return iConnection->second->credentials( role );
00410 }
00411
00412
00413 std::set< std::string >
00414 cond::XMLAuthenticationService::XMLAuthenticationService::verifyFileName()
00415 {
00416 coral::MessageStream log("cond::XMLAuthenticationService::verifyFileName");
00417 std::set< std::string > fileNames;
00418
00419
00420 boost::filesystem::path filePath( m_inputFileName );
00421 if ( boost::filesystem::exists( m_inputFileName ) ) {
00422 if(boost::filesystem::is_directory( m_inputFileName )){
00423
00424 log <<coral::Error << "Provided path \"" << m_inputFileName << "\" is a directory." <<coral::MessageStream::endmsg;
00425 return fileNames;
00426 }
00427 boost::filesystem::path& fullPath = filePath.normalize();
00428 fileNames.insert( fullPath.string() );
00429 if(filePath.is_complete()) return fileNames;
00430 }
00431
00432
00433 const char* thePathVariable = ::getenv( "CORAL_AUTH_PATH" );
00434 if ( ! thePathVariable ) return fileNames;
00435 log<<coral::Debug<< "File \"" << m_inputFileName << "\" not found in the current directory. Trying in the search path." <<coral::MessageStream::endmsg;
00436
00437 std::string searchPath(thePathVariable);
00438
00439 if(boost::filesystem::exists(searchPath)){
00440 if(!boost::filesystem::is_directory( searchPath )){
00441 log<<coral::Debug<<"Search path \"" << searchPath << "\" is not a directory."<<coral::MessageStream::endmsg;
00442 return fileNames;
00443 }
00444 boost::filesystem::path fullPath( searchPath );
00445 fullPath /= filePath;
00446 fileNames.insert( fullPath.string() );
00447 } else {
00448 log<<coral::Debug<<"Search path \"" << searchPath << "\" does not exist."<<coral::MessageStream::endmsg;
00449 return fileNames;
00450 }
00451
00452 return fileNames;
00453 }
00454
00455 DEFINE_CORALSERVICE(cond::XMLAuthenticationService::XMLAuthenticationService,"COND/Services/XMLAuthenticationService");