/[winpt]/trunk/Src/wptCardEdit.cpp
ViewVC logotype

Contents of /trunk/Src/wptCardEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations)
Wed Oct 12 10:04:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 12124 byte(s)
First testing phase finished.
Provide bug fixes for a lot of (minor) problems.

1 /* wptCardEdit.cpp - OpenPGP editing interface
2 * Copyright (C) 2005 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with WinPT; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #include <windows.h>
22
23 #include "gpgme.h"
24 #include "wptCardEdit.h"
25 #include "wptGPG.h"
26
27 /* Create a new Smartcard context. */
28 static gpgme_error_t
29 gpg_card_new (gpg_card_t *ret_card)
30 {
31 gpg_card_t c;
32
33 if (!ret_card)
34 return gpg_error (GPG_ERR_INV_ARG);
35 *ret_card = NULL;
36 c = (gpg_card_t)calloc (1, sizeof *c);
37 if( !c )
38 return gpg_error (GPG_ERR_ENOMEM);
39 *ret_card = c;
40 return 0;
41 }
42
43
44 /* Release an existing Smartcard context. @card. */
45 void
46 gpg_card_release (gpg_card_t card)
47 {
48 int i;
49
50 if (!card)
51 return;
52 if (card->aid)
53 free (card->aid);
54 if (card->version)
55 free (card->version);
56 if (card->lang)
57 free (card->lang);
58 if (card->login)
59 free (card->login);
60
61 for (i=0; i < 3; i++) {
62 if (card->fpr[i])
63 free (card->fpr[i]);
64 }
65 if (card->surname)
66 free (card->surname);
67 if (card->givenname)
68 free (card->givenname);
69 if (card->serial)
70 free (card->serial);
71 if (card->vendor)
72 free (card->vendor);
73 if (card->url)
74 free (card->url);
75 free (card);
76
77 }
78
79
80 /* Colon handler for parsing the GPG card colon output. */
81 static gpgme_error_t
82 statuscard_colon_handler (gpg_card_t *ctx, char * line, int *cnt)
83 {
84 enum rectype_t {
85 CARD_None = 0,
86 CARD_AID,
87 CARD_Version,
88 CARD_Vendor,
89 CARD_Serial,
90 CARD_Name,
91 CARD_Lang,
92 CARD_Sex,
93 CARD_Url,
94 CARD_Login,
95 CARD_MaxPinLen,
96 CARD_SigCount,
97 CARD_Fpr
98 };
99 enum rectype_t rectype;
100 gpgme_error_t err;
101 gpg_card_t card;
102 char *p, *pend;
103 int field = 0;
104
105 if (!line)
106 return gpg_error (GPG_ERR_EOF);
107
108 if (!*ctx) {
109 err = gpg_card_new (ctx);
110 return err;
111 }
112 card = *ctx;
113
114 for( p = line; p; p = pend ) {
115 field++;
116 pend = strchr (p, ':');
117 if (pend)
118 *pend++ = 0;
119
120 if (field == 1) {
121 if (!strcmp (p, "AID"))
122 rectype = CARD_AID;
123 else if( !strcmp( p, "version" ) )
124 rectype = CARD_Version;
125 else if( !strcmp( p, "vendor" ) )
126 rectype = CARD_Vendor;
127 else if( !strcmp( p, "serial" ) )
128 rectype = CARD_Serial;
129 else if( !strcmp( p, "name" ) )
130 rectype = CARD_Name;
131 else if( !strcmp( p, "lang" ) )
132 rectype = CARD_Lang;
133 else if( !strcmp( p, "sex" ) )
134 rectype = CARD_Sex;
135 else if( !strcmp( p, "url" ) )
136 rectype = CARD_Url;
137 else if( !strcmp( p, "login" ) )
138 rectype = CARD_Login;
139 else if( !strcmp( p, "maxpinlen" ) )
140 rectype = CARD_MaxPinLen;
141 else if( !strcmp( p, "sigcount" ) )
142 rectype = CARD_SigCount;
143 else if( !strcmp( p, "fpr" ) )
144 rectype = CARD_Fpr;
145 else
146 rectype = CARD_None;
147 }
148 switch( rectype ) {
149 case CARD_AID:
150 if( field == 2 ) {
151 card->aid = strdup (p);
152 if (!card->aid)
153 return gpg_error (GPG_ERR_ENOMEM);
154 }
155 break;
156 case CARD_Version:
157 if( field == 2 ) {
158 card->version = strdup (p);
159 if (!card->version)
160 return gpg_error (GPG_ERR_ENOMEM);
161 }
162 break;
163 case CARD_Vendor:
164 if( field == 3 ) {
165 card->vendor = strdup( p );
166 if (!card->vendor)
167 return gpg_error (GPG_ERR_ENOMEM);
168 }
169 break;
170 case CARD_Serial:
171 if( field == 2 ) {
172 card->serial = strdup( p );
173 if (!card->serial)
174 return gpg_error (GPG_ERR_ENOMEM);
175 }
176 break;
177 case CARD_Name:
178 if( field == 2 ) {
179 card->givenname = strdup( p );
180 if (!card->givenname)
181 return gpg_error (GPG_ERR_ENOMEM);
182 }
183 else if( field == 3 ) {
184 card->surname = strdup( p );
185 if (!card->surname)
186 return gpg_error (GPG_ERR_ENOMEM);
187 }
188 break;
189 case CARD_Lang:
190 if( field == 2 ) {
191 card->lang = strdup( p );
192 if (!card->lang)
193 return gpg_error (GPG_ERR_ENOMEM);
194 }
195 break;
196 case CARD_Sex:
197 if( field == 2 )
198 card->sex = *p;
199 break;
200 case CARD_Url:
201 if( field == 2 ) {
202 if (card->url)
203 free (card->url);
204 card->url = (char*)calloc (1, strlen (p) + 1);
205 if( !card->url ) {
206 return gpg_error (GPG_ERR_ENOMEM);
207 }
208 gpg_decode_c_string (p, &card->url, strlen (p) + 1);
209 if (!card->url)
210 return gpg_error (GPG_ERR_ENOMEM);
211 }
212 break;
213 case CARD_Login:
214 if( field == 2 ) {
215 card->login = strdup (p);
216 if (!card->login)
217 return gpg_error (GPG_ERR_ENOMEM);
218 }
219 break;
220 case CARD_MaxPinLen:
221 break;
222 case CARD_SigCount:
223 if( field == 2 )
224 card->sig_count = atol( p );
225 break;
226 case CARD_Fpr:
227 if( field == 2 || field == 3 || field == 4 ) {
228 card->fpr[(*cnt)++] = strdup( p );
229 }
230 break;
231 }
232 }
233 return 0;
234 }
235
236
237 /* Dummy handler to get the colon data and then quit. */
238 static gpgme_error_t
239 list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
240 {
241 static int step=0;
242 const char *s="";
243 DWORD n;
244
245 if (!strcmp (key, "keyedit.prompt") && step == 0) {
246 step = 1;
247 s = "list\n";
248 WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
249 }
250 else if (!strcmp (key, "keyedit.prompt") && step == 1) {
251 step = 0;
252 s = "quit\n";
253 WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
254 }
255 return 0;
256 }
257
258
259 /* Construct an empty object. */
260 GpgCardEdit::GpgCardEdit (void)
261 {
262 pin = NULL;
263 pin_new = NULL;
264 admin_pin = NULL;
265
266 type = 0;
267 cnt = 0;
268 cancel = 0;
269
270 gpgme_new (&ctx);
271 }
272
273 /* Release the object. */
274 GpgCardEdit::~GpgCardEdit (void)
275 {
276 gpgme_release (ctx);
277 if (this->keygen.name)
278 free (this->keygen.name);
279 if (this->keygen.comment)
280 free (this->keygen.comment);
281 if (this->keygen.email)
282 free (this->keygen.email);
283 if (this->keygen.expdate)
284 free (this->keygen.expdate);
285 }
286
287
288 /* Set the user PIN for the object to @pin. */
289 void
290 GpgCardEdit::setPIN (const char *pin)
291 {
292 this->pin = pin;
293 }
294
295 /* Set the admin PIN for the object to @admin_pin. */
296 void
297 GpgCardEdit::setAdminPIN (const char *admin_pin)
298 {
299 this->admin_pin = admin_pin;
300 }
301
302
303 /* Set the new user PIN for the object to @new_pin. */
304 void
305 GpgCardEdit::setNewPIN (const char *new_pin)
306 {
307 this->pin_new = new_pin;
308 }
309
310
311 /* Set the passphrase needed when generating a key to @pass. */
312 void
313 GpgCardEdit::setKeygenPassphrase (const char *pass)
314 {
315 this->keygen.pass = pass;
316 }
317
318
319 /* Set the callback to @cb and the hook value to @cb_value. */
320 void
321 GpgCardEdit::setCallback (const char* (*cb)(int code, void *opaque),
322 void *cb_value)
323 {
324 this->cb_value = cb_value;
325 this->card_cb = cb;
326 }
327
328
329 void
330 GpgCardEdit::setType (int type)
331 {
332 this->type = type;
333 }
334
335 /* Read the information from the inserted card and return
336 it in form of a card context @r_card.
337 Return value: 0 on success. */
338 gpgme_error_t
339 GpgCardEdit::getCardStatus (gpg_card_t *r_card)
340 {
341 gpgme_data_t tmp = NULL;
342 gpgme_error_t err;
343 char buf[200];
344 int cnt = 0;
345
346 if (!r_card)
347 return gpg_error (GPG_ERR_INV_ARG);
348
349 err = gpgme_data_new (&tmp);
350 if (err)
351 return err;
352
353 err = gpgme_op_card_edit (ctx, NULL, list_handler, NULL, tmp);
354 if (err) {
355 gpgme_data_release (tmp);
356 return err;
357 }
358
359 *r_card=NULL;
360 gpgme_data_rewind (tmp);
361 while (gpg_data_readline (tmp, buf, sizeof buf-2) > 0)
362 statuscard_colon_handler (r_card, buf, &cnt);
363 gpgme_data_release (tmp);
364
365 return err;
366 }
367
368
369 /* Generate a key on a smart card with the following params:
370 @flags: user specific params.
371 @name: name of the key holder.
372 @email: email of the key holder.
373 @comment: optional comment.
374 @valid: how long is the key valid in days.
375 Return value: 0 on success. */
376 gpgme_error_t
377 GpgCardEdit::genKey (int flags, const char *name,
378 const char *email, const char *comment,
379 long valid)
380 {
381 gpgme_error_t err;
382
383 if (!name || !email)
384 return gpg_error (GPG_ERR_INV_ARG);
385 if (!this->keygen.pass)
386 return gpg_error (GPG_ERR_INV_OBJ);
387
388 type = GPG_EDITCARD_GENKEY;
389 this->keygen.flags = flags;
390
391 if (this->keygen.name)
392 free (this->keygen.name);
393 this->keygen.name = strdup (name);
394 if (this->keygen.email)
395 free (this->keygen.email);
396 this->keygen.email = strdup (email);
397 if (this->keygen.comment)
398 free (this->keygen.comment);
399 this->keygen.comment = comment? strdup (comment) : strdup ("");
400 if (this->keygen.expdate)
401 free (this->keygen.expdate);
402 this->keygen.expdate = (char*)calloc (1, 16);
403 if (this->keygen.expdate)
404 sprintf (this->keygen.expdate, "%d", valid);
405
406 if (!this->keygen.name || !this->keygen.email ||
407 !this->keygen.comment || !this->keygen.expdate)
408 return gpg_error (GPG_ERR_ENOMEM);
409
410 err = gpg_card_edit (ctx, this);
411 return err;
412 }
413
414
415 /* Change the pin from @pin to @pin_new.
416 Return value: 0 on success. */
417 gpgme_error_t
418 GpgCardEdit::changePIN (void)
419 {
420 gpgme_error_t err;
421
422 if (!this->pin || !this->pin_new)
423 return gpg_error (GPG_ERR_INV_ARG);
424
425 if (!type) {
426 if (this->pin && this->pin_new)
427 type = GPG_EDITCARD_CHUPIN;
428 else if (this->pin && this->admin_pin)
429 type = GPG_EDITCARD_CHAPIN;
430 else
431 type = GPG_EDITCARD_UNBPIN;
432 }
433
434 err = gpg_card_edit (ctx, this);
435 return err;
436 }
437
438
439 gpgme_error_t
440 GpgCardEdit::updateName (const char *given, const char *sur)
441 {
442 gpgme_error_t err;
443
444 if (!this->pin)
445 return gpg_error (GPG_ERR_INV_OBJ);
446
447 this->edit.surname = sur;
448 this->edit.givenname = given;
449
450 err = gpg_card_edit (ctx, this);
451 return err;
452 }
453
454 gpgme_error_t
455 GpgCardEdit::updateURL (const char *url)
456 {
457 gpgme_error_t err;
458
459 if (!this->pin)
460 return gpg_error (GPG_ERR_INV_OBJ);
461
462 this->edit.keyurl = url;
463
464 err = gpg_card_edit (ctx, this);
465 return err;
466 }
467
468
469 gpgme_error_t
470 GpgCardEdit::updateLogin (const char *login)
471 {
472 gpgme_error_t err;
473
474 if (!this->pin)
475 return gpg_error (GPG_ERR_INV_OBJ);
476
477 this->edit.login = login;
478
479 err = gpg_card_edit (ctx, this);
480 return err;
481 }
482
483 gpgme_error_t
484 GpgCardEdit::updateSex (char sex)
485 {
486 gpgme_error_t err;
487
488 if (!this->pin)
489 return gpg_error (GPG_ERR_INV_OBJ);
490
491 this->edit.sex = sex;
492 err = gpg_card_edit (ctx, this);
493 return err;
494 }
495
496 gpgme_error_t
497 GpgCardEdit::updateLanguage (const char *lang)
498 {
499 gpgme_error_t err;
500
501 if (!this->pin)
502 return gpg_error (GPG_ERR_INV_OBJ);
503
504 this->edit.lang = lang;
505 err = gpg_card_edit (ctx, this);
506 return err;
507 }
508
509
510 /* Fetch the key specified by the url stored on the card.
511 Return value: 0 on success. */
512 gpgme_error_t
513 GpgCardEdit::fetchKey (void)
514 {
515 gpgme_error_t err = 0;
516
517 if (!this->pin)
518 return gpg_error (GPG_ERR_INV_OBJ);
519
520 return 0;
521 }
522
523
524 gpgme_error_t
525 GpgCardEdit:: doCmd (int cmd, const char *arg1, const char *arg2)
526 {
527 switch (cmd) {
528 case GPG_EDITCARD_NAME:
529 return updateName (arg1, arg2); /* given, surname */
530
531 case GPG_EDITCARD_LANG:
532 return updateLanguage (arg1); /* lang */
533
534 case GPG_EDITCARD_SEX:
535 return updateSex (*arg1); /* sex */
536
537 case GPG_EDITCARD_KEYURL:
538 return updateURL (arg1); /* url */
539
540 case GPG_EDITCARD_LOGIN:
541 return updateLogin (arg1); /* login */
542 }
543
544 return 0;
545 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26