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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 210 - (hide annotations)
Thu May 4 08:44:11 2006 UTC (18 years, 10 months ago) by twoaday
File size: 24611 byte(s)
2006-05-03  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeyCache.cpp (keycache_prepare2): Fix possible segv.
        Thanks to Mathias.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26