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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26