/[winpt]/trunk/Src/wptKeyCache.cpp
ViewVC logotype

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 150 - (hide annotations)
Wed Jan 18 11:52:45 2006 UTC (19 years, 1 month ago) by twoaday
File size: 18908 byte(s)
2006-01-18  Timo Schulz  <ts@g10code.com>
 
        * wptListview.cpp (listview_del_sel_items): Fixed index
        calculation. This fixed a lot of problems with the KM listview
        update.
        (listview_del_all): Renamed to...
        (listview_del_all_items): ..this. Changed all callers.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Just refresh
        list when file import contained new/updated keys.
        * wptKeyManager.cpp (km_file_import): Indicate if the
        import contained any new/update keys.
        * wptClipImportDlg.cpp (print_import_status): Just mark
        keys which actually changed.
         


1 werner 36 /* wptKeyCache.cpp- Caching for the pub- and the secring
2 twoaday 133 * Copyright (C) 2001-2006 Timo Schulz
3 werner 36 *
4     * This file is part of MyGPGME.
5     *
6     * 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
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * MyGPGME is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19     */
20 twoaday 121
21 werner 42 #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25 werner 36 #include <windows.h>
26     #include <stdio.h>
27     #include <string.h>
28     #include <malloc.h>
29     #include <ctype.h>
30     #include <assert.h>
31 twoaday 121 #include <gpgme.h>
32 werner 36
33     #include "wptKeyCache.h"
34     #include "openpgp.h"
35     #include "wptNLS.h"
36     #include "wptErrors.h"
37     #include "wptW32API.h"
38 twoaday 133 #include "wptGPG.h"
39 werner 36
40    
41 twoaday 133 /* Attribute list which holds the image data. */
42     struct attr_list_s {
43     struct attr_list_s *next;
44     char *fpr; /* fingerprint of the key */
45     unsigned char *d; /* actual JPEG data. */
46     unsigned long octets; /* length of the data. */
47     unsigned int flags; /* status of the attribute. */
48     };
49     typedef struct attr_list_s *attr_list_t;
50    
51    
52     void
53     free_attr_list (attr_list_t ctx)
54 werner 36 {
55 twoaday 133 attr_list_t n;
56     while (ctx) {
57     n = ctx->next;
58     free (ctx->fpr);
59     free (ctx->d);
60     ctx = n;
61     }
62     }
63    
64     /* Parse the attribute list in @fp and store it into @ctx.
65     Return value: number of parsed items. */
66     int
67     parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
68     {
69     attr_list_t c, t;
70     char buf[512], *p, *buffer;
71     int pos, n=0;
72    
73     *ctx = NULL;
74     while (fgets (buf, 511, fp)) {
75     if (strstr (buf, "\r\n"))
76     buf[strlen (buf)-2]=0;
77     if (strstr (buf, "\n"))
78     buf[strlen (buf)-1]=0;
79     if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
80     continue;
81     buffer = buf+9+10;
82     pos = 0;
83     c = (attr_list_t)calloc (1, sizeof *c);
84     p = strtok (buffer, " ");
85     while (p != NULL) {
86     switch (pos) {
87     case 0:
88     c->fpr = strdup (p);
89     break;
90    
91     case 1:
92     c->octets = strtoul (p, NULL, 10);
93     break;
94    
95     case 7:
96     c->flags = strtoul (p, NULL, 10);
97     break;
98    
99     default:
100     break;
101     }
102     pos++;
103     p = strtok (NULL, " ");
104     }
105     /*printf ("id=%s octets=%d flags=%d\n", c->fpr, c->octets, c->flags);*/
106     if (!*ctx)
107     *ctx = c;
108     else {
109     for (t = *ctx; t->next; t=t->next)
110     ;
111     t->next = c;
112     }
113     c->d = (unsigned char*)malloc (c->octets);
114     memcpy (c->d, data, c->octets);
115     data += c->octets;
116     datlen -= c->octets;
117     n++;
118     }
119     /*assert (datlen == 0); */
120     return n;
121     }
122 werner 36
123 twoaday 133
124     static int
125     parse_attr_data (const char *keyid, attr_list_t *list)
126     {
127     gpgme_error_t err;
128     FILE *tmp;
129     char *status;
130     BYTE *data;
131     DWORD ndata;
132    
133     err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
134     if (err)
135     return err;
136    
137     if (ndata > 0) {
138     tmp = tmpfile ();
139     fwrite (status, 1, strlen (status), tmp);
140     fflush (tmp);
141     rewind (tmp);
142    
143     ndata = parse_attr_list (tmp, data, ndata, list);
144     fclose (tmp);
145 werner 36 }
146 twoaday 133 else
147     *list = NULL;
148    
149     safe_free (status);
150     safe_free (data);
151     return ndata;
152 werner 36 }
153    
154 twoaday 121
155 werner 36 /* Parse the secret keyring and retrieve some additional information
156     for each key which was found. */
157     static void
158     parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
159     {
160 twoaday 133 PACKET *pkt;
161 werner 36 PKT_secret_key *sk;
162     gpg_iobuf_t inp;
163     gpgme_error_t err;
164     gpgme_key_t key;
165     struct keycache_s *c=NULL;
166     char keyid[16+1];
167    
168     inp = gpg_iobuf_open (secring);
169 twoaday 133 if (!inp)
170 werner 36 return;
171 twoaday 133
172 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL);
173 twoaday 133 pkt = (PACKET*)calloc (1, sizeof *pkt);
174 werner 36 gpg_init_packet (pkt);
175     while (gpg_parse_packet (inp, pkt) != -1) {
176     if (pkt->pkttype == PKT_SECRET_KEY) {
177     sk = pkt->pkt.secret_key;
178     /* XXX: key IDs of card public keys are wrong! */
179     _snprintf (keyid, sizeof (keyid)-1, "%08lX",
180     gpg_keyid_from_sk (sk, NULL));
181     if (kid && strcmp (kid, keyid) != 0)
182     goto next;
183     err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);
184     if (err)
185     goto next;
186     c->gloflags.is_protected = sk->is_protected;
187     c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
188     if (c->pubpart != NULL) {
189     c->pubpart->gloflags.is_protected = sk->is_protected;
190     c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
191     }
192     }
193     next:
194     gpg_free_packet (pkt);
195     gpg_init_packet (pkt);
196     }
197     safe_free (pkt);
198     gpg_iobuf_close (inp);
199     }
200    
201    
202 twoaday 133 /* Update the photo image of a single key with the fingerprint
203     @fpr. The @dat struct contains the new item data. */
204     static gpgme_error_t
205     keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
206     {
207     struct keycache_s *fnd = NULL;
208     gpgme_key_t key;
209    
210     gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
211     if (!fnd)
212     return gpg_error (GPG_ERR_NOT_FOUND);
213     safe_free (fnd->attrib.d);
214     fnd->attrib.flags = dat->flags;
215     fnd->attrib.len = dat->octets;
216     fnd->attrib.d = (unsigned char*)malloc (dat->octets);
217     memcpy (fnd->attrib.d, dat->d, dat->octets);
218     return 0;
219     }
220    
221    
222     /* Update all photo images in the cache. */
223     static gpgme_error_t
224     keycache_update_photos (gpg_keycache_t ctx)
225     {
226     attr_list_t list=NULL, n;
227     DWORD ndata;
228    
229     ndata = parse_attr_data (NULL, &list);
230     if (ndata < 1) {
231     free_attr_list (list);
232     return 0;
233     }
234    
235     for (n=list; n; n=n->next)
236     keycache_update_photo (ctx, n->fpr, n);
237     free_attr_list (list);
238     return 0;
239     }
240    
241    
242 werner 36 /* Merge the information from the keyrings into the key cache structure. */
243     gpgme_error_t
244     keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
245     const char *pubring, const char *secring)
246     {
247 twoaday 69 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
248 werner 36 gpgme_key_t key = NULL;
249     gpg_iobuf_t inp;
250 twoaday 133 PACKET *pkt;
251 werner 36 struct keycache_s *c;
252     const byte *sym_prefs;
253 twoaday 133 char keyid[16+1];
254 werner 36 int key_seen = 0;
255 twoaday 65 size_t nsym =0;
256 werner 36
257     if (secring) {
258     parse_secring (ctx, kid, secring);
259 twoaday 133 if (!pubring)
260 werner 36 return 0;
261     }
262     inp = gpg_iobuf_open (pubring);
263 twoaday 133 if (!inp)
264 werner 36 return gpg_error (GPG_ERR_KEYRING_OPEN);
265 twoaday 123 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
266 werner 36
267 twoaday 133 pkt = (PACKET*)calloc (1, sizeof * pkt);
268 twoaday 123 gpg_init_packet (pkt);
269 werner 36 while (gpg_parse_packet (inp, pkt) != -1) {
270     if (pkt->pkttype == PKT_PUBLIC_KEY) {
271     strcpy (keyid, "");
272     key_seen = 1;
273     }
274    
275 twoaday 133 if (pkt->pkttype == PKT_SIGNATURE &&
276     pkt->pkt.signature->sig_class == 0x1F) {
277 werner 36 if (pkt->pkt.signature->numrevkeys == 0)
278     goto next;
279 twoaday 133 _snprintf (keyid, sizeof (keyid) -1, "%08X",
280     pkt->pkt.signature->keyid[1]);
281 werner 36 if (kid && strcmp (kid, keyid) != 0)
282     goto next;
283     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
284     if (err)
285     goto next;
286     c->gloflags.has_desig_rev = 1;
287     }
288     if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
289 twoaday 133 sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
290     SIGSUBPKT_PREF_SYM, &nsym);
291     if (!sym_prefs)
292 werner 36 goto next;
293 twoaday 133 _snprintf (keyid, sizeof (keyid) - 1, "%08X",
294     pkt->pkt.signature->keyid[1]);
295 werner 36 if (kid && strcmp (kid, keyid) != 0)
296     goto next;
297     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
298     if (err)
299     goto next;
300     else if (nsym > 0) {
301     c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
302     if (!c->sym_prefs)
303     return gpg_error (GPG_ERR_ENOMEM);
304     memcpy (c->sym_prefs, sym_prefs, nsym);
305     }
306     }
307     next:
308     gpg_free_packet (pkt);
309     gpg_init_packet(pkt);
310     }
311    
312     safe_free (pkt);
313     gpg_iobuf_close (inp);
314     return err;
315     }
316    
317    
318     gpgme_error_t
319     gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)
320     {
321     return keycache_prepare2 (ctx, NULL, pubr, secr);
322     }
323    
324     gpgme_error_t
325     gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,
326     const char *pubr, const char *secr)
327     {
328     if (!strncmp (keyid, "0x", 2))
329     keyid += 2;
330     return keycache_prepare2 (ctx, keyid, pubr, secr);
331     }
332    
333    
334     /* Create new keycache object and return it in @r_ctx.
335     Return value: 0 on success. */
336     gpgme_error_t
337     gpg_keycache_new (gpg_keycache_t *r_ctx)
338     {
339     gpg_keycache_t ctx;
340    
341     if (!r_ctx)
342     return gpg_error (GPG_ERR_INV_ARG);
343     ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
344     if (!ctx)
345     return gpg_error (GPG_ERR_ENOMEM);
346     ctx->secret = 0;
347     ctx->pos = 0;
348     *r_ctx = ctx;
349     return 0;
350     }
351    
352    
353     /* Release keycache object @ctx. */
354     void
355     gpg_keycache_release (gpg_keycache_t ctx)
356     {
357     struct keycache_s *c, *c2;
358    
359     if (!ctx)
360     return;
361    
362     for (c = ctx->item; c; c = c2) {
363     c2 = c->next;
364     gpgme_key_release (c->key);
365     c->key = NULL;
366 twoaday 133 safe_free (c->sym_prefs);
367     safe_free (c->attrib.d);
368     safe_free (c->card_type);
369 werner 36 free (c);
370     }
371 twoaday 133 safe_free (ctx);
372 werner 36 }
373    
374    
375     /* Set (progress) callback for the given keycache object.
376     @ctx the keycache
377     @cb the callback function
378     @cb_value1 opaque value which is passed to the callback.
379     @cb_value2 see @cb_value1. */
380     void
381     gpg_keycache_set_cb (gpg_keycache_t ctx,
382     void (*cb)(void *, const char *, int, int, int),
383     void * cb_value1, int cb_value2)
384     {
385     if (!ctx)
386     return;
387     ctx->cb = cb;
388     ctx->cb_value = cb_value1;
389     ctx->cb_value2 = cb_value2;
390     }
391    
392    
393     /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.
394     Return value: 0 on success. */
395     gpgme_error_t
396     gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
397     {
398 twoaday 41 struct keycache_s *c, *n1;
399 werner 36
400     if (!ctx)
401     return gpg_error (GPG_ERR_INV_ARG);
402    
403     c = (struct keycache_s*)calloc (1, sizeof *c);
404     if (!c)
405     return gpg_error (GPG_ERR_ENOMEM);
406     c->gloflags.is_protected = 1; /*default: assume protection. */
407     c->key = key;
408     if (!ctx->item)
409     ctx->item = c;
410     else {
411     for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)
412     ;
413     n1->next = c;
414     }
415     if (opaque)
416     *opaque = c;
417     return 0;
418     }
419    
420    
421    
422     #define has_keyid_len(pattern) (\
423     strlen (pattern) == 8 || strlen (pattern) == 10 || \
424     strlen (pattern) == 16 || strlen (pattern) == 18)
425    
426    
427     gpgme_error_t
428     gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,
429     gpgme_key_t *r_key, struct keycache_s **r_item)
430     {
431     struct keycache_s *c;
432     gpgme_subkey_t s;
433     gpgme_user_id_t u;
434     gpgme_key_t key;
435     const char *kid;
436    
437     if (!ctx || !r_key)
438     return gpg_error (GPG_ERR_INV_ARG);
439    
440     if (strstr (pattern, "0x"))
441     pattern += 2;
442    
443     /* Sometimes a subkey has no valid fpr. As a kludge we convert v4
444     fingerprints into the 64-bit keyid. */
445     if (strlen (pattern) == 40 && isxdigit (*pattern))
446     pattern += 32;
447    
448     /* XXX: this code is very slow, revamp it and use hash tables whenever
449     it is possible. */
450     for (c = ctx->item; c; c = c->next) {
451     key = c->key;
452     assert (key->_refs >= 1);
453     for (s = key->subkeys; s; s = s->next) {
454     for (u = key->uids; u; u = u->next) {
455     if (u->name && stristr (u->name, pattern)) {
456     if (r_item)
457     *r_item = c;
458     *r_key = flags? c->pubpart->key : c->key;
459     return 0;
460     }
461     }
462     if (has_keyid_len (pattern))
463     kid = s->keyid;
464     else
465     kid = s->fpr;
466     if (kid && stristr (kid, pattern)) {
467     if (r_item)
468     *r_item = c;
469     *r_key = flags? c->pubpart->key : c->key;
470     return 0;
471     }
472     }
473     }
474     *r_key = NULL;
475     return gpg_error (GPG_ERR_INTERNAL);
476 twoaday 133 }
477 werner 36
478    
479     gpgme_error_t
480     gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,
481     int flags, gpgme_key_t *r_key)
482     {
483     return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);
484     }
485    
486    
487 twoaday 133 /* Reload a photo image of a single key with the keyid @keyid.
488     Return value: 0 on success. */
489     static gpgme_error_t
490     keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
491     {
492     attr_list_t list;
493    
494     if (parse_attr_data (keyid, &list) < 1) {
495     free_attr_list (list);
496     return 0;
497     }
498     keycache_update_photo (ctx, list->fpr, list);
499     free_attr_list (list);
500     return 0;
501     }
502    
503    
504 twoaday 147 /* Return the next key which was updated. Before it is
505     returned the update flag is cleared.
506 twoaday 150 @r_status is 1 for a new key and 2 for an updated key.
507 twoaday 147 Return value: 0 on success. */
508 werner 36 gpgme_error_t
509 twoaday 147 gpg_keycache_next_updated_key (gpg_keycache_t ctx,
510 twoaday 150 struct keycache_s **r_obj,
511     int *r_status)
512 twoaday 147 {
513     struct keycache_s *c;
514    
515     for (c = ctx->item; c; c = c->next) {
516 twoaday 150 if (c->flags != 0) {
517     *r_status = c->flags;
518 twoaday 147 c->flags = 0;
519     *r_obj = c;
520     return 0;
521     }
522     }
523     return gpg_error (GPG_ERR_NOT_FOUND);
524     }
525    
526    
527    
528     gpgme_error_t
529 werner 36 gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
530     void *opaque, const char *keyid)
531     {
532     struct keycache_s *c = NULL, *c_new=NULL;
533     gpgme_key_t key=NULL, fndkey=NULL;
534     gpgme_error_t err;
535     gpgme_ctx_t gctx;
536     gpg_keycache_t pub = (gpg_keycache_t)opaque;
537    
538     err = gpgme_new (&gctx);
539     if (err)
540     return err;
541 twoaday 150 gpgme_set_keylist_mode (gctx, GPGME_KEYLIST_MODE_SIGS);
542 werner 36 err = gpgme_get_key (gctx, keyid, &key, is_sec);
543     gpgme_release (gctx);
544     if (err)
545     return err;
546     err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
547     if (!err && c != NULL) {
548     log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
549     gpgme_key_release (fndkey);
550     c->key = key;
551 twoaday 150 c->flags = KC_FLAG_UPD;
552 werner 36 if (is_sec && pub != NULL &&
553     !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
554     log_debug ("keycache update: set public part %p\r\n", fndkey);
555     c->pubpart->key = fndkey;
556     }
557 twoaday 133 /* XXX: this is also called for keys without a photo-id. */
558     keycache_reload_photo (ctx, keyid);
559 werner 36 }
560     else {
561     log_debug ("keycache add: sync public part\r\n");
562     if (is_sec)
563     gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);
564     gpg_keycache_add_key (ctx, key, (void **)&c);
565     if (c != NULL && is_sec) {
566     log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);
567     c->pubpart = c_new;
568     if (c_new != NULL) {
569     c->pubpart->key = fndkey;
570     c->gloflags.is_protected = c_new->gloflags.is_protected;
571     c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
572     }
573     }
574 twoaday 147 if (c)
575 twoaday 150 c->flags = KC_FLAG_ADD;
576 werner 36 }
577     return 0;
578     }
579    
580    
581     /* Delete a key from the cache @ctx with the pattern @pattern.
582     Return value: 0 on success. */
583     gpgme_error_t
584     gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)
585     {
586     struct keycache_s *itm = NULL, *c;
587     gpgme_key_t key;
588     gpgme_error_t rc;
589    
590     if (!ctx)
591     return gpg_error (GPG_ERR_INV_ARG);
592     rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
593     if (rc)
594     return rc;
595    
596     c = ctx->item;
597     if (c->next == NULL) {
598     gpgme_key_release (itm->key);
599     if (itm)
600     free (itm);
601     ctx->item = NULL;
602     }
603     else {
604     while (c && c->next != itm)
605     c = c->next;
606     c->next = c->next->next;
607     gpgme_key_release (itm->key);
608     if (itm)
609     free (itm);
610     }
611     return 0;
612     }
613    
614    
615     /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring
616     will be added to the cache. @secret is 1 if the source is the secret keyring.
617     Return value: 0 on success. */
618     gpgme_error_t
619     gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)
620     {
621     gpgme_error_t err;
622     gpgme_ctx_t c;
623     gpgme_key_t key;
624     int count = 0;
625    
626     if (!ctx)
627     return gpg_error (GPG_ERR_INV_ARG);
628    
629     err = gpgme_new (&c);
630     if (err)
631     return err;
632    
633     gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS);
634     err = gpgme_op_keylist_start (c, pattern, secret);
635     while(!err) {
636     err = gpgme_op_keylist_next (c, &key);
637     if (!err)
638     err = gpg_keycache_add_key (ctx, key, NULL);
639     if (ctx->cb)
640     ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,
641     count++, ctx->cb_value2);
642     }
643     if (gpgme_err_code (err) == GPG_ERR_EOF)
644     err = gpg_error (GPG_ERR_NO_ERROR);
645 twoaday 133 keycache_update_photos (ctx);
646 werner 36 /* XXX: make sure the progress dialog is closed. */
647     gpgme_op_keylist_end (c);
648     gpgme_release (c);
649     return err;
650     }
651    
652    
653     /* XXX: kludge to see if the key is stored on a card. */
654     static int
655     key_divert_to_card (gpgme_key_t key)
656     {
657     gpgme_subkey_t k;
658     int n=0, n_alg=0, can_auth = 0;
659    
660     for (k = key->subkeys; k; k = k->next) {
661     n++;
662     if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)
663     n_alg++;
664     if (k->can_authenticate)
665     can_auth++;
666     }
667     if (n == 3 && n_alg == 3 && can_auth == 1)
668     return 1;
669     return 0;
670     }
671    
672    
673 twoaday 123 static unsigned char*
674     copy_uid_prefs (const unsigned char *prefs)
675     {
676     unsigned char *p;
677     size_t pos=0;
678    
679     while (prefs[pos] != 0)
680     pos++;
681     p = (unsigned char*)calloc (1, pos+1);
682     if (!p)
683     abort ();
684     memcpy (p, prefs, pos);
685     return p;
686     }
687    
688    
689 werner 36 gpgme_error_t
690     gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
691     {
692     struct keycache_s *c, *c_sec;
693     gpgme_key_t key;
694    
695     if (!pub || !sec)
696     return gpg_error (GPG_ERR_INV_ARG);
697    
698     for (c=sec->item; c; c=c->next) {
699     if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
700     c_sec->gloflags.is_protected = c->gloflags.is_protected;
701     c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
702     if (!c->gloflags.divert_to_card)
703     c->gloflags.divert_to_card = key_divert_to_card (key);
704 twoaday 123 c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
705 werner 36 c->pubpart = c_sec;
706     c->pubpart->key = key;
707     }
708     }
709     return 0;
710     }
711    
712    
713     /* Rewind the given cache @ctx to the begin. */
714     void
715     gpg_keycache_rewind (gpg_keycache_t ctx)
716     {
717     if (ctx)
718     ctx->pos = 0;
719     }
720    
721    
722    
723     /* Return the number of elements in the cache @ctx. */
724     int
725     gpg_keycache_get_size (gpg_keycache_t ctx)
726     {
727     struct keycache_s *c;
728     int count = 0;
729    
730     if (!ctx)
731     return 0;
732     for (c = ctx->item; c; c = c->next)
733     count++;
734     return count;
735     }
736    
737    
738     static gpgme_error_t
739     keycache_next_key (gpg_keycache_t ctx, int flags,
740     struct keycache_s **c, gpgme_key_t *r_key)
741     {
742     if (!ctx || !r_key)
743     return gpg_error (GPG_ERR_INV_ARG);
744    
745     if (!ctx->pos)
746     ctx->tmp = ctx->item;
747    
748     if (!ctx->tmp || !ctx->tmp->key) {
749     ctx->pos = 0;
750     *r_key = NULL;
751     return gpg_error (GPG_ERR_EOF);
752     }
753 twoaday 150 if (ctx->tmp->flags != 0)
754     ctx->tmp->flags = 0; /* reset the 'updated' status. */
755 werner 36 *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
756     *c = ctx->tmp = ctx->tmp->next;
757     ctx->pos++;
758    
759     return 0;
760     }
761    
762    
763     /* Return the next key from the cache @ctx. The key will be returned
764     in @r_key. @flags can contain additional flags.
765     Return value: 0 on success. */
766     gpgme_error_t
767     gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
768     {
769     struct keycache_s *c=NULL;
770     gpgme_error_t err = 0;
771    
772     err = keycache_next_key (ctx, flags, &c, r_key);
773     return err;
774     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26