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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 340 - (hide annotations)
Sun Nov 27 13:15:07 2011 UTC (13 years, 3 months ago) by twoaday
File size: 26148 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26