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

Annotation of /trunk/Src/wptCardEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (hide annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File size: 11861 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


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     /*
205     card->url = calloc( 1, strlen( p ) + 1 );
206     if( !card->url ) {
207     return; // XXX
208     }
209     _gpgme_decode_c_string (p, &card->url, strlen (p) + 1);
210     */
211     card->url = strdup (p); /* XXX */
212     if (!card->url)
213     return gpg_error (GPG_ERR_ENOMEM);
214     }
215     break;
216     case CARD_Login:
217     if( field == 2 ) {
218     card->login = strdup (p);
219     if (!card->login)
220     return gpg_error (GPG_ERR_ENOMEM);
221     }
222     break;
223     case CARD_MaxPinLen:
224     break;
225     case CARD_SigCount:
226     if( field == 2 )
227     card->sig_count = atol( p );
228     break;
229     case CARD_Fpr:
230     if( field == 2 || field == 3 || field == 4 ) {
231     card->fpr[(*cnt)++] = strdup( p );
232     }
233     break;
234     }
235     }
236     return 0;
237     }
238    
239    
240     /* Dummy handler to get the colon data and then quit. */
241     static gpgme_error_t
242     list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
243     {
244     const char *s = "quit\n";
245     write (fd, s, strlen (s));
246     return 0;
247     }
248    
249    
250     /* Construct an empty object. */
251     GpgCardEdit::GpgCardEdit (void)
252     {
253     pin = NULL;
254     pin_new = NULL;
255     admin_pin = NULL;
256    
257     type = 0;
258     cnt = 0;
259     cancel = 0;
260    
261     gpgme_new (&ctx);
262     }
263    
264     /* Release the object. */
265     GpgCardEdit::~GpgCardEdit (void)
266     {
267     gpgme_release (ctx);
268     if (this->keygen.name)
269     free (this->keygen.name);
270     if (this->keygen.comment)
271     free (this->keygen.comment);
272     if (this->keygen.email)
273     free (this->keygen.email);
274     if (this->keygen.expdate)
275     free (this->keygen.expdate);
276     }
277    
278    
279     /* Set the user PIN for the object to @pin. */
280     void
281     GpgCardEdit::setPIN (const char *pin)
282     {
283     this->pin = pin;
284     }
285    
286     /* Set the admin PIN for the object to @admin_pin. */
287     void
288     GpgCardEdit::setAdminPIN (const char *admin_pin)
289     {
290     this->admin_pin = admin_pin;
291     }
292    
293    
294     /* Set the new user PIN for the object to @new_pin. */
295     void
296     GpgCardEdit::setNewPIN (const char *new_pin)
297     {
298     this->pin_new = new_pin;
299     }
300    
301    
302     /* Set the passphrase needed when generating a key to @pass. */
303     void
304     GpgCardEdit::setKeygenPassphrase (const char *pass)
305     {
306     this->keygen.pass = pass;
307     }
308    
309    
310     /* Set the callback to @cb and the hook value to @cb_value. */
311     void
312     GpgCardEdit::setCallback (const char* (*cb)(int code, void *opaque),
313     void *cb_value)
314     {
315     this->cb_value = cb_value;
316     this->card_cb = cb;
317     }
318    
319    
320     void
321     GpgCardEdit::setType (int type)
322     {
323     this->type = type;
324     }
325    
326     /* Read the information from the inserted card and return
327     it in form of a card context @r_card.
328     Return value: 0 on success. */
329     gpgme_error_t
330     GpgCardEdit::getCardStatus (gpg_card_t *r_card)
331     {
332     gpgme_data_t tmp = NULL;
333     gpgme_error_t err;
334     char buf[200];
335     int cnt = 0;
336    
337     if (!r_card)
338     return gpg_error (GPG_ERR_INV_ARG);
339    
340     err = gpgme_data_new (&tmp);
341     if (err)
342     return err;
343    
344     err = gpgme_op_card_edit (ctx, NULL, list_handler, NULL, tmp);
345     if (err) {
346     gpgme_data_release (tmp);
347     return err;
348     }
349    
350     *r_card=NULL;
351     gpgme_data_rewind (tmp);
352     while (gpg_data_readline (tmp, buf, sizeof buf-2) > 0)
353     statuscard_colon_handler (r_card, buf, &cnt);
354     gpgme_data_release (tmp);
355    
356     return err;
357     }
358    
359    
360     /* Generate a key on a smart card with the following params:
361     @flags: user specific params.
362     @name: name of the key holder.
363     @email: email of the key holder.
364     @comment: optional comment.
365     @valid: how long is the key valid in days.
366     Return value: 0 on success. */
367     gpgme_error_t
368     GpgCardEdit::genKey (int flags, const char *name,
369     const char *email, const char *comment,
370     long valid)
371     {
372     gpgme_error_t err;
373    
374     if (!name || !email)
375     return gpg_error (GPG_ERR_INV_ARG);
376     if (!this->keygen.pass)
377     return gpg_error (GPG_ERR_INV_OBJ);
378    
379     type = GPG_EDITCARD_GENKEY;
380     this->keygen.flags = flags;
381    
382     if (this->keygen.name)
383     free (this->keygen.name);
384     this->keygen.name = strdup (name);
385     if (this->keygen.email)
386     free (this->keygen.email);
387     this->keygen.email = strdup (email);
388     if (this->keygen.comment)
389     free (this->keygen.comment);
390     this->keygen.comment = comment? strdup (comment) : strdup ("");
391     if (this->keygen.expdate)
392     free (this->keygen.expdate);
393     this->keygen.expdate = (char*)calloc (1, 16);
394     if (this->keygen.expdate)
395     sprintf (this->keygen.expdate, "%d", valid);
396    
397     if (!this->keygen.name || !this->keygen.email ||
398     !this->keygen.comment || !this->keygen.expdate)
399     return gpg_error (GPG_ERR_ENOMEM);
400    
401     err = gpg_card_edit (ctx, this);
402     return err;
403     }
404    
405    
406     /* Change the pin from @pin to @pin_new.
407     Return value: 0 on success. */
408     gpgme_error_t
409     GpgCardEdit::changePIN (void)
410     {
411     gpgme_error_t err;
412    
413     if (!this->pin || !this->pin_new)
414     return gpg_error (GPG_ERR_INV_ARG);
415    
416     if (!type) {
417     if (this->pin && this->pin_new)
418     type = GPG_EDITCARD_CHUPIN;
419     else if (this->pin && this->admin_pin)
420     type = GPG_EDITCARD_CHAPIN;
421     else
422     type = GPG_EDITCARD_UNBPIN;
423     }
424    
425     err = gpg_card_edit (ctx, this);
426     return err;
427     }
428    
429    
430     gpgme_error_t
431     GpgCardEdit::updateName (const char *given, const char *sur)
432     {
433     gpgme_error_t err;
434    
435     if (!this->pin)
436     return gpg_error (GPG_ERR_INV_OBJ);
437    
438     this->edit.surname = sur;
439     this->edit.givenname = given;
440    
441     err = gpg_card_edit (ctx, this);
442     return err;
443     }
444    
445     gpgme_error_t
446     GpgCardEdit::updateURL (const char *url)
447     {
448     gpgme_error_t err;
449    
450     if (!this->pin)
451     return gpg_error (GPG_ERR_INV_OBJ);
452    
453     this->edit.keyurl = url;
454    
455     err = gpg_card_edit (ctx, this);
456     return err;
457     }
458    
459    
460     gpgme_error_t
461     GpgCardEdit::updateLogin (const char *login)
462     {
463     gpgme_error_t err;
464    
465     if (!this->pin)
466     return gpg_error (GPG_ERR_INV_OBJ);
467    
468     this->edit.login = login;
469    
470     err = gpg_card_edit (ctx, this);
471     return err;
472     }
473    
474     gpgme_error_t
475     GpgCardEdit::updateSex (char sex)
476     {
477     gpgme_error_t err;
478    
479     if (!this->pin)
480     return gpg_error (GPG_ERR_INV_OBJ);
481    
482     this->edit.sex = sex;
483     err = gpg_card_edit (ctx, this);
484     return err;
485     }
486    
487     gpgme_error_t
488     GpgCardEdit::updateLanguage (const char *lang)
489     {
490     gpgme_error_t err;
491    
492     if (!this->pin)
493     return gpg_error (GPG_ERR_INV_OBJ);
494    
495     this->edit.lang = lang;
496     err = gpg_card_edit (ctx, this);
497     return err;
498     }
499    
500    
501     /* Fetch the key specified by the url stored on the card.
502     Return value: 0 on success. */
503     gpgme_error_t
504     GpgCardEdit::fetchKey (void)
505     {
506     gpgme_error_t err = 0;
507    
508     if (!this->pin)
509     return gpg_error (GPG_ERR_INV_OBJ);
510    
511     return 0;
512     }
513    
514    
515     gpgme_error_t
516     GpgCardEdit:: doCmd (int cmd, const char *arg1, const char *arg2)
517     {
518     switch (cmd) {
519     case GPG_EDITCARD_NAME:
520     return updateName (arg1, arg2); /* given, surname */
521    
522     case GPG_EDITCARD_LANG:
523     return updateLanguage (arg1); /* lang */
524    
525     case GPG_EDITCARD_SEX:
526     return updateSex (*arg1); /* sex */
527    
528     case GPG_EDITCARD_KEYURL:
529     return updateURL (arg1); /* url */
530    
531     case GPG_EDITCARD_LOGIN:
532     return updateLogin (arg1); /* login */
533     }
534    
535     return 0;
536     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26