/[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 123 by twoaday, Wed Dec 14 09:01:45 2005 UTC revision 175 by twoaday, Tue Feb 7 08:58:04 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 35  Line 35 
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  #if 0  /* Attribute list which holds the image data. */
42  /* convert a binary buffer into its hex representation. */  struct attr_list_s {
43  static void      struct attr_list_s *next;
44  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)      char *fpr;                   /* fingerprint of the key */
45  {      unsigned char *d;            /* actual JPEG data. */
46      char dig[3];      unsigned long octets;        /* length of the data. */
47      size_t i;      unsigned int flags;          /* status of the attribute. */
48    };
49    typedef struct attr_list_s *attr_list_t;
50    
51      memset (dst, 0, dlen);  
52      for (i = 0; i < nbytes && dlen > 0; i++) {  void
53          sprintf (dig, "%02X", buf[i]);  free_attr_list (attr_list_t ctx)
54          strcat (dst, dig);  {
55          dlen -= 2;      attr_list_t n;
56        while (ctx) {
57            n = ctx->next;
58            free (ctx->fpr);
59            free (ctx->d);
60            ctx = n;
61      }      }
62  }  }
63  #endif          
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        BYTE *data;
130        char *status, tmpnam[MAX_PATH+1];
131        DWORD ndata = 0;
132    
133        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
134        if (err)
135            return err;
136    
137        get_temp_name (tmpnam, MAX_PATH, NULL);
138        tmp = fopen (tmpnam, "w+b");
139        if (ndata > 0 && tmp != NULL) {
140            fwrite (status, 1, strlen (status), tmp);
141            fflush (tmp);
142            rewind (tmp);
143    
144            ndata = parse_attr_list (tmp, data, ndata, list);
145            fclose (tmp);
146            DeleteFile (tmpnam);
147        }
148        else
149            *list = NULL;
150    
151        safe_free (status);
152        safe_free (data);
153        return ndata;
154    }
155    
156    
157  /* Parse the secret keyring and retrieve some additional information  /* Parse the secret keyring and retrieve some additional information
# Line 60  buffer_to_string (char *dst, size_t dlen Line 159  buffer_to_string (char *dst, size_t dlen
159  static void  static void
160  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
161  {      {    
162      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
163      PKT_secret_key *sk;      PKT_secret_key *sk;
164      gpg_iobuf_t inp;      gpg_iobuf_t inp;
165      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 168  parse_secring (gpg_keycache_t cache, con
168      char keyid[16+1];      char keyid[16+1];
169    
170      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
171      if (!inp) {      if (!inp)
         safe_free (pkt);  
172          return;          return;
173      }  
174      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
175        pkt = (PACKET*)calloc (1, sizeof *pkt);
176      gpg_init_packet (pkt);      gpg_init_packet (pkt);
177      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
178          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 102  next: Line 201  next:
201  }  }
202    
203    
204    /* Update the photo image of a single key with the fingerprint
205       @fpr. The @dat struct contains the new item data. */
206    static gpgme_error_t
207    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
208    {
209        struct keycache_s *fnd = NULL;
210        gpgme_key_t key;
211        
212        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
213        if (!fnd)
214            return gpg_error (GPG_ERR_NOT_FOUND);
215        safe_free (fnd->attrib.d);
216        fnd->attrib.flags = dat->flags;
217        fnd->attrib.len = dat->octets;
218        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
219        memcpy (fnd->attrib.d, dat->d, dat->octets);
220        return 0;
221    }
222    
223    
224    /* Update all photo images in the cache. */
225    static gpgme_error_t
226    keycache_update_photos (gpg_keycache_t ctx)
227    {
228        attr_list_t list=NULL, n;
229        DWORD ndata;
230    
231        ndata = parse_attr_data (NULL, &list);
232        if (ndata < 1) {
233            free_attr_list (list);
234            return 0;
235        }
236    
237        for (n=list; n; n=n->next)
238            keycache_update_photo (ctx, n->fpr, n);
239        free_attr_list (list);
240        return 0;
241    }
242    
243    
244  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
245  gpgme_error_t  gpgme_error_t
246  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
# Line 110  keycache_prepare2 (gpg_keycache_t ctx, c Line 249  keycache_prepare2 (gpg_keycache_t ctx, c
249      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
250      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
251      gpg_iobuf_t inp;      gpg_iobuf_t inp;
252      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
253      struct keycache_s *c;      struct keycache_s *c;
254      const byte *sym_prefs;      const byte *sym_prefs;
255      char keyid[16+1], *id = NULL;      char keyid[16+1];
256      int key_seen = 0;      int key_seen = 0;
257      size_t nsym =0;      size_t nsym =0;
258    
259      if (secring) {      if (secring) {
260          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
261          if (!pubring) {          if (!pubring)
             safe_free (pkt);  
262              return 0;              return 0;
         }  
263      }      }
264      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
265      if (!inp) {      if (!inp)
         safe_free (pkt);  
266          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
     }  
267      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
268    
269        pkt = (PACKET*)calloc (1, sizeof * pkt);
270      gpg_init_packet (pkt);      gpg_init_packet (pkt);
271      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
272          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
# Line 138  keycache_prepare2 (gpg_keycache_t ctx, c Line 274  keycache_prepare2 (gpg_keycache_t ctx, c
274              key_seen = 1;              key_seen = 1;
275          }          }
276    
277          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_SIGNATURE &&
278                pkt->pkt.signature->sig_class == 0x1F) {
279              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
280                  goto next;                  goto next;
281              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
282                            pkt->pkt.signature->keyid[1]);
283              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
284                  goto next;                  goto next;
285              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 150  keycache_prepare2 (gpg_keycache_t ctx, c Line 288  keycache_prepare2 (gpg_keycache_t ctx, c
288              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
289          }          }
290          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
291              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
292                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
293              if (sym_prefs == NULL)              if (!sym_prefs)
294                  goto next;                  goto next;
295              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
296                            pkt->pkt.signature->keyid[1]);
297              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
298                  goto next;                  goto next;
299              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 167  keycache_prepare2 (gpg_keycache_t ctx, c Line 306  keycache_prepare2 (gpg_keycache_t ctx, c
306                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
307              }              }
308          }          }
         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 *uid = pkt->pkt.user_id;  
             c->attrib.used = 1;  
             c->attrib.len = uid->attrib_len;  
             c->attrib.d = (unsigned char*)calloc (1, uid->attrib_len + 1);  
             if (!c->attrib.d) {  
                 err = gpg_error (GPG_ERR_ENOMEM);  
                 goto fail;  
             }  
             memcpy (c->attrib.d, uid->attrib_data, uid->attrib_len);  
             key = NULL;  
             c = NULL;  
         }  
309  next:  next:
310          gpg_free_packet (pkt);          gpg_free_packet (pkt);
311          gpg_init_packet(pkt);          gpg_init_packet(pkt);
312      }      }
313    
 fail:  
     safe_free (id);  
314      safe_free (pkt);      safe_free (pkt);
315      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
316      return err;      return err;
# Line 251  gpg_keycache_release (gpg_keycache_t ctx Line 365  gpg_keycache_release (gpg_keycache_t ctx
365          c2 = c->next;          c2 = c->next;
366          gpgme_key_release (c->key);          gpgme_key_release (c->key);
367          c->key = NULL;          c->key = NULL;
368          if (c->sym_prefs)          safe_free (c->sym_prefs);
369              free (c->sym_prefs);          safe_free (c->attrib.d);
370          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);  
371          free (c);          free (c);
372      }      }
373      if (ctx)      safe_free (ctx);
         free (ctx);  
374  }  }
375    
376    
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 475  gpg_keycache_find_key2 (gpg_keycache_t c
475      }      }
476      *r_key = NULL;      *r_key = NULL;
477      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
478  } /* keycache_find_key */  }
479    
480    
481  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 486  gpg_keycache_find_key (gpg_keycache_t ct
486  }  }
487    
488    
489    /* Reload a photo image of a single key with the keyid @keyid.
490       Return value: 0 on success. */
491    static gpgme_error_t
492    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
493    {
494        attr_list_t list;
495    
496        if (parse_attr_data (keyid, &list) < 1) {
497            free_attr_list (list);
498            return 0;
499        }
500        keycache_update_photo (ctx, list->fpr, list);
501        free_attr_list (list);
502        return 0;
503    }
504    
505    
506    /* Return the next key which was updated. Before it is
507       returned the update flag is cleared.
508       @r_status is 1 for a new key and 2 for an updated key.
509       Return value: 0 on success. */
510    gpgme_error_t
511    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
512                                   struct keycache_s **r_obj,
513                                   int *r_status)
514    {
515        struct keycache_s *c;
516    
517        for (c = ctx->item; c; c = c->next) {
518            if (c->flags != 0) {
519                *r_status = c->flags;
520                c->flags = 0;
521                *r_obj = c;
522                return 0;
523            }
524        }
525        return gpg_error (GPG_ERR_NOT_FOUND);
526    }
527    
528    
529    
530  gpgme_error_t  gpgme_error_t
531  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
532                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 391  gpg_keycache_update_key (gpg_keycache_t Line 540  gpg_keycache_update_key (gpg_keycache_t
540      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
541      if (err)      if (err)
542          return err;          return err;
543        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS);
544      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
545      gpgme_release (gctx);      gpgme_release (gctx);
546      if (err)      if (err)
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 550  gpg_keycache_update_key (gpg_keycache_t
550          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
551          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
552          c->key = key;          c->key = key;
553          c->flags = 0;          c->flags = KC_FLAG_UPD;
554          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
555              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
556              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
557              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
558          }          }
559            /* XXX: this is also called for keys without a photo-id. */
560            keycache_reload_photo (ctx, keyid);
561      }      }
562      else {      else {
563          log_debug ("keycache add: sync public part\r\n");          log_debug ("keycache add: sync public part\r\n");
# Line 421  gpg_keycache_update_key (gpg_keycache_t Line 573  gpg_keycache_update_key (gpg_keycache_t
573                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
574              }              }
575          }          }
576            if (c)
577                c->flags = KC_FLAG_ADD;
578      }      }
579      return 0;      return 0;
580  }  }
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 644  gpg_keycache_init (gpg_keycache_t ctx, c
644      }      }
645      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
646          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
647        keycache_update_photos (ctx);
648      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
649      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
650      gpgme_release (c);      gpgme_release (c);
# Line 548  gpg_keycache_sync (gpg_keycache_t pub, g Line 703  gpg_keycache_sync (gpg_keycache_t pub, g
703              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
704              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
705                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
706              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
707                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
708              c->pubpart = c_sec;              c->pubpart = c_sec;
709              c->pubpart->key = key;              c->pubpart->key = key;
710          }          }
# Line 597  keycache_next_key (gpg_keycache_t ctx, i Line 753  keycache_next_key (gpg_keycache_t ctx, i
753          *r_key = NULL;          *r_key = NULL;
754          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
755      }      }
756            if (ctx->tmp->flags != 0)
757            ctx->tmp->flags = 0; /* reset the 'updated' status. */
758        /* it might be possible there is no public key. */
759        if (flags && ctx->tmp->pubpart == NULL)
760            flags = 0;
761      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
762      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp = ctx->tmp->next;
763      ctx->pos++;      ctx->pos++;
# Line 618  gpg_keycache_next_key (gpg_keycache_t ct Line 778  gpg_keycache_next_key (gpg_keycache_t ct
778      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
779      return err;      return err;
780  }  }
781    
782    /* Search for a key with the pattern @pattern and mark
783       this key as the default signing key if found.
784       Return value: 0 on success. */
785    gpgme_error_t
786    gpg_keycache_set_default_key (gpg_keycache_t ctx,
787                                  const char *pattern)
788    {
789        gpgme_error_t err;
790        gpgme_key_t key;
791        struct keycache_s *itm;
792    
793        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
794        if (err)
795            return err;
796    
797        if (itm)
798            itm->default_key = 1;
799        return 0;
800    }
801    
802    /* Return the default key from the cache. If no was
803       marked before, NULL is returned in @r_key.
804       Return value: 0 on success. */
805    gpgme_error_t
806    gpg_keycache_get_default_key (gpg_keycache_t ctx,
807                                  gpgme_key_t *r_key)
808    {
809        struct keycache_s *itm;
810    
811        *r_key = NULL;
812        for (itm = ctx->item; itm; itm = itm->next) {
813            if (itm->default_key) {
814                *r_key = itm->key;
815                break;
816            }
817        }
818        if (!*r_key)
819            return gpgme_error (GPG_ERR_NOT_FOUND);
820        return 0;
821    }
822    
823    
824    

Legend:
Removed from v.123  
changed lines
  Added in v.175

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26