/[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 217 by twoaday, Mon May 22 14:21:39 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 25  Line 25 
25  #include <windows.h>  #include <windows.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <string.h>  #include <string.h>
 #include <malloc.h>  
28  #include <ctype.h>  #include <ctype.h>
29  #include <assert.h>  #include <assert.h>
30  #include <gpgme.h>  #include <gpgme.h>
# Line 35  Line 34 
34  #include "wptNLS.h"  #include "wptNLS.h"
35  #include "wptErrors.h"  #include "wptErrors.h"
36  #include "wptW32API.h"  #include "wptW32API.h"
37    #include "wptGPG.h"
38    #include "wptTypes.h"
39    #include "wptCommonCtl.h"
40    #include "wptContext.h"
41    #include "wptKeyEdit.h"
42    #include "wptUTF8.h"
43    
44    
45    gpgme_error_t parse_keyserver_url (char **r_keyserver, unsigned short *r_port);
46    
47    /* Attribute list which holds the image data. */
48    struct attr_list_s {
49        struct attr_list_s *next;
50        char *fpr;                   /* fingerprint of the key */
51        unsigned char *d;            /* actual JPEG data. */
52        unsigned long octets;        /* length of the data. */
53        unsigned int flags;          /* status of the attribute. */
54    };
55    typedef struct attr_list_s *attr_list_t;
56    
57    
58  #if 0  /* Free attribute list @ctx. */
59  /* convert a binary buffer into its hex representation. */  void
60  static void  free_attr_list (attr_list_t ctx)
 buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)  
61  {  {
62      char dig[3];      attr_list_t n;
     size_t i;  
63    
64      memset (dst, 0, dlen);      while (ctx) {
65      for (i = 0; i < nbytes && dlen > 0; i++) {          n = ctx->next;
66          sprintf (dig, "%02X", buf[i]);          free_if_alloc (ctx->fpr);
67          strcat (dst, dig);          free_if_alloc (ctx->d);
68          dlen -= 2;          free_if_alloc (ctx);
69            ctx = n;
70      }      }
71  }  }
72  #endif          
73    /* Parse the attribute list in @fp and store it into @ctx.
74       Return value: number of parsed items. */
75    int
76    parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
77    {
78        attr_list_t c, t;
79        char buf[512], *p, *buffer;
80        int pos, n=0;
81        
82        *ctx = NULL;
83        while (fgets (buf, 511, fp)) {
84            if (strstr (buf, "\r\n"))
85                buf[strlen (buf)-2]=0;
86            if (strstr (buf, "\n"))
87                buf[strlen (buf)-1]=0;
88            if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
89                continue;
90            buffer = buf+9+10;
91            pos = 0;
92            c = new attr_list_s;
93            if (!c)
94                BUG (0);
95            memset (c, 0, sizeof *c);
96    
97            p = strtok (buffer, " ");
98            while (p != NULL) {
99                switch (pos) {
100                case 0:
101                    c->fpr = m_strdup (p);
102                    break;
103                    
104                case 1:
105                    c->octets = strtoul (p, NULL, 10);
106                    break;
107                    
108                case 7:
109                    c->flags = strtoul (p, NULL, 10);
110                    break;
111                    
112                default:
113                    break;
114                }
115                pos++;
116                p = strtok (NULL, " ");
117            }
118            if (!*ctx)
119                *ctx = c;
120            else {
121                for (t = *ctx; t->next; t=t->next)
122                    ;
123                t->next = c;
124            }
125            c->d = new unsigned char[c->octets];
126            if (!c->d)
127                BUG (0);
128            memcpy (c->d, data, c->octets);
129            data += c->octets;
130            datlen -= c->octets;
131            n++;
132        }
133        /*assert (datlen == 0); */
134        return n;
135    }
136    
137    
138    static int
139    parse_attr_data (const char *keyid, attr_list_t *list)
140    {
141        gpgme_error_t err;
142        FILE *tmp;    
143        BYTE *data;
144        char *status, tmpnam[MAX_PATH+1];
145        DWORD ndata = 0;
146    
147        err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
148        if (err)
149            return err;
150    
151        get_temp_name (tmpnam, MAX_PATH, NULL);
152        tmp = fopen (tmpnam, "w+b");
153        if (ndata > 0 && tmp != NULL) {
154            fwrite (status, 1, strlen (status), tmp);
155            fflush (tmp);
156            rewind (tmp);
157    
158            ndata = parse_attr_list (tmp, data, ndata, list);
159            fclose (tmp);
160            DeleteFile (tmpnam);
161        }
162        else
163            *list = NULL;
164    
165        safe_free (status);
166        safe_free (data);
167        return ndata;
168    }
169    
170    
171  /* 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 173  buffer_to_string (char *dst, size_t dlen
173  static void  static void
174  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
175  {      {    
176      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);      PACKET *pkt;
177      PKT_secret_key *sk;      PKT_secret_key *sk;
178      gpg_iobuf_t inp;      gpg_iobuf_t inp;
179      gpgme_error_t err;      gpgme_error_t err;
# Line 69  parse_secring (gpg_keycache_t cache, con Line 182  parse_secring (gpg_keycache_t cache, con
182      char keyid[16+1];      char keyid[16+1];
183    
184      inp = gpg_iobuf_open (secring);      inp = gpg_iobuf_open (secring);
185      if (!inp) {      if (!inp)
         safe_free (pkt);  
186          return;          return;
187      }  
188      gpg_iobuf_ioctl (inp, 3, 1, NULL);      gpg_iobuf_ioctl (inp, 3, 1, NULL);
189        pkt = (PACKET*)calloc (1, sizeof *pkt);
190        if (!pkt)
191            BUG (0);
192      gpg_init_packet (pkt);      gpg_init_packet (pkt);
193      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
194          if (pkt->pkttype == PKT_SECRET_KEY) {          if (pkt->pkttype == PKT_SECRET_KEY) {
# Line 88  parse_secring (gpg_keycache_t cache, con Line 203  parse_secring (gpg_keycache_t cache, con
203                  goto next;                  goto next;
204              c->gloflags.is_protected = sk->is_protected;              c->gloflags.is_protected = sk->is_protected;
205              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
206              if (c->pubpart != NULL) {                  if (c->pubpart != NULL) {
207                  c->pubpart->gloflags.is_protected = sk->is_protected;                      c->pubpart->gloflags.is_protected = sk->is_protected;
208                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
209              }              }
210          }          }
# Line 102  next: Line 217  next:
217  }  }
218    
219    
220    /* Update the photo image of a single key with the fingerprint
221       @fpr. The @dat struct contains the new item data. */
222    static gpgme_error_t
223    keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
224    {
225        struct keycache_s *fnd = NULL;
226        gpgme_key_t key;
227        
228        gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
229        if (!fnd)
230            return gpg_error (GPG_ERR_NOT_FOUND);
231        free_if_alloc (fnd->attrib.d);
232        fnd->attrib.flags = dat->flags;
233        fnd->attrib.len = dat->octets;
234        fnd->attrib.d = new unsigned char[dat->octets];
235        if (!fnd->attrib.d)
236            BUG (0);
237        memcpy (fnd->attrib.d, dat->d, dat->octets);
238        return 0;
239    }
240    
241    
242    /* Update all photo images in the cache. */
243    static gpgme_error_t
244    keycache_update_photos (gpg_keycache_t ctx)
245    {
246        attr_list_t list=NULL, n;
247        DWORD ndata;
248    
249        ndata = parse_attr_data (NULL, &list);
250        if (ndata < 1) {
251            free_attr_list (list);
252            return 0;
253        }
254    
255        for (n=list; n; n=n->next)
256            keycache_update_photo (ctx, n->fpr, n);
257        free_attr_list (list);
258        return 0;
259    }
260    
261    
262    void
263    keycache_decode_uid (struct keycache_s *ctx)
264    {
265        gpgme_user_id_t u;
266        struct native_uid_s *n, *t;
267    
268        for (u = ctx->key->uids; u; u = u->next) {
269            n = new native_uid_s;
270            if (!n)
271                BUG (0);
272            memset (n, 0, sizeof *n);
273            if (is_8bit_string (u->uid)) {
274                n->malloced = 1;
275                n->uid = utf8_to_native (u->uid);
276                if (u->name != NULL)
277                    n->name = utf8_to_native (u->name);
278                if (u->email != NULL)
279                    n->email = m_strdup (u->email);
280                if (u->comment != NULL)
281                    n->comment = utf8_to_native (u->comment);
282            }
283            else {
284                n->malloced = 0;
285                n->uid = u->uid;
286                n->name = u->name;
287                n->comment = u->comment;
288                n->email = u->email;
289            }
290            n->signatures = u->signatures;
291            n->validity = u->validity;
292            n->revoked = u->revoked;
293            if (!ctx->uids)
294                ctx->uids = n;
295            else {
296                for (t = ctx->uids; t->next; t=t->next)
297                    ;
298                t->next = n;          
299            }
300        }
301    }
302    
303    
304    /* Store utf8 decoded user IDs in the code to avoid in-place decoding. */
305    static void
306    keycache_decode_uids (gpg_keycache_t ctx)
307    {
308        struct keycache_s *c;
309    
310        for (c = ctx->item; c; c = c->next)
311            keycache_decode_uid (c);
312    }
313    
314    
315    static void
316    free_native_uids (struct native_uid_s **r_n)
317    {
318        struct native_uid_s *t;
319        struct native_uid_s *n = *r_n;
320    
321        while (n != NULL) {
322            t = n->next;
323            if (n->malloced) {
324                free_if_alloc (n->uid);
325                free_if_alloc (n->name);
326                free_if_alloc (n->comment);
327                free_if_alloc (n->email);
328            }
329            free_if_alloc (n);
330            n = t;
331        }
332        *r_n = NULL;
333    }
334    
335    
336    
337  /* Merge the information from the keyrings into the key cache structure. */  /* Merge the information from the keyrings into the key cache structure. */
338  gpgme_error_t  static gpgme_error_t
339  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
340                     const char *pubring, const char *secring)                     const char *pubring, const char *secring)
341  {  {
342      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
343      gpgme_key_t key = NULL;      gpgme_key_t key = NULL;
344      gpg_iobuf_t inp;      gpg_iobuf_t inp;
345      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);      PACKET *pkt;
346      struct keycache_s *c;      struct keycache_s *c;
347      const byte *sym_prefs;      const byte *sym_prefs;
348      char keyid[16+1], *id = NULL;      char keyid[16+1];
349      int key_seen = 0;      int key_seen = 0;
350      size_t nsym =0;      size_t nsym =0;
351    
352      if (secring) {      if (secring) {
353          parse_secring (ctx, kid, secring);          parse_secring (ctx, kid, secring);
354          if (!pubring) {          if (!pubring)
             safe_free (pkt);  
355              return 0;              return 0;
         }  
356      }      }
357      inp = gpg_iobuf_open (pubring);      inp = gpg_iobuf_open (pubring);
358      if (!inp) {      if (!inp)
         safe_free (pkt);  
359          return gpg_error (GPG_ERR_KEYRING_OPEN);          return gpg_error (GPG_ERR_KEYRING_OPEN);
     }  
360      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
361    
362        pkt = (PACKET*)calloc (1, sizeof * pkt);
363        if (!pkt)
364            BUG (0);
365      gpg_init_packet (pkt);      gpg_init_packet (pkt);
366      while (gpg_parse_packet (inp, pkt) != -1) {      while (gpg_parse_packet (inp, pkt) != -1) {
367          if (pkt->pkttype == PKT_PUBLIC_KEY) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
368              strcpy (keyid, "");              strcpy (keyid, "");
369              key_seen = 1;              key_seen = 1;
370          }          }
371            if (pkt->pkttype == PKT_SIGNATURE &&
372          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {              pkt->pkt.signature->sig_class == 0x1F) {
373              if (pkt->pkt.signature->numrevkeys == 0)              if (pkt->pkt.signature->numrevkeys == 0)
374                  goto next;                  goto next;
375              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) -1, "%08X",
376                            pkt->pkt.signature->keyid[1]);
377              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
378                  goto next;                  goto next;
379              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 381  keycache_prepare2 (gpg_keycache_t ctx, c
381                  goto next;                  goto next;
382              c->gloflags.has_desig_rev = 1;              c->gloflags.has_desig_rev = 1;
383          }          }
384          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 && c != NULL) {
385              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
386                                              SIGSUBPKT_PREF_SYM, &nsym);                                                SIGSUBPKT_PREF_SYM, &nsym);
387              if (sym_prefs == NULL)              if (!sym_prefs)
388                  goto next;                  goto next;
389              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);              _snprintf (keyid, sizeof (keyid) - 1, "%08X",
390                            pkt->pkt.signature->keyid[1]);
391              if (kid && strcmp (kid, keyid) != 0)              if (kid && strcmp (kid, keyid) != 0)
392                  goto next;                  goto next;
393              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
394              if (err)              if (err || !c)
395                    goto next;
396                if (c->sym_prefs) /* only use the prefs from the primary uid. */
397                  goto next;                  goto next;
398              else if (nsym > 0) {              else if (nsym > 0) {
399                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  c->sym_prefs = new unsigned char[nsym+1];
400                  if (!c->sym_prefs)                  if (!c->sym_prefs)
401                      return gpg_error (GPG_ERR_ENOMEM);                      BUG (0);
402                    memset (c->sym_prefs, 0, nsym+1);
403                  memcpy (c->sym_prefs, sym_prefs, nsym);                  memcpy (c->sym_prefs, sym_prefs, nsym);
404              }              }
405          }          }
         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;  
         }  
406  next:  next:
407          gpg_free_packet (pkt);          gpg_free_packet (pkt);
408          gpg_init_packet(pkt);          gpg_init_packet(pkt);
409      }      }
410    
 fail:  
     safe_free (id);  
411      safe_free (pkt);      safe_free (pkt);
412      gpg_iobuf_close (inp);      gpg_iobuf_close (inp);
413      return err;      return err;
# Line 228  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 439  gpg_keycache_new (gpg_keycache_t *r_ctx)
439            
440      if (!r_ctx)      if (!r_ctx)
441          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
442      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);      ctx = new gpg_keycache_s;    
443      if (!ctx)      if (!ctx)
444          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
445        memset (ctx, 0, sizeof *ctx);
446      ctx->secret = 0;      ctx->secret = 0;
447      ctx->pos = 0;      ctx->pos = 0;
448      *r_ctx = ctx;      *r_ctx = ctx;
# Line 238  gpg_keycache_new (gpg_keycache_t *r_ctx) Line 450  gpg_keycache_new (gpg_keycache_t *r_ctx)
450  }  }
451    
452    
453    void
454    gpg_keycache_item_release (struct keycache_s *c)
455    {
456        if (c->key)
457            gpgme_key_release (c->key);    
458        c->key = NULL;      
459        if (c->rev != NULL)    
460            gpg_desig_rev_release (c->rev);
461        c->rev = NULL;
462        free_if_alloc (c->pref_keyserver);
463        free_if_alloc (c->sym_prefs);
464        free_if_alloc (c->attrib.d);
465        free_if_alloc (c->card_type);
466        free_native_uids (&c->uids);
467        free_if_alloc (c);
468    }
469    
470    
471  /* Release keycache object @ctx. */  /* Release keycache object @ctx. */
472  void  void
473  gpg_keycache_release (gpg_keycache_t ctx)  gpg_keycache_release (gpg_keycache_t ctx)
# Line 249  gpg_keycache_release (gpg_keycache_t ctx Line 479  gpg_keycache_release (gpg_keycache_t ctx
479    
480      for (c = ctx->item; c; c = c2) {      for (c = ctx->item; c; c = c2) {
481          c2 = c->next;          c2 = c->next;
482          gpgme_key_release (c->key);          gpg_keycache_item_release (c);
         c->key = NULL;  
         if (c->sym_prefs)  
             free (c->sym_prefs);  
         c->sym_prefs = NULL;  
         if (c->attrib.d)  
             free (c->attrib.d);  
         c->attrib.d = NULL;  
         if (c->card_type)  
             free (c->card_type);  
         free (c);  
483      }      }
484      if (ctx)      free_if_alloc (ctx);
         free (ctx);  
485  }  }
486    
487    
# Line 294  gpg_keycache_add_key (gpg_keycache_t ctx Line 513  gpg_keycache_add_key (gpg_keycache_t ctx
513      if (!ctx)      if (!ctx)
514          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
515            
516      c = (struct keycache_s*)calloc (1, sizeof *c);      c = new keycache_s;
517      if (!c)      if (!c)
518          return gpg_error (GPG_ERR_ENOMEM);          BUG (0);
519        memset (c, 0, sizeof *c);
520      c->gloflags.is_protected = 1; /*default: assume protection. */      c->gloflags.is_protected = 1; /*default: assume protection. */
521      c->key = key;      c->key = key;
522      if (!ctx->item)      if (!ctx->item)
# Line 367  gpg_keycache_find_key2 (gpg_keycache_t c Line 587  gpg_keycache_find_key2 (gpg_keycache_t c
587      }      }
588      *r_key = NULL;      *r_key = NULL;
589      return gpg_error (GPG_ERR_INTERNAL);      return gpg_error (GPG_ERR_INTERNAL);
590  } /* keycache_find_key */  }
591    
592    
593  gpgme_error_t  gpgme_error_t
# Line 378  gpg_keycache_find_key (gpg_keycache_t ct Line 598  gpg_keycache_find_key (gpg_keycache_t ct
598  }  }
599    
600    
601    /* Reload a photo image of a single key with the keyid @keyid.
602       Return value: 0 on success. */
603    static gpgme_error_t
604    keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
605    {
606        attr_list_t list;
607    
608        if (parse_attr_data (keyid, &list) < 1) {
609            free_attr_list (list);
610            return 0;
611        }
612        keycache_update_photo (ctx, list->fpr, list);
613        free_attr_list (list);
614        return 0;
615    }
616    
617    
618    /* Return the next key which was updated. Before it is
619       returned the update flag is cleared.
620       @r_status is 1 for a new key and 2 for an updated key.
621       Return value: 0 on success. */
622    gpgme_error_t
623    gpg_keycache_next_updated_key (gpg_keycache_t ctx,
624                                   struct keycache_s **r_obj,
625                                   int *r_status)
626    {
627        struct keycache_s *c;
628    
629        for (c = ctx->item; c; c = c->next) {
630            if (c->flags != 0) {
631                *r_status = c->flags;
632                *r_obj = c;
633                c->flags = 0; /* reset update flag. */
634                return 0;
635            }
636        }
637        return gpg_error (GPG_ERR_NOT_FOUND);
638    }
639    
640    
641    static gpgme_error_t
642    get_gpg_key (const char *keyid, int is_sec, gpgme_key_t *r_key)
643    {
644        gpgme_ctx_t ctx;
645        gpgme_error_t err;
646    
647        err = gpgme_new (&ctx);
648        if (err)
649            return err;
650        gpgme_set_keylist_mode  (ctx, GPGME_KEYLIST_MODE_SIGS);
651        err = gpgme_get_key (ctx, keyid, r_key, is_sec);
652        gpgme_release (ctx);
653        return err;
654    }
655    
656    
657    /* Fetch a key directly from gpg but without adding
658       it to the key cache. Caller must free @r_ctx. */
659    gpgme_error_t
660    gpg_keycache_fetch_key (const char *keyid, int is_sec,
661                            gpgme_key_t *r_key, struct keycache_s **r_c)
662    {
663        gpgme_error_t err;
664        gpgme_key_t key;
665        struct keycache_s *c;
666    
667        *r_key = NULL;
668        *r_c = NULL;
669        err = get_gpg_key (keyid, is_sec, &key);
670        if (err)
671            return err;
672    
673        c = new keycache_s;
674        if (!c)
675            BUG (0);
676        memset (c, 0, sizeof *c);
677        c->gloflags.is_protected = 1; /*default: assume protection. */
678        c->key = key;    
679        keycache_decode_uid (c);
680        *r_key = key;
681        *r_c = c;
682        return 0;
683    }
684    
685    
686    /* Update the key with the keyid @key in the key cache.
687       If the key does not exist, it is added otherwise all
688       parts are first freed and then replaced with the updated data. */
689  gpgme_error_t  gpgme_error_t
690  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
691                           void *opaque, const char *keyid)                           void *opaque, const char *keyid)
692  {  {    
     struct keycache_s *c = NULL, *c_new=NULL;  
693      gpgme_key_t key=NULL, fndkey=NULL;      gpgme_key_t key=NULL, fndkey=NULL;
694      gpgme_error_t err;      gpgme_error_t err;
695      gpgme_ctx_t gctx;      struct keycache_s *c = NULL, *c_new=NULL;
696      gpg_keycache_t pub = (gpg_keycache_t)opaque;      gpg_keycache_t pub = (gpg_keycache_t)opaque;
697    
698      err = gpgme_new (&gctx);      err = get_gpg_key (keyid, is_sec, &key);
     if (err)  
         return err;  
     err = gpgme_get_key (gctx, keyid, &key, is_sec);  
     gpgme_release (gctx);  
699      if (err)      if (err)
700          return err;          return err;
701      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
# Line 400  gpg_keycache_update_key (gpg_keycache_t Line 703  gpg_keycache_update_key (gpg_keycache_t
703          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
704          gpgme_key_release (fndkey);          gpgme_key_release (fndkey);
705          c->key = key;          c->key = key;
706          c->flags = 0;          c->flags = KC_FLAG_UPD;
707          if (is_sec && pub != NULL &&          if (is_sec && pub != NULL &&
708              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
709              log_debug ("keycache update: set public part %p\r\n", fndkey);              log_debug ("keycache update: set public part %p\r\n", fndkey);
710              c->pubpart->key = fndkey;              c->pubpart->key = fndkey;
711          }          }
712            /* XXX: this is also called for keys without a photo-id. */
713            keycache_reload_photo (ctx, keyid);
714      }      }
715      else {      else {
716          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 726  gpg_keycache_update_key (gpg_keycache_t
726                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
727              }              }
728          }          }
729            if (c != NULL)
730                c->flags = KC_FLAG_ADD;
731        }
732    
733        /* refresh utf8 user ID list. */
734        if (c != NULL && c->key) {
735            free_native_uids (&c->uids);
736            keycache_decode_uid (c);
737      }      }
738    
739      return 0;      return 0;
740  }  }
741    
# Line 443  gpg_keycache_delete_key (gpg_keycache_t Line 757  gpg_keycache_delete_key (gpg_keycache_t
757            
758      c = ctx->item;      c = ctx->item;
759      if (c->next == NULL) {      if (c->next == NULL) {
760          gpgme_key_release (itm->key);          if (itm->key)
761          if (itm)              gpgme_key_release (itm->key);
762              free (itm);          itm->key = NULL;
763          ctx->item = NULL;          free_if_alloc (itm);
764      }      }
765      else {      else {
766          while (c && c->next != itm)          for (; c != NULL; c = c->next) {
767              c = c->next;              if (c->next == itm)
768                    break;
769            }
770            assert (c != NULL); /* XXX: sometimes access violation. */
771          c->next = c->next->next;          c->next = c->next->next;
772          gpgme_key_release (itm->key);          if (itm->key)
773          if (itm)              gpgme_key_release (itm->key);
774              free (itm);          itm->key = NULL;
775            free_if_alloc (itm);
776      }      }
777      return 0;      return 0;
778  }  }
# Line 478  gpg_keycache_init (gpg_keycache_t ctx, c Line 796  gpg_keycache_init (gpg_keycache_t ctx, c
796      if (err)      if (err)
797          return err;          return err;
798    
799        /* XXX: GPGME_KEYLIST_MODE_SIG_NOTATIONS causes an internal error! */
800      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);
801      err = gpgme_op_keylist_start (c, pattern, secret);      err = gpgme_op_keylist_start (c, pattern, secret);
802      while(!err) {      while(!err) {
# Line 490  gpg_keycache_init (gpg_keycache_t ctx, c Line 809  gpg_keycache_init (gpg_keycache_t ctx, c
809      }      }
810      if (gpgme_err_code (err) == GPG_ERR_EOF)      if (gpgme_err_code (err) == GPG_ERR_EOF)
811          err = gpg_error (GPG_ERR_NO_ERROR);          err = gpg_error (GPG_ERR_NO_ERROR);
812      /* XXX: make sure the progress dialog is closed. */      keycache_update_photos (ctx);
813        keycache_decode_uids (ctx);
814      gpgme_op_keylist_end (c);      gpgme_op_keylist_end (c);
815      gpgme_release (c);      gpgme_release (c);
816      return err;      return err;
# Line 525  copy_uid_prefs (const unsigned char *pre Line 845  copy_uid_prefs (const unsigned char *pre
845    
846      while (prefs[pos] != 0)      while (prefs[pos] != 0)
847          pos++;          pos++;
848      p = (unsigned char*)calloc (1, pos+1);      p = new unsigned char[pos+1];
849      if (!p)      if (!p)
850          abort ();          BUG (0);
851        memset (p, 0, pos+1);
852      memcpy (p, prefs, pos);      memcpy (p, prefs, pos);
853      return p;      return p;
854  }  }
855    
856    
857    /* Sync the secret and the public key cache information. */
858  gpgme_error_t  gpgme_error_t
859  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
860  {  {
# Line 542  gpg_keycache_sync (gpg_keycache_t pub, g Line 864  gpg_keycache_sync (gpg_keycache_t pub, g
864      if (!pub || !sec)      if (!pub || !sec)
865          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
866            
867      for (c=sec->item; c; c=c->next) {        for (c=sec->item; c; c=c->next) {
868          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
869              c_sec->gloflags.is_protected = c->gloflags.is_protected;              c_sec->gloflags.is_protected = c->gloflags.is_protected;
870              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
871              if (!c->gloflags.divert_to_card)              if (!c->gloflags.divert_to_card)
872                  c->gloflags.divert_to_card = key_divert_to_card (key);                  c->gloflags.divert_to_card = key_divert_to_card (key);
873              c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);              if (c_sec->sym_prefs)
874                    c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
875              c->pubpart = c_sec;              c->pubpart = c_sec;
876              c->pubpart->key = key;              c->pubpart->key = key;
877          }          }
# Line 597  keycache_next_key (gpg_keycache_t ctx, i Line 920  keycache_next_key (gpg_keycache_t ctx, i
920          *r_key = NULL;          *r_key = NULL;
921          return gpg_error (GPG_ERR_EOF);          return gpg_error (GPG_ERR_EOF);
922      }      }
923            if (ctx->tmp->flags != 0)
924            ctx->tmp->flags = 0; /* reset the 'updated' status. */
925    
926        /* it might be possible there is no public key. */
927        if (flags && ctx->tmp->pubpart == NULL)
928            flags = 0;
929      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
930      *c = ctx->tmp = ctx->tmp->next;      *c = ctx->tmp;
931        ctx->tmp = ctx->tmp->next;
932      ctx->pos++;      ctx->pos++;
933    
934      return 0;      return 0;
# Line 613  gpgme_error_t Line 942  gpgme_error_t
942  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)
943  {  {
944      struct keycache_s *c=NULL;      struct keycache_s *c=NULL;
945      gpgme_error_t err = 0;      gpgme_error_t err;
946    
947      err = keycache_next_key (ctx, flags, &c, r_key);      err = keycache_next_key (ctx, flags, &c, r_key);
948      return err;      return err;
949  }  }
950    
951    
952    gpgme_error_t
953    gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags,
954                            struct keycache_s **c, gpgme_key_t *r_key)
955    {
956        return keycache_next_key (ctx, flags, c, r_key);
957    }
958    
959    
960    /* Search for a key with the pattern @pattern and mark
961       this key as the default signing key if found.
962       Return value: 0 on success. */
963    gpgme_error_t
964    gpg_keycache_set_default_key (gpg_keycache_t ctx,
965                                  const char *pattern)
966    {
967        gpgme_error_t err;
968        gpgme_key_t key;
969        struct keycache_s *itm;
970    
971        err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
972        if (err)
973            return err;
974    
975        if (itm)
976            itm->default_key = 1;
977        return 0;
978    }
979    
980    /* Return the default key from the cache. If no was
981       marked before, NULL is returned in @r_key.
982       Return value: 0 on success. */
983    gpgme_error_t
984    gpg_keycache_get_default_key (gpg_keycache_t ctx,
985                                  gpgme_key_t *r_key)
986    {
987        struct keycache_s *itm;
988    
989        *r_key = NULL;
990        for (itm = ctx->item; itm; itm = itm->next) {
991            if (itm->default_key) {
992                *r_key = itm->key;
993                break;
994            }
995        }
996        if (!*r_key)
997            return gpgme_error (GPG_ERR_NOT_FOUND);
998        return 0;
999    }
1000    
1001    
1002    static gpgme_error_t
1003    decode_subpacket (const char *subpkt_data, int *type,
1004                      char **out, WORD *outlen)
1005    {
1006        char tmp[128], *val;
1007        char *enc = NULL;      
1008        size_t pos = 0;
1009    
1010        /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
1011        *outlen = 0;
1012        *out = NULL;
1013        
1014        if (strncmp (subpkt_data, "spk:", 4))
1015            return gpg_error (GPG_ERR_NO_DATA);
1016    
1017        /* XXX: do not use static buffer sizes. */
1018        strncpy (tmp, subpkt_data, DIM (tmp)-4);
1019        val = strtok (tmp, ":");
1020        while (val != NULL) {
1021            switch (pos++) {
1022            case 0:
1023                break;
1024    
1025            case 1:
1026                if (type)
1027                    *type = atoi (val);
1028                break;
1029    
1030            case 2:
1031                break;
1032    
1033            case 3:
1034                *outlen = atoi (val);
1035                break;
1036    
1037            case 4:
1038                enc = m_strdup (val);
1039                break;
1040            }
1041            val = strtok (NULL, ":");
1042        }
1043        if (!enc)
1044            return gpg_error (GPG_ERR_NO_DATA);
1045        unhexify_buffer (enc, out);
1046        free_if_alloc (enc);
1047        return 0;
1048    }
1049    
1050    
1051    /* If the attribute given in @attr is not set in the
1052       key cache object, try to update it. */
1053    gpgme_error_t
1054    gpg_keycache_update_attr (struct keycache_s *item,
1055                              int attr, int force)
1056    {
1057        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
1058        char *val = NULL;
1059        WORD n = 0;    
1060    
1061        switch (attr) {
1062        case KC_ATTR_PREFSYM:
1063            if (!force && item->sym_prefs)
1064                break;
1065            free_if_alloc (item->sym_prefs);
1066            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1067            if (!err && val != NULL)
1068                err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
1069            break;
1070    
1071        case KC_ATTR_PREFKSERV:
1072            if (!force && item->pref_keyserver)
1073                break;
1074            free_if_alloc (item->pref_keyserver);
1075            err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1076            if (!err && val != NULL)
1077                err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
1078            if (!err && item->pref_keyserver)
1079                err = parse_keyserver_url (&item->pref_keyserver,
1080                                           &item->pref_keyserver_port);
1081            break;
1082        }
1083        safe_free (val);
1084        return err;
1085    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26