1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/KeyRing.cc
14 //#include "zypp/base/Logger.h"
19 #include "zypp/ZYppFactory.h"
20 #include "zypp/ZYpp.h"
22 #include <boost/regex.hpp>
24 #include "zypp/base/String.h"
25 #include "zypp/KeyRing.h"
26 #include "zypp/ExternalProgram.h"
27 #include "zypp/TmpPath.h"
30 using namespace boost;
31 using namespace zypp::filesystem;
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
38 IMPL_PTR_TYPE(KeyRing);
40 static void dumpRegexpResults( const boost::smatch &what )
42 for ( unsigned int k=0; k < what.size(); k++)
44 XXX << "[match "<< k << "] [" << what[k] << "]" << std::endl;
48 ///////////////////////////////////////////////////////////////////
50 // CLASS NAME : KeyRing::Impl
52 /** KeyRing implementation. */
58 Impl( const Pathname &general_kr, const Pathname &trusted_kr )
60 filesystem::assert_dir(general_kr);
61 filesystem::assert_dir(trusted_kr);
63 _general_kr = general_kr;
64 _trusted_kr = trusted_kr;
67 void importKey( const Pathname &keyfile, bool trusted = false);
68 PublicKey readPublicKey( const Pathname &keyfile );
69 std::string readSignatureKeyId( const Pathname &keyfile );
71 void deleteKey( const std::string &id, bool trusted );
72 std::list<PublicKey> trustedPublicKeys();
73 std::list<PublicKey> publicKeys();
75 bool verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature);
77 bool verifyFileSignature( const Pathname &file, const Pathname &signature);
78 bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
80 //mutable std::map<Locale, std::string> translations;
81 bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
82 void importKey( const Pathname &keyfile, const Pathname &keyring);
84 void exportKey( std::string id, const Pathname &keyring, const Pathname &keyfile);
86 void deleteKey( const std::string &id, const Pathname &keyring );
87 std::list<PublicKey> publicKeys(const Pathname &keyring);
89 bool publicKeyExists( std::string id, const Pathname &keyring);
94 /** Offer default Impl. */
95 static shared_ptr<Impl> nullimpl()
97 static shared_ptr<Impl> _nullimpl( new Impl );
102 friend Impl * rwcowClone<Impl>( const Impl * rhs );
103 /** clone for RWCOW_pointer */
105 { return new Impl( *this ); }
108 void KeyRing::Impl::importKey( const Pathname &keyfile, bool trusted)
110 importKey( keyfile, trusted ? _trusted_kr : _general_kr );
113 void KeyRing::Impl::deleteKey( const std::string &id, bool trusted)
115 deleteKey( id, trusted ? _trusted_kr : _general_kr );
118 std::list<PublicKey> KeyRing::Impl::publicKeys()
120 return publicKeys( _general_kr );
123 std::list<PublicKey> KeyRing::Impl::trustedPublicKeys()
125 return publicKeys( _trusted_kr );
128 bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
130 return verifyFile( file, signature, _trusted_kr );
133 bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
135 return verifyFile( file, signature, _general_kr );
138 bool KeyRing::Impl::publicKeyExists( std::string id, const Pathname &keyring)
140 std::list<PublicKey> keys = publicKeys(keyring);
141 for (std::list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
143 if ( id == (*it).id )
149 void KeyRing::Impl::exportKey( std::string id, const Pathname &keyring, const Pathname &keyfile)
159 keyring.asString().c_str(),
162 keyfile.asString().c_str(),
167 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
171 bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
173 callback::SendReport<KeyRingReport> report;
174 callback::SendReport<KeyRingSignals> emitSignal;
175 MIL << "Going to verify signature for " << file << " with " << signature << std::endl;
176 // struct KeyRingReport : public callback::ReportBase
177 // virtual bool askUserToAcceptUnsignedFile( const Pathname &file )
178 // virtual bool askUserToAcceptUnknownKey( const std::string keyid, const std::string keyname )
179 // virtual bool askUserToTrustKey( const std::string keyid, const std::string keyname )
180 // virtual bool askUserToAcceptVerificationFailed( const Pathname &file, const std::string keyid, const std::string keyname )
182 // struct KeyRingSignals : public callback::ReportBase
183 // virtual void trustedKeyAdded( const KeyRing &keyring, const std::string keyid, const std::string keyname )
184 // virtual void trustedKeyRemoved( const KeyRing &keyring, const std::string keyid, const std::string keyname )
186 // get the id of the signature
187 std::string id = readSignatureKeyId(signature);
189 // doeskey exists in trusted keyring
190 if ( publicKeyExists( id, _trusted_kr ) )
193 exportKey( id, _trusted_kr, trustedKey.path());
194 PublicKey key = readPublicKey(trustedKey.path());
195 MIL << "Key " << id << " " << key.name << " is trusted" << std::endl;
196 // it exists, is trusted, does it validates?
197 if ( verifyFile( file, signature, _trusted_kr ) )
200 return report->askUserToAcceptVerificationFailed( file, key.id, key.name );
204 if ( publicKeyExists( id, _general_kr ) )
207 exportKey( id, _general_kr, unKey.path());
208 PublicKey key = readPublicKey(unKey.path());
209 MIL << "Key " << id << " " << key.name << " is not trusted" << std::endl;
210 // ok the key is not trusted, ask the user to trust it or not
211 if ( report->askUserToTrustKey(key.id, key.name) )
213 MIL << "User wants to trust key " << id << " " << key.name << std::endl;
215 exportKey( id, _general_kr, unKey.path());
216 importKey( unKey.path(), _trusted_kr );
218 if ( verifyFile( file, signature, _trusted_kr ) )
220 MIL << "File signature is verified" << std::endl;
225 MIL << "File signature check fails" << std::endl;
226 if ( report->askUserToAcceptVerificationFailed( file, key.id, key.name ) )
228 MIL << "User continues anyway." << std::endl;
233 MIL << "User does not want to continue" << std::endl;
240 MIL << "User does not want to trust key " << id << " " << key.name << std::endl;
247 if ( report->askUserToAcceptUnknownKey( id, "Unkown Key" ) )
249 MIL << "User wants to accept unknown key " << id << std::endl;
254 MIL << "User does not want to accept unknown key " << id << std::endl;
263 PublicKey KeyRing::Impl::readPublicKey( const Pathname &keyfile )
268 "--with-fingerprint",
276 keyfile.asString().c_str(),
280 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
285 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
287 // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
290 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
292 //MIL << "[" << line << "]" << std::endl;
294 if(boost::regex_match(line, what, rxColons, boost::match_extra))
296 if ( what[1] == "pub" )
302 //dumpRegexpResults(what);
309 std::list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
315 "--list-public-keys",
317 "--with-fingerprint",
319 keyring.asString().c_str(),
322 std::list<PublicKey> keys;
324 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
328 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
329 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
331 //MIL << line << std::endl;
333 if(boost::regex_match(line, what, rxColons, boost::match_extra))
335 if ( what[1] == "pub" )
340 MIL << "Found key " << key.id << " [" << key.name << "]" << std::endl;
343 dumpRegexpResults(what);
350 void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
361 keyring.asString().c_str(),
363 keyfile.asString().c_str(),
368 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
372 ZYPP_THROW(Exception("failed to import key"));
375 void KeyRing::Impl::deleteKey( const std::string &id, const Pathname &keyring )
387 keyring.asString().c_str(),
393 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
395 int code = prog.close();
397 ZYPP_THROW(Exception("Failed to delete key."));
399 MIL << "Deleted key " << id << " from keyring " << keyring << std::endl;
403 std::string KeyRing::Impl::readSignatureKeyId( const Pathname &keyfile )
405 // HACK create a tmp keyring with no keys
418 dir.path().asString().c_str(),
419 keyfile.asString().c_str(),
423 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
428 boost::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
430 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
432 //MIL << "[" << line << "]" << std::endl;
434 if(boost::regex_match(line, what, rxNoKey, boost::match_extra))
436 if ( what.size() > 1 )
438 //dumpRegexpResults(what);
445 bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
457 keyring.asString().c_str(),
459 signature.asString().c_str(),
460 file.asString().c_str(),
464 // no need to parse output for now
465 // [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
466 // [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
467 // gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
468 // [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
469 // [GNUPG:] TRUST_UNDEFINED
471 // [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
472 // [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
474 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
476 return (prog.close() == 0) ? true : false;
479 ///////////////////////////////////////////////////////////////////
481 ///////////////////////////////////////////////////////////////////
483 // CLASS NAME : KeyRing
485 ///////////////////////////////////////////////////////////////////
487 ///////////////////////////////////////////////////////////////////
489 // METHOD NAME : KeyRing::KeyRing
490 // METHOD TYPE : Ctor
493 : _pimpl( Impl::nullimpl() )
496 ///////////////////////////////////////////////////////////////////
498 // METHOD NAME : KeyRing::KeyRing
499 // METHOD TYPE : Ctor
501 KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr )
502 : _pimpl( new Impl(general_kr, trusted_kr) )
505 ///////////////////////////////////////////////////////////////////
507 // METHOD NAME : KeyRing::~KeyRing
508 // METHOD TYPE : Dtor
513 ///////////////////////////////////////////////////////////////////
515 // Forward to implementation:
517 ///////////////////////////////////////////////////////////////////
519 void KeyRing::importKey( const Pathname &keyfile, bool trusted)
521 _pimpl->importKey(keyfile, trusted);
524 PublicKey KeyRing::readPublicKey( const Pathname &keyfile )
526 return _pimpl->readPublicKey(keyfile);
529 std::string KeyRing::readSignatureKeyId( const Pathname &keyfile )
531 return _pimpl->readSignatureKeyId(keyfile);
534 void KeyRing::deleteKey( const std::string &id, bool trusted )
536 _pimpl->deleteKey(id, trusted);
539 std::list<PublicKey> KeyRing::publicKeys()
541 return _pimpl->publicKeys();
544 std::list<PublicKey> KeyRing::trustedPublicKeys()
546 return _pimpl->trustedPublicKeys();
549 bool KeyRing::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
551 return _pimpl->verifyFileSignatureWorkflow(file, signature);
554 bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
556 return _pimpl->verifyFileSignature(file, signature);
559 bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
561 return _pimpl->verifyFileTrustedSignature(file, signature);
564 /////////////////////////////////////////////////////////////////
566 ///////////////////////////////////////////////////////////////////