CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:39:09 2009 for CMSSW by  doxygen 1.5.4