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

Annotation of /trunk/Src/wptCardEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide annotations)
Sat Oct 8 10:43:08 2005 UTC (19 years, 4 months ago) by twoaday
File size: 12124 byte(s)
Bug fixes to correct some problems introduced by
the MyGPGME to GPGME port.

1 twoaday 23 /* 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     #include <io.h>
23     #include "w32gpgme.h"
24     #include "wptCardEdit.h"
25    
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 twoaday 24 card->url = (char*)calloc (1, strlen (p) + 1);
205 twoaday 23 if( !card->url ) {
206 twoaday 24 return gpg_error (GPG_ERR_ENOMEM);
207 twoaday 23 }
208 twoaday 24 gpg_decode_c_string (p, &card->url, strlen (p) + 1);
209 twoaday 23 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 twoaday 24 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 twoaday 23 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