*
*/
#include <iostream>
+#include <vector>
//#include "zypp/base/Logger.h"
#include "zypp/base/Exception.h"
#include "zypp/base/Logger.h"
#include "zypp/Date.h"
+#include "zypp/TmpPath.h"
#include <ctime>
///////////////////////////////////////////////////////////////////
namespace zypp
-{ /////////////////////////////////////////////////////////////////
+{ /////////////////////////////////////////////////////////////////
//
// CLASS NAME : PublicKey::Impl
//
readFromFile(file);
MIL << "Done reading key" << std::endl;
}
-
+
public:
/** Offer default Impl. */
static shared_ptr<Impl> nullimpl()
return _nullimpl;
}
-
+
std::string asString() const
{
- return "[" + id() + "] [" + name() + "] [" + fingerprint() + "]";
+ return "[" + id() + "-" + str::hexstring(created(),8).substr(2) + "] [" + name() + "] [" + fingerprint() + "]";
}
-
+
std::string armoredData() const
{ return _data; }
-
+
std::string id() const
{ return _id; }
-
+
std::string name() const
{ return _name; }
-
+
std::string fingerprint() const
{ return _fingerprint; }
Date expires() const
{ return _expires; }
-
+
Pathname path() const
- {
+ {
return _data_file.path();
//return _data_file;
}
-
+
protected:
- // create Date from a string in format YYYY-MM-DD
- Date createDate(const std::string &datestr)
- {
- // empty input
- if (datestr.empty())
- {
- return Date();
- }
-
- tm date;
- memset(&date, 0, sizeof(date));
-
- try
- {
- // set the date
- date.tm_year = str::strtonum<int>(std::string(datestr, 0, 4)) - 1900; // years since 1900
- date.tm_mon = str::strtonum<int>(std::string(datestr, 5, 2)) - 1; // months since January
- date.tm_mday = str::strtonum<int>(std::string(datestr, 9, 2)); // day
- }
- catch(...)
- {
- WAR << "Cannot parse date string: " << datestr << std::endl;
- return Date();
- }
-
- time_t time_epoch = ::mktime(&date);
-
- return Date(time_epoch);
- }
-
void readFromFile( const Pathname &keyfile)
{
- static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
-
+
PathInfo info(keyfile);
- MIL << "Reading pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1")<< endl;
+ MIL << "Reading pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1")<< endl;
if ( !info.isExist() )
ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
-
+
if ( copy( keyfile, _data_file.path() ) != 0 )
ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " + _data_file.path().asString() ));
-
- filesystem::TmpDir dir;
-
+ filesystem::TmpDir dir;
const char* argv[] =
{
"gpg",
+ "-v",
"--no-default-keyring",
- "--homedir",
- dir.path().asString().c_str(),
+ "--fixed-list-mode",
"--with-fingerprint",
"--with-colons",
+ "--homedir",
+ dir.path().asString().c_str(),
"--quiet",
"--no-tty",
"--no-greeting",
_data_file.path().asString().c_str(),
NULL
};
-
+
ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
-
+
std::string line;
- int count = 0;
-
- // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
-
- for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
+ bool sawpub = false;
+ bool sawsig = false;
+
+ // pub:-:1024:17:A84EDAE89C800ACA:971961473:1214043198::-:SuSE Package Signing Key <build@suse.de>:
+ // fpr:::::::::79C179B2E1C820C1890F9994A84EDAE89C800ACA:
+ // sig:::17:A84EDAE89C800ACA:1087899198:::::[selfsig]::13x:
+ // sig:::17:9E40E310000AABA4:980442706::::[User ID not found]:10x:
+ // sig:::1:77B2E6003D25D3D9:980443247::::[User ID not found]:10x:
+ // sub:-:2048:16:197448E88495160C:971961490:1214043258::: [expires: 2008-06-21]
+ // sig:::17:A84EDAE89C800ACA:1087899258:::::[keybind]::18x:
+
+ for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
{
- //MIL << "[" << line << "]" << std::endl;
- str::smatch what;
- if(str::regex_match(line, what, rxColons))
+ // trim trailing NL.
+ if ( line.empty() )
+ continue;
+ if ( line[line.size()-1] == '\n' )
+ line.erase( line.size()-1 );
+
+ // split at ':'
+ std::vector<std::string> words;
+ str::splitFields( line, std::back_inserter(words), ":" );
+ if( words.empty() )
+ continue;
+
+ if ( words[0] == "pub" )
{
- if ( what[1] == "pub" )
- {
- _id = what[5];
- //replace all escaped semicolon with real
- _name = str::gsub(what[10],"\\x3a",":");
- _created = createDate(what[6]);
- _expires = createDate(what[7]);
- //return key;
- }
- else if ( what[1] == "fpr" )
- {
- _fingerprint = what[10];
- }
- //dumpRegexpResults(what);
+ if ( sawpub )
+ continue;
+ sawpub = true;
+ // take default from pub
+ _id = words[4];
+ _name = words[9];
+ _created = Date(str::strtonum<Date::ValueType>(words[5]));
+ _expires = Date(str::strtonum<Date::ValueType>(words[6]));
+
+ }
+ else if ( words[0] == "sig" )
+ {
+ if ( sawsig || words[words.size()-2] != "13x" )
+ continue;
+ sawsig = true;
+ // update creation and expire dates from 1st signature type "13x"
+ if ( ! words[5].empty() )
+ _created = Date(str::strtonum<Date::ValueType>(words[5]));
+ if ( ! words[6].empty() )
+ _expires = Date(str::strtonum<Date::ValueType>(words[6]));
+ }
+ else if ( words[0] == "fpr" )
+ {
+ _fingerprint = words[9];
+ }
+ else if ( words[0] == "uid" )
+ {
+ if ( ! words[9].empty() )
+ _name = words[9];
}
}
prog.close();
-
- if (_id.size() == 0 )
- ZYPP_THROW(BadKeyException("File " + keyfile.asString() + " doesn't contain public key data" , keyfile));
+
+ if ( _id.size() == 0 )
+ ZYPP_THROW( BadKeyException( "File " + keyfile.asString() + " doesn't contain public key data" , keyfile ) );
+
+ //replace all escaped semicolon with real ':'
+ str::replaceAll( _name, "\\x3a", ":" );
}
-
+
private:
std::string _id;
std::string _name;
PublicKey::PublicKey( const Pathname &file )
: _pimpl( new Impl(file) )
- {}
+ {
+ MIL << *this << endl;
+ }
+
///////////////////////////////////////////////////////////////////
//
// METHOD NAME : PublicKey::~PublicKey
{
return _pimpl->asString();
}
-
+
std::string PublicKey::armoredData() const
{ return _pimpl->armoredData(); }
-
+
std::string PublicKey::id() const
{ return _pimpl->id(); }
-
+
std::string PublicKey::name() const
{ return _pimpl->name(); }
-
+
std::string PublicKey::fingerprint() const
{ return _pimpl->fingerprint(); }
Date PublicKey::expires() const
{ return _pimpl->expires(); }
-
+
Pathname PublicKey::path() const
{ return _pimpl->path(); }
bool PublicKey::operator==( PublicKey b ) const
{
- return (b.id() == id()) && (b.fingerprint() == fingerprint() );
+ return ( b.id() == id()
+ && b.fingerprint() == fingerprint()
+ && b.created() == created() );
}
-
+
bool PublicKey::operator==( std::string sid ) const
{
return sid == id();
}
-
+
+ std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
+ {
+ str << "[" << obj.name() << "]" << endl;
+ str << " fpr " << obj.fingerprint() << endl;
+ str << " id " << obj.id() << endl;
+ str << " cre " << obj.created() << endl;
+ str << " exp " << obj.expires() << endl;
+ str << "]";
+ return str;
+ }
+
/////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
-
+
/**
* Exception thrown when the supplied key is
* not a valid gpg key
BadKeyException()
: Exception( "Bad Key Exception" )
{}
-
+
Pathname keyFile() const
{ return _keyfile; }
-
+
/** Ctor taking message.
* Use \ref ZYPP_THROW to throw exceptions.
*/
private:
Pathname _keyfile;
};
-
- // forward declaration of class Date
+
+ // forward declaration of class Date
class Date;
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : PublicKey
//
- /**
+ /**
* Class that represent a GPG Public Key
*/
class PublicKey
public:
PublicKey();
- /** Ctor
+ /** Ctor
* \throws when data does not make a key
*/
PublicKey(const Pathname &file);
-
+
~PublicKey();
-
+
bool isValid() const
{ return ( ! id().empty() && ! fingerprint().empty() && !path().empty() ); }
-
+
std::string asString() const;
std::string armoredData() const;
std::string id() const;
/**
* Date when the key was created (time is 00:00:00)
- */
+ */
Date created() const;
/**
*/
Date expires() const;
- Pathname path() const;
-
+ Pathname path() const;
+
bool operator==( PublicKey b ) const;
bool operator==( std::string sid ) const;
-
+
private:
/** Pointer to implementation */
RWCOW_pointer<Impl> _pimpl;
inline std::ostream & operator<<( std::ostream & str, const PublicKey & obj )
{ return str << obj.asString(); }
- /////////////////////////////////////////////////////////////////
+ /** \relates PublicKey Detailed stream output */
+ std::ostream & dumpOn( std::ostream & str, const PublicKey & obj );
+
+ /////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////
#endif // ZYPP_PUBLICKEY_H
// check if the key is already in the rpm database and just
// return if it does.
set<Edition> rpm_keys = pubkeyEditions();
+ string keyshortid = pubkey_r.id().substr(8,8);
+ MIL << "Comparing '" << keyshortid << "' to: ";
for ( set<Edition>::const_iterator it = rpm_keys.begin(); it != rpm_keys.end(); ++it)
{
string id = str::toUpper( (*it).version() );
- string keyshortid = pubkey_r.id().substr(8,8);
- MIL << "Comparing '" << id << "' to '" << keyshortid << "'" << endl;
+ MIL << ", '" << id << "'";
if ( id == keyshortid )
{
- // they match id
- // FIXME id is not sufficient?
- MIL << "Key " << pubkey_r << " is already in the rpm trusted keyring." << endl;
- return;
+ // they match id
+ // now check if timestamp is different
+ Date date = Date(str::strtonum<Date::ValueType>("0x" + (*it).release()));
+ if ( date == pubkey_r.created() )
+ {
+
+ MIL << endl << "Key " << pubkey_r << " is already in the rpm trusted keyring." << endl;
+ return;
+ }
+ else
+ {
+ MIL << endl << "Key " << pubkey_r << " has another version in keyring. ( " << date << " & " << pubkey_r.created() << ")" << endl;
+
+ }
+
}
}
// key does not exists, lets import it
-
+ MIL << endl;
+
RpmArgVec opts;
opts.push_back ( "--import" );
opts.push_back ( "--" );
report->start( name_r );
- try
- {
- doRemovePackage(name_r, flags, report);
- }
- catch (RpmException & excpt_r)
- {
- report->problem(excpt_r); //! partial fix to bug #388810, \todo allow to abort/retry failed rpm removal
- report->finish(excpt_r);
- ZYPP_RETHROW(excpt_r);
- }
- report->finish();
+ do
+ try
+ {
+ doRemovePackage(name_r, flags, report);
+ report->finish();
+ break;
+ }
+ catch (RpmException & excpt_r)
+ {
+ RpmRemoveReport::Action user = report->problem( excpt_r );
+
+ if ( user == RpmRemoveReport::ABORT )
+ {
+ report->finish( excpt_r );
+ ZYPP_RETHROW(excpt_r);
+ }
+ else if ( user == RpmRemoveReport::IGNORE )
+ {
+ break;
+ }
+ }
+ while (true);
}