LCOV - code coverage report
Current view: top level - lang/cpp/src - key.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 104 523 19.9 %
Date: 2018-11-15 08:49:49 Functions: 27 129 20.9 %

          Line data    Source code
       1             : /*
       2             :   key.cpp - wraps a gpgme key
       3             :   Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
       4             : 
       5             :   This file is part of GPGME++.
       6             : 
       7             :   GPGME++ is free software; you can redistribute it and/or
       8             :   modify it under the terms of the GNU Library General Public
       9             :   License as published by the Free Software Foundation; either
      10             :   version 2 of the License, or (at your option) any later version.
      11             : 
      12             :   GPGME++ is distributed in the hope that it will be useful,
      13             :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :   GNU Library General Public License for more details.
      16             : 
      17             :   You should have received a copy of the GNU Library General Public License
      18             :   along with GPGME++; see the file COPYING.LIB.  If not, write to the
      19             :   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      20             :   Boston, MA 02110-1301, USA.
      21             : */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             :  #include "config.h"
      25             : #endif
      26             : 
      27             : #include <key.h>
      28             : 
      29             : #include "util.h"
      30             : #include "tofuinfo.h"
      31             : #include "context.h"
      32             : 
      33             : #include <gpgme.h>
      34             : 
      35             : #include <string.h>
      36             : #include <strings.h>
      37             : #include <istream>
      38             : #include <iterator>
      39             : 
      40           8 : const GpgME::Key::Null GpgME::Key::null;
      41             : 
      42             : namespace GpgME
      43             : {
      44             : 
      45           3 : Key::Key() : key() {}
      46             : 
      47           0 : Key::Key(const Null &) : key() {}
      48             : 
      49           0 : Key::Key(const shared_gpgme_key_t &k) : key(k) {}
      50             : 
      51          57 : Key::Key(gpgme_key_t k, bool ref)
      52             :     : key(k
      53             :           ? shared_gpgme_key_t(k, &gpgme_key_unref)
      54          57 :           : shared_gpgme_key_t())
      55             : {
      56          57 :     if (ref && impl()) {
      57          11 :         gpgme_key_ref(impl());
      58             :     }
      59          57 : }
      60             : 
      61          17 : UserID Key::userID(unsigned int index) const
      62             : {
      63          17 :     return UserID(key, index);
      64             : }
      65             : 
      66           0 : Subkey Key::subkey(unsigned int index) const
      67             : {
      68           0 :     return Subkey(key, index);
      69             : }
      70             : 
      71          12 : unsigned int Key::numUserIDs() const
      72             : {
      73          12 :     if (!key) {
      74           0 :         return 0;
      75             :     }
      76          12 :     unsigned int count = 0;
      77          39 :     for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
      78          27 :         ++count;
      79             :     }
      80          12 :     return count;
      81             : }
      82             : 
      83           4 : unsigned int Key::numSubkeys() const
      84             : {
      85           4 :     if (!key) {
      86           0 :         return 0;
      87             :     }
      88           4 :     unsigned int count = 0;
      89          12 :     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
      90           8 :         ++count;
      91             :     }
      92           4 :     return count;
      93             : }
      94             : 
      95           9 : std::vector<UserID> Key::userIDs() const
      96             : {
      97           9 :     if (!key) {
      98           0 :         return std::vector<UserID>();
      99             :     }
     100             : 
     101          18 :     std::vector<UserID> v;
     102           9 :     v.reserve(numUserIDs());
     103          26 :     for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
     104          17 :         v.push_back(UserID(key, uid));
     105             :     }
     106           9 :     return v;
     107             : }
     108             : 
     109           4 : std::vector<Subkey> Key::subkeys() const
     110             : {
     111           4 :     if (!key) {
     112           0 :         return std::vector<Subkey>();
     113             :     }
     114             : 
     115           8 :     std::vector<Subkey> v;
     116           4 :     v.reserve(numSubkeys());
     117          12 :     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
     118           8 :         v.push_back(Subkey(key, subkey));
     119             :     }
     120           4 :     return v;
     121             : }
     122             : 
     123           3 : Key::OwnerTrust Key::ownerTrust() const
     124             : {
     125           3 :     if (!key) {
     126           0 :         return Unknown;
     127             :     }
     128           3 :     switch (key->owner_trust) {
     129             :     default:
     130           2 :     case GPGME_VALIDITY_UNKNOWN:   return Unknown;
     131           0 :     case GPGME_VALIDITY_UNDEFINED: return Undefined;
     132           0 :     case GPGME_VALIDITY_NEVER:     return Never;
     133           0 :     case GPGME_VALIDITY_MARGINAL:  return Marginal;
     134           0 :     case GPGME_VALIDITY_FULL:     return Full;
     135           1 :     case GPGME_VALIDITY_ULTIMATE: return Ultimate;
     136             :     }
     137             : }
     138           0 : char Key::ownerTrustAsString() const
     139             : {
     140           0 :     if (!key) {
     141           0 :         return '?';
     142             :     }
     143           0 :     switch (key->owner_trust) {
     144             :     default:
     145           0 :     case GPGME_VALIDITY_UNKNOWN:   return '?';
     146           0 :     case GPGME_VALIDITY_UNDEFINED: return 'q';
     147           0 :     case GPGME_VALIDITY_NEVER:     return 'n';
     148           0 :     case GPGME_VALIDITY_MARGINAL:  return 'm';
     149           0 :     case GPGME_VALIDITY_FULL:     return 'f';
     150           0 :     case GPGME_VALIDITY_ULTIMATE: return 'u';
     151             :     }
     152             : }
     153             : 
     154           9 : Protocol Key::protocol() const
     155             : {
     156           9 :     if (!key) {
     157           0 :         return UnknownProtocol;
     158             :     }
     159           9 :     switch (key->protocol) {
     160           0 :     case GPGME_PROTOCOL_CMS:     return CMS;
     161           9 :     case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
     162           0 :     default:                     return UnknownProtocol;
     163             :     }
     164             : }
     165             : 
     166           0 : const char *Key::protocolAsString() const
     167             : {
     168           0 :     return key ? gpgme_get_protocol_name(key->protocol) : 0 ;
     169             : }
     170             : 
     171           0 : bool Key::isRevoked() const
     172             : {
     173           0 :     return key && key->revoked;
     174             : }
     175             : 
     176           0 : bool Key::isExpired() const
     177             : {
     178           0 :     return key && key->expired;
     179             : }
     180             : 
     181           0 : bool Key::isDisabled() const
     182             : {
     183           0 :     return key && key->disabled;
     184             : }
     185             : 
     186           0 : bool Key::isInvalid() const
     187             : {
     188           0 :     return key && key->invalid;
     189             : }
     190             : 
     191           0 : bool Key::hasSecret() const
     192             : {
     193           0 :     return key && key->secret;
     194             : }
     195             : 
     196           0 : bool Key::isRoot() const
     197             : {
     198           0 :     return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
     199           0 :            strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
     200             : }
     201             : 
     202           0 : bool Key::canEncrypt() const
     203             : {
     204           0 :     return key && key->can_encrypt;
     205             : }
     206             : 
     207           0 : bool Key::canSign() const
     208             : {
     209             : #ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
     210           0 :     if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
     211           0 :         return true;
     212             :     }
     213             : #endif
     214           0 :     return canReallySign();
     215             : }
     216             : 
     217           0 : bool Key::canReallySign() const
     218             : {
     219           0 :     return key && key->can_sign;
     220             : }
     221             : 
     222           0 : bool Key::canCertify() const
     223             : {
     224           0 :     return key && key->can_certify;
     225             : }
     226             : 
     227           0 : bool Key::canAuthenticate() const
     228             : {
     229           0 :     return key && key->can_authenticate;
     230             : }
     231             : 
     232           0 : bool Key::isQualified() const
     233             : {
     234           0 :     return key && key->is_qualified;
     235             : }
     236             : 
     237           0 : bool Key::isDeVs() const
     238             : {
     239           0 :     if (!key) {
     240           0 :         return false;
     241             :     }
     242           0 :     if (!key->subkeys || !key->subkeys->is_de_vs) {
     243           0 :         return false;
     244             :     }
     245           0 :     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
     246           0 :         if (!subkey->is_de_vs) {
     247           0 :             return false;
     248             :         }
     249             :     }
     250           0 :     return true;
     251             : }
     252             : 
     253           0 : const char *Key::issuerSerial() const
     254             : {
     255           0 :     return key ? key->issuer_serial : 0 ;
     256             : }
     257           0 : const char *Key::issuerName() const
     258             : {
     259           0 :     return key ? key->issuer_name : 0 ;
     260             : }
     261           0 : const char *Key::chainID() const
     262             : {
     263           0 :     return key ? key->chain_id : 0 ;
     264             : }
     265             : 
     266           1 : const char *Key::keyID() const
     267             : {
     268           1 :     return key && key->subkeys ? key->subkeys->keyid : 0 ;
     269             : }
     270             : 
     271           0 : const char *Key::shortKeyID() const
     272             : {
     273           0 :     if (!key || !key->subkeys || !key->subkeys->keyid) {
     274           0 :         return 0;
     275             :     }
     276           0 :     const int len = strlen(key->subkeys->keyid);
     277           0 :     if (len > 8) {
     278           0 :         return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
     279             :     } else {
     280           0 :         return key->subkeys->keyid;
     281             :     }
     282             : }
     283             : 
     284          43 : const char *Key::primaryFingerprint() const
     285             : {
     286          43 :     if (!key) {
     287           0 :         return nullptr;
     288             :     }
     289          43 :     if (key->fpr) {
     290             :         /* Return what gpgme thinks is the primary fingerprint */
     291          43 :         return key->fpr;
     292             :     }
     293           0 :     if (key->subkeys) {
     294             :         /* Return the first subkeys fingerprint */
     295           0 :         return key->subkeys->fpr;
     296             :     }
     297           0 :     return nullptr;
     298             : }
     299             : 
     300           0 : unsigned int Key::keyListMode() const
     301             : {
     302           0 :     return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ;
     303             : }
     304             : 
     305           0 : const Key &Key::mergeWith(const Key &other)
     306             : {
     307             :     // ### incomplete. Just merges has* and can*, nothing else atm
     308             :     // ### detach also missing
     309             : 
     310           0 :     if (!this->primaryFingerprint() ||
     311           0 :             !other.primaryFingerprint() ||
     312           0 :             strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
     313           0 :         return *this; // only merge the Key object which describe the same key
     314             :     }
     315             : 
     316           0 :     const gpgme_key_t me = impl();
     317           0 :     const gpgme_key_t him = other.impl();
     318             : 
     319           0 :     if (!me || !him) {
     320           0 :         return *this;
     321             :     }
     322             : 
     323           0 :     me->revoked          |= him->revoked;
     324           0 :     me->expired          |= him->expired;
     325           0 :     me->disabled         |= him->disabled;
     326           0 :     me->invalid          |= him->invalid;
     327           0 :     me->can_encrypt      |= him->can_encrypt;
     328           0 :     me->can_sign         |= him->can_sign;
     329           0 :     me->can_certify      |= him->can_certify;
     330           0 :     me->secret           |= him->secret;
     331           0 :     me->can_authenticate |= him->can_authenticate;
     332           0 :     me->is_qualified     |= him->is_qualified;
     333           0 :     me->keylist_mode     |= him->keylist_mode;
     334             : 
     335             :     // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
     336           0 :     for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
     337           0 :         for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
     338           0 :             if (strcmp(mysk->fpr, hissk->fpr) == 0) {
     339           0 :                 mysk->is_cardkey |= hissk->is_cardkey;
     340           0 :                 break;
     341             :             }
     342             :         }
     343             :     }
     344             : 
     345           0 :     return *this;
     346             : }
     347             : 
     348           7 : void Key::update()
     349             : {
     350           7 :     if (isNull() || !primaryFingerprint()) {
     351           0 :         return;
     352             :     }
     353           7 :     auto ctx = Context::createForProtocol(protocol());
     354           7 :     if (!ctx) {
     355           0 :         return;
     356             :     }
     357             :     ctx->setKeyListMode(KeyListMode::Local |
     358             :                         KeyListMode::Signatures |
     359             :                         KeyListMode::SignatureNotations |
     360             :                         KeyListMode::Validate |
     361           7 :                         KeyListMode::WithTofu);
     362          14 :     Error err;
     363          14 :     auto newKey = ctx->key(primaryFingerprint(), err, true);
     364             :     // Not secret so we get the information from the pubring.
     365           7 :     if (newKey.isNull())
     366             :       {
     367           0 :         newKey = ctx->key(primaryFingerprint(), err, false);
     368             :       }
     369           7 :     delete ctx;
     370           7 :     if (err) {
     371           0 :         return;
     372             :     }
     373           7 :     swap(newKey);
     374           7 :     return;
     375             : }
     376             : 
     377             : // static
     378           0 : Key Key::locate(const char *mbox)
     379             : {
     380           0 :     if (!mbox) {
     381           0 :         return Key();
     382             :     }
     383             : 
     384           0 :     auto ctx = Context::createForProtocol(OpenPGP);
     385           0 :     if (!ctx) {
     386           0 :         return Key();
     387             :     }
     388             : 
     389           0 :     ctx->setKeyListMode (Extern | Local);
     390             : 
     391           0 :     Error e = ctx->startKeyListing (mbox);
     392           0 :     auto ret = ctx->nextKey (e);
     393           0 :     delete ctx;
     394             : 
     395           0 :     return ret;
     396             : }
     397             : 
     398             : //
     399             : //
     400             : // class Subkey
     401             : //
     402             : //
     403             : 
     404           0 : gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
     405             : {
     406           0 :     if (key) {
     407           0 :         for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
     408           0 :             if (idx == 0) {
     409           0 :                 return s;
     410             :             }
     411             :         }
     412             :     }
     413           0 :     return 0;
     414             : }
     415             : 
     416           8 : gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
     417             : {
     418           8 :     if (key) {
     419          12 :         for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
     420          12 :             if (s == subkey) {
     421           8 :                 return subkey;
     422             :             }
     423             :         }
     424             :     }
     425           0 :     return 0;
     426             : }
     427             : 
     428           0 : Subkey::Subkey() : key(), subkey(0) {}
     429             : 
     430           0 : Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
     431           0 :     : key(k), subkey(find_subkey(k, idx))
     432             : {
     433             : 
     434           0 : }
     435             : 
     436           8 : Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
     437           8 :     : key(k), subkey(verify_subkey(k, sk))
     438             : {
     439             : 
     440           8 : }
     441             : 
     442           0 : Key Subkey::parent() const
     443             : {
     444           0 :     return Key(key);
     445             : }
     446             : 
     447           0 : const char *Subkey::keyID() const
     448             : {
     449           0 :     return subkey ? subkey->keyid : 0 ;
     450             : }
     451             : 
     452           2 : const char *Subkey::fingerprint() const
     453             : {
     454           2 :     return subkey ? subkey->fpr : 0 ;
     455             : }
     456             : 
     457           2 : Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
     458             : {
     459           2 :     return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
     460             : }
     461             : 
     462           0 : const char *Subkey::publicKeyAlgorithmAsString() const
     463             : {
     464           0 :     return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
     465             : }
     466             : 
     467             : /* static */
     468          11 : const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
     469             : {
     470          11 :     if (algo == AlgoUnknown) {
     471           1 :         return NULL;
     472             :     }
     473          10 :     return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
     474             : }
     475             : 
     476           0 : std::string Subkey::algoName() const
     477             : {
     478             :     char *gpgmeStr;
     479           0 :     if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
     480           0 :         std::string ret = std::string(gpgmeStr);
     481           0 :         gpgme_free(gpgmeStr);
     482           0 :         return ret;
     483             :     }
     484           0 :     return std::string();
     485             : }
     486             : 
     487           0 : bool Subkey::canEncrypt() const
     488             : {
     489           0 :     return subkey && subkey->can_encrypt;
     490             : }
     491             : 
     492           0 : bool Subkey::canSign() const
     493             : {
     494           0 :     return subkey && subkey->can_sign;
     495             : }
     496             : 
     497           0 : bool Subkey::canCertify() const
     498             : {
     499           0 :     return subkey && subkey->can_certify;
     500             : }
     501             : 
     502           0 : bool Subkey::canAuthenticate() const
     503             : {
     504           0 :     return subkey && subkey->can_authenticate;
     505             : }
     506             : 
     507           0 : bool Subkey::isQualified() const
     508             : {
     509           0 :     return subkey && subkey->is_qualified;
     510             : }
     511             : 
     512           0 : bool Subkey::isDeVs() const
     513             : {
     514           0 :     return subkey && subkey->is_de_vs;
     515             : }
     516             : 
     517           0 : bool Subkey::isCardKey() const
     518             : {
     519           0 :     return subkey && subkey->is_cardkey;
     520             : }
     521             : 
     522           0 : const char *Subkey::cardSerialNumber() const
     523             : {
     524           0 :     return subkey ? subkey->card_number : nullptr;
     525             : }
     526             : 
     527           0 : const char *Subkey::keyGrip() const
     528             : {
     529           0 :     return subkey ? subkey->keygrip : nullptr;
     530             : }
     531             : 
     532           0 : bool Subkey::isSecret() const
     533             : {
     534           0 :     return subkey && subkey->secret;
     535             : }
     536             : 
     537           0 : unsigned int Subkey::length() const
     538             : {
     539           0 :     return subkey ? subkey->length : 0 ;
     540             : }
     541             : 
     542           0 : time_t Subkey::creationTime() const
     543             : {
     544           0 :     return static_cast<time_t>(subkey ? subkey->timestamp : 0);
     545             : }
     546             : 
     547           0 : time_t Subkey::expirationTime() const
     548             : {
     549           0 :     return static_cast<time_t>(subkey ? subkey->expires : 0);
     550             : }
     551             : 
     552           0 : bool Subkey::neverExpires() const
     553             : {
     554           0 :     return expirationTime() == time_t(0);
     555             : }
     556             : 
     557           0 : bool Subkey::isRevoked() const
     558             : {
     559           0 :     return subkey && subkey->revoked;
     560             : }
     561             : 
     562           0 : bool Subkey::isInvalid() const
     563             : {
     564           0 :     return subkey && subkey->invalid;
     565             : }
     566             : 
     567           0 : bool Subkey::isExpired() const
     568             : {
     569           0 :     return subkey && subkey->expired;
     570             : }
     571             : 
     572           0 : bool Subkey::isDisabled() const
     573             : {
     574           0 :     return subkey && subkey->disabled;
     575             : }
     576             : 
     577             : //
     578             : //
     579             : // class UserID
     580             : //
     581             : //
     582             : 
     583          17 : gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
     584             : {
     585          17 :     if (key) {
     586          17 :         for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
     587          17 :             if (idx == 0) {
     588          17 :                 return u;
     589             :             }
     590             :         }
     591             :     }
     592           0 :     return 0;
     593             : }
     594             : 
     595          17 : gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
     596             : {
     597          17 :     if (key) {
     598          32 :         for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
     599          32 :             if (u == uid) {
     600          17 :                 return uid;
     601             :             }
     602             :         }
     603             :     }
     604           0 :     return 0;
     605             : }
     606             : 
     607           0 : UserID::UserID() : key(), uid(0) {}
     608             : 
     609          17 : UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
     610          17 :     : key(k), uid(verify_uid(k, u))
     611             : {
     612             : 
     613          17 : }
     614             : 
     615          17 : UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
     616          17 :     : key(k), uid(find_uid(k, idx))
     617             : {
     618             : 
     619          17 : }
     620             : 
     621           0 : Key UserID::parent() const
     622             : {
     623           0 :     return Key(key);
     624             : }
     625             : 
     626           0 : UserID::Signature UserID::signature(unsigned int index) const
     627             : {
     628           0 :     return Signature(key, uid, index);
     629             : }
     630             : 
     631           0 : unsigned int UserID::numSignatures() const
     632             : {
     633           0 :     if (!uid) {
     634           0 :         return 0;
     635             :     }
     636           0 :     unsigned int count = 0;
     637           0 :     for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
     638           0 :         ++count;
     639             :     }
     640           0 :     return count;
     641             : }
     642             : 
     643           0 : std::vector<UserID::Signature> UserID::signatures() const
     644             : {
     645           0 :     if (!uid) {
     646           0 :         return std::vector<Signature>();
     647             :     }
     648             : 
     649           0 :     std::vector<Signature> v;
     650           0 :     v.reserve(numSignatures());
     651           0 :     for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
     652           0 :         v.push_back(Signature(key, uid, sig));
     653             :     }
     654           0 :     return v;
     655             : }
     656             : 
     657           5 : const char *UserID::id() const
     658             : {
     659           5 :     return uid ? uid->uid : 0 ;
     660             : }
     661             : 
     662           0 : const char *UserID::name() const
     663             : {
     664           0 :     return uid ? uid->name : 0 ;
     665             : }
     666             : 
     667           3 : const char *UserID::email() const
     668             : {
     669           3 :     return uid ? uid->email : 0 ;
     670             : }
     671             : 
     672           0 : const char *UserID::comment() const
     673             : {
     674           0 :     return uid ? uid->comment : 0 ;
     675             : }
     676             : 
     677           0 : UserID::Validity UserID::validity() const
     678             : {
     679           0 :     if (!uid) {
     680           0 :         return Unknown;
     681             :     }
     682           0 :     switch (uid->validity) {
     683             :     default:
     684           0 :     case GPGME_VALIDITY_UNKNOWN:   return Unknown;
     685           0 :     case GPGME_VALIDITY_UNDEFINED: return Undefined;
     686           0 :     case GPGME_VALIDITY_NEVER:     return Never;
     687           0 :     case GPGME_VALIDITY_MARGINAL:  return Marginal;
     688           0 :     case GPGME_VALIDITY_FULL:      return Full;
     689           0 :     case GPGME_VALIDITY_ULTIMATE:  return Ultimate;
     690             :     }
     691             : }
     692             : 
     693           0 : char UserID::validityAsString() const
     694             : {
     695           0 :     if (!uid) {
     696           0 :         return '?';
     697             :     }
     698           0 :     switch (uid->validity) {
     699             :     default:
     700           0 :     case GPGME_VALIDITY_UNKNOWN:   return '?';
     701           0 :     case GPGME_VALIDITY_UNDEFINED: return 'q';
     702           0 :     case GPGME_VALIDITY_NEVER:     return 'n';
     703           0 :     case GPGME_VALIDITY_MARGINAL:  return 'm';
     704           0 :     case GPGME_VALIDITY_FULL:      return 'f';
     705           0 :     case GPGME_VALIDITY_ULTIMATE:  return 'u';
     706             :     }
     707             : }
     708             : 
     709           1 : bool UserID::isRevoked() const
     710             : {
     711           1 :     return uid && uid->revoked;
     712             : }
     713             : 
     714           0 : bool UserID::isInvalid() const
     715             : {
     716           0 :     return uid && uid->invalid;
     717             : }
     718             : 
     719          23 : TofuInfo UserID::tofuInfo() const
     720             : {
     721          23 :     if (!uid) {
     722           0 :         return TofuInfo();
     723             :     }
     724          23 :     return TofuInfo(uid->tofu);
     725             : }
     726             : 
     727             : //
     728             : //
     729             : // class Signature
     730             : //
     731             : //
     732             : 
     733           0 : gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
     734             : {
     735           0 :     if (uid) {
     736           0 :         for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
     737           0 :             if (idx == 0) {
     738           0 :                 return s;
     739             :             }
     740             :         }
     741             :     }
     742           0 :     return 0;
     743             : }
     744             : 
     745           0 : gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
     746             : {
     747           0 :     if (uid) {
     748           0 :         for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
     749           0 :             if (s == sig) {
     750           0 :                 return sig;
     751             :             }
     752             :         }
     753             :     }
     754           0 :     return 0;
     755             : }
     756             : 
     757           0 : UserID::Signature::Signature() : key(), uid(0), sig(0) {}
     758             : 
     759           0 : UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
     760           0 :     : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
     761             : {
     762             : 
     763           0 : }
     764             : 
     765           0 : UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
     766           0 :     : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
     767             : {
     768             : 
     769           0 : }
     770             : 
     771           0 : UserID UserID::Signature::parent() const
     772             : {
     773           0 :     return UserID(key, uid);
     774             : }
     775             : 
     776           0 : const char *UserID::Signature::signerKeyID() const
     777             : {
     778           0 :     return sig ? sig->keyid : 0 ;
     779             : }
     780             : 
     781           0 : const char *UserID::Signature::algorithmAsString() const
     782             : {
     783           0 :     return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
     784             : }
     785             : 
     786           0 : unsigned int UserID::Signature::algorithm() const
     787             : {
     788           0 :     return sig ? sig->pubkey_algo : 0 ;
     789             : }
     790             : 
     791           0 : time_t UserID::Signature::creationTime() const
     792             : {
     793           0 :     return static_cast<time_t>(sig ? sig->timestamp : 0);
     794             : }
     795             : 
     796           0 : time_t UserID::Signature::expirationTime() const
     797             : {
     798           0 :     return static_cast<time_t>(sig ? sig->expires : 0);
     799             : }
     800             : 
     801           0 : bool UserID::Signature::neverExpires() const
     802             : {
     803           0 :     return expirationTime() == time_t(0);
     804             : }
     805             : 
     806           0 : bool UserID::Signature::isRevokation() const
     807             : {
     808           0 :     return sig && sig->revoked;
     809             : }
     810             : 
     811           0 : bool UserID::Signature::isInvalid() const
     812             : {
     813           0 :     return sig && sig->invalid;
     814             : }
     815             : 
     816           0 : bool UserID::Signature::isExpired() const
     817             : {
     818           0 :     return sig && sig->expired;
     819             : }
     820             : 
     821           0 : bool UserID::Signature::isExportable() const
     822             : {
     823           0 :     return sig && sig->exportable;
     824             : }
     825             : 
     826           0 : const char *UserID::Signature::signerUserID() const
     827             : {
     828           0 :     return sig ? sig->uid : 0 ;
     829             : }
     830             : 
     831           0 : const char *UserID::Signature::signerName() const
     832             : {
     833           0 :     return sig ? sig->name : 0 ;
     834             : }
     835             : 
     836           0 : const char *UserID::Signature::signerEmail() const
     837             : {
     838           0 :     return sig ? sig->email : 0 ;
     839             : }
     840             : 
     841           0 : const char *UserID::Signature::signerComment() const
     842             : {
     843           0 :     return sig ? sig->comment : 0 ;
     844             : }
     845             : 
     846           0 : unsigned int UserID::Signature::certClass() const
     847             : {
     848           0 :     return sig ? sig->sig_class : 0 ;
     849             : }
     850             : 
     851           0 : UserID::Signature::Status UserID::Signature::status() const
     852             : {
     853           0 :     if (!sig) {
     854           0 :         return GeneralError;
     855             :     }
     856             : 
     857           0 :     switch (gpgme_err_code(sig->status)) {
     858           0 :     case GPG_ERR_NO_ERROR:      return NoError;
     859           0 :     case GPG_ERR_SIG_EXPIRED:   return SigExpired;
     860           0 :     case GPG_ERR_KEY_EXPIRED:   return KeyExpired;
     861           0 :     case GPG_ERR_BAD_SIGNATURE: return BadSignature;
     862           0 :     case GPG_ERR_NO_PUBKEY:     return NoPublicKey;
     863             :     default:
     864           0 :     case GPG_ERR_GENERAL:       return GeneralError;
     865             :     }
     866             : }
     867             : 
     868           0 : std::string UserID::Signature::statusAsString() const
     869             : {
     870           0 :     if (!sig) {
     871           0 :         return std::string();
     872             :     }
     873             :     char buf[ 1024 ];
     874           0 :     gpgme_strerror_r(sig->status, buf, sizeof buf);
     875           0 :     buf[ sizeof buf - 1 ] = '\0';
     876           0 :     return std::string(buf);
     877             : }
     878             : 
     879           0 : GpgME::Notation UserID::Signature::notation(unsigned int idx) const
     880             : {
     881           0 :     if (!sig) {
     882           0 :         return GpgME::Notation();
     883             :     }
     884           0 :     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
     885           0 :         if (nota->name) {
     886           0 :             if (idx-- == 0) {
     887           0 :                 return GpgME::Notation(nota);
     888             :             }
     889             :         }
     890             :     }
     891           0 :     return GpgME::Notation();
     892             : }
     893             : 
     894           0 : unsigned int UserID::Signature::numNotations() const
     895             : {
     896           0 :     if (!sig) {
     897           0 :         return 0;
     898             :     }
     899           0 :     unsigned int count = 0;
     900           0 :     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
     901           0 :         if (nota->name) {
     902           0 :             ++count; // others are policy URLs...
     903             :         }
     904             :     }
     905           0 :     return count;
     906             : }
     907             : 
     908           0 : std::vector<Notation> UserID::Signature::notations() const
     909             : {
     910           0 :     if (!sig) {
     911           0 :         return std::vector<GpgME::Notation>();
     912             :     }
     913           0 :     std::vector<GpgME::Notation> v;
     914           0 :     v.reserve(numNotations());
     915           0 :     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
     916           0 :         if (nota->name) {
     917           0 :             v.push_back(GpgME::Notation(nota));
     918             :         }
     919             :     }
     920           0 :     return v;
     921             : }
     922             : 
     923           0 : const char *UserID::Signature::policyURL() const
     924             : {
     925           0 :     if (!sig) {
     926           0 :         return 0;
     927             :     }
     928           0 :     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
     929           0 :         if (!nota->name) {
     930           0 :             return nota->value;
     931             :         }
     932             :     }
     933           0 :     return 0;
     934             : }
     935             : 
     936           0 : std::string UserID::addrSpecFromString(const char *userid)
     937             : {
     938           0 :     if (!userid) {
     939           0 :         return std::string();
     940             :     }
     941           0 :     char *normalized = gpgme_addrspec_from_uid (userid);
     942           0 :     if (normalized) {
     943           0 :         std::string ret(normalized);
     944           0 :         gpgme_free(normalized);
     945           0 :         return ret;
     946             :     }
     947           0 :     return std::string();
     948             : }
     949             : 
     950           0 : std::string UserID::addrSpec() const
     951             : {
     952           0 :     if (!uid || !uid->address) {
     953           0 :         return std::string();
     954             :     }
     955             : 
     956           0 :     return uid->address;
     957             : }
     958             : 
     959           0 : Error UserID::revoke()
     960             : {
     961           0 :     if (isNull()) {
     962           0 :         return Error::fromCode(GPG_ERR_GENERAL);
     963             :     }
     964           0 :     auto ctx = Context::createForProtocol(parent().protocol());
     965           0 :     if (!ctx) {
     966           0 :         return Error::fromCode(GPG_ERR_INV_ENGINE);
     967             :     }
     968           0 :     Error ret = ctx->revUid(key, id());
     969           0 :     delete ctx;
     970           0 :     return ret;
     971             : }
     972             : 
     973           0 : static Key::Origin gpgme_origin_to_pp_origin (const unsigned int origin)
     974             : {
     975           0 :     switch (origin) {
     976             :         case GPGME_KEYORG_KS:
     977           0 :             return Key::OriginKS;
     978             :         case GPGME_KEYORG_DANE:
     979           0 :             return Key::OriginDane;
     980             :         case GPGME_KEYORG_WKD:
     981           0 :             return Key::OriginWKD;
     982             :         case GPGME_KEYORG_URL:
     983           0 :             return Key::OriginURL;
     984             :         case GPGME_KEYORG_FILE:
     985           0 :             return Key::OriginFile;
     986             :         case GPGME_KEYORG_SELF:
     987           0 :             return Key::OriginSelf;
     988             :         case GPGME_KEYORG_OTHER:
     989           0 :             return Key::OriginOther;
     990             :         case GPGME_KEYORG_UNKNOWN:
     991             :         default:
     992           0 :             return Key::OriginUnknown;
     993             :     }
     994             : }
     995             : 
     996           0 : Key::Origin UserID::origin() const
     997             : {
     998           0 :     if (isNull()) {
     999           0 :         return Key::OriginUnknown;
    1000             :     }
    1001           0 :     return gpgme_origin_to_pp_origin(uid->origin);
    1002             : }
    1003             : 
    1004           0 : time_t UserID::lastUpdate() const
    1005             : {
    1006           0 :     return static_cast<time_t>(uid ? uid->last_update : 0);
    1007             : }
    1008             : 
    1009           0 : Error Key::addUid(const char *uid)
    1010             : {
    1011           0 :     if (isNull()) {
    1012           0 :         return Error::fromCode(GPG_ERR_GENERAL);
    1013             :     }
    1014           0 :     auto ctx = Context::createForProtocol(protocol());
    1015           0 :     if (!ctx) {
    1016           0 :         return Error::fromCode(GPG_ERR_INV_ENGINE);
    1017             :     }
    1018           0 :     Error ret = ctx->addUid(key, uid);
    1019           0 :     delete ctx;
    1020           0 :     return ret;
    1021             : }
    1022             : 
    1023           0 : Key::Origin Key::origin() const
    1024             : {
    1025           0 :     if (isNull()) {
    1026           0 :         return OriginUnknown;
    1027             :     }
    1028           0 :     return gpgme_origin_to_pp_origin(key->origin);
    1029             : }
    1030             : 
    1031           0 : time_t Key::lastUpdate() const
    1032             : {
    1033           0 :     return static_cast<time_t>(key ? key->last_update : 0);
    1034             : }
    1035             : 
    1036           0 : bool Key::isBad() const
    1037             : {
    1038           0 :     return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
    1039             : }
    1040             : 
    1041           0 : bool Subkey::isBad() const
    1042             : {
    1043           0 :     return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
    1044             : }
    1045             : 
    1046           0 : bool UserID::isBad() const
    1047             : {
    1048           0 :     return isNull() || isRevoked() || isInvalid();
    1049             : }
    1050             : 
    1051           0 : bool UserID::Signature::isBad() const
    1052             : {
    1053           0 :     return isNull() || isExpired() || isInvalid();
    1054             : }
    1055             : 
    1056           0 : std::ostream &operator<<(std::ostream &os, const UserID &uid)
    1057             : {
    1058           0 :     os << "GpgME::UserID(";
    1059           0 :     if (!uid.isNull()) {
    1060             :         os << "\n name:      " << protect(uid.name())
    1061             :            << "\n email:     " << protect(uid.email())
    1062           0 :            << "\n mbox:      " << uid.addrSpec()
    1063             :            << "\n comment:   " << protect(uid.comment())
    1064           0 :            << "\n validity:  " << uid.validityAsString()
    1065           0 :            << "\n revoked:   " << uid.isRevoked()
    1066           0 :            << "\n invalid:   " << uid.isInvalid()
    1067           0 :            << "\n numsigs:   " << uid.numSignatures()
    1068           0 :            << "\n origin:    " << uid.origin()
    1069           0 :            << "\n updated:   " << uid.lastUpdate()
    1070           0 :            << "\n tofuinfo:\n" << uid.tofuInfo();
    1071             :     }
    1072           0 :     return os << ')';
    1073             : }
    1074             : 
    1075           0 : std::ostream &operator<<(std::ostream &os, const Key &key)
    1076             : {
    1077           0 :     os << "GpgME::Key(";
    1078           0 :     if (!key.isNull()) {
    1079             :         os << "\n protocol:   " << protect(key.protocolAsString())
    1080           0 :            << "\n ownertrust: " << key.ownerTrustAsString()
    1081             :            << "\n issuer:     " << protect(key.issuerName())
    1082             :            << "\n fingerprint:" << protect(key.primaryFingerprint())
    1083           0 :            << "\n listmode:   " << key.keyListMode()
    1084           0 :            << "\n canSign:    " << key.canReallySign()
    1085           0 :            << "\n canEncrypt: " << key.canEncrypt()
    1086           0 :            << "\n canCertify: " << key.canCertify()
    1087           0 :            << "\n canAuth:    " << key.canAuthenticate()
    1088           0 :            << "\n origin:     " << key.origin()
    1089           0 :            << "\n updated:    " << key.lastUpdate()
    1090           0 :            << "\n uids:\n";
    1091           0 :         const std::vector<UserID> uids = key.userIDs();
    1092             :         std::copy(uids.begin(), uids.end(),
    1093           0 :                   std::ostream_iterator<UserID>(os, "\n"));
    1094             :     }
    1095           0 :     return os << ')';
    1096             : }
    1097             : 
    1098          24 : } // namespace GpgME

Generated by: LCOV version 1.13