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

Legend:
Removed from v.28  
changed lines
  Added in v.65

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26