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
|