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

Contents of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 175 - (show annotations)
Tue Feb 7 08:58:04 2006 UTC (19 years ago) by twoaday
File size: 20091 byte(s)
2006-02-04  Timo Schulz  <ts@g10code.de>
                                                                                                                            
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Check for
        at least one ultimately trusted key.
        * wptKeyManager.cpp (km_refresh_key_from_keyserver):
        Only check inet connection if we refresh all keys.
        * wptGPGUtil.cpp (gpg_extract_keys): New.
        * wptClipEncryptDlg.cpp (clip_encrypt_dlg_proc): Use textmode.
        * wptClipSignEncDlg.cpp (clip_signenc_dlg_proc): Likewise.
        * wptClipSignDlg.cpp (get_selected_key): New.
        (one_key_proc): Use it here.
        (count_useable_seckeys): New.
        * wptSigTreeDlg.cpp (sigtree_dlg_proc): New.
        * wptKeyEditDlgs.cpp (diff_time): Removed.
        (w32_mktime): New.
        (keyedit_addsubkey_dlg_proc): Use it here.
                                                                                                                            
2006-02-02  Timo Schulz  <ts@g10code.de>
                                                                                                                            
        * wptW32API.cpp (get_temp_name): New.
        * wptKeyserver.cpp (ldap_recvkey): Use it here.
        * wptKeyPropsDlg.cpp (get_photo_tmpname): Likewise.
        * wptGPGUtil.cpp (create_tempfile): Likewise.
        * wptImportList.cpp (implist_load): Likewise.
        * wptKeyCache.cpp (parse_attr_data): Likewise.
        (w32_tempfile): Removed.
        * wptGPGME.cpp (check_ultimate_trusted_key): New.
                                                                                                                            

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26