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