Line data Source code
1 : /*
2 : key.h - 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 : // -*- c++ -*-
24 : #ifndef __GPGMEPP_KEY_H__
25 : #define __GPGMEPP_KEY_H__
26 :
27 : #include "global.h"
28 : #include "notation.h"
29 :
30 : #include "gpgmefw.h"
31 :
32 : #include <memory>
33 : #include <sys/time.h>
34 :
35 : #include <vector>
36 : #include <algorithm>
37 : #include <string>
38 :
39 : namespace GpgME
40 : {
41 :
42 : class Context;
43 :
44 : class Subkey;
45 : class UserID;
46 : class TofuInfo;
47 :
48 : typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
49 :
50 : //
51 : // class Key
52 : //
53 :
54 412 : class GPGMEPP_EXPORT Key
55 : {
56 : friend class ::GpgME::Context;
57 : struct Null {
58 8 : Null() {}
59 : };
60 : public:
61 : Key();
62 : /* implicit */ Key(const Null &);
63 : Key(const shared_gpgme_key_t &key);
64 : Key(gpgme_key_t key, bool acquireRef);
65 :
66 : static const Null null;
67 :
68 13 : const Key &operator=(Key other)
69 : {
70 13 : swap(other);
71 13 : return *this;
72 : }
73 :
74 : const Key &mergeWith(const Key &other);
75 :
76 20 : void swap(Key &other)
77 : {
78 : using std::swap;
79 20 : swap(this->key, other.key);
80 20 : }
81 :
82 34 : bool isNull() const
83 : {
84 34 : return !key;
85 : }
86 :
87 : UserID userID(unsigned int index) const;
88 : Subkey subkey(unsigned int index) const;
89 :
90 : unsigned int numUserIDs() const;
91 : unsigned int numSubkeys() const;
92 :
93 : std::vector<UserID> userIDs() const;
94 : std::vector<Subkey> subkeys() const;
95 :
96 : bool isRevoked() const;
97 : bool isExpired() const;
98 : bool isDisabled() const;
99 : bool isInvalid() const;
100 :
101 : /*! Shorthand for isNull || isRevoked || isExpired ||
102 : * isDisabled || isInvalid */
103 : bool isBad() const;
104 :
105 : bool canEncrypt() const;
106 : /*!
107 : This function contains a workaround for old gpgme's: all secret
108 : OpenPGP keys canSign() == true, which canReallySign() doesn't
109 : have. I don't have time to find what breaks when I remove this
110 : workaround, but since Kleopatra merges secret into public keys,
111 : the workaround is not necessary there (and actively harms), I've
112 : added a new function instead.
113 : */
114 : bool canSign() const;
115 : bool canReallySign() const;
116 : bool canCertify() const;
117 : bool canAuthenticate() const;
118 : bool isQualified() const;
119 : bool isDeVs() const;
120 :
121 : bool hasSecret() const;
122 : GPGMEPP_DEPRECATED bool isSecret() const
123 : {
124 : return hasSecret();
125 : }
126 :
127 : /*!
128 : @return true if this is a X.509 root certificate (currently
129 : equivalent to something like
130 : strcmp( chainID(), subkey(0).fingerprint() ) == 0 )
131 : */
132 : bool isRoot() const;
133 :
134 : enum OwnerTrust { Unknown = 0, Undefined = 1, Never = 2,
135 : Marginal = 3, Full = 4, Ultimate = 5
136 : };
137 :
138 : OwnerTrust ownerTrust() const;
139 : char ownerTrustAsString() const;
140 :
141 : Protocol protocol() const;
142 : const char *protocolAsString() const;
143 :
144 : const char *issuerSerial() const;
145 : const char *issuerName() const;
146 : const char *chainID() const;
147 :
148 : const char *keyID() const;
149 : const char *shortKeyID() const;
150 : const char *primaryFingerprint() const;
151 :
152 : unsigned int keyListMode() const;
153 :
154 : /*! Update information about this key.
155 : * Starts a keylisting for this key with validity
156 : * and tofu information gathering. Blocks for
157 : * how long the keylisting takes.*/
158 : void update();
159 :
160 : /**
161 : * @brief Add a user id to this key.
162 : *
163 : * Needs gnupg 2.1.13 and the key needs to be updated
164 : * afterwards to see the new uid.
165 : *
166 : * @param uid should be fully formatted and UTF-8 encoded.
167 : *
168 : * @returns a possible error.
169 : **/
170 : Error addUid(const char *uid);
171 :
172 : /**
173 : * @brief try to locate the best pgp key for a given mailbox.
174 : *
175 : * Boils down to gpg --locate-key <mbox>
176 : * This may take some time if remote sources are also
177 : * used.
178 : *
179 : * @param mbox should be a mail address does not need to be normalized.
180 : *
181 : * @returns The best key for a mailbox or a null key.
182 : */
183 : static Key locate(const char *mbox);
184 :
185 : /* @enum Origin
186 : * @brief The Origin of the key. */
187 : enum Origin : unsigned int {
188 : OriginUnknown = 0,
189 : OriginKS = 1,
190 : OriginDane = 3,
191 : OriginWKD = 4,
192 : OriginURL = 5,
193 : OriginFile = 6,
194 : OriginSelf = 7,
195 : OriginOther = 31,
196 : };
197 : /*! Get the origin of the key.
198 : *
199 : * @returns the Origin. */
200 : Origin origin() const;
201 :
202 : /*! Get the last update time.
203 : *
204 : * @returns the last update time. */
205 : time_t lastUpdate() const;
206 : private:
207 41 : gpgme_key_t impl() const
208 : {
209 41 : return key.get();
210 : }
211 : shared_gpgme_key_t key;
212 : };
213 :
214 : //
215 : // class Subkey
216 : //
217 :
218 28 : class GPGMEPP_EXPORT Subkey
219 : {
220 : public:
221 : Subkey();
222 : Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey);
223 : Subkey(const shared_gpgme_key_t &key, unsigned int idx);
224 :
225 : const Subkey &operator=(Subkey other)
226 : {
227 : swap(other);
228 : return *this;
229 : }
230 :
231 : void swap(Subkey &other)
232 : {
233 : using std::swap;
234 : swap(this->key, other.key);
235 : swap(this->subkey, other.subkey);
236 : }
237 :
238 0 : bool isNull() const
239 : {
240 0 : return !key || !subkey;
241 : }
242 :
243 : Key parent() const;
244 :
245 : const char *keyID() const;
246 : const char *fingerprint() const;
247 :
248 : time_t creationTime() const;
249 : time_t expirationTime() const;
250 : bool neverExpires() const;
251 :
252 : bool isRevoked() const;
253 : bool isExpired() const;
254 : bool isInvalid() const;
255 : bool isDisabled() const;
256 :
257 : /*! Shorthand for isNull || isRevoked || isExpired ||
258 : * isDisabled || isInvalid */
259 : bool isBad() const;
260 :
261 : bool canEncrypt() const;
262 : bool canSign() const;
263 : bool canCertify() const;
264 : bool canAuthenticate() const;
265 : bool isQualified() const;
266 : bool isDeVs() const;
267 : bool isCardKey() const;
268 :
269 : bool isSecret() const;
270 :
271 : /** Same as gpgme_pubkey_algo_t */
272 : enum PubkeyAlgo {
273 : AlgoUnknown = 0,
274 : AlgoRSA = 1,
275 : AlgoRSA_E = 2,
276 : AlgoRSA_S = 3,
277 : AlgoELG_E = 16,
278 : AlgoDSA = 17,
279 : AlgoECC = 18,
280 : AlgoELG = 20,
281 : AlgoECDSA = 301,
282 : AlgoECDH = 302,
283 : AlgoEDDSA = 303,
284 : AlgoMax = 1 << 31
285 : };
286 :
287 : PubkeyAlgo publicKeyAlgorithm() const;
288 :
289 : /**
290 : @brief Get the public key algorithm name.
291 :
292 : This only works for the pre 2.1 algorithms for ECC NULL is returned.
293 :
294 : @returns a statically allocated string with the name of the public
295 : key algorithm, or NULL if that name is not known.
296 : */
297 : const char *publicKeyAlgorithmAsString() const;
298 :
299 : /** @brief Same as publicKeyAlgorithmAsString but static. */
300 : static const char *publicKeyAlgorithmAsString(PubkeyAlgo algo);
301 :
302 : /**
303 : @brief Get the key algo string like GnuPG 2.1 prints it.
304 :
305 : This returns combinations of size and algorithm. Like
306 : bp512 or rsa2048. Misnamed because publicKeyAlgorithmAsString
307 : already used the older pubkey_algo_name.
308 : Actually uses gpgme_pubkey_algo_string.
309 :
310 : @returns the key algorithm as string. Empty string on error.
311 : */
312 : std::string algoName() const;
313 :
314 : unsigned int length() const;
315 :
316 : const char *cardSerialNumber() const;
317 :
318 : const char *keyGrip() const;
319 :
320 : private:
321 : shared_gpgme_key_t key;
322 : gpgme_sub_key_t subkey;
323 : };
324 :
325 : //
326 : // class UserID
327 : //
328 :
329 86 : class GPGMEPP_EXPORT UserID
330 : {
331 : public:
332 : class Signature;
333 :
334 : UserID();
335 : UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid);
336 : UserID(const shared_gpgme_key_t &key, unsigned int idx);
337 :
338 0 : const UserID &operator=(UserID other)
339 : {
340 0 : swap(other);
341 0 : return *this;
342 : }
343 :
344 0 : void swap(UserID &other)
345 : {
346 : using std::swap;
347 0 : swap(this->key, other.key);
348 0 : swap(this->uid, other.uid);
349 0 : }
350 :
351 0 : bool isNull() const
352 : {
353 0 : return !key || !uid;
354 : }
355 :
356 : Key parent() const;
357 :
358 : unsigned int numSignatures() const;
359 : Signature signature(unsigned int index) const;
360 : std::vector<Signature> signatures() const;
361 :
362 : const char *id() const;
363 : const char *name() const;
364 : const char *email() const;
365 : const char *comment() const;
366 :
367 : enum Validity { Unknown = 0, Undefined = 1, Never = 2,
368 : Marginal = 3, Full = 4, Ultimate = 5
369 : };
370 :
371 : Validity validity() const;
372 : char validityAsString() const;
373 :
374 : bool isRevoked() const;
375 : bool isInvalid() const;
376 :
377 : /*! Shorthand for isNull || isRevoked || isInvalid */
378 : bool isBad() const;
379 :
380 : /** TOFU info for this userid.
381 : * @returns The TOFU stats or a null TofuInfo.
382 : */
383 : GpgME::TofuInfo tofuInfo() const;
384 :
385 : /*! Wrapper around gpgme_addrspec_from_uid.
386 : *
387 : * The input string should match the format of
388 : * a user id string.
389 : *
390 : * @returns a normalized mail address if found
391 : * or an empty string. */
392 : static std::string addrSpecFromString(const char *uid);
393 :
394 : /*! Wrapper around gpgme_addrspec_from_uid.
395 : *
396 : * @returns a normalized mail address for this userid
397 : * or an empty string. */
398 : std::string addrSpec() const;
399 :
400 : /*! Revoke the user id.
401 : *
402 : * Key needs update afterwards.
403 : *
404 : * @returns an error on error.*/
405 : Error revoke();
406 :
407 : /*! Get the origin of the key.
408 : *
409 : * @returns the Origin. */
410 : Key::Origin origin() const;
411 :
412 : /*! Get the last update time.
413 : *
414 : * @returns the last update time. */
415 : time_t lastUpdate() const;
416 : private:
417 : shared_gpgme_key_t key;
418 : gpgme_user_id_t uid;
419 : };
420 :
421 : //
422 : // class UserID::Signature
423 : //
424 :
425 0 : class GPGMEPP_EXPORT UserID::Signature
426 : {
427 : public:
428 : typedef GPGMEPP_DEPRECATED GpgME::Notation Notation;
429 :
430 : Signature();
431 : Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig);
432 : Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx);
433 :
434 : const Signature &operator=(Signature other)
435 : {
436 : swap(other);
437 : return *this;
438 : }
439 :
440 : void swap(Signature &other)
441 : {
442 : using std::swap;
443 : swap(this->key, other.key);
444 : swap(this->uid, other.uid);
445 : swap(this->sig, other.sig);
446 : }
447 :
448 0 : bool isNull() const
449 : {
450 0 : return !sig || !uid || !key ;
451 : }
452 :
453 : UserID parent() const;
454 :
455 : const char *signerKeyID() const;
456 :
457 : const char *algorithmAsString() const;
458 : unsigned int algorithm() const;
459 : time_t creationTime() const;
460 : time_t expirationTime() const;
461 : bool neverExpires() const;
462 :
463 : bool isRevokation() const;
464 : bool isInvalid() const;
465 : bool isExpired() const;
466 : bool isExportable() const;
467 :
468 : /*! Shorthand for isNull || isExpired || isInvalid */
469 : bool isBad() const;
470 :
471 : const char *signerUserID() const;
472 : const char *signerName() const;
473 : const char *signerEmail() const;
474 : const char *signerComment() const;
475 :
476 : unsigned int certClass() const;
477 :
478 : enum Status { NoError = 0, SigExpired, KeyExpired,
479 : BadSignature, NoPublicKey, GeneralError
480 : };
481 : Status status() const;
482 : std::string statusAsString() const;
483 :
484 : const char *policyURL() const;
485 :
486 : unsigned int numNotations() const;
487 : GpgME::Notation notation(unsigned int idx) const;
488 : std::vector<GpgME::Notation> notations() const;
489 :
490 : private:
491 : shared_gpgme_key_t key;
492 : gpgme_user_id_t uid;
493 : gpgme_key_sig_t sig;
494 : };
495 :
496 : GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid);
497 : GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key);
498 :
499 : } // namespace GpgME
500 :
501 0 : GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Key)
502 : GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Subkey)
503 : GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID)
504 : GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID::Signature)
505 :
506 0 : GPGMEPP_MAKE_STRCMP(ByFingerprint, .primaryFingerprint());
507 : GPGMEPP_MAKE_STRCMP(ByKeyID, .keyID());
508 : GPGMEPP_MAKE_STRCMP(ByShortKeyID, .shortKeyID());
509 : GPGMEPP_MAKE_STRCMP(ByChainID, .chainID());
510 :
511 : #endif // __GPGMEPP_KEY_H__
|