Blame lang/cpp/src/key.cpp

Packit d7e8d0
/*
Packit d7e8d0
  key.cpp - wraps a gpgme key
Packit d7e8d0
  Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
Packit d7e8d0
Packit d7e8d0
  This file is part of GPGME++.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is free software; you can redistribute it and/or
Packit d7e8d0
  modify it under the terms of the GNU Library General Public
Packit d7e8d0
  License as published by the Free Software Foundation; either
Packit d7e8d0
  version 2 of the License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is distributed in the hope that it will be useful,
Packit d7e8d0
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit d7e8d0
  GNU Library General Public License for more details.
Packit d7e8d0
Packit d7e8d0
  You should have received a copy of the GNU Library General Public License
Packit d7e8d0
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
Packit d7e8d0
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d7e8d0
  Boston, MA 02110-1301, USA.
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
 #include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include <key.h>
Packit d7e8d0
Packit d7e8d0
#include "util.h"
Packit d7e8d0
#include "tofuinfo.h"
Packit d7e8d0
#include "context.h"
Packit d7e8d0
Packit d7e8d0
#include <gpgme.h>
Packit d7e8d0
Packit d7e8d0
#include <string.h>
Packit d7e8d0
#include <strings.h>
Packit d7e8d0
#include <istream>
Packit d7e8d0
#include <iterator>
Packit d7e8d0
Packit d7e8d0
const GpgME::Key::Null GpgME::Key::null;
Packit d7e8d0
Packit d7e8d0
namespace GpgME
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
Key::Key() : key() {}
Packit d7e8d0
Packit d7e8d0
Key::Key(const Null &) : key() {}
Packit d7e8d0
Packit d7e8d0
Key::Key(const shared_gpgme_key_t &k) : key(k) {}
Packit d7e8d0
Packit d7e8d0
Key::Key(gpgme_key_t k, bool ref)
Packit d7e8d0
    : key(k
Packit d7e8d0
          ? shared_gpgme_key_t(k, &gpgme_key_unref)
Packit d7e8d0
          : shared_gpgme_key_t())
Packit d7e8d0
{
Packit d7e8d0
    if (ref && impl()) {
Packit d7e8d0
        gpgme_key_ref(impl());
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID Key::userID(unsigned int index) const
Packit d7e8d0
{
Packit d7e8d0
    return UserID(key, index);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Subkey Key::subkey(unsigned int index) const
Packit d7e8d0
{
Packit d7e8d0
    return Subkey(key, index);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Key::numUserIDs() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    unsigned int count = 0;
Packit d7e8d0
    for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
Packit d7e8d0
        ++count;
Packit d7e8d0
    }
Packit d7e8d0
    return count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Key::numSubkeys() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    unsigned int count = 0;
Packit d7e8d0
    for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
Packit d7e8d0
        ++count;
Packit d7e8d0
    }
Packit d7e8d0
    return count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<UserID> Key::userIDs() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return std::vector<UserID>();
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    std::vector<UserID> v;
Packit d7e8d0
    v.reserve(numUserIDs());
Packit d7e8d0
    for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
Packit d7e8d0
        v.push_back(UserID(key, uid));
Packit d7e8d0
    }
Packit d7e8d0
    return v;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<Subkey> Key::subkeys() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return std::vector<Subkey>();
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    std::vector<Subkey> v;
Packit d7e8d0
    v.reserve(numSubkeys());
Packit d7e8d0
    for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
Packit d7e8d0
        v.push_back(Subkey(key, subkey));
Packit d7e8d0
    }
Packit d7e8d0
    return v;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Key::OwnerTrust Key::ownerTrust() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return Unknown;
Packit d7e8d0
    }
Packit d7e8d0
    switch (key->owner_trust) {
Packit d7e8d0
    default:
Packit d7e8d0
    case GPGME_VALIDITY_UNKNOWN:   return Unknown;
Packit d7e8d0
    case GPGME_VALIDITY_UNDEFINED: return Undefined;
Packit d7e8d0
    case GPGME_VALIDITY_NEVER:     return Never;
Packit d7e8d0
    case GPGME_VALIDITY_MARGINAL:  return Marginal;
Packit d7e8d0
    case GPGME_VALIDITY_FULL:     return Full;
Packit d7e8d0
    case GPGME_VALIDITY_ULTIMATE: return Ultimate;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
char Key::ownerTrustAsString() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return '?';
Packit d7e8d0
    }
Packit d7e8d0
    switch (key->owner_trust) {
Packit d7e8d0
    default:
Packit d7e8d0
    case GPGME_VALIDITY_UNKNOWN:   return '?';
Packit d7e8d0
    case GPGME_VALIDITY_UNDEFINED: return 'q';
Packit d7e8d0
    case GPGME_VALIDITY_NEVER:     return 'n';
Packit d7e8d0
    case GPGME_VALIDITY_MARGINAL:  return 'm';
Packit d7e8d0
    case GPGME_VALIDITY_FULL:     return 'f';
Packit d7e8d0
    case GPGME_VALIDITY_ULTIMATE: return 'u';
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Protocol Key::protocol() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return UnknownProtocol;
Packit d7e8d0
    }
Packit d7e8d0
    switch (key->protocol) {
Packit d7e8d0
    case GPGME_PROTOCOL_CMS:     return CMS;
Packit d7e8d0
    case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
Packit d7e8d0
    default:                     return UnknownProtocol;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Key::protocolAsString() const
Packit d7e8d0
{
Packit d7e8d0
    return key ? gpgme_get_protocol_name(key->protocol) : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isRevoked() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->revoked;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isExpired() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->expired;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isDisabled() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->disabled;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isInvalid() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->invalid;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::hasSecret() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->secret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isRoot() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
Packit d7e8d0
           strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::canEncrypt() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->can_encrypt;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::canSign() const
Packit d7e8d0
{
Packit d7e8d0
#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
Packit d7e8d0
    if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
Packit d7e8d0
        return true;
Packit d7e8d0
    }
Packit d7e8d0
#endif
Packit d7e8d0
    return canReallySign();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::canReallySign() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->can_sign;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::canCertify() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->can_certify;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::canAuthenticate() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->can_authenticate;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isQualified() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->is_qualified;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Key::isDeVs() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return false;
Packit d7e8d0
    }
Packit d7e8d0
    if (!key->subkeys || !key->subkeys->is_de_vs) {
Packit d7e8d0
        return false;
Packit d7e8d0
    }
Packit d7e8d0
    for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
Packit d7e8d0
        if (!subkey->is_de_vs) {
Packit d7e8d0
            return false;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return true;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Key::issuerSerial() const
Packit d7e8d0
{
Packit d7e8d0
    return key ? key->issuer_serial : 0 ;
Packit d7e8d0
}
Packit d7e8d0
const char *Key::issuerName() const
Packit d7e8d0
{
Packit d7e8d0
    return key ? key->issuer_name : 0 ;
Packit d7e8d0
}
Packit d7e8d0
const char *Key::chainID() const
Packit d7e8d0
{
Packit d7e8d0
    return key ? key->chain_id : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Key::keyID() const
Packit d7e8d0
{
Packit d7e8d0
    return key && key->subkeys ? key->subkeys->keyid : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Key::shortKeyID() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key || !key->subkeys || !key->subkeys->keyid) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    const int len = strlen(key->subkeys->keyid);
Packit d7e8d0
    if (len > 8) {
Packit d7e8d0
        return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
Packit d7e8d0
    } else {
Packit d7e8d0
        return key->subkeys->keyid;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Key::primaryFingerprint() const
Packit d7e8d0
{
Packit d7e8d0
    if (!key) {
Packit d7e8d0
        return nullptr;
Packit d7e8d0
    }
Packit d7e8d0
    if (key->fpr) {
Packit d7e8d0
        /* Return what gpgme thinks is the primary fingerprint */
Packit d7e8d0
        return key->fpr;
Packit d7e8d0
    }
Packit d7e8d0
    if (key->subkeys) {
Packit d7e8d0
        /* Return the first subkeys fingerprint */
Packit d7e8d0
        return key->subkeys->fpr;
Packit d7e8d0
    }
Packit d7e8d0
    return nullptr;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Key::keyListMode() const
Packit d7e8d0
{
Packit d7e8d0
    return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const Key &Key::mergeWith(const Key &other)
Packit d7e8d0
{
Packit d7e8d0
    // ### incomplete. Just merges has* and can*, nothing else atm
Packit d7e8d0
    // ### detach also missing
Packit d7e8d0
Packit d7e8d0
    if (!this->primaryFingerprint() ||
Packit d7e8d0
            !other.primaryFingerprint() ||
Packit d7e8d0
            strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
Packit d7e8d0
        return *this; // only merge the Key object which describe the same key
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    const gpgme_key_t me = impl();
Packit d7e8d0
    const gpgme_key_t him = other.impl();
Packit d7e8d0
Packit d7e8d0
    if (!me || !him) {
Packit d7e8d0
        return *this;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    me->revoked          |= him->revoked;
Packit d7e8d0
    me->expired          |= him->expired;
Packit d7e8d0
    me->disabled         |= him->disabled;
Packit d7e8d0
    me->invalid          |= him->invalid;
Packit d7e8d0
    me->can_encrypt      |= him->can_encrypt;
Packit d7e8d0
    me->can_sign         |= him->can_sign;
Packit d7e8d0
    me->can_certify      |= him->can_certify;
Packit d7e8d0
    me->secret           |= him->secret;
Packit d7e8d0
    me->can_authenticate |= him->can_authenticate;
Packit d7e8d0
    me->is_qualified     |= him->is_qualified;
Packit d7e8d0
    me->keylist_mode     |= him->keylist_mode;
Packit d7e8d0
Packit d7e8d0
    // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
Packit d7e8d0
    for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
Packit d7e8d0
        for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
Packit d7e8d0
            if (strcmp(mysk->fpr, hissk->fpr) == 0) {
Packit d7e8d0
                mysk->is_cardkey |= hissk->is_cardkey;
Packit d7e8d0
                break;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    return *this;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void Key::update()
Packit d7e8d0
{
Packit d7e8d0
    auto ctx = Context::createForProtocol(protocol());
Packit d7e8d0
    if (!ctx) {
Packit d7e8d0
        return;
Packit d7e8d0
    }
Packit d7e8d0
    ctx->setKeyListMode(KeyListMode::Local |
Packit d7e8d0
                        KeyListMode::Signatures |
Packit d7e8d0
                        KeyListMode::SignatureNotations |
Packit d7e8d0
                        KeyListMode::Validate |
Packit d7e8d0
                        KeyListMode::WithTofu);
Packit d7e8d0
    Error err;
Packit d7e8d0
    auto newKey = ctx->key(primaryFingerprint(), err, true);
Packit d7e8d0
    // Not secret so we get the information from the pubring.
Packit d7e8d0
    if (newKey.isNull())
Packit d7e8d0
      {
Packit d7e8d0
        newKey = ctx->key(primaryFingerprint(), err, false);
Packit d7e8d0
      }
Packit d7e8d0
    delete ctx;
Packit d7e8d0
    if (err) {
Packit d7e8d0
        return;
Packit d7e8d0
    }
Packit d7e8d0
    swap(newKey);
Packit d7e8d0
    return;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
// class Subkey
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
Packit d7e8d0
{
Packit d7e8d0
    if (key) {
Packit d7e8d0
        for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
Packit d7e8d0
            if (idx == 0) {
Packit d7e8d0
                return s;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
Packit d7e8d0
{
Packit d7e8d0
    if (key) {
Packit d7e8d0
        for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
Packit d7e8d0
            if (s == subkey) {
Packit d7e8d0
                return subkey;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Subkey::Subkey() : key(), subkey(0) {}
Packit d7e8d0
Packit d7e8d0
Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
Packit d7e8d0
    : key(k), subkey(find_subkey(k, idx))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
Packit d7e8d0
    : key(k), subkey(verify_subkey(k, sk))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Key Subkey::parent() const
Packit d7e8d0
{
Packit d7e8d0
    return Key(key);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Subkey::keyID() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? subkey->keyid : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Subkey::fingerprint() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? subkey->fpr : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Subkey::publicKeyAlgorithmAsString() const
Packit d7e8d0
{
Packit d7e8d0
    return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* static */
Packit d7e8d0
const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
Packit d7e8d0
{
Packit d7e8d0
    if (algo == AlgoUnknown) {
Packit d7e8d0
        return NULL;
Packit d7e8d0
    }
Packit d7e8d0
    return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::string Subkey::algoName() const
Packit d7e8d0
{
Packit d7e8d0
    char *gpgmeStr;
Packit d7e8d0
    if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
Packit d7e8d0
        std::string ret = std::string(gpgmeStr);
Packit d7e8d0
        gpgme_free(gpgmeStr);
Packit d7e8d0
        return ret;
Packit d7e8d0
    }
Packit d7e8d0
    return std::string();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::canEncrypt() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->can_encrypt;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::canSign() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->can_sign;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::canCertify() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->can_certify;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::canAuthenticate() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->can_authenticate;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isQualified() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->is_qualified;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isDeVs() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->is_de_vs;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isCardKey() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->is_cardkey;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Subkey::cardSerialNumber() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? subkey->card_number : nullptr;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Subkey::keyGrip() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? subkey->keygrip : nullptr;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isSecret() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->secret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Subkey::length() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey ? subkey->length : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
time_t Subkey::creationTime() const
Packit d7e8d0
{
Packit d7e8d0
    return static_cast<time_t>(subkey ? subkey->timestamp : 0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
time_t Subkey::expirationTime() const
Packit d7e8d0
{
Packit d7e8d0
    return static_cast<time_t>(subkey ? subkey->expires : 0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::neverExpires() const
Packit d7e8d0
{
Packit d7e8d0
    return expirationTime() == time_t(0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isRevoked() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->revoked;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isInvalid() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->invalid;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isExpired() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->expired;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Subkey::isDisabled() const
Packit d7e8d0
{
Packit d7e8d0
    return subkey && subkey->disabled;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
// class UserID
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
Packit d7e8d0
{
Packit d7e8d0
    if (key) {
Packit d7e8d0
        for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
Packit d7e8d0
            if (idx == 0) {
Packit d7e8d0
                return u;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
Packit d7e8d0
{
Packit d7e8d0
    if (key) {
Packit d7e8d0
        for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
Packit d7e8d0
            if (u == uid) {
Packit d7e8d0
                return uid;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::UserID() : key(), uid(0) {}
Packit d7e8d0
Packit d7e8d0
UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
Packit d7e8d0
    : key(k), uid(verify_uid(k, u))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
Packit d7e8d0
    : key(k), uid(find_uid(k, idx))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Key UserID::parent() const
Packit d7e8d0
{
Packit d7e8d0
    return Key(key);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::Signature UserID::signature(unsigned int index) const
Packit d7e8d0
{
Packit d7e8d0
    return Signature(key, uid, index);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int UserID::numSignatures() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    unsigned int count = 0;
Packit d7e8d0
    for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
Packit d7e8d0
        ++count;
Packit d7e8d0
    }
Packit d7e8d0
    return count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<UserID::Signature> UserID::signatures() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid) {
Packit d7e8d0
        return std::vector<Signature>();
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    std::vector<Signature> v;
Packit d7e8d0
    v.reserve(numSignatures());
Packit d7e8d0
    for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
Packit d7e8d0
        v.push_back(Signature(key, uid, sig));
Packit d7e8d0
    }
Packit d7e8d0
    return v;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::id() const
Packit d7e8d0
{
Packit d7e8d0
    return uid ? uid->uid : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::name() const
Packit d7e8d0
{
Packit d7e8d0
    return uid ? uid->name : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::email() const
Packit d7e8d0
{
Packit d7e8d0
    return uid ? uid->email : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::comment() const
Packit d7e8d0
{
Packit d7e8d0
    return uid ? uid->comment : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::Validity UserID::validity() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid) {
Packit d7e8d0
        return Unknown;
Packit d7e8d0
    }
Packit d7e8d0
    switch (uid->validity) {
Packit d7e8d0
    default:
Packit d7e8d0
    case GPGME_VALIDITY_UNKNOWN:   return Unknown;
Packit d7e8d0
    case GPGME_VALIDITY_UNDEFINED: return Undefined;
Packit d7e8d0
    case GPGME_VALIDITY_NEVER:     return Never;
Packit d7e8d0
    case GPGME_VALIDITY_MARGINAL:  return Marginal;
Packit d7e8d0
    case GPGME_VALIDITY_FULL:      return Full;
Packit d7e8d0
    case GPGME_VALIDITY_ULTIMATE:  return Ultimate;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
char UserID::validityAsString() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid) {
Packit d7e8d0
        return '?';
Packit d7e8d0
    }
Packit d7e8d0
    switch (uid->validity) {
Packit d7e8d0
    default:
Packit d7e8d0
    case GPGME_VALIDITY_UNKNOWN:   return '?';
Packit d7e8d0
    case GPGME_VALIDITY_UNDEFINED: return 'q';
Packit d7e8d0
    case GPGME_VALIDITY_NEVER:     return 'n';
Packit d7e8d0
    case GPGME_VALIDITY_MARGINAL:  return 'm';
Packit d7e8d0
    case GPGME_VALIDITY_FULL:      return 'f';
Packit d7e8d0
    case GPGME_VALIDITY_ULTIMATE:  return 'u';
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::isRevoked() const
Packit d7e8d0
{
Packit d7e8d0
    return uid && uid->revoked;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::isInvalid() const
Packit d7e8d0
{
Packit d7e8d0
    return uid && uid->invalid;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
TofuInfo UserID::tofuInfo() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid) {
Packit d7e8d0
        return TofuInfo();
Packit d7e8d0
    }
Packit d7e8d0
    return TofuInfo(uid->tofu);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
// class Signature
Packit d7e8d0
//
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
Packit d7e8d0
{
Packit d7e8d0
    if (uid) {
Packit d7e8d0
        for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
Packit d7e8d0
            if (idx == 0) {
Packit d7e8d0
                return s;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
Packit d7e8d0
{
Packit d7e8d0
    if (uid) {
Packit d7e8d0
        for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
Packit d7e8d0
            if (s == sig) {
Packit d7e8d0
                return sig;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::Signature::Signature() : key(), uid(0), sig(0) {}
Packit d7e8d0
Packit d7e8d0
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
Packit d7e8d0
    : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
Packit d7e8d0
    : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID UserID::Signature::parent() const
Packit d7e8d0
{
Packit d7e8d0
    return UserID(key, uid);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::signerKeyID() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->keyid : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::algorithmAsString() const
Packit d7e8d0
{
Packit d7e8d0
    return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int UserID::Signature::algorithm() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->pubkey_algo : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
time_t UserID::Signature::creationTime() const
Packit d7e8d0
{
Packit d7e8d0
    return static_cast<time_t>(sig ? sig->timestamp : 0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
time_t UserID::Signature::expirationTime() const
Packit d7e8d0
{
Packit d7e8d0
    return static_cast<time_t>(sig ? sig->expires : 0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::Signature::neverExpires() const
Packit d7e8d0
{
Packit d7e8d0
    return expirationTime() == time_t(0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::Signature::isRevokation() const
Packit d7e8d0
{
Packit d7e8d0
    return sig && sig->revoked;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::Signature::isInvalid() const
Packit d7e8d0
{
Packit d7e8d0
    return sig && sig->invalid;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::Signature::isExpired() const
Packit d7e8d0
{
Packit d7e8d0
    return sig && sig->expired;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool UserID::Signature::isExportable() const
Packit d7e8d0
{
Packit d7e8d0
    return sig && sig->exportable;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::signerUserID() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->uid : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::signerName() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->name : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::signerEmail() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->email : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::signerComment() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->comment : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int UserID::Signature::certClass() const
Packit d7e8d0
{
Packit d7e8d0
    return sig ? sig->sig_class : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
UserID::Signature::Status UserID::Signature::status() const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return GeneralError;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    switch (gpgme_err_code(sig->status)) {
Packit d7e8d0
    case GPG_ERR_NO_ERROR:      return NoError;
Packit d7e8d0
    case GPG_ERR_SIG_EXPIRED:   return SigExpired;
Packit d7e8d0
    case GPG_ERR_KEY_EXPIRED:   return KeyExpired;
Packit d7e8d0
    case GPG_ERR_BAD_SIGNATURE: return BadSignature;
Packit d7e8d0
    case GPG_ERR_NO_PUBKEY:     return NoPublicKey;
Packit d7e8d0
    default:
Packit d7e8d0
    case GPG_ERR_GENERAL:       return GeneralError;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::string UserID::Signature::statusAsString() const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return std::string();
Packit d7e8d0
    }
Packit d7e8d0
    char buf[ 1024 ];
Packit d7e8d0
    gpgme_strerror_r(sig->status, buf, sizeof buf);
Packit d7e8d0
    buf[ sizeof buf - 1 ] = '\0';
Packit d7e8d0
    return std::string(buf);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
GpgME::Notation UserID::Signature::notation(unsigned int idx) const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return GpgME::Notation();
Packit d7e8d0
    }
Packit d7e8d0
    for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
Packit d7e8d0
        if (nota->name) {
Packit d7e8d0
            if (idx-- == 0) {
Packit d7e8d0
                return GpgME::Notation(nota);
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return GpgME::Notation();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int UserID::Signature::numNotations() const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    unsigned int count = 0;
Packit d7e8d0
    for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
Packit d7e8d0
        if (nota->name) {
Packit d7e8d0
            ++count; // others are policy URLs...
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<Notation> UserID::Signature::notations() const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return std::vector<GpgME::Notation>();
Packit d7e8d0
    }
Packit d7e8d0
    std::vector<GpgME::Notation> v;
Packit d7e8d0
    v.reserve(numNotations());
Packit d7e8d0
    for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
Packit d7e8d0
        if (nota->name) {
Packit d7e8d0
            v.push_back(GpgME::Notation(nota));
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return v;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *UserID::Signature::policyURL() const
Packit d7e8d0
{
Packit d7e8d0
    if (!sig) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
Packit d7e8d0
        if (!nota->name) {
Packit d7e8d0
            return nota->value;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::string UserID::addrSpecFromString(const char *userid)
Packit d7e8d0
{
Packit d7e8d0
    if (!userid) {
Packit d7e8d0
        return std::string();
Packit d7e8d0
    }
Packit d7e8d0
    char *normalized = gpgme_addrspec_from_uid (userid);
Packit d7e8d0
    if (normalized) {
Packit d7e8d0
        std::string ret(normalized);
Packit d7e8d0
        gpgme_free(normalized);
Packit d7e8d0
        return ret;
Packit d7e8d0
    }
Packit d7e8d0
    return std::string();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::string UserID::addrSpec() const
Packit d7e8d0
{
Packit d7e8d0
    if (!uid || !uid->address) {
Packit d7e8d0
        return std::string();
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    return uid->address;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error UserID::revoke()
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error::fromCode(GPG_ERR_GENERAL);
Packit d7e8d0
    }
Packit d7e8d0
    auto ctx = Context::createForProtocol(parent().protocol());
Packit d7e8d0
    if (!ctx) {
Packit d7e8d0
        return Error::fromCode(GPG_ERR_INV_ENGINE);
Packit d7e8d0
    }
Packit d7e8d0
    Error ret = ctx->revUid(key, id());
Packit d7e8d0
    delete ctx;
Packit d7e8d0
    return ret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error Key::addUid(const char *uid)
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error::fromCode(GPG_ERR_GENERAL);
Packit d7e8d0
    }
Packit d7e8d0
    auto ctx = Context::createForProtocol(protocol());
Packit d7e8d0
    if (!ctx) {
Packit d7e8d0
        return Error::fromCode(GPG_ERR_INV_ENGINE);
Packit d7e8d0
    }
Packit d7e8d0
    Error ret = ctx->addUid(key, uid);
Packit d7e8d0
    delete ctx;
Packit d7e8d0
    return ret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &operator<<(std::ostream &os, const UserID &uid)
Packit d7e8d0
{
Packit d7e8d0
    os << "GpgME::UserID(";
Packit d7e8d0
    if (!uid.isNull()) {
Packit d7e8d0
        os << "\n name:      " << protect(uid.name())
Packit d7e8d0
           << "\n email:     " << protect(uid.email())
Packit d7e8d0
           << "\n mbox:      " << uid.addrSpec()
Packit d7e8d0
           << "\n comment:   " << protect(uid.comment())
Packit d7e8d0
           << "\n validity:  " << uid.validityAsString()
Packit d7e8d0
           << "\n revoked:   " << uid.isRevoked()
Packit d7e8d0
           << "\n invalid:   " << uid.isInvalid()
Packit d7e8d0
           << "\n numsigs:   " << uid.numSignatures()
Packit d7e8d0
           << "\n tofuinfo:\n" << uid.tofuInfo();
Packit d7e8d0
    }
Packit d7e8d0
    return os << ')';
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &operator<<(std::ostream &os, const Key &key)
Packit d7e8d0
{
Packit d7e8d0
    os << "GpgME::Key(";
Packit d7e8d0
    if (!key.isNull()) {
Packit d7e8d0
        os << "\n protocol:   " << protect(key.protocolAsString())
Packit d7e8d0
           << "\n ownertrust: " << key.ownerTrustAsString()
Packit d7e8d0
           << "\n issuer:     " << protect(key.issuerName())
Packit d7e8d0
           << "\n fingerprint:" << protect(key.primaryFingerprint())
Packit d7e8d0
           << "\n listmode:   " << key.keyListMode()
Packit d7e8d0
           << "\n canSign:    " << key.canReallySign()
Packit d7e8d0
           << "\n canEncrypt: " << key.canEncrypt()
Packit d7e8d0
           << "\n canCertify: " << key.canCertify()
Packit d7e8d0
           << "\n canAuth:    " << key.canAuthenticate()
Packit d7e8d0
           << "\n uids:\n";
Packit d7e8d0
        const std::vector<UserID> uids = key.userIDs();
Packit d7e8d0
        std::copy(uids.begin(), uids.end(),
Packit d7e8d0
                  std::ostream_iterator<UserID>(os, "\n"));
Packit d7e8d0
    }
Packit d7e8d0
    return os << ')';
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
} // namespace GpgME