17 #include <boost/thread/once.hpp> 18 #include <boost/interprocess/smart_ptr/scoped_ptr.hpp> 24 #undef ZYPP_BASE_LOGGER_LOGGROUP 25 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::gpg" 37 boost::once_flag gpgme_init_once = BOOST_ONCE_INIT;
41 const char *version = gpgme_check_version(NULL);
44 MIL <<
"Initialized libgpgme version: " << version << endl;
48 MIL <<
"Initialized libgpgme with unknown version" << endl;
53 typedef boost::interprocess::scoped_ptr<gpgme_data, boost::function<void (gpgme_data_t)>> GpgmeDataPtr;
54 typedef boost::interprocess::scoped_ptr<_gpgme_key, boost::function<void (gpgme_key_t)>> GpgmeKeyPtr;
55 typedef boost::interprocess::scoped_ptr<FILE, boost::function<int (FILE *)>> FILEPtr;
59 GpgmeErr( gpgme_error_t err_r = GPG_ERR_NO_ERROR )
62 operator gpgme_error_t()
const {
return _err; }
67 std::ostream &
operator<<( std::ostream &
str,
const GpgmeErr & obj )
68 {
return str <<
"<" << gpgme_strsource(obj) <<
"> " << gpgme_strerror(obj); }
71 std::ostream &
operator<<( std::ostream &
str,
const _gpgme_op_import_result & obj )
73 str <<
"gpgme_op_import_result {" << endl;
74 str <<
" " << obj.considered <<
" The total number of considered keys." << endl;
75 str <<
" " << obj.no_user_id <<
" The number of keys without user ID." << endl;
76 str <<
" " << obj.imported <<
" The total number of imported keys." << endl;
77 str <<
" " << obj.imported_rsa <<
" imported RSA keys." << endl;
78 str <<
" " << obj.unchanged <<
" unchanged keys." << endl;
79 str <<
" " << obj.new_user_ids <<
" new user IDs." << endl;
80 str <<
" " << obj.new_sub_keys <<
" new sub keys." << endl;
81 str <<
" " << obj.new_signatures <<
" new signatures." << endl;
82 str <<
" " << obj.new_revocations <<
" new revocations." << endl;
83 str <<
" " << obj.secret_read <<
" secret keys read." << endl;
84 str <<
" " << obj.secret_imported <<
" imported secret keys." << endl;
85 str <<
" " << obj.secret_unchanged <<
" unchanged secret keys." << endl;
86 str <<
" " << obj.not_imported <<
" keys not imported." << endl;
87 for ( gpgme_import_status_t p = obj.imports; p; p = p->next )
89 str <<
" - " << p->fpr <<
": " << p->result << endl;
108 { boost::call_once( gpgme_init_once, initGpgme ); }
111 {
if (
_ctx ) gpgme_release(
_ctx ); }
145 if (!
PathInfo( signature_r ).isExist())
146 return std::list<std::string>();
148 FILEPtr dataFile(fopen(file_r.
c_str(),
"rb"), fclose);
150 return std::list<std::string>();
152 GpgmeDataPtr fileData(
nullptr, gpgme_data_release);
153 GpgmeErr err = gpgme_data_new_from_stream (&fileData.get(), dataFile.get());
156 return std::list<std::string>();
159 FILEPtr sigFile(fopen(signature_r.
c_str(),
"rb"), fclose);
161 ERR <<
"Unable to open signature file '" << signature_r <<
"'" <<endl;
162 return std::list<std::string>();
165 GpgmeDataPtr sigData(
nullptr, gpgme_data_release);
166 err = gpgme_data_new_from_stream (&sigData.get(), sigFile.get());
169 return std::list<std::string>();
172 err = gpgme_op_verify(
_ctx, sigData.get(), fileData.get(), NULL);
173 if (err != GPG_ERR_NO_ERROR) {
175 return std::list<std::string>();
178 gpgme_verify_result_t res = gpgme_op_verify_result(
_ctx);
179 if (!res || !res->signatures) {
180 ERR <<
"Unable to read signature fingerprints" <<endl;
181 return std::list<std::string>();
184 bool foundBadSignature =
false;
185 std::list<std::string> signatures;
186 for ( gpgme_signature_t sig = res->signatures; sig; sig = sig->next ) {
194 std::string id( sig->fpr );
195 if (
id.size() > 16 )
196 id =
id.substr(
id.size()-16 );
197 signatures.push_back( std::move(
id) );
200 if ( sig->status != GPG_ERR_NO_ERROR )
202 if ( gpgme_err_code(sig->status) != GPG_ERR_KEY_EXPIRED )
204 if ( !foundBadSignature )
205 foundBadSignature =
true;
207 WAR <<
"Failed signature check: " << file_r <<
" " << GpgmeErr(sig->status) << endl;
212 WAR <<
"Legacy: Ignore expired key: " << file_r <<
" " << GpgmeErr(sig->status) << endl;
218 *verify_r = (!foundBadSignature);
239 DBG <<
"createForOpenPGP(" << keyring_r <<
")" << endl;
245 GpgmeErr err = gpgme_new( &ctx );
246 if ( err != GPG_ERR_NO_ERROR )
250 err = gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
251 if ( err != GPG_ERR_NO_ERROR )
254 if ( !keyring_r.
empty() ) {
256 gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info( ctx );
260 err = gpgme_ctx_set_engine_info( ctx, GPGME_PROTOCOL_OpenPGP, enginfo->file_name, keyring_r.
c_str() );
261 if ( err != GPG_ERR_NO_ERROR )
271 if ( gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info(
_pimpl->
_ctx ) )
272 ret = enginfo->home_dir;
278 std::list<PublicKeyData> ret;
279 GpgmeErr err = GPG_ERR_NO_ERROR;
284 if ( (err = gpgme_set_keylist_mode(
_pimpl->
_ctx, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS )) != GPG_ERR_NO_ERROR ) {
285 ERR <<
"gpgme_set_keylist_mode: " << err << endl;
289 if ( (err = gpgme_op_keylist_start(
_pimpl->
_ctx, NULL, 0 )) != GPG_ERR_NO_ERROR ) {
290 ERR <<
"gpgme_op_keylist_start: " << err << endl;
297 for ( ; gpgme_op_keylist_next(
_pimpl->
_ctx, &(*key) ) == GPG_ERR_NO_ERROR; key.getDispose()( key ) ) {
300 ret.push_back( data );
315 std::list<PublicKeyData> ret;
332 std::list<PublicKeyData> ret;
333 GpgmeErr err = GPG_ERR_NO_ERROR;
336 if ( (err = gpgme_data_new_from_file( &(*data), file_r.
c_str(), 1 )) != GPG_ERR_NO_ERROR ) {
337 ERR <<
"gpgme_data_new_from_file " << file_r <<
": " << err << endl;
342 AutoDispose<gpgme_keylist_mode_t> guard { gpgme_get_keylist_mode(
_pimpl->
_ctx ), bind( &gpgme_set_keylist_mode,
_pimpl->
_ctx, _1 ) };
344 if ( (err = gpgme_set_keylist_mode(
_pimpl->
_ctx, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS )) != GPG_ERR_NO_ERROR ) {
345 ERR <<
"gpgme_set_keylist_mode: " << err << endl;
349 if ( (err = gpgme_op_keylist_from_data_start(
_pimpl->
_ctx, data, 0 )) != GPG_ERR_NO_ERROR ) {
350 ERR <<
"gpgme_op_keylist_from_data_start " << file_r <<
": " << err << endl;
354 AutoDispose<gpgme_ctx_t> guard2 {
_pimpl->
_ctx, &gpgme_op_keylist_end };
356 AutoDispose<gpgme_key_t> key {
nullptr, &gpgme_key_release };
357 for ( ; gpgme_op_keylist_next(
_pimpl->
_ctx, &(*key) ) == GPG_ERR_NO_ERROR; key.getDispose()( key ) ) {
360 ret.push_back( data );
374 GpgmeErr err = GPG_ERR_NO_ERROR;
376 GpgmeKeyPtr foundKey;
380 gpgme_op_keylist_start(
_pimpl->
_ctx, NULL, 0);
381 while (!(err = gpgme_op_keylist_next(
_pimpl->
_ctx, &key))) {
382 if (key->subkeys &&
id ==
str::asString(key->subkeys->keyid)) {
383 GpgmeKeyPtr(key, gpgme_key_release).swap(foundKey);
386 gpgme_key_release(key);
391 WAR <<
"Key " <<
id <<
"not found" << endl;
396 gpgme_key_t keyarray[2];
397 keyarray[0] = foundKey.get();
400 GpgmeDataPtr out(
nullptr, gpgme_data_release);
401 err = gpgme_data_new (&out.get());
409 err = gpgme_op_export_keys (
_pimpl->
_ctx, keyarray, 0, out.get());
411 int ret = gpgme_data_seek (out.get(), 0, SEEK_SET);
413 ERR <<
"Unable to seek in exported key data" << endl;
417 const int bufsize = 512;
418 char buf[bufsize + 1];
419 while ((ret = gpgme_data_read(out.get(), buf, bufsize)) > 0) {
420 stream.write(buf, ret);
425 ERR <<
"Unable to read exported key data" << endl;
429 ERR <<
"Error exporting key: "<< err << endl;
439 if ( !
PathInfo( keyfile ).isExist() ) {
440 ERR <<
"Keyfile '" << keyfile <<
"' does not exist.";
444 GpgmeDataPtr data(
nullptr, gpgme_data_release);
447 err = gpgme_data_new_from_file(&data.get(), keyfile.
c_str(), 1);
449 ERR <<
"Error importing key: "<< err << endl;
453 err = gpgme_op_import(
_pimpl->
_ctx, data.get());
455 ERR <<
"Error importing key: "<< err << endl;
461 if ( gpgme_import_result_t res = gpgme_op_import_result(
_pimpl->
_ctx) )
466 ERR <<
"Error importing key: No keys considered (bsc#1127220, [libgpgme] signal received?)" << endl;
471 return (err == GPG_ERR_NO_ERROR);
477 GpgmeErr err = GPG_ERR_NO_ERROR;
479 gpgme_op_keylist_start(
_pimpl->
_ctx, NULL, 0);
481 while (!(err = gpgme_op_keylist_next(
_pimpl->
_ctx, &key))) {
482 if (key->subkeys &&
id ==
str::asString(key->subkeys->keyid)) {
485 gpgme_key_release(key);
489 ERR <<
"Error deleting key: "<< err << endl;
494 gpgme_key_release(key);
498 WAR <<
"Key: '"<<
id <<
"' not found." << endl;
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
std::list< PublicKeyData > readKeyFromFile(const Pathname &file)
Returns a list of all PublicKeyData found in file.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
std::list< std::string > readSignaturesFprs(const Pathname &signature_r)
Return all fingerprints found in signature_r.
Class representing one GPG Public Keys data.
int clean_dir(const Pathname &path)
Like 'rm -r DIR/ *'.
const char * c_str() const
String representation.
String related utilities and Regular expression matching.
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
bool verify(const Pathname &file, const Pathname &signature)
Tries to verify file using signature, returns true on success.
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
bool exportKey(const std::string &id, std::ostream &stream)
Exports the key with id into the given stream, returns true on success.
RW_pointer< Impl > _pimpl
Pointer to implementation.
Pathname homedir() const
Return the homedir/keyring.
bool empty() const
Test for an empty path.
bool importKey(const Pathname &keyfile)
Tries to import a key from keyfile, returns true on success.
std::ostream & operator<<(std::ostream &str, const Exception &obj)
bool verifySignaturesFprs(const Pathname &file_r, const Pathname &signature_r)
Tries to verify the file_r using signature_r.
Pathname myTmpDir()
Global access to the zypp.TMPDIR (created on demand, deleted when libzypp is unloaded) ...
bool deleteKey(const std::string &id)
Tries to delete a key specified by id, returns true on success.
std::list< PublicKeyData > listKeys()
Returns a list of all public keys found in the current keyring.
GpgmeException(const std::string &in_r, const GpgmeErr &err_r)
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Wrapper class for ::stat/::lstat.
std::list< std::string > readSignatureFingerprints(const Pathname &signature)
Reads all fingerprints from the signature file , returns a list of all found fingerprints.
std::list< std::string > readSignaturesFprsOptVerify(const Pathname &signature_r, const Pathname &file_r="/dev/null", bool *verify_r=nullptr)
Return all fingerprints found in signature_r and optionally verify the file_r on the fly...
static PublicKeyData fromGpgmeKey(_gpgme_key *data)
Easy-to use interface to the ZYPP dependency resolver.
bool _volatile
readKeyFromFile workaround bsc#1140670