/[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 42 by werner, Fri Oct 28 08:25:30 2005 UTC revision 150 by twoaday, Wed Jan 18 11:52:45 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-2005 Timo Schulz   *      Copyright (C) 2001-2006 Timo Schulz
3   *   *
4   * This file is part of MyGPGME.   * This file is part of MyGPGME.
5   *   *
# Line 17  Line 17 
17   * along with this program; if not, write to the Free Software   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19   */   */
20    
21  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
22  #include <config.h>  #include <config.h>
23  #endif  #endif
24    
25  #include <windows.h>  #include <windows.h>
 #include <windows.h>  
26  #include <stdio.h>  #include <stdio.h>
27  #include <string.h>  #include <string.h>
28  #include <malloc.h>  #include <malloc.h>
29  #include <ctype.h>  #include <ctype.h>
30  #include <assert.h>  #include <assert.h>
31    #include <gpgme.h>
32    
 #include "w32gpgme.h"  
33  #include "wptKeyCache.h"  #include "wptKeyCache.h"
34  #include "openpgp.h"  #include "openpgp.h"
35  #include "wptNLS.h"  #include "wptNLS.h"
36  #include "wptErrors.h"  #include "wptErrors.h"
37  #include "wptW32API.h"  #include "wptW32API.h"
38    #include "wptGPG.h"
39    
40    
41  /* convert a binary buffer into its hex representation. */  /* Attribute list which holds the image data. */
42  static void  struct attr_list_s {
43  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)      struct attr_list_s *next;
44  {      char *fpr;                   /* fingerprint of the key */
45      char dig[3];      unsigned char *d;            /* actual JPEG data. */
46      size_t i;      unsigned long octets;        /* length of the data. */
47        unsigned int flags;          /* status of the attribute. */
48    };
49    typedef struct attr_list_s *attr_list_t;
50    
51    
52      memset (dst, 0, dlen);  void
53      for (i = 0; i < nbytes && dlen > 0; i++) {  free_attr_list (attr_list_t ctx)
54          sprintf (dig, "%02X", buf[i]);  {
55          strcat (dst, dig);      attr_list_t n;
56          dlen -= 2;      while (ctx) {
57            n = ctx->next;
58            free (ctx->fpr);
59            free (ctx->d);
60            ctx = n;
61      }      }
62  }  }
63            
64    /* Parse the attribute list in @fp and store it into @ctx.
65       Return value: number of parsed items. */
66    int
67    parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
68    {
69        attr_list_t c, t;
70        char buf[512], *p, *buffer;
71        int pos, n=0;
72        
73        *ctx = NULL;
74        while (fgets (buf, 511, fp)) {
75            if (strstr (buf, "\r\n"))
76                buf[strlen (buf)-2]=0;
77            if (strstr (buf, "\n"))
78                buf[strlen (buf)-1]=0;
79            if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
80                continue;
81            buffer = buf+9+10;
82            pos = 0;
83            c = (attr_list_t)calloc (1, sizeof *c);
84            p = strtok (buffer, " ");
85            while (p != NULL) {
86                switch (pos) {
87                case 0:
88                    c->fpr = strdup (p);
89                    break;
90                    
91                case 1:
92                    c->octets = strtoul (p, NULL, 10);
93                    break;
94                    
95                case 7:
96                    c->flags = strtoul (p, NULL, 10);
97                    break;
98                    
99                default:
100                    break;
101                }
102                pos++;
103                p = strtok (NULL, " ");
104            }
105            /*printf ("id=%s octets=%d flags=%d\n", c->fpr, c->octets, c->flags);*/
106            if (!*ctx)
107                *ctx = c;
108            else {
109                for (t = *ctx; t->next; t=t->next)
110                    ;
111                t->next = c;
112            }
113            c->d = (unsigned char*)malloc (c->octets);
114            memcpy (c->d, data, c->octets);
115            data += c->octets;
116            datlen -= c->octets;
117            n++;
118        }
119        /*assert (datlen == 0); */
120        return n;
121    }
122    
123    
124    static int
125    parse_attr_data (const char *keyid, attr_list_t *list)
126    {
127        gpgme_error_t err;
128        FILE *tmp;
129        char *status;
130        BYTE *data;
131        DWORD ndata;
132    
133        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
134        if (err)
135            return err;
136    
137        if (ndata > 0) {
138            tmp = tmpfile ();
139            fwrite (status, 1, strlen (status), tmp);
140            fflush (tmp);
141            rewind (tmp);
142    
143            ndata = parse_attr_list (tmp, data, ndata, list);
144            fclose (tmp);
145        }
146        else
147            *list = NULL;
148    
149        safe_free (status);
150        safe_free (data);
151        return ndata;
152    }
153    
154    
155  /* Parse the secret keyring and retrieve some additional information  /* Parse the secret keyring and retrieve some additional information
# Line 58  buffer_to_string (char *dst, size_t dlen Line 157  buffer_to_string (char *dst, size_t dlen
157  static void  static void
158  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
159  {      {    
160      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
161      PKT_secret_key *sk;      PKT_secret_key *sk;
162      gpg_iobuf_t inp;      gpg_iobuf_t inp;
163      gpgme_error_t err;      gpgme_error_t err;
# Line 67  parse_secring (gpg_keycache_t cache, con Line 166  parse_secring (gpg_keycache_t cache, con
166      char keyid[16+1];      char keyid[16+1];
167    
168      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
169      if (!inp) {      if (!inp)
         safe_free (pkt);  
170          return;          return;
171      }  
172      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
173        pkt = (PACKET*)calloc (1, sizeof *pkt);
174      gpg_init_packet (pkt);      gpg_init_packet (pkt);
175      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
176          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 100  next: Line 199  next:
199  }  }
200    
201    
202    /* Update the photo image of a single key with the fingerprint
203       @fpr. The @dat struct contains the new item data. */
204    static gpgme_error_t
205    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
206    {
207        struct keycache_s *fnd = NULL;
208        gpgme_key_t key;
209        
210        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
211        if (!fnd)
212            return gpg_error (GPG_ERR_NOT_FOUND);
213        safe_free (fnd->attrib.d);
214        fnd->attrib.flags = dat->flags;
215        fnd->attrib.len = dat->octets;
216        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
217        memcpy (fnd->attrib.d, dat->d, dat->octets);
218        return 0;
219    }
220    
221    
222    /* Update all photo images in the cache. */
223    static gpgme_error_t
224    keycache_update_photos (gpg_keycache_t ctx)
225    {
226        attr_list_t list=NULL, n;
227        DWORD ndata;
228    
229        ndata = parse_attr_data (NULL, &list);
230        if (ndata < 1) {
231            free_attr_list (list);
232            return 0;
233        }
234    
235        for (n=list; n; n=n->next)
236            keycache_update_photo (ctx, n->fpr, n);
237        free_attr_list (list);
238        return 0;
239    }
240    
241    
242  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
243  gpgme_error_t  gpgme_error_t
244  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
245                     const char *pubring, const char *secring)                     const char *pubring, const char *secring)
246  {  {
247      gpgme_error_t err;      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
248      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
249      gpg_iobuf_t inp;      gpg_iobuf_t inp;
250      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
251      struct keycache_s *c;      struct keycache_s *c;
252      const byte *sym_prefs;      const byte *sym_prefs;
253      char keyid[16+1], *id = NULL;      char keyid[16+1];
254      int key_seen = 0;      int key_seen = 0;
255      size_t nbytes = 0, nsym =0;      size_t nsym =0;
256    
257      if (secring) {      if (secring) {
258          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
259          if (!pubring) {          if (!pubring)
             safe_free(pkt);  
260              return 0;              return 0;
         }  
261      }      }
262      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
263      if (!inp) {      if (!inp)
         safe_free( pkt );  
264          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
265      }      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
     gpg_iobuf_ioctl( inp, 3, 1, NULL ); /* disable cache */  
266    
267      gpg_init_packet( pkt );      pkt = (PACKET*)calloc (1, sizeof * pkt);
268        gpg_init_packet (pkt);
269      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
270          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
271              strcpy (keyid, "");              strcpy (keyid, "");
272              key_seen = 1;              key_seen = 1;
273          }          }
274    
275          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_SIGNATURE &&
276                pkt->pkt.signature->sig_class == 0x1F) {
277              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
278                  goto next;                  goto next;
279              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
280                            pkt->pkt.signature->keyid[1]);
281              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
282                  goto next;                  goto next;
283              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 148  keycache_prepare2 (gpg_keycache_t ctx, c Line 286  keycache_prepare2 (gpg_keycache_t ctx, c
286              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
287          }          }
288          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
289              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
290                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
291              if (sym_prefs == NULL)              if (!sym_prefs)
292                  goto next;                  goto next;
293              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
294                            pkt->pkt.signature->keyid[1]);
295              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
296                  goto next;                  goto next;
297              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 165  keycache_prepare2 (gpg_keycache_t ctx, c Line 304  keycache_prepare2 (gpg_keycache_t ctx, c
304                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
305              }              }
306          }          }
         if (pkt->pkttype == PKT_USER_ID) {  
             if (id)  
                 free (id);  
             id = strdup (pkt->pkt.user_id->name);  
             if (!id) {  
                 err = gpg_error (GPG_ERR_ENOMEM);  
                 goto fail;  
             }  
         }  
         if ((pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE)  
             && pkt->pkt.user_id->attrib_data && key) {  
             PKT_user_id *id = pkt->pkt.user_id;  
             c->attrib.used = 1;  
             c->attrib.len = id->attrib_len;  
             c->attrib.d = (unsigned char*)calloc (1, id->attrib_len + 1);  
             if (!c->attrib.d) {  
                 err = gpg_error (GPG_ERR_ENOMEM);  
                 goto fail;  
             }  
             memcpy (c->attrib.d, id->attrib_data, id->attrib_len);  
             key = NULL;  
             c = NULL;  
         }  
307  next:  next:
308          gpg_free_packet (pkt);          gpg_free_packet (pkt);
309          gpg_init_packet(pkt);          gpg_init_packet(pkt);
310      }      }
311    
 fail:  
     safe_free (id);  
312      safe_free (pkt);      safe_free (pkt);
313      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
314      return err;      return err;
# Line 249  gpg_keycache_release (gpg_keycache_t ctx Line 363  gpg_keycache_release (gpg_keycache_t ctx
363          c2 = c->next;          c2 = c->next;
364          gpgme_key_release (c->key);          gpgme_key_release (c->key);
365          c->key = NULL;          c->key = NULL;
366          if (c->sym_prefs)          safe_free (c->sym_prefs);
367              free (c->sym_prefs);          safe_free (c->attrib.d);
368          c->sym_prefs = NULL;          safe_free (c->card_type);
         if (c->attrib.d)  
             free (c->attrib.d);  
         c->attrib.d = NULL;  
         if (c->card_type)  
             free (c->card_type);  
369          free (c);          free (c);
370      }      }
371      if (ctx)      safe_free (ctx);
         free (ctx);  
372  }  }
373    
374    
# Line 365  gpg_keycache_find_key2 (gpg_keycache_t c Line 473  gpg_keycache_find_key2 (gpg_keycache_t c
473      }      }
474      *r_key = NULL;      *r_key = NULL;
475      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
476  } /* keycache_find_key */  }
477    
478    
479  gpgme_error_t  gpgme_error_t
# Line 376  gpg_keycache_find_key (gpg_keycache_t ct Line 484  gpg_keycache_find_key (gpg_keycache_t ct
484  }  }
485    
486    
487    /* Reload a photo image of a single key with the keyid @keyid.
488       Return value: 0 on success. */
489    static gpgme_error_t
490    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
491    {
492        attr_list_t list;
493    
494        if (parse_attr_data (keyid, &list) < 1) {
495            free_attr_list (list);
496            return 0;
497        }
498        keycache_update_photo (ctx, list->fpr, list);
499        free_attr_list (list);
500        return 0;
501    }
502    
503    
504    /* Return the next key which was updated. Before it is
505       returned the update flag is cleared.
506       @r_status is 1 for a new key and 2 for an updated key.
507       Return value: 0 on success. */
508    gpgme_error_t
509    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
510                                   struct keycache_s **r_obj,
511                                   int *r_status)
512    {
513        struct keycache_s *c;
514    
515        for (c = ctx->item; c; c = c->next) {
516            if (c->flags != 0) {
517                *r_status = c->flags;
518                c->flags = 0;
519                *r_obj = c;
520                return 0;
521            }
522        }
523        return gpg_error (GPG_ERR_NOT_FOUND);
524    }
525    
526    
527    
528  gpgme_error_t  gpgme_error_t
529  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
530                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 389  gpg_keycache_update_key (gpg_keycache_t Line 538  gpg_keycache_update_key (gpg_keycache_t
538      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
539      if (err)      if (err)
540          return err;          return err;
541        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS);
542      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
543      gpgme_release (gctx);      gpgme_release (gctx);
544      if (err)      if (err)
# Line 398  gpg_keycache_update_key (gpg_keycache_t Line 548  gpg_keycache_update_key (gpg_keycache_t
548          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
549          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
550          c->key = key;          c->key = key;
551          c->flags = 0;          c->flags = KC_FLAG_UPD;
552          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
553              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
554              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
555              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
556          }          }
557            /* XXX: this is also called for keys without a photo-id. */
558            keycache_reload_photo (ctx, keyid);
559      }      }
560      else {      else {
561          log_debug ("keycache add: sync public part\r\n");          log_debug ("keycache add: sync public part\r\n");
# Line 419  gpg_keycache_update_key (gpg_keycache_t Line 571  gpg_keycache_update_key (gpg_keycache_t
571                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
572              }              }
573          }          }
574            if (c)
575                c->flags = KC_FLAG_ADD;
576      }      }
577      return 0;      return 0;
578  }  }
# Line 488  gpg_keycache_init (gpg_keycache_t ctx, c Line 642  gpg_keycache_init (gpg_keycache_t ctx, c
642      }      }
643      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
644          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
645        keycache_update_photos (ctx);
646      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
647      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
648      gpgme_release (c);      gpgme_release (c);
# Line 515  key_divert_to_card (gpgme_key_t key) Line 670  key_divert_to_card (gpgme_key_t key)
670  }  }
671    
672    
673    static unsigned char*
674    copy_uid_prefs (const unsigned char *prefs)
675    {
676        unsigned char *p;
677        size_t pos=0;
678    
679        while (prefs[pos] != 0)
680            pos++;
681        p = (unsigned char*)calloc (1, pos+1);
682        if (!p)
683            abort ();
684        memcpy (p, prefs, pos);
685        return p;
686    }
687    
688    
689  gpgme_error_t  gpgme_error_t
690  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
691  {  {
# Line 530  gpg_keycache_sync (gpg_keycache_t pub, g Line 701  gpg_keycache_sync (gpg_keycache_t pub, g
701              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
702              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
703                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
704                c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
705              c->pubpart = c_sec;              c->pubpart = c_sec;
706              c->pubpart->key = key;              c->pubpart->key = key;
707          }          }
# Line 578  keycache_next_key (gpg_keycache_t ctx, i Line 750  keycache_next_key (gpg_keycache_t ctx, i
750          *r_key = NULL;          *r_key = NULL;
751          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
752      }      }
753            if (ctx->tmp->flags != 0)
754            ctx->tmp->flags = 0; /* reset the 'updated' status. */
755      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
756      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp = ctx->tmp->next;
757      ctx->pos++;      ctx->pos++;

Legend:
Removed from v.42  
changed lines
  Added in v.150

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26