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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 217 - (hide annotations)
Mon May 22 14:21:39 2006 UTC (18 years, 9 months ago) by twoaday
File size: 25782 byte(s)
2005-05-20  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeyPropsDlg.cpp (keyprops_load_photo): avoid expensive
        process call when no photo is available.
        (keyprops_dlg_proc): avoid static data.
        * wptFileManager.cpp (fm_add_sig_stat): Free memory in case
        of on demand key requests.
        (show_verify_result): Likewise.
        (secret_key_available): Likewise.
        (fm_decrypt, fm_sign): Handle the new on demand key request
        mode and free all memory.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26