Line data Source code
1 : /*
2 : gpggencardkeyinteractor.cpp - Edit Interactor to generate a key on a card
3 : Copyright (C) 2017 by Bundesamt für Sicherheit in der Informationstechnik
4 : Software engineering by Intevation GmbH
5 :
6 : This file is part of GPGME++.
7 :
8 : GPGME++ is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU Library General Public
10 : License as published by the Free Software Foundation; either
11 : version 2 of the License, or (at your option) any later version.
12 :
13 : GPGME++ is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU Library General Public License for more details.
17 :
18 : You should have received a copy of the GNU Library General Public License
19 : along with GPGME++; see the file COPYING.LIB. If not, write to the
20 : Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 : Boston, MA 02110-1301, USA.
22 : */
23 :
24 : #ifdef HAVE_CONFIG_H
25 : #include "config.h"
26 : #endif
27 :
28 : #include "gpggencardkeyinteractor.h"
29 :
30 : #include "error.h"
31 :
32 : #include <gpgme.h>
33 :
34 : using namespace GpgME;
35 :
36 0 : class GpgGenCardKeyInteractor::Private
37 : {
38 : public:
39 0 : Private() : keysize("2048"), backup(false)
40 : {
41 :
42 0 : }
43 : std::string name, email, backupFileName, expiry, serial, keysize;
44 : bool backup;
45 : };
46 :
47 0 : GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor() {}
48 :
49 0 : GpgGenCardKeyInteractor::GpgGenCardKeyInteractor(const std::string &serial):
50 0 : d(new Private)
51 : {
52 0 : d->serial = serial;
53 0 : }
54 :
55 0 : void GpgGenCardKeyInteractor::setNameUtf8(const std::string &name)
56 : {
57 0 : d->name = name;
58 0 : }
59 :
60 0 : void GpgGenCardKeyInteractor::setEmailUtf8(const std::string &email)
61 : {
62 0 : d->email = email;
63 0 : }
64 :
65 0 : void GpgGenCardKeyInteractor::setDoBackup(bool value)
66 : {
67 0 : d->backup = value;
68 0 : }
69 :
70 0 : void GpgGenCardKeyInteractor::setKeySize(int value)
71 : {
72 0 : d->keysize = std::to_string(value);
73 0 : }
74 :
75 0 : void GpgGenCardKeyInteractor::setExpiry(const std::string &timeStr)
76 : {
77 0 : d->expiry = timeStr;
78 0 : }
79 :
80 0 : std::string GpgGenCardKeyInteractor::backupFileName() const
81 : {
82 0 : return d->backupFileName;
83 : }
84 :
85 : namespace GpgGenCardKeyInteractor_Private
86 : {
87 : enum {
88 : START = EditInteractor::StartState,
89 : DO_ADMIN,
90 : EXPIRE,
91 :
92 : GOT_SERIAL,
93 : COMMAND,
94 : NAME,
95 : EMAIL,
96 : COMMENT,
97 : BACKUP,
98 : REPLACE,
99 : SIZE,
100 : SIZE2,
101 : SIZE3,
102 : BACKUP_KEY_CREATED,
103 : KEY_CREATED,
104 : QUIT,
105 : SAVE,
106 :
107 : ERROR = EditInteractor::ErrorState
108 : };
109 : }
110 :
111 0 : const char *GpgGenCardKeyInteractor::action(Error &err) const
112 : {
113 :
114 : using namespace GpgGenCardKeyInteractor_Private;
115 :
116 0 : switch (state()) {
117 : case DO_ADMIN:
118 0 : return "admin";
119 : case COMMAND:
120 0 : return "generate";
121 : case NAME:
122 0 : return d->name.c_str();
123 : case EMAIL:
124 0 : return d->email.c_str();
125 : case EXPIRE:
126 0 : return d->expiry.c_str();
127 : case BACKUP:
128 0 : return d->backup ? "Y" : "N";
129 : case REPLACE:
130 0 : return "Y";
131 : case SIZE:
132 : case SIZE2:
133 : case SIZE3:
134 0 : return d->keysize.c_str();
135 : case COMMENT:
136 0 : return "";
137 : case SAVE:
138 0 : return "Y";
139 : case QUIT:
140 0 : return "quit";
141 : case KEY_CREATED:
142 : case START:
143 : case GOT_SERIAL:
144 : case BACKUP_KEY_CREATED:
145 : case ERROR:
146 0 : return 0;
147 : default:
148 0 : err = Error::fromCode(GPG_ERR_GENERAL);
149 0 : return 0;
150 : }
151 : }
152 :
153 0 : unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char *args, Error &err) const
154 : {
155 :
156 0 : static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
157 0 : static const Error INV_NAME_ERROR = Error::fromCode(GPG_ERR_INV_NAME);
158 0 : static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
159 0 : static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
160 :
161 0 : if (needsNoResponse(status)) {
162 0 : return state();
163 : }
164 :
165 : using namespace GpgGenCardKeyInteractor_Private;
166 :
167 0 : switch (state()) {
168 : case START:
169 0 : if (status == GPGME_STATUS_CARDCTRL &&
170 0 : !d->serial.empty()) {
171 0 : const std::string sArgs = args;
172 0 : if (sArgs.find(d->serial) == std::string::npos) {
173 : // Wrong smartcard
174 0 : err = Error::fromCode(GPG_ERR_WRONG_CARD);
175 0 : return ERROR;
176 : } else {
177 0 : printf("EditInteractor: Confirmed S/N: %s %s\n",
178 0 : d->serial.c_str(), sArgs.c_str());
179 : }
180 0 : return GOT_SERIAL;
181 0 : } else if (d->serial.empty()) {
182 0 : return GOT_SERIAL;
183 : }
184 0 : err = GENERAL_ERROR;
185 0 : return ERROR;
186 : case GOT_SERIAL:
187 0 : if (status == GPGME_STATUS_GET_LINE &&
188 0 : strcmp(args, "cardedit.prompt") == 0) {
189 0 : return DO_ADMIN;
190 : }
191 0 : err = GENERAL_ERROR;
192 0 : return ERROR;
193 : case DO_ADMIN:
194 0 : if (status == GPGME_STATUS_GET_LINE &&
195 0 : strcmp(args, "cardedit.prompt") == 0) {
196 0 : return COMMAND;
197 : }
198 0 : err = GENERAL_ERROR;
199 0 : return ERROR;
200 : case COMMAND:
201 0 : if (status == GPGME_STATUS_GET_LINE &&
202 0 : strcmp(args, "cardedit.genkeys.backup_enc") == 0) {
203 0 : return BACKUP;
204 : }
205 0 : err = GENERAL_ERROR;
206 0 : return ERROR;
207 : case BACKUP:
208 0 : if (status == GPGME_STATUS_GET_BOOL &&
209 0 : strcmp(args, "cardedit.genkeys.replace_keys") == 0) {
210 0 : return REPLACE;
211 : }
212 0 : if (status == GPGME_STATUS_GET_LINE &&
213 0 : strcmp(args, "cardedit.genkeys.size") == 0) {
214 0 : return SIZE;
215 : }
216 0 : err = GENERAL_ERROR;
217 0 : return ERROR;
218 : case REPLACE:
219 0 : if (status == GPGME_STATUS_GET_LINE &&
220 0 : strcmp(args, "cardedit.genkeys.size") == 0) {
221 0 : printf("Moving to SIZE\n");
222 0 : return SIZE;
223 : }
224 0 : err = GENERAL_ERROR;
225 0 : return ERROR;
226 : case SIZE:
227 0 : if (status == GPGME_STATUS_GET_LINE &&
228 0 : strcmp(args, "cardedit.genkeys.size") == 0) {
229 0 : return SIZE2;
230 : }
231 0 : if (status == GPGME_STATUS_GET_LINE &&
232 0 : strcmp(args, "keygen.valid") == 0) {
233 0 : return EXPIRE;
234 : }
235 0 : err = GENERAL_ERROR;
236 0 : return ERROR;
237 : case SIZE2:
238 0 : if (status == GPGME_STATUS_GET_LINE &&
239 0 : strcmp(args, "cardedit.genkeys.size") == 0) {
240 0 : return SIZE3;
241 : }
242 0 : if (status == GPGME_STATUS_GET_LINE &&
243 0 : strcmp(args, "keygen.valid") == 0) {
244 0 : return EXPIRE;
245 : }
246 0 : err = GENERAL_ERROR;
247 0 : return ERROR;
248 : case SIZE3:
249 0 : if (status == GPGME_STATUS_GET_LINE &&
250 0 : strcmp(args, "keygen.valid") == 0) {
251 0 : return EXPIRE;
252 : }
253 0 : err = GENERAL_ERROR;
254 0 : return ERROR;
255 : case EXPIRE:
256 0 : if (status == GPGME_STATUS_GET_LINE &&
257 0 : strcmp(args, "keygen.name") == 0) {
258 0 : return NAME;
259 : }
260 0 : err = GENERAL_ERROR;
261 0 : return ERROR;
262 : case NAME:
263 0 : if (status == GPGME_STATUS_GET_LINE &&
264 0 : strcmp(args, "keygen.email") == 0) {
265 0 : return EMAIL;
266 : }
267 0 : err = GENERAL_ERROR;
268 0 : if (status == GPGME_STATUS_GET_LINE &&
269 0 : strcmp(args, "keygen.name") == 0) {
270 0 : err = INV_NAME_ERROR;
271 : }
272 0 : return ERROR;
273 : case EMAIL:
274 0 : if (status == GPGME_STATUS_GET_LINE &&
275 0 : strcmp(args, "keygen.comment") == 0) {
276 0 : return COMMENT;
277 : }
278 0 : err = GENERAL_ERROR;
279 0 : if (status == GPGME_STATUS_GET_LINE &&
280 0 : strcmp(args, "keygen.email") == 0) {
281 0 : err = INV_EMAIL_ERROR;
282 : }
283 0 : return ERROR;
284 : case COMMENT:
285 0 : if (status == GPGME_STATUS_BACKUP_KEY_CREATED) {
286 0 : std::string sArgs = args;
287 0 : const auto pos = sArgs.rfind(" ");
288 0 : if (pos != std::string::npos) {
289 0 : d->backupFileName = sArgs.substr(pos + 1);
290 0 : return BACKUP_KEY_CREATED;
291 : }
292 : }
293 0 : if (status == GPGME_STATUS_KEY_CREATED) {
294 0 : return KEY_CREATED;
295 : }
296 0 : if (status == GPGME_STATUS_GET_LINE &&
297 0 : strcmp(args, "keyedit.prompt") == 0) {
298 0 : return QUIT;
299 : }
300 0 : err = GENERAL_ERROR;
301 0 : if (status == GPGME_STATUS_GET_LINE &&
302 0 : strcmp(args, "keygen.comment") == 0) {
303 0 : err = INV_COMMENT_ERROR;
304 : }
305 0 : return ERROR;
306 : case BACKUP_KEY_CREATED:
307 0 : if (status == GPGME_STATUS_KEY_CREATED) {
308 0 : return KEY_CREATED;
309 : }
310 0 : err = GENERAL_ERROR;
311 0 : return ERROR;
312 : case KEY_CREATED:
313 0 : return QUIT;
314 : case QUIT:
315 0 : if (status == GPGME_STATUS_GET_LINE &&
316 0 : strcmp(args, "cardedit.prompt") == 0) {
317 0 : return QUIT;
318 : }
319 0 : err = GENERAL_ERROR;
320 0 : return ERROR;
321 : case ERROR:
322 0 : if (status == GPGME_STATUS_GET_LINE &&
323 0 : strcmp(args, "keyedit.prompt") == 0) {
324 0 : return QUIT;
325 : }
326 0 : err = lastError();
327 0 : return ERROR;
328 : default:
329 0 : err = GENERAL_ERROR;
330 0 : return ERROR;
331 : }
332 : }
|