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 6 : const GpgME::Key::Null GpgME::Key::null;
41 :
42 : namespace GpgME
43 : {
44 :
45 1 : 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 43 : Key::Key(gpgme_key_t k, bool ref)
52 : : key(k
53 : ? shared_gpgme_key_t(k, &gpgme_key_unref)
54 43 : : shared_gpgme_key_t())
55 : {
56 43 : if (ref && impl()) {
57 9 : gpgme_key_ref(impl());
58 : }
59 43 : }
60 :
61 15 : UserID Key::userID(unsigned int index) const
62 : {
63 15 : 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 8 : unsigned int Key::numUserIDs() const
72 : {
73 8 : if (!key) {
74 0 : return 0;
75 : }
76 8 : unsigned int count = 0;
77 20 : for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
78 12 : ++count;
79 : }
80 8 : 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 7 : std::vector<UserID> Key::userIDs() const
96 : {
97 7 : if (!key) {
98 0 : return std::vector<UserID>();
99 : }
100 :
101 7 : std::vector<UserID> v;
102 7 : v.reserve(numUserIDs());
103 16 : for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
104 9 : v.push_back(UserID(key, uid));
105 : }
106 7 : 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 4 : 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 5 : Protocol Key::protocol() const
155 : {
156 5 : if (!key) {
157 0 : return UnknownProtocol;
158 : }
159 5 : switch (key->protocol) {
160 0 : case GPGME_PROTOCOL_CMS: return CMS;
161 5 : 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 5 : bool Key::hasSecret() const
192 : {
193 5 : 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 : const char *Key::issuerSerial() const
238 : {
239 0 : return key ? key->issuer_serial : 0 ;
240 : }
241 0 : const char *Key::issuerName() const
242 : {
243 0 : return key ? key->issuer_name : 0 ;
244 : }
245 0 : const char *Key::chainID() const
246 : {
247 0 : return key ? key->chain_id : 0 ;
248 : }
249 :
250 1 : const char *Key::keyID() const
251 : {
252 1 : return key && key->subkeys ? key->subkeys->keyid : 0 ;
253 : }
254 :
255 0 : const char *Key::shortKeyID() const
256 : {
257 0 : if (!key || !key->subkeys || !key->subkeys->keyid) {
258 0 : return 0;
259 : }
260 0 : const int len = strlen(key->subkeys->keyid);
261 0 : if (len > 8) {
262 0 : return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
263 : } else {
264 0 : return key->subkeys->keyid;
265 : }
266 : }
267 :
268 27 : const char *Key::primaryFingerprint() const
269 : {
270 27 : if (!key) {
271 0 : return nullptr;
272 : }
273 27 : if (key->fpr) {
274 : /* Return what gpgme thinks is the primary fingerprint */
275 27 : return key->fpr;
276 : }
277 0 : if (key->subkeys) {
278 : /* Return the first subkeys fingerprint */
279 0 : return key->subkeys->fpr;
280 : }
281 0 : return nullptr;
282 : }
283 :
284 0 : unsigned int Key::keyListMode() const
285 : {
286 0 : return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ;
287 : }
288 :
289 0 : const Key &Key::mergeWith(const Key &other)
290 : {
291 : // ### incomplete. Just merges has* and can*, nothing else atm
292 : // ### detach also missing
293 :
294 0 : if (!this->primaryFingerprint() ||
295 0 : !other.primaryFingerprint() ||
296 0 : strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
297 0 : return *this; // only merge the Key object which describe the same key
298 : }
299 :
300 0 : const gpgme_key_t me = impl();
301 0 : const gpgme_key_t him = other.impl();
302 :
303 0 : if (!me || !him) {
304 0 : return *this;
305 : }
306 :
307 0 : me->revoked |= him->revoked;
308 0 : me->expired |= him->expired;
309 0 : me->disabled |= him->disabled;
310 0 : me->invalid |= him->invalid;
311 0 : me->can_encrypt |= him->can_encrypt;
312 0 : me->can_sign |= him->can_sign;
313 0 : me->can_certify |= him->can_certify;
314 0 : me->secret |= him->secret;
315 0 : me->can_authenticate |= him->can_authenticate;
316 0 : me->is_qualified |= him->is_qualified;
317 0 : me->keylist_mode |= him->keylist_mode;
318 :
319 : // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
320 0 : for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
321 0 : for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
322 0 : if (strcmp(mysk->fpr, hissk->fpr) == 0) {
323 0 : mysk->is_cardkey |= hissk->is_cardkey;
324 0 : break;
325 : }
326 : }
327 : }
328 :
329 0 : return *this;
330 : }
331 :
332 5 : void Key::update()
333 : {
334 5 : auto ctx = Context::createForProtocol(protocol());
335 5 : if (!ctx) {
336 0 : return;
337 : }
338 : ctx->setKeyListMode(KeyListMode::Local |
339 : KeyListMode::Signatures |
340 : KeyListMode::SignatureNotations |
341 : KeyListMode::Validate |
342 5 : KeyListMode::WithTofu);
343 5 : Error err;
344 10 : auto newKey = ctx->key(primaryFingerprint(), err, hasSecret());
345 5 : delete ctx;
346 5 : if (err) {
347 0 : return;
348 : }
349 5 : swap(newKey);
350 10 : return;
351 : }
352 :
353 : //
354 : //
355 : // class Subkey
356 : //
357 : //
358 :
359 0 : gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
360 : {
361 0 : if (key) {
362 0 : for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
363 0 : if (idx == 0) {
364 0 : return s;
365 : }
366 : }
367 : }
368 0 : return 0;
369 : }
370 :
371 8 : gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
372 : {
373 8 : if (key) {
374 12 : for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
375 12 : if (s == subkey) {
376 8 : return subkey;
377 : }
378 : }
379 : }
380 0 : return 0;
381 : }
382 :
383 0 : Subkey::Subkey() : key(), subkey(0) {}
384 :
385 0 : Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
386 0 : : key(k), subkey(find_subkey(k, idx))
387 : {
388 :
389 0 : }
390 :
391 8 : Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
392 8 : : key(k), subkey(verify_subkey(k, sk))
393 : {
394 :
395 8 : }
396 :
397 0 : Key Subkey::parent() const
398 : {
399 0 : return Key(key);
400 : }
401 :
402 0 : const char *Subkey::keyID() const
403 : {
404 0 : return subkey ? subkey->keyid : 0 ;
405 : }
406 :
407 2 : const char *Subkey::fingerprint() const
408 : {
409 2 : return subkey ? subkey->fpr : 0 ;
410 : }
411 :
412 2 : Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
413 : {
414 2 : return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
415 : }
416 :
417 0 : const char *Subkey::publicKeyAlgorithmAsString() const
418 : {
419 0 : return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
420 : }
421 :
422 : /* static */
423 11 : const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
424 : {
425 11 : if (algo == AlgoUnknown) {
426 1 : return NULL;
427 : }
428 10 : return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
429 : }
430 :
431 0 : std::string Subkey::algoName() const
432 : {
433 : char *gpgmeStr;
434 0 : if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
435 0 : std::string ret = std::string(gpgmeStr);
436 0 : gpgme_free(gpgmeStr);
437 0 : return ret;
438 : }
439 0 : return std::string();
440 : }
441 :
442 0 : bool Subkey::canEncrypt() const
443 : {
444 0 : return subkey && subkey->can_encrypt;
445 : }
446 :
447 0 : bool Subkey::canSign() const
448 : {
449 0 : return subkey && subkey->can_sign;
450 : }
451 :
452 0 : bool Subkey::canCertify() const
453 : {
454 0 : return subkey && subkey->can_certify;
455 : }
456 :
457 0 : bool Subkey::canAuthenticate() const
458 : {
459 0 : return subkey && subkey->can_authenticate;
460 : }
461 :
462 0 : bool Subkey::isQualified() const
463 : {
464 0 : return subkey && subkey->is_qualified;
465 : }
466 :
467 0 : bool Subkey::isCardKey() const
468 : {
469 0 : return subkey && subkey->is_cardkey;
470 : }
471 :
472 0 : const char *Subkey::cardSerialNumber() const
473 : {
474 0 : return subkey ? subkey->card_number : 0 ;
475 : }
476 :
477 0 : bool Subkey::isSecret() const
478 : {
479 0 : return subkey && subkey->secret;
480 : }
481 :
482 0 : unsigned int Subkey::length() const
483 : {
484 0 : return subkey ? subkey->length : 0 ;
485 : }
486 :
487 0 : time_t Subkey::creationTime() const
488 : {
489 0 : return static_cast<time_t>(subkey ? subkey->timestamp : 0);
490 : }
491 :
492 0 : time_t Subkey::expirationTime() const
493 : {
494 0 : return static_cast<time_t>(subkey ? subkey->expires : 0);
495 : }
496 :
497 0 : bool Subkey::neverExpires() const
498 : {
499 0 : return expirationTime() == time_t(0);
500 : }
501 :
502 0 : bool Subkey::isRevoked() const
503 : {
504 0 : return subkey && subkey->revoked;
505 : }
506 :
507 0 : bool Subkey::isInvalid() const
508 : {
509 0 : return subkey && subkey->invalid;
510 : }
511 :
512 0 : bool Subkey::isExpired() const
513 : {
514 0 : return subkey && subkey->expired;
515 : }
516 :
517 0 : bool Subkey::isDisabled() const
518 : {
519 0 : return subkey && subkey->disabled;
520 : }
521 :
522 : //
523 : //
524 : // class UserID
525 : //
526 : //
527 :
528 15 : gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
529 : {
530 15 : if (key) {
531 15 : for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
532 15 : if (idx == 0) {
533 15 : return u;
534 : }
535 : }
536 : }
537 0 : return 0;
538 : }
539 :
540 9 : gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
541 : {
542 9 : if (key) {
543 12 : for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
544 12 : if (u == uid) {
545 9 : return uid;
546 : }
547 : }
548 : }
549 0 : return 0;
550 : }
551 :
552 0 : UserID::UserID() : key(), uid(0) {}
553 :
554 9 : UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
555 9 : : key(k), uid(verify_uid(k, u))
556 : {
557 :
558 9 : }
559 :
560 15 : UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
561 15 : : key(k), uid(find_uid(k, idx))
562 : {
563 :
564 15 : }
565 :
566 0 : Key UserID::parent() const
567 : {
568 0 : return Key(key);
569 : }
570 :
571 0 : UserID::Signature UserID::signature(unsigned int index) const
572 : {
573 0 : return Signature(key, uid, index);
574 : }
575 :
576 0 : unsigned int UserID::numSignatures() const
577 : {
578 0 : if (!uid) {
579 0 : return 0;
580 : }
581 0 : unsigned int count = 0;
582 0 : for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
583 0 : ++count;
584 : }
585 0 : return count;
586 : }
587 :
588 0 : std::vector<UserID::Signature> UserID::signatures() const
589 : {
590 0 : if (!uid) {
591 0 : return std::vector<Signature>();
592 : }
593 :
594 0 : std::vector<Signature> v;
595 0 : v.reserve(numSignatures());
596 0 : for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
597 0 : v.push_back(Signature(key, uid, sig));
598 : }
599 0 : return v;
600 : }
601 :
602 0 : const char *UserID::id() const
603 : {
604 0 : return uid ? uid->uid : 0 ;
605 : }
606 :
607 0 : const char *UserID::name() const
608 : {
609 0 : return uid ? uid->name : 0 ;
610 : }
611 :
612 3 : const char *UserID::email() const
613 : {
614 3 : return uid ? uid->email : 0 ;
615 : }
616 :
617 0 : const char *UserID::comment() const
618 : {
619 0 : return uid ? uid->comment : 0 ;
620 : }
621 :
622 0 : UserID::Validity UserID::validity() const
623 : {
624 0 : if (!uid) {
625 0 : return Unknown;
626 : }
627 0 : switch (uid->validity) {
628 : default:
629 0 : case GPGME_VALIDITY_UNKNOWN: return Unknown;
630 0 : case GPGME_VALIDITY_UNDEFINED: return Undefined;
631 0 : case GPGME_VALIDITY_NEVER: return Never;
632 0 : case GPGME_VALIDITY_MARGINAL: return Marginal;
633 0 : case GPGME_VALIDITY_FULL: return Full;
634 0 : case GPGME_VALIDITY_ULTIMATE: return Ultimate;
635 : }
636 : }
637 :
638 0 : char UserID::validityAsString() const
639 : {
640 0 : if (!uid) {
641 0 : return '?';
642 : }
643 0 : switch (uid->validity) {
644 : default:
645 0 : case GPGME_VALIDITY_UNKNOWN: return '?';
646 0 : case GPGME_VALIDITY_UNDEFINED: return 'q';
647 0 : case GPGME_VALIDITY_NEVER: return 'n';
648 0 : case GPGME_VALIDITY_MARGINAL: return 'm';
649 0 : case GPGME_VALIDITY_FULL: return 'f';
650 0 : case GPGME_VALIDITY_ULTIMATE: return 'u';
651 : }
652 : }
653 :
654 0 : bool UserID::isRevoked() const
655 : {
656 0 : return uid && uid->revoked;
657 : }
658 :
659 0 : bool UserID::isInvalid() const
660 : {
661 0 : return uid && uid->invalid;
662 : }
663 :
664 21 : TofuInfo UserID::tofuInfo() const
665 : {
666 21 : if (!uid) {
667 0 : return TofuInfo();
668 : }
669 21 : return TofuInfo(uid->tofu);
670 : }
671 :
672 : //
673 : //
674 : // class Signature
675 : //
676 : //
677 :
678 0 : gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
679 : {
680 0 : if (uid) {
681 0 : for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
682 0 : if (idx == 0) {
683 0 : return s;
684 : }
685 : }
686 : }
687 0 : return 0;
688 : }
689 :
690 0 : gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
691 : {
692 0 : if (uid) {
693 0 : for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
694 0 : if (s == sig) {
695 0 : return sig;
696 : }
697 : }
698 : }
699 0 : return 0;
700 : }
701 :
702 0 : UserID::Signature::Signature() : key(), uid(0), sig(0) {}
703 :
704 0 : UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
705 0 : : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
706 : {
707 :
708 0 : }
709 :
710 0 : UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
711 0 : : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
712 : {
713 :
714 0 : }
715 :
716 0 : UserID UserID::Signature::parent() const
717 : {
718 0 : return UserID(key, uid);
719 : }
720 :
721 0 : const char *UserID::Signature::signerKeyID() const
722 : {
723 0 : return sig ? sig->keyid : 0 ;
724 : }
725 :
726 0 : const char *UserID::Signature::algorithmAsString() const
727 : {
728 0 : return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
729 : }
730 :
731 0 : unsigned int UserID::Signature::algorithm() const
732 : {
733 0 : return sig ? sig->pubkey_algo : 0 ;
734 : }
735 :
736 0 : time_t UserID::Signature::creationTime() const
737 : {
738 0 : return static_cast<time_t>(sig ? sig->timestamp : 0);
739 : }
740 :
741 0 : time_t UserID::Signature::expirationTime() const
742 : {
743 0 : return static_cast<time_t>(sig ? sig->expires : 0);
744 : }
745 :
746 0 : bool UserID::Signature::neverExpires() const
747 : {
748 0 : return expirationTime() == time_t(0);
749 : }
750 :
751 0 : bool UserID::Signature::isRevokation() const
752 : {
753 0 : return sig && sig->revoked;
754 : }
755 :
756 0 : bool UserID::Signature::isInvalid() const
757 : {
758 0 : return sig && sig->invalid;
759 : }
760 :
761 0 : bool UserID::Signature::isExpired() const
762 : {
763 0 : return sig && sig->expired;
764 : }
765 :
766 0 : bool UserID::Signature::isExportable() const
767 : {
768 0 : return sig && sig->exportable;
769 : }
770 :
771 0 : const char *UserID::Signature::signerUserID() const
772 : {
773 0 : return sig ? sig->uid : 0 ;
774 : }
775 :
776 0 : const char *UserID::Signature::signerName() const
777 : {
778 0 : return sig ? sig->name : 0 ;
779 : }
780 :
781 0 : const char *UserID::Signature::signerEmail() const
782 : {
783 0 : return sig ? sig->email : 0 ;
784 : }
785 :
786 0 : const char *UserID::Signature::signerComment() const
787 : {
788 0 : return sig ? sig->comment : 0 ;
789 : }
790 :
791 0 : unsigned int UserID::Signature::certClass() const
792 : {
793 0 : return sig ? sig->sig_class : 0 ;
794 : }
795 :
796 0 : UserID::Signature::Status UserID::Signature::status() const
797 : {
798 0 : if (!sig) {
799 0 : return GeneralError;
800 : }
801 :
802 0 : switch (gpgme_err_code(sig->status)) {
803 0 : case GPG_ERR_NO_ERROR: return NoError;
804 0 : case GPG_ERR_SIG_EXPIRED: return SigExpired;
805 0 : case GPG_ERR_KEY_EXPIRED: return KeyExpired;
806 0 : case GPG_ERR_BAD_SIGNATURE: return BadSignature;
807 0 : case GPG_ERR_NO_PUBKEY: return NoPublicKey;
808 : default:
809 0 : case GPG_ERR_GENERAL: return GeneralError;
810 : }
811 : }
812 :
813 0 : std::string UserID::Signature::statusAsString() const
814 : {
815 0 : if (!sig) {
816 0 : return std::string();
817 : }
818 : char buf[ 1024 ];
819 0 : gpgme_strerror_r(sig->status, buf, sizeof buf);
820 0 : buf[ sizeof buf - 1 ] = '\0';
821 0 : return std::string(buf);
822 : }
823 :
824 0 : GpgME::Notation UserID::Signature::notation(unsigned int idx) const
825 : {
826 0 : if (!sig) {
827 0 : return GpgME::Notation();
828 : }
829 0 : for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
830 0 : if (nota->name) {
831 0 : if (idx-- == 0) {
832 0 : return GpgME::Notation(nota);
833 : }
834 : }
835 : }
836 0 : return GpgME::Notation();
837 : }
838 :
839 0 : unsigned int UserID::Signature::numNotations() const
840 : {
841 0 : if (!sig) {
842 0 : return 0;
843 : }
844 0 : unsigned int count = 0;
845 0 : for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
846 0 : if (nota->name) {
847 0 : ++count; // others are policy URLs...
848 : }
849 : }
850 0 : return count;
851 : }
852 :
853 0 : std::vector<Notation> UserID::Signature::notations() const
854 : {
855 0 : if (!sig) {
856 0 : return std::vector<GpgME::Notation>();
857 : }
858 0 : std::vector<GpgME::Notation> v;
859 0 : v.reserve(numNotations());
860 0 : for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
861 0 : if (nota->name) {
862 0 : v.push_back(GpgME::Notation(nota));
863 : }
864 : }
865 0 : return v;
866 : }
867 :
868 0 : const char *UserID::Signature::policyURL() const
869 : {
870 0 : if (!sig) {
871 0 : return 0;
872 : }
873 0 : for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
874 0 : if (!nota->name) {
875 0 : return nota->value;
876 : }
877 : }
878 0 : return 0;
879 : }
880 :
881 0 : std::string UserID::addrSpecFromString(const char *userid)
882 : {
883 0 : if (!userid) {
884 0 : return std::string();
885 : }
886 0 : char *normalized = gpgme_addrspec_from_uid (userid);
887 0 : if (normalized) {
888 0 : std::string ret(normalized);
889 0 : gpgme_free(normalized);
890 0 : return ret;
891 : }
892 0 : return std::string();
893 : }
894 :
895 0 : std::string UserID::addrSpec() const
896 : {
897 0 : return addrSpecFromString(email());
898 : }
899 :
900 0 : std::ostream &operator<<(std::ostream &os, const UserID &uid)
901 : {
902 0 : os << "GpgME::UserID(";
903 0 : if (!uid.isNull()) {
904 0 : os << "\n name: " << protect(uid.name())
905 0 : << "\n email: " << protect(uid.email())
906 0 : << "\n comment: " << protect(uid.comment())
907 0 : << "\n validity: " << uid.validityAsString()
908 0 : << "\n revoked: " << uid.isRevoked()
909 0 : << "\n invalid: " << uid.isInvalid()
910 0 : << "\n numsigs: " << uid.numSignatures()
911 0 : << "\n tofuinfo:\n" << uid.tofuInfo();
912 : }
913 0 : return os << ')';
914 : }
915 :
916 0 : std::ostream &operator<<(std::ostream &os, const Key &key)
917 : {
918 0 : os << "GpgME::Key(";
919 0 : if (!key.isNull()) {
920 0 : os << "\n protocol: " << protect(key.protocolAsString())
921 0 : << "\n ownertrust: " << key.ownerTrustAsString()
922 0 : << "\n issuer: " << protect(key.issuerName())
923 0 : << "\n fingerprint:" << protect(key.primaryFingerprint())
924 0 : << "\n listmode: " << key.keyListMode()
925 0 : << "\n canSign: " << key.canReallySign()
926 0 : << "\n canEncrypt: " << key.canEncrypt()
927 0 : << "\n canCertify: " << key.canCertify()
928 0 : << "\n canAuth: " << key.canAuthenticate()
929 0 : << "\n uids:\n";
930 0 : const std::vector<UserID> uids = key.userIDs();
931 : std::copy(uids.begin(), uids.end(),
932 0 : std::ostream_iterator<UserID>(os, "\n"));
933 : }
934 0 : return os << ')';
935 : }
936 :
937 18 : } // namespace GpgME
|