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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 205 - (hide annotations)
Thu Apr 27 12:46:03 2006 UTC (18 years, 10 months ago) by twoaday
File size: 23903 byte(s)
2006-04-27  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeyManager.cpp (km_get_key_ptr): New.
        * wptListview.cpp (listview_get_item_text): Drop utf8 support.
        * wptKeyCache.cpp (keycache_decode_uids): New.
        (free_native_uids): New.
        * wptKeyEdit.cpp (uid_inf_colon_handler): Do utf8 decodig here.
                                                                                
2006-04-26  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeylist.cpp (get_keyid_from_fpr): New.
        * wptDecryptClipDlg.cpp (clip_decrypt_dlg): Use it here.
        * wptVerifyList.cpp (verlist_add_sig): Likewise.


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 twoaday 196 * This file is part of WinPT.
5 werner 36 *
6 twoaday 196 * WinPT is free software; you can redistribute it and/or modify
7 werner 36 * 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 twoaday 196 * WinPT is distributed in the hope that it will be useful,
12 werner 36 * 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 twoaday 181 #include "wptTypes.h"
40 twoaday 205 #include "wptUTF8.h"
41 werner 36
42    
43 twoaday 133 /* Attribute list which holds the image data. */
44     struct attr_list_s {
45     struct attr_list_s *next;
46     char *fpr; /* fingerprint of the key */
47     unsigned char *d; /* actual JPEG data. */
48     unsigned long octets; /* length of the data. */
49     unsigned int flags; /* status of the attribute. */
50     };
51     typedef struct attr_list_s *attr_list_t;
52    
53    
54 twoaday 181 /* Free attribute list @ctx. */
55 twoaday 133 void
56     free_attr_list (attr_list_t ctx)
57 werner 36 {
58 twoaday 133 attr_list_t n;
59     while (ctx) {
60     n = ctx->next;
61 twoaday 196 safe_free (ctx->fpr);
62     safe_free (ctx->d);
63 twoaday 133 ctx = n;
64     }
65     }
66    
67     /* Parse the attribute list in @fp and store it into @ctx.
68     Return value: number of parsed items. */
69     int
70     parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
71     {
72     attr_list_t c, t;
73     char buf[512], *p, *buffer;
74     int pos, n=0;
75    
76     *ctx = NULL;
77     while (fgets (buf, 511, fp)) {
78     if (strstr (buf, "\r\n"))
79     buf[strlen (buf)-2]=0;
80     if (strstr (buf, "\n"))
81     buf[strlen (buf)-1]=0;
82     if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
83     continue;
84     buffer = buf+9+10;
85     pos = 0;
86     c = (attr_list_t)calloc (1, sizeof *c);
87 twoaday 181 if (!c)
88     BUG (0);
89 twoaday 133 p = strtok (buffer, " ");
90     while (p != NULL) {
91     switch (pos) {
92     case 0:
93     c->fpr = strdup (p);
94     break;
95    
96     case 1:
97     c->octets = strtoul (p, NULL, 10);
98     break;
99    
100     case 7:
101     c->flags = strtoul (p, NULL, 10);
102     break;
103    
104     default:
105     break;
106     }
107     pos++;
108     p = strtok (NULL, " ");
109     }
110     if (!*ctx)
111     *ctx = c;
112     else {
113     for (t = *ctx; t->next; t=t->next)
114     ;
115     t->next = c;
116     }
117     c->d = (unsigned char*)malloc (c->octets);
118 twoaday 181 if (!c->d)
119     BUG (0);
120 twoaday 133 memcpy (c->d, data, c->octets);
121     data += c->octets;
122     datlen -= c->octets;
123     n++;
124     }
125     /*assert (datlen == 0); */
126     return n;
127     }
128 werner 36
129 twoaday 133
130     static int
131     parse_attr_data (const char *keyid, attr_list_t *list)
132     {
133     gpgme_error_t err;
134 twoaday 175 FILE *tmp;
135     BYTE *data;
136 twoaday 164 char *status, tmpnam[MAX_PATH+1];
137 twoaday 175 DWORD ndata = 0;
138 twoaday 133
139     err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
140     if (err)
141     return err;
142    
143 twoaday 175 get_temp_name (tmpnam, MAX_PATH, NULL);
144     tmp = fopen (tmpnam, "w+b");
145     if (ndata > 0 && tmp != NULL) {
146 twoaday 133 fwrite (status, 1, strlen (status), tmp);
147     fflush (tmp);
148     rewind (tmp);
149    
150     ndata = parse_attr_list (tmp, data, ndata, list);
151     fclose (tmp);
152 twoaday 164 DeleteFile (tmpnam);
153 werner 36 }
154 twoaday 133 else
155     *list = NULL;
156    
157     safe_free (status);
158     safe_free (data);
159     return ndata;
160 werner 36 }
161    
162 twoaday 121
163 werner 36 /* Parse the secret keyring and retrieve some additional information
164     for each key which was found. */
165     static void
166     parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
167     {
168 twoaday 133 PACKET *pkt;
169 werner 36 PKT_secret_key *sk;
170     gpg_iobuf_t inp;
171     gpgme_error_t err;
172     gpgme_key_t key;
173     struct keycache_s *c=NULL;
174     char keyid[16+1];
175    
176     inp = gpg_iobuf_open (secring);
177 twoaday 133 if (!inp)
178 werner 36 return;
179 twoaday 133
180 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL);
181 twoaday 133 pkt = (PACKET*)calloc (1, sizeof *pkt);
182 twoaday 181 if (!pkt)
183     BUG (0);
184 werner 36 gpg_init_packet (pkt);
185     while (gpg_parse_packet (inp, pkt) != -1) {
186     if (pkt->pkttype == PKT_SECRET_KEY) {
187     sk = pkt->pkt.secret_key;
188     /* XXX: key IDs of card public keys are wrong! */
189     _snprintf (keyid, sizeof (keyid)-1, "%08lX",
190     gpg_keyid_from_sk (sk, NULL));
191     if (kid && strcmp (kid, keyid) != 0)
192     goto next;
193     err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);
194     if (err)
195     goto next;
196     c->gloflags.is_protected = sk->is_protected;
197     c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
198     if (c->pubpart != NULL) {
199     c->pubpart->gloflags.is_protected = sk->is_protected;
200     c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
201     }
202     }
203     next:
204     gpg_free_packet (pkt);
205     gpg_init_packet (pkt);
206     }
207     safe_free (pkt);
208     gpg_iobuf_close (inp);
209     }
210    
211    
212 twoaday 133 /* Update the photo image of a single key with the fingerprint
213     @fpr. The @dat struct contains the new item data. */
214     static gpgme_error_t
215     keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
216     {
217     struct keycache_s *fnd = NULL;
218     gpgme_key_t key;
219    
220     gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
221     if (!fnd)
222     return gpg_error (GPG_ERR_NOT_FOUND);
223     safe_free (fnd->attrib.d);
224     fnd->attrib.flags = dat->flags;
225     fnd->attrib.len = dat->octets;
226     fnd->attrib.d = (unsigned char*)malloc (dat->octets);
227 twoaday 181 if (!fnd->attrib.d)
228     BUG (0);
229 twoaday 133 memcpy (fnd->attrib.d, dat->d, dat->octets);
230     return 0;
231     }
232    
233    
234     /* Update all photo images in the cache. */
235     static gpgme_error_t
236     keycache_update_photos (gpg_keycache_t ctx)
237     {
238     attr_list_t list=NULL, n;
239     DWORD ndata;
240    
241     ndata = parse_attr_data (NULL, &list);
242     if (ndata < 1) {
243     free_attr_list (list);
244     return 0;
245     }
246    
247     for (n=list; n; n=n->next)
248     keycache_update_photo (ctx, n->fpr, n);
249     free_attr_list (list);
250     return 0;
251     }
252    
253    
254 twoaday 205 /* Store utf8 decoded user IDs in the code to avoid in-place decoding. */
255     static gpgme_error_t
256     keycache_decode_uids (gpg_keycache_t ctx)
257     {
258     struct native_uid_s *n, *t;
259     struct keycache_s *c;
260     gpgme_user_id_t u;
261    
262     for (c = ctx->item; c; c = c->next) {
263     for (u = c->key->uids; u; u = u->next) {
264     n = (struct native_uid_s*)calloc (1, sizeof *n);
265     if (!n)
266     BUG (0);
267     if (is_8bit_string (u->uid)) {
268     n->malloced = 1;
269     n->uid = utf8_to_native (u->uid);
270     if (u->name != NULL)
271     n->name = utf8_to_native (u->name);
272     if (u->email != NULL)
273     n->email = strdup (u->email);
274     if (u->comment != NULL)
275     n->comment = utf8_to_native (u->comment);
276     }
277     else {
278     n->malloced = 0;
279     n->uid = u->uid;
280     n->name = u->name;
281     n->comment = u->comment;
282     n->email = u->email;
283     }
284     if (!c->uids)
285     c->uids = n;
286     else {
287     for (t = c->uids; t->next; t=t->next)
288     ;
289     t->next = n;
290     }
291     }
292     }
293     return 0;
294     }
295    
296    
297     static void
298     free_native_uids (struct native_uid_s *n)
299     {
300     struct native_uid_s *t;
301    
302     while (n != NULL) {
303     t = n->next;
304     if (n->malloced) {
305     safe_free (n->uid);
306     safe_free (n->name);
307     safe_free (n->comment);
308     safe_free (n->email);
309     safe_free (n->uid);
310     }
311     safe_free (n);
312     n = t;
313     }
314     }
315    
316    
317    
318 werner 36 /* Merge the information from the keyrings into the key cache structure. */
319     gpgme_error_t
320     keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
321     const char *pubring, const char *secring)
322     {
323 twoaday 69 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
324 werner 36 gpgme_key_t key = NULL;
325     gpg_iobuf_t inp;
326 twoaday 133 PACKET *pkt;
327 werner 36 struct keycache_s *c;
328     const byte *sym_prefs;
329 twoaday 133 char keyid[16+1];
330 werner 36 int key_seen = 0;
331 twoaday 65 size_t nsym =0;
332 werner 36
333     if (secring) {
334     parse_secring (ctx, kid, secring);
335 twoaday 133 if (!pubring)
336 werner 36 return 0;
337     }
338     inp = gpg_iobuf_open (pubring);
339 twoaday 133 if (!inp)
340 werner 36 return gpg_error (GPG_ERR_KEYRING_OPEN);
341 twoaday 123 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
342 werner 36
343 twoaday 133 pkt = (PACKET*)calloc (1, sizeof * pkt);
344 twoaday 181 if (!pkt)
345     BUG (0);
346 twoaday 123 gpg_init_packet (pkt);
347 werner 36 while (gpg_parse_packet (inp, pkt) != -1) {
348     if (pkt->pkttype == PKT_PUBLIC_KEY) {
349     strcpy (keyid, "");
350     key_seen = 1;
351     }
352    
353 twoaday 133 if (pkt->pkttype == PKT_SIGNATURE &&
354     pkt->pkt.signature->sig_class == 0x1F) {
355 werner 36 if (pkt->pkt.signature->numrevkeys == 0)
356     goto next;
357 twoaday 133 _snprintf (keyid, sizeof (keyid) -1, "%08X",
358     pkt->pkt.signature->keyid[1]);
359 werner 36 if (kid && strcmp (kid, keyid) != 0)
360     goto next;
361     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
362     if (err)
363     goto next;
364     c->gloflags.has_desig_rev = 1;
365     }
366     if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
367 twoaday 133 sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
368     SIGSUBPKT_PREF_SYM, &nsym);
369     if (!sym_prefs)
370 werner 36 goto next;
371 twoaday 133 _snprintf (keyid, sizeof (keyid) - 1, "%08X",
372     pkt->pkt.signature->keyid[1]);
373 werner 36 if (kid && strcmp (kid, keyid) != 0)
374     goto next;
375     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
376     if (err)
377     goto next;
378     else if (nsym > 0) {
379     c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
380     if (!c->sym_prefs)
381 twoaday 181 BUG (0);
382 werner 36 memcpy (c->sym_prefs, sym_prefs, nsym);
383     }
384     }
385     next:
386     gpg_free_packet (pkt);
387     gpg_init_packet(pkt);
388     }
389    
390     safe_free (pkt);
391     gpg_iobuf_close (inp);
392     return err;
393     }
394    
395    
396     gpgme_error_t
397     gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)
398     {
399     return keycache_prepare2 (ctx, NULL, pubr, secr);
400     }
401    
402     gpgme_error_t
403     gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,
404     const char *pubr, const char *secr)
405     {
406     if (!strncmp (keyid, "0x", 2))
407     keyid += 2;
408     return keycache_prepare2 (ctx, keyid, pubr, secr);
409     }
410    
411    
412     /* Create new keycache object and return it in @r_ctx.
413     Return value: 0 on success. */
414     gpgme_error_t
415     gpg_keycache_new (gpg_keycache_t *r_ctx)
416     {
417     gpg_keycache_t ctx;
418    
419     if (!r_ctx)
420     return gpg_error (GPG_ERR_INV_ARG);
421     ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
422     if (!ctx)
423 twoaday 181 BUG (0);
424 werner 36 ctx->secret = 0;
425     ctx->pos = 0;
426     *r_ctx = ctx;
427     return 0;
428     }
429    
430    
431     /* Release keycache object @ctx. */
432     void
433     gpg_keycache_release (gpg_keycache_t ctx)
434     {
435     struct keycache_s *c, *c2;
436    
437     if (!ctx)
438     return;
439    
440     for (c = ctx->item; c; c = c2) {
441     c2 = c->next;
442     gpgme_key_release (c->key);
443     c->key = NULL;
444 twoaday 181 safe_free (c->pref_keyserver);
445 twoaday 133 safe_free (c->sym_prefs);
446     safe_free (c->attrib.d);
447     safe_free (c->card_type);
448 twoaday 205 free_native_uids (c->uids);
449 twoaday 196 safe_free (c);
450 werner 36 }
451 twoaday 133 safe_free (ctx);
452 werner 36 }
453    
454    
455     /* Set (progress) callback for the given keycache object.
456     @ctx the keycache
457     @cb the callback function
458     @cb_value1 opaque value which is passed to the callback.
459     @cb_value2 see @cb_value1. */
460     void
461     gpg_keycache_set_cb (gpg_keycache_t ctx,
462     void (*cb)(void *, const char *, int, int, int),
463     void * cb_value1, int cb_value2)
464     {
465     if (!ctx)
466     return;
467     ctx->cb = cb;
468     ctx->cb_value = cb_value1;
469     ctx->cb_value2 = cb_value2;
470     }
471    
472    
473     /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.
474     Return value: 0 on success. */
475     gpgme_error_t
476     gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
477     {
478 twoaday 41 struct keycache_s *c, *n1;
479 werner 36
480     if (!ctx)
481     return gpg_error (GPG_ERR_INV_ARG);
482    
483     c = (struct keycache_s*)calloc (1, sizeof *c);
484     if (!c)
485 twoaday 181 BUG (0);
486 werner 36 c->gloflags.is_protected = 1; /*default: assume protection. */
487     c->key = key;
488     if (!ctx->item)
489     ctx->item = c;
490     else {
491     for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)
492     ;
493     n1->next = c;
494     }
495     if (opaque)
496     *opaque = c;
497     return 0;
498     }
499    
500    
501    
502     #define has_keyid_len(pattern) (\
503     strlen (pattern) == 8 || strlen (pattern) == 10 || \
504     strlen (pattern) == 16 || strlen (pattern) == 18)
505    
506    
507     gpgme_error_t
508     gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,
509     gpgme_key_t *r_key, struct keycache_s **r_item)
510     {
511     struct keycache_s *c;
512     gpgme_subkey_t s;
513     gpgme_user_id_t u;
514     gpgme_key_t key;
515     const char *kid;
516    
517     if (!ctx || !r_key)
518     return gpg_error (GPG_ERR_INV_ARG);
519    
520     if (strstr (pattern, "0x"))
521     pattern += 2;
522    
523     /* Sometimes a subkey has no valid fpr. As a kludge we convert v4
524     fingerprints into the 64-bit keyid. */
525     if (strlen (pattern) == 40 && isxdigit (*pattern))
526     pattern += 32;
527    
528     /* XXX: this code is very slow, revamp it and use hash tables whenever
529     it is possible. */
530     for (c = ctx->item; c; c = c->next) {
531     key = c->key;
532     assert (key->_refs >= 1);
533     for (s = key->subkeys; s; s = s->next) {
534     for (u = key->uids; u; u = u->next) {
535     if (u->name && stristr (u->name, pattern)) {
536     if (r_item)
537     *r_item = c;
538     *r_key = flags? c->pubpart->key : c->key;
539     return 0;
540     }
541     }
542     if (has_keyid_len (pattern))
543     kid = s->keyid;
544     else
545     kid = s->fpr;
546     if (kid && stristr (kid, pattern)) {
547     if (r_item)
548     *r_item = c;
549     *r_key = flags? c->pubpart->key : c->key;
550     return 0;
551     }
552     }
553     }
554     *r_key = NULL;
555     return gpg_error (GPG_ERR_INTERNAL);
556 twoaday 133 }
557 werner 36
558    
559     gpgme_error_t
560     gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,
561     int flags, gpgme_key_t *r_key)
562     {
563     return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);
564     }
565    
566    
567 twoaday 133 /* Reload a photo image of a single key with the keyid @keyid.
568     Return value: 0 on success. */
569     static gpgme_error_t
570     keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
571     {
572     attr_list_t list;
573    
574     if (parse_attr_data (keyid, &list) < 1) {
575     free_attr_list (list);
576     return 0;
577     }
578     keycache_update_photo (ctx, list->fpr, list);
579     free_attr_list (list);
580     return 0;
581     }
582    
583    
584 twoaday 147 /* Return the next key which was updated. Before it is
585     returned the update flag is cleared.
586 twoaday 150 @r_status is 1 for a new key and 2 for an updated key.
587 twoaday 147 Return value: 0 on success. */
588 werner 36 gpgme_error_t
589 twoaday 147 gpg_keycache_next_updated_key (gpg_keycache_t ctx,
590 twoaday 150 struct keycache_s **r_obj,
591     int *r_status)
592 twoaday 147 {
593     struct keycache_s *c;
594    
595     for (c = ctx->item; c; c = c->next) {
596 twoaday 150 if (c->flags != 0) {
597     *r_status = c->flags;
598 twoaday 187 *r_obj = c;
599 twoaday 147 c->flags = 0;
600     return 0;
601     }
602     }
603     return gpg_error (GPG_ERR_NOT_FOUND);
604     }
605    
606    
607    
608     gpgme_error_t
609 werner 36 gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
610     void *opaque, const char *keyid)
611     {
612     struct keycache_s *c = NULL, *c_new=NULL;
613     gpgme_key_t key=NULL, fndkey=NULL;
614     gpgme_error_t err;
615     gpgme_ctx_t gctx;
616     gpg_keycache_t pub = (gpg_keycache_t)opaque;
617    
618     err = gpgme_new (&gctx);
619     if (err)
620     return err;
621 twoaday 150 gpgme_set_keylist_mode (gctx, GPGME_KEYLIST_MODE_SIGS);
622 werner 36 err = gpgme_get_key (gctx, keyid, &key, is_sec);
623     gpgme_release (gctx);
624     if (err)
625     return err;
626     err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
627     if (!err && c != NULL) {
628     log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
629     gpgme_key_release (fndkey);
630     c->key = key;
631 twoaday 150 c->flags = KC_FLAG_UPD;
632 werner 36 if (is_sec && pub != NULL &&
633     !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
634     log_debug ("keycache update: set public part %p\r\n", fndkey);
635     c->pubpart->key = fndkey;
636     }
637 twoaday 133 /* XXX: this is also called for keys without a photo-id. */
638     keycache_reload_photo (ctx, keyid);
639 werner 36 }
640     else {
641     log_debug ("keycache add: sync public part\r\n");
642     if (is_sec)
643     gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);
644     gpg_keycache_add_key (ctx, key, (void **)&c);
645     if (c != NULL && is_sec) {
646     log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);
647     c->pubpart = c_new;
648     if (c_new != NULL) {
649     c->pubpart->key = fndkey;
650     c->gloflags.is_protected = c_new->gloflags.is_protected;
651     c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
652     }
653     }
654 twoaday 147 if (c)
655 twoaday 150 c->flags = KC_FLAG_ADD;
656 werner 36 }
657     return 0;
658     }
659    
660    
661     /* Delete a key from the cache @ctx with the pattern @pattern.
662     Return value: 0 on success. */
663     gpgme_error_t
664     gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)
665     {
666     struct keycache_s *itm = NULL, *c;
667     gpgme_key_t key;
668     gpgme_error_t rc;
669    
670     if (!ctx)
671     return gpg_error (GPG_ERR_INV_ARG);
672     rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
673     if (rc)
674     return rc;
675    
676     c = ctx->item;
677     if (c->next == NULL) {
678     gpgme_key_release (itm->key);
679 twoaday 187 safe_free (itm);
680 werner 36 ctx->item = NULL;
681     }
682     else {
683 twoaday 187 for (; c != NULL; c = c->next) {
684     if (c->next == itm)
685     break;
686     }
687     assert (c != NULL); /* XXX: sometimes access violation. */
688 werner 36 c->next = c->next->next;
689     gpgme_key_release (itm->key);
690 twoaday 187 safe_free (itm);
691 werner 36 }
692     return 0;
693     }
694    
695    
696     /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring
697     will be added to the cache. @secret is 1 if the source is the secret keyring.
698     Return value: 0 on success. */
699     gpgme_error_t
700     gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)
701     {
702     gpgme_error_t err;
703     gpgme_ctx_t c;
704     gpgme_key_t key;
705     int count = 0;
706    
707     if (!ctx)
708     return gpg_error (GPG_ERR_INV_ARG);
709    
710     err = gpgme_new (&c);
711     if (err)
712     return err;
713    
714     gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS);
715     err = gpgme_op_keylist_start (c, pattern, secret);
716     while(!err) {
717     err = gpgme_op_keylist_next (c, &key);
718     if (!err)
719     err = gpg_keycache_add_key (ctx, key, NULL);
720     if (ctx->cb)
721     ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,
722     count++, ctx->cb_value2);
723     }
724     if (gpgme_err_code (err) == GPG_ERR_EOF)
725     err = gpg_error (GPG_ERR_NO_ERROR);
726 twoaday 133 keycache_update_photos (ctx);
727 twoaday 205 keycache_decode_uids (ctx);
728 werner 36 /* XXX: make sure the progress dialog is closed. */
729     gpgme_op_keylist_end (c);
730     gpgme_release (c);
731     return err;
732     }
733    
734    
735     /* XXX: kludge to see if the key is stored on a card. */
736     static int
737     key_divert_to_card (gpgme_key_t key)
738     {
739     gpgme_subkey_t k;
740     int n=0, n_alg=0, can_auth = 0;
741    
742     for (k = key->subkeys; k; k = k->next) {
743     n++;
744     if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)
745     n_alg++;
746     if (k->can_authenticate)
747     can_auth++;
748     }
749     if (n == 3 && n_alg == 3 && can_auth == 1)
750     return 1;
751     return 0;
752     }
753    
754    
755 twoaday 123 static unsigned char*
756     copy_uid_prefs (const unsigned char *prefs)
757     {
758     unsigned char *p;
759     size_t pos=0;
760    
761     while (prefs[pos] != 0)
762     pos++;
763     p = (unsigned char*)calloc (1, pos+1);
764     if (!p)
765 twoaday 181 BUG (0);
766 twoaday 123 memcpy (p, prefs, pos);
767     return p;
768     }
769    
770    
771 werner 36 gpgme_error_t
772     gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
773     {
774     struct keycache_s *c, *c_sec;
775     gpgme_key_t key;
776    
777     if (!pub || !sec)
778     return gpg_error (GPG_ERR_INV_ARG);
779    
780     for (c=sec->item; c; c=c->next) {
781     if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
782     c_sec->gloflags.is_protected = c->gloflags.is_protected;
783     c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
784     if (!c->gloflags.divert_to_card)
785     c->gloflags.divert_to_card = key_divert_to_card (key);
786 twoaday 168 if (c_sec->sym_prefs)
787     c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
788 werner 36 c->pubpart = c_sec;
789     c->pubpart->key = key;
790     }
791     }
792     return 0;
793     }
794    
795    
796     /* Rewind the given cache @ctx to the begin. */
797     void
798     gpg_keycache_rewind (gpg_keycache_t ctx)
799     {
800     if (ctx)
801     ctx->pos = 0;
802     }
803    
804    
805    
806     /* Return the number of elements in the cache @ctx. */
807     int
808     gpg_keycache_get_size (gpg_keycache_t ctx)
809     {
810     struct keycache_s *c;
811     int count = 0;
812    
813     if (!ctx)
814     return 0;
815     for (c = ctx->item; c; c = c->next)
816     count++;
817     return count;
818     }
819    
820    
821     static gpgme_error_t
822     keycache_next_key (gpg_keycache_t ctx, int flags,
823     struct keycache_s **c, gpgme_key_t *r_key)
824     {
825     if (!ctx || !r_key)
826     return gpg_error (GPG_ERR_INV_ARG);
827    
828     if (!ctx->pos)
829     ctx->tmp = ctx->item;
830    
831     if (!ctx->tmp || !ctx->tmp->key) {
832     ctx->pos = 0;
833     *r_key = NULL;
834     return gpg_error (GPG_ERR_EOF);
835     }
836 twoaday 150 if (ctx->tmp->flags != 0)
837     ctx->tmp->flags = 0; /* reset the 'updated' status. */
838 twoaday 165 /* it might be possible there is no public key. */
839     if (flags && ctx->tmp->pubpart == NULL)
840     flags = 0;
841 werner 36 *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
842 twoaday 205 *c = ctx->tmp;
843     ctx->tmp = ctx->tmp->next;
844 werner 36 ctx->pos++;
845    
846     return 0;
847     }
848    
849    
850     /* Return the next key from the cache @ctx. The key will be returned
851     in @r_key. @flags can contain additional flags.
852     Return value: 0 on success. */
853     gpgme_error_t
854     gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
855     {
856     struct keycache_s *c=NULL;
857 twoaday 205 gpgme_error_t err;
858 werner 36
859     err = keycache_next_key (ctx, flags, &c, r_key);
860     return err;
861     }
862 twoaday 167
863 twoaday 205 gpgme_error_t
864     gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags,
865     struct keycache_s **c, gpgme_key_t *r_key)
866     {
867     return keycache_next_key (ctx, flags, c, r_key);
868     }
869 twoaday 181
870 twoaday 205
871 twoaday 167 /* Search for a key with the pattern @pattern and mark
872     this key as the default signing key if found.
873     Return value: 0 on success. */
874     gpgme_error_t
875     gpg_keycache_set_default_key (gpg_keycache_t ctx,
876     const char *pattern)
877     {
878     gpgme_error_t err;
879     gpgme_key_t key;
880     struct keycache_s *itm;
881    
882     err = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
883     if (err)
884     return err;
885    
886     if (itm)
887     itm->default_key = 1;
888     return 0;
889     }
890    
891     /* Return the default key from the cache. If no was
892     marked before, NULL is returned in @r_key.
893     Return value: 0 on success. */
894     gpgme_error_t
895     gpg_keycache_get_default_key (gpg_keycache_t ctx,
896     gpgme_key_t *r_key)
897     {
898     struct keycache_s *itm;
899    
900     *r_key = NULL;
901     for (itm = ctx->item; itm; itm = itm->next) {
902     if (itm->default_key) {
903     *r_key = itm->key;
904     break;
905     }
906     }
907     if (!*r_key)
908     return gpgme_error (GPG_ERR_NOT_FOUND);
909     return 0;
910     }
911    
912    
913 twoaday 181 static gpgme_error_t
914     decode_subpacket (const char *subpkt_data, int *type,
915     char **out, WORD *outlen)
916     {
917     char tmp[128], *p = tmp, *val;
918 twoaday 187 char *enc = NULL;
919 twoaday 181 size_t pos = 0, i=0;
920 twoaday 167
921 twoaday 181 /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
922     *outlen = 0;
923     *out = NULL;
924    
925     if (strncmp (subpkt_data, "spk:", 4))
926     return gpg_error (GPG_ERR_NO_DATA);
927    
928     strncpy (tmp, subpkt_data, 62);
929     val = strtok (tmp, ":");
930     while (val != NULL) {
931     switch (pos++) {
932     case 0:
933     break;
934    
935     case 1:
936     if (type)
937     *type = atoi (val);
938     break;
939    
940     case 2:
941     break;
942    
943     case 3:
944     *outlen = atoi (val);
945     break;
946    
947     case 4:
948     enc = strdup (val);
949     break;
950     }
951     val = strtok (NULL, ":");
952     }
953     if (!enc)
954     return gpg_error (GPG_ERR_NO_DATA);;
955     *out = (char*)calloc (1, strlen (enc)+1);
956 twoaday 188 if (!*out)
957     BUG (0);
958 twoaday 181 for (pos = 0; pos < strlen (enc); pos++) {
959     if (enc[pos] == '%' && enc[pos+1] == '%')
960     (*out)[i++] = '%';
961     else if (enc[pos] == '%') {
962 twoaday 188 char temp[3];
963     temp[0] = enc[++pos];
964     temp[1] = enc[++pos];
965     temp[2] = 0;
966     (*out)[i++] = (char)strtoul (temp, NULL, 16);
967 twoaday 181 }
968     else
969     (*out)[i++] = enc[pos];
970     }
971     (*out)[i] = 0;
972 twoaday 196 safe_free (enc);
973 twoaday 181 return 0;
974     }
975    
976    
977     /* If the attribute given in @attr is not set in the
978     key cache object, try to update it. */
979     gpgme_error_t
980     gpg_keycache_update_attr (struct keycache_s *item,
981     int attr, int force)
982     {
983     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
984     char *val = NULL;
985     WORD n = 0;
986    
987     switch (attr) {
988     case KC_ATTR_PREFSYM:
989     if (!force && item->sym_prefs)
990     break;
991     safe_free (item->sym_prefs);
992     err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
993     if (!err && val != NULL)
994     err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
995     break;
996    
997     case KC_ATTR_PREFKSERV:
998     if (!force && item->pref_keyserver)
999     break;
1000     safe_free (item->pref_keyserver);
1001     err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
1002     if (!err && val != NULL)
1003     err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
1004     break;
1005     }
1006     safe_free (val);
1007     return err;
1008     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26