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

Annotation of /trunk/Src/wptCardEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (hide annotations)
Mon Oct 31 21:14:11 2005 UTC (19 years, 4 months ago) by werner
File size: 15228 byte(s)
More changes.  Compiles again but there are at least gettext issues with
w32-gettext.c.  I can't get a gpg-error build with ENABLE_NLS.

1 werner 36 /* 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     #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25     #include <windows.h>
26     #include <time.h>
27    
28     #include "gpgme.h"
29     #include "wptCard.h"
30     #include "wptCardEdit.h"
31     #include "wptGPG.h"
32     #include "wptErrors.h"
33    
34     /* Create a new Smartcard context. */
35     static gpgme_error_t
36     gpg_card_new (gpg_card_t *ret_card)
37     {
38     gpg_card_t c;
39    
40     if (!ret_card)
41     return gpg_error (GPG_ERR_INV_ARG);
42     *ret_card = NULL;
43     c = (gpg_card_t)calloc (1, sizeof *c);
44     if (!c)
45     return gpg_error (GPG_ERR_ENOMEM);
46     *ret_card = c;
47     return 0;
48     }
49    
50    
51     /* Release an existing Smartcard context. @card. */
52     void
53     gpg_card_release (gpg_card_t card)
54     {
55     int i;
56    
57     if (!card)
58     return;
59     if (card->aid)
60     free (card->aid);
61     if (card->version)
62     free (card->version);
63     if (card->lang)
64     free (card->lang);
65     if (card->login)
66     free (card->login);
67     for (i=0; i < 3; i++) {
68     if (card->fpr[i])
69     free (card->fpr[i]);
70     if (card->ca_fpr[i])
71     free (card->ca_fpr[i]);
72     if (card->fpr_created_str[i])
73     free (card->fpr_created_str[i]);
74     }
75     if (card->surname)
76     free (card->surname);
77     if (card->givenname)
78     free (card->givenname);
79     if (card->serial)
80     free (card->serial);
81     if (card->vendor)
82     free (card->vendor);
83     if (card->url)
84     free (card->url);
85     if (card->card_type)
86     free (card->card_type);
87     free (card);
88    
89     }
90    
91    
92     /* Parse the timestamp @long_ts and return a string
93     representation of it (format: YYYY-DD-MM HH:MM:SS). */
94     static char*
95     get_str_timestamp (long long_ts)
96     {
97     struct tm *tm;
98     char *p, *fmt;
99    
100     tm = localtime (&long_ts);
101     fmt = "%04d-%02d-%02d %02d:%02d:%02d";
102     p = (char*)calloc (1, strlen (fmt)+32);
103     if (!p)
104     abort ();
105     sprintf (p, fmt,
106     tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
107     tm->tm_hour, tm->tm_min, tm->tm_sec);
108     return p;
109     }
110    
111    
112     /* Colon handler for parsing the GPG card colon output. */
113     static gpgme_error_t
114     statuscard_colon_handler (gpg_card_t card, char * line)
115     {
116     enum rectype_t {
117     CARD_None = 0,
118     CARD_AID,
119     CARD_Version,
120     CARD_Vendor,
121     CARD_Serial,
122     CARD_Name,
123     CARD_Lang,
124     CARD_Sex,
125     CARD_Url,
126     CARD_Login,
127     CARD_MaxPinLen,
128     CARD_SigCount,
129     CARD_CAFpr,
130     CARD_Fpr,
131     CARD_FprTime
132     };
133     enum rectype_t rectype;
134     char *p, *pend;
135     int field = 0;
136    
137     if (!line)
138     return gpg_error (GPG_ERR_EOF);
139    
140     for (p = line; p; p = pend) {
141     field++;
142     pend = strchr (p, ':');
143     if (pend)
144     *pend++ = 0;
145    
146     if (field == 1) {
147     if (!strcmp (p, "AID"))
148     rectype = CARD_AID;
149     else if( !strcmp( p, "version" ) )
150     rectype = CARD_Version;
151     else if( !strcmp( p, "vendor" ) )
152     rectype = CARD_Vendor;
153     else if( !strcmp( p, "serial" ) )
154     rectype = CARD_Serial;
155     else if( !strcmp( p, "name" ) )
156     rectype = CARD_Name;
157     else if( !strcmp( p, "lang" ) )
158     rectype = CARD_Lang;
159     else if( !strcmp( p, "sex" ) )
160     rectype = CARD_Sex;
161     else if( !strcmp( p, "url" ) )
162     rectype = CARD_Url;
163     else if( !strcmp( p, "login" ) )
164     rectype = CARD_Login;
165     else if( !strcmp( p, "maxpinlen" ) )
166     rectype = CARD_MaxPinLen;
167     else if( !strcmp( p, "sigcount" ) )
168     rectype = CARD_SigCount;
169     else if (!strcmp (p, "cafpr"))
170     rectype = CARD_CAFpr;
171     else if (!strcmp (p, "fpr"))
172     rectype = CARD_Fpr;
173     else if (!strcmp (p, "fprtime"))
174     rectype = CARD_FprTime;
175     else
176     rectype = CARD_None;
177     }
178     switch (rectype) {
179     case CARD_AID:
180     if (field == 2) {
181     card->aid = strdup (p);
182     if (!card->aid)
183     return gpg_error (GPG_ERR_ENOMEM);
184     }
185     else if (field == 3) {
186     card->card_type = strdup (p);
187     if (!card->card_type)
188     return gpg_error (GPG_ERR_ENOMEM);
189     }
190     break;
191    
192     case CARD_Version:
193     if (field == 2) {
194     card->version = strdup (p);
195     if (!card->version)
196     return gpg_error (GPG_ERR_ENOMEM);
197     }
198     break;
199    
200     case CARD_Vendor:
201     if (field == 3) {
202     card->vendor = strdup (p);
203     if (!card->vendor)
204     return gpg_error (GPG_ERR_ENOMEM);
205     }
206     break;
207    
208     case CARD_Serial:
209     if (field == 2) {
210     card->serial = strdup (p);
211     if (!card->serial)
212     return gpg_error (GPG_ERR_ENOMEM);
213     }
214     break;
215     case CARD_Name:
216     if (field == 2) {
217     card->givenname = strdup (p);
218     if (!card->givenname)
219     return gpg_error (GPG_ERR_ENOMEM);
220     }
221     else if (field == 3) {
222     card->surname = strdup (p);
223     if (!card->surname)
224     return gpg_error (GPG_ERR_ENOMEM);
225     }
226     break;
227     case CARD_Lang:
228     if( field == 2 ) {
229     card->lang = strdup (p);
230     if (!card->lang)
231     return gpg_error (GPG_ERR_ENOMEM);
232     }
233     break;
234     case CARD_Sex:
235     if( field == 2 )
236     card->sex = *p;
237     break;
238    
239     case CARD_Url:
240     if( field == 2 ) {
241     if (card->url)
242     free (card->url);
243     card->url = (char*)calloc (1, strlen (p) + 1);
244     if( !card->url ) {
245     return gpg_error (GPG_ERR_ENOMEM);
246     }
247     gpg_decode_c_string (p, &card->url, strlen (p) + 1);
248     if (!card->url)
249     return gpg_error (GPG_ERR_ENOMEM);
250     }
251     break;
252    
253     case CARD_Login:
254     if (field == 2) {
255     card->login = strdup (p);
256     if (!card->login)
257     return gpg_error (GPG_ERR_ENOMEM);
258     }
259     break;
260    
261     case CARD_MaxPinLen:
262     break;
263    
264     case CARD_SigCount:
265     if (field == 2)
266     card->sig_count = atol (p);
267     break;
268    
269     case CARD_CAFpr:
270     if (!p)
271     break;
272     if (field > 4 || field == 1)
273     break;
274     card->ca_fpr[field-2] = strdup (p);
275     if (!card->ca_fpr[field-2])
276     return gpg_error (GPG_ERR_ENOMEM);
277     break;
278    
279     case CARD_Fpr:
280     if (field > 4 || field == 1) /* max 3 fprs */
281     break;
282     card->fpr[field-2] = strdup (p);
283     if (!card->fpr[field-2])
284     return gpg_error (GPG_ERR_ENOMEM);
285     break;
286    
287     case CARD_FprTime:
288     if (field > 4 || field == 1)
289     break;
290     card->fpr_created[field-2] = strtoul (p, NULL, 10);
291     card->fpr_created_str[field-2] = get_str_timestamp (strtoul (p, NULL, 10));
292     if (!card->fpr_created_str[field-2])
293     return gpg_error (GPG_ERR_ENOMEM);
294     break;
295    
296     }
297     }
298     return 0;
299     }
300    
301    
302     /* Dummy handler to get the colon data and then quit. */
303     static gpgme_error_t
304     list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
305     {
306     static int wait_card=0;
307     GpgCardEdit *ce = (GpgCardEdit *)opaque;
308     const char *s="";
309     DWORD n;
310    
311    
312     if (code == GPGME_STATUS_CARDCTRL) {
313     if (!strcmp (key, "5"))
314     ce->setResult (GPG_CARDRES_NOCARD);
315     else if (!strcmp (key, "1"))
316     wait_card = 1;
317     }
318     if (wait_card && !strcmp (key, "cardctrl.insert_card.okay")) {
319     n = MessageBox (NULL, _("Please insert the card and click OK or Cancel to abort."),
320     _("GPG Card Status"), MB_ICONQUESTION|MB_OKCANCEL);
321     if (n == IDCANCEL) {
322     ce->setResult (GPG_CARDRES_CANCEL);
323     WriteFile ((HANDLE)fd, "c\n", 2, &n, NULL);
324     wait_card = 0;
325     }
326     }
327     if (!strcmp (key, "cardedit.prompt")) {
328     s = "quit\n";
329     if (!WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL))
330     log_debug ("list_handler: WriteFile() failed ec=%d\r\n",
331     (int)GetLastError ());
332     wait_card = 0;
333     }
334     return 0;
335     }
336    
337    
338     /* Construct an empty object. */
339     GpgCardEdit::GpgCardEdit (void)
340     {
341     pin = NULL;
342     pin_new = NULL;
343     admin_pin = NULL;
344    
345     keygen.comment = NULL;
346     keygen.email = NULL;
347     keygen.name = NULL;
348     keygen.expdate = NULL;
349     keygen.key_fpr = NULL;
350    
351     type = 0;
352     cnt = 0;
353     cancel = 0;
354     result = 0;
355    
356     gpgme_new (&ctx); /* XXX: check return code */
357     }
358    
359     /* Release the object. */
360     GpgCardEdit::~GpgCardEdit (void)
361     {
362     if (keygen.name)
363     free (keygen.name);
364     if (keygen.comment)
365     free (keygen.comment);
366     if (keygen.email)
367     free (keygen.email);
368     if (keygen.expdate)
369     free (keygen.expdate);
370     if (keygen.key_fpr)
371     free (keygen.key_fpr);
372     gpgme_release (ctx);
373     }
374    
375    
376     /* Set the user PIN for the object to @pin. */
377     void
378     GpgCardEdit::setPIN (const char *pin)
379     {
380     this->pin = pin;
381     }
382    
383     /* Set the admin PIN for the object to @admin_pin. */
384     void
385     GpgCardEdit::setAdminPIN (const char *admin_pin)
386     {
387     this->admin_pin = admin_pin;
388     }
389    
390    
391     /* Set the new user PIN for the object to @new_pin. */
392     void
393     GpgCardEdit::setNewPIN (const char *new_pin)
394     {
395     this->pin_new = new_pin;
396     }
397    
398    
399     /* Set the passphrase needed when generating a key to @pass. */
400     void
401     GpgCardEdit::setKeygenPassphrase (const char *pass)
402     {
403     this->keygen.pass = pass;
404     }
405    
406    
407     /* Set the callback to @cb and the hook value to @cb_value. */
408     void
409     GpgCardEdit::setCallback (const char* (*cb)(int code, void *opaque),
410     void *cb_value)
411     {
412     this->cb_value = cb_value;
413     this->card_cb = cb;
414     }
415    
416    
417     /* Read the information from the inserted card and return
418     it in form of a card context @r_card.
419     Return value: 0 on success. */
420     gpgme_error_t
421     GpgCardEdit::getCardStatus (gpg_card_t *r_card)
422     {
423     gpgme_data_t out = NULL;
424     gpgme_error_t err;
425     gpg_card_t card=NULL;
426     char buf[200];
427    
428     if (!r_card)
429     return gpg_error (GPG_ERR_INV_ARG);
430    
431     err = gpg_card_new (&card);
432     if (err)
433     return err;
434    
435     err = gpgme_data_new (&out);
436     if (err) {
437     gpg_card_release (card);
438     return err;
439     }
440    
441     err = gpgme_op_card_edit (ctx, NULL, list_handler, this, out);
442     gpgme_data_rewind (out);
443     if (err) {
444     gpgme_data_release (out);
445     gpg_card_release (card);
446     return err;
447     }
448     if (getResult () & GPG_CARDRES_NOCARD ||
449     getResult () & GPG_CARDRES_CANCEL) {
450     gpg_card_release (card);
451     gpgme_data_release (out);
452     return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
453     }
454    
455     *r_card = card;
456     while (gpg_data_readline (out, buf, sizeof (buf)-2) > 0) {
457     err = statuscard_colon_handler (card, buf);
458     if (err)
459     break;
460     }
461     gpgme_data_release (out);
462    
463     return err;
464     }
465    
466    
467     /* Generate a key on a smart card with the following params:
468     @flags: user specific params.
469     @name: name of the key holder.
470     @email: email of the key holder.
471     @comment: optional comment.
472     @valid: how long is the key valid in days.
473     Return value: 0 on success. */
474     gpgme_error_t
475     GpgCardEdit::genKey (int flags, const char *name,
476     const char *email, const char *comment, long valid,
477     char **r_key_fpr)
478     {
479     gpgme_error_t err;
480    
481     if (!name || !email)
482     return gpg_error (GPG_ERR_INV_ARG);
483     if (!this->keygen.pass)
484     return gpg_error (GPG_ERR_INV_OBJ);
485    
486     type = GPG_EDITCARD_GENKEY;
487     this->keygen.flags = flags;
488    
489     if (this->keygen.name)
490     free (this->keygen.name);
491     this->keygen.name = strdup (name);
492     if (this->keygen.email)
493     free (this->keygen.email);
494     this->keygen.email = strdup (email);
495     if (this->keygen.comment)
496     free (this->keygen.comment);
497     this->keygen.comment = comment? strdup (comment) : strdup ("");
498     if (this->keygen.expdate)
499     free (this->keygen.expdate);
500     this->keygen.expdate = (char*)calloc (1, 16);
501     if (this->keygen.expdate)
502     sprintf (this->keygen.expdate, "%d", valid);
503    
504     if (!this->keygen.name || !this->keygen.email)
505     return gpg_error (GPG_ERR_ENOMEM);
506    
507     err = gpg_card_edit (ctx, this);
508     if (!err)
509     err = getResult () & GPG_CARDRES_CANCEL? gpg_error (GPG_ERR_CANCELED) : 0;
510     if (!err && r_key_fpr)
511     *r_key_fpr = strdup (keygen.key_fpr? keygen.key_fpr : "");
512     return err;
513     }
514    
515    
516     /* Change the pin from @pin to @pin_new.
517     Return value: 0 on success. */
518     gpgme_error_t
519     GpgCardEdit::changePIN (int type)
520     {
521     gpgme_error_t err;
522    
523     if (!this->pin_new)
524     return gpg_error (GPG_ERR_INV_ARG);
525    
526     if (!type) {
527     if (this->pin && this->pin_new)
528     this->type = GPG_EDITCARD_CHUPIN;
529     else if (this->pin && this->admin_pin)
530     this->type = GPG_EDITCARD_CHAPIN;
531     else
532     this->type = GPG_EDITCARD_UNBPIN;
533     }
534     else
535     this->type = type;
536     /* check if the user provided the needed PIN. */
537     if ((this->type == GPG_EDITCARD_CHUPIN && !this->pin) ||
538     (this->type == GPG_EDITCARD_CHAPIN && !this->admin_pin))
539     return gpg_error (GPG_ERR_INV_ARG);
540    
541     err = gpg_card_edit (ctx, this);
542     return err;
543     }
544    
545    
546     gpgme_error_t
547     GpgCardEdit::updateName (const char *given, const char *sur)
548     {
549     gpgme_error_t err;
550    
551     if (!this->admin_pin)
552     return gpg_error (GPG_ERR_INV_OBJ);
553    
554     this->type = GPG_EDITCARD_NAME;
555     this->edit.surname = sur;
556     this->edit.givenname = given;
557    
558     err = gpg_card_edit (ctx, this);
559     return err;
560     }
561    
562     gpgme_error_t
563     GpgCardEdit::updateURL (const char *url)
564     {
565     gpgme_error_t err;
566    
567     if (!this->admin_pin)
568     return gpg_error (GPG_ERR_INV_OBJ);
569    
570     type = GPG_EDITCARD_KEYURL;
571     this->edit.keyurl = url;
572    
573     err = gpg_card_edit (ctx, this);
574     return err;
575     }
576    
577    
578     gpgme_error_t
579     GpgCardEdit::updateLogin (const char *login)
580     {
581     gpgme_error_t err;
582    
583     if (!this->admin_pin)
584     return gpg_error (GPG_ERR_INV_OBJ);
585    
586     this->type = GPG_EDITCARD_LOGIN;
587     this->edit.login = login;
588    
589     err = gpg_card_edit (ctx, this);
590     return err;
591     }
592    
593     gpgme_error_t
594     GpgCardEdit::updateSex (char sex)
595     {
596     gpgme_error_t err;
597    
598     if (!this->admin_pin)
599     return gpg_error (GPG_ERR_INV_OBJ);
600    
601     type = GPG_EDITCARD_SEX;
602     this->edit.sex = sex;
603    
604     err = gpg_card_edit (ctx, this);
605     return err;
606     }
607    
608     gpgme_error_t
609     GpgCardEdit::updateLanguage (const char *lang)
610     {
611     gpgme_error_t err;
612    
613     if (!this->admin_pin)
614     return gpg_error (GPG_ERR_INV_OBJ);
615    
616     type = GPG_EDITCARD_LANG;
617     this->edit.lang = lang;
618    
619     err = gpg_card_edit (ctx, this);
620     return err;
621     }
622    
623    
624     /* Fetch the key specified by the url stored on the card.
625     Return value: 0 on success. */
626     gpgme_error_t
627     GpgCardEdit::fetchKey (void)
628     {
629     gpgme_error_t err = 0;
630    
631     if (!this->pin)
632     return gpg_error (GPG_ERR_INV_OBJ);
633    
634     return 0;
635     }
636    
637    
638     /* Dispatcher for the various commands. @cmd is the card command ID
639     and @arg1 and @arg2 the actual values for the command.
640     Return value: 0 on success. */
641     gpgme_error_t
642     GpgCardEdit:: doCmd (int cmd, const char *arg1, const char *arg2)
643     {
644     switch (cmd) {
645     case GPG_EDITCARD_NAME:
646     return updateName (arg1, arg2); /* given, surname */
647    
648     case GPG_EDITCARD_LANG:
649     return updateLanguage (arg1); /* lang */
650    
651     case GPG_EDITCARD_SEX:
652     return updateSex (*arg1); /* sex */
653    
654     case GPG_EDITCARD_KEYURL:
655     return updateURL (arg1); /* url */
656    
657     case GPG_EDITCARD_LOGIN:
658     return updateLogin (arg1); /* login */
659    
660     default:
661     return gpg_error (GPG_ERR_INV_VALUE);
662     }
663    
664     return 0;
665     }
666    
667    
668     /* Set the result for the executed operation.
669     The values will be ORed. */
670     void
671     GpgCardEdit::setResult (int res)
672     {
673     result |= res;
674     }
675    
676    
677     /* Return the result of the executed operation. */
678     int
679     GpgCardEdit::getResult (void)
680     {
681     return result;
682     }
683    
684    
685     /* Reset the object state. */
686     void
687     GpgCardEdit::reset (void)
688     {
689     cnt = 0;
690     }
691    
692    
693     /* Return card command type */
694     int
695     GpgCardEdit::getType (void)
696     {
697     return type;
698     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26