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/base/IOStream.h"
26 #include "zypp/KeyRing.h"
27 #include "zypp/ExternalProgram.h"
28 #include "zypp/TmpPath.h"
31 using namespace boost;
32 using namespace zypp::filesystem;
35 ///////////////////////////////////////////////////////////////////
37 { /////////////////////////////////////////////////////////////////
39 IMPL_PTR_TYPE(KeyRing);
41 static void dumpRegexpResults( const boost::smatch &what )
43 for ( unsigned int k=0; k < what.size(); k++)
45 XXX << "[match "<< k << "] [" << what[k] << "]" << std::endl;
49 static bool printLine( const std::string &line )
51 MIL << line << std::endl;
54 static void dumpFile(const Pathname &file)
56 std::ifstream is(file.asString().c_str());
57 iostr::forEachLine( is, printLine);
60 ///////////////////////////////////////////////////////////////////
62 // CLASS NAME : KeyRing::Impl
64 /** KeyRing implementation. */
70 Impl( const Pathname &general_kr, const Pathname &trusted_kr )
72 filesystem::assert_dir(general_kr);
73 filesystem::assert_dir(trusted_kr);
75 _general_kr = general_kr;
76 _trusted_kr = trusted_kr;
79 void importKey( const Pathname &keyfile, bool trusted = false);
80 PublicKey readPublicKey( const Pathname &keyfile );
81 std::string readSignatureKeyId( const Pathname &data, const Pathname &keyfile );
83 void deleteKey( const std::string &id, bool trusted );
84 std::list<PublicKey> trustedPublicKeys();
85 std::list<PublicKey> publicKeys();
87 void dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream );
89 bool verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature);
91 bool verifyFileSignature( const Pathname &file, const Pathname &signature);
92 bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
94 //mutable std::map<Locale, std::string> translations;
95 bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
96 void importKey( const Pathname &keyfile, const Pathname &keyring);
98 void exportKey( std::string id, const Pathname &keyfile, bool trusted);
100 void deleteKey( const std::string &id, const Pathname &keyring );
101 std::list<PublicKey> publicKeys(const Pathname &keyring);
103 bool publicKeyExists( std::string id, const Pathname &keyring);
105 Pathname _general_kr;
106 Pathname _trusted_kr;
108 /** Offer default Impl. */
109 static shared_ptr<Impl> nullimpl()
111 static shared_ptr<Impl> _nullimpl( new Impl );
116 friend Impl * rwcowClone<Impl>( const Impl * rhs );
117 /** clone for RWCOW_pointer */
119 { return new Impl( *this ); }
122 void KeyRing::Impl::importKey( const Pathname &keyfile, bool trusted)
124 importKey( keyfile, trusted ? _trusted_kr : _general_kr );
127 void KeyRing::Impl::deleteKey( const std::string &id, bool trusted)
129 deleteKey( id, trusted ? _trusted_kr : _general_kr );
132 std::list<PublicKey> KeyRing::Impl::publicKeys()
134 return publicKeys( _general_kr );
137 std::list<PublicKey> KeyRing::Impl::trustedPublicKeys()
139 return publicKeys( _trusted_kr );
142 bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
144 return verifyFile( file, signature, _trusted_kr );
147 bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
149 return verifyFile( file, signature, _general_kr );
152 bool KeyRing::Impl::publicKeyExists( std::string id, const Pathname &keyring)
154 std::list<PublicKey> keys = publicKeys(keyring);
155 for (std::list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
157 if ( id == (*it).id )
163 void KeyRing::Impl::exportKey( std::string id, const Pathname &keyfile, bool trusted)
166 std::ofstream os(keyfile.asString().c_str());
167 dumpPublicKey( id, trusted, os );
170 catch (std::exception &e)
172 ERR << "Cannot export key " << id << " from " << (trusted ? "trusted" : "untrusted ") << " keyring to file " << keyfile << std::endl;
176 void KeyRing::Impl::dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream )
178 Pathname keyring = trusted ? _trusted_kr : _general_kr;
185 "--no-permission-warning",
188 keyring.asString().c_str(),
194 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
197 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
205 bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
207 callback::SendReport<KeyRingReport> report;
208 callback::SendReport<KeyRingSignals> emitSignal;
209 MIL << "Going to verify signature for " << file << " with " << signature << std::endl;
211 // get the id of the signature
212 std::string id = readSignatureKeyId(file, signature);
214 // doeskey exists in trusted keyring
215 if ( publicKeyExists( id, _trusted_kr ) )
218 exportKey( id, trustedKey.path(), true);
219 PublicKey key = readPublicKey(trustedKey.path());
220 MIL << "Key " << id << " " << key.name << " is trusted" << std::endl;
221 // it exists, is trusted, does it validates?
222 if ( verifyFile( file, signature, _trusted_kr ) )
225 return report->askUserToAcceptVerificationFailed( file, key.id, key.name );
229 if ( publicKeyExists( id, _general_kr ) )
232 exportKey( id, unKey.path(), false);
233 MIL << "Exported key " << id << " to " << unKey << std::endl;
235 PublicKey key = readPublicKey(unKey.path());
236 MIL << "Key " << id << " " << key.name << " is not trusted" << std::endl;
237 // ok the key is not trusted, ask the user to trust it or not
238 if ( report->askUserToTrustKey(key.id, key.name) )
240 MIL << "User wants to trust key " << id << " " << key.name << std::endl;
241 //dumpFile(unKey.path());
243 importKey( unKey.path(), _trusted_kr );
244 emitSignal->trustedKeyAdded( (const KeyRing &)(*this), id, key.name );
247 if ( verifyFile( file, signature, _trusted_kr ) )
249 MIL << "File signature is verified" << std::endl;
254 MIL << "File signature check fails" << std::endl;
255 if ( report->askUserToAcceptVerificationFailed( file, key.id, key.name ) )
257 MIL << "User continues anyway." << std::endl;
262 MIL << "User does not want to continue" << std::endl;
269 MIL << "User does not want to trust key " << id << " " << key.name << std::endl;
276 if ( report->askUserToAcceptUnknownKey( id, "Unkown Key" ) )
278 MIL << "User wants to accept unknown key " << id << std::endl;
283 MIL << "User does not want to accept unknown key " << id << std::endl;
292 PublicKey KeyRing::Impl::readPublicKey( const Pathname &keyfile )
297 "--with-fingerprint",
305 keyfile.asString().c_str(),
309 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
314 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
316 // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
319 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
321 //MIL << "[" << line << "]" << std::endl;
323 if(boost::regex_match(line, what, rxColons, boost::match_extra))
325 if ( what[1] == "pub" )
331 //dumpRegexpResults(what);
338 std::list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
344 "--list-public-keys",
346 "--with-fingerprint",
348 keyring.asString().c_str(),
351 std::list<PublicKey> keys;
353 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
357 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
358 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
360 //MIL << line << std::endl;
362 if(boost::regex_match(line, what, rxColons, boost::match_extra))
364 if ( what[1] == "pub" )
369 MIL << "Found key " << key.id << " [" << key.name << "]" << std::endl;
372 dumpRegexpResults(what);
379 void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
387 "--no-permission-warning",
391 keyring.asString().c_str(),
393 keyfile.asString().c_str(),
398 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
402 // ZYPP_THROW(Exception("failed to import key"));
405 void KeyRing::Impl::deleteKey( const std::string &id, const Pathname &keyring )
417 keyring.asString().c_str(),
423 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
425 int code = prog.close();
427 ZYPP_THROW(Exception("Failed to delete key."));
429 MIL << "Deleted key " << id << " from keyring " << keyring << std::endl;
433 std::string KeyRing::Impl::readSignatureKeyId( const Pathname &data, const Pathname &keyfile )
435 // HACK create a tmp keyring with no keys
448 dir.path().asString().c_str(),
450 keyfile.asString().c_str(),
451 data.asString().c_str(),
455 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
460 boost::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
462 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
464 //MIL << "[" << line << "]" << std::endl;
466 if(boost::regex_match(line, what, rxNoKey, boost::match_extra))
468 if ( what.size() > 1 )
470 //dumpRegexpResults(what);
477 bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
489 keyring.asString().c_str(),
491 signature.asString().c_str(),
492 file.asString().c_str(),
496 // no need to parse output for now
497 // [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
498 // [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
499 // gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
500 // [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
501 // [GNUPG:] TRUST_UNDEFINED
503 // [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
504 // [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
506 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
508 return (prog.close() == 0) ? true : false;
511 ///////////////////////////////////////////////////////////////////
513 ///////////////////////////////////////////////////////////////////
515 // CLASS NAME : KeyRing
517 ///////////////////////////////////////////////////////////////////
519 ///////////////////////////////////////////////////////////////////
521 // METHOD NAME : KeyRing::KeyRing
522 // METHOD TYPE : Ctor
525 : _pimpl( Impl::nullimpl() )
528 ///////////////////////////////////////////////////////////////////
530 // METHOD NAME : KeyRing::KeyRing
531 // METHOD TYPE : Ctor
533 KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr )
534 : _pimpl( new Impl(general_kr, trusted_kr) )
537 ///////////////////////////////////////////////////////////////////
539 // METHOD NAME : KeyRing::~KeyRing
540 // METHOD TYPE : Dtor
545 ///////////////////////////////////////////////////////////////////
547 // Forward to implementation:
549 ///////////////////////////////////////////////////////////////////
551 void KeyRing::importKey( const Pathname &keyfile, bool trusted)
553 _pimpl->importKey(keyfile, trusted);
556 PublicKey KeyRing::readPublicKey( const Pathname &keyfile )
558 return _pimpl->readPublicKey(keyfile);
561 std::string KeyRing::readSignatureKeyId( const Pathname &data, const Pathname &keyfile )
563 return _pimpl->readSignatureKeyId(data, keyfile);
566 void KeyRing::deleteKey( const std::string &id, bool trusted )
568 _pimpl->deleteKey(id, trusted);
571 std::list<PublicKey> KeyRing::publicKeys()
573 return _pimpl->publicKeys();
576 std::list<PublicKey> KeyRing::trustedPublicKeys()
578 return _pimpl->trustedPublicKeys();
581 bool KeyRing::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
583 return _pimpl->verifyFileSignatureWorkflow(file, signature);
586 bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
588 return _pimpl->verifyFileSignature(file, signature);
591 bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
593 return _pimpl->verifyFileTrustedSignature(file, signature);
596 void KeyRing::dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream )
598 _pimpl->dumpPublicKey( id, trusted, stream);
601 /////////////////////////////////////////////////////////////////
603 ///////////////////////////////////////////////////////////////////