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;
}
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" ) );
}
}
}
}
}
}
-
+
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() ) );
+ }
/******************************************************************
**