"Fossies" - the Fresh Open Source Software Archive 
Member "gpgme-1.15.1/lang/cpp/src/key.cpp" (8 Jan 2021, 29660 Bytes) of package /linux/privat/gpgme-1.15.1.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "key.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.15.0_vs_1.15.1.
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 #include "engineinfo.h"
33
34 #include <gpgme.h>
35
36 #include <string.h>
37 #include <strings.h>
38 #include <cassert>
39 #include <istream>
40 #include <iterator>
41
42 const GpgME::Key::Null GpgME::Key::null;
43
44 namespace GpgME
45 {
46
47 Key::Key() : key() {}
48
49 Key::Key(const Null &) : key() {}
50
51 Key::Key(const shared_gpgme_key_t &k) : key(k) {}
52
53 Key::Key(gpgme_key_t k, bool ref)
54 : key(k
55 ? shared_gpgme_key_t(k, &gpgme_key_unref)
56 : shared_gpgme_key_t())
57 {
58 if (ref && impl()) {
59 gpgme_key_ref(impl());
60 }
61 }
62
63 UserID Key::userID(unsigned int index) const
64 {
65 return UserID(key, index);
66 }
67
68 Subkey Key::subkey(unsigned int index) const
69 {
70 return Subkey(key, index);
71 }
72
73 unsigned int Key::numUserIDs() const
74 {
75 if (!key) {
76 return 0;
77 }
78 unsigned int count = 0;
79 for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
80 ++count;
81 }
82 return count;
83 }
84
85 unsigned int Key::numSubkeys() const
86 {
87 if (!key) {
88 return 0;
89 }
90 unsigned int count = 0;
91 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
92 ++count;
93 }
94 return count;
95 }
96
97 std::vector<UserID> Key::userIDs() const
98 {
99 if (!key) {
100 return std::vector<UserID>();
101 }
102
103 std::vector<UserID> v;
104 v.reserve(numUserIDs());
105 for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
106 v.push_back(UserID(key, uid));
107 }
108 return v;
109 }
110
111 std::vector<Subkey> Key::subkeys() const
112 {
113 if (!key) {
114 return std::vector<Subkey>();
115 }
116
117 std::vector<Subkey> v;
118 v.reserve(numSubkeys());
119 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
120 v.push_back(Subkey(key, subkey));
121 }
122 return v;
123 }
124
125 Key::OwnerTrust Key::ownerTrust() const
126 {
127 if (!key) {
128 return Unknown;
129 }
130 switch (key->owner_trust) {
131 default:
132 case GPGME_VALIDITY_UNKNOWN: return Unknown;
133 case GPGME_VALIDITY_UNDEFINED: return Undefined;
134 case GPGME_VALIDITY_NEVER: return Never;
135 case GPGME_VALIDITY_MARGINAL: return Marginal;
136 case GPGME_VALIDITY_FULL: return Full;
137 case GPGME_VALIDITY_ULTIMATE: return Ultimate;
138 }
139 }
140 char Key::ownerTrustAsString() const
141 {
142 if (!key) {
143 return '?';
144 }
145 switch (key->owner_trust) {
146 default:
147 case GPGME_VALIDITY_UNKNOWN: return '?';
148 case GPGME_VALIDITY_UNDEFINED: return 'q';
149 case GPGME_VALIDITY_NEVER: return 'n';
150 case GPGME_VALIDITY_MARGINAL: return 'm';
151 case GPGME_VALIDITY_FULL: return 'f';
152 case GPGME_VALIDITY_ULTIMATE: return 'u';
153 }
154 }
155
156 Protocol Key::protocol() const
157 {
158 if (!key) {
159 return UnknownProtocol;
160 }
161 switch (key->protocol) {
162 case GPGME_PROTOCOL_CMS: return CMS;
163 case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
164 default: return UnknownProtocol;
165 }
166 }
167
168 const char *Key::protocolAsString() const
169 {
170 return key ? gpgme_get_protocol_name(key->protocol) : nullptr ;
171 }
172
173 bool Key::isRevoked() const
174 {
175 return key && key->revoked;
176 }
177
178 bool Key::isExpired() const
179 {
180 return key && key->expired;
181 }
182
183 bool Key::isDisabled() const
184 {
185 return key && key->disabled;
186 }
187
188 bool Key::isInvalid() const
189 {
190 return key && key->invalid;
191 }
192
193 bool Key::hasSecret() const
194 {
195 return key && key->secret;
196 }
197
198 bool Key::isRoot() const
199 {
200 return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
201 strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
202 }
203
204 bool Key::canEncrypt() const
205 {
206 return key && key->can_encrypt;
207 }
208
209 bool Key::canSign() const
210 {
211 #ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
212 if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
213 return true;
214 }
215 #endif
216 return canReallySign();
217 }
218
219 bool Key::canReallySign() const
220 {
221 return key && key->can_sign;
222 }
223
224 bool Key::canCertify() const
225 {
226 return key && key->can_certify;
227 }
228
229 bool Key::canAuthenticate() const
230 {
231 return key && key->can_authenticate;
232 }
233
234 bool Key::isQualified() const
235 {
236 return key && key->is_qualified;
237 }
238
239 bool Key::isDeVs() const
240 {
241 if (!key) {
242 return false;
243 }
244 if (!key->subkeys || !key->subkeys->is_de_vs) {
245 return false;
246 }
247 for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
248 if (!subkey->is_de_vs) {
249 return false;
250 }
251 }
252 return true;
253 }
254
255 const char *Key::issuerSerial() const
256 {
257 return key ? key->issuer_serial : nullptr ;
258 }
259 const char *Key::issuerName() const
260 {
261 return key ? key->issuer_name : nullptr ;
262 }
263 const char *Key::chainID() const
264 {
265 return key ? key->chain_id : nullptr ;
266 }
267
268 const char *Key::keyID() const
269 {
270 return key && key->subkeys ? key->subkeys->keyid : nullptr ;
271 }
272
273 const char *Key::shortKeyID() const
274 {
275 if (!key || !key->subkeys || !key->subkeys->keyid) {
276 return nullptr;
277 }
278 const int len = strlen(key->subkeys->keyid);
279 if (len > 8) {
280 return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
281 } else {
282 return key->subkeys->keyid;
283 }
284 }
285
286 const char *Key::primaryFingerprint() const
287 {
288 if (!key) {
289 return nullptr;
290 }
291 if (key->fpr) {
292 /* Return what gpgme thinks is the primary fingerprint */
293 return key->fpr;
294 }
295 if (key->subkeys) {
296 /* Return the first subkeys fingerprint */
297 return key->subkeys->fpr;
298 }
299 return nullptr;
300 }
301
302 unsigned int Key::keyListMode() const
303 {
304 return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0;
305 }
306
307 const Key &Key::mergeWith(const Key &other)
308 {
309 // ### incomplete. Just merges has* and can*, nothing else atm
310 // ### detach also missing
311
312 if (!this->primaryFingerprint() ||
313 !other.primaryFingerprint() ||
314 strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
315 return *this; // only merge the Key object which describe the same key
316 }
317
318 const gpgme_key_t me = impl();
319 const gpgme_key_t him = other.impl();
320
321 if (!me || !him) {
322 return *this;
323 }
324
325 me->revoked |= him->revoked;
326 me->expired |= him->expired;
327 me->disabled |= him->disabled;
328 me->invalid |= him->invalid;
329 me->can_encrypt |= him->can_encrypt;
330 me->can_sign |= him->can_sign;
331 me->can_certify |= him->can_certify;
332 me->secret |= him->secret;
333 me->can_authenticate |= him->can_authenticate;
334 me->is_qualified |= him->is_qualified;
335 me->keylist_mode |= him->keylist_mode;
336
337 // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
338 for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
339 for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
340 if (strcmp(mysk->fpr, hissk->fpr) == 0) {
341 mysk->is_cardkey |= hissk->is_cardkey;
342 mysk->secret |= hissk->secret;
343 if (hissk->keygrip && !mysk->keygrip) {
344 mysk->keygrip = strdup(hissk->keygrip);
345 }
346 break;
347 }
348 }
349 }
350
351 return *this;
352 }
353
354 void Key::update()
355 {
356 if (isNull() || !primaryFingerprint()) {
357 return;
358 }
359 auto ctx = Context::createForProtocol(protocol());
360 if (!ctx) {
361 return;
362 }
363 ctx->setKeyListMode(KeyListMode::Local |
364 KeyListMode::Signatures |
365 KeyListMode::SignatureNotations |
366 KeyListMode::Validate |
367 KeyListMode::WithTofu |
368 KeyListMode::WithKeygrip |
369 KeyListMode::WithSecret);
370 Error err;
371 Key newKey;
372 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.0") {
373 newKey = ctx->key(primaryFingerprint(), err, true);
374 // Not secret so we get the information from the pubring.
375 if (newKey.isNull()) {
376 newKey = ctx->key(primaryFingerprint(), err, false);
377 }
378 } else {
379 newKey = ctx->key(primaryFingerprint(), err, false);
380 }
381 delete ctx;
382 if (err) {
383 return;
384 }
385 swap(newKey);
386 }
387
388 // static
389 Key Key::locate(const char *mbox)
390 {
391 if (!mbox) {
392 return Key();
393 }
394
395 auto ctx = Context::createForProtocol(OpenPGP);
396 if (!ctx) {
397 return Key();
398 }
399
400 ctx->setKeyListMode (Extern | Local);
401
402 Error e = ctx->startKeyListing (mbox);
403 auto ret = ctx->nextKey (e);
404 delete ctx;
405
406 return ret;
407 }
408
409 //
410 //
411 // class Subkey
412 //
413 //
414
415 static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
416 {
417 if (key) {
418 for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
419 if (idx == 0) {
420 return s;
421 }
422 }
423 }
424 return nullptr;
425 }
426
427 static gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
428 {
429 if (key) {
430 for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
431 if (s == subkey) {
432 return subkey;
433 }
434 }
435 }
436 return nullptr;
437 }
438
439 Subkey::Subkey() : key(), subkey(nullptr) {}
440
441 Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
442 : key(k), subkey(find_subkey(k, idx))
443 {
444
445 }
446
447 Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
448 : key(k), subkey(verify_subkey(k, sk))
449 {
450
451 }
452
453 Key Subkey::parent() const
454 {
455 return Key(key);
456 }
457
458 const char *Subkey::keyID() const
459 {
460 return subkey ? subkey->keyid : nullptr ;
461 }
462
463 const char *Subkey::fingerprint() const
464 {
465 return subkey ? subkey->fpr : nullptr ;
466 }
467
468 Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
469 {
470 return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
471 }
472
473 const char *Subkey::publicKeyAlgorithmAsString() const
474 {
475 return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
476 }
477
478 /* static */
479 const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
480 {
481 if (algo == AlgoUnknown) {
482 return NULL;
483 }
484 return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
485 }
486
487 std::string Subkey::algoName() const
488 {
489 char *gpgmeStr;
490 if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
491 std::string ret = std::string(gpgmeStr);
492 gpgme_free(gpgmeStr);
493 return ret;
494 }
495 return std::string();
496 }
497
498 bool Subkey::canEncrypt() const
499 {
500 return subkey && subkey->can_encrypt;
501 }
502
503 bool Subkey::canSign() const
504 {
505 return subkey && subkey->can_sign;
506 }
507
508 bool Subkey::canCertify() const
509 {
510 return subkey && subkey->can_certify;
511 }
512
513 bool Subkey::canAuthenticate() const
514 {
515 return subkey && subkey->can_authenticate;
516 }
517
518 bool Subkey::isQualified() const
519 {
520 return subkey && subkey->is_qualified;
521 }
522
523 bool Subkey::isDeVs() const
524 {
525 return subkey && subkey->is_de_vs;
526 }
527
528 bool Subkey::isCardKey() const
529 {
530 return subkey && subkey->is_cardkey;
531 }
532
533 const char *Subkey::cardSerialNumber() const
534 {
535 return subkey ? subkey->card_number : nullptr;
536 }
537
538 const char *Subkey::keyGrip() const
539 {
540 return subkey ? subkey->keygrip : nullptr;
541 }
542
543 bool Subkey::isSecret() const
544 {
545 return subkey && subkey->secret;
546 }
547
548 unsigned int Subkey::length() const
549 {
550 return subkey ? subkey->length : 0 ;
551 }
552
553 time_t Subkey::creationTime() const
554 {
555 return static_cast<time_t>(subkey ? subkey->timestamp : 0);
556 }
557
558 time_t Subkey::expirationTime() const
559 {
560 return static_cast<time_t>(subkey ? subkey->expires : 0);
561 }
562
563 bool Subkey::neverExpires() const
564 {
565 return expirationTime() == time_t(0);
566 }
567
568 bool Subkey::isRevoked() const
569 {
570 return subkey && subkey->revoked;
571 }
572
573 bool Subkey::isInvalid() const
574 {
575 return subkey && subkey->invalid;
576 }
577
578 bool Subkey::isExpired() const
579 {
580 return subkey && subkey->expired;
581 }
582
583 bool Subkey::isDisabled() const
584 {
585 return subkey && subkey->disabled;
586 }
587
588 //
589 //
590 // class UserID
591 //
592 //
593
594 static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
595 {
596 if (key) {
597 for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
598 if (idx == 0) {
599 return u;
600 }
601 }
602 }
603 return nullptr;
604 }
605
606 static gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
607 {
608 if (key) {
609 for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
610 if (u == uid) {
611 return uid;
612 }
613 }
614 }
615 return nullptr;
616 }
617
618 UserID::UserID() : key(), uid(nullptr) {}
619
620 UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
621 : key(k), uid(verify_uid(k, u))
622 {
623
624 }
625
626 UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
627 : key(k), uid(find_uid(k, idx))
628 {
629
630 }
631
632 Key UserID::parent() const
633 {
634 return Key(key);
635 }
636
637 UserID::Signature UserID::signature(unsigned int index) const
638 {
639 return Signature(key, uid, index);
640 }
641
642 unsigned int UserID::numSignatures() const
643 {
644 if (!uid) {
645 return 0;
646 }
647 unsigned int count = 0;
648 for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
649 ++count;
650 }
651 return count;
652 }
653
654 std::vector<UserID::Signature> UserID::signatures() const
655 {
656 if (!uid) {
657 return std::vector<Signature>();
658 }
659
660 std::vector<Signature> v;
661 v.reserve(numSignatures());
662 for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
663 v.push_back(Signature(key, uid, sig));
664 }
665 return v;
666 }
667
668 const char *UserID::id() const
669 {
670 return uid ? uid->uid : nullptr ;
671 }
672
673 const char *UserID::name() const
674 {
675 return uid ? uid->name : nullptr ;
676 }
677
678 const char *UserID::email() const
679 {
680 return uid ? uid->email : nullptr ;
681 }
682
683 const char *UserID::comment() const
684 {
685 return uid ? uid->comment : nullptr ;
686 }
687
688 const char *UserID::uidhash() const
689 {
690 return uid ? uid->uidhash : nullptr ;
691 }
692
693 UserID::Validity UserID::validity() const
694 {
695 if (!uid) {
696 return Unknown;
697 }
698 switch (uid->validity) {
699 default:
700 case GPGME_VALIDITY_UNKNOWN: return Unknown;
701 case GPGME_VALIDITY_UNDEFINED: return Undefined;
702 case GPGME_VALIDITY_NEVER: return Never;
703 case GPGME_VALIDITY_MARGINAL: return Marginal;
704 case GPGME_VALIDITY_FULL: return Full;
705 case GPGME_VALIDITY_ULTIMATE: return Ultimate;
706 }
707 }
708
709 char UserID::validityAsString() const
710 {
711 if (!uid) {
712 return '?';
713 }
714 switch (uid->validity) {
715 default:
716 case GPGME_VALIDITY_UNKNOWN: return '?';
717 case GPGME_VALIDITY_UNDEFINED: return 'q';
718 case GPGME_VALIDITY_NEVER: return 'n';
719 case GPGME_VALIDITY_MARGINAL: return 'm';
720 case GPGME_VALIDITY_FULL: return 'f';
721 case GPGME_VALIDITY_ULTIMATE: return 'u';
722 }
723 }
724
725 bool UserID::isRevoked() const
726 {
727 return uid && uid->revoked;
728 }
729
730 bool UserID::isInvalid() const
731 {
732 return uid && uid->invalid;
733 }
734
735 TofuInfo UserID::tofuInfo() const
736 {
737 if (!uid) {
738 return TofuInfo();
739 }
740 return TofuInfo(uid->tofu);
741 }
742
743 static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
744 const char *keyid)
745 {
746 if (!keyid) {
747 return nullptr;
748 }
749 gpgme_key_sig_t ret = NULL;
750 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
751 if (s->keyid && !strcmp(keyid, s->keyid)) {
752 if (!s->expired && !s->revoked && !s->invalid && !s->status) {
753 if (!ret) {
754 ret = s;
755 } else if (ret && ret->timestamp <= s->timestamp) {
756 /* Equals because when the timestamps are the same we prefer
757 the last in the list */
758 ret = s;
759 }
760 }
761 }
762 }
763 return ret;
764 }
765
766 const char *UserID::remark(const Key &remarker, Error &err) const
767 {
768 if (!uid || remarker.isNull()) {
769 err = Error::fromCode(GPG_ERR_GENERAL);
770 return nullptr;
771 }
772
773 if (key->protocol != GPGME_PROTOCOL_OpenPGP) {
774 return nullptr;
775 }
776
777 if (!(key->keylist_mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
778 !(key->keylist_mode & GPGME_KEYLIST_MODE_SIGS)) {
779 err = Error::fromCode(GPG_ERR_NO_DATA);
780 return nullptr;
781 }
782
783 gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
784
785 if (!s) {
786 return nullptr;
787 }
788
789 for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
790 if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
791 return n->value;
792 }
793 }
794 return nullptr;
795 }
796
797 std::vector<std::string> UserID::remarks(std::vector<Key> keys, Error &err) const
798 {
799 std::vector<std::string> ret;
800
801 for (const auto &key: keys) {
802 const char *rem = remark(key, err);
803 if (err) {
804 return ret;
805 }
806 if (rem) {
807 ret.push_back(rem);
808 }
809 }
810 return ret;
811 }
812
813 //
814 //
815 // class Signature
816 //
817 //
818
819 static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
820 {
821 if (uid) {
822 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
823 if (idx == 0) {
824 return s;
825 }
826 }
827 }
828 return nullptr;
829 }
830
831 static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
832 {
833 if (uid) {
834 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
835 if (s == sig) {
836 return sig;
837 }
838 }
839 }
840 return nullptr;
841 }
842
843 static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
844 {
845 if (uid) {
846 int i = 0;
847 for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
848 if (s == sig) {
849 return i;
850 }
851 }
852 }
853 return -1;
854 }
855
856 UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
857
858 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
859 : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
860 {
861 }
862
863 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
864 : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
865 {
866 }
867
868 bool UserID::Signature::operator<(const Signature &other)
869 {
870 // kept for binary compatibility
871 return static_cast<const UserID::Signature *>(this)->operator<(other);
872 }
873
874 bool UserID::Signature::operator<(const Signature &other) const
875 {
876 // based on cmp_signodes() in g10/keylist.c
877
878 // both signatures must belong to the same user ID
879 assert(uid == other.uid);
880
881 // self-signatures are ordered first
882 const char *primaryKeyId = parent().parent().keyID();
883 const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
884 const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
885 if (thisIsSelfSignature && !otherIsSelfSignature) {
886 return true;
887 }
888 if (otherIsSelfSignature && !thisIsSelfSignature) {
889 return false;
890 }
891
892 // then sort by signer key ID (which are or course the same for self-sigs)
893 const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
894 if (keyIdComparison < 0) {
895 return true;
896 }
897 if (keyIdComparison > 0) {
898 return false;
899 }
900
901 // followed by creation time
902 if (creationTime() < other.creationTime()) {
903 return true;
904 }
905 if (creationTime() > other.creationTime()) {
906 return false;
907 }
908
909 // followed by the class in a way that a rev comes first
910 if (certClass() < other.certClass()) {
911 return true;
912 }
913 if (certClass() > other.certClass()) {
914 return false;
915 }
916
917 // to make the sort stable we compare the indexes of the signatures as last resort
918 return signature_index(uid, sig) < signature_index(uid, other.sig);
919 }
920
921 UserID UserID::Signature::parent() const
922 {
923 return UserID(key, uid);
924 }
925
926 const char *UserID::Signature::signerKeyID() const
927 {
928 return sig ? sig->keyid : nullptr ;
929 }
930
931 const char *UserID::Signature::algorithmAsString() const
932 {
933 return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
934 }
935
936 unsigned int UserID::Signature::algorithm() const
937 {
938 return sig ? sig->pubkey_algo : 0 ;
939 }
940
941 time_t UserID::Signature::creationTime() const
942 {
943 return static_cast<time_t>(sig ? sig->timestamp : 0);
944 }
945
946 time_t UserID::Signature::expirationTime() const
947 {
948 return static_cast<time_t>(sig ? sig->expires : 0);
949 }
950
951 bool UserID::Signature::neverExpires() const
952 {
953 return expirationTime() == time_t(0);
954 }
955
956 bool UserID::Signature::isRevokation() const
957 {
958 return sig && sig->revoked;
959 }
960
961 bool UserID::Signature::isInvalid() const
962 {
963 return sig && sig->invalid;
964 }
965
966 bool UserID::Signature::isExpired() const
967 {
968 return sig && sig->expired;
969 }
970
971 bool UserID::Signature::isExportable() const
972 {
973 return sig && sig->exportable;
974 }
975
976 const char *UserID::Signature::signerUserID() const
977 {
978 return sig ? sig->uid : nullptr ;
979 }
980
981 const char *UserID::Signature::signerName() const
982 {
983 return sig ? sig->name : nullptr ;
984 }
985
986 const char *UserID::Signature::signerEmail() const
987 {
988 return sig ? sig->email : nullptr ;
989 }
990
991 const char *UserID::Signature::signerComment() const
992 {
993 return sig ? sig->comment : nullptr ;
994 }
995
996 unsigned int UserID::Signature::certClass() const
997 {
998 return sig ? sig->sig_class : 0 ;
999 }
1000
1001 UserID::Signature::Status UserID::Signature::status() const
1002 {
1003 if (!sig) {
1004 return GeneralError;
1005 }
1006
1007 switch (gpgme_err_code(sig->status)) {
1008 case GPG_ERR_NO_ERROR: return NoError;
1009 case GPG_ERR_SIG_EXPIRED: return SigExpired;
1010 case GPG_ERR_KEY_EXPIRED: return KeyExpired;
1011 case GPG_ERR_BAD_SIGNATURE: return BadSignature;
1012 case GPG_ERR_NO_PUBKEY: return NoPublicKey;
1013 default:
1014 case GPG_ERR_GENERAL: return GeneralError;
1015 }
1016 }
1017
1018 std::string UserID::Signature::statusAsString() const
1019 {
1020 if (!sig) {
1021 return std::string();
1022 }
1023 char buf[ 1024 ];
1024 gpgme_strerror_r(sig->status, buf, sizeof buf);
1025 buf[ sizeof buf - 1 ] = '\0';
1026 return std::string(buf);
1027 }
1028
1029 GpgME::Notation UserID::Signature::notation(unsigned int idx) const
1030 {
1031 if (!sig) {
1032 return GpgME::Notation();
1033 }
1034 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1035 if (nota->name) {
1036 if (idx-- == 0) {
1037 return GpgME::Notation(nota);
1038 }
1039 }
1040 }
1041 return GpgME::Notation();
1042 }
1043
1044 unsigned int UserID::Signature::numNotations() const
1045 {
1046 if (!sig) {
1047 return 0;
1048 }
1049 unsigned int count = 0;
1050 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1051 if (nota->name) {
1052 ++count; // others are policy URLs...
1053 }
1054 }
1055 return count;
1056 }
1057
1058 std::vector<Notation> UserID::Signature::notations() const
1059 {
1060 if (!sig) {
1061 return std::vector<GpgME::Notation>();
1062 }
1063 std::vector<GpgME::Notation> v;
1064 v.reserve(numNotations());
1065 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1066 if (nota->name) {
1067 v.push_back(GpgME::Notation(nota));
1068 }
1069 }
1070 return v;
1071 }
1072
1073 const char *UserID::Signature::policyURL() const
1074 {
1075 if (!sig) {
1076 return nullptr;
1077 }
1078 for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1079 if (!nota->name) {
1080 return nota->value;
1081 }
1082 }
1083 return nullptr;
1084 }
1085
1086 std::string UserID::addrSpecFromString(const char *userid)
1087 {
1088 if (!userid) {
1089 return std::string();
1090 }
1091 char *normalized = gpgme_addrspec_from_uid (userid);
1092 if (normalized) {
1093 std::string ret(normalized);
1094 gpgme_free(normalized);
1095 return ret;
1096 }
1097 return std::string();
1098 }
1099
1100 std::string UserID::addrSpec() const
1101 {
1102 if (!uid || !uid->address) {
1103 return std::string();
1104 }
1105
1106 return uid->address;
1107 }
1108
1109 Error UserID::revoke()
1110 {
1111 if (isNull()) {
1112 return Error::fromCode(GPG_ERR_GENERAL);
1113 }
1114 auto ctx = Context::createForProtocol(parent().protocol());
1115 if (!ctx) {
1116 return Error::fromCode(GPG_ERR_INV_ENGINE);
1117 }
1118 Error ret = ctx->revUid(key, id());
1119 delete ctx;
1120 return ret;
1121 }
1122
1123 static Key::Origin gpgme_origin_to_pp_origin (const unsigned int origin)
1124 {
1125 switch (origin) {
1126 case GPGME_KEYORG_KS:
1127 return Key::OriginKS;
1128 case GPGME_KEYORG_DANE:
1129 return Key::OriginDane;
1130 case GPGME_KEYORG_WKD:
1131 return Key::OriginWKD;
1132 case GPGME_KEYORG_URL:
1133 return Key::OriginURL;
1134 case GPGME_KEYORG_FILE:
1135 return Key::OriginFile;
1136 case GPGME_KEYORG_SELF:
1137 return Key::OriginSelf;
1138 case GPGME_KEYORG_OTHER:
1139 return Key::OriginOther;
1140 case GPGME_KEYORG_UNKNOWN:
1141 default:
1142 return Key::OriginUnknown;
1143 }
1144 }
1145
1146 Key::Origin UserID::origin() const
1147 {
1148 if (isNull()) {
1149 return Key::OriginUnknown;
1150 }
1151 return gpgme_origin_to_pp_origin(uid->origin);
1152 }
1153
1154 time_t UserID::lastUpdate() const
1155 {
1156 return static_cast<time_t>(uid ? uid->last_update : 0);
1157 }
1158
1159 Error Key::addUid(const char *uid)
1160 {
1161 if (isNull()) {
1162 return Error::fromCode(GPG_ERR_GENERAL);
1163 }
1164 auto ctx = Context::createForProtocol(protocol());
1165 if (!ctx) {
1166 return Error::fromCode(GPG_ERR_INV_ENGINE);
1167 }
1168 Error ret = ctx->addUid(key, uid);
1169 delete ctx;
1170 return ret;
1171 }
1172
1173 Key::Origin Key::origin() const
1174 {
1175 if (isNull()) {
1176 return OriginUnknown;
1177 }
1178 return gpgme_origin_to_pp_origin(key->origin);
1179 }
1180
1181 time_t Key::lastUpdate() const
1182 {
1183 return static_cast<time_t>(key ? key->last_update : 0);
1184 }
1185
1186 bool Key::isBad() const
1187 {
1188 return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1189 }
1190
1191 bool Subkey::isBad() const
1192 {
1193 return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1194 }
1195
1196 bool UserID::isBad() const
1197 {
1198 return isNull() || isRevoked() || isInvalid();
1199 }
1200
1201 bool UserID::Signature::isBad() const
1202 {
1203 return isNull() || isExpired() || isInvalid();
1204 }
1205
1206 std::ostream &operator<<(std::ostream &os, const UserID &uid)
1207 {
1208 os << "GpgME::UserID(";
1209 if (!uid.isNull()) {
1210 os << "\n name: " << protect(uid.name())
1211 << "\n email: " << protect(uid.email())
1212 << "\n mbox: " << uid.addrSpec()
1213 << "\n comment: " << protect(uid.comment())
1214 << "\n validity: " << uid.validityAsString()
1215 << "\n revoked: " << uid.isRevoked()
1216 << "\n invalid: " << uid.isInvalid()
1217 << "\n numsigs: " << uid.numSignatures()
1218 << "\n origin: " << uid.origin()
1219 << "\n updated: " << uid.lastUpdate()
1220 << "\n tofuinfo:\n" << uid.tofuInfo();
1221 }
1222 return os << ')';
1223 }
1224
1225 std::ostream &operator<<(std::ostream &os, const Subkey &subkey)
1226 {
1227 os << "GpgME::Subkey(";
1228 if (!subkey.isNull()) {
1229 os << "\n fingerprint: " << protect(subkey.fingerprint())
1230 << "\n creationTime: " << subkey.creationTime()
1231 << "\n expirationTime:" << subkey.expirationTime()
1232 << "\n isRevoked: " << subkey.isRevoked()
1233 << "\n isExpired: " << subkey.isExpired()
1234 << "\n isInvalid: " << subkey.isRevoked()
1235 << "\n isDisabled: " << subkey.isInvalid()
1236 << "\n canSign: " << subkey.canSign()
1237 << "\n canEncrypt: " << subkey.canEncrypt()
1238 << "\n canCertify: " << subkey.canCertify()
1239 << "\n canAuth: " << subkey.canAuthenticate();
1240 }
1241 return os << ')';
1242 }
1243
1244 std::ostream &operator<<(std::ostream &os, const Key &key)
1245 {
1246 os << "GpgME::Key(";
1247 if (!key.isNull()) {
1248 os << "\n protocol: " << protect(key.protocolAsString())
1249 << "\n ownertrust: " << key.ownerTrustAsString()
1250 << "\n issuer: " << protect(key.issuerName())
1251 << "\n fingerprint:" << protect(key.primaryFingerprint())
1252 << "\n listmode: " << key.keyListMode()
1253 << "\n canSign: " << key.canReallySign()
1254 << "\n canEncrypt: " << key.canEncrypt()
1255 << "\n canCertify: " << key.canCertify()
1256 << "\n canAuth: " << key.canAuthenticate()
1257 << "\n origin: " << key.origin()
1258 << "\n updated: " << key.lastUpdate()
1259 << "\n uids:\n";
1260 const std::vector<UserID> uids = key.userIDs();
1261 std::copy(uids.begin(), uids.end(),
1262 std::ostream_iterator<UserID>(os, "\n"));
1263 const std::vector<Subkey> subkeys = key.subkeys();
1264 std::copy(subkeys.begin(), subkeys.end(),
1265 std::ostream_iterator<Subkey>(os, "\n"));
1266 }
1267 return os << ')';
1268 }
1269
1270 } // namespace GpgME