/[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 121 by twoaday, Mon Dec 12 11:19:56 2005 UTC revision 167 by twoaday, Thu Jan 26 10:17:17 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    /* Always use the $users temp folder. */
125    static FILE*
126    w32_tmpfile (char *tmp, DWORD tmplen)
127    {
128        char id[16];
129    
130        if (!GetTempPath (tmplen-17, tmp))
131            return NULL;
132        if (tmp[strlen (tmp)-1] != '\\')
133            strcat (tmp, "\\");
134        _snprintf (id, sizeof (id)-1, "%lu", GetTickCount ());
135        strcat (tmp, id);
136        return fopen (tmp, "w+b");
137    }
138    
139    
140    static int
141    parse_attr_data (const char *keyid, attr_list_t *list)
142    {
143        gpgme_error_t err;
144        FILE *tmp;
145        char *status, tmpnam[MAX_PATH+1];
146        BYTE *data;
147        DWORD ndata;
148    
149        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
150        if (err)
151            return err;
152    
153        if (ndata > 0 && (tmp = w32_tmpfile (tmpnam, MAX_PATH)) != NULL) {
154            fwrite (status, 1, strlen (status), tmp);
155            fflush (tmp);
156            rewind (tmp);
157    
158            ndata = parse_attr_list (tmp, data, ndata, list);
159            fclose (tmp);
160            DeleteFile (tmpnam);
161        }
162        else
163            *list = NULL;
164    
165        safe_free (status);
166        safe_free (data);
167        return ndata;
168    }
169    
170    
171  /* 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 173  buffer_to_string (char *dst, size_t dlen
173  static void  static void
174  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
175  {      {    
176      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
177      PKT_secret_key *sk;      PKT_secret_key *sk;
178      gpg_iobuf_t inp;      gpg_iobuf_t inp;
179      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 182  parse_secring (gpg_keycache_t cache, con
182      char keyid[16+1];      char keyid[16+1];
183    
184      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
185      if (!inp) {      if (!inp)
         safe_free (pkt);  
186          return;          return;
187      }  
188      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
189        pkt = (PACKET*)calloc (1, sizeof *pkt);
190      gpg_init_packet (pkt);      gpg_init_packet (pkt);
191      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
192          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 102  next: Line 215  next:
215  }  }
216    
217    
218    /* Update the photo image of a single key with the fingerprint
219       @fpr. The @dat struct contains the new item data. */
220    static gpgme_error_t
221    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
222    {
223        struct keycache_s *fnd = NULL;
224        gpgme_key_t key;
225        
226        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
227        if (!fnd)
228            return gpg_error (GPG_ERR_NOT_FOUND);
229        safe_free (fnd->attrib.d);
230        fnd->attrib.flags = dat->flags;
231        fnd->attrib.len = dat->octets;
232        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
233        memcpy (fnd->attrib.d, dat->d, dat->octets);
234        return 0;
235    }
236    
237    
238    /* Update all photo images in the cache. */
239    static gpgme_error_t
240    keycache_update_photos (gpg_keycache_t ctx)
241    {
242        attr_list_t list=NULL, n;
243        DWORD ndata;
244    
245        ndata = parse_attr_data (NULL, &list);
246        if (ndata < 1) {
247            free_attr_list (list);
248            return 0;
249        }
250    
251        for (n=list; n; n=n->next)
252            keycache_update_photo (ctx, n->fpr, n);
253        free_attr_list (list);
254        return 0;
255    }
256    
257    
258  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
259  gpgme_error_t  gpgme_error_t
260  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 263  keycache_prepare2 (gpg_keycache_t ctx, c
263      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
264      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
265      gpg_iobuf_t inp;      gpg_iobuf_t inp;
266      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
267      struct keycache_s *c;      struct keycache_s *c;
268      const byte *sym_prefs;      const byte *sym_prefs;
269      char keyid[16+1], *id = NULL;      char keyid[16+1];
270      int key_seen = 0;      int key_seen = 0;
271      size_t nsym =0;      size_t nsym =0;
272    
273      if (secring) {      if (secring) {
274          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
275          if (!pubring) {          if (!pubring)
             safe_free(pkt);  
276              return 0;              return 0;
         }  
277      }      }
278      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
279      if (!inp) {      if (!inp)
         safe_free( pkt );  
280          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
281      }      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
     gpg_iobuf_ioctl( inp, 3, 1, NULL ); /* disable cache */  
282    
283      gpg_init_packet( pkt );      pkt = (PACKET*)calloc (1, sizeof * pkt);
284        gpg_init_packet (pkt);
285      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
286          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
287              strcpy (keyid, "");              strcpy (keyid, "");
288              key_seen = 1;              key_seen = 1;
289          }          }
290    
291          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_SIGNATURE &&
292                pkt->pkt.signature->sig_class == 0x1F) {
293              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
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 150  keycache_prepare2 (gpg_keycache_t ctx, c Line 302  keycache_prepare2 (gpg_keycache_t ctx, c
302              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
303          }          }
304          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
305              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
306                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
307              if (sym_prefs == NULL)              if (!sym_prefs)
308                  goto next;                  goto next;
309              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
310                            pkt->pkt.signature->keyid[1]);
311              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
312                  goto next;                  goto next;
313              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 320  keycache_prepare2 (gpg_keycache_t ctx, c
320                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
321              }              }
322          }          }
         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;  
         }  
323  next:  next:
324          gpg_free_packet (pkt);          gpg_free_packet (pkt);
325          gpg_init_packet(pkt);          gpg_init_packet(pkt);
326      }      }
327    
 fail:  
     safe_free (id);  
328      safe_free (pkt);      safe_free (pkt);
329      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
330      return err;      return err;
# Line 251  gpg_keycache_release (gpg_keycache_t ctx Line 379  gpg_keycache_release (gpg_keycache_t ctx
379          c2 = c->next;          c2 = c->next;
380          gpgme_key_release (c->key);          gpgme_key_release (c->key);
381          c->key = NULL;          c->key = NULL;
382          if (c->sym_prefs)          safe_free (c->sym_prefs);
383              free (c->sym_prefs);          safe_free (c->attrib.d);
384          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);  
385          free (c);          free (c);
386      }      }
387      if (ctx)      safe_free (ctx);
         free (ctx);  
388  }  }
389    
390    
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 489  gpg_keycache_find_key2 (gpg_keycache_t c
489      }      }
490      *r_key = NULL;      *r_key = NULL;
491      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
492  } /* keycache_find_key */  }
493    
494    
495  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 500  gpg_keycache_find_key (gpg_keycache_t ct
500  }  }
501    
502    
503    /* Reload a photo image of a single key with the keyid @keyid.
504       Return value: 0 on success. */
505    static gpgme_error_t
506    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
507    {
508        attr_list_t list;
509    
510        if (parse_attr_data (keyid, &list) < 1) {
511            free_attr_list (list);
512            return 0;
513        }
514        keycache_update_photo (ctx, list->fpr, list);
515        free_attr_list (list);
516        return 0;
517    }
518    
519    
520    /* Return the next key which was updated. Before it is
521       returned the update flag is cleared.
522       @r_status is 1 for a new key and 2 for an updated key.
523       Return value: 0 on success. */
524    gpgme_error_t
525    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
526                                   struct keycache_s **r_obj,
527                                   int *r_status)
528    {
529        struct keycache_s *c;
530    
531        for (c = ctx->item; c; c = c->next) {
532            if (c->flags != 0) {
533                *r_status = c->flags;
534                c->flags = 0;
535                *r_obj = c;
536                return 0;
537            }
538        }
539        return gpg_error (GPG_ERR_NOT_FOUND);
540    }
541    
542    
543    
544  gpgme_error_t  gpgme_error_t
545  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
546                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 391  gpg_keycache_update_key (gpg_keycache_t Line 554  gpg_keycache_update_key (gpg_keycache_t
554      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
555      if (err)      if (err)
556          return err;          return err;
557        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS);
558      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
559      gpgme_release (gctx);      gpgme_release (gctx);
560      if (err)      if (err)
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 564  gpg_keycache_update_key (gpg_keycache_t
564          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
565          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
566          c->key = key;          c->key = key;
567          c->flags = 0;          c->flags = KC_FLAG_UPD;
568          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
569              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
570              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
571              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
572          }          }
573            /* XXX: this is also called for keys without a photo-id. */
574            keycache_reload_photo (ctx, keyid);
575      }      }
576      else {      else {
577          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 587  gpg_keycache_update_key (gpg_keycache_t
587                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
588              }              }
589          }          }
590            if (c)
591                c->flags = KC_FLAG_ADD;
592      }      }
593      return 0;      return 0;
594  }  }
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 658  gpg_keycache_init (gpg_keycache_t ctx, c
658      }      }
659      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
660          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
661        keycache_update_photos (ctx);
662      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
663      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
664      gpgme_release (c);      gpgme_release (c);
# Line 517  key_divert_to_card (gpgme_key_t key) Line 686  key_divert_to_card (gpgme_key_t key)
686  }  }
687    
688    
689    static unsigned char*
690    copy_uid_prefs (const unsigned char *prefs)
691    {
692        unsigned char *p;
693        size_t pos=0;
694    
695        while (prefs[pos] != 0)
696            pos++;
697        p = (unsigned char*)calloc (1, pos+1);
698        if (!p)
699            abort ();
700        memcpy (p, prefs, pos);
701        return p;
702    }
703    
704    
705  gpgme_error_t  gpgme_error_t
706  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
707  {  {
# Line 532  gpg_keycache_sync (gpg_keycache_t pub, g Line 717  gpg_keycache_sync (gpg_keycache_t pub, g
717              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
718              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
719                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
720                c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
721              c->pubpart = c_sec;              c->pubpart = c_sec;
722              c->pubpart->key = key;              c->pubpart->key = key;
723          }          }
# Line 580  keycache_next_key (gpg_keycache_t ctx, i Line 766  keycache_next_key (gpg_keycache_t ctx, i
766          *r_key = NULL;          *r_key = NULL;
767          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
768      }      }
769            if (ctx->tmp->flags != 0)
770            ctx->tmp->flags = 0; /* reset the 'updated' status. */
771        /* it might be possible there is no public key. */
772        if (flags && ctx->tmp->pubpart == NULL)
773            flags = 0;
774      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
775      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp = ctx->tmp->next;
776      ctx->pos++;      ctx->pos++;
# Line 601  gpg_keycache_next_key (gpg_keycache_t ct Line 791  gpg_keycache_next_key (gpg_keycache_t ct
791      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
792      return err;      return err;
793  }  }
794    
795    /* Search for a key with the pattern @pattern and mark
796       this key as the default signing key if found.
797       Return value: 0 on success. */
798    gpgme_error_t
799    gpg_keycache_set_default_key (gpg_keycache_t ctx,
800                                  const char *pattern)
801    {
802        gpgme_error_t err;
803        gpgme_key_t key;
804        struct keycache_s *itm;
805    
806        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
807        if (err)
808            return err;
809    
810        if (itm)
811            itm->default_key = 1;
812        return 0;
813    }
814    
815    /* Return the default key from the cache. If no was
816       marked before, NULL is returned in @r_key.
817       Return value: 0 on success. */
818    gpgme_error_t
819    gpg_keycache_get_default_key (gpg_keycache_t ctx,
820                                  gpgme_key_t *r_key)
821    {
822        struct keycache_s *itm;
823    
824        *r_key = NULL;
825        for (itm = ctx->item; itm; itm = itm->next) {
826            if (itm->default_key) {
827                *r_key = itm->key;
828                break;
829            }
830        }
831        if (!*r_key)
832            return gpgme_error (GPG_ERR_NOT_FOUND);
833        return 0;
834    }
835    
836    
837    

Legend:
Removed from v.121  
changed lines
  Added in v.167

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26