Tizen 2.0 Release
[external/libgnutls26.git] / lib / opencdk / keydb.c
1 /* keydb.c - Key database routines
2  * Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Timo Schulz
6  *
7  * This file is part of OpenCDK.
8  *
9  * The OpenCDK library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <sys/stat.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33
34 #include "opencdk.h"
35 #include "main.h"
36 #include "packet.h"
37 #include "filters.h"
38 #include "stream.h"
39 #include "keydb.h"
40
41 #define KEYID_CMP(a, b) ((a[0]) == (b[0]) && (a[1]) == (b[1]))
42 #define KEYDB_CACHE_ENTRIES 8
43
44 static void keydb_cache_free (key_table_t cache);
45 static int classify_data (const byte * buf, size_t len);
46 static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk);
47
48 static char *
49 keydb_idx_mkname (const char *file)
50 {
51   static const char *fmt = "%s.idx";
52   char *fname;
53   size_t len = strlen (file) + strlen (fmt);
54
55   fname = cdk_calloc (1, len + 1);
56   if (!fname)
57     return NULL;
58   if (snprintf (fname, len, fmt, file) <= 0)
59     return NULL;
60   return fname;
61 }
62
63
64 /* This functions builds an index of the keyring into a separate file
65    with the name keyring.ext.idx. It contains the offset of all public-
66    and public subkeys. The format of the file is:
67    --------
68     4 octets offset of the packet
69     8 octets keyid
70    20 octets fingerprint
71    --------
72    We store the keyid and the fingerprint due to the fact we can't get
73    the keyid from a v3 fingerprint directly.
74 */
75 static cdk_error_t
76 keydb_idx_build (const char *file)
77 {
78   cdk_packet_t pkt;
79   cdk_stream_t inp, out = NULL;
80   byte buf[4 + 8 + KEY_FPR_LEN];
81   char *idx_name;
82   u32 keyid[2];
83   cdk_error_t rc;
84
85   if (!file)
86     {
87       gnutls_assert ();
88       return CDK_Inv_Value;
89     }
90
91   rc = cdk_stream_open (file, &inp);
92   if (rc)
93     {
94       gnutls_assert ();
95       return rc;
96     }
97
98   idx_name = keydb_idx_mkname (file);
99   if (!idx_name)
100     {
101       cdk_stream_close (inp);
102       gnutls_assert ();
103       return CDK_Out_Of_Core;
104     }
105   rc = cdk_stream_create (idx_name, &out);
106   cdk_free (idx_name);
107   if (rc)
108     {
109       cdk_stream_close (inp);
110       gnutls_assert ();
111       return rc;
112     }
113
114   cdk_pkt_new (&pkt);
115   while (!cdk_stream_eof (inp))
116     {
117       off_t pos = cdk_stream_tell (inp);
118
119       rc = cdk_pkt_read (inp, pkt);
120       if (rc)
121         {
122           _cdk_log_debug ("index build failed packet off=%lu\n", pos);
123           /* FIXME: The index is incomplete */
124           break;
125         }
126       if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
127           pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
128         {
129           _cdk_u32tobuf (pos, buf);
130           cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
131           _cdk_u32tobuf (keyid[0], buf + 4);
132           _cdk_u32tobuf (keyid[1], buf + 8);
133           cdk_pk_get_fingerprint (pkt->pkt.public_key, buf + 12);
134           cdk_stream_write (out, buf, 4 + 8 + KEY_FPR_LEN);
135         }
136       cdk_pkt_free (pkt);
137     }
138
139   cdk_pkt_release (pkt);
140
141   cdk_stream_close (out);
142   cdk_stream_close (inp);
143   gnutls_assert ();
144   return rc;
145 }
146
147
148 /**
149  * cdk_keydb_idx_rebuild:
150  * @hd: key database handle
151  *
152  * Rebuild the key index files for the given key database.
153  **/
154 cdk_error_t
155 cdk_keydb_idx_rebuild (cdk_keydb_hd_t db, cdk_keydb_search_t dbs)
156 {
157   struct stat stbuf;
158   char *tmp_idx_name;
159   cdk_error_t rc;
160   int err;
161
162   if (!db || !db->name || !dbs)
163     {
164       gnutls_assert ();
165       return CDK_Inv_Value;
166     }
167   if (db->secret)
168     return 0;
169
170   tmp_idx_name = keydb_idx_mkname (db->name);
171   if (!tmp_idx_name)
172     {
173       gnutls_assert ();
174       return CDK_Out_Of_Core;
175     }
176   err = stat (tmp_idx_name, &stbuf);
177   cdk_free (tmp_idx_name);
178   /* This function expects an existing index which can be rebuild,
179      if no index exists we do not build one and just return. */
180   if (err)
181     return 0;
182
183   cdk_stream_close (dbs->idx);
184   dbs->idx = NULL;
185   if (!dbs->idx_name)
186     {
187       dbs->idx_name = keydb_idx_mkname (db->name);
188       if (!dbs->idx_name)
189         {
190           gnutls_assert ();
191           return CDK_Out_Of_Core;
192         }
193     }
194   rc = keydb_idx_build (db->name);
195   if (!rc)
196     rc = cdk_stream_open (dbs->idx_name, &dbs->idx);
197   else
198     gnutls_assert ();
199   return rc;
200 }
201
202
203 static cdk_error_t
204 keydb_idx_parse (cdk_stream_t inp, key_idx_t * r_idx)
205 {
206   key_idx_t idx;
207   byte buf[4];
208
209   if (!inp || !r_idx)
210     {
211       gnutls_assert ();
212       return CDK_Inv_Value;
213     }
214
215   idx = cdk_calloc (1, sizeof *idx);
216   if (!idx)
217     {
218       gnutls_assert ();
219       return CDK_Out_Of_Core;
220     }
221
222   while (!cdk_stream_eof (inp))
223     {
224       if (cdk_stream_read (inp, buf, 4) == CDK_EOF)
225         break;
226       idx->offset = _cdk_buftou32 (buf);
227       cdk_stream_read (inp, buf, 4);
228       idx->keyid[0] = _cdk_buftou32 (buf);
229       cdk_stream_read (inp, buf, 4);
230       idx->keyid[1] = _cdk_buftou32 (buf);
231       cdk_stream_read (inp, idx->fpr, KEY_FPR_LEN);
232       break;
233     }
234   *r_idx = idx;
235   return cdk_stream_eof (inp) ? CDK_EOF : 0;
236 }
237
238
239 static cdk_error_t
240 keydb_idx_search (cdk_stream_t inp, u32 * keyid, const byte * fpr,
241                   off_t * r_off)
242 {
243   key_idx_t idx;
244
245   if (!inp || !r_off)
246     {
247       gnutls_assert ();
248       return CDK_Inv_Value;
249     }
250   if ((keyid && fpr) || (!keyid && !fpr))
251     {
252       gnutls_assert ();
253       return CDK_Inv_Mode;
254     }
255
256   /* We need an initialize the offset var with a value
257      because it might be possible the returned offset will
258      be 0 and then we cannot differ between the begin and an EOF. */
259   *r_off = 0xFFFFFFFF;
260   cdk_stream_seek (inp, 0);
261   while (keydb_idx_parse (inp, &idx) != CDK_EOF)
262     {
263       if (keyid && KEYID_CMP (keyid, idx->keyid))
264         {
265           *r_off = idx->offset;
266           break;
267         }
268       else if (fpr && !memcmp (idx->fpr, fpr, KEY_FPR_LEN))
269         {
270           *r_off = idx->offset;
271           break;
272         }
273       cdk_free (idx);
274       idx = NULL;
275     }
276   cdk_free (idx);
277   return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF;
278 }
279
280
281 /**
282  * cdk_keydb_new_from_mem:
283  * @r_hd: The keydb output handle.
284  * @data: The raw key data.
285  * @datlen: The length of the raw data.
286  * 
287  * Create a new keyring db handle from the contents of a buffer.
288  */
289 cdk_error_t
290 cdk_keydb_new_from_mem (cdk_keydb_hd_t * r_db, int secret,
291                         const void *data, size_t datlen)
292 {
293   cdk_keydb_hd_t db;
294   cdk_error_t rc;
295
296   if (!r_db)
297     {
298       gnutls_assert ();
299       return CDK_Inv_Value;
300     }
301   *r_db = NULL;
302   db = calloc (1, sizeof *db);
303   rc = cdk_stream_tmp_from_mem (data, datlen, &db->fp);
304   if (!db->fp)
305     {
306       cdk_free (db);
307       gnutls_assert ();
308       return rc;
309     }
310   if (cdk_armor_filter_use (db->fp))
311     cdk_stream_set_armor_flag (db->fp, 0);
312   db->type = CDK_DBTYPE_DATA;
313   db->secret = secret;
314   *r_db = db;
315   return 0;
316 }
317
318
319 /**
320  * cdk_keydb_new_from_stream:
321  * @r_hd: the output keydb handle
322  * @secret: does the stream contain secret key data
323  * @in: the input stream to use
324  * 
325  * This function creates a new keydb handle based on the given
326  * stream. The stream is not closed in cdk_keydb_free() and it
327  * is up to the caller to close it. No decoding is done.
328  */
329 cdk_error_t
330 cdk_keydb_new_from_stream (cdk_keydb_hd_t * r_hd, int secret, cdk_stream_t in)
331 {
332   cdk_keydb_hd_t hd;
333
334   if (!r_hd)
335     {
336       gnutls_assert ();
337       return CDK_Inv_Value;
338     }
339   *r_hd = NULL;
340
341   hd = calloc (1, sizeof *hd);
342   hd->fp = in;
343   hd->fp_ref = 1;
344   hd->type = CDK_DBTYPE_STREAM;
345   hd->secret = secret;
346   *r_hd = hd;
347
348   /* We do not push any filters and thus we expect that the format
349      of the stream has the format the user wanted. */
350
351   return 0;
352 }
353
354
355 cdk_error_t
356 cdk_keydb_new_from_file (cdk_keydb_hd_t * r_hd, int secret, const char *fname)
357 {
358   cdk_keydb_hd_t hd;
359
360   if (!r_hd)
361     {
362       gnutls_assert ();
363       return CDK_Inv_Value;
364     }
365   *r_hd = NULL;
366   hd = calloc (1, sizeof *hd);
367   hd->name = cdk_strdup (fname);
368   if (!hd->name)
369     {
370       cdk_free (hd);
371       gnutls_assert ();
372       return CDK_Out_Of_Core;
373     }
374   hd->type = secret ? CDK_DBTYPE_SK_KEYRING : CDK_DBTYPE_PK_KEYRING;
375   hd->secret = secret;
376   *r_hd = hd;
377   return 0;
378 }
379
380
381
382 /**
383  * cdk_keydb_new:
384  * @r_hd: handle to store the new keydb object
385  * @type: type of the keyring
386  * @data: data which depends on the keyring type
387  * @count: length of the data
388  *
389  * Create a new keydb object
390  **/
391 cdk_error_t
392 cdk_keydb_new (cdk_keydb_hd_t * r_hd, int type, void *data, size_t count)
393 {
394   switch (type)
395     {
396     case CDK_DBTYPE_PK_KEYRING:
397     case CDK_DBTYPE_SK_KEYRING:
398       return cdk_keydb_new_from_file (r_hd, type == CDK_DBTYPE_SK_KEYRING,
399                                       (const char *) data);
400
401     case CDK_DBTYPE_DATA:
402       return cdk_keydb_new_from_mem (r_hd, 0, data, count);
403
404     case CDK_DBTYPE_STREAM:
405       return cdk_keydb_new_from_stream (r_hd, 0, (cdk_stream_t) data);
406
407     default:
408       gnutls_assert ();
409       return CDK_Inv_Mode;
410     }
411   gnutls_assert ();
412   return CDK_Inv_Mode;
413 }
414
415
416 /**
417  * cdk_keydb_free:
418  * @hd: the keydb object
419  *
420  * Free the keydb object.
421  **/
422 void
423 cdk_keydb_free (cdk_keydb_hd_t hd)
424 {
425   if (!hd)
426     return;
427
428   if (hd->name)
429     {
430       cdk_free (hd->name);
431       hd->name = NULL;
432     }
433
434   if (hd->fp && !hd->fp_ref)
435     {
436       cdk_stream_close (hd->fp);
437       hd->fp = NULL;
438     }
439
440
441   hd->isopen = 0;
442   hd->secret = 0;
443   cdk_free (hd);
444 }
445
446
447 static cdk_error_t
448 _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t * ret_kr)
449 {
450   cdk_error_t rc;
451   cdk_stream_t kr;
452
453   if (!hd || !ret_kr)
454     {
455       gnutls_assert ();
456       return CDK_Inv_Value;
457     }
458
459   rc = 0;
460   if ((hd->type == CDK_DBTYPE_DATA || hd->type == CDK_DBTYPE_STREAM)
461       && hd->fp)
462     {
463       kr = hd->fp;
464       cdk_stream_seek (kr, 0);
465     }
466   else if (hd->type == CDK_DBTYPE_PK_KEYRING ||
467            hd->type == CDK_DBTYPE_SK_KEYRING)
468     {
469       rc = cdk_stream_open (hd->name, &kr);
470
471       if (rc)
472         goto leave;
473
474       if (cdk_armor_filter_use (kr))
475         cdk_stream_set_armor_flag (kr, 0);
476     }
477   else
478     {
479       gnutls_assert ();
480       return CDK_Inv_Mode;
481     }
482
483 leave:
484
485   *ret_kr = kr;
486   return rc;
487 }
488
489
490 static int
491 find_by_keyid (cdk_kbnode_t knode, cdk_keydb_search_t ks)
492 {
493   cdk_kbnode_t node;
494   u32 keyid[2];
495
496   for (node = knode; node; node = node->next)
497     {
498       if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
499           node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
500           node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
501           node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
502         {
503           _cdk_pkt_get_keyid (node->pkt, keyid);
504           switch (ks->type)
505             {
506             case CDK_DBSEARCH_SHORT_KEYID:
507               if (keyid[1] == ks->u.keyid[1])
508                 return 1;
509               break;
510
511             case CDK_DBSEARCH_KEYID:
512               if (KEYID_CMP (keyid, ks->u.keyid))
513                 return 1;
514               break;
515
516             default:
517               _cdk_log_debug ("find_by_keyid: invalid mode = %d\n", ks->type);
518               return 0;
519             }
520         }
521     }
522   return 0;
523 }
524
525
526 static int
527 find_by_fpr (cdk_kbnode_t knode, cdk_keydb_search_t ks)
528 {
529   cdk_kbnode_t node;
530   byte fpr[KEY_FPR_LEN];
531
532   if (ks->type != CDK_DBSEARCH_FPR)
533     return 0;
534
535   for (node = knode; node; node = node->next)
536     {
537       if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
538           node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
539           node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
540           node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
541         {
542           _cdk_pkt_get_fingerprint (node->pkt, fpr);
543           if (!memcmp (ks->u.fpr, fpr, KEY_FPR_LEN))
544             return 1;
545           break;
546         }
547     }
548
549   return 0;
550 }
551
552
553 static int
554 find_by_pattern (cdk_kbnode_t knode, cdk_keydb_search_t ks)
555 {
556   cdk_kbnode_t node;
557   size_t uidlen;
558   char *name;
559
560   for (node = knode; node; node = node->next)
561     {
562       if (node->pkt->pkttype != CDK_PKT_USER_ID)
563         continue;
564       if (node->pkt->pkt.user_id->attrib_img != NULL)
565         continue;               /* Skip attribute packets. */
566       uidlen = node->pkt->pkt.user_id->len;
567       name = node->pkt->pkt.user_id->name;
568       switch (ks->type)
569         {
570         case CDK_DBSEARCH_EXACT:
571           if (name &&
572               (strlen (ks->u.pattern) == uidlen &&
573                !strncmp (ks->u.pattern, name, uidlen)))
574             return 1;
575           break;
576
577         case CDK_DBSEARCH_SUBSTR:
578           if (uidlen > 65536)
579             break;
580           if (name && strlen (ks->u.pattern) > uidlen)
581             break;
582           if (name && _cdk_memistr (name, uidlen, ks->u.pattern))
583             return 1;
584           break;
585
586         default:               /* Invalid mode */
587           return 0;
588         }
589     }
590   return 0;
591 }
592
593
594 static void
595 keydb_cache_free (key_table_t cache)
596 {
597   key_table_t c2;
598
599   while (cache)
600     {
601       c2 = cache->next;
602       cache->offset = 0;
603       cdk_free (cache);
604       cache = c2;
605     }
606 }
607
608
609 static key_table_t
610 keydb_cache_find (cdk_keydb_search_t desc)
611 {
612   key_table_t cache = desc->cache;
613   key_table_t t;
614
615   for (t = cache; t; t = t->next)
616     {
617       switch (desc->type)
618         {
619         case CDK_DBSEARCH_SHORT_KEYID:
620         case CDK_DBSEARCH_KEYID:
621           if (KEYID_CMP (desc->u.keyid, desc->u.keyid))
622             return t;
623           break;
624
625         case CDK_DBSEARCH_EXACT:
626           if (strlen (desc->u.pattern) == strlen (desc->u.pattern) &&
627               !strcmp (desc->u.pattern, desc->u.pattern))
628             return t;
629           break;
630
631         case CDK_DBSEARCH_SUBSTR:
632           if (strstr (desc->u.pattern, desc->u.pattern))
633             return t;
634           break;
635
636         case CDK_DBSEARCH_FPR:
637           if (!memcmp (desc->u.fpr, desc->u.fpr, KEY_FPR_LEN))
638             return t;
639           break;
640         }
641     }
642
643   return NULL;
644 }
645
646
647 static cdk_error_t
648 keydb_cache_add (cdk_keydb_search_t dbs, off_t offset)
649 {
650   key_table_t k;
651
652   if (dbs->ncache > KEYDB_CACHE_ENTRIES)
653     return 0;                   /* FIXME: we should replace the last entry. */
654   k = cdk_calloc (1, sizeof *k);
655   if (!k)
656     {
657       gnutls_assert ();
658       return CDK_Out_Of_Core;
659     }
660
661   k->offset = offset;
662
663   k->next = dbs->cache;
664   dbs->cache = k;
665   dbs->ncache++;
666   _cdk_log_debug ("cache: add entry off=%d type=%d\n", (int) offset,
667                   (int) dbs->type);
668   return 0;
669 }
670
671 static cdk_error_t
672 idx_init (cdk_keydb_hd_t db, cdk_keydb_search_t dbs)
673 {
674   cdk_error_t ec, rc = 0;
675
676   if (cdk_stream_get_length (db->fp) < 524288)
677     {
678       dbs->no_cache = 1;
679       goto leave;
680     }
681
682   dbs->idx_name = keydb_idx_mkname (db->name);
683   if (!dbs->idx_name)
684     {
685       rc = CDK_Out_Of_Core;
686       goto leave;
687     }
688   ec = cdk_stream_open (dbs->idx_name, &dbs->idx);
689
690   if (ec && !db->secret)
691     {
692       rc = keydb_idx_build (db->name);
693       if (!rc)
694         rc = cdk_stream_open (dbs->idx_name, &dbs->idx);
695       if (!rc)
696         {
697           _cdk_log_debug ("create key index table\n");
698         }
699       else
700         {
701           /* This is no real error, it just means we can't create
702              the index at the given directory. maybe we've no write
703              access. in this case, we simply disable the index. */
704           _cdk_log_debug ("disable key index table err=%d\n", rc);
705           rc = 0;
706           dbs->no_cache = 1;
707         }
708     }
709
710 leave:
711
712   return rc;
713 }
714
715 /**
716  * cdk_keydb_search_start:
717  * @st: search handle
718  * @db: key database handle
719  * @type: specifies the search type
720  * @desc: description which depends on the type
721  *
722  * Create a new keydb search object.
723  **/
724 cdk_error_t
725 cdk_keydb_search_start (cdk_keydb_search_t * st, cdk_keydb_hd_t db, int type,
726                         void *desc)
727 {
728   u32 *keyid;
729   char *p, tmp[3];
730   int i;
731   cdk_error_t rc;
732
733   if (!db)
734     {
735       gnutls_assert ();
736       return CDK_Inv_Value;
737     }
738   if (type != CDK_DBSEARCH_NEXT && !desc)
739     {
740       gnutls_assert ();
741       return CDK_Inv_Mode;
742     }
743
744   *st = cdk_calloc (1, sizeof (cdk_keydb_search_s));
745   if (!(*st))
746     {
747       gnutls_assert ();
748       return CDK_Out_Of_Core;
749     }
750
751   rc = idx_init (db, *st);
752   if (rc != CDK_Success)
753     {
754       free (*st);
755       gnutls_assert ();
756       return rc;
757     }
758
759   (*st)->type = type;
760   switch (type)
761     {
762     case CDK_DBSEARCH_EXACT:
763     case CDK_DBSEARCH_SUBSTR:
764       cdk_free ((*st)->u.pattern);
765       (*st)->u.pattern = cdk_strdup (desc);
766       if (!(*st)->u.pattern)
767         {
768           cdk_free (*st);
769           gnutls_assert ();
770           return CDK_Out_Of_Core;
771         }
772       break;
773
774     case CDK_DBSEARCH_SHORT_KEYID:
775       keyid = desc;
776       (*st)->u.keyid[1] = keyid[0];
777       break;
778
779     case CDK_DBSEARCH_KEYID:
780       keyid = desc;
781       (*st)->u.keyid[0] = keyid[0];
782       (*st)->u.keyid[1] = keyid[1];
783       break;
784
785     case CDK_DBSEARCH_FPR:
786       memcpy ((*st)->u.fpr, desc, KEY_FPR_LEN);
787       break;
788
789     case CDK_DBSEARCH_NEXT:
790       break;
791
792     case CDK_DBSEARCH_AUTO:
793       /* Override the type with the actual db search type. */
794       (*st)->type = classify_data (desc, strlen (desc));
795       switch ((*st)->type)
796         {
797         case CDK_DBSEARCH_SUBSTR:
798         case CDK_DBSEARCH_EXACT:
799           cdk_free ((*st)->u.pattern);
800           p = (*st)->u.pattern = cdk_strdup (desc);
801           if (!p)
802             {
803               cdk_free (*st);
804               gnutls_assert ();
805               return CDK_Out_Of_Core;
806             }
807           break;
808
809         case CDK_DBSEARCH_SHORT_KEYID:
810         case CDK_DBSEARCH_KEYID:
811           p = desc;
812           if (!strncmp (p, "0x", 2))
813             p += 2;
814           if (strlen (p) == 8)
815             {
816               (*st)->u.keyid[0] = 0;
817               (*st)->u.keyid[1] = strtoul (p, NULL, 16);
818             }
819           else if (strlen (p) == 16)
820             {
821               (*st)->u.keyid[0] = strtoul (p, NULL, 16);
822               (*st)->u.keyid[1] = strtoul (p + 8, NULL, 16);
823             }
824           else
825             {                   /* Invalid key ID object. */
826               cdk_free (*st);
827               gnutls_assert ();
828               return CDK_Inv_Mode;
829             }
830           break;
831
832         case CDK_DBSEARCH_FPR:
833           p = desc;
834           if (strlen (p) != 2 * KEY_FPR_LEN)
835             {
836               cdk_free (*st);
837               gnutls_assert ();
838               return CDK_Inv_Mode;
839             }
840           for (i = 0; i < KEY_FPR_LEN; i++)
841             {
842               tmp[0] = p[2 * i];
843               tmp[1] = p[2 * i + 1];
844               tmp[2] = 0x00;
845               (*st)->u.fpr[i] = strtoul (tmp, NULL, 16);
846             }
847           break;
848         }
849       break;
850
851     default:
852       cdk_free (*st);
853       _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type);
854       gnutls_assert ();
855       return CDK_Inv_Mode;
856     }
857
858   return 0;
859 }
860
861
862 static cdk_error_t
863 keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_keydb_search_t ks,
864                       int *r_cache_hit, off_t * r_off)
865 {
866   key_table_t c;
867
868   if (!hd || !r_cache_hit || !r_off)
869     {
870       gnutls_assert ();
871       return CDK_Inv_Value;
872     }
873
874   /* Reset the values. */
875   *r_cache_hit = 0;
876   *r_off = 0;
877
878   c = keydb_cache_find (ks);
879   if (c != NULL)
880     {
881       _cdk_log_debug ("cache: found entry in cache.\n");
882       *r_cache_hit = 1;
883       *r_off = c->offset;
884       return 0;
885     }
886
887   /* No index cache available so we just return here. */
888   if (!ks->idx)
889     return 0;
890
891   if (ks->idx)
892     {
893       if (ks->type == CDK_DBSEARCH_KEYID)
894         {
895           if (keydb_idx_search (ks->idx, ks->u.keyid, NULL, r_off))
896             {
897               gnutls_assert ();
898               return CDK_Error_No_Key;
899             }
900           _cdk_log_debug ("cache: found keyid entry in idx table.\n");
901           *r_cache_hit = 1;
902         }
903       else if (ks->type == CDK_DBSEARCH_FPR)
904         {
905           if (keydb_idx_search (ks->idx, NULL, ks->u.fpr, r_off))
906             {
907               gnutls_assert ();
908               return CDK_Error_No_Key;
909             }
910           _cdk_log_debug ("cache: found fpr entry in idx table.\n");
911           *r_cache_hit = 1;
912         }
913     }
914
915   return 0;
916 }
917
918 void
919 cdk_keydb_search_release (cdk_keydb_search_t st)
920 {
921   keydb_cache_free (st->cache);
922
923   if (st->idx)
924     cdk_stream_close (st->idx);
925
926   if (!st)
927     return;
928   if (st->type == CDK_DBSEARCH_EXACT || st->type == CDK_DBSEARCH_SUBSTR)
929     cdk_free (st->u.pattern);
930
931   cdk_free (st);
932 }
933
934 /**
935  * cdk_keydb_search:
936  * @st: the search handle
937  * @hd: the keydb object
938  * @ret_key: kbnode object to store the key
939  *
940  * Search for a key in the given keyring. The search mode is handled
941  * via @ks. If the key was found, @ret_key contains the key data.
942  **/
943 cdk_error_t
944 cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd,
945                   cdk_kbnode_t * ret_key)
946 {
947   cdk_stream_t kr;
948   cdk_kbnode_t knode;
949   cdk_error_t rc = 0;
950   off_t pos = 0, off = 0;
951   int key_found = 0, cache_hit = 0;
952
953   if (!hd || !ret_key || !st)
954     {
955       gnutls_assert ();
956       return CDK_Inv_Value;
957     }
958
959   *ret_key = NULL;
960   kr = NULL;
961
962   rc = _cdk_keydb_open (hd, &kr);
963   if (rc)
964     {
965       gnutls_assert ();
966       return rc;
967     }
968
969   if (!st->no_cache)
970     {
971       /* It is possible the index is not up-to-date and thus we do
972          not find the requesed key. In this case, we reset cache hit
973          and continue our normal search procedure. */
974       rc = keydb_pos_from_cache (hd, st, &cache_hit, &off);
975       if (rc)
976         cache_hit = 0;
977     }
978
979   knode = NULL;
980
981   while (!key_found && !rc)
982     {
983       if (cache_hit && st->type != CDK_DBSEARCH_NEXT)
984         cdk_stream_seek (kr, off);
985       else if (st->type == CDK_DBSEARCH_NEXT)
986         cdk_stream_seek (kr, st->off);
987
988       pos = cdk_stream_tell (kr);
989
990       rc = cdk_keydb_get_keyblock (kr, &knode);
991
992       if (rc)
993         {
994           if (rc == CDK_EOF)
995             break;
996           else
997             {
998               gnutls_assert ();
999               return rc;
1000             }
1001         }
1002
1003       switch (st->type)
1004         {
1005         case CDK_DBSEARCH_SHORT_KEYID:
1006         case CDK_DBSEARCH_KEYID:
1007           key_found = find_by_keyid (knode, st);
1008           break;
1009
1010         case CDK_DBSEARCH_FPR:
1011           key_found = find_by_fpr (knode, st);
1012           break;
1013
1014         case CDK_DBSEARCH_EXACT:
1015         case CDK_DBSEARCH_SUBSTR:
1016           key_found = find_by_pattern (knode, st);
1017           break;
1018
1019         case CDK_DBSEARCH_NEXT:
1020           st->off = cdk_stream_tell (kr);
1021           key_found = knode ? 1 : 0;
1022           break;
1023         }
1024
1025       if (key_found)
1026         {
1027           if (!keydb_cache_find (st))
1028             keydb_cache_add (st, pos);
1029           break;
1030         }
1031
1032       cdk_kbnode_release (knode);
1033       knode = NULL;
1034     }
1035
1036   if (key_found && rc == CDK_EOF)
1037     rc = 0;
1038   else if (rc == CDK_EOF && !key_found)
1039     {
1040       gnutls_assert ();
1041       rc = CDK_Error_No_Key;
1042     }
1043   *ret_key = key_found ? knode : NULL;
1044   return rc;
1045 }
1046
1047 cdk_error_t
1048 cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, u32 * keyid, cdk_kbnode_t * ret_key)
1049 {
1050   cdk_error_t rc;
1051   cdk_keydb_search_t st;
1052
1053   if (!hd || !keyid || !ret_key)
1054     {
1055       gnutls_assert ();
1056       return CDK_Inv_Value;
1057     }
1058
1059   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
1060   if (!rc)
1061     rc = cdk_keydb_search (st, hd, ret_key);
1062
1063   cdk_keydb_search_release (st);
1064   return rc;
1065 }
1066
1067
1068 cdk_error_t
1069 cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const byte * fpr,
1070                      cdk_kbnode_t * r_key)
1071 {
1072   cdk_error_t rc;
1073   cdk_keydb_search_t st;
1074
1075   if (!hd || !fpr || !r_key)
1076     {
1077       gnutls_assert ();
1078       return CDK_Inv_Value;
1079     }
1080
1081   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_FPR, (byte *) fpr);
1082   if (!rc)
1083     rc = cdk_keydb_search (st, hd, r_key);
1084
1085   cdk_keydb_search_release (st);
1086   return rc;
1087 }
1088
1089
1090 cdk_error_t
1091 cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt,
1092                          cdk_kbnode_t * ret_key)
1093 {
1094   cdk_error_t rc;
1095   cdk_keydb_search_t st;
1096
1097   if (!hd || !patt || !ret_key)
1098     {
1099       gnutls_assert ();
1100       return CDK_Inv_Value;
1101     }
1102
1103   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_SUBSTR, (char *) patt);
1104   if (!rc)
1105     rc = cdk_keydb_search (st, hd, ret_key);
1106
1107   if (rc)
1108     gnutls_assert ();
1109
1110   cdk_keydb_search_release (st);
1111   return rc;
1112 }
1113
1114
1115 static int
1116 keydb_check_key (cdk_packet_t pkt)
1117 {
1118   cdk_pkt_pubkey_t pk;
1119   int is_sk, valid;
1120
1121   if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1122       pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1123     {
1124       pk = pkt->pkt.public_key;
1125       is_sk = 0;
1126     }
1127   else if (pkt->pkttype == CDK_PKT_SECRET_KEY ||
1128            pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1129     {
1130       pk = pkt->pkt.secret_key->pk;
1131       is_sk = 1;
1132     }
1133   else                          /* No key object. */
1134     return 0;
1135   valid = !pk->is_revoked && !pk->has_expired;
1136   if (is_sk)
1137     return valid;
1138   return valid && !pk->is_invalid;
1139 }
1140
1141
1142 /* Find the first kbnode with the requested packet type
1143    that represents a valid key. */
1144 static cdk_kbnode_t
1145 kbnode_find_valid (cdk_kbnode_t root, cdk_packet_type_t pkttype)
1146 {
1147   cdk_kbnode_t n;
1148
1149   for (n = root; n; n = n->next)
1150     {
1151       if (n->pkt->pkttype != pkttype)
1152         continue;
1153       if (keydb_check_key (n->pkt))
1154         return n;
1155     }
1156
1157   return NULL;
1158 }
1159
1160
1161 static cdk_kbnode_t
1162 keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk)
1163 {
1164   cdk_kbnode_t node, key;
1165   int req_type;
1166   long timestamp;
1167
1168   req_type = is_pk ? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY;
1169   if (!req_usage)
1170     return kbnode_find_valid (root, req_type);
1171
1172   node = cdk_kbnode_find (root, req_type);
1173   if (node && !keydb_check_key (node->pkt))
1174     return NULL;
1175
1176   key = NULL;
1177   timestamp = 0;
1178   /* We iteratre over the all nodes and search for keys or
1179      subkeys which match the usage and which are not invalid.
1180      A timestamp is used to figure out the newest valid key. */
1181   for (node = root; node; node = node->next)
1182     {
1183       if (is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1184                     node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1185           && keydb_check_key (node->pkt)
1186           && (node->pkt->pkt.public_key->pubkey_usage & req_usage))
1187         {
1188           if (node->pkt->pkt.public_key->timestamp > timestamp)
1189             key = node;
1190         }
1191       if (!is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
1192                      node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1193           && keydb_check_key (node->pkt)
1194           && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage))
1195         {
1196           if (node->pkt->pkt.secret_key->pk->timestamp > timestamp)
1197             key = node;
1198         }
1199
1200     }
1201   return key;
1202 }
1203
1204
1205 static cdk_kbnode_t
1206 keydb_find_bykeyid (cdk_kbnode_t root, const u32 * keyid, int search_mode)
1207 {
1208   cdk_kbnode_t node;
1209   u32 kid[2];
1210
1211   for (node = root; node; node = node->next)
1212     {
1213       if (!_cdk_pkt_get_keyid (node->pkt, kid))
1214         continue;
1215       if (search_mode == CDK_DBSEARCH_SHORT_KEYID && kid[1] == keyid[1])
1216         return node;
1217       else if (kid[0] == keyid[0] && kid[1] == keyid[1])
1218         return node;
1219     }
1220   return NULL;
1221 }
1222
1223
1224 cdk_error_t
1225 _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
1226                            cdk_seckey_t * ret_sk, int usage)
1227 {
1228   cdk_kbnode_t knode = NULL;
1229   cdk_kbnode_t node, sk_node, pk_node;
1230   cdk_pkt_seckey_t sk;
1231   cdk_error_t rc;
1232   const char *s;
1233   int pkttype;
1234   cdk_keydb_search_t st;
1235
1236   if (!ret_sk || !usage)
1237     {
1238       gnutls_assert ();
1239       return CDK_Inv_Value;
1240     }
1241
1242   if (!hd)
1243     {
1244       gnutls_assert ();
1245       return CDK_Error_No_Keyring;
1246     }
1247
1248   *ret_sk = NULL;
1249   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name);
1250   if (rc)
1251     {
1252       gnutls_assert ();
1253       return rc;
1254     }
1255
1256   rc = cdk_keydb_search (st, hd, &knode);
1257   if (rc)
1258     {
1259       gnutls_assert ();
1260       return rc;
1261     }
1262
1263   cdk_keydb_search_release (st);
1264
1265   sk_node = keydb_find_byusage (knode, usage, 0);
1266   if (!sk_node)
1267     {
1268       cdk_kbnode_release (knode);
1269       gnutls_assert ();
1270       return CDK_Unusable_Key;
1271     }
1272
1273   /* We clone the node with the secret key to avoid that the
1274      packet will be released. */
1275   _cdk_kbnode_clone (sk_node);
1276   sk = sk_node->pkt->pkt.secret_key;
1277
1278   for (node = knode; node; node = node->next)
1279     {
1280       if (node->pkt->pkttype == CDK_PKT_USER_ID)
1281         {
1282           s = node->pkt->pkt.user_id->name;
1283           if (sk && !sk->pk->uid && _cdk_memistr (s, strlen (s), name))
1284             {
1285               _cdk_copy_userid (&sk->pk->uid, node->pkt->pkt.user_id);
1286               break;
1287             }
1288         }
1289     }
1290
1291   /* To find the self signature, we need the primary public key because
1292      the selected secret key might be different from the primary key. */
1293   pk_node = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
1294   if (!pk_node)
1295     {
1296       cdk_kbnode_release (knode);
1297       gnutls_assert ();
1298       return CDK_Unusable_Key;
1299     }
1300   node = find_selfsig_node (knode, pk_node->pkt->pkt.secret_key->pk);
1301   if (sk->pk->uid && node)
1302     _cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature);
1303
1304   /* We only release the outer packet. */
1305   _cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void *) &sk);
1306   cdk_kbnode_release (knode);
1307   *ret_sk = sk;
1308   return rc;
1309 }
1310
1311
1312 cdk_error_t
1313 _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
1314                            cdk_pubkey_t * ret_pk, int usage)
1315 {
1316   cdk_kbnode_t knode, node, pk_node;
1317   cdk_pkt_pubkey_t pk;
1318   const char *s;
1319   cdk_error_t rc;
1320   cdk_keydb_search_t st;
1321
1322   if (!ret_pk || !usage)
1323     {
1324       gnutls_assert ();
1325       return CDK_Inv_Value;
1326     }
1327   if (!hd)
1328     {
1329       gnutls_assert ();
1330       return CDK_Error_No_Keyring;
1331     }
1332
1333   *ret_pk = NULL;
1334   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name);
1335   if (!rc)
1336     rc = cdk_keydb_search (st, hd, &knode);
1337   if (rc)
1338     {
1339       gnutls_assert ();
1340       return rc;
1341     }
1342
1343   cdk_keydb_search_release (st);
1344
1345   node = keydb_find_byusage (knode, usage, 1);
1346   if (!node)
1347     {
1348       cdk_kbnode_release (knode);
1349       gnutls_assert ();
1350       return CDK_Unusable_Key;
1351     }
1352
1353   pk = NULL;
1354   _cdk_copy_pubkey (&pk, node->pkt->pkt.public_key);
1355   for (node = knode; node; node = node->next)
1356     {
1357       if (node->pkt->pkttype == CDK_PKT_USER_ID)
1358         {
1359           s = node->pkt->pkt.user_id->name;
1360           if (pk && !pk->uid && _cdk_memistr (s, strlen (s), name))
1361             {
1362               _cdk_copy_userid (&pk->uid, node->pkt->pkt.user_id);
1363               break;
1364             }
1365         }
1366     }
1367
1368   /* Same as in the sk code, the selected key can be a sub key 
1369      and thus we need the primary key to find the self sig. */
1370   pk_node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1371   if (!pk_node)
1372     {
1373       cdk_kbnode_release (knode);
1374       gnutls_assert ();
1375       return CDK_Unusable_Key;
1376     }
1377   node = find_selfsig_node (knode, pk_node->pkt->pkt.public_key);
1378   if (pk->uid && node)
1379     _cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature);
1380   cdk_kbnode_release (knode);
1381
1382   *ret_pk = pk;
1383   return rc;
1384 }
1385
1386
1387 /**
1388  * cdk_keydb_get_pk:
1389  * @hd: key db handle
1390  * @keyid: keyid of the key
1391  * @r_pk: the allocated public key
1392  * 
1393  * Perform a key database search by keyid and return the raw public
1394  * key without any signatures or user id's.
1395  **/
1396 cdk_error_t
1397 cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 * keyid, cdk_pubkey_t * r_pk)
1398 {
1399   cdk_kbnode_t knode = NULL, node;
1400   cdk_pubkey_t pk;
1401   cdk_error_t rc;
1402   size_t s_type;
1403   int pkttype;
1404   cdk_keydb_search_t st;
1405
1406   if (!keyid || !r_pk)
1407     {
1408       gnutls_assert ();
1409       return CDK_Inv_Value;
1410     }
1411   if (!hd)
1412     {
1413       gnutls_assert ();
1414       return CDK_Error_No_Keyring;
1415     }
1416
1417   *r_pk = NULL;
1418   s_type = !keyid[0] ? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID;
1419   rc = cdk_keydb_search_start (&st, hd, s_type, keyid);
1420   if (rc)
1421     {
1422       gnutls_assert ();
1423       return rc;
1424     }
1425   rc = cdk_keydb_search (st, hd, &knode);
1426   cdk_keydb_search_release (st);
1427   if (rc)
1428     {
1429       gnutls_assert ();
1430       return rc;
1431     }
1432
1433   node = keydb_find_bykeyid (knode, keyid, s_type);
1434   if (!node)
1435     {
1436       cdk_kbnode_release (knode);
1437       gnutls_assert ();
1438       return CDK_Error_No_Key;
1439     }
1440
1441   /* See comment in cdk_keydb_get_sk() */
1442   _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &pk);
1443   *r_pk = pk;
1444   _cdk_kbnode_clone (node);
1445   cdk_kbnode_release (knode);
1446
1447   return rc;
1448 }
1449
1450
1451 /**
1452  * cdk_keydb_get_sk:
1453  * @hd: key db handle
1454  * @keyid: the keyid of the key
1455  * @ret_sk: the allocated secret key
1456  * 
1457  * Perform a key database search by keyid and return
1458  * only the raw secret key without the additional nodes,
1459  * like the user id or the signatures.
1460  **/
1461 cdk_error_t
1462 cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 * keyid, cdk_seckey_t * ret_sk)
1463 {
1464   cdk_kbnode_t snode, node;
1465   cdk_seckey_t sk;
1466   cdk_error_t rc;
1467   int pkttype;
1468
1469   if (!keyid || !ret_sk)
1470     {
1471       gnutls_assert ();
1472       return CDK_Inv_Value;
1473     }
1474   if (!hd)
1475     {
1476       gnutls_assert ();
1477       return CDK_Error_No_Keyring;
1478     }
1479
1480   *ret_sk = NULL;
1481   rc = cdk_keydb_get_bykeyid (hd, keyid, &snode);
1482   if (rc)
1483     {
1484       gnutls_assert ();
1485       return rc;
1486     }
1487
1488   node = keydb_find_bykeyid (snode, keyid, CDK_DBSEARCH_KEYID);
1489   if (!node)
1490     {
1491       cdk_kbnode_release (snode);
1492       gnutls_assert ();
1493       return CDK_Error_No_Key;
1494     }
1495
1496   /* We need to release the packet itself but not its contents
1497      and thus we detach the openpgp packet and release the structure. */
1498   _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &sk);
1499   _cdk_kbnode_clone (node);
1500   cdk_kbnode_release (snode);
1501
1502   *ret_sk = sk;
1503   return 0;
1504 }
1505
1506
1507 static int
1508 is_selfsig (cdk_kbnode_t node, const u32 * keyid)
1509 {
1510   cdk_pkt_signature_t sig;
1511
1512   if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
1513     return 0;
1514   sig = node->pkt->pkt.signature;
1515   if ((sig->sig_class >= 0x10 && sig->sig_class <= 0x13) &&
1516       sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1])
1517     return 1;
1518
1519   return 0;
1520 }
1521
1522
1523 /* Find the newest self signature for the public key @pk
1524    and return the signature node. */
1525 static cdk_kbnode_t
1526 find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk)
1527 {
1528   cdk_kbnode_t n, sig;
1529   unsigned int ts;
1530   u32 keyid[2];
1531
1532   cdk_pk_get_keyid (pk, keyid);
1533   sig = NULL;
1534   ts = 0;
1535   for (n = key; n; n = n->next)
1536     {
1537       if (is_selfsig (n, keyid) && n->pkt->pkt.signature->timestamp > ts)
1538         {
1539           ts = n->pkt->pkt.signature->timestamp;
1540           sig = n;
1541         }
1542     }
1543
1544   return sig;
1545 }
1546
1547 static unsigned int
1548 key_usage_to_cdk_usage (unsigned int usage)
1549 {
1550   unsigned key_usage = 0;
1551
1552   if (usage & 0x01)             /* cert + sign data */
1553     key_usage |= CDK_KEY_USG_CERT_SIGN;
1554   if (usage & 0x02)             /* cert + sign data */
1555     key_usage |= CDK_KEY_USG_DATA_SIGN;
1556   if (usage & 0x04)             /* encrypt comm. + storage */
1557     key_usage |= CDK_KEY_USG_COMM_ENCR;
1558   if (usage & 0x08)             /* encrypt comm. + storage */
1559     key_usage |= CDK_KEY_USG_STORAGE_ENCR;
1560   if (usage & 0x10)             /* encrypt comm. + storage */
1561     key_usage |= CDK_KEY_USG_SPLIT_KEY;
1562   if (usage & 0x20)
1563     key_usage |= CDK_KEY_USG_AUTH;
1564   if (usage & 0x80)             /* encrypt comm. + storage */
1565     key_usage |= CDK_KEY_USG_SHARED_KEY;
1566
1567   return key_usage;
1568 }
1569
1570 static cdk_error_t
1571 keydb_merge_selfsig (cdk_kbnode_t key, u32 * keyid)
1572 {
1573   cdk_kbnode_t node, kbnode, unode;
1574   cdk_subpkt_t s = NULL;
1575   cdk_pkt_signature_t sig = NULL;
1576   cdk_pkt_userid_t uid = NULL;
1577   const byte *symalg = NULL, *hashalg = NULL, *compalg = NULL;
1578   size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0;
1579   size_t key_expire = 0;
1580
1581   if (!key)
1582     {
1583       gnutls_assert ();
1584       return CDK_Inv_Value;
1585     }
1586
1587   for (node = key; node; node = node->next)
1588     {
1589       if (!is_selfsig (node, keyid))
1590         continue;
1591       unode = cdk_kbnode_find_prev (key, node, CDK_PKT_USER_ID);
1592       if (!unode)
1593         {
1594           gnutls_assert ();
1595           return CDK_Error_No_Key;
1596         }
1597       uid = unode->pkt->pkt.user_id;
1598       sig = node->pkt->pkt.signature;
1599       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID);
1600       if (s)
1601         uid->is_primary = 1;
1602       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_FEATURES);
1603       if (s && s->size == 1 && s->d[0] & 0x01)
1604         uid->mdc_feature = 1;
1605       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE);
1606       if (s && s->size == 4)
1607         key_expire = _cdk_buftou32 (s->d);
1608       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM);
1609       if (s)
1610         {
1611           symalg = s->d;
1612           nsymalg = s->size;
1613           n += s->size + 1;
1614         }
1615       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_HASH);
1616       if (s)
1617         {
1618           hashalg = s->d;
1619           nhashalg = s->size;
1620           n += s->size + 1;
1621         }
1622       s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP);
1623       if (s)
1624         {
1625           compalg = s->d;
1626           ncompalg = s->size;
1627           n += s->size + 1;
1628         }
1629       if (uid->prefs != NULL)
1630         cdk_free (uid->prefs);
1631       if (!n || !hashalg || !compalg || !symalg)
1632         uid->prefs = NULL;
1633       else
1634         {
1635           uid->prefs = cdk_calloc (1, sizeof (*uid->prefs) * (n + 1));
1636           if (!uid->prefs)
1637             {
1638               gnutls_assert ();
1639               return CDK_Out_Of_Core;
1640             }
1641           n = 0;
1642           for (; nsymalg; nsymalg--, n++)
1643             {
1644               uid->prefs[n].type = CDK_PREFTYPE_SYM;
1645               uid->prefs[n].value = *symalg++;
1646             }
1647           for (; nhashalg; nhashalg--, n++)
1648             {
1649               uid->prefs[n].type = CDK_PREFTYPE_HASH;
1650               uid->prefs[n].value = *hashalg++;
1651             }
1652           for (; ncompalg; ncompalg--, n++)
1653             {
1654               uid->prefs[n].type = CDK_PREFTYPE_ZIP;
1655               uid->prefs[n].value = *compalg++;
1656             }
1657
1658           uid->prefs[n].type = CDK_PREFTYPE_NONE;       /* end of list marker */
1659           uid->prefs[n].value = 0;
1660           uid->prefs_size = n;
1661         }
1662     }
1663
1664   /* Now we add the extracted information to the primary key. */
1665   kbnode = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY);
1666   if (kbnode)
1667     {
1668       cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key;
1669       if (uid && uid->prefs && n)
1670         {
1671           if (pk->prefs != NULL)
1672             cdk_free (pk->prefs);
1673           pk->prefs = _cdk_copy_prefs (uid->prefs);
1674           pk->prefs_size = n;
1675         }
1676       if (key_expire)
1677         {
1678           pk->expiredate = pk->timestamp + key_expire;
1679           pk->has_expired = pk->expiredate > (u32) gnutls_time (NULL) ? 0 : 1;
1680         }
1681
1682       pk->is_invalid = 0;
1683     }
1684
1685   return 0;
1686 }
1687
1688
1689 static cdk_error_t
1690 keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check)
1691 {
1692   cdk_kbnode_t node, kb;
1693   cdk_pkt_signature_t sig;
1694   cdk_pkt_pubkey_t pk;
1695   cdk_subpkt_t s = NULL;
1696   u32 expiredate = 0, curtime = (u32) gnutls_time (NULL);
1697   u32 keyid[2];
1698
1699   if (!knode)
1700     {
1701       gnutls_assert ();
1702       return CDK_Inv_Value;
1703     }
1704   if (check && !hd)
1705     {
1706       gnutls_assert ();
1707       return CDK_Inv_Mode;
1708     }
1709
1710   kb = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
1711   if (kb)
1712     return 0;
1713
1714   /* Reset */
1715   for (node = knode; node; node = node->next)
1716     {
1717       if (node->pkt->pkttype == CDK_PKT_USER_ID)
1718         node->pkt->pkt.user_id->is_revoked = 0;
1719       else if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1720                node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1721         node->pkt->pkt.public_key->is_revoked = 0;
1722     }
1723
1724   kb = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1725   if (!kb)
1726     {
1727       gnutls_assert ();
1728       return CDK_Wrong_Format;
1729     }
1730   cdk_pk_get_keyid (kb->pkt->pkt.public_key, keyid);
1731
1732   for (node = knode; node; node = node->next)
1733     {
1734       if (node->pkt->pkttype == CDK_PKT_SIGNATURE)
1735         {
1736           sig = node->pkt->pkt.signature;
1737           /* Revocation certificates for primary keys */
1738           if (sig->sig_class == 0x20)
1739             {
1740               kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
1741               if (kb)
1742                 {
1743                   kb->pkt->pkt.public_key->is_revoked = 1;
1744                   if (check)
1745                     _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1746                 }
1747               else
1748                 {
1749                   gnutls_assert ();
1750                   return CDK_Error_No_Key;
1751                 }
1752             }
1753           /* Revocation certificates for subkeys */
1754           else if (sig->sig_class == 0x28)
1755             {
1756               kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
1757               if (kb)
1758                 {
1759                   kb->pkt->pkt.public_key->is_revoked = 1;
1760                   if (check)
1761                     _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1762                 }
1763               else
1764                 {
1765                   gnutls_assert ();
1766                   return CDK_Error_No_Key;
1767                 }
1768             }
1769           /* Revocation certifcates for user ID's */
1770           else if (sig->sig_class == 0x30)
1771             {
1772               if (sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1])
1773                 continue;       /* revokes an earlier signature, no userID. */
1774               kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID);
1775               if (kb)
1776                 {
1777                   kb->pkt->pkt.user_id->is_revoked = 1;
1778                   if (check)
1779                     _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1780                 }
1781               else
1782                 {
1783                   gnutls_assert ();
1784                   return CDK_Error_No_Key;
1785                 }
1786             }
1787           /* Direct certificates for primary keys */
1788           else if (sig->sig_class == 0x1F)
1789             {
1790               kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
1791               if (kb)
1792                 {
1793                   pk = kb->pkt->pkt.public_key;
1794                   pk->is_invalid = 0;
1795                   s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
1796                                        CDK_SIGSUBPKT_KEY_EXPIRE);
1797                   if (s)
1798                     {
1799                       expiredate = _cdk_buftou32 (s->d);
1800                       pk->expiredate = pk->timestamp + expiredate;
1801                       pk->has_expired = pk->expiredate > curtime ? 0 : 1;
1802                     }
1803                   if (check)
1804                     _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1805                 }
1806               else
1807                 {
1808                   gnutls_assert ();
1809                   return CDK_Error_No_Key;
1810                 }
1811             }
1812           /* Direct certificates for subkeys */
1813           else if (sig->sig_class == 0x18)
1814             {
1815               kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
1816               if (kb)
1817                 {
1818                   pk = kb->pkt->pkt.public_key;
1819                   pk->is_invalid = 0;
1820                   s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
1821                                        CDK_SIGSUBPKT_KEY_EXPIRE);
1822                   if (s)
1823                     {
1824                       expiredate = _cdk_buftou32 (s->d);
1825                       pk->expiredate = pk->timestamp + expiredate;
1826                       pk->has_expired = pk->expiredate > curtime ? 0 : 1;
1827                     }
1828                   if (check)
1829                     _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1830                 }
1831               else
1832                 {
1833                   gnutls_assert ();
1834                   return CDK_Error_No_Key;
1835                 }
1836             }
1837         }
1838     }
1839   node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1840   if (node && node->pkt->pkt.public_key->version == 3)
1841     {
1842       /* v3 public keys have no additonal signatures for the key directly.
1843          we say the key is valid when we have at least a self signature. */
1844       pk = node->pkt->pkt.public_key;
1845       for (node = knode; node; node = node->next)
1846         {
1847           if (is_selfsig (node, keyid))
1848             {
1849               pk->is_invalid = 0;
1850               break;
1851             }
1852         }
1853     }
1854   if (node && (node->pkt->pkt.public_key->is_revoked ||
1855                node->pkt->pkt.public_key->has_expired))
1856     {
1857       /* If the primary key has been revoked, mark all subkeys as invalid
1858          because without a primary key they are not useable */
1859       for (node = knode; node; node = node->next)
1860         {
1861           if (node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1862             node->pkt->pkt.public_key->is_invalid = 1;
1863         }
1864     }
1865
1866   return 0;
1867 }
1868
1869 static void
1870 add_key_usage (cdk_kbnode_t knode, u32 keyid[2], unsigned int usage)
1871 {
1872   cdk_kbnode_t p, ctx;
1873   cdk_packet_t pkt;
1874
1875   ctx = NULL;
1876   while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
1877     {
1878       pkt = cdk_kbnode_get_packet (p);
1879       if ((pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
1880            || pkt->pkttype == CDK_PKT_PUBLIC_KEY)
1881           && pkt->pkt.public_key->keyid[0] == keyid[0]
1882           && pkt->pkt.public_key->keyid[1] == keyid[1])
1883         {
1884           pkt->pkt.public_key->pubkey_usage = usage;
1885           return;
1886         }
1887     }
1888   return;
1889 }
1890
1891 cdk_error_t
1892 cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * r_knode)
1893 {
1894   cdk_packet_t pkt;
1895   cdk_kbnode_t knode, node;
1896   cdk_desig_revoker_t revkeys;
1897   cdk_error_t rc;
1898   u32 keyid[2], main_keyid[2];
1899   off_t old_off;
1900   int key_seen, got_key;
1901
1902   if (!inp || !r_knode)
1903     {
1904       gnutls_assert ();
1905       return CDK_Inv_Value;
1906     }
1907
1908   /* Reset all values. */
1909   keyid[0] = keyid[1] = 0;
1910   main_keyid[0] = main_keyid[1] = 0;
1911   revkeys = NULL;
1912   knode = NULL;
1913   key_seen = got_key = 0;
1914
1915   *r_knode = NULL;
1916   rc = CDK_EOF;
1917   while (!cdk_stream_eof (inp))
1918     {
1919       cdk_pkt_new (&pkt);
1920       old_off = cdk_stream_tell (inp);
1921       rc = cdk_pkt_read (inp, pkt);
1922       if (rc)
1923         {
1924           cdk_pkt_release (pkt);
1925           if (rc == CDK_EOF)
1926             break;
1927           else
1928             {                   /* Release all packets we reached so far. */
1929               _cdk_log_debug ("keydb_get_keyblock: error %d\n", rc);
1930               cdk_kbnode_release (knode);
1931               gnutls_assert ();
1932               return rc;
1933             }
1934         }
1935
1936       if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1937           pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
1938           pkt->pkttype == CDK_PKT_SECRET_KEY ||
1939           pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1940         {
1941           if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1942                            pkt->pkttype == CDK_PKT_SECRET_KEY))
1943             {
1944               /* The next key starts here so set the file pointer
1945                  and leave the loop. */
1946               cdk_stream_seek (inp, old_off);
1947               cdk_pkt_release (pkt);
1948               break;
1949             }
1950           if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1951               pkt->pkttype == CDK_PKT_SECRET_KEY)
1952             {
1953               _cdk_pkt_get_keyid (pkt, main_keyid);
1954               key_seen = 1;
1955             }
1956           else if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
1957                    pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1958             {
1959               if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1960                 {
1961                   pkt->pkt.public_key->main_keyid[0] = main_keyid[0];
1962                   pkt->pkt.public_key->main_keyid[1] = main_keyid[1];
1963                 }
1964               else
1965                 {
1966                   pkt->pkt.secret_key->main_keyid[0] = main_keyid[0];
1967                   pkt->pkt.secret_key->main_keyid[1] = main_keyid[1];
1968                 }
1969             }
1970           /* We save this for the signature */
1971           _cdk_pkt_get_keyid (pkt, keyid);
1972           got_key = 1;
1973         }
1974       else if (pkt->pkttype == CDK_PKT_USER_ID)
1975         ;
1976       else if (pkt->pkttype == CDK_PKT_SIGNATURE)
1977         {
1978           cdk_subpkt_t s;
1979
1980           pkt->pkt.signature->key[0] = keyid[0];
1981           pkt->pkt.signature->key[1] = keyid[1];
1982           if (pkt->pkt.signature->sig_class == 0x1F &&
1983               pkt->pkt.signature->revkeys)
1984             revkeys = pkt->pkt.signature->revkeys;
1985
1986           s =
1987             cdk_subpkt_find (pkt->pkt.signature->hashed,
1988                              CDK_SIGSUBPKT_KEY_FLAGS);
1989           if (s)
1990             {
1991               unsigned int key_usage = key_usage_to_cdk_usage (s->d[0]);
1992               add_key_usage (knode, pkt->pkt.signature->key, key_usage);
1993             }
1994         }
1995       node = cdk_kbnode_new (pkt);
1996       if (!knode)
1997         knode = node;
1998       else
1999         _cdk_kbnode_add (knode, node);
2000     }
2001
2002   if (got_key)
2003     {
2004       keydb_merge_selfsig (knode, main_keyid);
2005       rc = keydb_parse_allsigs (knode, NULL, 0);
2006       if (revkeys)
2007         {
2008           node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
2009           if (node)
2010             node->pkt->pkt.public_key->revkeys = revkeys;
2011         }
2012     }
2013   else
2014     cdk_kbnode_release (knode);
2015   *r_knode = got_key ? knode : NULL;
2016
2017   /* It is possible that we are in an EOF condition after we
2018      successfully read a keyblock. For example if the requested
2019      key is the last in the file. */
2020   if (rc == CDK_EOF && got_key)
2021     rc = 0;
2022   return rc;
2023 }
2024
2025
2026 /* Return the type of the given data. In case it cannot be classified,
2027    a substring search will be performed. */
2028 static int
2029 classify_data (const byte * buf, size_t len)
2030 {
2031   int type;
2032   unsigned int i;
2033
2034   if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
2035     {                           /* Skip hex prefix. */
2036       buf += 2;
2037       len -= 2;
2038     }
2039
2040   /* The length of the data does not match either a keyid or a fingerprint. */
2041   if (len != 8 && len != 16 && len != 40)
2042     return CDK_DBSEARCH_SUBSTR;
2043
2044   for (i = 0; i < len; i++)
2045     {
2046       if (!isxdigit (buf[i]))
2047         return CDK_DBSEARCH_SUBSTR;
2048     }
2049   if (i != len)
2050     return CDK_DBSEARCH_SUBSTR;
2051   switch (len)
2052     {
2053     case 8:
2054       type = CDK_DBSEARCH_SHORT_KEYID;
2055       break;
2056     case 16:
2057       type = CDK_DBSEARCH_KEYID;
2058       break;
2059     case 40:
2060       type = CDK_DBSEARCH_FPR;
2061       break;
2062     default:
2063       type = CDK_DBSEARCH_SUBSTR;
2064       break;
2065     }
2066
2067   return type;
2068 }
2069
2070
2071 /**
2072  * cdk_keydb_export:
2073  * @hd: the keydb handle
2074  * @out: the output stream
2075  * @remusr: the list of key pattern to export
2076  *
2077  * Export a list of keys to the given output stream.
2078  * Use string list with names for pattering searching.
2079  * This procedure strips local signatures.
2080  **/
2081 cdk_error_t
2082 cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
2083 {
2084   cdk_kbnode_t knode, node;
2085   cdk_strlist_t r;
2086   cdk_error_t rc;
2087   int old_ctb;
2088   cdk_keydb_search_t st;
2089
2090   for (r = remusr; r; r = r->next)
2091     {
2092       rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, r->d);
2093       if (rc)
2094         {
2095           gnutls_assert ();
2096           return rc;
2097         }
2098       rc = cdk_keydb_search (st, hd, &knode);
2099       cdk_keydb_search_release (st);
2100
2101       if (rc)
2102         {
2103           gnutls_assert ();
2104           return rc;
2105         }
2106
2107       node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
2108       if (!node)
2109         {
2110           gnutls_assert ();
2111           return CDK_Error_No_Key;
2112         }
2113
2114       /* If the key is a version 3 key, use the old packet
2115          format for the output. */
2116       if (node->pkt->pkt.public_key->version == 3)
2117         old_ctb = 1;
2118       else
2119         old_ctb = 0;
2120
2121       for (node = knode; node; node = node->next)
2122         {
2123           /* No specified format; skip them */
2124           if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
2125             continue;
2126           /* We never export local signed signatures */
2127           if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2128               !node->pkt->pkt.signature->flags.exportable)
2129             continue;
2130           /* Filter out invalid signatures */
2131           if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2132               (!KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo)))
2133             continue;
2134
2135           /* Adjust the ctb flag if needed. */
2136           node->pkt->old_ctb = old_ctb;
2137           rc = cdk_pkt_write (out, node->pkt);
2138           if (rc)
2139             {
2140               cdk_kbnode_release (knode);
2141               gnutls_assert ();
2142               return rc;
2143             }
2144         }
2145       cdk_kbnode_release (knode);
2146       knode = NULL;
2147     }
2148   return 0;
2149 }
2150
2151
2152 static cdk_packet_t
2153 find_key_packet (cdk_kbnode_t knode, int *r_is_sk)
2154 {
2155   cdk_packet_t pkt;
2156
2157   pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY);
2158   if (!pkt)
2159     {
2160       pkt = cdk_kbnode_find_packet (knode, CDK_PKT_SECRET_KEY);
2161       if (r_is_sk)
2162         *r_is_sk = pkt ? 1 : 0;
2163     }
2164   return pkt;
2165 }
2166
2167
2168 /* Return 1 if the is allowd in a key node. */
2169 static int
2170 is_key_node (cdk_kbnode_t node)
2171 {
2172   switch (node->pkt->pkttype)
2173     {
2174     case CDK_PKT_SIGNATURE:
2175     case CDK_PKT_SECRET_KEY:
2176     case CDK_PKT_PUBLIC_KEY:
2177     case CDK_PKT_SECRET_SUBKEY:
2178     case CDK_PKT_PUBLIC_SUBKEY:
2179     case CDK_PKT_USER_ID:
2180     case CDK_PKT_ATTRIBUTE:
2181       return 1;
2182
2183     default:
2184       return 0;
2185     }
2186
2187   return 0;
2188 }
2189
2190
2191 cdk_error_t
2192 cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
2193 {
2194   cdk_kbnode_t node, chk;
2195   cdk_packet_t pkt;
2196   cdk_stream_t out;
2197   cdk_error_t rc;
2198   u32 keyid[2];
2199
2200   if (!hd || !knode)
2201     {
2202       gnutls_assert ();
2203       return CDK_Inv_Value;
2204     }
2205
2206   pkt = find_key_packet (knode, NULL);
2207   if (!pkt)
2208     {
2209       gnutls_assert ();
2210       return CDK_Inv_Packet;
2211     }
2212
2213   _cdk_pkt_get_keyid (pkt, keyid);
2214   chk = NULL;
2215   cdk_keydb_get_bykeyid (hd, keyid, &chk);
2216   if (chk)
2217     {                           /* FIXME: search for new signatures */
2218       cdk_kbnode_release (chk);
2219       return 0;
2220     }
2221
2222   /* We append data to the stream so we need to close
2223      the stream here to re-open it later. */
2224   if (hd->fp)
2225     {
2226       cdk_stream_close (hd->fp);
2227       hd->fp = NULL;
2228     }
2229
2230   rc = _cdk_stream_append (hd->name, &out);
2231   if (rc)
2232     {
2233       gnutls_assert ();
2234       return rc;
2235     }
2236
2237   for (node = knode; node; node = node->next)
2238     {
2239       if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
2240         continue;               /* No uniformed syntax for this packet */
2241       if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2242           !node->pkt->pkt.signature->flags.exportable)
2243         {
2244           _cdk_log_debug ("key db import: skip local signature\n");
2245           continue;
2246         }
2247
2248       if (!is_key_node (node))
2249         {
2250           _cdk_log_debug ("key db import: skip invalid node of type %d\n",
2251                           node->pkt->pkttype);
2252           continue;
2253         }
2254
2255       rc = cdk_pkt_write (out, node->pkt);
2256       if (rc)
2257         {
2258           cdk_stream_close (out);
2259           gnutls_assert ();
2260           return rc;
2261         }
2262     }
2263
2264   cdk_stream_close (out);
2265   hd->stats.new_keys++;
2266
2267   return 0;
2268 }
2269
2270
2271 cdk_error_t
2272 _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
2273 {
2274   cdk_kbnode_t knode = NULL, unode = NULL;
2275   cdk_error_t rc;
2276   int check;
2277   cdk_keydb_search_t st;
2278
2279   if (!hd)
2280     {
2281       gnutls_assert ();
2282       return CDK_Inv_Value;
2283     }
2284
2285   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
2286   if (rc)
2287     {
2288       gnutls_assert ();
2289       return rc;
2290     }
2291   rc = cdk_keydb_search (st, hd, &knode);
2292   cdk_keydb_search_release (st);
2293
2294   if (rc)
2295     {
2296       gnutls_assert ();
2297       return rc;
2298     }
2299
2300   rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id);
2301   if (!rc)
2302     {
2303       rc = cdk_keydb_search (st, hd, &unode);
2304       cdk_keydb_search_release (st);
2305     }
2306   if (rc)
2307     {
2308       cdk_kbnode_release (knode);
2309       gnutls_assert ();
2310       return rc;
2311     }
2312
2313   check = 0;
2314   cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
2315   if (unode && find_by_keyid (unode, st))
2316     check++;
2317   cdk_keydb_search_release (st);
2318   cdk_kbnode_release (unode);
2319
2320   cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id);
2321   if (knode && find_by_pattern (knode, st))
2322     check++;
2323   cdk_keydb_search_release (st);
2324   cdk_kbnode_release (knode);
2325
2326   return check == 2 ? 0 : CDK_Inv_Value;
2327 }
2328
2329
2330 /**
2331  * cdk_keydb_check_sk:
2332  * @hd: the key db handle
2333  * @keyid: the 64-bit keyid
2334  * 
2335  * Check if a secret key with the given key ID is available
2336  * in the key database.
2337  **/
2338 cdk_error_t
2339 cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 * keyid)
2340 {
2341   cdk_stream_t db;
2342   cdk_packet_t pkt;
2343   cdk_error_t rc;
2344   u32 kid[2];
2345
2346   if (!hd || !keyid)
2347     {
2348       gnutls_assert ();
2349       return CDK_Inv_Value;
2350     }
2351   if (!hd->secret)
2352     {
2353       gnutls_assert ();
2354       return CDK_Inv_Mode;
2355     }
2356
2357   rc = _cdk_keydb_open (hd, &db);
2358   if (rc)
2359     {
2360       gnutls_assert ();
2361       return rc;
2362     }
2363   cdk_pkt_new (&pkt);
2364   while (!cdk_pkt_read (db, pkt))
2365     {
2366       if (pkt->pkttype != CDK_PKT_SECRET_KEY &&
2367           pkt->pkttype != CDK_PKT_SECRET_SUBKEY)
2368         {
2369           cdk_pkt_free (pkt);
2370           continue;
2371         }
2372       cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
2373       if (KEYID_CMP (kid, keyid))
2374         {
2375           cdk_pkt_release (pkt);
2376           return 0;
2377         }
2378       cdk_pkt_free (pkt);
2379     }
2380   cdk_pkt_release (pkt);
2381   gnutls_assert ();
2382   return CDK_Error_No_Key;
2383 }
2384
2385
2386 /**
2387  * cdk_listkey_start:
2388  * @r_ctx: pointer to store the new context
2389  * @db: the key database handle
2390  * @patt: string pattern
2391  * @fpatt: recipients from a stringlist to show
2392  *
2393  * Prepare a key listing with the given parameters. Two modes are supported.
2394  * The first mode uses string pattern to determine if the key should be
2395  * returned or not. The other mode uses a string list to request the key
2396  * which should be listed.
2397  **/
2398 cdk_error_t
2399 cdk_listkey_start (cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
2400                    const char *patt, cdk_strlist_t fpatt)
2401 {
2402   cdk_listkey_t ctx;
2403   cdk_stream_t inp;
2404   cdk_error_t rc;
2405
2406   if (!r_ctx || !db)
2407     {
2408       gnutls_assert ();
2409       return CDK_Inv_Value;
2410     }
2411   if ((patt && fpatt) || (!patt && !fpatt))
2412     {
2413       gnutls_assert ();
2414       return CDK_Inv_Mode;
2415     }
2416   rc = _cdk_keydb_open (db, &inp);
2417   if (rc)
2418     {
2419       gnutls_assert ();
2420       return rc;
2421     }
2422   ctx = cdk_calloc (1, sizeof *ctx);
2423   if (!ctx)
2424     {
2425       gnutls_assert ();
2426       return CDK_Out_Of_Core;
2427     }
2428   ctx->db = db;
2429   ctx->inp = inp;
2430   if (patt)
2431     {
2432       ctx->u.patt = cdk_strdup (patt);
2433       if (!ctx->u.patt)
2434         {
2435           gnutls_assert ();
2436           return CDK_Out_Of_Core;
2437         }
2438     }
2439   else if (fpatt)
2440     {
2441       cdk_strlist_t l;
2442       for (l = fpatt; l; l = l->next)
2443         cdk_strlist_add (&ctx->u.fpatt, l->d);
2444     }
2445   ctx->type = patt ? 1 : 0;
2446   ctx->init = 1;
2447   *r_ctx = ctx;
2448   return 0;
2449 }
2450
2451
2452 /**
2453  * cdk_listkey_close:
2454  * @ctx: the list key context
2455  *
2456  * Free the list key context.
2457  **/
2458 void
2459 cdk_listkey_close (cdk_listkey_t ctx)
2460 {
2461   if (!ctx)
2462     return;
2463
2464   if (ctx->type)
2465     cdk_free (ctx->u.patt);
2466   else
2467     cdk_strlist_free (ctx->u.fpatt);
2468   cdk_free (ctx);
2469 }
2470
2471
2472 /**
2473  * cdk_listkey_next:
2474  * @ctx: list key context
2475  * @r_key: the pointer to the new key node object
2476  *
2477  * Retrieve the next key from the pattern of the key list context.
2478  **/
2479 cdk_error_t
2480 cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t * ret_key)
2481 {
2482   if (!ctx || !ret_key)
2483     {
2484       gnutls_assert ();
2485       return CDK_Inv_Value;
2486     }
2487   if (!ctx->init)
2488     {
2489       gnutls_assert ();
2490       return CDK_Inv_Mode;
2491     }
2492
2493   if (ctx->type && ctx->u.patt[0] == '*')
2494     return cdk_keydb_get_keyblock (ctx->inp, ret_key);
2495   else if (ctx->type)
2496     {
2497       cdk_kbnode_t node;
2498       struct cdk_keydb_search_s ks;
2499       cdk_error_t rc;
2500
2501       for (;;)
2502         {
2503           rc = cdk_keydb_get_keyblock (ctx->inp, &node);
2504           if (rc)
2505             {
2506               gnutls_assert ();
2507               return rc;
2508             }
2509           memset (&ks, 0, sizeof (ks));
2510           ks.type = CDK_DBSEARCH_SUBSTR;
2511           ks.u.pattern = ctx->u.patt;
2512           if (find_by_pattern (node, &ks))
2513             {
2514               *ret_key = node;
2515               return 0;
2516             }
2517           cdk_kbnode_release (node);
2518           node = NULL;
2519         }
2520     }
2521   else
2522     {
2523       if (!ctx->t)
2524         ctx->t = ctx->u.fpatt;
2525       else if (ctx->t->next)
2526         ctx->t = ctx->t->next;
2527       else
2528         return CDK_EOF;
2529       return cdk_keydb_get_bypattern (ctx->db, ctx->t->d, ret_key);
2530     }
2531   gnutls_assert ();
2532   return CDK_General_Error;
2533 }
2534
2535
2536 int
2537 _cdk_keydb_is_secret (cdk_keydb_hd_t db)
2538 {
2539   return db->secret;
2540 }