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. */
69 _general_kr = _general_tmp_dir.path();
70 _trusted_kr = _trusted_tmp_dir.path();
74 Impl( const Pathname &general_kr, const Pathname &trusted_kr )
76 filesystem::assert_dir(general_kr);
77 filesystem::assert_dir(trusted_kr);
79 _general_kr = general_kr;
80 _trusted_kr = trusted_kr;
84 void importKey( const Pathname &keyfile, bool trusted = false);
85 PublicKey readPublicKey( const Pathname &keyfile );
86 std::string readSignatureKeyId( const Pathname &data, const Pathname &keyfile );
88 void deleteKey( const std::string &id, bool trusted );
89 std::list<PublicKey> trustedPublicKeys();
90 std::list<PublicKey> publicKeys();
92 void dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream );
94 bool verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature);
96 bool verifyFileSignature( const Pathname &file, const Pathname &signature);
97 bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
99 //mutable std::map<Locale, std::string> translations;
100 bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
101 void importKey( const Pathname &keyfile, const Pathname &keyring);
103 void exportKey( std::string id, const Pathname &keyfile, bool trusted);
105 void deleteKey( const std::string &id, const Pathname &keyring );
106 std::list<PublicKey> publicKeys(const Pathname &keyring);
108 bool publicKeyExists( std::string id, const Pathname &keyring);
110 Pathname _general_kr;
111 Pathname _trusted_kr;
113 // Used for trusted and untrusted keyrings
114 TmpDir _trusted_tmp_dir;
115 TmpDir _general_tmp_dir;
117 /** Offer default Impl. */
118 static shared_ptr<Impl> nullimpl()
120 static shared_ptr<Impl> _nullimpl( new Impl );
125 friend Impl * rwcowClone<Impl>( const Impl * rhs );
126 /** clone for RWCOW_pointer */
128 { return new Impl( *this ); }
131 void KeyRing::Impl::importKey( const Pathname &keyfile, bool trusted)
133 importKey( keyfile, trusted ? _trusted_kr : _general_kr );
136 void KeyRing::Impl::deleteKey( const std::string &id, bool trusted)
138 deleteKey( id, trusted ? _trusted_kr : _general_kr );
141 std::list<PublicKey> KeyRing::Impl::publicKeys()
143 return publicKeys( _general_kr );
146 std::list<PublicKey> KeyRing::Impl::trustedPublicKeys()
148 return publicKeys( _trusted_kr );
151 bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
153 return verifyFile( file, signature, _trusted_kr );
156 bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
158 return verifyFile( file, signature, _general_kr );
161 bool KeyRing::Impl::publicKeyExists( std::string id, const Pathname &keyring)
163 std::list<PublicKey> keys = publicKeys(keyring);
164 for (std::list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
166 if ( id == (*it).id )
172 void KeyRing::Impl::exportKey( std::string id, const Pathname &keyfile, bool trusted)
175 std::ofstream os(keyfile.asString().c_str());
176 dumpPublicKey( id, trusted, os );
179 catch (std::exception &e)
181 ERR << "Cannot export key " << id << " from " << (trusted ? "trusted" : "untrusted ") << " keyring to file " << keyfile << std::endl;
185 void KeyRing::Impl::dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream )
187 Pathname keyring = trusted ? _trusted_kr : _general_kr;
194 "--no-permission-warning",
197 keyring.asString().c_str(),
203 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
206 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
214 bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
216 callback::SendReport<KeyRingReport> report;
217 callback::SendReport<KeyRingSignals> emitSignal;
218 MIL << "Going to verify signature for " << file << " with " << signature << std::endl;
220 // get the id of the signature
221 std::string id = readSignatureKeyId(file, signature);
223 // doeskey exists in trusted keyring
224 if ( publicKeyExists( id, _trusted_kr ) )
227 exportKey( id, trustedKey.path(), true);
228 PublicKey key = readPublicKey(trustedKey.path());
229 MIL << "Key " << id << " " << key.name << " is trusted" << std::endl;
230 // it exists, is trusted, does it validates?
231 if ( verifyFile( file, signature, _trusted_kr ) )
234 return report->askUserToAcceptVerificationFailed( file, key.id, key.name );
238 if ( publicKeyExists( id, _general_kr ) )
241 exportKey( id, unKey.path(), false);
242 MIL << "Exported key " << id << " to " << unKey << std::endl;
244 PublicKey key = readPublicKey(unKey.path());
245 MIL << "Key " << id << " " << key.name << " is not trusted" << std::endl;
246 // ok the key is not trusted, ask the user to trust it or not
247 #warning We need the key details passed to the callback
248 if ( report->askUserToTrustKey(key.id, key.name, "") )
250 MIL << "User wants to trust key " << id << " " << key.name << std::endl;
251 //dumpFile(unKey.path());
253 importKey( unKey.path(), _trusted_kr );
254 emitSignal->trustedKeyAdded( (const KeyRing &)(*this), id, key.name );
257 if ( verifyFile( file, signature, _trusted_kr ) )
259 MIL << "File signature is verified" << std::endl;
264 MIL << "File signature check fails" << std::endl;
265 if ( report->askUserToAcceptVerificationFailed( file, key.id, key.name ) )
267 MIL << "User continues anyway." << std::endl;
272 MIL << "User does not want to continue" << std::endl;
279 MIL << "User does not want to trust key " << id << " " << key.name << std::endl;
286 if ( report->askUserToAcceptUnknownKey( file, id, "Unknown Key" ) )
288 MIL << "User wants to accept unknown key " << id << std::endl;
293 MIL << "User does not want to accept unknown key " << id << std::endl;
302 PublicKey KeyRing::Impl::readPublicKey( const Pathname &keyfile )
307 "--with-fingerprint",
315 keyfile.asString().c_str(),
319 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
324 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
326 // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
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" )
341 //dumpRegexpResults(what);
348 std::list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
354 "--list-public-keys",
356 "--with-fingerprint",
358 keyring.asString().c_str(),
361 std::list<PublicKey> keys;
363 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
367 boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
368 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
370 //MIL << line << std::endl;
372 if(boost::regex_match(line, what, rxColons, boost::match_extra))
374 if ( what[1] == "pub" )
379 MIL << "Found key " << key.id << " [" << key.name << "]" << std::endl;
382 dumpRegexpResults(what);
389 void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
397 "--no-permission-warning",
401 keyring.asString().c_str(),
403 keyfile.asString().c_str(),
408 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
412 // ZYPP_THROW(Exception("failed to import key"));
415 void KeyRing::Impl::deleteKey( const std::string &id, const Pathname &keyring )
427 keyring.asString().c_str(),
433 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
435 int code = prog.close();
437 ZYPP_THROW(Exception("Failed to delete key."));
439 MIL << "Deleted key " << id << " from keyring " << keyring << std::endl;
443 std::string KeyRing::Impl::readSignatureKeyId( const Pathname &data, const Pathname &keyfile )
445 // HACK create a tmp keyring with no keys
458 dir.path().asString().c_str(),
460 keyfile.asString().c_str(),
461 data.asString().c_str(),
465 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
470 boost::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
472 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
474 //MIL << "[" << line << "]" << std::endl;
476 if(boost::regex_match(line, what, rxNoKey, boost::match_extra))
478 if ( what.size() > 1 )
480 //dumpRegexpResults(what);
487 bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
499 keyring.asString().c_str(),
501 signature.asString().c_str(),
502 file.asString().c_str(),
506 // no need to parse output for now
507 // [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
508 // [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
509 // gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
510 // [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
511 // [GNUPG:] TRUST_UNDEFINED
513 // [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
514 // [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
516 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
518 return (prog.close() == 0) ? true : false;
521 ///////////////////////////////////////////////////////////////////
523 ///////////////////////////////////////////////////////////////////
525 // CLASS NAME : KeyRing
527 ///////////////////////////////////////////////////////////////////
529 ///////////////////////////////////////////////////////////////////
531 // METHOD NAME : KeyRing::KeyRing
532 // METHOD TYPE : Ctor
535 : _pimpl( new Impl() )
538 ///////////////////////////////////////////////////////////////////
540 // METHOD NAME : KeyRing::KeyRing
541 // METHOD TYPE : Ctor
543 //KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr )
544 //: _pimpl( new Impl(general_kr, trusted_kr) )
547 ///////////////////////////////////////////////////////////////////
549 // METHOD NAME : KeyRing::~KeyRing
550 // METHOD TYPE : Dtor
555 ///////////////////////////////////////////////////////////////////
557 // Forward to implementation:
559 ///////////////////////////////////////////////////////////////////
561 void KeyRing::importKey( const Pathname &keyfile, bool trusted)
563 _pimpl->importKey(keyfile, trusted);
566 PublicKey KeyRing::readPublicKey( const Pathname &keyfile )
568 return _pimpl->readPublicKey(keyfile);
571 std::string KeyRing::readSignatureKeyId( const Pathname &data, const Pathname &keyfile )
573 return _pimpl->readSignatureKeyId(data, keyfile);
576 void KeyRing::deleteKey( const std::string &id, bool trusted )
578 _pimpl->deleteKey(id, trusted);
581 std::list<PublicKey> KeyRing::publicKeys()
583 return _pimpl->publicKeys();
586 std::list<PublicKey> KeyRing::trustedPublicKeys()
588 return _pimpl->trustedPublicKeys();
591 bool KeyRing::verifyFileSignatureWorkflow( const Pathname &file, const Pathname &signature)
593 return _pimpl->verifyFileSignatureWorkflow(file, signature);
596 bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
598 return _pimpl->verifyFileSignature(file, signature);
601 bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
603 return _pimpl->verifyFileTrustedSignature(file, signature);
606 void KeyRing::dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream )
608 _pimpl->dumpPublicKey( id, trusted, stream);
611 /////////////////////////////////////////////////////////////////
613 ///////////////////////////////////////////////////////////////////