Author: mlandres
Date: Mon Jun 30 10:30:02 2008
New Revision: 10487
URL: http://svn.opensuse.org/viewcvs/zypp?rev=10487&view=rev
Log:
- Fix permanent duplication of gpg keys in the rpm database. Also
retrieve correct creation and expire dates. (bnc #401259)
- Invoke gpg with --homdir, otherwise command fails if executed
within a wrapper. (bnc #401259)
Modified:
trunk/libzypp/package/libzypp.changes
trunk/libzypp/zypp/KeyRing.cc
trunk/libzypp/zypp/PublicKey.cc
trunk/libzypp/zypp/PublicKey.h
trunk/libzypp/zypp/base/String.h
trunk/libzypp/zypp/target/rpm/RpmDb.cc
Modified: trunk/libzypp/package/libzypp.changes
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/package/libzypp.changes?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/package/libzypp.changes (original)
+++ trunk/libzypp/package/libzypp.changes Mon Jun 30 10:30:02 2008
@@ -1,4 +1,13 @@
-------------------------------------------------------------------
+Mon Jun 30 10:28:27 CEST 2008 - ma@suse.de
+
+- Fix permanent duplication of gpg keys in the rpm database. Also
+ retrieve correct creation and expire dates. (bnc #401259)
+- Invoke gpg with --homdir, otherwise command fails if executed
+ within a wrapper. (bnc #401259)
+- revision 10487
+
+-------------------------------------------------------------------
Thu Jun 26 12:07:33 CEST 2008 - schubi@suse.de
- version 5.0.1
Modified: trunk/libzypp/zypp/KeyRing.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/KeyRing.cc?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/zypp/KeyRing.cc (original)
+++ trunk/libzypp/zypp/KeyRing.cc Mon Jun 30 10:30:02 2008
@@ -249,6 +249,7 @@
for (list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
{
if ( id == (*it).id() )
+
return true;
}
return false;
@@ -339,6 +340,19 @@
{
PublicKey key = exportKey( id, trustedKeyRing() );
+ // lets look if there is an updated key in the
+ // general keyring
+ if ( publicKeyExists( id, generalKeyRing() ) )
+ {
+ PublicKey untkey = exportKey( id, generalKeyRing() );
+ if ( untkey.created() > key.created() )
+ {
+ MIL << "Key " << key << " was updated. Saving new version into trusted keyring." << endl;
+ importKey( untkey, true );
+ key = untkey;
+ }
+ }
+
MIL << "Key " << id << " " << key.name() << " is trusted" << endl;
// it exists, is trusted, does it validates?
if ( verifyFile( file, signature, trustedKeyRing() ) )
Modified: trunk/libzypp/zypp/PublicKey.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/PublicKey.cc?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/zypp/PublicKey.cc (original)
+++ trunk/libzypp/zypp/PublicKey.cc Mon Jun 30 10:30:02 2008
@@ -10,6 +10,7 @@
*
*/
#include <iostream>
+#include <vector>
//#include "zypp/base/Logger.h"
@@ -22,6 +23,7 @@
#include "zypp/base/Exception.h"
#include "zypp/base/Logger.h"
#include "zypp/Date.h"
+#include "zypp/TmpPath.h"
#include <ctime>
@@ -29,7 +31,7 @@
///////////////////////////////////////////////////////////////////
namespace zypp
-{ /////////////////////////////////////////////////////////////////
+{ /////////////////////////////////////////////////////////////////
//
// CLASS NAME : PublicKey::Impl
//
@@ -44,7 +46,7 @@
readFromFile(file);
MIL << "Done reading key" << std::endl;
}
-
+
public:
/** Offer default Impl. */
static shared_ptr<Impl> nullimpl()
@@ -53,21 +55,21 @@
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; }
@@ -76,68 +78,37 @@
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);
+ protected:
- 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",
@@ -147,42 +118,77 @@
_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 :
-
- 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 :
+ // 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::vectorstd::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::strtonumDate::ValueType(words[5]));
+ _expires = Date(str::strtonumDate::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::strtonumDate::ValueType(words[5]));
+ if ( ! words[6].empty() )
+ _expires = Date(str::strtonumDate::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;
@@ -211,7 +217,10 @@
PublicKey::PublicKey( const Pathname &file )
: _pimpl( new Impl(file) )
- {}
+ {
+ MIL << *this << endl;
+ }
+
///////////////////////////////////////////////////////////////////
//
// METHOD NAME : PublicKey::~PublicKey
@@ -230,16 +239,16 @@
{
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(); }
@@ -248,20 +257,33 @@
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
///////////////////////////////////////////////////////////////////
Modified: trunk/libzypp/zypp/PublicKey.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/PublicKey.h?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/zypp/PublicKey.h (original)
+++ trunk/libzypp/zypp/PublicKey.h Mon Jun 30 10:30:02 2008
@@ -25,7 +25,7 @@
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
-
+
/**
* Exception thrown when the supplied key is
* not a valid gpg key
@@ -39,10 +39,10 @@
BadKeyException()
: Exception( "Bad Key Exception" )
{}
-
+
Pathname keyFile() const
{ return _keyfile; }
-
+
/** Ctor taking message.
* Use \ref ZYPP_THROW to throw exceptions.
*/
@@ -54,16 +54,16 @@
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
@@ -76,16 +76,16 @@
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;
@@ -94,7 +94,7 @@
/**
* Date when the key was created (time is 00:00:00)
- */
+ */
Date created() const;
/**
@@ -103,11 +103,11 @@
*/
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;
@@ -118,7 +118,10 @@
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
Modified: trunk/libzypp/zypp/base/String.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/base/String.h?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/zypp/base/String.h (original)
+++ trunk/libzypp/zypp/base/String.h Mon Jun 30 10:30:02 2008
@@ -439,6 +439,57 @@
}
return ret;
}
+
+ /** Split \a line_r into fields.
+ * Any single character in \a sepchars_r is treated as a
+ * field separator. The words are passed to OutputIterator
+ * \a result_r.
+ * \code
+ * "" -> words 0
+ * ":" -> words 2 |||
+ * "a" -> words 1 |a|
+ * ":a" -> words 2 ||a|
+ * "a:" -> words 2 |a||
+ * ":a:" -> words 3 ||a||
+ *
+ * \endcode
+ *
+ * \code
+ * std::vectorstd::string words;
+ * str::split( "some line", std::back_inserter(words) )
+ * \endcode
+ *
+ */
+ template<class _OutputIterator>
+ unsigned splitFields( const C_Str & line_r,
+ _OutputIterator result_r,
+ const C_Str & sepchars_r = ":" )
+ {
+ const char * beg = line_r;
+ const char * cur = beg;
+ unsigned ret = 0;
+ for ( beg = cur; *beg; beg = cur, ++result_r )
+ {
+ // skip non sepchars
+ while( *cur && !::strchr( sepchars_r, *cur ) )
+ ++cur;
+ // build string
+ *result_r = std::string( beg, cur-beg );
+ ++ret;
+ // skip sepchar
+ if ( *cur )
+ {
+ ++cur;
+ if ( ! *cur ) // ending with sepchar
+ {
+ *result_r = std::string(); // add final empty field
+ ++ret;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
//@}
///////////////////////////////////////////////////////////////////
Modified: trunk/libzypp/zypp/target/rpm/RpmDb.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/target/rpm/RpmDb.cc?rev=10487&r1=10486&r2=10487&view=diff
==============================================================================
--- trunk/libzypp/zypp/target/rpm/RpmDb.cc (original)
+++ trunk/libzypp/zypp/target/rpm/RpmDb.cc Mon Jun 30 10:30:02 2008
@@ -1001,21 +1001,34 @@
// 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::strtonumDate::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 ( "--" );
@@ -2097,17 +2110,28 @@
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);
}
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org