CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/CondCore/DBCommon/plugins/XMLAuthenticationService.cc

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 "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 //#include <iostream>
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   //std::cout<< "Processing file \""<< inputFileName<<"\"" <<std::endl;
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   // check the 
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           // Locate the credential
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             // Issue a warning here.
00214             //coral::MessageStream log( this, this->name(),seal::Msg::Verbose );
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" ) { // The default parameters
00241                   char* parameterName = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00242                   std::string sParameterName = parameterName;
00243                   xercesc::XMLString::release( &parameterName );
00244                   char* parameterValue = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 1 )->getNodeValue() );
00245                   std::string sParameterValue = parameterValue;
00246                   xercesc::XMLString::release( &parameterValue );
00247 
00248                   credential->appendCredentialItem( sParameterName, sParameterValue );
00249                 }
00250                 else if ( sNodeName == "role" ) { // A role
00251                   char* roleName  = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00252                   std::string sRoleName = roleName;
00253                   xercesc::XMLString::release( &roleName );
00254 
00255                   // Retrieve the parameters for the role
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     //coral::MessageStream log( this, this->name(),coral::Msg::Verbose );
00299     //log << coral::Msg::Error << message << coral::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00308     //log << seal::Msg::Error << message << seal::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00317     //log << seal::Msg::Error << message << seal::flush;
00318     log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00319     xercesc::XMLString::release( &message );
00320     result = false;
00321   }
00322   catch (...){
00323     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00324     //log << seal::Msg::Error << "Unexpected Exception parsing file \"" << inputFileName << "\"" << seal::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00341     //std::cout<< "Could not open \"" << m_inputFileName << "\" for reading" << std::endl;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00354     //log << seal::Msg::Error << message << seal::flush;
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   // Try the file name as is...
00420   boost::filesystem::path filePath( m_inputFileName );
00421   if ( boost::filesystem::exists( m_inputFileName ) ) {
00422     if(boost::filesystem::is_directory( m_inputFileName )){
00423       //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
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   // Try to find other files in the path variable
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   //std::cout<<"searchPath "<<searchPath<<std::endl;
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");