/[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 214 by twoaday, Sun May 14 18:40:36 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 "wptCommonCtl.h"
41    #include "wptContext.h"
42    #include "wptKeyEdit.h"
43    #include "wptUTF8.h"
44    
45    
46    gpgme_error_t parse_keyserver_url (char **r_keyserver, unsigned short *r_port);
47    
48    /* Attribute list which holds the image data. */
49    struct attr_list_s {
50        struct attr_list_s *next;
51        char *fpr;                   /* fingerprint of the key */
52        unsigned char *d;            /* actual JPEG data. */
53        unsigned long octets;        /* length of the data. */
54        unsigned int flags;          /* status of the attribute. */
55    };
56    typedef struct attr_list_s *attr_list_t;
57    
58    
59  #if 0  /* Free attribute list @ctx. */
60  /* convert a binary buffer into its hex representation. */  void
61  static void  free_attr_list (attr_list_t ctx)
62  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)  {
63        attr_list_t n;
64        while (ctx) {
65            n = ctx->next;
66            safe_free (ctx->fpr);
67            safe_free (ctx->d);
68            ctx = n;
69        }
70    }
71            
72    /* Parse the attribute list in @fp and store it into @ctx.
73       Return value: number of parsed items. */
74    int
75    parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
76    {
77        attr_list_t c, t;
78        char buf[512], *p, *buffer;
79        int pos, n=0;
80        
81        *ctx = NULL;
82        while (fgets (buf, 511, fp)) {
83            if (strstr (buf, "\r\n"))
84                buf[strlen (buf)-2]=0;
85            if (strstr (buf, "\n"))
86                buf[strlen (buf)-1]=0;
87            if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
88                continue;
89            buffer = buf+9+10;
90            pos = 0;
91            c = (attr_list_t)calloc (1, sizeof *c);
92            if (!c)
93                BUG (0);
94            p = strtok (buffer, " ");
95            while (p != NULL) {
96                switch (pos) {
97                case 0:
98                    c->fpr = strdup (p);
99                    break;
100                    
101                case 1:
102                    c->octets = strtoul (p, NULL, 10);
103                    break;
104                    
105                case 7:
106                    c->flags = strtoul (p, NULL, 10);
107                    break;
108                    
109                default:
110                    break;
111                }
112                pos++;
113                p = strtok (NULL, " ");
114            }
115            if (!*ctx)
116                *ctx = c;
117            else {
118                for (t = *ctx; t->next; t=t->next)
119                    ;
120                t->next = c;
121            }
122            c->d = (unsigned char*)malloc (c->octets);
123            if (!c->d)
124                BUG (0);
125            memcpy (c->d, data, c->octets);
126            data += c->octets;
127            datlen -= c->octets;
128            n++;
129        }
130        /*assert (datlen == 0); */
131        return n;
132    }
133    
134    
135    static int
136    parse_attr_data (const char *keyid, attr_list_t *list)
137  {  {
138      char dig[3];      gpgme_error_t err;
139      size_t i;      FILE *tmp;    
140        BYTE *data;
141        char *status, tmpnam[MAX_PATH+1];
142        DWORD ndata = 0;
143    
144        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
145        if (err)
146            return err;
147    
148      memset (dst, 0, dlen);      get_temp_name (tmpnam, MAX_PATH, NULL);
149      for (i = 0; i < nbytes && dlen > 0; i++) {      tmp = fopen (tmpnam, "w+b");
150          sprintf (dig, "%02X", buf[i]);      if (ndata > 0 && tmp != NULL) {
151          strcat (dst, dig);          fwrite (status, 1, strlen (status), tmp);
152          dlen -= 2;          fflush (tmp);
153            rewind (tmp);
154    
155            ndata = parse_attr_list (tmp, data, ndata, list);
156            fclose (tmp);
157            DeleteFile (tmpnam);
158      }      }
159        else
160            *list = NULL;
161    
162        safe_free (status);
163        safe_free (data);
164        return ndata;
165  }  }
 #endif  
166    
167    
168  /* 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 170  buffer_to_string (char *dst, size_t dlen
170  static void  static void
171  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
172  {      {    
173      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
174      PKT_secret_key *sk;      PKT_secret_key *sk;
175      gpg_iobuf_t inp;      gpg_iobuf_t inp;
176      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 179  parse_secring (gpg_keycache_t cache, con
179      char keyid[16+1];      char keyid[16+1];
180    
181      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
182      if (!inp) {      if (!inp)
         safe_free (pkt);  
183          return;          return;
184      }  
185      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
186        pkt = (PACKET*)calloc (1, sizeof *pkt);
187        if (!pkt)
188            BUG (0);
189      gpg_init_packet (pkt);      gpg_init_packet (pkt);
190      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
191          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 102  next: Line 214  next:
214  }  }
215    
216    
217    /* Update the photo image of a single key with the fingerprint
218       @fpr. The @dat struct contains the new item data. */
219    static gpgme_error_t
220    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
221    {
222        struct keycache_s *fnd = NULL;
223        gpgme_key_t key;
224        
225        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
226        if (!fnd)
227            return gpg_error (GPG_ERR_NOT_FOUND);
228        safe_free (fnd->attrib.d);
229        fnd->attrib.flags = dat->flags;
230        fnd->attrib.len = dat->octets;
231        fnd->attrib.d = (unsigned char*)malloc (dat->octets);
232        if (!fnd->attrib.d)
233            BUG (0);
234        memcpy (fnd->attrib.d, dat->d, dat->octets);
235        return 0;
236    }
237    
238    
239    /* Update all photo images in the cache. */
240    static gpgme_error_t
241    keycache_update_photos (gpg_keycache_t ctx)
242    {
243        attr_list_t list=NULL, n;
244        DWORD ndata;
245    
246        ndata = parse_attr_data (NULL, &list);
247        if (ndata < 1) {
248            free_attr_list (list);
249            return 0;
250        }
251    
252        for (n=list; n; n=n->next)
253            keycache_update_photo (ctx, n->fpr, n);
254        free_attr_list (list);
255        return 0;
256    }
257    
258    
259    static void
260    keycache_decode_uid (struct keycache_s *ctx)
261    {
262        gpgme_user_id_t u;
263        struct native_uid_s *n, *t;
264    
265        for (u = ctx->key->uids; u; u = u->next) {
266            n = (struct native_uid_s*)calloc (1, sizeof *n);
267            if (!n)
268                BUG (0);
269            if (is_8bit_string (u->uid)) {
270                n->malloced = 1;
271                n->uid = utf8_to_native (u->uid);
272                if (u->name != NULL)
273                    n->name = utf8_to_native (u->name);
274                if (u->email != NULL)
275                    n->email = strdup (u->email);
276                if (u->comment != NULL)
277                    n->comment = utf8_to_native (u->comment);
278            }
279            else {
280                n->malloced = 0;
281                n->uid = u->uid;
282                n->name = u->name;
283                n->comment = u->comment;
284                n->email = u->email;
285            }
286            n->signatures = u->signatures;
287            n->validity = u->validity;
288            n->revoked = u->revoked;
289            if (!ctx->uids)
290                ctx->uids = n;
291            else {
292                for (t = ctx->uids; t->next; t=t->next)
293                    ;
294                t->next = n;          
295            }
296        }
297    }
298    
299    
300    /* Store utf8 decoded user IDs in the code to avoid in-place decoding. */
301    static void
302    keycache_decode_uids (gpg_keycache_t ctx)
303    {
304        struct keycache_s *c;
305    
306        for (c = ctx->item; c; c = c->next)
307            keycache_decode_uid (c);
308    }
309    
310    
311    static void
312    free_native_uids (struct native_uid_s **r_n)
313    {
314        struct native_uid_s *t;
315        struct native_uid_s *n = *r_n;
316    
317        while (n != NULL) {
318            t = n->next;
319            if (n->malloced) {
320                safe_free (n->uid);
321                safe_free (n->name);
322                safe_free (n->comment);
323                safe_free (n->email);
324                safe_free (n->uid);
325            }
326            safe_free (n);
327            n = t;
328        }
329        *r_n = NULL;
330    }
331    
332    
333    
334  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
335  gpgme_error_t  static gpgme_error_t
336  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
337                     const char *pubring, const char *secring)                     const char *pubring, const char *secring)
338  {  {
339      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
340      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
341      gpg_iobuf_t inp;      gpg_iobuf_t inp;
342      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
343      struct keycache_s *c;      struct keycache_s *c;
344      const byte *sym_prefs;      const byte *sym_prefs;
345      char keyid[16+1], *id = NULL;      char keyid[16+1];
346      int key_seen = 0;      int key_seen = 0;
347      size_t nsym =0;      size_t nsym =0;
348    
349      if (secring) {      if (secring) {
350          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
351          if (!pubring) {          if (!pubring)
             safe_free (pkt);  
352              return 0;              return 0;
         }  
353      }      }
354      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
355      if (!inp) {      if (!inp)
         safe_free (pkt);  
356          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
     }  
357      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
358    
359        pkt = (PACKET*)calloc (1, sizeof * pkt);
360        if (!pkt)
361            BUG (0);
362      gpg_init_packet (pkt);      gpg_init_packet (pkt);
363      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
364          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
365              strcpy (keyid, "");              strcpy (keyid, "");
366              key_seen = 1;              key_seen = 1;
367          }          }
368            if (pkt->pkttype == PKT_SIGNATURE &&
369          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {              pkt->pkt.signature->sig_class == 0x1F) {
370              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
371                  goto next;                  goto next;
372              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
373                            pkt->pkt.signature->keyid[1]);
374              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
375                  goto next;                  goto next;
376              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
# Line 149  keycache_prepare2 (gpg_keycache_t ctx, c Line 378  keycache_prepare2 (gpg_keycache_t ctx, c
378                  goto next;                  goto next;
379              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
380          }          }
381          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1) {
382              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
383                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
384              if (sym_prefs == NULL)              if (!sym_prefs)
385                  goto next;                  goto next;
386              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
387                            pkt->pkt.signature->keyid[1]);
388              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
389                  goto next;                  goto next;
390              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
391              if (err)              if (err || !c)
392                    goto next;
393                if (c->sym_prefs) /* only use the prefs from the primary uid. */
394                  goto next;                  goto next;
395              else if (nsym > 0) {              else if (nsym > 0) {
396                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
397                  if (!c->sym_prefs)                  if (!c->sym_prefs)
398                      return gpg_error (GPG_ERR_ENOMEM);                      BUG (0);
399                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
400              }              }
401          }          }
         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;  
         }  
402  next:  next:
403          gpg_free_packet (pkt);          gpg_free_packet (pkt);
404          gpg_init_packet(pkt);          gpg_init_packet(pkt);
405      }      }
406    
 fail:  
     safe_free (id);  
407      safe_free (pkt);      safe_free (pkt);
408      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
409      return err;      return err;
# Line 230  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 437  gpg_keycache_new (gpg_keycache_t *r_ctx)
437          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
438      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
439      if (!ctx)      if (!ctx)
440          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
441      ctx->secret = 0;      ctx->secret = 0;
442      ctx->pos = 0;      ctx->pos = 0;
443      *r_ctx = ctx;      *r_ctx = ctx;
# Line 251  gpg_keycache_release (gpg_keycache_t ctx Line 458  gpg_keycache_release (gpg_keycache_t ctx
458          c2 = c->next;          c2 = c->next;
459          gpgme_key_release (c->key);          gpgme_key_release (c->key);
460          c->key = NULL;          c->key = NULL;
461          if (c->sym_prefs)          if (c->rev != NULL)
462              free (c->sym_prefs);              gpg_desig_rev_release (c->rev);
463          c->sym_prefs = NULL;          c->rev = NULL;
464          if (c->attrib.d)          safe_free (c->pref_keyserver);
465              free (c->attrib.d);          safe_free (c->sym_prefs);
466          c->attrib.d = NULL;          safe_free (c->attrib.d);
467          if (c->card_type)          safe_free (c->card_type);
468              free (c->card_type);          free_native_uids (&c->uids);
469          free (c);          safe_free (c);
470      }      }
471      if (ctx)      safe_free (ctx);
         free (ctx);  
472  }  }
473    
474    
# Line 296  gpg_keycache_add_key (gpg_keycache_t ctx Line 502  gpg_keycache_add_key (gpg_keycache_t ctx
502            
503      c = (struct keycache_s*)calloc (1, sizeof *c);      c = (struct keycache_s*)calloc (1, sizeof *c);
504      if (!c)      if (!c)
505          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
506      c->gloflags.is_protected = 1; /*default: assume protection. */      c->gloflags.is_protected = 1; /*default: assume protection. */
507      c->key = key;      c->key = key;
508      if (!ctx->item)      if (!ctx->item)
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 573  gpg_keycache_find_key2 (gpg_keycache_t c
573      }      }
574      *r_key = NULL;      *r_key = NULL;
575      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
576  } /* keycache_find_key */  }
577    
578    
579  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 584  gpg_keycache_find_key (gpg_keycache_t ct
584  }  }
585    
586    
587    /* Reload a photo image of a single key with the keyid @keyid.
588       Return value: 0 on success. */
589    static gpgme_error_t
590    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
591    {
592        attr_list_t list;
593    
594        if (parse_attr_data (keyid, &list) < 1) {
595            free_attr_list (list);
596            return 0;
597        }
598        keycache_update_photo (ctx, list->fpr, list);
599        free_attr_list (list);
600        return 0;
601    }
602    
603    
604    /* Return the next key which was updated. Before it is
605       returned the update flag is cleared.
606       @r_status is 1 for a new key and 2 for an updated key.
607       Return value: 0 on success. */
608    gpgme_error_t
609    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
610                                   struct keycache_s **r_obj,
611                                   int *r_status)
612    {
613        struct keycache_s *c;
614    
615        for (c = ctx->item; c; c = c->next) {
616            if (c->flags != 0) {
617                *r_status = c->flags;
618                *r_obj = c;
619                c->flags = 0;
620                return 0;
621            }
622        }
623        return gpg_error (GPG_ERR_NOT_FOUND);
624    }
625    
626    
627    
628  gpgme_error_t  gpgme_error_t
629  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
630                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
# Line 391  gpg_keycache_update_key (gpg_keycache_t Line 638  gpg_keycache_update_key (gpg_keycache_t
638      err = gpgme_new (&gctx);      err = gpgme_new (&gctx);
639      if (err)      if (err)
640          return err;          return err;
641        gpgme_set_keylist_mode  (gctx, GPGME_KEYLIST_MODE_SIGS/*|GPGME_KEYLIST_MODE_SIG_NOTATIONS*/);
642      err = gpgme_get_key (gctx, keyid, &key, is_sec);      err = gpgme_get_key (gctx, keyid, &key, is_sec);
643      gpgme_release (gctx);      gpgme_release (gctx);
644      if (err)      if (err)
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 648  gpg_keycache_update_key (gpg_keycache_t
648          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
649          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
650          c->key = key;          c->key = key;
651          c->flags = 0;          c->flags = KC_FLAG_UPD;
652          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
653              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
654              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
655              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
656          }          }
657            /* XXX: this is also called for keys without a photo-id. */
658            keycache_reload_photo (ctx, keyid);
659      }      }
660      else {      else {
661          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 671  gpg_keycache_update_key (gpg_keycache_t
671                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
672              }              }
673          }          }
674            if (c)
675                c->flags = KC_FLAG_ADD;
676    
677        }
678    
679        /* refresh utf8 user ID list. */
680        if (c != NULL) {
681            free_native_uids (&c->uids);
682            keycache_decode_uid (c);
683      }      }
684    
685      return 0;      return 0;
686  }  }
687    
# Line 444  gpg_keycache_delete_key (gpg_keycache_t Line 704  gpg_keycache_delete_key (gpg_keycache_t
704      c = ctx->item;      c = ctx->item;
705      if (c->next == NULL) {      if (c->next == NULL) {
706          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
707          if (itm)          safe_free (itm);
             free (itm);  
708          ctx->item = NULL;          ctx->item = NULL;
709      }      }
710      else {      else {
711          while (c && c->next != itm)          for (; c != NULL; c = c->next) {
712              c = c->next;              if (c->next == itm)
713                    break;
714            }
715            assert (c != NULL); /* XXX: sometimes access violation. */
716          c->next = c->next->next;          c->next = c->next->next;
717          gpgme_key_release (itm->key);          gpgme_key_release (itm->key);
718          if (itm)          safe_free (itm);
             free (itm);  
719      }      }
720      return 0;      return 0;
721  }  }
# Line 478  gpg_keycache_init (gpg_keycache_t ctx, c Line 739  gpg_keycache_init (gpg_keycache_t ctx, c
739      if (err)      if (err)
740          return err;          return err;
741    
742      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);      /* XXX: GPGME_KEYLIST_MODE_SIG_NOTATIONS causes an internal error! */
743        gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS/*|GPGME_KEYLIST_MODE_SIG_NOTATIONS*/);
744      err = gpgme_op_keylist_start (c, pattern, secret);      err = gpgme_op_keylist_start (c, pattern, secret);
745      while(!err) {      while(!err) {
746          err = gpgme_op_keylist_next (c, &key);          err = gpgme_op_keylist_next (c, &key);
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 752  gpg_keycache_init (gpg_keycache_t ctx, c
752      }      }
753      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
754          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
755        keycache_update_photos (ctx);
756        keycache_decode_uids (ctx);
757      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
758      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
759      gpgme_release (c);      gpgme_release (c);
# Line 527  copy_uid_prefs (const unsigned char *pre Line 791  copy_uid_prefs (const unsigned char *pre
791          pos++;          pos++;
792      p = (unsigned char*)calloc (1, pos+1);      p = (unsigned char*)calloc (1, pos+1);
793      if (!p)      if (!p)
794          abort ();          BUG (0);
795      memcpy (p, prefs, pos);      memcpy (p, prefs, pos);
796      return p;      return p;
797  }  }
# Line 548  gpg_keycache_sync (gpg_keycache_t pub, g Line 812  gpg_keycache_sync (gpg_keycache_t pub, g
812              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
813              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
814                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
815              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
816                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
817              c->pubpart = c_sec;              c->pubpart = c_sec;
818              c->pubpart->key = key;              c->pubpart->key = key;
819          }          }
# Line 597  keycache_next_key (gpg_keycache_t ctx, i Line 862  keycache_next_key (gpg_keycache_t ctx, i
862          *r_key = NULL;          *r_key = NULL;
863          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
864      }      }
865            if (ctx->tmp->flags != 0)
866            ctx->tmp->flags = 0; /* reset the 'updated' status. */
867        /* it might be possible there is no public key. */
868        if (flags && ctx->tmp->pubpart == NULL)
869            flags = 0;
870      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
871      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp;
872        ctx->tmp = ctx->tmp->next;    
873      ctx->pos++;      ctx->pos++;
874    
875      return 0;      return 0;
# Line 613  gpgme_error_t Line 883  gpgme_error_t
883  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)
884  {  {
885      struct keycache_s *c=NULL;      struct keycache_s *c=NULL;
886      gpgme_error_t err = 0;      gpgme_error_t err;
887    
888      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
889      return err;      return err;
890  }  }
891    
892    gpgme_error_t
893    gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags,
894                            struct keycache_s **c, gpgme_key_t *r_key)
895    {
896        return keycache_next_key (ctx, flags, c, r_key);
897    }
898    
899    
900    /* Search for a key with the pattern @pattern and mark
901       this key as the default signing key if found.
902       Return value: 0 on success. */
903    gpgme_error_t
904    gpg_keycache_set_default_key (gpg_keycache_t ctx,
905                                  const char *pattern)
906    {
907        gpgme_error_t err;
908        gpgme_key_t key;
909        struct keycache_s *itm;
910    
911        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
912        if (err)
913            return err;
914    
915        if (itm)
916            itm->default_key = 1;
917        return 0;
918    }
919    
920    /* Return the default key from the cache. If no was
921       marked before, NULL is returned in @r_key.
922       Return value: 0 on success. */
923    gpgme_error_t
924    gpg_keycache_get_default_key (gpg_keycache_t ctx,
925                                  gpgme_key_t *r_key)
926    {
927        struct keycache_s *itm;
928    
929        *r_key = NULL;
930        for (itm = ctx->item; itm; itm = itm->next) {
931            if (itm->default_key) {
932                *r_key = itm->key;
933                break;
934            }
935        }
936        if (!*r_key)
937            return gpgme_error (GPG_ERR_NOT_FOUND);
938        return 0;
939    }
940    
941    
942    static gpgme_error_t
943    decode_subpacket (const char *subpkt_data, int *type,
944                      char **out, WORD *outlen)
945    {
946        char tmp[128], *val;
947        char *enc = NULL;
948        size_t pos = 0, i=0;
949    
950        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
951        *outlen = 0;
952        *out = NULL;
953        
954        if (strncmp (subpkt_data, "spk:", 4))
955            return gpg_error (GPG_ERR_NO_DATA);
956    
957        strncpy (tmp, subpkt_data, 62);
958        val = strtok (tmp, ":");
959        while (val != NULL) {
960            switch (pos++) {
961            case 0:
962                break;
963    
964            case 1:
965                if (type)
966                    *type = atoi (val);
967                break;
968    
969            case 2:
970                break;
971    
972            case 3:
973                *outlen = atoi (val);
974                break;
975    
976            case 4:
977                enc = strdup (val);
978                break;
979            }
980            val = strtok (NULL, ":");
981        }
982        if (!enc)
983            return gpg_error (GPG_ERR_NO_DATA);;
984        *out = (char*)calloc (1, strlen (enc)+1);
985        if (!*out)
986            BUG (0);
987        for (pos = 0; pos < strlen (enc); pos++) {
988            if (enc[pos] == '%' && enc[pos+1] == '%')
989                (*out)[i++] = '%';
990            else if (enc[pos] == '%') {
991                char temp[3];
992                temp[0] = enc[++pos];
993                temp[1] = enc[++pos];
994                temp[2] = 0;
995                (*out)[i++] = (char)strtoul (temp, NULL, 16);
996            }
997            else
998                (*out)[i++] = enc[pos];
999        }
1000        (*out)[i] = 0;
1001        safe_free (enc);
1002        return 0;
1003    }
1004    
1005    
1006    /* If the attribute given in @attr is not set in the
1007       key cache object, try to update it. */
1008    gpgme_error_t
1009    gpg_keycache_update_attr (struct keycache_s *item,
1010                              int attr, int force)
1011    {
1012        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
1013        char *val = NULL;
1014        WORD n = 0;    
1015    
1016        switch (attr) {
1017        case KC_ATTR_PREFSYM:
1018            if (!force && item->sym_prefs)
1019                break;
1020            safe_free (item->sym_prefs);
1021            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1022            if (!err && val != NULL)
1023                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
1024            break;
1025    
1026        case KC_ATTR_PREFKSERV:
1027            if (!force && item->pref_keyserver)
1028                break;
1029            safe_free (item->pref_keyserver);
1030            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1031            if (!err && val != NULL)
1032                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
1033            if (!err && item->pref_keyserver)
1034                err = parse_keyserver_url (&item->pref_keyserver,
1035                                           &item->pref_keyserver_port);
1036            break;
1037        }
1038        safe_free (val);
1039        return err;
1040    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26