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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 271 - (hide annotations)
Sun Nov 5 08:57:45 2006 UTC (18 years, 3 months ago) by twoaday
File size: 26328 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26