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

Diff of /trunk/Src/wptKeyCache.cpp

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

revision 133 by twoaday, Mon Jan 9 09:15:29 2006 UTC revision 234 by twoaday, Tue Jun 27 10:16:41 2006 UTC
# Line 1  Line 1 
1  /* wptKeyCache.cpp- Caching for the pub- and the secring  /* wptKeyCache.cpp- Caching for the pub- and the secring
2   *      Copyright (C) 2001-2006 Timo Schulz   *      Copyright (C) 2001-2006 Timo Schulz
3   *   *
4   * This file is part of MyGPGME.   * This file is part of WinPT.
5   *   *
6   * MyGPGME 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   * MyGPGME 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.
# Line 25  Line 25 
25  #include <windows.h>  #include <windows.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <string.h>  #include <string.h>
 #include <malloc.h>  
28  #include <ctype.h>  #include <ctype.h>
29  #include <assert.h>  #include <assert.h>
30  #include <gpgme.h>  #include <gpgme.h>
# Line 36  Line 35 
35  #include "wptErrors.h"  #include "wptErrors.h"
36  #include "wptW32API.h"  #include "wptW32API.h"
37  #include "wptGPG.h"  #include "wptGPG.h"
38    #include "wptTypes.h"
39    #include "wptCommonCtl.h"
40    #include "wptContext.h"
41    #include "wptKeyEdit.h"
42    #include "wptUTF8.h"
43    
44    
45    gpgme_error_t parse_keyserver_url (char **r_keyserver, unsigned short *r_port);
46    
47  /* Attribute list which holds the image data. */  /* Attribute list which holds the image data. */
48  struct attr_list_s {  struct attr_list_s {
49      struct attr_list_s *next;      struct attr_list_s *next;
# Line 49  struct attr_list_s { Line 55  struct attr_list_s {
55  typedef struct attr_list_s *attr_list_t;  typedef struct attr_list_s *attr_list_t;
56    
57    
58    /* XXX: convert it to an inline function and place it in a header file. */
59    static unsigned char*
60    safe_uchar_alloc (size_t n)
61    {
62        unsigned char *p = new unsigned char[n];
63        if (!p)
64            BUG (0);
65        return p;
66    }
67    
68    
69    /* Free attribute list @ctx. */
70  void  void
71  free_attr_list (attr_list_t ctx)  free_attr_list (attr_list_t ctx)
72  {  {
73      attr_list_t n;      attr_list_t n;
74    
75      while (ctx) {      while (ctx) {
76          n = ctx->next;          n = ctx->next;
77          free (ctx->fpr);          free_if_alloc (ctx->fpr);
78          free (ctx->d);          free_if_alloc (ctx->d);
79            free_if_alloc (ctx);
80          ctx = n;          ctx = n;
81      }      }
82  }  }
# Line 80  parse_attr_list (FILE *fp, const BYTE *d Line 100  parse_attr_list (FILE *fp, const BYTE *d
100              continue;              continue;
101          buffer = buf+9+10;          buffer = buf+9+10;
102          pos = 0;          pos = 0;
103          c = (attr_list_t)calloc (1, sizeof *c);          c = new attr_list_s;
104            if (!c)
105                BUG (0);
106            memset (c, 0, sizeof *c);
107    
108          p = strtok (buffer, " ");          p = strtok (buffer, " ");
109          while (p != NULL) {          while (p != NULL) {
110              switch (pos) {              switch (pos) {
111              case 0:              case 0:
112                  c->fpr = strdup (p);                  c->fpr = m_strdup (p);
113                  break;                  break;
114                                    
115              case 1:              case 1:
# Line 102  parse_attr_list (FILE *fp, const BYTE *d Line 126  parse_attr_list (FILE *fp, const BYTE *d
126              pos++;              pos++;
127              p = strtok (NULL, " ");              p = strtok (NULL, " ");
128          }          }
         /*printf ("id=%s octets=%d flags=%d\n", c->fpr, c->octets, c->flags);*/  
129          if (!*ctx)          if (!*ctx)
130              *ctx = c;              *ctx = c;
131          else {          else {
# Line 110  parse_attr_list (FILE *fp, const BYTE *d Line 133  parse_attr_list (FILE *fp, const BYTE *d
133                  ;                  ;
134              t->next = c;              t->next = c;
135          }          }
136          c->d = (unsigned char*)malloc (c->octets);          c->d = safe_uchar_alloc (c->octets);
137          memcpy (c->d, data, c->octets);          memcpy (c->d, data, c->octets);
138          data += c->octets;          data += c->octets;
139          datlen -= c->octets;          datlen -= c->octets;
# Line 125  static int Line 148  static int
148  parse_attr_data (const char *keyid, attr_list_t *list)  parse_attr_data (const char *keyid, attr_list_t *list)
149  {  {
150      gpgme_error_t err;      gpgme_error_t err;
151      FILE *tmp;      FILE *tmp;    
     char *status;  
152      BYTE *data;      BYTE *data;
153      DWORD ndata;      char *status, tmpnam[MAX_PATH+1];
154        DWORD ndata = 0;
155    
156      err = gpg_get_photoid_data (keyid, &status, &data, &ndata);      err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
157      if (err)      if (err)
158          return err;          return err;
159    
160      if (ndata > 0) {      get_temp_name (tmpnam, MAX_PATH, NULL);
161          tmp = tmpfile ();      tmp = fopen (tmpnam, "w+b");
162        if (ndata > 0 && tmp != NULL) {
163          fwrite (status, 1, strlen (status), tmp);          fwrite (status, 1, strlen (status), tmp);
164          fflush (tmp);          fflush (tmp);
165          rewind (tmp);          rewind (tmp);
166    
167          ndata = parse_attr_list (tmp, data, ndata, list);          ndata = parse_attr_list (tmp, data, ndata, list);
168          fclose (tmp);          fclose (tmp);
169            DeleteFile (tmpnam);
170      }      }
171      else      else
172          *list = NULL;          *list = NULL;
# Line 171  parse_secring (gpg_keycache_t cache, con Line 196  parse_secring (gpg_keycache_t cache, con
196    
197      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
198      pkt = (PACKET*)calloc (1, sizeof *pkt);      pkt = (PACKET*)calloc (1, sizeof *pkt);
199        if (!pkt)
200            BUG (0);
201      gpg_init_packet (pkt);      gpg_init_packet (pkt);
202      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
203          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 185  parse_secring (gpg_keycache_t cache, con Line 212  parse_secring (gpg_keycache_t cache, con
212                  goto next;                  goto next;
213              c->gloflags.is_protected = sk->is_protected;              c->gloflags.is_protected = sk->is_protected;
214              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
215              if (c->pubpart != NULL) {                  if (c->pubpart != NULL) {
216                  c->pubpart->gloflags.is_protected = sk->is_protected;                      c->pubpart->gloflags.is_protected = sk->is_protected;
217                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
218              }              }
219          }          }
# Line 210  keycache_update_photo (gpg_keycache_t ct Line 237  keycache_update_photo (gpg_keycache_t ct
237      gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);      gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
238      if (!fnd)      if (!fnd)
239          return gpg_error (GPG_ERR_NOT_FOUND);          return gpg_error (GPG_ERR_NOT_FOUND);
240      safe_free (fnd->attrib.d);      free_if_alloc (fnd->attrib.d);
241      fnd->attrib.flags = dat->flags;      fnd->attrib.flags = dat->flags;
242      fnd->attrib.len = dat->octets;      fnd->attrib.len = dat->octets;
243      fnd->attrib.d = (unsigned char*)malloc (dat->octets);      fnd->attrib.d = safe_uchar_alloc (dat->octets);
244      memcpy (fnd->attrib.d, dat->d, dat->octets);      memcpy (fnd->attrib.d, dat->d, dat->octets);
245      return 0;      return 0;
246  }  }
# Line 239  keycache_update_photos (gpg_keycache_t c Line 266  keycache_update_photos (gpg_keycache_t c
266  }  }
267    
268    
269    void
270    keycache_decode_uid (struct keycache_s *ctx)
271    {
272        gpgme_user_id_t u;
273        struct native_uid_s *n, *t;
274    
275        for (u = ctx->key->uids; u; u = u->next) {
276            n = new native_uid_s;
277            if (!n)
278                BUG (0);
279            memset (n, 0, sizeof *n);
280            if (is_8bit_string (u->uid)) {
281                n->malloced = 1;
282                n->uid = utf8_to_native (u->uid);
283                if (u->name != NULL)
284                    n->name = utf8_to_native (u->name);
285                if (u->email != NULL)
286                    n->email = m_strdup (u->email);
287                if (u->comment != NULL)
288                    n->comment = utf8_to_native (u->comment);
289            }
290            else {
291                n->malloced = 0;
292                n->uid = u->uid;
293                n->name = u->name;
294                n->comment = u->comment;
295                n->email = u->email;
296            }
297            n->signatures = u->signatures;
298            n->validity = u->validity;
299            n->revoked = u->revoked;
300            if (!ctx->uids)
301                ctx->uids = n;
302            else {
303                for (t = ctx->uids; t->next; t=t->next)
304                    ;
305                t->next = n;          
306            }
307        }
308    }
309    
310    
311    /* Store utf8 decoded user IDs in the code to avoid in-place decoding. */
312    static void
313    keycache_decode_uids (gpg_keycache_t ctx)
314    {
315        struct keycache_s *c;
316    
317        for (c = ctx->item; c; c = c->next)
318            keycache_decode_uid (c);
319    }
320    
321    
322    static void
323    free_native_uids (struct native_uid_s **r_n)
324    {
325        struct native_uid_s *t;
326        struct native_uid_s *n = *r_n;
327    
328        while (n != NULL) {
329            t = n->next;
330            if (n->malloced) {
331                free_if_alloc (n->uid);
332                free_if_alloc (n->name);
333                free_if_alloc (n->comment);
334                free_if_alloc (n->email);
335            }
336            free_if_alloc (n);
337            n = t;
338        }
339        *r_n = NULL;
340    }
341    
342    
343    
344  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
345  gpgme_error_t  static gpgme_error_t
346  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
347                     const char *pubring, const char *secring)                     const char *pubring, const char *secring)
348  {  {
# Line 249  keycache_prepare2 (gpg_keycache_t ctx, c Line 351  keycache_prepare2 (gpg_keycache_t ctx, c
351      gpg_iobuf_t inp;      gpg_iobuf_t inp;
352      PACKET *pkt;      PACKET *pkt;
353      struct keycache_s *c;      struct keycache_s *c;
354      const byte *sym_prefs;      const BYTE *sym_prefs;
355      char keyid[16+1];      char keyid[16+1];
356      int key_seen = 0;      int key_seen = 0;
357      size_t nsym =0;      size_t nsym =0;
# Line 265  keycache_prepare2 (gpg_keycache_t ctx, c Line 367  keycache_prepare2 (gpg_keycache_t ctx, c
367      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
368    
369      pkt = (PACKET*)calloc (1, sizeof * pkt);      pkt = (PACKET*)calloc (1, sizeof * pkt);
370        if (!pkt)
371            BUG (0);
372      gpg_init_packet (pkt);      gpg_init_packet (pkt);
373      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
374          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
375              strcpy (keyid, "");              strcpy (keyid, "");
376              key_seen = 1;              key_seen = 1;
377          }          }
   
378          if (pkt->pkttype == PKT_SIGNATURE &&          if (pkt->pkttype == PKT_SIGNATURE &&
379              pkt->pkt.signature->sig_class == 0x1F) {              pkt->pkt.signature->sig_class == 0x1F) {
380              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
# Line 285  keycache_prepare2 (gpg_keycache_t ctx, c Line 388  keycache_prepare2 (gpg_keycache_t ctx, c
388                  goto next;                  goto next;
389              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
390          }          }
391          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 && c != NULL) {
392              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
393                                                SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
394              if (!sym_prefs)              if (!sym_prefs)
# Line 295  keycache_prepare2 (gpg_keycache_t ctx, c Line 398  keycache_prepare2 (gpg_keycache_t ctx, c
398              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
399                  goto next;                  goto next;
400              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
401              if (err)              if (err || !c)
402                    goto next;
403                if (c->sym_prefs) // only use the prefs from the primary uid.
404                  goto next;                  goto next;
405              else if (nsym > 0) {              else if (nsym > 0) {
406                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  c->sym_prefs = safe_uchar_alloc (nsym+1);
407                  if (!c->sym_prefs)                  memset (c->sym_prefs, 0, nsym+1);
                     return gpg_error (GPG_ERR_ENOMEM);  
408                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
409              }              }
410          }          }
# Line 340  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 444  gpg_keycache_new (gpg_keycache_t *r_ctx)
444            
445      if (!r_ctx)      if (!r_ctx)
446          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
447      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);      ctx = new gpg_keycache_s;    
448      if (!ctx)      if (!ctx)
449          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
450        memset (ctx, 0, sizeof *ctx);
451      ctx->secret = 0;      ctx->secret = 0;
452      ctx->pos = 0;      ctx->pos = 0;
453      *r_ctx = ctx;      *r_ctx = ctx;
# Line 350  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 455  gpg_keycache_new (gpg_keycache_t *r_ctx)
455  }  }
456    
457    
458    void
459    gpg_keycache_item_release (struct keycache_s *c)
460    {
461        if (c->key)
462            gpgme_key_release (c->key);    
463        c->key = NULL;      
464        if (c->rev != NULL)    
465            gpg_desig_rev_release (c->rev);
466        c->rev = NULL;
467        free_if_alloc (c->pref_keyserver);
468        free_if_alloc (c->sym_prefs);
469        free_if_alloc (c->attrib.d);
470        free_if_alloc (c->card_type);
471        free_native_uids (&c->uids);
472        free_if_alloc (c);
473    }
474    
475    
476  /* Release keycache object @ctx. */  /* Release keycache object @ctx. */
477  void  void
478  gpg_keycache_release (gpg_keycache_t ctx)  gpg_keycache_release (gpg_keycache_t ctx)
# Line 361  gpg_keycache_release (gpg_keycache_t ctx Line 484  gpg_keycache_release (gpg_keycache_t ctx
484    
485      for (c = ctx->item; c; c = c2) {      for (c = ctx->item; c; c = c2) {
486          c2 = c->next;          c2 = c->next;
487          gpgme_key_release (c->key);          gpg_keycache_item_release (c);
         c->key = NULL;  
         safe_free (c->sym_prefs);  
         safe_free (c->attrib.d);  
         safe_free (c->card_type);  
         free (c);  
488      }      }
489      safe_free (ctx);      free_if_alloc (ctx);
490  }  }
491    
492    
# Line 400  gpg_keycache_add_key (gpg_keycache_t ctx Line 518  gpg_keycache_add_key (gpg_keycache_t ctx
518      if (!ctx)      if (!ctx)
519          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
520            
521      c = (struct keycache_s*)calloc (1, sizeof *c);      c = new keycache_s;
522      if (!c)      if (!c)
523          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
524        memset (c, 0, sizeof *c);
525      c->gloflags.is_protected = 1; /*default: assume protection. */      c->gloflags.is_protected = 1; /*default: assume protection. */
526      c->key = key;      c->key = key;
527      if (!ctx->item)      if (!ctx->item)
# Line 501  keycache_reload_photo (gpg_keycache_t ct Line 620  keycache_reload_photo (gpg_keycache_t ct
620  }  }
621    
622    
623    /* Return the next key which was updated. Before it is
624       returned the update flag is cleared.
625       @r_status is 1 for a new key and 2 for an updated key.
626       Return value: 0 on success. */
627    gpgme_error_t
628    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
629                                   struct keycache_s **r_obj,
630                                   int *r_status)
631    {
632        struct keycache_s *c;
633    
634        for (c = ctx->item; c; c = c->next) {
635            if (c->flags != 0) {
636                *r_status = c->flags;
637                *r_obj = c;
638                c->flags = 0; /* reset update flag. */
639                return 0;
640            }
641        }
642        return gpg_error (GPG_ERR_NOT_FOUND);
643    }
644    
645    
646    /* Helper to retrieve a GPG key. */
647    static gpgme_error_t
648    get_gpg_key (const char *keyid, int is_sec, gpgme_key_t *r_key)
649    {
650        gpgme_ctx_t ctx;
651        gpgme_error_t err;
652    
653        err = gpgme_new (&ctx);
654        if (err)
655            return err;
656        gpgme_set_keylist_mode  (ctx, GPGME_KEYLIST_MODE_SIGS);
657        err = gpgme_get_key (ctx, keyid, r_key, is_sec);
658        gpgme_release (ctx);
659        return err;
660    }
661    
662    
663    /* Fetch a key directly from gpg but without adding
664       it to the key cache. Caller must free @r_ctx. */
665    gpgme_error_t
666    gpg_keycache_fetch_key (const char *keyid, int is_sec,
667                            gpgme_key_t *r_key, struct keycache_s **r_c)
668    {
669        gpgme_error_t err;
670        gpgme_key_t key;
671        struct keycache_s *c;
672    
673        *r_key = NULL;
674        *r_c = NULL;
675        err = get_gpg_key (keyid, is_sec, &key);
676        if (err)
677            return err;
678    
679        c = new keycache_s;
680        if (!c)
681            BUG (0);
682        memset (c, 0, sizeof *c);
683        c->gloflags.is_protected = 1; /*default: assume protection. */
684        c->key = key;    
685        keycache_decode_uid (c);
686        *r_key = key;
687        *r_c = c;
688        return 0;
689    }
690    
691    
692    /* Update the key with the keyid @key in the key cache.
693       If the key does not exist, it is added otherwise all
694       parts are first freed and then replaced with the updated data. */
695  gpgme_error_t  gpgme_error_t
696  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
697                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
698  {  {    
     struct keycache_s *c = NULL, *c_new=NULL;  
699      gpgme_key_t key=NULL, fndkey=NULL;      gpgme_key_t key=NULL, fndkey=NULL;
700      gpgme_error_t err;      gpgme_error_t err;
701      gpgme_ctx_t gctx;      struct keycache_s *c = NULL, *c_new=NULL;
702      gpg_keycache_t pub = (gpg_keycache_t)opaque;      gpg_keycache_t pub = (gpg_keycache_t)opaque;
703    
704      err = gpgme_new (&gctx);      err = get_gpg_key (keyid, is_sec, &key);
     if (err)  
         return err;  
     err = gpgme_get_key (gctx, keyid, &key, is_sec);  
     gpgme_release (gctx);  
705      if (err)      if (err)
706          return err;          return err;
707      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
# Line 523  gpg_keycache_update_key (gpg_keycache_t Line 709  gpg_keycache_update_key (gpg_keycache_t
709          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
710          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
711          c->key = key;          c->key = key;
712          c->flags = 0;          c->flags = KC_FLAG_UPD;
713          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
714              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
715              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
# Line 546  gpg_keycache_update_key (gpg_keycache_t Line 732  gpg_keycache_update_key (gpg_keycache_t
732                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
733              }              }
734          }          }
735            if (c != NULL)
736                c->flags = KC_FLAG_ADD;
737        }
738    
739        /* refresh utf8 user ID list. */
740        if (c != NULL && c->key) {
741            free_native_uids (&c->uids);
742            keycache_decode_uid (c);
743      }      }
744    
745      return 0;      return 0;
746  }  }
747    
# Line 568  gpg_keycache_delete_key (gpg_keycache_t Line 763  gpg_keycache_delete_key (gpg_keycache_t
763            
764      c = ctx->item;      c = ctx->item;
765      if (c->next == NULL) {      if (c->next == NULL) {
766          gpgme_key_release (itm->key);          if (itm->key)
767          if (itm)              gpgme_key_release (itm->key);
768              free (itm);          itm->key = NULL;
769          ctx->item = NULL;          free_if_alloc (itm);
770      }      }
771      else {      else {
772          while (c && c->next != itm)          for (; c != NULL; c = c->next) {
773              c = c->next;              if (c->next == itm)
774                    break;
775            }
776            assert (c != NULL); /* XXX: sometimes access violation. */
777          c->next = c->next->next;          c->next = c->next->next;
778          gpgme_key_release (itm->key);          if (itm->key)
779          if (itm)              gpgme_key_release (itm->key);
780              free (itm);          itm->key = NULL;
781            free_if_alloc (itm);
782      }      }
783      return 0;      return 0;
784  }  }
# Line 603  gpg_keycache_init (gpg_keycache_t ctx, c Line 802  gpg_keycache_init (gpg_keycache_t ctx, c
802      if (err)      if (err)
803          return err;          return err;
804    
805        /* XXX: GPGME_KEYLIST_MODE_SIG_NOTATIONS causes an internal error! */
806      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);
807      err = gpgme_op_keylist_start (c, pattern, secret);      err = gpgme_op_keylist_start (c, pattern, secret);
808      while(!err) {      while(!err) {
# Line 616  gpg_keycache_init (gpg_keycache_t ctx, c Line 816  gpg_keycache_init (gpg_keycache_t ctx, c
816      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
817          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
818      keycache_update_photos (ctx);      keycache_update_photos (ctx);
819      /* XXX: make sure the progress dialog is closed. */      keycache_decode_uids (ctx);
820      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
821      gpgme_release (c);      gpgme_release (c);
822      return err;      return err;
823  }  }
824    
825    
826  /* XXX: kludge to see if the key is stored on a card. */  /* Return 1 if we can assume that the actual private key is
827       stored on a smart card. This is not bullet proof, but the
828       card provides 3 keys (RSA) and each key for a different purpose. */
829  static int  static int
830  key_divert_to_card (gpgme_key_t key)  key_divert_to_card (gpgme_key_t key)
831  {  {
832      gpgme_subkey_t k;      gpgme_subkey_t k;
833      int n=0, n_alg=0, can_auth = 0;      int n=0, n_alg=0;
834        int can_auth = 0, can_encr = 0;
835    
836      for (k = key->subkeys; k; k = k->next) {      for (k = key->subkeys; k; k = k->next) {
837          n++;          n++;
# Line 636  key_divert_to_card (gpgme_key_t key) Line 839  key_divert_to_card (gpgme_key_t key)
839              n_alg++;              n_alg++;
840          if (k->can_authenticate)          if (k->can_authenticate)
841              can_auth++;              can_auth++;
842            if (k->can_encrypt)
843                can_encr++;
844      }      }
845      if (n == 3 && n_alg == 3 && can_auth == 1)      if (n == 3 && n_alg == 3 && can_auth == 1 && can_encr == 1)
846          return 1;          return 1;
847      return 0;      return 0;
848  }  }
# Line 651  copy_uid_prefs (const unsigned char *pre Line 856  copy_uid_prefs (const unsigned char *pre
856    
857      while (prefs[pos] != 0)      while (prefs[pos] != 0)
858          pos++;          pos++;
859      p = (unsigned char*)calloc (1, pos+1);      p = safe_uchar_alloc (pos+1);
860      if (!p)      memset (p, 0, pos+1);
         abort ();  
861      memcpy (p, prefs, pos);      memcpy (p, prefs, pos);
862      return p;      return p;
863  }  }
864    
865    
866    /* Sync the secret and the public key cache information. */
867  gpgme_error_t  gpgme_error_t
868  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
869  {  {
# Line 668  gpg_keycache_sync (gpg_keycache_t pub, g Line 873  gpg_keycache_sync (gpg_keycache_t pub, g
873      if (!pub || !sec)      if (!pub || !sec)
874          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
875            
876      for (c=sec->item; c; c=c->next) {        for (c=sec->item; c; c=c->next) {
877          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0,
878                                         &key, &c_sec)) {
879              c_sec->gloflags.is_protected = c->gloflags.is_protected;              c_sec->gloflags.is_protected = c->gloflags.is_protected;
880              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
881              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
882                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
883              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
884                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
885              c->pubpart = c_sec;              c->pubpart = c_sec;
886              c->pubpart->key = key;              c->pubpart->key = key;
887          }          }
# Line 723  keycache_next_key (gpg_keycache_t ctx, i Line 930  keycache_next_key (gpg_keycache_t ctx, i
930          *r_key = NULL;          *r_key = NULL;
931          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
932      }      }
933            if (ctx->tmp->flags != 0)
934            ctx->tmp->flags = 0; /* reset the 'updated' status. */
935    
936        /* it might be possible there is no public key. */
937        if (flags && ctx->tmp->pubpart == NULL)
938            flags = 0;
939      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
940      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp;
941        ctx->tmp = ctx->tmp->next;
942      ctx->pos++;      ctx->pos++;
943    
944      return 0;      return 0;
# Line 739  gpgme_error_t Line 952  gpgme_error_t
952  gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)  gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
953  {  {
954      struct keycache_s *c=NULL;      struct keycache_s *c=NULL;
955      gpgme_error_t err = 0;      gpgme_error_t err;
956    
957      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
958      return err;      return err;
959  }  }
960    
961    
962    gpgme_error_t
963    gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags,
964                            struct keycache_s **c, gpgme_key_t *r_key)
965    {
966        return keycache_next_key (ctx, flags, c, r_key);
967    }
968    
969    
970    /* Search for a key with the pattern @pattern and mark
971       this key as the default signing key if found.
972       Return value: 0 on success. */
973    gpgme_error_t
974    gpg_keycache_set_default_key (gpg_keycache_t ctx,
975                                  const char *pattern)
976    {
977        gpgme_error_t err;
978        gpgme_key_t key;
979        struct keycache_s *itm;
980    
981        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
982        if (err)
983            return err;
984    
985        if (itm)
986            itm->default_key = 1;
987        return 0;
988    }
989    
990    /* Return the default key from the cache. If no was
991       marked before, NULL is returned in @r_key.
992       Return value: 0 on success. */
993    gpgme_error_t
994    gpg_keycache_get_default_key (gpg_keycache_t ctx,
995                                  gpgme_key_t *r_key)
996    {
997        struct keycache_s *itm;
998    
999        *r_key = NULL;
1000        for (itm = ctx->item; itm; itm = itm->next) {
1001            if (itm->default_key) {
1002                *r_key = itm->key;
1003                break;
1004            }
1005        }
1006        if (!*r_key)
1007            return gpgme_error (GPG_ERR_NOT_FOUND);
1008        return 0;
1009    }
1010    
1011    
1012    static gpgme_error_t
1013    decode_subpacket (const char *subpkt_data, int *type,
1014                      char **out, WORD *outlen)
1015    {
1016        char tmp[128], *val;
1017        char *enc = NULL;      
1018        size_t pos = 0;
1019    
1020        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
1021        *outlen = 0;
1022        *out = NULL;
1023        
1024        if (strncmp (subpkt_data, "spk:", 4))
1025            return gpg_error (GPG_ERR_NO_DATA);
1026    
1027        /* XXX: do not use static buffer sizes. */
1028        strncpy (tmp, subpkt_data, DIM (tmp)-4);
1029        val = strtok (tmp, ":");
1030        while (val != NULL) {
1031            switch (pos++) {
1032            case 0:
1033                break;
1034    
1035            case 1:
1036                if (type)
1037                    *type = atoi (val);
1038                break;
1039    
1040            case 2:
1041                break;
1042    
1043            case 3:
1044                *outlen = atoi (val);
1045                break;
1046    
1047            case 4:
1048                enc = m_strdup (val);
1049                break;
1050            }
1051            val = strtok (NULL, ":");
1052        }
1053        if (!enc)
1054            return gpg_error (GPG_ERR_NO_DATA);
1055        unhexify_buffer (enc, out);
1056        free_if_alloc (enc);
1057        return 0;
1058    }
1059    
1060    
1061    /* If the attribute given in @attr is not set in the
1062       key cache object, try to update it. */
1063    gpgme_error_t
1064    gpg_keycache_update_attr (struct keycache_s *item,
1065                              int attr, int force)
1066    {
1067        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
1068        char *val = NULL;
1069        WORD n = 0;    
1070    
1071        switch (attr) {
1072        case KC_ATTR_PREFSYM:
1073            if (!force && item->sym_prefs)
1074                break;
1075            free_if_alloc (item->sym_prefs);
1076            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1077            if (!err && val != NULL)
1078                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
1079            break;
1080    
1081        case KC_ATTR_PREFKSERV:
1082            if (!force && item->pref_keyserver)
1083                break;
1084            free_if_alloc (item->pref_keyserver);
1085            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1086            if (!err && val != NULL)
1087                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
1088            if (!err && item->pref_keyserver)
1089                err = parse_keyserver_url (&item->pref_keyserver,
1090                                           &item->pref_keyserver_port);
1091            break;
1092        }
1093        safe_free (val);
1094        return err;
1095    }

Legend:
Removed from v.133  
changed lines
  Added in v.234

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26