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

Contents of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 168 - (show annotations)
Fri Jan 27 10:08:10 2006 UTC (19 years, 1 month ago) by twoaday
File size: 20380 byte(s)
2006-01-27  Timo Schulz  <ts@g10code.de>
 
        * WinPT.cpp (WinMain): Set minimal list mode as default.
        * wptKeyCache.cpp (gpg_keycache_sync): Handle special v3 keys.
         

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26