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

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 168 - (hide 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 werner 36 /* wptKeyCache.cpp- Caching for the pub- and the secring
2 twoaday 133 * Copyright (C) 2001-2006 Timo Schulz
3 werner 36 *
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 twoaday 121
21 werner 42 #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25 werner 36 #include <windows.h>
26     #include <stdio.h>
27     #include <string.h>
28     #include <malloc.h>
29     #include <ctype.h>
30     #include <assert.h>
31 twoaday 121 #include <gpgme.h>
32 werner 36
33     #include "wptKeyCache.h"
34     #include "openpgp.h"
35     #include "wptNLS.h"
36     #include "wptErrors.h"
37     #include "wptW32API.h"
38 twoaday 133 #include "wptGPG.h"
39 werner 36
40    
41 twoaday 133 /* 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 werner 36 {
55 twoaday 133 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 werner 36
123 twoaday 133
124 twoaday 164 /* 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 twoaday 133 static int
141     parse_attr_data (const char *keyid, attr_list_t *list)
142     {
143     gpgme_error_t err;
144     FILE *tmp;
145 twoaday 164 char *status, tmpnam[MAX_PATH+1];
146 twoaday 133 BYTE *data;
147     DWORD ndata;
148    
149     err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
150     if (err)
151     return err;
152    
153 twoaday 164 if (ndata > 0 && (tmp = w32_tmpfile (tmpnam, MAX_PATH)) != NULL) {
154 twoaday 133 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 twoaday 164 DeleteFile (tmpnam);
161 werner 36 }
162 twoaday 133 else
163     *list = NULL;
164    
165     safe_free (status);
166     safe_free (data);
167     return ndata;
168 werner 36 }
169    
170 twoaday 121
171 werner 36 /* 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 twoaday 133 PACKET *pkt;
177 werner 36 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 twoaday 133 if (!inp)
186 werner 36 return;
187 twoaday 133
188 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL);
189 twoaday 133 pkt = (PACKET*)calloc (1, sizeof *pkt);
190 werner 36 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 twoaday 133 /* 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 werner 36 /* 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 twoaday 69 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
264 werner 36 gpgme_key_t key = NULL;
265     gpg_iobuf_t inp;
266 twoaday 133 PACKET *pkt;
267 werner 36 struct keycache_s *c;
268     const byte *sym_prefs;
269 twoaday 133 char keyid[16+1];
270 werner 36 int key_seen = 0;
271 twoaday 65 size_t nsym =0;
272 werner 36
273     if (secring) {
274     parse_secring (ctx, kid, secring);
275 twoaday 133 if (!pubring)
276 werner 36 return 0;
277     }
278     inp = gpg_iobuf_open (pubring);
279 twoaday 133 if (!inp)
280 werner 36 return gpg_error (GPG_ERR_KEYRING_OPEN);
281 twoaday 123 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
282 werner 36
283 twoaday 133 pkt = (PACKET*)calloc (1, sizeof * pkt);
284 twoaday 123 gpg_init_packet (pkt);
285 werner 36 while (gpg_parse_packet (inp, pkt) != -1) {
286     if (pkt->pkttype == PKT_PUBLIC_KEY) {
287     strcpy (keyid, "");
288     key_seen = 1;
289     }
290    
291 twoaday 133 if (pkt->pkttype == PKT_SIGNATURE &&
292     pkt->pkt.signature->sig_class == 0x1F) {
293 werner 36 if (pkt->pkt.signature->numrevkeys == 0)
294     goto next;
295 twoaday 133 _snprintf (keyid, sizeof (keyid) -1, "%08X",
296     pkt->pkt.signature->keyid[1]);
297 werner 36 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 twoaday 133 sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
306     SIGSUBPKT_PREF_SYM, &nsym);
307     if (!sym_prefs)
308 werner 36 goto next;
309 twoaday 133 _snprintf (keyid, sizeof (keyid) - 1, "%08X",
310     pkt->pkt.signature->keyid[1]);
311 werner 36 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 twoaday 133 safe_free (c->sym_prefs);
383     safe_free (c->attrib.d);
384     safe_free (c->card_type);
385 werner 36 free (c);
386     }
387 twoaday 133 safe_free (ctx);
388 werner 36 }
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 twoaday 41 struct keycache_s *c, *n1;
415 werner 36
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 twoaday 133 }
493 werner 36
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 twoaday 133 /* 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 twoaday 147 /* Return the next key which was updated. Before it is
521     returned the update flag is cleared.
522 twoaday 150 @r_status is 1 for a new key and 2 for an updated key.
523 twoaday 147 Return value: 0 on success. */
524 werner 36 gpgme_error_t
525 twoaday 147 gpg_keycache_next_updated_key (gpg_keycache_t ctx,
526 twoaday 150 struct keycache_s **r_obj,
527     int *r_status)
528 twoaday 147 {
529     struct keycache_s *c;
530    
531     for (c = ctx->item; c; c = c->next) {
532 twoaday 150 if (c->flags != 0) {
533     *r_status = c->flags;
534 twoaday 147 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 werner 36 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 twoaday 150 gpgme_set_keylist_mode (gctx, GPGME_KEYLIST_MODE_SIGS);
558 werner 36 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 twoaday 150 c->flags = KC_FLAG_UPD;
568 werner 36 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 twoaday 133 /* XXX: this is also called for keys without a photo-id. */
574     keycache_reload_photo (ctx, keyid);
575 werner 36 }
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 twoaday 147 if (c)
591 twoaday 150 c->flags = KC_FLAG_ADD;
592 werner 36 }
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 twoaday 133 keycache_update_photos (ctx);
662 werner 36 /* 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 twoaday 123 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 werner 36 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 twoaday 168 if (c_sec->sym_prefs)
721     c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
722 werner 36 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 twoaday 150 if (ctx->tmp->flags != 0)
771     ctx->tmp->flags = 0; /* reset the 'updated' status. */
772 twoaday 165 /* it might be possible there is no public key. */
773     if (flags && ctx->tmp->pubpart == NULL)
774     flags = 0;
775 werner 36 *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 twoaday 167
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