/[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 207 by twoaday, Fri Apr 28 10:28:24 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 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 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    #include "wptTypes.h"
40    #include "wptUTF8.h"
41    
42    
43    /* Attribute list which holds the image data. */
44    struct attr_list_s {
45        struct attr_list_s *next;
46        char *fpr;                   /* fingerprint of the key */
47        unsigned char *d;            /* actual JPEG data. */
48        unsigned long octets;        /* length of the data. */
49        unsigned int flags;          /* status of the attribute. */
50    };
51    typedef struct attr_list_s *attr_list_t;
52    
53    
54  #if 0  /* Free attribute list @ctx. */
55  /* convert a binary buffer into its hex representation. */  void
56  static void  free_attr_list (attr_list_t ctx)
 buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)  
57  {  {
58      char dig[3];      attr_list_t n;
59      size_t i;      while (ctx) {
60            n = ctx->next;
61      memset (dst, 0, dlen);          safe_free (ctx->fpr);
62      for (i = 0; i < nbytes && dlen > 0; i++) {          safe_free (ctx->d);
63          sprintf (dig, "%02X", buf[i]);          ctx = n;
         strcat (dst, dig);  
         dlen -= 2;  
64      }      }
65  }  }
66  #endif          
67    /* Parse the attribute list in @fp and store it into @ctx.
68       Return value: number of parsed items. */
69    int
70    parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
71    {
72        attr_list_t c, t;
73        char buf[512], *p, *buffer;
74        int pos, n=0;
75        
76        *ctx = NULL;
77        while (fgets (buf, 511, fp)) {
78            if (strstr (buf, "\r\n"))
79                buf[strlen (buf)-2]=0;
80            if (strstr (buf, "\n"))
81                buf[strlen (buf)-1]=0;
82            if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
83                continue;
84            buffer = buf+9+10;
85            pos = 0;
86            c = (attr_list_t)calloc (1, sizeof *c);
87            if (!c)
88                BUG (0);
89            p = strtok (buffer, " ");
90            while (p != NULL) {
91                switch (pos) {
92                case 0:
93                    c->fpr = strdup (p);
94                    break;
95                    
96                case 1:
97                    c->octets = strtoul (p, NULL, 10);
98                    break;
99                    
100                case 7:
101                    c->flags = strtoul (p, NULL, 10);
102                    break;
103                    
104                default:
105                    break;
106                }
107                pos++;
108                p = strtok (NULL, " ");
109            }
110            if (!*ctx)
111                *ctx = c;
112            else {
113                for (t = *ctx; t->next; t=t->next)
114                    ;
115                t->next = c;
116            }
117            c->d = (unsigned char*)malloc (c->octets);
118            if (!c->d)
119                BUG (0);
120            memcpy (c->d, data, c->octets);
121            data += c->octets;
122            datlen -= c->octets;
123            n++;
124        }
125        /*assert (datlen == 0); */
126        return n;
127    }
128    
129    
130    static int
131    parse_attr_data (const char *keyid, attr_list_t *list)
132    {
133        gpgme_error_t err;
134        FILE *tmp;    
135        BYTE *data;
136        char *status, tmpnam[MAX_PATH+1];
137        DWORD ndata = 0;
138    
139        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
140        if (err)
141            return err;
142    
143        get_temp_name (tmpnam, MAX_PATH, NULL);
144        tmp = fopen (tmpnam, "w+b");
145        if (ndata > 0 && tmp != NULL) {
146            fwrite (status, 1, strlen (status), tmp);
147            fflush (tmp);
148            rewind (tmp);
149    
150            ndata = parse_attr_list (tmp, data, ndata, list);
151            fclose (tmp);
152            DeleteFile (tmpnam);
153        }
154        else
155            *list = NULL;
156    
157        safe_free (status);
158        safe_free (data);
159        return ndata;
160    }
161    
162    
163  /* 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 165  buffer_to_string (char *dst, size_t dlen
165  static void  static void
166  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
167  {      {    
168      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
169      PKT_secret_key *sk;      PKT_secret_key *sk;
170      gpg_iobuf_t inp;      gpg_iobuf_t inp;
171      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 174  parse_secring (gpg_keycache_t cache, con
174      char keyid[16+1];      char keyid[16+1];
175    
176      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
177      if (!inp) {      if (!inp)
         safe_free (pkt);  
178          return;          return;
179      }  
180      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
181        pkt = (PACKET*)calloc (1, sizeof *pkt);
182        if (!pkt)
183            BUG (0);
184      gpg_init_packet (pkt);      gpg_init_packet (pkt);
185      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
186          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 102  next: Line 209  next:
209  }  }
210    
211    
212    /* Update the photo image of a single key with the fingerprint
213       @fpr. The @dat struct contains the new item data. */
214    static gpgme_error_t
215    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
216    {
217        struct keycache_s *fnd = NULL;
218        gpgme_key_t key;
219        
220        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
221        if (!fnd)
222            return gpg_error (GPG_ERR_NOT_FOUND);
223        safe_free (fnd->attrib.d);
224        fnd->attrib.flags = dat->flags;
225        fnd->attrib.len = dat->octets;
226        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
227        if (!fnd->attrib.d)
228            BUG (0);
229        memcpy (fnd->attrib.d, dat->d, dat->octets);
230        return 0;
231    }
232    
233    
234    /* Update all photo images in the cache. */
235    static gpgme_error_t
236    keycache_update_photos (gpg_keycache_t ctx)
237    {
238        attr_list_t list=NULL, n;
239        DWORD ndata;
240    
241        ndata = parse_attr_data (NULL, &list);
242        if (ndata < 1) {
243            free_attr_list (list);
244            return 0;
245        }
246    
247        for (n=list; n; n=n->next)
248            keycache_update_photo (ctx, n->fpr, n);
249        free_attr_list (list);
250        return 0;
251    }
252    
253    
254    static void
255    keycache_decode_uid (struct keycache_s *ctx)
256    {
257        gpgme_user_id_t u;
258        struct native_uid_s *n, *t;
259    
260        for (u = ctx->key->uids; u; u = u->next) {
261            n = (struct native_uid_s*)calloc (1, sizeof *n);
262            if (!n)
263                BUG (0);
264            if (is_8bit_string (u->uid)) {
265                n->malloced = 1;
266                n->uid = utf8_to_native (u->uid);
267                if (u->name != NULL)
268                    n->name = utf8_to_native (u->name);
269                if (u->email != NULL)
270                    n->email = strdup (u->email);
271                if (u->comment != NULL)
272                    n->comment = utf8_to_native (u->comment);
273            }
274            else {
275                n->malloced = 0;
276                n->uid = u->uid;
277                n->name = u->name;
278                n->comment = u->comment;
279                n->email = u->email;
280            }
281            n->validity = u->validity;
282            n->revoked = u->revoked;
283            if (!ctx->uids)
284                ctx->uids = n;
285            else {
286                for (t = ctx->uids; t->next; t=t->next)
287                    ;
288                t->next = n;          
289            }
290        }
291    }
292    
293    
294    /* Store utf8 decoded user IDs in the code to avoid in-place decoding. */
295    static void
296    keycache_decode_uids (gpg_keycache_t ctx)
297    {
298        struct keycache_s *c;
299    
300        for (c = ctx->item; c; c = c->next)
301            keycache_decode_uid (c);
302    }
303    
304    
305    static void
306    free_native_uids (struct native_uid_s **r_n)
307    {
308        struct native_uid_s *t;
309        struct native_uid_s *n = *r_n;
310    
311        while (n != NULL) {
312            t = n->next;
313            if (n->malloced) {
314                safe_free (n->uid);
315                safe_free (n->name);
316                safe_free (n->comment);
317                safe_free (n->email);
318                safe_free (n->uid);
319            }
320            safe_free (n);
321            n = t;
322        }
323        *r_n = NULL;
324    }
325    
326    
327    
328  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
329  gpgme_error_t  gpgme_error_t
330  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 333  keycache_prepare2 (gpg_keycache_t ctx, c
333      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
334      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
335      gpg_iobuf_t inp;      gpg_iobuf_t inp;
336      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
337      struct keycache_s *c;      struct keycache_s *c;
338      const byte *sym_prefs;      const byte *sym_prefs;
339      char keyid[16+1], *id = NULL;      char keyid[16+1];
340      int key_seen = 0;      int key_seen = 0;
341      size_t nsym =0;      size_t nsym =0;
342    
343      if (secring) {      if (secring) {
344          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
345          if (!pubring) {          if (!pubring)
             safe_free (pkt);  
346              return 0;              return 0;
         }  
347      }      }
348      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
349      if (!inp) {      if (!inp)
         safe_free (pkt);  
350          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
     }  
351      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
352    
353        pkt = (PACKET*)calloc (1, sizeof * pkt);
354        if (!pkt)
355            BUG (0);
356      gpg_init_packet (pkt);      gpg_init_packet (pkt);
357      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
358          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
# Line 138  keycache_prepare2 (gpg_keycache_t ctx, c Line 360  keycache_prepare2 (gpg_keycache_t ctx, c
360              key_seen = 1;              key_seen = 1;
361          }          }
362    
363          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_SIGNATURE &&
364                pkt->pkt.signature->sig_class == 0x1F) {
365              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
366                  goto next;                  goto next;
367              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
368                            pkt->pkt.signature->keyid[1]);
369              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
370                  goto next;                  goto next;
371              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 374  keycache_prepare2 (gpg_keycache_t ctx, c
374              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
375          }          }
376          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
377              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
378                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
379              if (sym_prefs == NULL)              if (!sym_prefs)
380                  goto next;                  goto next;
381              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
382                            pkt->pkt.signature->keyid[1]);
383              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
384                  goto next;                  goto next;
385              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 163  keycache_prepare2 (gpg_keycache_t ctx, c Line 388  keycache_prepare2 (gpg_keycache_t ctx, c
388              else if (nsym > 0) {              else if (nsym > 0) {
389                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
390                  if (!c->sym_prefs)                  if (!c->sym_prefs)
391                      return gpg_error (GPG_ERR_ENOMEM);                      BUG (0);
392                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
393              }              }
394          }          }
         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;  
         }  
395  next:  next:
396          gpg_free_packet (pkt);          gpg_free_packet (pkt);
397          gpg_init_packet(pkt);          gpg_init_packet(pkt);
398      }      }
399    
 fail:  
     safe_free (id);  
400      safe_free (pkt);      safe_free (pkt);
401      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
402      return err;      return err;
# Line 230  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 430  gpg_keycache_new (gpg_keycache_t *r_ctx)
430          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
431      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
432      if (!ctx)      if (!ctx)
433          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
434      ctx->secret = 0;      ctx->secret = 0;
435      ctx->pos = 0;      ctx->pos = 0;
436      *r_ctx = ctx;      *r_ctx = ctx;
# Line 251  gpg_keycache_release (gpg_keycache_t ctx Line 451  gpg_keycache_release (gpg_keycache_t ctx
451          c2 = c->next;          c2 = c->next;
452          gpgme_key_release (c->key);          gpgme_key_release (c->key);
453          c->key = NULL;          c->key = NULL;
454          if (c->sym_prefs)          safe_free (c->pref_keyserver);
455              free (c->sym_prefs);          safe_free (c->sym_prefs);
456          c->sym_prefs = NULL;          safe_free (c->attrib.d);
457          if (c->attrib.d)          safe_free (c->card_type);
458              free (c->attrib.d);          free_native_uids (&c->uids);
459          c->attrib.d = NULL;          safe_free (c);
         if (c->card_type)  
             free (c->card_type);  
         free (c);  
460      }      }
461      if (ctx)      safe_free (ctx);
         free (ctx);  
462  }  }
463    
464    
# Line 296  gpg_keycache_add_key (gpg_keycache_t ctx Line 492  gpg_keycache_add_key (gpg_keycache_t ctx
492            
493      c = (struct keycache_s*)calloc (1, sizeof *c);      c = (struct keycache_s*)calloc (1, sizeof *c);
494      if (!c)      if (!c)
495          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
496      c->gloflags.is_protected = 1; /*default: assume protection. */      c->gloflags.is_protected = 1; /*default: assume protection. */
497      c->key = key;      c->key = key;
498      if (!ctx->item)      if (!ctx->item)
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 563  gpg_keycache_find_key2 (gpg_keycache_t c
563      }      }
564      *r_key = NULL;      *r_key = NULL;
565      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
566  } /* keycache_find_key */  }
567    
568    
569  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 574  gpg_keycache_find_key (gpg_keycache_t ct
574  }  }
575    
576    
577    /* Reload a photo image of a single key with the keyid @keyid.
578       Return value: 0 on success. */
579    static gpgme_error_t
580    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
581    {
582        attr_list_t list;
583    
584        if (parse_attr_data (keyid, &list) < 1) {
585            free_attr_list (list);
586            return 0;
587        }
588        keycache_update_photo (ctx, list->fpr, list);
589        free_attr_list (list);
590        return 0;
591    }
592    
593    
594    /* Return the next key which was updated. Before it is
595       returned the update flag is cleared.
596       @r_status is 1 for a new key and 2 for an updated key.
597       Return value: 0 on success. */
598    gpgme_error_t
599    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
600                                   struct keycache_s **r_obj,
601                                   int *r_status)
602    {
603        struct keycache_s *c;
604    
605        for (c = ctx->item; c; c = c->next) {
606            if (c->flags != 0) {
607                *r_status = c->flags;
608                *r_obj = c;
609                c->flags = 0;
610                return 0;
611            }
612        }
613        return gpg_error (GPG_ERR_NOT_FOUND);
614    }
615    
616    
617    
618  gpgme_error_t  gpgme_error_t
619  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
620                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 391  gpg_keycache_update_key (gpg_keycache_t Line 628  gpg_keycache_update_key (gpg_keycache_t
628      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
629      if (err)      if (err)
630          return err;          return err;
631        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS);
632      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
633      gpgme_release (gctx);      gpgme_release (gctx);
634      if (err)      if (err)
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 638  gpg_keycache_update_key (gpg_keycache_t
638          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
639          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
640          c->key = key;          c->key = key;
641          c->flags = 0;          c->flags = KC_FLAG_UPD;
642          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
643              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
644              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
645              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
646          }          }
647            /* XXX: this is also called for keys without a photo-id. */
648            keycache_reload_photo (ctx, keyid);
649    
650            /* refresh utf8 user ID list. */
651            free_native_uids (&c->uids);
652            keycache_decode_uid (c);
653      }      }
654      else {      else {
655          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 665  gpg_keycache_update_key (gpg_keycache_t
665                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
666              }              }
667          }          }
668            if (c)
669                c->flags = KC_FLAG_ADD;
670      }      }
671      return 0;      return 0;
672  }  }
# Line 444  gpg_keycache_delete_key (gpg_keycache_t Line 690  gpg_keycache_delete_key (gpg_keycache_t
690      c = ctx->item;      c = ctx->item;
691      if (c->next == NULL) {      if (c->next == NULL) {
692          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
693          if (itm)          safe_free (itm);
             free (itm);  
694          ctx->item = NULL;          ctx->item = NULL;
695      }      }
696      else {      else {
697          while (c && c->next != itm)          for (; c != NULL; c = c->next) {
698              c = c->next;              if (c->next == itm)
699                    break;
700            }
701            assert (c != NULL); /* XXX: sometimes access violation. */
702          c->next = c->next->next;          c->next = c->next->next;
703          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
704          if (itm)          safe_free (itm);
             free (itm);  
705      }      }
706      return 0;      return 0;
707  }  }
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 737  gpg_keycache_init (gpg_keycache_t ctx, c
737      }      }
738      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
739          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
740        keycache_update_photos (ctx);
741        keycache_decode_uids (ctx);
742      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
743      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
744      gpgme_release (c);      gpgme_release (c);
# Line 527  copy_uid_prefs (const unsigned char *pre Line 776  copy_uid_prefs (const unsigned char *pre
776          pos++;          pos++;
777      p = (unsigned char*)calloc (1, pos+1);      p = (unsigned char*)calloc (1, pos+1);
778      if (!p)      if (!p)
779          abort ();          BUG (0);
780      memcpy (p, prefs, pos);      memcpy (p, prefs, pos);
781      return p;      return p;
782  }  }
# Line 548  gpg_keycache_sync (gpg_keycache_t pub, g Line 797  gpg_keycache_sync (gpg_keycache_t pub, g
797              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
798              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
799                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
800              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
801                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
802              c->pubpart = c_sec;              c->pubpart = c_sec;
803              c->pubpart->key = key;              c->pubpart->key = key;
804          }          }
# Line 597  keycache_next_key (gpg_keycache_t ctx, i Line 847  keycache_next_key (gpg_keycache_t ctx, i
847          *r_key = NULL;          *r_key = NULL;
848          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
849      }      }
850            if (ctx->tmp->flags != 0)
851            ctx->tmp->flags = 0; /* reset the 'updated' status. */
852        /* it might be possible there is no public key. */
853        if (flags && ctx->tmp->pubpart == NULL)
854            flags = 0;
855      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
856      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp;
857        ctx->tmp = ctx->tmp->next;    
858      ctx->pos++;      ctx->pos++;
859    
860      return 0;      return 0;
# Line 613  gpgme_error_t Line 868  gpgme_error_t
868  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)
869  {  {
870      struct keycache_s *c=NULL;      struct keycache_s *c=NULL;
871      gpgme_error_t err = 0;      gpgme_error_t err;
872    
873      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
874      return err;      return err;
875  }  }
876    
877    gpgme_error_t
878    gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags,
879                            struct keycache_s **c, gpgme_key_t *r_key)
880    {
881        return keycache_next_key (ctx, flags, c, r_key);
882    }
883    
884    
885    /* Search for a key with the pattern @pattern and mark
886       this key as the default signing key if found.
887       Return value: 0 on success. */
888    gpgme_error_t
889    gpg_keycache_set_default_key (gpg_keycache_t ctx,
890                                  const char *pattern)
891    {
892        gpgme_error_t err;
893        gpgme_key_t key;
894        struct keycache_s *itm;
895    
896        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
897        if (err)
898            return err;
899    
900        if (itm)
901            itm->default_key = 1;
902        return 0;
903    }
904    
905    /* Return the default key from the cache. If no was
906       marked before, NULL is returned in @r_key.
907       Return value: 0 on success. */
908    gpgme_error_t
909    gpg_keycache_get_default_key (gpg_keycache_t ctx,
910                                  gpgme_key_t *r_key)
911    {
912        struct keycache_s *itm;
913    
914        *r_key = NULL;
915        for (itm = ctx->item; itm; itm = itm->next) {
916            if (itm->default_key) {
917                *r_key = itm->key;
918                break;
919            }
920        }
921        if (!*r_key)
922            return gpgme_error (GPG_ERR_NOT_FOUND);
923        return 0;
924    }
925    
926    
927    static gpgme_error_t
928    decode_subpacket (const char *subpkt_data, int *type,
929                      char **out, WORD *outlen)
930    {
931        char tmp[128], *p = tmp, *val;
932        char *enc = NULL;
933        size_t pos = 0, i=0;
934    
935        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
936        *outlen = 0;
937        *out = NULL;
938        
939        if (strncmp (subpkt_data, "spk:", 4))
940            return gpg_error (GPG_ERR_NO_DATA);
941    
942        strncpy (tmp, subpkt_data, 62);
943        val = strtok (tmp, ":");
944        while (val != NULL) {
945            switch (pos++) {
946            case 0:
947                break;
948    
949            case 1:
950                if (type)
951                    *type = atoi (val);
952                break;
953    
954            case 2:
955                break;
956    
957            case 3:
958                *outlen = atoi (val);
959                break;
960    
961            case 4:
962                enc = strdup (val);
963                break;
964            }
965            val = strtok (NULL, ":");
966        }
967        if (!enc)
968            return gpg_error (GPG_ERR_NO_DATA);;
969        *out = (char*)calloc (1, strlen (enc)+1);
970        if (!*out)
971            BUG (0);
972        for (pos = 0; pos < strlen (enc); pos++) {
973            if (enc[pos] == '%' && enc[pos+1] == '%')
974                (*out)[i++] = '%';
975            else if (enc[pos] == '%') {
976                char temp[3];
977                temp[0] = enc[++pos];
978                temp[1] = enc[++pos];
979                temp[2] = 0;
980                (*out)[i++] = (char)strtoul (temp, NULL, 16);
981            }
982            else
983                (*out)[i++] = enc[pos];
984        }
985        (*out)[i] = 0;
986        safe_free (enc);
987        return 0;
988    }
989    
990    
991    /* If the attribute given in @attr is not set in the
992       key cache object, try to update it. */
993    gpgme_error_t
994    gpg_keycache_update_attr (struct keycache_s *item,
995                              int attr, int force)
996    {
997        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
998        char *val = NULL;
999        WORD n = 0;    
1000    
1001        switch (attr) {
1002        case KC_ATTR_PREFSYM:
1003            if (!force && item->sym_prefs)
1004                break;
1005            safe_free (item->sym_prefs);
1006            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1007            if (!err && val != NULL)
1008                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
1009            break;
1010    
1011        case KC_ATTR_PREFKSERV:
1012            if (!force && item->pref_keyserver)
1013                break;
1014            safe_free (item->pref_keyserver);
1015            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1016            if (!err && val != NULL)
1017                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
1018            break;
1019        }
1020        safe_free (val);
1021        return err;
1022    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26