Line data Source code
1 : /*
2 : decryptionresult.cpp - wraps a gpgme keygen result
3 : Copyright (C) 2004 Klarälvdalens Datakonsult AB
4 : 2016 Bundesamt für Sicherheit in der Informationstechnik
5 : Software engineering by Intevation GmbH
6 :
7 : This file is part of GPGME++.
8 :
9 : GPGME++ is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU Library General Public
11 : License as published by the Free Software Foundation; either
12 : version 2 of the License, or (at your option) any later version.
13 :
14 : GPGME++ is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Library General Public License for more details.
18 :
19 : You should have received a copy of the GNU Library General Public License
20 : along with GPGME++; see the file COPYING.LIB. If not, write to the
21 : Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 : Boston, MA 02110-1301, USA.
23 : */
24 :
25 : #ifdef HAVE_CONFIG_H
26 : #include "config.h"
27 : #endif
28 :
29 : #include <decryptionresult.h>
30 : #include "result_p.h"
31 : #include "util.h"
32 :
33 : #include <gpgme.h>
34 :
35 : #include <algorithm>
36 : #include <iterator>
37 : #include <cstring>
38 : #include <cstdlib>
39 : #include <istream>
40 :
41 : #include <string.h>
42 :
43 : class GpgME::DecryptionResult::Private
44 : {
45 : public:
46 3 : explicit Private(const _gpgme_op_decrypt_result &r) : res(r)
47 : {
48 3 : if (res.unsupported_algorithm) {
49 0 : res.unsupported_algorithm = strdup(res.unsupported_algorithm);
50 : }
51 3 : if (res.file_name) {
52 0 : res.file_name = strdup(res.file_name);
53 : }
54 3 : if (res.symkey_algo) {
55 3 : res.symkey_algo = strdup(res.symkey_algo);
56 : }
57 : //FIXME: copying gpgme_recipient_t objects invalidates the keyid member,
58 : //thus we use _keyid for now (internal API)
59 5 : for (gpgme_recipient_t r = res.recipients ; r ; r = r->next) {
60 2 : recipients.push_back(*r);
61 : }
62 3 : res.recipients = 0;
63 3 : }
64 3 : ~Private()
65 3 : {
66 3 : if (res.unsupported_algorithm) {
67 0 : std::free(res.unsupported_algorithm);
68 : }
69 3 : res.unsupported_algorithm = 0;
70 3 : if (res.file_name) {
71 0 : std::free(res.file_name);
72 : }
73 3 : res.file_name = 0;
74 3 : if (res.symkey_algo) {
75 3 : std::free(res.symkey_algo);
76 : }
77 3 : res.symkey_algo = 0;
78 3 : }
79 :
80 : _gpgme_op_decrypt_result res;
81 : std::vector<_gpgme_recipient> recipients;
82 : };
83 :
84 0 : GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, int error)
85 0 : : GpgME::Result(error), d()
86 : {
87 0 : init(ctx);
88 0 : }
89 :
90 3 : GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, const Error &error)
91 3 : : GpgME::Result(error), d()
92 : {
93 3 : init(ctx);
94 3 : }
95 :
96 3 : void GpgME::DecryptionResult::init(gpgme_ctx_t ctx)
97 : {
98 3 : if (!ctx) {
99 0 : return;
100 : }
101 3 : gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx);
102 3 : if (!res) {
103 0 : return;
104 : }
105 3 : d.reset(new Private(*res));
106 : }
107 :
108 6 : make_standard_stuff(DecryptionResult)
109 :
110 0 : const char *GpgME::DecryptionResult::unsupportedAlgorithm() const
111 : {
112 0 : return d ? d->res.unsupported_algorithm : 0 ;
113 : }
114 :
115 0 : bool GpgME::DecryptionResult::isWrongKeyUsage() const
116 : {
117 0 : return d && d->res.wrong_key_usage;
118 : }
119 :
120 0 : bool GpgME::DecryptionResult::isDeVs() const
121 : {
122 0 : return d && d->res.is_de_vs;
123 : }
124 :
125 0 : const char *GpgME::DecryptionResult::fileName() const
126 : {
127 0 : return d ? d->res.file_name : 0 ;
128 : }
129 :
130 0 : unsigned int GpgME::DecryptionResult::numRecipients() const
131 : {
132 0 : return d ? d->recipients.size() : 0 ;
133 : }
134 :
135 0 : GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient(unsigned int idx) const
136 : {
137 0 : if (d && idx < d->recipients.size()) {
138 0 : return Recipient(&d->recipients[idx]);
139 : }
140 0 : return Recipient();
141 : }
142 :
143 : namespace
144 : {
145 : struct make_recipient {
146 0 : GpgME::DecryptionResult::Recipient operator()(_gpgme_recipient &t)
147 : {
148 0 : return GpgME::DecryptionResult::Recipient(&t);
149 : }
150 : };
151 : }
152 :
153 0 : std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const
154 : {
155 0 : std::vector<Recipient> result;
156 0 : if (d) {
157 0 : result.reserve(d->recipients.size());
158 0 : std::transform(d->recipients.begin(), d->recipients.end(),
159 : std::back_inserter(result),
160 0 : make_recipient());
161 : }
162 0 : return result;
163 : }
164 :
165 0 : const char *GpgME::DecryptionResult::sessionKey() const
166 : {
167 0 : return d ? d->res.session_key : nullptr;
168 : }
169 :
170 0 : const char *GpgME::DecryptionResult::symkeyAlgo() const
171 : {
172 0 : return d ? d->res.symkey_algo : nullptr;
173 : }
174 :
175 0 : bool GpgME::DecryptionResult::isLegacyCipherNoMDC() const
176 : {
177 0 : return d && d->res.legacy_cipher_nomdc;
178 : }
179 :
180 : class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient
181 : {
182 : public:
183 0 : Private(gpgme_recipient_t reci) : _gpgme_recipient(*reci) {}
184 : };
185 :
186 0 : GpgME::DecryptionResult::Recipient::Recipient()
187 0 : : d()
188 : {
189 :
190 0 : }
191 :
192 0 : GpgME::DecryptionResult::Recipient::Recipient(gpgme_recipient_t r)
193 0 : : d()
194 : {
195 0 : if (r) {
196 0 : d.reset(new Private(r));
197 : }
198 0 : }
199 :
200 0 : bool GpgME::DecryptionResult::Recipient::isNull() const
201 : {
202 0 : return !d;
203 : }
204 :
205 0 : const char *GpgME::DecryptionResult::Recipient::keyID() const
206 : {
207 : //_keyid is internal API, but the public keyid is invalid after copying (see above)
208 0 : if (d) {
209 0 : return d->_keyid;
210 : }
211 0 : return 0;
212 : }
213 :
214 0 : const char *GpgME::DecryptionResult::Recipient::shortKeyID() const
215 : {
216 : //_keyid is internal API, but the public keyid is invalid after copying (see above)
217 0 : if (d) {
218 0 : return d->_keyid + 8;
219 : }
220 0 : return 0;
221 : }
222 :
223 0 : unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const
224 : {
225 0 : if (d) {
226 0 : return d->pubkey_algo;
227 : }
228 0 : return 0;
229 : }
230 :
231 0 : const char *GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const
232 : {
233 0 : if (d) {
234 0 : return gpgme_pubkey_algo_name(d->pubkey_algo);
235 : }
236 0 : return 0;
237 : }
238 :
239 0 : GpgME::Error GpgME::DecryptionResult::Recipient::status() const
240 : {
241 0 : if (d) {
242 0 : return Error(d->status);
243 : }
244 0 : return Error();
245 : }
246 :
247 0 : std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result)
248 : {
249 0 : os << "GpgME::DecryptionResult(";
250 0 : if (!result.isNull()) {
251 0 : os << "\n error: " << result.error()
252 : << "\n fileName: " << protect(result.fileName())
253 : << "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm())
254 0 : << "\n isWrongKeyUsage: " << result.isWrongKeyUsage()
255 0 : << "\n isDeVs " << result.isDeVs()
256 0 : << "\n legacyCipherNoMDC " << result.isLegacyCipherNoMDC()
257 : << "\n symkeyAlgo: " << protect(result.symkeyAlgo())
258 0 : << "\n recipients:\n";
259 0 : const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
260 : std::copy(recipients.begin(), recipients.end(),
261 0 : std::ostream_iterator<DecryptionResult::Recipient>(os, "\n"));
262 : }
263 0 : return os << ')';
264 : }
265 :
266 0 : std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult::Recipient &reci)
267 : {
268 0 : os << "GpgME::DecryptionResult::Recipient(";
269 0 : if (!reci.isNull()) {
270 : os << "\n keyID: " << protect(reci.keyID())
271 : << "\n shortKeyID: " << protect(reci.shortKeyID())
272 : << "\n publicKeyAlgorithm: " << protect(reci.publicKeyAlgorithmAsString())
273 0 : << "\n status: " << reci.status();
274 : }
275 0 : return os << ')';
276 24 : }
|