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

Legend:
Removed from v.42  
changed lines
  Added in v.209

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26