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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26