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

Contents of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 187 - (show annotations)
Wed Mar 22 11:04:20 2006 UTC (18 years, 11 months ago) by twoaday
File size: 22321 byte(s)
2006-03-21  Timo Schulz  <ts@g10code.de>
 
        * wptUTF8.cpp (native_to_utf8): Use directly W32 API.
        (utf8_to_native): Likewise. Remove cp850 conversion.
        * wptKeyEditDlgs.cpp (do_find_userid): Correct UTF8 handling.
        * wptKeyManager.cpp (km_delete_keys): Do not reset 'with_seckey'
        flag.

Prepare new release...


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26