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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 175 - (hide annotations)
Tue Feb 7 08:58:04 2006 UTC (19 years ago) by twoaday
File size: 20091 byte(s)
2006-02-04  Timo Schulz  <ts@g10code.de>
                                                                                                                            
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Check for
        at least one ultimately trusted key.
        * wptKeyManager.cpp (km_refresh_key_from_keyserver):
        Only check inet connection if we refresh all keys.
        * wptGPGUtil.cpp (gpg_extract_keys): New.
        * wptClipEncryptDlg.cpp (clip_encrypt_dlg_proc): Use textmode.
        * wptClipSignEncDlg.cpp (clip_signenc_dlg_proc): Likewise.
        * wptClipSignDlg.cpp (get_selected_key): New.
        (one_key_proc): Use it here.
        (count_useable_seckeys): New.
        * wptSigTreeDlg.cpp (sigtree_dlg_proc): New.
        * wptKeyEditDlgs.cpp (diff_time): Removed.
        (w32_mktime): New.
        (keyedit_addsubkey_dlg_proc): Use it here.
                                                                                                                            
2006-02-02  Timo Schulz  <ts@g10code.de>
                                                                                                                            
        * wptW32API.cpp (get_temp_name): New.
        * wptKeyserver.cpp (ldap_recvkey): Use it here.
        * wptKeyPropsDlg.cpp (get_photo_tmpname): Likewise.
        * wptGPGUtil.cpp (create_tempfile): Likewise.
        * wptImportList.cpp (implist_load): Likewise.
        * wptKeyCache.cpp (parse_attr_data): Likewise.
        (w32_tempfile): Removed.
        * wptGPGME.cpp (check_ultimate_trusted_key): New.
                                                                                                                            

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 twoaday 175 FILE *tmp;
129     BYTE *data;
130 twoaday 164 char *status, tmpnam[MAX_PATH+1];
131 twoaday 175 DWORD ndata = 0;
132 twoaday 133
133     err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
134     if (err)
135     return err;
136    
137 twoaday 175 get_temp_name (tmpnam, MAX_PATH, NULL);
138     tmp = fopen (tmpnam, "w+b");
139     if (ndata > 0 && tmp != NULL) {
140 twoaday 133 fwrite (status, 1, strlen (status), tmp);
141     fflush (tmp);
142     rewind (tmp);
143    
144     ndata = parse_attr_list (tmp, data, ndata, list);
145     fclose (tmp);
146 twoaday 164 DeleteFile (tmpnam);
147 werner 36 }
148 twoaday 133 else
149     *list = NULL;
150    
151     safe_free (status);
152     safe_free (data);
153     return ndata;
154 werner 36 }
155    
156 twoaday 121
157 werner 36 /* Parse the secret keyring and retrieve some additional information
158     for each key which was found. */
159     static void
160     parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
161     {
162 twoaday 133 PACKET *pkt;
163 werner 36 PKT_secret_key *sk;
164     gpg_iobuf_t inp;
165     gpgme_error_t err;
166     gpgme_key_t key;
167     struct keycache_s *c=NULL;
168     char keyid[16+1];
169    
170     inp = gpg_iobuf_open (secring);
171 twoaday 133 if (!inp)
172 werner 36 return;
173 twoaday 133
174 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL);
175 twoaday 133 pkt = (PACKET*)calloc (1, sizeof *pkt);
176 werner 36 gpg_init_packet (pkt);
177     while (gpg_parse_packet (inp, pkt) != -1) {
178     if (pkt->pkttype == PKT_SECRET_KEY) {
179     sk = pkt->pkt.secret_key;
180     /* XXX: key IDs of card public keys are wrong! */
181     _snprintf (keyid, sizeof (keyid)-1, "%08lX",
182     gpg_keyid_from_sk (sk, NULL));
183     if (kid && strcmp (kid, keyid) != 0)
184     goto next;
185     err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);
186     if (err)
187     goto next;
188     c->gloflags.is_protected = sk->is_protected;
189     c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
190     if (c->pubpart != NULL) {
191     c->pubpart->gloflags.is_protected = sk->is_protected;
192     c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
193     }
194     }
195     next:
196     gpg_free_packet (pkt);
197     gpg_init_packet (pkt);
198     }
199     safe_free (pkt);
200     gpg_iobuf_close (inp);
201     }
202    
203    
204 twoaday 133 /* Update the photo image of a single key with the fingerprint
205     @fpr. The @dat struct contains the new item data. */
206     static gpgme_error_t
207     keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
208     {
209     struct keycache_s *fnd = NULL;
210     gpgme_key_t key;
211    
212     gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
213     if (!fnd)
214     return gpg_error (GPG_ERR_NOT_FOUND);
215     safe_free (fnd->attrib.d);
216     fnd->attrib.flags = dat->flags;
217     fnd->attrib.len = dat->octets;
218     fnd->attrib.d = (unsigned char*)malloc (dat->octets);
219     memcpy (fnd->attrib.d, dat->d, dat->octets);
220     return 0;
221     }
222    
223    
224     /* Update all photo images in the cache. */
225     static gpgme_error_t
226     keycache_update_photos (gpg_keycache_t ctx)
227     {
228     attr_list_t list=NULL, n;
229     DWORD ndata;
230    
231     ndata = parse_attr_data (NULL, &list);
232     if (ndata < 1) {
233     free_attr_list (list);
234     return 0;
235     }
236    
237     for (n=list; n; n=n->next)
238     keycache_update_photo (ctx, n->fpr, n);
239     free_attr_list (list);
240     return 0;
241     }
242    
243    
244 werner 36 /* Merge the information from the keyrings into the key cache structure. */
245     gpgme_error_t
246     keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
247     const char *pubring, const char *secring)
248     {
249 twoaday 69 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
250 werner 36 gpgme_key_t key = NULL;
251     gpg_iobuf_t inp;
252 twoaday 133 PACKET *pkt;
253 werner 36 struct keycache_s *c;
254     const byte *sym_prefs;
255 twoaday 133 char keyid[16+1];
256 werner 36 int key_seen = 0;
257 twoaday 65 size_t nsym =0;
258 werner 36
259     if (secring) {
260     parse_secring (ctx, kid, secring);
261 twoaday 133 if (!pubring)
262 werner 36 return 0;
263     }
264     inp = gpg_iobuf_open (pubring);
265 twoaday 133 if (!inp)
266 werner 36 return gpg_error (GPG_ERR_KEYRING_OPEN);
267 twoaday 123 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
268 werner 36
269 twoaday 133 pkt = (PACKET*)calloc (1, sizeof * pkt);
270 twoaday 123 gpg_init_packet (pkt);
271 werner 36 while (gpg_parse_packet (inp, pkt) != -1) {
272     if (pkt->pkttype == PKT_PUBLIC_KEY) {
273     strcpy (keyid, "");
274     key_seen = 1;
275     }
276    
277 twoaday 133 if (pkt->pkttype == PKT_SIGNATURE &&
278     pkt->pkt.signature->sig_class == 0x1F) {
279 werner 36 if (pkt->pkt.signature->numrevkeys == 0)
280     goto next;
281 twoaday 133 _snprintf (keyid, sizeof (keyid) -1, "%08X",
282     pkt->pkt.signature->keyid[1]);
283 werner 36 if (kid && strcmp (kid, keyid) != 0)
284     goto next;
285     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
286     if (err)
287     goto next;
288     c->gloflags.has_desig_rev = 1;
289     }
290     if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
291 twoaday 133 sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
292     SIGSUBPKT_PREF_SYM, &nsym);
293     if (!sym_prefs)
294 werner 36 goto next;
295 twoaday 133 _snprintf (keyid, sizeof (keyid) - 1, "%08X",
296     pkt->pkt.signature->keyid[1]);
297 werner 36 if (kid && strcmp (kid, keyid) != 0)
298     goto next;
299     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
300     if (err)
301     goto next;
302     else if (nsym > 0) {
303     c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
304     if (!c->sym_prefs)
305     return gpg_error (GPG_ERR_ENOMEM);
306     memcpy (c->sym_prefs, sym_prefs, nsym);
307     }
308     }
309     next:
310     gpg_free_packet (pkt);
311     gpg_init_packet(pkt);
312     }
313    
314     safe_free (pkt);
315     gpg_iobuf_close (inp);
316     return err;
317     }
318    
319    
320     gpgme_error_t
321     gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)
322     {
323     return keycache_prepare2 (ctx, NULL, pubr, secr);
324     }
325    
326     gpgme_error_t
327     gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,
328     const char *pubr, const char *secr)
329     {
330     if (!strncmp (keyid, "0x", 2))
331     keyid += 2;
332     return keycache_prepare2 (ctx, keyid, pubr, secr);
333     }
334    
335    
336     /* Create new keycache object and return it in @r_ctx.
337     Return value: 0 on success. */
338     gpgme_error_t
339     gpg_keycache_new (gpg_keycache_t *r_ctx)
340     {
341     gpg_keycache_t ctx;
342    
343     if (!r_ctx)
344     return gpg_error (GPG_ERR_INV_ARG);
345     ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
346     if (!ctx)
347     return gpg_error (GPG_ERR_ENOMEM);
348     ctx->secret = 0;
349     ctx->pos = 0;
350     *r_ctx = ctx;
351     return 0;
352     }
353    
354    
355     /* Release keycache object @ctx. */
356     void
357     gpg_keycache_release (gpg_keycache_t ctx)
358     {
359     struct keycache_s *c, *c2;
360    
361     if (!ctx)
362     return;
363    
364     for (c = ctx->item; c; c = c2) {
365     c2 = c->next;
366     gpgme_key_release (c->key);
367     c->key = NULL;
368 twoaday 133 safe_free (c->sym_prefs);
369     safe_free (c->attrib.d);
370     safe_free (c->card_type);
371 werner 36 free (c);
372     }
373 twoaday 133 safe_free (ctx);
374 werner 36 }
375    
376    
377     /* Set (progress) callback for the given keycache object.
378     @ctx the keycache
379     @cb the callback function
380     @cb_value1 opaque value which is passed to the callback.
381     @cb_value2 see @cb_value1. */
382     void
383     gpg_keycache_set_cb (gpg_keycache_t ctx,
384     void (*cb)(void *, const char *, int, int, int),
385     void * cb_value1, int cb_value2)
386     {
387     if (!ctx)
388     return;
389     ctx->cb = cb;
390     ctx->cb_value = cb_value1;
391     ctx->cb_value2 = cb_value2;
392     }
393    
394    
395     /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.
396     Return value: 0 on success. */
397     gpgme_error_t
398     gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
399     {
400 twoaday 41 struct keycache_s *c, *n1;
401 werner 36
402     if (!ctx)
403     return gpg_error (GPG_ERR_INV_ARG);
404    
405     c = (struct keycache_s*)calloc (1, sizeof *c);
406     if (!c)
407     return gpg_error (GPG_ERR_ENOMEM);
408     c->gloflags.is_protected = 1; /*default: assume protection. */
409     c->key = key;
410     if (!ctx->item)
411     ctx->item = c;
412     else {
413     for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)
414     ;
415     n1->next = c;
416     }
417     if (opaque)
418     *opaque = c;
419     return 0;
420     }
421    
422    
423    
424     #define has_keyid_len(pattern) (\
425     strlen (pattern) == 8 || strlen (pattern) == 10 || \
426     strlen (pattern) == 16 || strlen (pattern) == 18)
427    
428    
429     gpgme_error_t
430     gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,
431     gpgme_key_t *r_key, struct keycache_s **r_item)
432     {
433     struct keycache_s *c;
434     gpgme_subkey_t s;
435     gpgme_user_id_t u;
436     gpgme_key_t key;
437     const char *kid;
438    
439     if (!ctx || !r_key)
440     return gpg_error (GPG_ERR_INV_ARG);
441    
442     if (strstr (pattern, "0x"))
443     pattern += 2;
444    
445     /* Sometimes a subkey has no valid fpr. As a kludge we convert v4
446     fingerprints into the 64-bit keyid. */
447     if (strlen (pattern) == 40 && isxdigit (*pattern))
448     pattern += 32;
449    
450     /* XXX: this code is very slow, revamp it and use hash tables whenever
451     it is possible. */
452     for (c = ctx->item; c; c = c->next) {
453     key = c->key;
454     assert (key->_refs >= 1);
455     for (s = key->subkeys; s; s = s->next) {
456     for (u = key->uids; u; u = u->next) {
457     if (u->name && stristr (u->name, pattern)) {
458     if (r_item)
459     *r_item = c;
460     *r_key = flags? c->pubpart->key : c->key;
461     return 0;
462     }
463     }
464     if (has_keyid_len (pattern))
465     kid = s->keyid;
466     else
467     kid = s->fpr;
468     if (kid && stristr (kid, pattern)) {
469     if (r_item)
470     *r_item = c;
471     *r_key = flags? c->pubpart->key : c->key;
472     return 0;
473     }
474     }
475     }
476     *r_key = NULL;
477     return gpg_error (GPG_ERR_INTERNAL);
478 twoaday 133 }
479 werner 36
480    
481     gpgme_error_t
482     gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,
483     int flags, gpgme_key_t *r_key)
484     {
485     return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);
486     }
487    
488    
489 twoaday 133 /* Reload a photo image of a single key with the keyid @keyid.
490     Return value: 0 on success. */
491     static gpgme_error_t
492     keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
493     {
494     attr_list_t list;
495    
496     if (parse_attr_data (keyid, &list) < 1) {
497     free_attr_list (list);
498     return 0;
499     }
500     keycache_update_photo (ctx, list->fpr, list);
501     free_attr_list (list);
502     return 0;
503     }
504    
505    
506 twoaday 147 /* Return the next key which was updated. Before it is
507     returned the update flag is cleared.
508 twoaday 150 @r_status is 1 for a new key and 2 for an updated key.
509 twoaday 147 Return value: 0 on success. */
510 werner 36 gpgme_error_t
511 twoaday 147 gpg_keycache_next_updated_key (gpg_keycache_t ctx,
512 twoaday 150 struct keycache_s **r_obj,
513     int *r_status)
514 twoaday 147 {
515     struct keycache_s *c;
516    
517     for (c = ctx->item; c; c = c->next) {
518 twoaday 150 if (c->flags != 0) {
519     *r_status = c->flags;
520 twoaday 147 c->flags = 0;
521     *r_obj = c;
522     return 0;
523     }
524     }
525     return gpg_error (GPG_ERR_NOT_FOUND);
526     }
527    
528    
529    
530     gpgme_error_t
531 werner 36 gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
532     void *opaque, const char *keyid)
533     {
534     struct keycache_s *c = NULL, *c_new=NULL;
535     gpgme_key_t key=NULL, fndkey=NULL;
536     gpgme_error_t err;
537     gpgme_ctx_t gctx;
538     gpg_keycache_t pub = (gpg_keycache_t)opaque;
539    
540     err = gpgme_new (&gctx);
541     if (err)
542     return err;
543 twoaday 150 gpgme_set_keylist_mode (gctx, GPGME_KEYLIST_MODE_SIGS);
544 werner 36 err = gpgme_get_key (gctx, keyid, &key, is_sec);
545     gpgme_release (gctx);
546     if (err)
547     return err;
548     err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
549     if (!err && c != NULL) {
550     log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
551     gpgme_key_release (fndkey);
552     c->key = key;
553 twoaday 150 c->flags = KC_FLAG_UPD;
554 werner 36 if (is_sec && pub != NULL &&
555     !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
556     log_debug ("keycache update: set public part %p\r\n", fndkey);
557     c->pubpart->key = fndkey;
558     }
559 twoaday 133 /* XXX: this is also called for keys without a photo-id. */
560     keycache_reload_photo (ctx, keyid);
561 werner 36 }
562     else {
563     log_debug ("keycache add: sync public part\r\n");
564     if (is_sec)
565     gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);
566     gpg_keycache_add_key (ctx, key, (void **)&c);
567     if (c != NULL && is_sec) {
568     log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);
569     c->pubpart = c_new;
570     if (c_new != NULL) {
571     c->pubpart->key = fndkey;
572     c->gloflags.is_protected = c_new->gloflags.is_protected;
573     c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
574     }
575     }
576 twoaday 147 if (c)
577 twoaday 150 c->flags = KC_FLAG_ADD;
578 werner 36 }
579     return 0;
580     }
581    
582    
583     /* Delete a key from the cache @ctx with the pattern @pattern.
584     Return value: 0 on success. */
585     gpgme_error_t
586     gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)
587     {
588     struct keycache_s *itm = NULL, *c;
589     gpgme_key_t key;
590     gpgme_error_t rc;
591    
592     if (!ctx)
593     return gpg_error (GPG_ERR_INV_ARG);
594     rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
595     if (rc)
596     return rc;
597    
598     c = ctx->item;
599     if (c->next == NULL) {
600     gpgme_key_release (itm->key);
601     if (itm)
602     free (itm);
603     ctx->item = NULL;
604     }
605     else {
606     while (c && c->next != itm)
607     c = c->next;
608     c->next = c->next->next;
609     gpgme_key_release (itm->key);
610     if (itm)
611     free (itm);
612     }
613     return 0;
614     }
615    
616    
617     /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring
618     will be added to the cache. @secret is 1 if the source is the secret keyring.
619     Return value: 0 on success. */
620     gpgme_error_t
621     gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)
622     {
623     gpgme_error_t err;
624     gpgme_ctx_t c;
625     gpgme_key_t key;
626     int count = 0;
627    
628     if (!ctx)
629     return gpg_error (GPG_ERR_INV_ARG);
630    
631     err = gpgme_new (&c);
632     if (err)
633     return err;
634    
635     gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS);
636     err = gpgme_op_keylist_start (c, pattern, secret);
637     while(!err) {
638     err = gpgme_op_keylist_next (c, &key);
639     if (!err)
640     err = gpg_keycache_add_key (ctx, key, NULL);
641     if (ctx->cb)
642     ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,
643     count++, ctx->cb_value2);
644     }
645     if (gpgme_err_code (err) == GPG_ERR_EOF)
646     err = gpg_error (GPG_ERR_NO_ERROR);
647 twoaday 133 keycache_update_photos (ctx);
648 werner 36 /* XXX: make sure the progress dialog is closed. */
649     gpgme_op_keylist_end (c);
650     gpgme_release (c);
651     return err;
652     }
653    
654    
655     /* XXX: kludge to see if the key is stored on a card. */
656     static int
657     key_divert_to_card (gpgme_key_t key)
658     {
659     gpgme_subkey_t k;
660     int n=0, n_alg=0, can_auth = 0;
661    
662     for (k = key->subkeys; k; k = k->next) {
663     n++;
664     if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)
665     n_alg++;
666     if (k->can_authenticate)
667     can_auth++;
668     }
669     if (n == 3 && n_alg == 3 && can_auth == 1)
670     return 1;
671     return 0;
672     }
673    
674    
675 twoaday 123 static unsigned char*
676     copy_uid_prefs (const unsigned char *prefs)
677     {
678     unsigned char *p;
679     size_t pos=0;
680    
681     while (prefs[pos] != 0)
682     pos++;
683     p = (unsigned char*)calloc (1, pos+1);
684     if (!p)
685     abort ();
686     memcpy (p, prefs, pos);
687     return p;
688     }
689    
690    
691 werner 36 gpgme_error_t
692     gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
693     {
694     struct keycache_s *c, *c_sec;
695     gpgme_key_t key;
696    
697     if (!pub || !sec)
698     return gpg_error (GPG_ERR_INV_ARG);
699    
700     for (c=sec->item; c; c=c->next) {
701     if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
702     c_sec->gloflags.is_protected = c->gloflags.is_protected;
703     c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
704     if (!c->gloflags.divert_to_card)
705     c->gloflags.divert_to_card = key_divert_to_card (key);
706 twoaday 168 if (c_sec->sym_prefs)
707     c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
708 werner 36 c->pubpart = c_sec;
709     c->pubpart->key = key;
710     }
711     }
712     return 0;
713     }
714    
715    
716     /* Rewind the given cache @ctx to the begin. */
717     void
718     gpg_keycache_rewind (gpg_keycache_t ctx)
719     {
720     if (ctx)
721     ctx->pos = 0;
722     }
723    
724    
725    
726     /* Return the number of elements in the cache @ctx. */
727     int
728     gpg_keycache_get_size (gpg_keycache_t ctx)
729     {
730     struct keycache_s *c;
731     int count = 0;
732    
733     if (!ctx)
734     return 0;
735     for (c = ctx->item; c; c = c->next)
736     count++;
737     return count;
738     }
739    
740    
741     static gpgme_error_t
742     keycache_next_key (gpg_keycache_t ctx, int flags,
743     struct keycache_s **c, gpgme_key_t *r_key)
744     {
745     if (!ctx || !r_key)
746     return gpg_error (GPG_ERR_INV_ARG);
747    
748     if (!ctx->pos)
749     ctx->tmp = ctx->item;
750    
751     if (!ctx->tmp || !ctx->tmp->key) {
752     ctx->pos = 0;
753     *r_key = NULL;
754     return gpg_error (GPG_ERR_EOF);
755     }
756 twoaday 150 if (ctx->tmp->flags != 0)
757     ctx->tmp->flags = 0; /* reset the 'updated' status. */
758 twoaday 165 /* it might be possible there is no public key. */
759     if (flags && ctx->tmp->pubpart == NULL)
760     flags = 0;
761 werner 36 *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
762     *c = ctx->tmp = ctx->tmp->next;
763     ctx->pos++;
764    
765     return 0;
766     }
767    
768    
769     /* Return the next key from the cache @ctx. The key will be returned
770     in @r_key. @flags can contain additional flags.
771     Return value: 0 on success. */
772     gpgme_error_t
773     gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
774     {
775     struct keycache_s *c=NULL;
776     gpgme_error_t err = 0;
777    
778     err = keycache_next_key (ctx, flags, &c, r_key);
779     return err;
780     }
781 twoaday 167
782     /* Search for a key with the pattern @pattern and mark
783     this key as the default signing key if found.
784     Return value: 0 on success. */
785     gpgme_error_t
786     gpg_keycache_set_default_key (gpg_keycache_t ctx,
787     const char *pattern)
788     {
789     gpgme_error_t err;
790     gpgme_key_t key;
791     struct keycache_s *itm;
792    
793     err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
794     if (err)
795     return err;
796    
797     if (itm)
798     itm->default_key = 1;
799     return 0;
800     }
801    
802     /* Return the default key from the cache. If no was
803     marked before, NULL is returned in @r_key.
804     Return value: 0 on success. */
805     gpgme_error_t
806     gpg_keycache_get_default_key (gpg_keycache_t ctx,
807     gpgme_key_t *r_key)
808     {
809     struct keycache_s *itm;
810    
811     *r_key = NULL;
812     for (itm = ctx->item; itm; itm = itm->next) {
813     if (itm->default_key) {
814     *r_key = itm->key;
815     break;
816     }
817     }
818     if (!*r_key)
819     return gpgme_error (GPG_ERR_NOT_FOUND);
820     return 0;
821     }
822    
823    
824    

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26