/[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 188 by twoaday, Wed Mar 22 12:39:02 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    #include "wptTypes.h"
40    
41    
42  #if 0  /* Attribute list which holds the image data. */
43  /* convert a binary buffer into its hex representation. */  struct attr_list_s {
44  static void      struct attr_list_s *next;
45  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)      char *fpr;                   /* fingerprint of the key */
46  {      unsigned char *d;            /* actual JPEG data. */
47      char dig[3];      unsigned long octets;        /* length of the data. */
48      size_t i;      unsigned int flags;          /* status of the attribute. */
49    };
50    typedef struct attr_list_s *attr_list_t;
51    
52      memset (dst, 0, dlen);  
53      for (i = 0; i < nbytes && dlen > 0; i++) {  /* Free attribute list @ctx. */
54          sprintf (dig, "%02X", buf[i]);  void
55          strcat (dst, dig);  free_attr_list (attr_list_t ctx)
56          dlen -= 2;  {
57        attr_list_t n;
58        while (ctx) {
59            n = ctx->next;
60            free (ctx->fpr);
61            free (ctx->d);
62            ctx = n;
63      }      }
64  }  }
65  #endif          
66    /* Parse the attribute list in @fp and store it into @ctx.
67       Return value: number of parsed items. */
68    int
69    parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
70    {
71        attr_list_t c, t;
72        char buf[512], *p, *buffer;
73        int pos, n=0;
74        
75        *ctx = NULL;
76        while (fgets (buf, 511, fp)) {
77            if (strstr (buf, "\r\n"))
78                buf[strlen (buf)-2]=0;
79            if (strstr (buf, "\n"))
80                buf[strlen (buf)-1]=0;
81            if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
82                continue;
83            buffer = buf+9+10;
84            pos = 0;
85            c = (attr_list_t)calloc (1, sizeof *c);
86            if (!c)
87                BUG (0);
88            p = strtok (buffer, " ");
89            while (p != NULL) {
90                switch (pos) {
91                case 0:
92                    c->fpr = strdup (p);
93                    break;
94                    
95                case 1:
96                    c->octets = strtoul (p, NULL, 10);
97                    break;
98                    
99                case 7:
100                    c->flags = strtoul (p, NULL, 10);
101                    break;
102                    
103                default:
104                    break;
105                }
106                pos++;
107                p = strtok (NULL, " ");
108            }
109            if (!*ctx)
110                *ctx = c;
111            else {
112                for (t = *ctx; t->next; t=t->next)
113                    ;
114                t->next = c;
115            }
116            c->d = (unsigned char*)malloc (c->octets);
117            if (!c->d)
118                BUG (0);
119            memcpy (c->d, data, c->octets);
120            data += c->octets;
121            datlen -= c->octets;
122            n++;
123        }
124        /*assert (datlen == 0); */
125        return n;
126    }
127    
128    
129    static int
130    parse_attr_data (const char *keyid, attr_list_t *list)
131    {
132        gpgme_error_t err;
133        FILE *tmp;    
134        BYTE *data;
135        char *status, tmpnam[MAX_PATH+1];
136        DWORD ndata = 0;
137    
138        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
139        if (err)
140            return err;
141    
142        get_temp_name (tmpnam, MAX_PATH, NULL);
143        tmp = fopen (tmpnam, "w+b");
144        if (ndata > 0 && tmp != NULL) {
145            fwrite (status, 1, strlen (status), tmp);
146            fflush (tmp);
147            rewind (tmp);
148    
149            ndata = parse_attr_list (tmp, data, ndata, list);
150            fclose (tmp);
151            DeleteFile (tmpnam);
152        }
153        else
154            *list = NULL;
155    
156        safe_free (status);
157        safe_free (data);
158        return ndata;
159    }
160    
161    
162  /* 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 164  buffer_to_string (char *dst, size_t dlen
164  static void  static void
165  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
166  {      {    
167      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
168      PKT_secret_key *sk;      PKT_secret_key *sk;
169      gpg_iobuf_t inp;      gpg_iobuf_t inp;
170      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 173  parse_secring (gpg_keycache_t cache, con
173      char keyid[16+1];      char keyid[16+1];
174    
175      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
176      if (!inp) {      if (!inp)
         safe_free (pkt);  
177          return;          return;
178      }  
179      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
180        pkt = (PACKET*)calloc (1, sizeof *pkt);
181        if (!pkt)
182            BUG (0);
183      gpg_init_packet (pkt);      gpg_init_packet (pkt);
184      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
185          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 102  next: Line 208  next:
208  }  }
209    
210    
211    /* Update the photo image of a single key with the fingerprint
212       @fpr. The @dat struct contains the new item data. */
213    static gpgme_error_t
214    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
215    {
216        struct keycache_s *fnd = NULL;
217        gpgme_key_t key;
218        
219        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
220        if (!fnd)
221            return gpg_error (GPG_ERR_NOT_FOUND);
222        safe_free (fnd->attrib.d);
223        fnd->attrib.flags = dat->flags;
224        fnd->attrib.len = dat->octets;
225        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
226        if (!fnd->attrib.d)
227            BUG (0);
228        memcpy (fnd->attrib.d, dat->d, dat->octets);
229        return 0;
230    }
231    
232    
233    /* Update all photo images in the cache. */
234    static gpgme_error_t
235    keycache_update_photos (gpg_keycache_t ctx)
236    {
237        attr_list_t list=NULL, n;
238        DWORD ndata;
239    
240        ndata = parse_attr_data (NULL, &list);
241        if (ndata < 1) {
242            free_attr_list (list);
243            return 0;
244        }
245    
246        for (n=list; n; n=n->next)
247            keycache_update_photo (ctx, n->fpr, n);
248        free_attr_list (list);
249        return 0;
250    }
251    
252    
253  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
254  gpgme_error_t  gpgme_error_t
255  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 258  keycache_prepare2 (gpg_keycache_t ctx, c
258      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
259      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
260      gpg_iobuf_t inp;      gpg_iobuf_t inp;
261      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
262      struct keycache_s *c;      struct keycache_s *c;
263      const byte *sym_prefs;      const byte *sym_prefs;
264      char keyid[16+1], *id = NULL;      char keyid[16+1];
265      int key_seen = 0;      int key_seen = 0;
266      size_t nsym =0;      size_t nsym =0;
267    
268      if (secring) {      if (secring) {
269          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
270          if (!pubring) {          if (!pubring)
             safe_free (pkt);  
271              return 0;              return 0;
         }  
272      }      }
273      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
274      if (!inp) {      if (!inp)
         safe_free (pkt);  
275          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
     }  
276      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
277    
278        pkt = (PACKET*)calloc (1, sizeof * pkt);
279        if (!pkt)
280            BUG (0);
281      gpg_init_packet (pkt);      gpg_init_packet (pkt);
282      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
283          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
# Line 138  keycache_prepare2 (gpg_keycache_t ctx, c Line 285  keycache_prepare2 (gpg_keycache_t ctx, c
285              key_seen = 1;              key_seen = 1;
286          }          }
287    
288          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_SIGNATURE &&
289                pkt->pkt.signature->sig_class == 0x1F) {
290              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
291                  goto next;                  goto next;
292              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
293                            pkt->pkt.signature->keyid[1]);
294              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
295                  goto next;                  goto next;
296              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 299  keycache_prepare2 (gpg_keycache_t ctx, c
299              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
300          }          }
301          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
302              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
303                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
304              if (sym_prefs == NULL)              if (!sym_prefs)
305                  goto next;                  goto next;
306              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
307                            pkt->pkt.signature->keyid[1]);
308              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
309                  goto next;                  goto next;
310              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 313  keycache_prepare2 (gpg_keycache_t ctx, c
313              else if (nsym > 0) {              else if (nsym > 0) {
314                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
315                  if (!c->sym_prefs)                  if (!c->sym_prefs)
316                      return gpg_error (GPG_ERR_ENOMEM);                      BUG (0);
317                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
318              }              }
319          }          }
         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;  
         }  
320  next:  next:
321          gpg_free_packet (pkt);          gpg_free_packet (pkt);
322          gpg_init_packet(pkt);          gpg_init_packet(pkt);
323      }      }
324    
 fail:  
     safe_free (id);  
325      safe_free (pkt);      safe_free (pkt);
326      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
327      return err;      return err;
# Line 230  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 355  gpg_keycache_new (gpg_keycache_t *r_ctx)
355          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
356      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
357      if (!ctx)      if (!ctx)
358          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
359      ctx->secret = 0;      ctx->secret = 0;
360      ctx->pos = 0;      ctx->pos = 0;
361      *r_ctx = ctx;      *r_ctx = ctx;
# Line 251  gpg_keycache_release (gpg_keycache_t ctx Line 376  gpg_keycache_release (gpg_keycache_t ctx
376          c2 = c->next;          c2 = c->next;
377          gpgme_key_release (c->key);          gpgme_key_release (c->key);
378          c->key = NULL;          c->key = NULL;
379          if (c->sym_prefs)          safe_free (c->pref_keyserver);
380              free (c->sym_prefs);          safe_free (c->sym_prefs);
381          c->sym_prefs = NULL;          safe_free (c->attrib.d);
382          if (c->attrib.d)          safe_free (c->card_type);
             free (c->attrib.d);  
         c->attrib.d = NULL;  
         if (c->card_type)  
             free (c->card_type);  
383          free (c);          free (c);
384      }      }
385      if (ctx)      safe_free (ctx);
         free (ctx);  
386  }  }
387    
388    
# Line 296  gpg_keycache_add_key (gpg_keycache_t ctx Line 416  gpg_keycache_add_key (gpg_keycache_t ctx
416            
417      c = (struct keycache_s*)calloc (1, sizeof *c);      c = (struct keycache_s*)calloc (1, sizeof *c);
418      if (!c)      if (!c)
419          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
420      c->gloflags.is_protected = 1; /*default: assume protection. */      c->gloflags.is_protected = 1; /*default: assume protection. */
421      c->key = key;      c->key = key;
422      if (!ctx->item)      if (!ctx->item)
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 487  gpg_keycache_find_key2 (gpg_keycache_t c
487      }      }
488      *r_key = NULL;      *r_key = NULL;
489      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
490  } /* keycache_find_key */  }
491    
492    
493  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 498  gpg_keycache_find_key (gpg_keycache_t ct
498  }  }
499    
500    
501    /* Reload a photo image of a single key with the keyid @keyid.
502       Return value: 0 on success. */
503    static gpgme_error_t
504    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
505    {
506        attr_list_t list;
507    
508        if (parse_attr_data (keyid, &list) < 1) {
509            free_attr_list (list);
510            return 0;
511        }
512        keycache_update_photo (ctx, list->fpr, list);
513        free_attr_list (list);
514        return 0;
515    }
516    
517    
518    /* Return the next key which was updated. Before it is
519       returned the update flag is cleared.
520       @r_status is 1 for a new key and 2 for an updated key.
521       Return value: 0 on success. */
522    gpgme_error_t
523    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
524                                   struct keycache_s **r_obj,
525                                   int *r_status)
526    {
527        struct keycache_s *c;
528    
529        for (c = ctx->item; c; c = c->next) {
530            if (c->flags != 0) {
531                *r_status = c->flags;
532                *r_obj = c;
533                c->flags = 0;
534                return 0;
535            }
536        }
537        return gpg_error (GPG_ERR_NOT_FOUND);
538    }
539    
540    
541    
542  gpgme_error_t  gpgme_error_t
543  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
544                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 391  gpg_keycache_update_key (gpg_keycache_t Line 552  gpg_keycache_update_key (gpg_keycache_t
552      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
553      if (err)      if (err)
554          return err;          return err;
555        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS);
556      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
557      gpgme_release (gctx);      gpgme_release (gctx);
558      if (err)      if (err)
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 562  gpg_keycache_update_key (gpg_keycache_t
562          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
563          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
564          c->key = key;          c->key = key;
565          c->flags = 0;          c->flags = KC_FLAG_UPD;
566          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
567              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
568              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
569              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
570          }          }
571            /* XXX: this is also called for keys without a photo-id. */
572            keycache_reload_photo (ctx, keyid);
573      }      }
574      else {      else {
575          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 585  gpg_keycache_update_key (gpg_keycache_t
585                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
586              }              }
587          }          }
588            if (c)
589                c->flags = KC_FLAG_ADD;
590      }      }
591      return 0;      return 0;
592  }  }
# Line 444  gpg_keycache_delete_key (gpg_keycache_t Line 610  gpg_keycache_delete_key (gpg_keycache_t
610      c = ctx->item;      c = ctx->item;
611      if (c->next == NULL) {      if (c->next == NULL) {
612          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
613          if (itm)          safe_free (itm);
             free (itm);  
614          ctx->item = NULL;          ctx->item = NULL;
615      }      }
616      else {      else {
617          while (c && c->next != itm)          for (; c != NULL; c = c->next) {
618              c = c->next;              if (c->next == itm)
619                    break;
620            }
621            assert (c != NULL); /* XXX: sometimes access violation. */
622          c->next = c->next->next;          c->next = c->next->next;
623          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
624          if (itm)          safe_free (itm);
             free (itm);  
625      }      }
626      return 0;      return 0;
627  }  }
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 657  gpg_keycache_init (gpg_keycache_t ctx, c
657      }      }
658      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
659          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
660        keycache_update_photos (ctx);
661      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
662      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
663      gpgme_release (c);      gpgme_release (c);
# Line 527  copy_uid_prefs (const unsigned char *pre Line 695  copy_uid_prefs (const unsigned char *pre
695          pos++;          pos++;
696      p = (unsigned char*)calloc (1, pos+1);      p = (unsigned char*)calloc (1, pos+1);
697      if (!p)      if (!p)
698          abort ();          BUG (0);
699      memcpy (p, prefs, pos);      memcpy (p, prefs, pos);
700      return p;      return p;
701  }  }
# Line 548  gpg_keycache_sync (gpg_keycache_t pub, g Line 716  gpg_keycache_sync (gpg_keycache_t pub, g
716              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
717              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
718                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
719              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
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 597  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 618  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    
796    /* Search for a key with the pattern @pattern and mark
797       this key as the default signing key if found.
798       Return value: 0 on success. */
799    gpgme_error_t
800    gpg_keycache_set_default_key (gpg_keycache_t ctx,
801                                  const char *pattern)
802    {
803        gpgme_error_t err;
804        gpgme_key_t key;
805        struct keycache_s *itm;
806    
807        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
808        if (err)
809            return err;
810    
811        if (itm)
812            itm->default_key = 1;
813        return 0;
814    }
815    
816    /* Return the default key from the cache. If no was
817       marked before, NULL is returned in @r_key.
818       Return value: 0 on success. */
819    gpgme_error_t
820    gpg_keycache_get_default_key (gpg_keycache_t ctx,
821                                  gpgme_key_t *r_key)
822    {
823        struct keycache_s *itm;
824    
825        *r_key = NULL;
826        for (itm = ctx->item; itm; itm = itm->next) {
827            if (itm->default_key) {
828                *r_key = itm->key;
829                break;
830            }
831        }
832        if (!*r_key)
833            return gpgme_error (GPG_ERR_NOT_FOUND);
834        return 0;
835    }
836    
837    
838    static gpgme_error_t
839    decode_subpacket (const char *subpkt_data, int *type,
840                      char **out, WORD *outlen)
841    {
842        char tmp[128], *p = tmp, *val;
843        char *enc = NULL;
844        size_t pos = 0, i=0;
845    
846        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
847        *outlen = 0;
848        *out = NULL;
849        
850        if (strncmp (subpkt_data, "spk:", 4))
851            return gpg_error (GPG_ERR_NO_DATA);
852    
853        strncpy (tmp, subpkt_data, 62);
854        val = strtok (tmp, ":");
855        while (val != NULL) {
856            switch (pos++) {
857            case 0:
858                break;
859    
860            case 1:
861                if (type)
862                    *type = atoi (val);
863                break;
864    
865            case 2:
866                break;
867    
868            case 3:
869                *outlen = atoi (val);
870                break;
871    
872            case 4:
873                enc = strdup (val);
874                break;
875            }
876            val = strtok (NULL, ":");
877        }
878        if (!enc)
879            return gpg_error (GPG_ERR_NO_DATA);;
880        *out = (char*)calloc (1, strlen (enc)+1);
881        if (!*out)
882            BUG (0);
883        for (pos = 0; pos < strlen (enc); pos++) {
884            if (enc[pos] == '%' && enc[pos+1] == '%')
885                (*out)[i++] = '%';
886            else if (enc[pos] == '%') {
887                char temp[3];
888                temp[0] = enc[++pos];
889                temp[1] = enc[++pos];
890                temp[2] = 0;
891                (*out)[i++] = (char)strtoul (temp, NULL, 16);
892            }
893            else
894                (*out)[i++] = enc[pos];
895        }
896        (*out)[i] = 0;
897        free (enc);
898        return 0;
899    }
900    
901    
902    /* If the attribute given in @attr is not set in the
903       key cache object, try to update it. */
904    gpgme_error_t
905    gpg_keycache_update_attr (struct keycache_s *item,
906                              int attr, int force)
907    {
908        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
909        char *val = NULL;
910        WORD n = 0;    
911    
912        switch (attr) {
913        case KC_ATTR_PREFSYM:
914            if (!force && item->sym_prefs)
915                break;
916            safe_free (item->sym_prefs);
917            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
918            if (!err && val != NULL)
919                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
920            break;
921    
922        case KC_ATTR_PREFKSERV:
923            if (!force && item->pref_keyserver)
924                break;
925            safe_free (item->pref_keyserver);
926            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
927            if (!err && val != NULL)
928                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
929            break;
930        }
931        safe_free (val);
932        return err;
933    }
934    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26