Line data Source code
1 : /*
2 : context.cpp - wraps a gpgme key context
3 : Copyright (C) 2003, 2007 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 <context.h>
28 : #include <eventloopinteractor.h>
29 : #include <trustitem.h>
30 : #include <keylistresult.h>
31 : #include <keygenerationresult.h>
32 : #include <importresult.h>
33 : #include <decryptionresult.h>
34 : #include <verificationresult.h>
35 : #include <signingresult.h>
36 : #include <encryptionresult.h>
37 : #include <engineinfo.h>
38 : #include <editinteractor.h>
39 : #include <vfsmountresult.h>
40 :
41 : #include <interfaces/assuantransaction.h>
42 : #include <defaultassuantransaction.h>
43 :
44 : #include "callbacks.h"
45 : #include "data_p.h"
46 : #include "context_p.h"
47 : #include "util.h"
48 : #include "tofuinfo.h"
49 :
50 : #include <gpgme.h>
51 :
52 : #include <istream>
53 : #ifndef NDEBUG
54 : #include <iostream>
55 : using std::cerr;
56 : using std::endl;
57 : #endif
58 :
59 : #include <cassert>
60 :
61 : namespace GpgME
62 : {
63 :
64 0 : static inline unsigned int xtoi_1(const char *str)
65 : {
66 0 : const unsigned int ch = *str;
67 : const unsigned int result =
68 0 : ch <= '9' ? ch - '0' :
69 0 : ch <= 'F' ? ch - 'A' + 10 :
70 0 : /* else */ ch - 'a' + 10 ;
71 0 : return result < 16 ? result : 0 ;
72 : }
73 0 : static inline int xtoi_2(const char *str)
74 : {
75 0 : return xtoi_1(str) * 16U + xtoi_1(str + 1);
76 : }
77 :
78 0 : static void percent_unescape(std::string &s, bool plus2space)
79 : {
80 0 : std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
81 0 : while (src != end) {
82 0 : if (*src == '%' && end - src > 2) {
83 0 : *dest++ = xtoi_2(&*++src);
84 0 : src += 2;
85 0 : } else if (*src == '+' && plus2space) {
86 0 : *dest++ = ' ';
87 0 : ++src;
88 : } else {
89 0 : *dest++ = *src++;
90 : }
91 : }
92 0 : s.erase(dest, end);
93 0 : }
94 :
95 0 : void initializeLibrary()
96 : {
97 0 : gpgme_check_version(0);
98 0 : }
99 :
100 0 : Error initializeLibrary(int)
101 : {
102 0 : if (gpgme_check_version(GPGME_VERSION)) {
103 0 : return Error();
104 : } else {
105 0 : return Error::fromCode(GPG_ERR_USER_1);
106 : }
107 : }
108 :
109 0 : static void format_error(gpgme_error_t err, std::string &str)
110 : {
111 : char buffer[ 1024 ];
112 0 : gpgme_strerror_r(err, buffer, sizeof buffer);
113 0 : buffer[ sizeof buffer - 1 ] = '\0';
114 0 : str = buffer;
115 0 : }
116 :
117 0 : const char *Error::source() const
118 : {
119 0 : return gpgme_strsource((gpgme_error_t)mErr);
120 : }
121 :
122 0 : const char *Error::asString() const
123 : {
124 0 : if (mMessage.empty()) {
125 0 : format_error(static_cast<gpgme_error_t>(mErr), mMessage);
126 : }
127 0 : return mMessage.c_str();
128 : }
129 :
130 0 : int Error::code() const
131 : {
132 0 : return gpgme_err_code(mErr);
133 : }
134 :
135 0 : int Error::sourceID() const
136 : {
137 0 : return gpgme_err_source(mErr);
138 : }
139 :
140 0 : bool Error::isCanceled() const
141 : {
142 0 : return code() == GPG_ERR_CANCELED;
143 : }
144 :
145 0 : int Error::toErrno() const
146 : {
147 : //#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
148 0 : return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
149 : //#else
150 : // return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
151 : //#endif
152 : }
153 :
154 : // static
155 0 : bool Error::hasSystemError()
156 : {
157 0 : return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
158 : }
159 :
160 : // static
161 0 : void Error::setSystemError(gpg_err_code_t err)
162 : {
163 0 : setErrno(gpgme_err_code_to_errno(err));
164 0 : }
165 :
166 : // static
167 0 : void Error::setErrno(int err)
168 : {
169 0 : gpgme_err_set_errno(err);
170 0 : }
171 :
172 : // static
173 0 : Error Error::fromSystemError(unsigned int src)
174 : {
175 0 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
176 : }
177 :
178 : // static
179 0 : Error Error::fromErrno(int err, unsigned int src)
180 : {
181 0 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
182 : }
183 :
184 : // static
185 0 : Error Error::fromCode(unsigned int err, unsigned int src)
186 : {
187 0 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
188 : }
189 :
190 0 : std::ostream &operator<<(std::ostream &os, const Error &err)
191 : {
192 0 : return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
193 : }
194 :
195 0 : Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
196 : {
197 0 : }
198 :
199 0 : Context::~Context()
200 : {
201 0 : delete d;
202 0 : }
203 :
204 0 : Context *Context::createForProtocol(Protocol proto)
205 : {
206 0 : gpgme_ctx_t ctx = 0;
207 0 : if (gpgme_new(&ctx) != 0) {
208 0 : return 0;
209 : }
210 :
211 0 : switch (proto) {
212 : case OpenPGP:
213 0 : if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
214 0 : gpgme_release(ctx);
215 0 : return 0;
216 : }
217 0 : break;
218 : case CMS:
219 0 : if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
220 0 : gpgme_release(ctx);
221 0 : return 0;
222 : }
223 0 : break;
224 : default:
225 0 : return 0;
226 : }
227 :
228 0 : return new Context(ctx);
229 : }
230 :
231 0 : std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
232 : {
233 0 : gpgme_ctx_t ctx = 0;
234 0 : if (const gpgme_error_t err = gpgme_new(&ctx)) {
235 0 : if (error) {
236 0 : *error = Error(err);
237 : }
238 0 : return std::unique_ptr<Context>();
239 : }
240 :
241 0 : switch (eng) {
242 : case AssuanEngine:
243 0 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
244 0 : gpgme_release(ctx);
245 0 : if (error) {
246 0 : *error = Error(err);
247 : }
248 0 : return std::unique_ptr<Context>();
249 : }
250 0 : break;
251 : case G13Engine:
252 0 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
253 0 : gpgme_release(ctx);
254 0 : if (error) {
255 0 : *error = Error(err);
256 : }
257 0 : return std::unique_ptr<Context>();
258 : }
259 0 : break;
260 : case SpawnEngine:
261 0 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
262 0 : gpgme_release(ctx);
263 0 : if (error) {
264 0 : *error = Error(err);
265 : }
266 0 : return std::unique_ptr<Context>();
267 : }
268 0 : break;
269 : default:
270 0 : if (error) {
271 0 : *error = Error::fromCode(GPG_ERR_INV_ARG);
272 : }
273 0 : return std::unique_ptr<Context>();
274 : }
275 :
276 0 : if (error) {
277 0 : *error = Error();
278 : }
279 :
280 0 : return std::unique_ptr<Context>(new Context(ctx));
281 : }
282 :
283 : //
284 : //
285 : // Context::Private
286 : //
287 : //
288 :
289 0 : Context::Private::Private(gpgme_ctx_t c)
290 : : ctx(c),
291 : iocbs(0),
292 : lastop(None),
293 : lasterr(GPG_ERR_NO_ERROR),
294 : lastAssuanInquireData(Data::null),
295 : lastAssuanTransaction(),
296 : lastEditInteractor(),
297 0 : lastCardEditInteractor()
298 : {
299 :
300 0 : }
301 :
302 0 : Context::Private::~Private()
303 : {
304 0 : if (ctx) {
305 0 : gpgme_release(ctx);
306 : }
307 0 : ctx = 0;
308 0 : delete iocbs;
309 0 : }
310 :
311 : //
312 : //
313 : // Context attributes:
314 : //
315 : //
316 :
317 0 : Protocol Context::protocol() const
318 : {
319 0 : gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
320 0 : switch (p) {
321 0 : case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
322 0 : case GPGME_PROTOCOL_CMS: return CMS;
323 0 : default: return UnknownProtocol;
324 : }
325 : }
326 :
327 0 : void Context::setArmor(bool useArmor)
328 : {
329 0 : gpgme_set_armor(d->ctx, int(useArmor));
330 0 : }
331 0 : bool Context::armor() const
332 : {
333 0 : return gpgme_get_armor(d->ctx);
334 : }
335 :
336 0 : void Context::setTextMode(bool useTextMode)
337 : {
338 0 : gpgme_set_textmode(d->ctx, int(useTextMode));
339 0 : }
340 0 : bool Context::textMode() const
341 : {
342 0 : return gpgme_get_textmode(d->ctx);
343 : }
344 :
345 0 : void Context::setOffline(bool useOfflineMode)
346 : {
347 0 : gpgme_set_offline(d->ctx, int(useOfflineMode));
348 0 : }
349 0 : bool Context::offline() const
350 : {
351 0 : return gpgme_get_offline(d->ctx);
352 : }
353 :
354 0 : void Context::setIncludeCertificates(int which)
355 : {
356 0 : if (which == DefaultCertificates) {
357 0 : which = GPGME_INCLUDE_CERTS_DEFAULT;
358 : }
359 0 : gpgme_set_include_certs(d->ctx, which);
360 0 : }
361 :
362 0 : int Context::includeCertificates() const
363 : {
364 0 : return gpgme_get_include_certs(d->ctx);
365 : }
366 :
367 0 : void Context::setKeyListMode(unsigned int mode)
368 : {
369 0 : gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
370 0 : }
371 :
372 0 : void Context::addKeyListMode(unsigned int mode)
373 : {
374 0 : const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
375 0 : gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
376 0 : }
377 :
378 0 : unsigned int Context::keyListMode() const
379 : {
380 0 : return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
381 : }
382 :
383 0 : void Context::setProgressProvider(ProgressProvider *provider)
384 : {
385 0 : gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
386 0 : }
387 0 : ProgressProvider *Context::progressProvider() const
388 : {
389 0 : void *pp = 0;
390 0 : gpgme_progress_cb_t pcb = &progress_callback;
391 0 : gpgme_get_progress_cb(d->ctx, &pcb, &pp);
392 0 : return static_cast<ProgressProvider *>(pp);
393 : }
394 :
395 0 : void Context::setPassphraseProvider(PassphraseProvider *provider)
396 : {
397 0 : gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
398 0 : }
399 :
400 0 : PassphraseProvider *Context::passphraseProvider() const
401 : {
402 0 : void *pp = 0;
403 0 : gpgme_passphrase_cb_t pcb = &passphrase_callback;
404 0 : gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
405 0 : return static_cast<PassphraseProvider *>(pp);
406 : }
407 :
408 0 : void Context::setManagedByEventLoopInteractor(bool manage)
409 : {
410 0 : if (!EventLoopInteractor::instance()) {
411 : #ifndef NDEBUG
412 : cerr << "Context::setManagedByEventLoopInteractor(): "
413 : "You must create an instance of EventLoopInteractor "
414 0 : "before using anything that needs one." << endl;
415 : #endif
416 0 : return;
417 : }
418 0 : if (manage) {
419 0 : EventLoopInteractor::instance()->manage(this);
420 : } else {
421 0 : EventLoopInteractor::instance()->unmanage(this);
422 : }
423 : }
424 0 : bool Context::managedByEventLoopInteractor() const
425 : {
426 0 : return d->iocbs != 0;
427 : }
428 :
429 0 : void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
430 : {
431 0 : if (!iocbs) {
432 0 : uninstallIOCallbacks();
433 0 : return;
434 : }
435 0 : gpgme_set_io_cbs(d->ctx, iocbs);
436 0 : delete d->iocbs; d->iocbs = iocbs;
437 : }
438 :
439 0 : void Context::uninstallIOCallbacks()
440 : {
441 : static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
442 : // io.add == 0 means disable io callbacks:
443 0 : gpgme_set_io_cbs(d->ctx, &noiocbs);
444 0 : delete d->iocbs; d->iocbs = 0;
445 0 : }
446 :
447 0 : Error Context::setLocale(int cat, const char *val)
448 : {
449 0 : return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
450 : }
451 :
452 0 : EngineInfo Context::engineInfo() const
453 : {
454 0 : return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
455 : }
456 :
457 0 : Error Context::setEngineFileName(const char *filename)
458 : {
459 0 : const char *const home_dir = engineInfo().homeDirectory();
460 0 : return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
461 : }
462 :
463 0 : Error Context::setEngineHomeDirectory(const char *home_dir)
464 : {
465 0 : const char *const filename = engineInfo().fileName();
466 0 : return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
467 : }
468 :
469 0 : Error Context::setSender (const char *sender)
470 : {
471 0 : return Error(gpgme_set_sender(d->ctx, sender));
472 : }
473 :
474 0 : const char *Context::getSender ()
475 : {
476 0 : return gpgme_get_sender(d->ctx);
477 : }
478 :
479 : //
480 : //
481 : // Key Management
482 : //
483 : //
484 :
485 0 : Error Context::startKeyListing(const char *pattern, bool secretOnly)
486 : {
487 0 : d->lastop = Private::KeyList;
488 0 : return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
489 : }
490 :
491 0 : Error Context::startKeyListing(const char *patterns[], bool secretOnly)
492 : {
493 0 : d->lastop = Private::KeyList;
494 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
495 0 : if (!patterns || !patterns[0] || !patterns[1]) {
496 : // max. one pattern -> use the non-ext version
497 0 : return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
498 : }
499 : #endif
500 0 : return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
501 : }
502 :
503 0 : Key Context::nextKey(GpgME::Error &e)
504 : {
505 0 : d->lastop = Private::KeyList;
506 : gpgme_key_t key;
507 0 : e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
508 0 : return Key(key, false);
509 : }
510 :
511 0 : KeyListResult Context::endKeyListing()
512 : {
513 0 : d->lasterr = gpgme_op_keylist_end(d->ctx);
514 0 : return keyListResult();
515 : }
516 :
517 0 : KeyListResult Context::keyListResult() const
518 : {
519 0 : return KeyListResult(d->ctx, Error(d->lasterr));
520 : }
521 :
522 0 : Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
523 : {
524 0 : d->lastop = Private::KeyList;
525 : gpgme_key_t key;
526 0 : e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
527 0 : return Key(key, false);
528 : }
529 :
530 0 : KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
531 : {
532 0 : d->lastop = Private::KeyGen;
533 0 : Data::Private *const dp = pubKey.impl();
534 0 : d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
535 0 : return KeyGenerationResult(d->ctx, Error(d->lasterr));
536 : }
537 :
538 0 : Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
539 : {
540 0 : d->lastop = Private::KeyGen;
541 0 : Data::Private *const dp = pubKey.impl();
542 0 : return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
543 : }
544 :
545 0 : KeyGenerationResult Context::keyGenerationResult() const
546 : {
547 0 : if (d->lastop & Private::KeyGen) {
548 0 : return KeyGenerationResult(d->ctx, Error(d->lasterr));
549 : } else {
550 0 : return KeyGenerationResult();
551 : }
552 : }
553 :
554 0 : Error Context::exportPublicKeys(const char *pattern, Data &keyData)
555 : {
556 0 : d->lastop = Private::Export;
557 0 : Data::Private *const dp = keyData.impl();
558 0 : return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
559 : }
560 :
561 0 : Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
562 : {
563 0 : d->lastop = Private::Export;
564 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
565 0 : if (!patterns || !patterns[0] || !patterns[1]) {
566 : // max. one pattern -> use the non-ext version
567 0 : return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
568 : }
569 : #endif
570 0 : Data::Private *const dp = keyData.impl();
571 0 : return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
572 : }
573 :
574 0 : Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
575 : {
576 0 : d->lastop = Private::Export;
577 0 : Data::Private *const dp = keyData.impl();
578 0 : return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
579 : }
580 :
581 0 : Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
582 : {
583 0 : d->lastop = Private::Export;
584 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
585 0 : if (!patterns || !patterns[0] || !patterns[1]) {
586 : // max. one pattern -> use the non-ext version
587 0 : return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
588 : }
589 : #endif
590 0 : Data::Private *const dp = keyData.impl();
591 0 : return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
592 : }
593 :
594 0 : ImportResult Context::importKeys(const Data &data)
595 : {
596 0 : d->lastop = Private::Import;
597 0 : const Data::Private *const dp = data.impl();
598 0 : d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
599 0 : return ImportResult(d->ctx, Error(d->lasterr));
600 : }
601 :
602 0 : ImportResult Context::importKeys(const std::vector<Key> &kk)
603 : {
604 0 : d->lastop = Private::Import;
605 0 : d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
606 :
607 0 : bool shouldHaveResult = false;
608 0 : gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
609 0 : gpgme_key_t *keys_it = &keys[0];
610 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
611 0 : if (it->impl()) {
612 0 : *keys_it++ = it->impl();
613 : }
614 : }
615 0 : *keys_it++ = 0;
616 0 : d->lasterr = gpgme_op_import_keys(d->ctx, keys);
617 0 : shouldHaveResult = true;
618 0 : if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
619 0 : gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
620 0 : protocol() == CMS) {
621 : // ok, try the workaround (export+import):
622 0 : std::vector<const char *> fprs;
623 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
624 0 : if (const char *fpr = it->primaryFingerprint()) {
625 0 : if (*fpr) {
626 0 : fprs.push_back(fpr);
627 : }
628 0 : } else if (const char *keyid = it->keyID()) {
629 0 : if (*keyid) {
630 0 : fprs.push_back(keyid);
631 : }
632 : }
633 : }
634 0 : fprs.push_back(0);
635 0 : Data data;
636 0 : Data::Private *const dp = data.impl();
637 0 : const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
638 0 : gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
639 0 : d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
640 0 : gpgme_set_keylist_mode(d->ctx, oldMode);
641 0 : if (!d->lasterr) {
642 0 : data.seek(0, SEEK_SET);
643 0 : d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
644 0 : shouldHaveResult = true;
645 : }
646 : }
647 0 : delete[] keys;
648 0 : if (shouldHaveResult) {
649 0 : return ImportResult(d->ctx, Error(d->lasterr));
650 : } else {
651 0 : return ImportResult(Error(d->lasterr));
652 : }
653 : }
654 :
655 0 : Error Context::startKeyImport(const Data &data)
656 : {
657 0 : d->lastop = Private::Import;
658 0 : const Data::Private *const dp = data.impl();
659 0 : return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
660 : }
661 :
662 0 : Error Context::startKeyImport(const std::vector<Key> &kk)
663 : {
664 0 : d->lastop = Private::Import;
665 0 : gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
666 0 : gpgme_key_t *keys_it = &keys[0];
667 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
668 0 : if (it->impl()) {
669 0 : *keys_it++ = it->impl();
670 : }
671 : }
672 0 : *keys_it++ = 0;
673 0 : Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
674 0 : delete[] keys;
675 0 : return err;
676 : }
677 :
678 0 : ImportResult Context::importResult() const
679 : {
680 0 : if (d->lastop & Private::Import) {
681 0 : return ImportResult(d->ctx, Error(d->lasterr));
682 : } else {
683 0 : return ImportResult();
684 : }
685 : }
686 :
687 0 : Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
688 : {
689 0 : d->lastop = Private::Delete;
690 0 : return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
691 : }
692 :
693 0 : Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
694 : {
695 0 : d->lastop = Private::Delete;
696 0 : return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
697 : }
698 :
699 0 : Error Context::passwd(const Key &key)
700 : {
701 0 : d->lastop = Private::Passwd;
702 0 : return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
703 : }
704 :
705 0 : Error Context::startPasswd(const Key &key)
706 : {
707 0 : d->lastop = Private::Passwd;
708 0 : return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
709 : }
710 :
711 :
712 : #pragma GCC diagnostic push
713 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
714 :
715 0 : Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
716 : {
717 0 : d->lastop = Private::Edit;
718 0 : d->lastEditInteractor = std::move(func);
719 0 : Data::Private *const dp = data.impl();
720 0 : return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
721 0 : d->lastEditInteractor.get() ? edit_interactor_callback : 0,
722 0 : d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
723 0 : dp ? dp->data : 0));
724 : }
725 :
726 :
727 0 : Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
728 : {
729 0 : d->lastop = Private::Edit;
730 0 : d->lastEditInteractor = std::move(func);
731 0 : Data::Private *const dp = data.impl();
732 0 : return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
733 0 : d->lastEditInteractor.get() ? edit_interactor_callback : 0,
734 0 : d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
735 0 : dp ? dp->data : 0));
736 : }
737 :
738 :
739 0 : EditInteractor *Context::lastEditInteractor() const
740 : {
741 0 : return d->lastEditInteractor.get();
742 : }
743 :
744 0 : std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
745 : {
746 0 : return std::move(d->lastEditInteractor);
747 : }
748 :
749 :
750 0 : Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
751 : {
752 0 : d->lastop = Private::CardEdit;
753 0 : d->lastCardEditInteractor = std::move(func);
754 0 : Data::Private *const dp = data.impl();
755 0 : return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
756 0 : d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
757 0 : d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
758 0 : dp ? dp->data : 0));
759 : }
760 :
761 0 : Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
762 : {
763 0 : d->lastop = Private::CardEdit;
764 0 : d->lastCardEditInteractor = std::move(func);
765 0 : Data::Private *const dp = data.impl();
766 0 : return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
767 0 : d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
768 0 : d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
769 0 : dp ? dp->data : 0));
770 : }
771 :
772 : #pragma GCC diagnostic pop
773 :
774 0 : EditInteractor *Context::lastCardEditInteractor() const
775 : {
776 0 : return d->lastCardEditInteractor.get();
777 : }
778 :
779 0 : std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
780 : {
781 0 : return std::move(d->lastCardEditInteractor);
782 : }
783 :
784 0 : Error Context::startTrustItemListing(const char *pattern, int maxLevel)
785 : {
786 0 : d->lastop = Private::TrustList;
787 0 : return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
788 : }
789 :
790 0 : TrustItem Context::nextTrustItem(Error &e)
791 : {
792 0 : gpgme_trust_item_t ti = 0;
793 0 : e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
794 0 : return TrustItem(ti);
795 : }
796 :
797 0 : Error Context::endTrustItemListing()
798 : {
799 0 : return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
800 : }
801 :
802 0 : static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
803 : {
804 0 : assert(opaque);
805 0 : AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
806 0 : return t->data(static_cast<const char *>(data), datalen).encodedError();
807 : }
808 :
809 0 : static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
810 : {
811 0 : assert(opaque);
812 0 : Context::Private *p = static_cast<Context::Private *>(opaque);
813 0 : AssuanTransaction *t = p->lastAssuanTransaction.get();
814 0 : assert(t);
815 0 : Error err;
816 0 : if (name) {
817 0 : p->lastAssuanInquireData = t->inquire(name, args, err);
818 : } else {
819 0 : p->lastAssuanInquireData = Data::null;
820 : }
821 0 : if (!p->lastAssuanInquireData.isNull()) {
822 0 : *r_data = p->lastAssuanInquireData.impl()->data;
823 : }
824 0 : return err.encodedError();
825 : }
826 :
827 0 : static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
828 : {
829 0 : assert(opaque);
830 0 : AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
831 0 : std::string a = args;
832 0 : percent_unescape(a, true); // ### why doesn't gpgme do this??
833 0 : return t->status(status, a.c_str()).encodedError();
834 : }
835 :
836 0 : Error Context::assuanTransact(const char *command)
837 : {
838 0 : return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
839 : }
840 :
841 0 : Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
842 : {
843 : gpgme_error_t err, operr;
844 :
845 0 : d->lastop = Private::AssuanTransact;
846 0 : d->lastAssuanTransaction = std::move(transaction);
847 0 : if (!d->lastAssuanTransaction.get()) {
848 0 : return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
849 : }
850 : err = gpgme_op_assuan_transact_ext
851 0 : (d->ctx,
852 : command,
853 : assuan_transaction_data_callback,
854 0 : d->lastAssuanTransaction.get(),
855 : assuan_transaction_inquire_callback,
856 0 : d,
857 : assuan_transaction_status_callback,
858 0 : d->lastAssuanTransaction.get(),
859 0 : &operr);
860 :
861 0 : if (!err)
862 0 : err = operr;
863 0 : d->lasterr = err;
864 :
865 0 : return Error(d->lasterr);
866 : }
867 :
868 0 : Error Context::startAssuanTransaction(const char *command)
869 : {
870 0 : return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
871 : }
872 :
873 0 : Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
874 : {
875 : gpgme_error_t err;
876 :
877 0 : d->lastop = Private::AssuanTransact;
878 0 : d->lastAssuanTransaction = std::move(transaction);
879 0 : if (!d->lastAssuanTransaction.get()) {
880 0 : return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
881 : }
882 : err = gpgme_op_assuan_transact_start
883 0 : (d->ctx,
884 : command,
885 : assuan_transaction_data_callback,
886 0 : d->lastAssuanTransaction.get(),
887 : assuan_transaction_inquire_callback,
888 0 : d,
889 : assuan_transaction_status_callback,
890 0 : d->lastAssuanTransaction.get());
891 :
892 0 : d->lasterr = err;
893 :
894 0 : return Error(d->lasterr);
895 : }
896 :
897 0 : AssuanTransaction *Context::lastAssuanTransaction() const
898 : {
899 0 : return d->lastAssuanTransaction.get();
900 : }
901 :
902 0 : std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
903 : {
904 0 : return std::move(d->lastAssuanTransaction);
905 : }
906 :
907 0 : DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
908 : {
909 0 : d->lastop = Private::Decrypt;
910 0 : const Data::Private *const cdp = cipherText.impl();
911 0 : Data::Private *const pdp = plainText.impl();
912 0 : d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
913 0 : return DecryptionResult(d->ctx, Error(d->lasterr));
914 : }
915 :
916 0 : Error Context::startDecryption(const Data &cipherText, Data &plainText)
917 : {
918 0 : d->lastop = Private::Decrypt;
919 0 : const Data::Private *const cdp = cipherText.impl();
920 0 : Data::Private *const pdp = plainText.impl();
921 0 : return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
922 : }
923 :
924 0 : DecryptionResult Context::decryptionResult() const
925 : {
926 0 : if (d->lastop & Private::Decrypt) {
927 0 : return DecryptionResult(d->ctx, Error(d->lasterr));
928 : } else {
929 0 : return DecryptionResult();
930 : }
931 : }
932 :
933 0 : VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
934 : {
935 0 : d->lastop = Private::Verify;
936 0 : const Data::Private *const sdp = signature.impl();
937 0 : const Data::Private *const tdp = signedText.impl();
938 0 : d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
939 0 : return VerificationResult(d->ctx, Error(d->lasterr));
940 : }
941 :
942 0 : VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
943 : {
944 0 : d->lastop = Private::Verify;
945 0 : const Data::Private *const sdp = signedData.impl();
946 0 : Data::Private *const pdp = plainText.impl();
947 0 : d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
948 0 : return VerificationResult(d->ctx, Error(d->lasterr));
949 : }
950 :
951 0 : Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
952 : {
953 0 : d->lastop = Private::Verify;
954 0 : const Data::Private *const sdp = signature.impl();
955 0 : const Data::Private *const tdp = signedText.impl();
956 0 : return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
957 : }
958 :
959 0 : Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
960 : {
961 0 : d->lastop = Private::Verify;
962 0 : const Data::Private *const sdp = signedData.impl();
963 0 : Data::Private *const pdp = plainText.impl();
964 0 : return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
965 : }
966 :
967 0 : VerificationResult Context::verificationResult() const
968 : {
969 0 : if (d->lastop & Private::Verify) {
970 0 : return VerificationResult(d->ctx, Error(d->lasterr));
971 : } else {
972 0 : return VerificationResult();
973 : }
974 : }
975 :
976 0 : std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
977 : {
978 0 : d->lastop = Private::DecryptAndVerify;
979 0 : const Data::Private *const cdp = cipherText.impl();
980 0 : Data::Private *const pdp = plainText.impl();
981 0 : d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
982 0 : return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
983 0 : VerificationResult(d->ctx, Error(d->lasterr)));
984 : }
985 :
986 0 : Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
987 : {
988 0 : d->lastop = Private::DecryptAndVerify;
989 0 : const Data::Private *const cdp = cipherText.impl();
990 0 : Data::Private *const pdp = plainText.impl();
991 0 : return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
992 : }
993 :
994 0 : unsigned int to_auditlog_flags(unsigned int flags)
995 : {
996 0 : unsigned int result = 0;
997 0 : if (flags & Context::HtmlAuditLog) {
998 0 : result |= GPGME_AUDITLOG_HTML;
999 : }
1000 0 : if (flags & Context::AuditLogWithHelp) {
1001 0 : result |= GPGME_AUDITLOG_WITH_HELP;
1002 : }
1003 0 : return result;
1004 : }
1005 :
1006 0 : Error Context::startGetAuditLog(Data &output, unsigned int flags)
1007 : {
1008 0 : d->lastop = Private::GetAuditLog;
1009 0 : Data::Private *const odp = output.impl();
1010 0 : return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1011 : }
1012 :
1013 0 : Error Context::getAuditLog(Data &output, unsigned int flags)
1014 : {
1015 0 : d->lastop = Private::GetAuditLog;
1016 0 : Data::Private *const odp = output.impl();
1017 0 : return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1018 : }
1019 :
1020 0 : void Context::clearSigningKeys()
1021 : {
1022 0 : gpgme_signers_clear(d->ctx);
1023 0 : }
1024 :
1025 0 : Error Context::addSigningKey(const Key &key)
1026 : {
1027 0 : return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1028 : }
1029 :
1030 0 : Key Context::signingKey(unsigned int idx) const
1031 : {
1032 0 : gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1033 0 : return Key(key, false);
1034 : }
1035 :
1036 0 : std::vector<Key> Context::signingKeys() const
1037 : {
1038 0 : std::vector<Key> result;
1039 : gpgme_key_t key;
1040 0 : for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1041 0 : result.push_back(Key(key, false));
1042 : }
1043 0 : return result;
1044 : }
1045 :
1046 0 : void Context::clearSignatureNotations()
1047 : {
1048 0 : gpgme_sig_notation_clear(d->ctx);
1049 0 : }
1050 :
1051 0 : GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1052 : {
1053 0 : return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1054 : }
1055 :
1056 0 : GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1057 : {
1058 0 : return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1059 : }
1060 :
1061 0 : const char *Context::signaturePolicyURL() const
1062 : {
1063 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1064 0 : if (!n->name) {
1065 0 : return n->value;
1066 : }
1067 : }
1068 0 : return nullptr;
1069 : }
1070 :
1071 0 : Notation Context::signatureNotation(unsigned int idx) const
1072 : {
1073 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1074 0 : if (n->name) {
1075 0 : if (idx-- == 0) {
1076 0 : return Notation(n);
1077 : }
1078 : }
1079 : }
1080 0 : return Notation();
1081 : }
1082 :
1083 0 : std::vector<Notation> Context::signatureNotations() const
1084 : {
1085 0 : std::vector<Notation> result;
1086 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1087 0 : if (n->name) {
1088 0 : result.push_back(Notation(n));
1089 : }
1090 : }
1091 0 : return result;
1092 : }
1093 :
1094 0 : static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1095 : {
1096 0 : switch (mode) {
1097 : default:
1098 0 : case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1099 0 : case Detached: return GPGME_SIG_MODE_DETACH;
1100 0 : case Clearsigned: return GPGME_SIG_MODE_CLEAR;
1101 : }
1102 : }
1103 :
1104 0 : SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1105 : {
1106 0 : d->lastop = Private::Sign;
1107 0 : const Data::Private *const pdp = plainText.impl();
1108 0 : Data::Private *const sdp = signature.impl();
1109 0 : d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
1110 0 : return SigningResult(d->ctx, Error(d->lasterr));
1111 : }
1112 :
1113 0 : Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1114 : {
1115 0 : d->lastop = Private::Sign;
1116 0 : const Data::Private *const pdp = plainText.impl();
1117 0 : Data::Private *const sdp = signature.impl();
1118 0 : return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
1119 : }
1120 :
1121 0 : SigningResult Context::signingResult() const
1122 : {
1123 0 : if (d->lastop & Private::Sign) {
1124 0 : return SigningResult(d->ctx, Error(d->lasterr));
1125 : } else {
1126 0 : return SigningResult();
1127 : }
1128 : }
1129 :
1130 0 : static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1131 : {
1132 0 : unsigned int result = 0;
1133 0 : if (flags & Context::AlwaysTrust) {
1134 0 : result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1135 : }
1136 0 : if (flags & Context::NoEncryptTo) {
1137 0 : result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1138 : }
1139 0 : if (flags & Context::Prepare) {
1140 0 : result |= GPGME_ENCRYPT_PREPARE;
1141 : }
1142 0 : if (flags & Context::ExpectSign) {
1143 0 : result |= GPGME_ENCRYPT_EXPECT_SIGN;
1144 : }
1145 0 : if (flags & Context::NoCompress) {
1146 0 : result |= GPGME_ENCRYPT_NO_COMPRESS;
1147 : }
1148 0 : if (flags & Context::Symmetric) {
1149 0 : result |= GPGME_ENCRYPT_SYMMETRIC;
1150 : }
1151 0 : return static_cast<gpgme_encrypt_flags_t>(result);
1152 : }
1153 :
1154 0 : gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1155 : {
1156 0 : if (recipients.empty()) {
1157 0 : return nullptr;
1158 : }
1159 0 : gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1160 0 : gpgme_key_t *keys_it = ret;
1161 0 : for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1162 0 : if (it->impl()) {
1163 0 : *keys_it++ = it->impl();
1164 : }
1165 : }
1166 0 : *keys_it++ = 0;
1167 0 : return ret;
1168 : }
1169 :
1170 0 : EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1171 : {
1172 0 : d->lastop = Private::Encrypt;
1173 0 : if (flags & NoEncryptTo) {
1174 0 : return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1175 : }
1176 0 : const Data::Private *const pdp = plainText.impl();
1177 0 : Data::Private *const cdp = cipherText.impl();
1178 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1179 0 : d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1180 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1181 0 : if (keys) {
1182 0 : delete[] keys;
1183 : }
1184 0 : return EncryptionResult(d->ctx, Error(d->lasterr));
1185 : }
1186 :
1187 0 : Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1188 : {
1189 0 : d->lastop = Private::Encrypt;
1190 0 : const Data::Private *const pdp = plainText.impl();
1191 0 : Data::Private *const cdp = cipherText.impl();
1192 0 : return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
1193 0 : pdp ? pdp->data : 0, cdp ? cdp->data : 0));
1194 : }
1195 :
1196 0 : Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1197 : {
1198 0 : d->lastop = Private::Encrypt;
1199 0 : if (flags & NoEncryptTo) {
1200 0 : return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1201 : }
1202 0 : const Data::Private *const pdp = plainText.impl();
1203 0 : Data::Private *const cdp = cipherText.impl();
1204 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1205 0 : d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1206 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1207 0 : if (keys) {
1208 0 : delete[] keys;
1209 : }
1210 0 : return Error(d->lasterr);
1211 : }
1212 :
1213 0 : EncryptionResult Context::encryptionResult() const
1214 : {
1215 0 : if (d->lastop & Private::Encrypt) {
1216 0 : return EncryptionResult(d->ctx, Error(d->lasterr));
1217 : } else {
1218 0 : return EncryptionResult();
1219 : }
1220 : }
1221 :
1222 0 : std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1223 : {
1224 0 : d->lastop = Private::SignAndEncrypt;
1225 0 : const Data::Private *const pdp = plainText.impl();
1226 0 : Data::Private *const cdp = cipherText.impl();
1227 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1228 0 : d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1229 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1230 0 : if (keys) {
1231 0 : delete[] keys;
1232 : }
1233 0 : return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1234 0 : EncryptionResult(d->ctx, Error(d->lasterr)));
1235 : }
1236 :
1237 0 : Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1238 : {
1239 0 : d->lastop = Private::SignAndEncrypt;
1240 0 : const Data::Private *const pdp = plainText.impl();
1241 0 : Data::Private *const cdp = cipherText.impl();
1242 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1243 0 : d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1244 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1245 0 : if (keys) {
1246 0 : delete[] keys;
1247 : }
1248 0 : return Error(d->lasterr);
1249 : }
1250 :
1251 0 : Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1252 : {
1253 0 : d->lastop = Private::CreateVFS;
1254 0 : gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1255 0 : gpgme_key_t *keys_it = keys;
1256 0 : for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1257 0 : if (it->impl()) {
1258 0 : *keys_it++ = it->impl();
1259 : }
1260 : }
1261 0 : *keys_it++ = 0;
1262 :
1263 : gpgme_error_t op_err;
1264 0 : d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1265 0 : delete[] keys;
1266 0 : Error error(d->lasterr);
1267 0 : if (error) {
1268 0 : return error;
1269 : }
1270 0 : return Error(d->lasterr = op_err);
1271 : }
1272 :
1273 0 : VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1274 : {
1275 0 : d->lastop = Private::MountVFS;
1276 : gpgme_error_t op_err;
1277 0 : d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1278 0 : return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1279 : }
1280 :
1281 0 : Error Context::cancelPendingOperation()
1282 : {
1283 0 : return Error(gpgme_cancel_async(d->ctx));
1284 : }
1285 :
1286 0 : bool Context::poll()
1287 : {
1288 0 : gpgme_error_t e = GPG_ERR_NO_ERROR;
1289 0 : const bool finished = gpgme_wait(d->ctx, &e, 0);
1290 0 : if (finished) {
1291 0 : d->lasterr = e;
1292 : }
1293 0 : return finished;
1294 : }
1295 :
1296 0 : Error Context::wait()
1297 : {
1298 0 : gpgme_error_t e = GPG_ERR_NO_ERROR;
1299 0 : gpgme_wait(d->ctx, &e, 1);
1300 0 : return Error(d->lasterr = e);
1301 : }
1302 :
1303 0 : Error Context::lastError() const
1304 : {
1305 0 : return Error(d->lasterr);
1306 : }
1307 :
1308 0 : Context::PinentryMode Context::pinentryMode() const
1309 : {
1310 0 : switch (gpgme_get_pinentry_mode (d->ctx)) {
1311 : case GPGME_PINENTRY_MODE_ASK:
1312 0 : return PinentryAsk;
1313 : case GPGME_PINENTRY_MODE_CANCEL:
1314 0 : return PinentryCancel;
1315 : case GPGME_PINENTRY_MODE_ERROR:
1316 0 : return PinentryError;
1317 : case GPGME_PINENTRY_MODE_LOOPBACK:
1318 0 : return PinentryLoopback;
1319 : case GPGME_PINENTRY_MODE_DEFAULT:
1320 : default:
1321 0 : return PinentryDefault;
1322 : }
1323 : }
1324 :
1325 0 : Error Context::setPinentryMode(PinentryMode which)
1326 : {
1327 : gpgme_pinentry_mode_t mode;
1328 0 : switch (which) {
1329 : case PinentryAsk:
1330 0 : mode = GPGME_PINENTRY_MODE_ASK;
1331 0 : break;
1332 : case PinentryCancel:
1333 0 : mode = GPGME_PINENTRY_MODE_CANCEL;
1334 0 : break;
1335 : case PinentryError:
1336 0 : mode = GPGME_PINENTRY_MODE_ERROR;
1337 0 : break;
1338 : case PinentryLoopback:
1339 0 : mode = GPGME_PINENTRY_MODE_LOOPBACK;
1340 0 : break;
1341 : case PinentryDefault:
1342 : default:
1343 0 : mode = GPGME_PINENTRY_MODE_DEFAULT;
1344 : }
1345 0 : return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1346 : }
1347 :
1348 0 : static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
1349 : {
1350 0 : switch (policy) {
1351 : case TofuInfo::PolicyNone:
1352 0 : return GPGME_TOFU_POLICY_NONE;
1353 : case TofuInfo::PolicyAuto:
1354 0 : return GPGME_TOFU_POLICY_AUTO;
1355 : case TofuInfo::PolicyGood:
1356 0 : return GPGME_TOFU_POLICY_GOOD;
1357 : case TofuInfo::PolicyBad:
1358 0 : return GPGME_TOFU_POLICY_BAD;
1359 : case TofuInfo::PolicyAsk:
1360 0 : return GPGME_TOFU_POLICY_ASK;
1361 : case TofuInfo::PolicyUnknown:
1362 : default:
1363 0 : return GPGME_TOFU_POLICY_UNKNOWN;
1364 : }
1365 : }
1366 :
1367 0 : Error Context::setTofuPolicy(const Key &k, unsigned int policy)
1368 : {
1369 0 : return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
1370 0 : k.impl(), to_tofu_policy_t(policy)));
1371 : }
1372 :
1373 0 : Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
1374 : {
1375 0 : return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
1376 0 : k.impl(), to_tofu_policy_t(policy)));
1377 : }
1378 :
1379 : // Engine Spawn stuff
1380 0 : Error Context::spawn(const char *file, const char *argv[],
1381 : Data &input, Data &output, Data &err,
1382 : SpawnFlags flags)
1383 : {
1384 0 : return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1385 0 : input.impl() ? input.impl()->data : nullptr,
1386 0 : output.impl() ? output.impl()->data : nullptr,
1387 0 : err.impl() ? err.impl()->data : nullptr,
1388 0 : static_cast<int>(flags)));
1389 : }
1390 :
1391 0 : Error Context::spawnAsync(const char *file, const char *argv[],
1392 : Data &input, Data &output, Data &err,
1393 : SpawnFlags flags)
1394 : {
1395 0 : return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1396 0 : input.impl() ? input.impl()->data : nullptr,
1397 0 : output.impl() ? output.impl()->data : nullptr,
1398 0 : err.impl() ? err.impl()->data : nullptr,
1399 0 : static_cast<int>(flags)));
1400 : }
1401 :
1402 0 : std::ostream &operator<<(std::ostream &os, Protocol proto)
1403 : {
1404 0 : os << "GpgME::Protocol(";
1405 0 : switch (proto) {
1406 : case OpenPGP:
1407 0 : os << "OpenPGP";
1408 0 : break;
1409 : case CMS:
1410 0 : os << "CMS";
1411 0 : break;
1412 : default:
1413 : case UnknownProtocol:
1414 0 : os << "UnknownProtocol";
1415 0 : break;
1416 : }
1417 0 : return os << ')';
1418 : }
1419 :
1420 0 : std::ostream &operator<<(std::ostream &os, Engine eng)
1421 : {
1422 0 : os << "GpgME::Engine(";
1423 0 : switch (eng) {
1424 : case GpgEngine:
1425 0 : os << "GpgEngine";
1426 0 : break;
1427 : case GpgSMEngine:
1428 0 : os << "GpgSMEngine";
1429 0 : break;
1430 : case GpgConfEngine:
1431 0 : os << "GpgConfEngine";
1432 0 : break;
1433 : case AssuanEngine:
1434 0 : os << "AssuanEngine";
1435 0 : break;
1436 : case SpawnEngine:
1437 0 : os << "SpawnEngine";
1438 0 : break;
1439 : default:
1440 : case UnknownEngine:
1441 0 : os << "UnknownEngine";
1442 0 : break;
1443 : }
1444 0 : return os << ')';
1445 : }
1446 :
1447 0 : std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1448 : {
1449 0 : os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1450 0 : switch (incl) {
1451 : case Context::DefaultCertificates:
1452 0 : os << "(DefaultCertificates)";
1453 0 : break;
1454 : case Context::AllCertificatesExceptRoot:
1455 0 : os << "(AllCertificatesExceptRoot)";
1456 0 : break;
1457 : case Context::AllCertificates:
1458 0 : os << "(AllCertificates)";
1459 0 : break;
1460 : case Context::NoCertificates:
1461 0 : os << "(NoCertificates)";
1462 0 : break;
1463 : case Context::OnlySenderCertificate:
1464 0 : os << "(OnlySenderCertificate)";
1465 0 : break;
1466 : }
1467 0 : return os << ')';
1468 : }
1469 :
1470 0 : std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1471 : {
1472 0 : os << "GpgME::KeyListMode(";
1473 : #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1474 0 : CHECK(Local);
1475 0 : CHECK(Extern);
1476 0 : CHECK(Signatures);
1477 0 : CHECK(Validate);
1478 0 : CHECK(Ephemeral);
1479 0 : CHECK(WithTofu);
1480 : #undef CHECK
1481 0 : return os << ')';
1482 : }
1483 :
1484 0 : std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1485 : {
1486 0 : os << "GpgME::SignatureMode(";
1487 0 : switch (mode) {
1488 : #define CHECK( x ) case x: os << #x; break
1489 0 : CHECK(NormalSignatureMode);
1490 0 : CHECK(Detached);
1491 0 : CHECK(Clearsigned);
1492 : #undef CHECK
1493 : default:
1494 0 : os << "???" "(" << static_cast<int>(mode) << ')';
1495 0 : break;
1496 : }
1497 0 : return os << ')';
1498 : }
1499 :
1500 0 : std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1501 : {
1502 0 : os << "GpgME::Context::EncryptionFlags(";
1503 : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1504 0 : CHECK(AlwaysTrust);
1505 0 : CHECK(NoEncryptTo);
1506 0 : CHECK(Prepare);
1507 0 : CHECK(ExpectSign);
1508 0 : CHECK(NoCompress);
1509 0 : CHECK(Symmetric);
1510 : #undef CHECK
1511 0 : return os << ')';
1512 : }
1513 :
1514 0 : std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1515 : {
1516 0 : os << "GpgME::Context::AuditLogFlags(";
1517 : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1518 0 : CHECK(HtmlAuditLog);
1519 0 : CHECK(AuditLogWithHelp);
1520 : #undef CHECK
1521 0 : return os << ')';
1522 : }
1523 :
1524 : } // namespace GpgME
1525 :
1526 0 : GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1527 : {
1528 0 : return Error(gpgme_set_locale(0, cat, val));
1529 : }
1530 :
1531 0 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1532 : {
1533 0 : gpgme_engine_info_t ei = 0;
1534 0 : if (gpgme_get_engine_info(&ei)) {
1535 0 : return EngineInfo();
1536 : }
1537 :
1538 0 : const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1539 :
1540 0 : for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1541 0 : if (i->protocol == p) {
1542 0 : return EngineInfo(i);
1543 : }
1544 : }
1545 :
1546 0 : return EngineInfo();
1547 : }
1548 :
1549 0 : const char *GpgME::dirInfo(const char *what)
1550 : {
1551 0 : return gpgme_get_dirinfo(what);
1552 : }
1553 :
1554 0 : GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1555 : {
1556 0 : const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1557 :
1558 0 : return Error(gpgme_engine_check_version(p));
1559 : }
1560 :
1561 : static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1562 :
1563 0 : static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1564 : {
1565 0 : switch (engine) {
1566 0 : case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
1567 0 : case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1568 : case GpgME::GpgConfEngine:
1569 0 : return GPGME_PROTOCOL_GPGCONF;
1570 : case GpgME::AssuanEngine:
1571 0 : return GPGME_PROTOCOL_ASSUAN;
1572 : case GpgME::G13Engine:
1573 0 : return GPGME_PROTOCOL_G13;
1574 : case GpgME::SpawnEngine:
1575 0 : return GPGME_PROTOCOL_SPAWN;
1576 : case GpgME::UnknownEngine:
1577 : ;
1578 : }
1579 0 : return UNKNOWN_PROTOCOL;
1580 : }
1581 :
1582 0 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1583 : {
1584 0 : gpgme_engine_info_t ei = 0;
1585 0 : if (gpgme_get_engine_info(&ei)) {
1586 0 : return EngineInfo();
1587 : }
1588 :
1589 0 : const gpgme_protocol_t p = engine2protocol(engine);
1590 :
1591 0 : for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1592 0 : if (i->protocol == p) {
1593 0 : return EngineInfo(i);
1594 : }
1595 : }
1596 :
1597 0 : return EngineInfo();
1598 : }
1599 :
1600 0 : GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1601 : {
1602 0 : const gpgme_protocol_t p = engine2protocol(engine);
1603 :
1604 0 : return Error(gpgme_engine_check_version(p));
1605 : }
1606 :
1607 : static const unsigned long supported_features = 0
1608 : | GpgME::ValidatingKeylistModeFeature
1609 : | GpgME::CancelOperationFeature
1610 : | GpgME::WrongKeyUsageFeature
1611 : | GpgME::DefaultCertificateInclusionFeature
1612 : | GpgME::GetSetEngineInfoFeature
1613 : | GpgME::ClearAddGetSignatureNotationsFeature
1614 : | GpgME::SetDataFileNameFeeature
1615 : | GpgME::SignatureNotationsKeylistModeFeature
1616 : | GpgME::KeySignatureNotationsFeature
1617 : | GpgME::KeyIsQualifiedFeature
1618 : | GpgME::SignatureNotationsCriticalFlagFeature
1619 : | GpgME::SignatureNotationsFlagsFeature
1620 : | GpgME::SignatureNotationsHumanReadableFlagFeature
1621 : | GpgME::SubkeyIsQualifiedFeature
1622 : | GpgME::EngineInfoHomeDirFeature
1623 : | GpgME::DecryptionResultFileNameFeature
1624 : | GpgME::DecryptionResultRecipientsFeature
1625 : | GpgME::VerificationResultFileNameFeature
1626 : | GpgME::SignaturePkaFieldsFeature
1627 : | GpgME::SignatureAlgorithmFieldsFeature
1628 : | GpgME::FdPointerFeature
1629 : | GpgME::AuditLogFeature
1630 : | GpgME::GpgConfEngineFeature
1631 : | GpgME::CancelOperationAsyncFeature
1632 : | GpgME::NoEncryptToEncryptionFlagFeature
1633 : | GpgME::CardKeyFeature
1634 : | GpgME::AssuanEngineFeature
1635 : | GpgME::EphemeralKeylistModeFeature
1636 : | GpgME::ImportFromKeyserverFeature
1637 : | GpgME::G13VFSFeature
1638 : | GpgME::PasswdFeature
1639 : ;
1640 :
1641 : static const unsigned long supported_features2 = 0
1642 : | GpgME::BinaryAndFineGrainedIdentify
1643 : ;
1644 :
1645 0 : bool GpgME::hasFeature(unsigned long features)
1646 : {
1647 0 : return features == (features & supported_features);
1648 : }
1649 :
1650 0 : bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1651 : {
1652 0 : return features == (features & supported_features)
1653 0 : && features2 == (features2 & supported_features2)
1654 : ;
1655 0 : }
|