/[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 36 by werner, Thu Oct 27 15:25:13 2005 UTC revision 181 by twoaday, Tue Mar 14 11:01:22 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 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    
41    
42  /* convert a binary buffer into its hex representation. */  /* Attribute list which holds the image data. */
43  static void  struct attr_list_s {
44  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)      struct attr_list_s *next;
45  {      char *fpr;                   /* fingerprint of the key */
46      char dig[3];      unsigned char *d;            /* actual JPEG data. */
47      size_t i;      unsigned long octets;        /* length of the data. */
48        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            
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    
# Line 58  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 67  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 100  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,
256                     const char *pubring, const char *secring)                     const char *pubring, const char *secring)
257  {  {
258      gpgme_error_t err;      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 nbytes = 0, 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      gpg_init_packet( pkt );      pkt = (PACKET*)calloc (1, sizeof * pkt);
279        if (!pkt)
280            BUG (0);
281        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) {
284              strcpy (keyid, "");              strcpy (keyid, "");
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 148  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 161  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 *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;  
         }  
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 228  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 249  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 287  gpg_keycache_set_cb (gpg_keycache_t ctx, Line 409  gpg_keycache_set_cb (gpg_keycache_t ctx,
409  gpgme_error_t  gpgme_error_t
410  gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)  gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
411  {  {
412      struct keycache_s * c, * n1;      struct keycache_s *c, *n1;
413            
414      if (!ctx)      if (!ctx)
415          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
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 365  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 376  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                c->flags = 0;
533                *r_obj = c;
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 389  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 398  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 419  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 488  gpg_keycache_init (gpg_keycache_t ctx, c Line 656  gpg_keycache_init (gpg_keycache_t ctx, c
656      }      }
657      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
658          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
659        keycache_update_photos (ctx);
660      /* XXX: make sure the progress dialog is closed. */      /* XXX: make sure the progress dialog is closed. */
661      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
662      gpgme_release (c);      gpgme_release (c);
# Line 515  key_divert_to_card (gpgme_key_t key) Line 684  key_divert_to_card (gpgme_key_t key)
684  }  }
685    
686    
687    static unsigned char*
688    copy_uid_prefs (const unsigned char *prefs)
689    {
690        unsigned char *p;
691        size_t pos=0;
692    
693        while (prefs[pos] != 0)
694            pos++;
695        p = (unsigned char*)calloc (1, pos+1);
696        if (!p)
697            BUG (0);
698        memcpy (p, prefs, pos);
699        return p;
700    }
701    
702    
703  gpgme_error_t  gpgme_error_t
704  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
705  {  {
# Line 530  gpg_keycache_sync (gpg_keycache_t pub, g Line 715  gpg_keycache_sync (gpg_keycache_t pub, g
715              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
716              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
717                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
718                if (c_sec->sym_prefs)
719                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
720              c->pubpart = c_sec;              c->pubpart = c_sec;
721              c->pubpart->key = key;              c->pubpart->key = key;
722          }          }
# Line 578  keycache_next_key (gpg_keycache_t ctx, i Line 765  keycache_next_key (gpg_keycache_t ctx, i
765          *r_key = NULL;          *r_key = NULL;
766          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
767      }      }
768            if (ctx->tmp->flags != 0)
769            ctx->tmp->flags = 0; /* reset the 'updated' status. */
770        /* it might be possible there is no public key. */
771        if (flags && ctx->tmp->pubpart == NULL)
772            flags = 0;
773      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
774      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp = ctx->tmp->next;
775      ctx->pos++;      ctx->pos++;
# Line 599  gpg_keycache_next_key (gpg_keycache_t ct Line 790  gpg_keycache_next_key (gpg_keycache_t ct
790      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
791      return err;      return err;
792  }  }
793    
794    
795    /* Search for a key with the pattern @pattern and mark
796       this key as the default signing key if found.
797       Return value: 0 on success. */
798    gpgme_error_t
799    gpg_keycache_set_default_key (gpg_keycache_t ctx,
800                                  const char *pattern)
801    {
802        gpgme_error_t err;
803        gpgme_key_t key;
804        struct keycache_s *itm;
805    
806        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
807        if (err)
808            return err;
809    
810        if (itm)
811            itm->default_key = 1;
812        return 0;
813    }
814    
815    /* Return the default key from the cache. If no was
816       marked before, NULL is returned in @r_key.
817       Return value: 0 on success. */
818    gpgme_error_t
819    gpg_keycache_get_default_key (gpg_keycache_t ctx,
820                                  gpgme_key_t *r_key)
821    {
822        struct keycache_s *itm;
823    
824        *r_key = NULL;
825        for (itm = ctx->item; itm; itm = itm->next) {
826            if (itm->default_key) {
827                *r_key = itm->key;
828                break;
829            }
830        }
831        if (!*r_key)
832            return gpgme_error (GPG_ERR_NOT_FOUND);
833        return 0;
834    }
835    
836    
837    static gpgme_error_t
838    decode_subpacket (const char *subpkt_data, int *type,
839                      char **out, WORD *outlen)
840    {
841        char tmp[128], *p = tmp, *val;
842        char *enc;
843        size_t pos = 0, i=0;
844    
845        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
846        *outlen = 0;
847        *out = NULL;
848        
849        if (strncmp (subpkt_data, "spk:", 4))
850            return gpg_error (GPG_ERR_NO_DATA);
851    
852        strncpy (tmp, subpkt_data, 62);
853        val = strtok (tmp, ":");
854        while (val != NULL) {
855            switch (pos++) {
856            case 0:
857                break;
858    
859            case 1:
860                if (type)
861                    *type = atoi (val);
862                break;
863    
864            case 2:
865                break;
866    
867            case 3:
868                *outlen = atoi (val);
869                break;
870    
871            case 4:
872                enc = strdup (val);
873                break;
874            }
875            val = strtok (NULL, ":");
876        }
877        if (!enc)
878            return gpg_error (GPG_ERR_NO_DATA);;
879        *out = (char*)calloc (1, strlen (enc)+1);
880        for (pos = 0; pos < strlen (enc); pos++) {
881            if (enc[pos] == '%' && enc[pos+1] == '%')
882                (*out)[i++] = '%';
883            else if (enc[pos] == '%') {
884                char tmp[3];
885                tmp[0] = enc[++pos];
886                tmp[1] = enc[++pos];
887                tmp[2] = 0;
888                (*out)[i++] = (char)strtoul (tmp, NULL, 16);
889            }
890            else
891                (*out)[i++] = enc[pos];
892        }
893        (*out)[i] = 0;
894        free (enc);
895        return 0;
896    }
897    
898    
899    /* If the attribute given in @attr is not set in the
900       key cache object, try to update it. */
901    gpgme_error_t
902    gpg_keycache_update_attr (struct keycache_s *item,
903                              int attr, int force)
904    {
905        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
906        char *val = NULL;
907        WORD n = 0;    
908    
909        switch (attr) {
910        case KC_ATTR_PREFSYM:
911            if (!force && item->sym_prefs)
912                break;
913            safe_free (item->sym_prefs);
914            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
915            if (!err && val != NULL)
916                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
917            break;
918    
919        case KC_ATTR_PREFKSERV:
920            if (!force && item->pref_keyserver)
921                break;
922            safe_free (item->pref_keyserver);
923            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
924            if (!err && val != NULL)
925                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
926            break;
927        }
928        safe_free (val);
929        return err;
930    }
931    

Legend:
Removed from v.36  
changed lines
  Added in v.181

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26