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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26