Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / FileChecker.cc
index 0529c7d..32a4dee 100644 (file)
 
 using namespace std;
 
+#undef ZYPP_BASE_LOGGER_LOGGROUP
+#define ZYPP_BASE_LOGGER_LOGGROUP "FileChecker"
+
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 { /////////////////////////////////////////////////////////////////
 
   ChecksumFileChecker::ChecksumFileChecker( const CheckSum &checksum )
     : _checksum(checksum)
-  {
-  }
+  {}
 
   void ChecksumFileChecker::operator()( const Pathname &file ) const
   {
-    MIL << "checking " << file << " file against checksum '" << _checksum << "'" << endl;
+    //MIL << "checking " << file << " file against checksum '" << _checksum << "'" << endl;
     callback::SendReport<DigestReport> report;
-    CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
-    
+
     if ( _checksum.empty() )
     {
       MIL << "File " <<  file << " has no checksum available." << std::endl;
@@ -43,21 +44,39 @@ namespace zypp
       }
       else
       {
-        ZYPP_THROW( FileCheckException( "No checksum available for " + file.basename() ) );
+        ZYPP_THROW( ExceptionType( file.basename() + " has no checksum" ) );
       }
     }
     else
     {
+      CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
       if ( (real_checksum != _checksum) )
       {
-        if ( report->askUserToAcceptWrongDigest( file, _checksum.checksum(), real_checksum.checksum() ) )
+       // Remember askUserToAcceptWrongDigest decision for at most 12hrs in memory;
+       // Actually we just want to prevent asking the same question again when the
+       // previously downloaded file is retrieved from the disk cache.
+       static std::map<std::string,std::string> exceptions;
+       static Date exceptionsAge;
+       Date now( Date::now() );
+       if ( !exceptions.empty() && now-exceptionsAge > 12*Date::hour )
+         exceptions.clear();
+
+       WAR << "File " <<  file << " has wrong checksum " << real_checksum << " (expected " << _checksum << ")" << endl;
+       if ( !exceptions.empty() && exceptions[real_checksum.checksum()] == _checksum.checksum() )
+       {
+         WAR << "User accepted " <<  file << " with WRONG CHECKSUM. (remembered)" << std::endl;
+          return;
+       }
+        else if ( report->askUserToAcceptWrongDigest( file, _checksum.checksum(), real_checksum.checksum() ) )
         {
           WAR << "User accepted " <<  file << " with WRONG CHECKSUM." << std::endl;
+         exceptions[real_checksum.checksum()] = _checksum.checksum();
+         exceptionsAge = now;
           return;
         }
         else
         {
-          ZYPP_THROW( FileCheckException( "Wrong checksum for "  + file.basename() ) );
+          ZYPP_THROW( ExceptionType( file.basename() + " has wrong checksum" ) );
         }
       }
     }
@@ -85,54 +104,44 @@ namespace zypp
       }
     }
   }
-  
+
   void CompositeFileChecker::add( const FileChecker &checker )
-  {
-    //MIL << "||# " << _checkers.size() << endl;
-    _checkers.push_back(checker);
-    //MIL << "||* " << _checkers.size() << endl;
-    
-  }
+  { _checkers.push_back(checker); }
 
-   SignatureFileChecker::SignatureFileChecker( const Pathname &signature,
-                                               const std::string &description )
-       : _signature(signature)
-       , _description(description)
-  {
 
-  }
-  
-  SignatureFileChecker::SignatureFileChecker( const std::string &description )
-      : _description(description)
-  {
-  }
-  
+  SignatureFileChecker::SignatureFileChecker( const Pathname & signature )
+       : _signature(signature)
+  {}
 
   SignatureFileChecker::SignatureFileChecker()
+  {}
+
+  void SignatureFileChecker::setKeyContext(const KeyContext & keycontext)
+  { _context = keycontext; }
+
+  void SignatureFileChecker::addPublicKey( const Pathname & publickey, const KeyContext & keycontext )
+  { addPublicKey( PublicKey(publickey), keycontext ); }
+
+  void SignatureFileChecker::addPublicKey( const PublicKey & publickey, const KeyContext & keycontext )
   {
+    getZYpp()->keyRing()->importKey(publickey, false);
+    _context = keycontext;
   }
-  
-  void SignatureFileChecker::addPublicKey( const Pathname &publickey )
-  {
-    ZYpp::Ptr z = getZYpp();
-    z->keyRing()->importKey(publickey, false);
-  }
-  
+
   void SignatureFileChecker::operator()(const Pathname &file ) const
   {
-    ZYpp::Ptr z = getZYpp();
-
-    if ( (! PathInfo(_signature).isExist()) && (!_signature.empty()))
+    if ( (! PathInfo(_signature).isExist()) && (!_signature.empty()) )
     {
-      ZYPP_THROW(FileCheckException("Signature " + _signature.asString() + " not found."));
+      ZYPP_THROW( ExceptionType("Signature " + _signature.asString() + " not found.") );
     }
 
     MIL << "checking " << file << " file validity using digital signature.." << endl;
-    bool valid = z->keyRing()->verifyFileSignatureWorkflow( file, _description.empty() ? file.basename() : _description, _signature);
+    _fileValidated = false;
+    _fileAccepted = getZYpp()->keyRing()->verifyFileSignatureWorkflow( file, file.basename(), _signature, _fileValidated, _context );
 
-    if (!valid)
-      ZYPP_THROW( FileCheckException( "Signature verification failed for "  + file.basename() ) );
 }
+    if ( !_fileAccepted )
+      ZYPP_THROW( ExceptionType( "Signature verification failed for "  + file.basename() ) );
+ }
 
   /******************************************************************
   **