CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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 "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 //#include <iostream>
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   //std::cout<< "Processing file \""<< inputFileName<<"\"" <<std::endl;
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   // check the 
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
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           // Locate the credential
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             // Issue a warning here.
00198             //coral::MessageStream log( this, this->name(),seal::Msg::Verbose );
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" ) { // The default parameters
00225                   char* parameterName = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00226                   std::string sParameterName = parameterName;
00227                   xercesc::XMLString::release( &parameterName );
00228                   char* parameterValue = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 1 )->getNodeValue() );
00229                   std::string sParameterValue = parameterValue;
00230                   xercesc::XMLString::release( &parameterValue );
00231 
00232                   credential->appendCredentialItem( sParameterName, sParameterValue );
00233                 }
00234                 else if ( sNodeName == "role" ) { // A role
00235                   char* roleName  = xercesc::XMLString::transcode( parameterNode->getAttributes()->item( 0 )->getNodeValue() );
00236                   std::string sRoleName = roleName;
00237                   xercesc::XMLString::release( &roleName );
00238 
00239                   // Retrieve the parameters for the role
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     //coral::MessageStream log( this, this->name(),coral::Msg::Verbose );
00283     //log << coral::Msg::Error << message << coral::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00292     //log << seal::Msg::Error << message << seal::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00301     //log << seal::Msg::Error << message << seal::flush;
00302     log<<coral::Error<<std::string(message)<<coral::MessageStream::endmsg;
00303     xercesc::XMLString::release( &message );
00304     result = false;
00305   }
00306   catch (...){
00307     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00308     //log << seal::Msg::Error << "Unexpected Exception parsing file \"" << inputFileName << "\"" << seal::flush;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00325     //std::cout<< "Could not open \"" << m_inputFileName << "\" for reading" << std::endl;
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     //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
00338     //log << seal::Msg::Error << message << seal::flush;
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   // Try the file name as is...
00404   boost::filesystem::path filePath( m_inputFileName );
00405   if ( boost::filesystem::exists( m_inputFileName ) ) {
00406     if(boost::filesystem::is_directory( m_inputFileName )){
00407       //seal::MessageStream log( this, this->name(),seal::Msg::Verbose );
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   // Try to find other files in the path variable
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   //std::cout<<"searchPath "<<searchPath<<std::endl;
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");