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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 214 - (hide annotations)
Sun May 14 18:40:36 2006 UTC (18 years, 9 months ago) by twoaday
File size: 24823 byte(s)
2006-05-14  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeyCache.cpp (gpg_keycache_update_attr): Parse
        preferred keyserver URL.
        * wptHTTP.cpp (extractHostInfo): Fix segv.
        * wptGPGUtil.cpp (gpg_find_key_subpacket): Ignore default
        gpg.conf.
        * wptKeyserverSearchDlg.cpp (search_hkp_keys): Do not
        assume an existing user id.
        * wptPassphraseCB.cpp (passphrase_cb): Automatic cancel
        if no passphrase is available.

(for complete list of changes, see Src/ChangeLog)

About to release 0.12.1


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26