16 #include <boost/thread/once.hpp> 17 #include <boost/interprocess/smart_ptr/scoped_ptr.hpp> 23 #undef ZYPP_BASE_LOGGER_LOGGROUP 24 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::gpg" 36 boost::once_flag gpgme_init_once = BOOST_ONCE_INIT;
39 typedef boost::interprocess::scoped_ptr<gpgme_data, boost::function<void (gpgme_data_t)>> GpgmeDataPtr;
40 typedef boost::interprocess::scoped_ptr<_gpgme_key, boost::function<void (gpgme_key_t)>> GpgmeKeyPtr;
41 typedef boost::interprocess::scoped_ptr<FILE, boost::function<int (FILE *)>> FILEPtr;
45 GpgmeErr( gpgme_error_t err_r = GPG_ERR_NO_ERROR )
48 operator gpgme_error_t()
const {
return _err; }
53 std::ostream &
operator<<( std::ostream &
str,
const GpgmeErr & obj )
54 {
return str <<
"<" << gpgme_strsource(obj) <<
"> " << gpgme_strerror(obj); }
58 const char *version = gpgme_check_version(NULL);
61 MIL <<
"Initialized libgpgme version: " << version << endl;
65 MIL <<
"Initialized libgpgme with unknown version" << endl;
70 std::ostream &
operator<<( std::ostream &
str,
const _gpgme_op_import_result & obj )
72 str <<
"gpgme_op_import_result {" << endl;
73 str <<
" " << obj.considered <<
" The total number of considered keys." << endl;
74 str <<
" " << obj.no_user_id <<
" The number of keys without user ID." << endl;
75 str <<
" " << obj.imported <<
" The total number of imported keys." << endl;
76 str <<
" " << obj.imported_rsa <<
" imported RSA keys." << endl;
77 str <<
" " << obj.unchanged <<
" unchanged keys." << endl;
78 str <<
" " << obj.new_user_ids <<
" new user IDs." << endl;
79 str <<
" " << obj.new_sub_keys <<
" new sub keys." << endl;
80 str <<
" " << obj.new_signatures <<
" new signatures." << endl;
81 str <<
" " << obj.new_revocations <<
" new revocations." << endl;
82 str <<
" " << obj.secret_read <<
" secret keys read." << endl;
83 str <<
" " << obj.secret_imported <<
" imported secret keys." << endl;
84 str <<
" " << obj.secret_unchanged <<
" unchanged secret keys." << endl;
85 str <<
" " << obj.not_imported <<
" keys not imported." << endl;
86 for ( gpgme_import_status_t p = obj.imports; p; p = p->next )
88 str <<
" - " << p->fpr <<
": " << p->result << endl;
142 if (!
PathInfo( signature_r ).isExist())
143 return std::list<std::string>();
145 FILEPtr dataFile(fopen(file_r.
c_str(),
"rb"), fclose);
147 return std::list<std::string>();
149 GpgmeDataPtr fileData(
nullptr, gpgme_data_release);
150 GpgmeErr err = gpgme_data_new_from_stream (&fileData.get(), dataFile.get());
153 return std::list<std::string>();
156 FILEPtr sigFile(fopen(signature_r.
c_str(),
"rb"), fclose);
158 ERR <<
"Unable to open signature file '" << signature_r <<
"'" <<endl;
159 return std::list<std::string>();
162 GpgmeDataPtr sigData(
nullptr, gpgme_data_release);
163 err = gpgme_data_new_from_stream (&sigData.get(), sigFile.get());
166 return std::list<std::string>();
169 err = gpgme_op_verify(
_ctx, sigData.get(), fileData.get(), NULL);
170 if (err != GPG_ERR_NO_ERROR) {
172 return std::list<std::string>();
175 gpgme_verify_result_t res = gpgme_op_verify_result(
_ctx);
176 if (!res || !res->signatures) {
177 ERR <<
"Unable to read signature fingerprints" <<endl;
178 return std::list<std::string>();
181 bool foundBadSignature =
false;
182 std::list<std::string> signatures;
183 for ( gpgme_signature_t sig = res->signatures; sig; sig = sig->next ) {
191 std::string id( sig->fpr );
192 if (
id.size() > 16 )
193 id =
id.substr(
id.size()-16 );
194 signatures.push_back( std::move(
id) );
197 if ( sig->status != GPG_ERR_NO_ERROR )
199 if ( gpgme_err_code(sig->status) != GPG_ERR_KEY_EXPIRED )
201 if ( !foundBadSignature )
202 foundBadSignature =
true;
204 WAR <<
"Failed signature check: " << file_r <<
" " << GpgmeErr(sig->status) << endl;
209 WAR <<
"Legacy: Ignore expired key: " << file_r <<
" " << GpgmeErr(sig->status) << endl;
215 *verify_r = (!foundBadSignature);
227 boost::call_once(gpgme_init_once, initGpgme);
230 GpgmeErr err = gpgme_new(&ctx);
231 if (err != GPG_ERR_NO_ERROR) {
233 return shared_ptr<KeyManagerCtx>();
237 err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
238 if (err != GPG_ERR_NO_ERROR) {
241 return shared_ptr<KeyManagerCtx>();
245 me->_pimpl->_ctx = ctx;
253 gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info(
_pimpl->
_ctx);
257 GpgmeErr err = gpgme_ctx_set_engine_info(
259 GPGME_PROTOCOL_OpenPGP,
263 if (err != GPG_ERR_NO_ERROR) {
264 ERR <<
"Unable to set homedir " << err << endl;
273 gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info(
_pimpl->
_ctx);
282 std::list<PublicKeyData> keys;
284 GpgmeErr err = GPG_ERR_NO_ERROR;
286 gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS;
288 gpgme_op_keylist_start (
_pimpl->
_ctx, NULL, 0);
290 while (!(err = gpgme_op_keylist_next(
_pimpl->
_ctx, &key))) {
293 keys.push_back(data);
295 gpgme_key_release(key);
310 return std::list<PublicKeyData>();
314 return std::list<PublicKeyData>();
317 std::list<PublicKeyData> keys =
listKeys();
332 GpgmeErr err = GPG_ERR_NO_ERROR;
334 GpgmeKeyPtr foundKey;
338 gpgme_op_keylist_start(
_pimpl->
_ctx, NULL, 0);
339 while (!(err = gpgme_op_keylist_next(
_pimpl->
_ctx, &key))) {
340 if (key->subkeys &&
id ==
str::asString(key->subkeys->keyid)) {
341 GpgmeKeyPtr(key, gpgme_key_release).swap(foundKey);
344 gpgme_key_release(key);
349 WAR <<
"Key " <<
id <<
"not found" << endl;
354 gpgme_key_t keyarray[2];
355 keyarray[0] = foundKey.get();
358 GpgmeDataPtr out(
nullptr, gpgme_data_release);
359 err = gpgme_data_new (&out.get());
367 err = gpgme_op_export_keys (
_pimpl->
_ctx, keyarray, 0, out.get());
369 int ret = gpgme_data_seek (out.get(), 0, SEEK_SET);
371 ERR <<
"Unable to seek in exported key data" << endl;
375 const int bufsize = 512;
376 char buf[bufsize + 1];
377 while ((ret = gpgme_data_read(out.get(), buf, bufsize)) > 0) {
378 stream.write(buf, ret);
383 ERR <<
"Unable to read exported key data" << endl;
387 ERR <<
"Error exporting key: "<< err << endl;
397 if ( !
PathInfo( keyfile ).isExist() ) {
398 ERR <<
"Keyfile '" << keyfile <<
"' does not exist.";
402 GpgmeDataPtr data(
nullptr, gpgme_data_release);
405 err = gpgme_data_new_from_file(&data.get(), keyfile.
c_str(), 1);
407 ERR <<
"Error importing key: "<< err << endl;
411 err = gpgme_op_import(
_pimpl->
_ctx, data.get());
413 ERR <<
"Error importing key: "<< err << endl;
419 if ( gpgme_import_result_t res = gpgme_op_import_result(
_pimpl->
_ctx) )
424 ERR <<
"Error importing key: No keys considered (bsc#1127220, [libgpgme] signal received?)" << endl;
429 return (err == GPG_ERR_NO_ERROR);
435 GpgmeErr err = GPG_ERR_NO_ERROR;
437 gpgme_op_keylist_start(
_pimpl->
_ctx, NULL, 0);
439 while (!(err = gpgme_op_keylist_next(
_pimpl->
_ctx, &key))) {
440 if (key->subkeys &&
id ==
str::asString(key->subkeys->keyid)) {
443 gpgme_key_release(key);
447 ERR <<
"Error deleting key: "<< err << endl;
452 gpgme_key_release(key);
456 WAR <<
"Key: '"<<
id <<
"' not found." << endl;
static Ptr createForOpenPGP()
Creates a new KeyManagerCtx for PGP.
std::list< PublicKeyData > readKeyFromFile(const Pathname &file)
Returns a list of all.
std::list< std::string > readSignaturesFprs(const Pathname &signature_r)
Return all fingerprints found in signature_r.
Class representing one GPG Public Keys data.
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.
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.
bool importKey(const Pathname &keyfile)
Tries to import a key from keyfile, returns true on success.
Provide a new empty temporary directory and recursively delete it when no longer needed.
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.
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.
bool setHomedir(const Pathname &keyring_r)
Changes the keyring directory.
shared_ptr< KeyManagerCtx > Ptr
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.