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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 256 - (hide annotations)
Sat Aug 5 10:31:06 2006 UTC (18 years, 6 months ago) by twoaday
File size: 26305 byte(s)
1.0.0pre3 release.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26