/[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 32 by twoaday, Mon Oct 24 08:03:48 2005 UTC revision 36 by werner, Thu Oct 27 15:25:13 2005 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-2005 Timo Schulz
3   *   *
4   * This file is part of MyGPGME.   * This file is part of MyGPGME.
5   *   *
6   * MyGPGME is free software; you can redistribute it and/or modify   * MyGPGME 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,   * MyGPGME 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.
15   *   *
16   * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
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  #include <windows.h>  #ifdef HAVE_CONFIG_H
21  #include <stdio.h>  #include <config.h>
22  #include <string.h>  #endif
23  #include <malloc.h>  
24  #include <ctype.h>  #include <windows.h>
25  #include <assert.h>  #include <windows.h>
26    #include <stdio.h>
27  #include "w32gpgme.h"  #include <string.h>
28  #include "wptKeyCache.h"  #include <malloc.h>
29  #include "openpgp.h"  #include <ctype.h>
30  #include "wptNLS.h"  #include <assert.h>
31  #include "wptErrors.h"  
32  #include "wptW32API.h"  #include "w32gpgme.h"
33    #include "wptKeyCache.h"
34    #include "openpgp.h"
35  /* convert a binary buffer into its hex representation. */  #include "wptNLS.h"
36  static void  #include "wptErrors.h"
37  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)  #include "wptW32API.h"
38  {  
39      char dig[3];  
40      size_t i;  /* convert a binary buffer into its hex representation. */
41    static void
42      memset (dst, 0, dlen);  buffer_to_string (char *dst, size_t dlen, const byte *buf, size_t nbytes)
43      for (i = 0; i < nbytes && dlen > 0; i++) {  {
44          sprintf (dig, "%02X", buf[i]);      char dig[3];
45          strcat (dst, dig);      size_t i;
46          dlen -= 2;  
47      }      memset (dst, 0, dlen);
48  }      for (i = 0; i < nbytes && dlen > 0; i++) {
49            sprintf (dig, "%02X", buf[i]);
50            strcat (dst, dig);
51  /* Parse the secret keyring and retrieve some additional information          dlen -= 2;
52     for each key which was found. */      }
53  static void  }
54  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)  
55  {      
56      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);  /* Parse the secret keyring and retrieve some additional information
57      PKT_secret_key *sk;     for each key which was found. */
58      gpg_iobuf_t inp;  static void
59      gpgme_error_t err;  parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
60      gpgme_key_t key;  {    
61      struct keycache_s *c=NULL;      PACKET *pkt = (PACKET*)calloc (1, sizeof *pkt);
62      char keyid[16+1];      PKT_secret_key *sk;
63        gpg_iobuf_t inp;
64      inp = gpg_iobuf_open (secring);      gpgme_error_t err;
65      if (!inp) {      gpgme_key_t key;
66          safe_free (pkt);      struct keycache_s *c=NULL;
67          return;      char keyid[16+1];
68      }  
69      gpg_iobuf_ioctl (inp, 3, 1, NULL);      inp = gpg_iobuf_open (secring);
70      gpg_init_packet (pkt);      if (!inp) {
71      while (gpg_parse_packet (inp, pkt) != -1) {          safe_free (pkt);
72          if (pkt->pkttype == PKT_SECRET_KEY) {          return;
73              sk = pkt->pkt.secret_key;      }
74              /* XXX: key IDs of card public keys are wrong! */      gpg_iobuf_ioctl (inp, 3, 1, NULL);
75              _snprintf (keyid, sizeof (keyid)-1, "%08lX",      gpg_init_packet (pkt);
76                         gpg_keyid_from_sk (sk, NULL));      while (gpg_parse_packet (inp, pkt) != -1) {
77              if (kid && strcmp (kid, keyid) != 0)          if (pkt->pkttype == PKT_SECRET_KEY) {
78                  goto next;              sk = pkt->pkt.secret_key;
79              err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);              /* XXX: key IDs of card public keys are wrong! */
80              if (err)              _snprintf (keyid, sizeof (keyid)-1, "%08lX",
81                  goto next;                         gpg_keyid_from_sk (sk, NULL));
82              c->gloflags.is_protected = sk->is_protected;              if (kid && strcmp (kid, keyid) != 0)
83              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;                  goto next;
84              if (c->pubpart != NULL) {                  err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);
85                  c->pubpart->gloflags.is_protected = sk->is_protected;                  if (err)
86                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;                  goto next;
87              }              c->gloflags.is_protected = sk->is_protected;
88          }              c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
89  next:              if (c->pubpart != NULL) {    
90          gpg_free_packet (pkt);                  c->pubpart->gloflags.is_protected = sk->is_protected;    
91          gpg_init_packet (pkt);                  c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
92      }              }
93      safe_free (pkt);          }
94      gpg_iobuf_close (inp);  next:
95  }          gpg_free_packet (pkt);
96            gpg_init_packet (pkt);
97        }
98  /* Merge the information from the keyrings into the key cache structure. */      safe_free (pkt);
99  gpgme_error_t      gpg_iobuf_close (inp);
100  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,  }
101                     const char *pubring, const char *secring)  
102  {  
103      gpgme_error_t err;  /* Merge the information from the keyrings into the key cache structure. */
104      gpgme_key_t key = NULL;  gpgme_error_t
105      gpg_iobuf_t inp;  keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
106      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);                     const char *pubring, const char *secring)
107      struct keycache_s *c;  {
108      const byte *sym_prefs;      gpgme_error_t err;
109      char keyid[16+1], *id = NULL;      gpgme_key_t key = NULL;
110      int key_seen = 0;      gpg_iobuf_t inp;
111      size_t nbytes = 0, nsym =0;      PACKET *pkt = (PACKET*)calloc (1, sizeof * pkt);
112        struct keycache_s *c;
113      if (secring) {      const byte *sym_prefs;
114          parse_secring (ctx, kid, secring);      char keyid[16+1], *id = NULL;
115          if (!pubring) {      int key_seen = 0;
116              safe_free(pkt);      size_t nbytes = 0, nsym =0;
117              return 0;  
118          }      if (secring) {
119      }          parse_secring (ctx, kid, secring);
120      inp = gpg_iobuf_open (pubring);          if (!pubring) {
121      if (!inp) {              safe_free(pkt);
122          safe_free( pkt );              return 0;
123          return gpg_error (GPG_ERR_KEYRING_OPEN);          }
124      }      }
125      gpg_iobuf_ioctl( inp, 3, 1, NULL ); /* disable cache */      inp = gpg_iobuf_open (pubring);
126        if (!inp) {
127      gpg_init_packet( pkt );          safe_free( pkt );
128      while (gpg_parse_packet (inp, pkt) != -1) {          return gpg_error (GPG_ERR_KEYRING_OPEN);
129          if (pkt->pkttype == PKT_PUBLIC_KEY) {      }
130              strcpy (keyid, "");      gpg_iobuf_ioctl( inp, 3, 1, NULL ); /* disable cache */
131              key_seen = 1;  
132          }      gpg_init_packet( pkt );
133        while (gpg_parse_packet (inp, pkt) != -1) {
134          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {          if (pkt->pkttype == PKT_PUBLIC_KEY) {
135              if (pkt->pkt.signature->numrevkeys == 0)              strcpy (keyid, "");
136                  goto next;              key_seen = 1;
137              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);          }
138              if (kid && strcmp (kid, keyid) != 0)  
139                  goto next;          if (pkt->pkttype == PKT_SIGNATURE && pkt->pkt.signature->sig_class == 0x1F) {
140              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              if (pkt->pkt.signature->numrevkeys == 0)
141              if (err)                  goto next;
142                  goto next;              _snprintf (keyid, sizeof keyid -1, "%08X", pkt->pkt.signature->keyid[1]);
143              c->gloflags.has_desig_rev = 1;              if (kid && strcmp (kid, keyid) != 0)
144          }                  goto next;
145          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
146              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,              if (err)
147                                              SIGSUBPKT_PREF_SYM, &nsym);                  goto next;
148              if (sym_prefs == NULL)              c->gloflags.has_desig_rev = 1;
149                  goto next;          }
150              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);          if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
151              if (kid && strcmp (kid, keyid) != 0)              sym_prefs=gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
152                  goto next;                                              SIGSUBPKT_PREF_SYM, &nsym);
153              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);              if (sym_prefs == NULL)
154              if (err)                  goto next;
155                  goto next;              _snprintf (keyid, sizeof keyid - 1, "%08X", pkt->pkt.signature->keyid[1]);
156              else if (nsym > 0) {              if (kid && strcmp (kid, keyid) != 0)
157                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);                  goto next;
158                  if (!c->sym_prefs)              err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
159                      return gpg_error (GPG_ERR_ENOMEM);              if (err)
160                  memcpy (c->sym_prefs, sym_prefs, nsym);                  goto next;
161              }              else if (nsym > 0) {
162          }                  c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
163          if (pkt->pkttype == PKT_USER_ID) {                  if (!c->sym_prefs)
164              if (id)                      return gpg_error (GPG_ERR_ENOMEM);
165                  free (id);                  memcpy (c->sym_prefs, sym_prefs, nsym);
166              id = strdup (pkt->pkt.user_id->name);              }
167              if (!id) {          }
168                  err = gpg_error (GPG_ERR_ENOMEM);          if (pkt->pkttype == PKT_USER_ID) {
169                  goto fail;              if (id)
170              }                  free (id);
171          }              id = strdup (pkt->pkt.user_id->name);
172          if ((pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE)              if (!id) {
173              && pkt->pkt.user_id->attrib_data && key) {                  err = gpg_error (GPG_ERR_ENOMEM);
174              PKT_user_id *id = pkt->pkt.user_id;                  goto fail;
175              c->attrib.used = 1;              }
176              c->attrib.len = id->attrib_len;          }
177              c->attrib.d = (unsigned char*)calloc (1, id->attrib_len + 1);          if ((pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE)
178              if (!c->attrib.d) {              && pkt->pkt.user_id->attrib_data && key) {
179                  err = gpg_error (GPG_ERR_ENOMEM);              PKT_user_id *id = pkt->pkt.user_id;
180                  goto fail;              c->attrib.used = 1;
181              }              c->attrib.len = id->attrib_len;
182              memcpy (c->attrib.d, id->attrib_data, id->attrib_len);              c->attrib.d = (unsigned char*)calloc (1, id->attrib_len + 1);
183              key = NULL;              if (!c->attrib.d) {
184              c = NULL;                  err = gpg_error (GPG_ERR_ENOMEM);
185          }                  goto fail;
186  next:              }
187          gpg_free_packet (pkt);              memcpy (c->attrib.d, id->attrib_data, id->attrib_len);
188          gpg_init_packet(pkt);              key = NULL;
189      }              c = NULL;
190            }
191  fail:  next:
192      safe_free (id);          gpg_free_packet (pkt);
193      safe_free (pkt);          gpg_init_packet(pkt);
194      gpg_iobuf_close (inp);      }
195      return err;  
196  }  fail:
197        safe_free (id);
198        safe_free (pkt);
199  gpgme_error_t      gpg_iobuf_close (inp);
200  gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)      return err;
201  {  }
202      return keycache_prepare2 (ctx, NULL, pubr, secr);  
203  }  
204    gpgme_error_t
205  gpgme_error_t  gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)
206  gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,  {
207                                 const char *pubr, const char *secr)      return keycache_prepare2 (ctx, NULL, pubr, secr);
208  {  }
209      if (!strncmp (keyid, "0x", 2))  
210          keyid += 2;    gpgme_error_t
211      return keycache_prepare2 (ctx, keyid, pubr, secr);  gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,
212  }                                 const char *pubr, const char *secr)
213    {
214        if (!strncmp (keyid, "0x", 2))
215  /* Create new keycache object and return it in @r_ctx.          keyid += 2;  
216     Return value: 0 on success. */      return keycache_prepare2 (ctx, keyid, pubr, secr);
217  gpgme_error_t  }
218  gpg_keycache_new (gpg_keycache_t *r_ctx)  
219  {  
220      gpg_keycache_t ctx;  /* Create new keycache object and return it in @r_ctx.
221           Return value: 0 on success. */
222      if (!r_ctx)  gpgme_error_t
223          return gpg_error (GPG_ERR_INV_ARG);  gpg_keycache_new (gpg_keycache_t *r_ctx)
224      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);  {
225      if (!ctx)      gpg_keycache_t ctx;
226          return gpg_error (GPG_ERR_ENOMEM);      
227      ctx->secret = 0;      if (!r_ctx)
228      ctx->pos = 0;          return gpg_error (GPG_ERR_INV_ARG);
229      *r_ctx = ctx;      ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
230      return 0;      if (!ctx)
231  }          return gpg_error (GPG_ERR_ENOMEM);
232        ctx->secret = 0;
233        ctx->pos = 0;
234  /* Release keycache object @ctx. */      *r_ctx = ctx;
235  void      return 0;
236  gpg_keycache_release (gpg_keycache_t ctx)  }
237  {  
238      struct keycache_s *c, *c2;  
239        /* Release keycache object @ctx. */
240      if (!ctx)  void
241          return;  gpg_keycache_release (gpg_keycache_t ctx)
242    {
243      for (c = ctx->item; c; c = c2) {      struct keycache_s *c, *c2;
244          c2 = c->next;      
245          gpgme_key_release (c->key);      if (!ctx)
246          c->key = NULL;          return;
247          if (c->sym_prefs)  
248              free (c->sym_prefs);      for (c = ctx->item; c; c = c2) {
249          c->sym_prefs = NULL;          c2 = c->next;
250          if (c->attrib.d)          gpgme_key_release (c->key);
251              free (c->attrib.d);          c->key = NULL;
252          c->attrib.d = NULL;          if (c->sym_prefs)
253          if (c->card_type)              free (c->sym_prefs);
254              free (c->card_type);          c->sym_prefs = NULL;
255          free (c);          if (c->attrib.d)
256      }              free (c->attrib.d);
257      if (ctx)          c->attrib.d = NULL;
258          free (ctx);          if (c->card_type)
259  }              free (c->card_type);
260            free (c);
261        }
262  /* Set (progress) callback for the given keycache object.      if (ctx)
263     @ctx the keycache          free (ctx);
264     @cb  the callback function  }
265     @cb_value1 opaque value which is passed to the callback.  
266     @cb_value2 see @cb_value1. */  
267  void  /* Set (progress) callback for the given keycache object.
268  gpg_keycache_set_cb (gpg_keycache_t ctx,     @ctx the keycache
269                       void (*cb)(void *, const char *, int, int, int),     @cb  the callback function
270                       void * cb_value1, int cb_value2)     @cb_value1 opaque value which is passed to the callback.
271  {     @cb_value2 see @cb_value1. */
272      if (!ctx)  void
273          return;  gpg_keycache_set_cb (gpg_keycache_t ctx,
274      ctx->cb = cb;                       void (*cb)(void *, const char *, int, int, int),
275      ctx->cb_value = cb_value1;                       void * cb_value1, int cb_value2)
276      ctx->cb_value2 = cb_value2;  {
277  }      if (!ctx)
278            return;
279        ctx->cb = cb;
280  /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.      ctx->cb_value = cb_value1;
281     Return value: 0 on success. */      ctx->cb_value2 = cb_value2;
282  gpgme_error_t  }
283  gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)  
284  {  
285      struct keycache_s * c, * n1;  /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.
286           Return value: 0 on success. */
287      if (!ctx)  gpgme_error_t
288          return gpg_error (GPG_ERR_INV_ARG);  gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
289        {
290      c = (struct keycache_s*)calloc (1, sizeof *c);      struct keycache_s * c, * n1;
291      if (!c)      
292          return gpg_error (GPG_ERR_ENOMEM);      if (!ctx)
293      c->gloflags.is_protected = 1; /*default: assume protection. */          return gpg_error (GPG_ERR_INV_ARG);
294      c->key = key;      
295      if (!ctx->item)      c = (struct keycache_s*)calloc (1, sizeof *c);
296          ctx->item = c;      if (!c)
297      else {          return gpg_error (GPG_ERR_ENOMEM);
298          for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)      c->gloflags.is_protected = 1; /*default: assume protection. */
299              ;      c->key = key;
300          n1->next = c;      if (!ctx->item)
301      }          ctx->item = c;
302      if (opaque)      else {
303          *opaque = c;          for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)
304      return 0;              ;
305  }          n1->next = c;
306        }
307        if (opaque)
308            *opaque = c;
309  #define has_keyid_len(pattern) (\      return 0;
310      strlen (pattern) == 8  || strlen (pattern) == 10 || \  }
311      strlen (pattern) == 16 || strlen (pattern) == 18)  
312    
313    
314  gpgme_error_t  #define has_keyid_len(pattern) (\
315  gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,      strlen (pattern) == 8  || strlen (pattern) == 10 || \
316                          gpgme_key_t *r_key, struct keycache_s **r_item)      strlen (pattern) == 16 || strlen (pattern) == 18)
317  {  
318      struct keycache_s *c;  
319      gpgme_subkey_t s;  gpgme_error_t
320      gpgme_user_id_t u;  gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,
321      gpgme_key_t key;                          gpgme_key_t *r_key, struct keycache_s **r_item)
322      const char *kid;  {
323            struct keycache_s *c;
324      if (!ctx || !r_key)      gpgme_subkey_t s;
325          return gpg_error (GPG_ERR_INV_ARG);      gpgme_user_id_t u;
326            gpgme_key_t key;
327      if (strstr (pattern, "0x"))      const char *kid;
328          pattern += 2;      
329        if (!ctx || !r_key)
330      /* Sometimes a subkey has no valid fpr. As a kludge we convert v4          return gpg_error (GPG_ERR_INV_ARG);
331         fingerprints into the 64-bit keyid. */      
332      if (strlen (pattern) == 40 && isxdigit (*pattern))      if (strstr (pattern, "0x"))
333          pattern += 32;          pattern += 2;
334    
335      /* XXX: this code is very slow, revamp it and use hash tables whenever      /* Sometimes a subkey has no valid fpr. As a kludge we convert v4
336              it is possible. */         fingerprints into the 64-bit keyid. */
337      for (c = ctx->item; c; c = c->next) {      if (strlen (pattern) == 40 && isxdigit (*pattern))
338          key = c->key;          pattern += 32;
339          assert (key->_refs >= 1);  
340          for (s = key->subkeys; s; s = s->next) {      /* XXX: this code is very slow, revamp it and use hash tables whenever
341              for (u = key->uids; u; u = u->next) {              it is possible. */
342                  if (u->name && stristr (u->name, pattern)) {      for (c = ctx->item; c; c = c->next) {
343                      if (r_item)          key = c->key;
344                          *r_item = c;          assert (key->_refs >= 1);
345                      *r_key = flags? c->pubpart->key : c->key;          for (s = key->subkeys; s; s = s->next) {
346                      return 0;              for (u = key->uids; u; u = u->next) {
347                  }                  if (u->name && stristr (u->name, pattern)) {
348              }                      if (r_item)
349              if (has_keyid_len (pattern))                          *r_item = c;
350                  kid = s->keyid;                      *r_key = flags? c->pubpart->key : c->key;
351              else                      return 0;
352                  kid = s->fpr;                  }
353              if (kid && stristr (kid, pattern)) {              }
354                  if (r_item)              if (has_keyid_len (pattern))
355                      *r_item = c;                  kid = s->keyid;
356                  *r_key = flags? c->pubpart->key : c->key;              else
357                  return 0;                  kid = s->fpr;
358              }              if (kid && stristr (kid, pattern)) {
359          }                  if (r_item)
360      }                      *r_item = c;
361      *r_key = NULL;                  *r_key = flags? c->pubpart->key : c->key;
362      return gpg_error (GPG_ERR_INTERNAL);                  return 0;
363  } /* keycache_find_key */              }
364            }
365        }
366  gpgme_error_t      *r_key = NULL;
367  gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,      return gpg_error (GPG_ERR_INTERNAL);
368                         int flags, gpgme_key_t *r_key)  } /* keycache_find_key */
369  {  
370      return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);  
371  }  gpgme_error_t
372    gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,
373                           int flags, gpgme_key_t *r_key)
374  gpgme_error_t  {
375  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,      return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);
376                           void *opaque, const char *keyid)  }
377  {  
378      struct keycache_s *c = NULL, *c_new=NULL;  
379      gpgme_key_t key=NULL, fndkey=NULL;  gpgme_error_t
380      gpgme_error_t err;  gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
381      gpgme_ctx_t gctx;                           void *opaque, const char *keyid)
382      gpg_keycache_t pub = (gpg_keycache_t)opaque;  {
383        struct keycache_s *c = NULL, *c_new=NULL;
384      err = gpgme_new (&gctx);      gpgme_key_t key=NULL, fndkey=NULL;
385      if (err)      gpgme_error_t err;
386          return err;      gpgme_ctx_t gctx;
387      err = gpgme_get_key (gctx, keyid, &key, is_sec);      gpg_keycache_t pub = (gpg_keycache_t)opaque;
388      gpgme_release (gctx);  
389      if (err)      err = gpgme_new (&gctx);
390          return err;      if (err)
391      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);          return err;
392      if (!err && c != NULL) {      err = gpgme_get_key (gctx, keyid, &key, is_sec);
393          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);      gpgme_release (gctx);
394          gpgme_key_release (fndkey);      if (err)
395          c->key = key;          return err;
396          c->flags = 0;      err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
397          if (is_sec && pub != NULL &&      if (!err && c != NULL) {
398              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {          log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
399              log_debug ("keycache update: set public part %p\r\n", fndkey);          gpgme_key_release (fndkey);
400              c->pubpart->key = fndkey;          c->key = key;
401          }          c->flags = 0;
402      }          if (is_sec && pub != NULL &&
403      else {              !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
404          log_debug ("keycache add: sync public part\r\n");              log_debug ("keycache update: set public part %p\r\n", fndkey);
405          if (is_sec)              c->pubpart->key = fndkey;
406              gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);          }
407          gpg_keycache_add_key (ctx, key, (void **)&c);      }
408          if (c != NULL && is_sec) {      else {
409              log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);          log_debug ("keycache add: sync public part\r\n");
410              c->pubpart = c_new;          if (is_sec)
411              if (c_new != NULL) {              gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);
412                  c->pubpart->key = fndkey;          gpg_keycache_add_key (ctx, key, (void **)&c);
413                  c->gloflags.is_protected = c_new->gloflags.is_protected;          if (c != NULL && is_sec) {
414                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;              log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);
415              }              c->pubpart = c_new;
416          }              if (c_new != NULL) {
417      }                  c->pubpart->key = fndkey;
418      return 0;                  c->gloflags.is_protected = c_new->gloflags.is_protected;
419  }                  c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
420                }
421            }
422  /* Delete a key from the cache @ctx with the pattern @pattern.      }
423     Return value: 0 on success. */      return 0;
424  gpgme_error_t  }
425  gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)  
426  {  
427      struct keycache_s *itm = NULL, *c;  /* Delete a key from the cache @ctx with the pattern @pattern.
428      gpgme_key_t key;     Return value: 0 on success. */
429      gpgme_error_t rc;  gpgme_error_t
430    gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)
431      if (!ctx)  {
432          return gpg_error (GPG_ERR_INV_ARG);      struct keycache_s *itm = NULL, *c;
433      rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);      gpgme_key_t key;
434      if (rc)      gpgme_error_t rc;
435          return rc;  
436            if (!ctx)
437      c = ctx->item;          return gpg_error (GPG_ERR_INV_ARG);
438      if (c->next == NULL) {      rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
439          gpgme_key_release (itm->key);      if (rc)
440          if (itm)          return rc;
441              free (itm);      
442          ctx->item = NULL;      c = ctx->item;
443      }      if (c->next == NULL) {
444      else {          gpgme_key_release (itm->key);
445          while (c && c->next != itm)          if (itm)
446              c = c->next;              free (itm);
447          c->next = c->next->next;          ctx->item = NULL;
448          gpgme_key_release (itm->key);      }
449          if (itm)      else {
450              free (itm);          while (c && c->next != itm)
451      }              c = c->next;
452      return 0;          c->next = c->next->next;
453  }          gpgme_key_release (itm->key);
454            if (itm)
455                free (itm);
456  /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring      }
457     will be added to the cache. @secret is 1 if the source is the secret keyring.      return 0;
458     Return value: 0 on success. */  }
459  gpgme_error_t  
460  gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)  
461  {  /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring
462      gpgme_error_t err;     will be added to the cache. @secret is 1 if the source is the secret keyring.
463      gpgme_ctx_t c;     Return value: 0 on success. */
464      gpgme_key_t key;  gpgme_error_t
465      int count = 0;  gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)
466        {
467      if (!ctx)      gpgme_error_t err;
468          return gpg_error (GPG_ERR_INV_ARG);      gpgme_ctx_t c;
469            gpgme_key_t key;
470      err = gpgme_new (&c);      int count = 0;
471      if (err)      
472          return err;      if (!ctx)
473            return gpg_error (GPG_ERR_INV_ARG);
474      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);      
475      err = gpgme_op_keylist_start (c, pattern, secret);      err = gpgme_new (&c);
476      while(!err) {      if (err)
477          err = gpgme_op_keylist_next (c, &key);          return err;
478          if (!err)  
479              err = gpg_keycache_add_key (ctx, key, NULL);      gpgme_set_keylist_mode  (c, GPGME_KEYLIST_MODE_SIGS);
480          if (ctx->cb)      err = gpgme_op_keylist_start (c, pattern, secret);
481              ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,      while(!err) {
482                       count++, ctx->cb_value2);          err = gpgme_op_keylist_next (c, &key);
483      }          if (!err)
484      if (gpgme_err_code (err) == GPG_ERR_EOF)              err = gpg_keycache_add_key (ctx, key, NULL);
485          err = gpg_error (GPG_ERR_NO_ERROR);          if (ctx->cb)
486      /* XXX: make sure the progress dialog is closed. */              ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,
487      gpgme_op_keylist_end (c);                       count++, ctx->cb_value2);
488      gpgme_release (c);      }
489      return err;      if (gpgme_err_code (err) == GPG_ERR_EOF)
490  }          err = gpg_error (GPG_ERR_NO_ERROR);
491        /* XXX: make sure the progress dialog is closed. */
492        gpgme_op_keylist_end (c);
493  /* XXX: kludge to see if the key is stored on a card. */      gpgme_release (c);
494  static int      return err;
495  key_divert_to_card (gpgme_key_t key)  }
496  {  
497      gpgme_subkey_t k;  
498      int n=0, n_alg=0, can_auth = 0;  /* XXX: kludge to see if the key is stored on a card. */
499    static int
500      for (k = key->subkeys; k; k = k->next) {  key_divert_to_card (gpgme_key_t key)
501          n++;  {
502          if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)      gpgme_subkey_t k;
503              n_alg++;      int n=0, n_alg=0, can_auth = 0;
504          if (k->can_authenticate)  
505              can_auth++;      for (k = key->subkeys; k; k = k->next) {
506      }          n++;
507      if (n == 3 && n_alg == 3 && can_auth == 1)          if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)
508          return 1;              n_alg++;
509      return 0;          if (k->can_authenticate)
510  }              can_auth++;
511        }
512        if (n == 3 && n_alg == 3 && can_auth == 1)
513  gpgme_error_t          return 1;
514  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)      return 0;
515  {  }
516      struct keycache_s *c, *c_sec;  
517      gpgme_key_t key;  
518    gpgme_error_t
519      if (!pub || !sec)  gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
520          return gpg_error (GPG_ERR_INV_ARG);  {
521            struct keycache_s *c, *c_sec;
522      for (c=sec->item; c; c=c->next) {        gpgme_key_t key;
523          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {  
524              c_sec->gloflags.is_protected = c->gloflags.is_protected;      if (!pub || !sec)
525              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;          return gpg_error (GPG_ERR_INV_ARG);
526              if (!c->gloflags.divert_to_card)      
527                  c->gloflags.divert_to_card = key_divert_to_card (key);      for (c=sec->item; c; c=c->next) {  
528              c->pubpart = c_sec;          if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
529              c->pubpart->key = key;              c_sec->gloflags.is_protected = c->gloflags.is_protected;
530          }              c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
531      }              if (!c->gloflags.divert_to_card)
532      return 0;                  c->gloflags.divert_to_card = key_divert_to_card (key);
533  }              c->pubpart = c_sec;
534                c->pubpart->key = key;
535            }
536  /* Rewind the given cache @ctx to the begin. */      }
537  void      return 0;
538  gpg_keycache_rewind (gpg_keycache_t ctx)  }
539  {  
540      if (ctx)  
541          ctx->pos = 0;  /* Rewind the given cache @ctx to the begin. */
542  }  void
543    gpg_keycache_rewind (gpg_keycache_t ctx)
544    {
545        if (ctx)
546  /* Return the number of elements in the cache @ctx. */          ctx->pos = 0;
547  int  }
548  gpg_keycache_get_size (gpg_keycache_t ctx)  
549  {  
550      struct keycache_s *c;  
551      int count = 0;  /* Return the number of elements in the cache @ctx. */
552        int
553      if (!ctx)  gpg_keycache_get_size (gpg_keycache_t ctx)
554          return 0;  {
555      for (c = ctx->item; c; c = c->next)      struct keycache_s *c;
556          count++;      int count = 0;
557      return count;      
558  }      if (!ctx)
559            return 0;
560        for (c = ctx->item; c; c = c->next)
561  static gpgme_error_t          count++;
562  keycache_next_key (gpg_keycache_t ctx, int flags,      return count;
563                     struct keycache_s **c, gpgme_key_t *r_key)  }
564  {        
565      if (!ctx || !r_key)  
566          return gpg_error (GPG_ERR_INV_ARG);  static gpgme_error_t
567    keycache_next_key (gpg_keycache_t ctx, int flags,
568      if (!ctx->pos)                     struct keycache_s **c, gpgme_key_t *r_key)
569          ctx->tmp = ctx->item;  {      
570            if (!ctx || !r_key)
571      if (!ctx->tmp || !ctx->tmp->key) {          return gpg_error (GPG_ERR_INV_ARG);
572          ctx->pos = 0;  
573          *r_key = NULL;      if (!ctx->pos)
574          return gpg_error (GPG_ERR_EOF);          ctx->tmp = ctx->item;
575      }      
576            if (!ctx->tmp || !ctx->tmp->key) {
577      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;          ctx->pos = 0;
578      *c = ctx->tmp = ctx->tmp->next;          *r_key = NULL;
579      ctx->pos++;          return gpg_error (GPG_ERR_EOF);
580        }
581      return 0;      
582  }      *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
583        *c = ctx->tmp = ctx->tmp->next;
584        ctx->pos++;
585  /* Return the next key from the cache @ctx. The key will be returned  
586     in @r_key. @flags can contain additional flags.      return 0;
587     Return value: 0 on success. */  }
588  gpgme_error_t  
589  gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)  
590  {  /* Return the next key from the cache @ctx. The key will be returned
591      struct keycache_s *c=NULL;     in @r_key. @flags can contain additional flags.
592      gpgme_error_t err = 0;     Return value: 0 on success. */
593    gpgme_error_t
594      err = keycache_next_key (ctx, flags, &c, r_key);  gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
595      return err;  {
596  }      struct keycache_s *c=NULL;
597        gpgme_error_t err = 0;
598    
599        err = keycache_next_key (ctx, flags, &c, r_key);
600        return err;
601    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26