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

Diff of /trunk/Src/wptCardEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.24  
changed lines
  Added in v.271

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26