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