diff options
author | Andre Heinecke <[email protected]> | 2016-02-22 17:28:08 +0000 |
---|---|---|
committer | Andre Heinecke <[email protected]> | 2016-02-22 18:01:37 +0000 |
commit | 0855a1296a1908016f011eb5e6552854ac53e63a (patch) | |
tree | ae662e7201a7d60d0e7733532ebded629cfacb94 /lang/cpp/src/key.cpp | |
parent | Fix possible _SC_OPEN_MAX max problem on AIX. (diff) | |
download | gpgme-0855a1296a1908016f011eb5e6552854ac53e63a.tar.gz gpgme-0855a1296a1908016f011eb5e6552854ac53e63a.zip |
Initial checkin of gpgmepp sources
Based on git.kde.org/pim/gpgmepp rev. 0e3ebc02
* lang/cpp/src/assuanresult.cpp,
lang/cpp/src/assuanresult.h,
lang/cpp/src/callbacks.cpp,
lang/cpp/src/callbacks.h,
lang/cpp/src/configuration.cpp,
lang/cpp/src/configuration.h,
lang/cpp/src/context.cpp,
lang/cpp/src/context.h,
lang/cpp/src/context_glib.cpp,
lang/cpp/src/context_p.h,
lang/cpp/src/context_qt.cpp,
lang/cpp/src/context_vanilla.cpp,
lang/cpp/src/data.cpp,
lang/cpp/src/data.h,
lang/cpp/src/data_p.h,
lang/cpp/src/decryptionresult.cpp,
lang/cpp/src/decryptionresult.h,
lang/cpp/src/defaultassuantransaction.cpp,
lang/cpp/src/defaultassuantransaction.h,
lang/cpp/src/editinteractor.cpp,
lang/cpp/src/editinteractor.h,
lang/cpp/src/encryptionresult.cpp,
lang/cpp/src/encryptionresult.h,
lang/cpp/src/engineinfo.cpp,
lang/cpp/src/engineinfo.h,
lang/cpp/src/error.h,
lang/cpp/src/eventloopinteractor.cpp,
lang/cpp/src/eventloopinteractor.h,
lang/cpp/src/exception.cpp,
lang/cpp/src/exception.h,
lang/cpp/src/global.h,
lang/cpp/src/gpgadduserideditinteractor.cpp,
lang/cpp/src/gpgadduserideditinteractor.h,
lang/cpp/src/gpgagentgetinfoassuantransaction.cpp,
lang/cpp/src/gpgagentgetinfoassuantransaction.h,
lang/cpp/src/gpgmefw.h,
lang/cpp/src/gpgmepp_export.h,
lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp,
lang/cpp/src/gpgsetexpirytimeeditinteractor.h,
lang/cpp/src/gpgsetownertrusteditinteractor.cpp,
lang/cpp/src/gpgsetownertrusteditinteractor.h,
lang/cpp/src/gpgsignkeyeditinteractor.cpp,
lang/cpp/src/gpgsignkeyeditinteractor.h,
lang/cpp/src/importresult.cpp,
lang/cpp/src/importresult.h,
lang/cpp/src/key.cpp,
lang/cpp/src/key.h,
lang/cpp/src/keygenerationresult.cpp,
lang/cpp/src/keygenerationresult.h,
lang/cpp/src/keylistresult.cpp,
lang/cpp/src/keylistresult.h,
lang/cpp/src/notation.h,
lang/cpp/src/result.h,
lang/cpp/src/result_p.h,
lang/cpp/src/scdgetinfoassuantransaction.cpp,
lang/cpp/src/scdgetinfoassuantransaction.h,
lang/cpp/src/signingresult.cpp,
lang/cpp/src/signingresult.h,
lang/cpp/src/trustitem.cpp,
lang/cpp/src/trustitem.h,
lang/cpp/src/util.h,
lang/cpp/src/verificationresult.cpp,
lang/cpp/src/verificationresult.h,
lang/cpp/src/vfsmountresult.cpp,
lang/cpp/src/vfsmountresult.h,
lang/cpp/src/interfaces/assuantransaction.h,
lang/cpp/src/interfaces/dataprovider.h,
lang/cpp/src/interfaces/passphraseprovider.h,
lang/cpp/src/interfaces/progressprovider.h: New.
Diffstat (limited to '')
-rw-r--r-- | lang/cpp/src/key.cpp | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp new file mode 100644 index 00000000..5eadbdd2 --- /dev/null +++ b/lang/cpp/src/key.cpp @@ -0,0 +1,847 @@ +/* + key.cpp - wraps a gpgme key + Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config-gpgme++.h" + +#include <key.h> + +#include "util.h" + +#include <gpgme.h> + +#include <string.h> + +const GpgME::Key::Null GpgME::Key::null; + +namespace GpgME +{ + +Key::Key() : key() {} + +Key::Key(const Null &) : key() {} + +Key::Key(const shared_gpgme_key_t &k) : key(k) {} + +Key::Key(gpgme_key_t k, bool ref) + : key(k + ? shared_gpgme_key_t(k, &gpgme_key_unref) + : shared_gpgme_key_t()) +{ + if (ref && impl()) { + gpgme_key_ref(impl()); + } +} + +UserID Key::userID(unsigned int index) const +{ + return UserID(key, index); +} + +Subkey Key::subkey(unsigned int index) const +{ + return Subkey(key, index); +} + +unsigned int Key::numUserIDs() const +{ + if (!key) { + return 0; + } + unsigned int count = 0; + for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) { + ++count; + } + return count; +} + +unsigned int Key::numSubkeys() const +{ + if (!key) { + return 0; + } + unsigned int count = 0; + for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) { + ++count; + } + return count; +} + +std::vector<UserID> Key::userIDs() const +{ + if (!key) { + return std::vector<UserID>(); + } + + std::vector<UserID> v; + v.reserve(numUserIDs()); + for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) { + v.push_back(UserID(key, uid)); + } + return v; +} + +std::vector<Subkey> Key::subkeys() const +{ + if (!key) { + return std::vector<Subkey>(); + } + + std::vector<Subkey> v; + v.reserve(numSubkeys()); + for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) { + v.push_back(Subkey(key, subkey)); + } + return v; +} + +Key::OwnerTrust Key::ownerTrust() const +{ + if (!key) { + return Unknown; + } + switch (key->owner_trust) { + default: + case GPGME_VALIDITY_UNKNOWN: return Unknown; + case GPGME_VALIDITY_UNDEFINED: return Undefined; + case GPGME_VALIDITY_NEVER: return Never; + case GPGME_VALIDITY_MARGINAL: return Marginal; + case GPGME_VALIDITY_FULL: return Full; + case GPGME_VALIDITY_ULTIMATE: return Ultimate; + } +} +char Key::ownerTrustAsString() const +{ + if (!key) { + return '?'; + } + switch (key->owner_trust) { + default: + case GPGME_VALIDITY_UNKNOWN: return '?'; + case GPGME_VALIDITY_UNDEFINED: return 'q'; + case GPGME_VALIDITY_NEVER: return 'n'; + case GPGME_VALIDITY_MARGINAL: return 'm'; + case GPGME_VALIDITY_FULL: return 'f'; + case GPGME_VALIDITY_ULTIMATE: return 'u'; + } +} + +Protocol Key::protocol() const +{ + if (!key) { + return UnknownProtocol; + } + switch (key->protocol) { + case GPGME_PROTOCOL_CMS: return CMS; + case GPGME_PROTOCOL_OpenPGP: return OpenPGP; + default: return UnknownProtocol; + } +} + +const char *Key::protocolAsString() const +{ + return key ? gpgme_get_protocol_name(key->protocol) : 0 ; +} + +bool Key::isRevoked() const +{ + return key && key->revoked; +} + +bool Key::isExpired() const +{ + return key && key->expired; +} + +bool Key::isDisabled() const +{ + return key && key->disabled; +} + +bool Key::isInvalid() const +{ + return key && key->invalid; +} + +bool Key::hasSecret() const +{ + return key && key->secret; +} + +bool Key::isRoot() const +{ + return key && key->subkeys && key->subkeys->fpr && key->chain_id && + strcasecmp(key->subkeys->fpr, key->chain_id) == 0; +} + +bool Key::canEncrypt() const +{ + return key && key->can_encrypt; +} + +bool Key::canSign() const +{ +#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN + if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) { + return true; + } +#endif + return canReallySign(); +} + +bool Key::canReallySign() const +{ + return key && key->can_sign; +} + +bool Key::canCertify() const +{ + return key && key->can_certify; +} + +bool Key::canAuthenticate() const +{ + return key && key->can_authenticate; +} + +bool Key::isQualified() const +{ +#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED + return key && key->is_qualified; +#else + return false; +#endif +} + +const char *Key::issuerSerial() const +{ + return key ? key->issuer_serial : 0 ; +} +const char *Key::issuerName() const +{ + return key ? key->issuer_name : 0 ; +} +const char *Key::chainID() const +{ + return key ? key->chain_id : 0 ; +} + +const char *Key::keyID() const +{ + return key && key->subkeys ? key->subkeys->keyid : 0 ; +} + +const char *Key::shortKeyID() const +{ + if (!key || !key->subkeys || !key->subkeys->keyid) { + return 0; + } + const int len = strlen(key->subkeys->keyid); + if (len > 8) { + return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation) + } else { + return key->subkeys->keyid; + } +} + +const char *Key::primaryFingerprint() const +{ + const char *fpr = key && key->subkeys ? key->subkeys->fpr : 0 ; + if (fpr) { + return fpr; + } else { + return keyID(); + } +} + +unsigned int Key::keyListMode() const +{ + return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ; +} + +const Key &Key::mergeWith(const Key &other) +{ + // ### incomplete. Just merges has* and can*, nothing else atm + // ### detach also missing + + if (!this->primaryFingerprint() || + !other.primaryFingerprint() || + strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) { + return *this; // only merge the Key object which describe the same key + } + + const gpgme_key_t me = impl(); + const gpgme_key_t him = other.impl(); + + if (!me || !him) { + return *this; + } + + me->revoked |= him->revoked; + me->expired |= him->expired; + me->disabled |= him->disabled; + me->invalid |= him->invalid; + me->can_encrypt |= him->can_encrypt; + me->can_sign |= him->can_sign; + me->can_certify |= him->can_certify; + me->secret |= him->secret; + me->can_authenticate |= him->can_authenticate; +#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED + me->is_qualified |= him->is_qualified; +#endif + me->keylist_mode |= him->keylist_mode; + +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost: + for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) { + for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) { + if (strcmp(mysk->fpr, hissk->fpr) == 0) { + mysk->is_cardkey |= hissk->is_cardkey; + break; + } + } + } +#endif + + return *this; +} + +// +// +// class Subkey +// +// + +gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx) +{ + if (key) { + for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) { + if (idx == 0) { + return s; + } + } + } + return 0; +} + +gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey) +{ + if (key) { + for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) { + if (s == subkey) { + return subkey; + } + } + } + return 0; +} + +Subkey::Subkey() : key(), subkey(0) {} + +Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx) + : key(k), subkey(find_subkey(k, idx)) +{ + +} + +Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk) + : key(k), subkey(verify_subkey(k, sk)) +{ + +} + +Key Subkey::parent() const +{ + return Key(key); +} + +const char *Subkey::keyID() const +{ + return subkey ? subkey->keyid : 0 ; +} + +const char *Subkey::fingerprint() const +{ + return subkey ? subkey->fpr : 0 ; +} + +unsigned int Subkey::publicKeyAlgorithm() const +{ + return subkey ? subkey->pubkey_algo : 0 ; +} + +const char *Subkey::publicKeyAlgorithmAsString() const +{ + return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0); +} + +bool Subkey::canEncrypt() const +{ + return subkey && subkey->can_encrypt; +} + +bool Subkey::canSign() const +{ + return subkey && subkey->can_sign; +} + +bool Subkey::canCertify() const +{ + return subkey && subkey->can_certify; +} + +bool Subkey::canAuthenticate() const +{ + return subkey && subkey->can_authenticate; +} + +bool Subkey::isQualified() const +{ +#ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED + return subkey && subkey->is_qualified; +#else + return false; +#endif +} + +bool Subkey::isCardKey() const +{ +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + return subkey && subkey->is_cardkey; +#else + return false; +#endif +} + +const char *Subkey::cardSerialNumber() const +{ +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + return subkey ? subkey->card_number : 0 ; +#else + return 0; +#endif +} + +bool Subkey::isSecret() const +{ + return subkey && subkey->secret; +} + +unsigned int Subkey::length() const +{ + return subkey ? subkey->length : 0 ; +} + +time_t Subkey::creationTime() const +{ + return static_cast<time_t>(subkey ? subkey->timestamp : 0); +} + +time_t Subkey::expirationTime() const +{ + return static_cast<time_t>(subkey ? subkey->expires : 0); +} + +bool Subkey::neverExpires() const +{ + return expirationTime() == time_t(0); +} + +bool Subkey::isRevoked() const +{ + return subkey && subkey->revoked; +} + +bool Subkey::isInvalid() const +{ + return subkey && subkey->invalid; +} + +bool Subkey::isExpired() const +{ + return subkey && subkey->expired; +} + +bool Subkey::isDisabled() const +{ + return subkey && subkey->disabled; +} + +// +// +// class UserID +// +// + +gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx) +{ + if (key) { + for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) { + if (idx == 0) { + return u; + } + } + } + return 0; +} + +gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid) +{ + if (key) { + for (gpgme_user_id_t u = key->uids ; u ; u = u->next) { + if (u == uid) { + return uid; + } + } + } + return 0; +} + +UserID::UserID() : key(), uid(0) {} + +UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u) + : key(k), uid(verify_uid(k, u)) +{ + +} + +UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx) + : key(k), uid(find_uid(k, idx)) +{ + +} + +Key UserID::parent() const +{ + return Key(key); +} + +UserID::Signature UserID::signature(unsigned int index) const +{ + return Signature(key, uid, index); +} + +unsigned int UserID::numSignatures() const +{ + if (!uid) { + return 0; + } + unsigned int count = 0; + for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) { + ++count; + } + return count; +} + +std::vector<UserID::Signature> UserID::signatures() const +{ + if (!uid) { + return std::vector<Signature>(); + } + + std::vector<Signature> v; + v.reserve(numSignatures()); + for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) { + v.push_back(Signature(key, uid, sig)); + } + return v; +} + +const char *UserID::id() const +{ + return uid ? uid->uid : 0 ; +} + +const char *UserID::name() const +{ + return uid ? uid->name : 0 ; +} + +const char *UserID::email() const +{ + return uid ? uid->email : 0 ; +} + +const char *UserID::comment() const +{ + return uid ? uid->comment : 0 ; +} + +UserID::Validity UserID::validity() const +{ + if (!uid) { + return Unknown; + } + switch (uid->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return Unknown; + case GPGME_VALIDITY_UNDEFINED: return Undefined; + case GPGME_VALIDITY_NEVER: return Never; + case GPGME_VALIDITY_MARGINAL: return Marginal; + case GPGME_VALIDITY_FULL: return Full; + case GPGME_VALIDITY_ULTIMATE: return Ultimate; + } +} + +char UserID::validityAsString() const +{ + if (!uid) { + return '?'; + } + switch (uid->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return '?'; + case GPGME_VALIDITY_UNDEFINED: return 'q'; + case GPGME_VALIDITY_NEVER: return 'n'; + case GPGME_VALIDITY_MARGINAL: return 'm'; + case GPGME_VALIDITY_FULL: return 'f'; + case GPGME_VALIDITY_ULTIMATE: return 'u'; + } +} + +bool UserID::isRevoked() const +{ + return uid && uid->revoked; +} + +bool UserID::isInvalid() const +{ + return uid && uid->invalid; +} + +// +// +// class Signature +// +// + +gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx) +{ + if (uid) { + for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) { + if (idx == 0) { + return s; + } + } + } + return 0; +} + +gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig) +{ + if (uid) { + for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) { + if (s == sig) { + return sig; + } + } + } + return 0; +} + +UserID::Signature::Signature() : key(), uid(0), sig(0) {} + +UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx) + : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx)) +{ + +} + +UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s) + : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s)) +{ + +} + +UserID UserID::Signature::parent() const +{ + return UserID(key, uid); +} + +const char *UserID::Signature::signerKeyID() const +{ + return sig ? sig->keyid : 0 ; +} + +const char *UserID::Signature::algorithmAsString() const +{ + return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0); +} + +unsigned int UserID::Signature::algorithm() const +{ + return sig ? sig->pubkey_algo : 0 ; +} + +time_t UserID::Signature::creationTime() const +{ + return static_cast<time_t>(sig ? sig->timestamp : 0); +} + +time_t UserID::Signature::expirationTime() const +{ + return static_cast<time_t>(sig ? sig->expires : 0); +} + +bool UserID::Signature::neverExpires() const +{ + return expirationTime() == time_t(0); +} + +bool UserID::Signature::isRevokation() const +{ + return sig && sig->revoked; +} + +bool UserID::Signature::isInvalid() const +{ + return sig && sig->invalid; +} + +bool UserID::Signature::isExpired() const +{ + return sig && sig->expired; +} + +bool UserID::Signature::isExportable() const +{ + return sig && sig->exportable; +} + +const char *UserID::Signature::signerUserID() const +{ + return sig ? sig->uid : 0 ; +} + +const char *UserID::Signature::signerName() const +{ + return sig ? sig->name : 0 ; +} + +const char *UserID::Signature::signerEmail() const +{ + return sig ? sig->email : 0 ; +} + +const char *UserID::Signature::signerComment() const +{ + return sig ? sig->comment : 0 ; +} + +unsigned int UserID::Signature::certClass() const +{ + return sig ? sig->sig_class : 0 ; +} + +UserID::Signature::Status UserID::Signature::status() const +{ + if (!sig) { + return GeneralError; + } + + switch (gpgme_err_code(sig->status)) { + case GPG_ERR_NO_ERROR: return NoError; + case GPG_ERR_SIG_EXPIRED: return SigExpired; + case GPG_ERR_KEY_EXPIRED: return KeyExpired; + case GPG_ERR_BAD_SIGNATURE: return BadSignature; + case GPG_ERR_NO_PUBKEY: return NoPublicKey; + default: + case GPG_ERR_GENERAL: return GeneralError; + } +} + +std::string UserID::Signature::statusAsString() const +{ + if (!sig) { + return std::string(); + } + char buf[ 1024 ]; + gpgme_strerror_r(sig->status, buf, sizeof buf); + buf[ sizeof buf - 1 ] = '\0'; + return std::string(buf); +} + +GpgME::Notation UserID::Signature::notation(unsigned int idx) const +{ + if (!sig) { + return GpgME::Notation(); + } +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + if (idx-- == 0) { + return GpgME::Notation(nota); + } + } + } +#endif + return GpgME::Notation(); +} + +unsigned int UserID::Signature::numNotations() const +{ + if (!sig) { + return 0; + } + unsigned int count = 0; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + ++count; // others are policy URLs... + } + } +#endif + return count; +} + +std::vector<Notation> UserID::Signature::notations() const +{ + if (!sig) { + return std::vector<GpgME::Notation>(); + } + std::vector<GpgME::Notation> v; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + v.reserve(numNotations()); + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + v.push_back(GpgME::Notation(nota)); + } + } +#endif + return v; +} + +const char *UserID::Signature::policyURL() const +{ +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + if (!sig) { + return 0; + } + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (!nota->name) { + return nota->value; + } + } +#endif + return 0; +} + +} // namespace GpgME |