gpg: Add signature cache support to the keybox.
[gnupg.git] / kbx / keybox-search.c
1 /* keybox-search.c - Search operations
2  * Copyright (C) 2001, 2002, 2003, 2004, 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
26
27 #include "../common/stringhelp.h" /* ascii_xxxx() */
28
29 #include "keybox-defs.h"
30 #include <gcrypt.h>
31
32
33 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
34                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
35 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
36
37
38 struct sn_array_s {
39     int snlen;
40     unsigned char *sn;
41 };
42
43
44
45 static inline ulong
46 get32 (const byte *buffer)
47 {
48   ulong a;
49   a =  *buffer << 24;
50   a |= buffer[1] << 16;
51   a |= buffer[2] << 8;
52   a |= buffer[3];
53   return a;
54 }
55
56 static inline ulong
57 get16 (const byte *buffer)
58 {
59   ulong a;
60   a =  *buffer << 8;
61   a |= buffer[1];
62   return a;
63 }
64
65
66
67 static inline int
68 blob_get_type (KEYBOXBLOB blob)
69 {
70   const unsigned char *buffer;
71   size_t length;
72
73   buffer = _keybox_get_blob_image (blob, &length);
74   if (length < 32)
75     return -1; /* blob too short */
76
77   return buffer[4];
78 }
79
80 static inline unsigned int
81 blob_get_blob_flags (KEYBOXBLOB blob)
82 {
83   const unsigned char *buffer;
84   size_t length;
85
86   buffer = _keybox_get_blob_image (blob, &length);
87   if (length < 8)
88     return 0; /* oops */
89
90   return get16 (buffer + 6);
91 }
92
93
94 /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
95    Return the offset and the length (in bytes) of the flag in
96    FLAGOFF,FLAG_SIZE. */
97 gpg_err_code_t
98 _keybox_get_flag_location (const unsigned char *buffer, size_t length,
99                            int what, size_t *flag_off, size_t *flag_size)
100 {
101   size_t pos;
102   size_t nkeys, keyinfolen;
103   size_t nuids, uidinfolen;
104   size_t nserial;
105   size_t nsigs, siginfolen, siginfooff;
106
107   switch (what)
108     {
109     case KEYBOX_FLAG_BLOB:
110       if (length < 8)
111         return GPG_ERR_INV_OBJ;
112       *flag_off = 6;
113       *flag_size = 2;
114       break;
115
116     case KEYBOX_FLAG_OWNERTRUST:
117     case KEYBOX_FLAG_VALIDITY:
118     case KEYBOX_FLAG_CREATED_AT:
119     case KEYBOX_FLAG_SIG_INFO:
120       if (length < 20)
121         return GPG_ERR_INV_OBJ;
122       /* Key info. */
123       nkeys = get16 (buffer + 16);
124       keyinfolen = get16 (buffer + 18 );
125       if (keyinfolen < 28)
126         return GPG_ERR_INV_OBJ;
127       pos = 20 + keyinfolen*nkeys;
128       if (pos+2 > length)
129         return GPG_ERR_INV_OBJ; /* Out of bounds. */
130       /* Serial number. */
131       nserial = get16 (buffer+pos);
132       pos += 2 + nserial;
133       if (pos+4 > length)
134         return GPG_ERR_INV_OBJ; /* Out of bounds. */
135       /* User IDs. */
136       nuids = get16 (buffer + pos); pos += 2;
137       uidinfolen = get16 (buffer + pos); pos += 2;
138       if (uidinfolen < 12 )
139         return GPG_ERR_INV_OBJ;
140       pos += uidinfolen*nuids;
141       if (pos+4 > length)
142         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
143       /* Signature info. */
144       siginfooff = pos;
145       nsigs = get16 (buffer + pos); pos += 2;
146       siginfolen = get16 (buffer + pos); pos += 2;
147       if (siginfolen < 4 )
148         return GPG_ERR_INV_OBJ;
149       pos += siginfolen*nsigs;
150       if (pos+1+1+2+4+4+4+4 > length)
151         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
152       *flag_size = 1;
153       *flag_off = pos;
154       switch (what)
155         {
156         case KEYBOX_FLAG_VALIDITY:
157           *flag_off += 1;
158           break;
159         case KEYBOX_FLAG_CREATED_AT:
160           *flag_size = 4;
161           *flag_off += 1+2+4+4+4;
162           break;
163         case KEYBOX_FLAG_SIG_INFO:
164           *flag_size = siginfolen * nsigs;
165           *flag_off = siginfooff;
166           break;
167         default:
168           break;
169         }
170       break;
171
172     default:
173       return GPG_ERR_INV_FLAG;
174     }
175   return 0;
176 }
177
178
179
180 /* Return one of the flags WHAT in VALUE from teh blob BUFFER of
181    LENGTH bytes.  Return 0 on success or an raw error code. */
182 static gpg_err_code_t
183 get_flag_from_image (const unsigned char *buffer, size_t length,
184                      int what, unsigned int *value)
185 {
186   gpg_err_code_t ec;
187   size_t pos, size;
188
189   *value = 0;
190   ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
191   if (!ec)
192     switch (size)
193       {
194       case 1: *value = buffer[pos]; break;
195       case 2: *value = get16 (buffer + pos); break;
196       case 4: *value = get32 (buffer + pos); break;
197       default: ec = GPG_ERR_BUG; break;
198       }
199
200   return ec;
201 }
202
203
204 static int
205 blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
206 {
207   const unsigned char *buffer;
208   size_t length;
209   size_t pos, off;
210   size_t nkeys, keyinfolen;
211   size_t nserial;
212
213   buffer = _keybox_get_blob_image (blob, &length);
214   if (length < 40)
215     return 0; /* blob too short */
216
217   /*keys*/
218   nkeys = get16 (buffer + 16);
219   keyinfolen = get16 (buffer + 18 );
220   if (keyinfolen < 28)
221     return 0; /* invalid blob */
222   pos = 20 + keyinfolen*nkeys;
223   if (pos+2 > length)
224     return 0; /* out of bounds */
225
226   /*serial*/
227   nserial = get16 (buffer+pos);
228   off = pos + 2;
229   if (off+nserial > length)
230     return 0; /* out of bounds */
231
232   return nserial == snlen && !memcmp (buffer+off, sn, snlen);
233 }
234
235
236 static int
237 blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
238 {
239   const unsigned char *buffer;
240   size_t length;
241   size_t pos, off;
242   size_t nkeys, keyinfolen;
243   int idx;
244
245   buffer = _keybox_get_blob_image (blob, &length);
246   if (length < 40)
247     return 0; /* blob too short */
248
249   /*keys*/
250   nkeys = get16 (buffer + 16);
251   keyinfolen = get16 (buffer + 18 );
252   if (keyinfolen < 28)
253     return 0; /* invalid blob */
254   pos = 20;
255   if (pos + keyinfolen*nkeys > length)
256     return 0; /* out of bounds */
257
258   for (idx=0; idx < nkeys; idx++)
259     {
260       off = pos + idx*keyinfolen;
261       if (!memcmp (buffer + off, fpr, 20))
262         return 1; /* found */
263     }
264   return 0; /* not found */
265 }
266
267 static int
268 blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
269                    int fproff, int fprlen)
270 {
271   const unsigned char *buffer;
272   size_t length;
273   size_t pos, off;
274   size_t nkeys, keyinfolen;
275   int idx;
276
277   buffer = _keybox_get_blob_image (blob, &length);
278   if (length < 40)
279     return 0; /* blob too short */
280
281   /*keys*/
282   nkeys = get16 (buffer + 16);
283   keyinfolen = get16 (buffer + 18 );
284   if (keyinfolen < 28)
285     return 0; /* invalid blob */
286   pos = 20;
287   if (pos + keyinfolen*nkeys > length)
288     return 0; /* out of bounds */
289
290   for (idx=0; idx < nkeys; idx++)
291     {
292       off = pos + idx*keyinfolen;
293       if (!memcmp (buffer + off + fproff, fpr, fprlen))
294         return 1; /* found */
295     }
296   return 0; /* not found */
297 }
298
299
300 static int
301 blob_cmp_name (KEYBOXBLOB blob, int idx,
302                const char *name, size_t namelen, int substr)
303 {
304   const unsigned char *buffer;
305   size_t length;
306   size_t pos, off, len;
307   size_t nkeys, keyinfolen;
308   size_t nuids, uidinfolen;
309   size_t nserial;
310
311   buffer = _keybox_get_blob_image (blob, &length);
312   if (length < 40)
313     return 0; /* blob too short */
314
315   /*keys*/
316   nkeys = get16 (buffer + 16);
317   keyinfolen = get16 (buffer + 18 );
318   if (keyinfolen < 28)
319     return 0; /* invalid blob */
320   pos = 20 + keyinfolen*nkeys;
321   if (pos+2 > length)
322     return 0; /* out of bounds */
323
324   /*serial*/
325   nserial = get16 (buffer+pos);
326   pos += 2 + nserial;
327   if (pos+4 > length)
328     return 0; /* out of bounds */
329
330   /* user ids*/
331   nuids = get16 (buffer + pos);  pos += 2;
332   uidinfolen = get16 (buffer + pos);  pos += 2;
333   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
334     return 0; /* invalid blob */
335   if (pos + uidinfolen*nuids > length)
336     return 0; /* out of bounds */
337
338   if (idx < 0)
339     { /* compare all names starting with that (negated) index */
340       idx = -idx;
341
342       for ( ;idx < nuids; idx++)
343         {
344           size_t mypos = pos;
345
346           mypos += idx*uidinfolen;
347           off = get32 (buffer+mypos);
348           len = get32 (buffer+mypos+4);
349           if (off+len > length)
350             return 0; /* error: better stop here out of bounds */
351           if (len < 1)
352             continue; /* empty name */
353           if (substr)
354             {
355               if (ascii_memcasemem (buffer+off, len, name, namelen))
356                 return 1; /* found */
357             }
358           else
359             {
360               if (len == namelen && !memcmp (buffer+off, name, len))
361                 return 1; /* found */
362             }
363         }
364       return 0; /* not found */
365     }
366   else
367     {
368       if (idx > nuids)
369         return 0; /* no user ID with that idx */
370       pos += idx*uidinfolen;
371       off = get32 (buffer+pos);
372       len = get32 (buffer+pos+4);
373       if (off+len > length)
374         return 0; /* out of bounds */
375       if (len < 1)
376         return 0; /* empty name */
377
378       if (substr)
379         {
380           return !!ascii_memcasemem (buffer+off, len, name, namelen);
381         }
382       else
383         {
384           return len == namelen && !memcmp (buffer+off, name, len);
385         }
386     }
387 }
388
389
390 /* compare all email addresses of the subject.  With SUBSTR given as
391    True a substring search is done in the mail address */
392 static int
393 blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr)
394 {
395   const unsigned char *buffer;
396   size_t length;
397   size_t pos, off, len;
398   size_t nkeys, keyinfolen;
399   size_t nuids, uidinfolen;
400   size_t nserial;
401   int idx;
402
403   /* fixme: this code is common to blob_cmp_mail */
404   buffer = _keybox_get_blob_image (blob, &length);
405   if (length < 40)
406     return 0; /* blob too short */
407
408   /*keys*/
409   nkeys = get16 (buffer + 16);
410   keyinfolen = get16 (buffer + 18 );
411   if (keyinfolen < 28)
412     return 0; /* invalid blob */
413   pos = 20 + keyinfolen*nkeys;
414   if (pos+2 > length)
415     return 0; /* out of bounds */
416
417   /*serial*/
418   nserial = get16 (buffer+pos);
419   pos += 2 + nserial;
420   if (pos+4 > length)
421     return 0; /* out of bounds */
422
423   /* user ids*/
424   nuids = get16 (buffer + pos);  pos += 2;
425   uidinfolen = get16 (buffer + pos);  pos += 2;
426   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
427     return 0; /* invalid blob */
428   if (pos + uidinfolen*nuids > length)
429     return 0; /* out of bounds */
430
431   if (namelen < 1)
432     return 0;
433
434   for (idx=1 ;idx < nuids; idx++)
435     {
436       size_t mypos = pos;
437
438       mypos += idx*uidinfolen;
439       off = get32 (buffer+mypos);
440       len = get32 (buffer+mypos+4);
441       if (off+len > length)
442         return 0; /* error: better stop here out of bounds */
443       if (len < 2 || buffer[off] != '<')
444         continue; /* empty name or trailing 0 not stored */
445       len--; /* one back */
446       if ( len < 3 || buffer[off+len] != '>')
447         continue; /* not a proper email address */
448       len--;
449       if (substr)
450         {
451           if (ascii_memcasemem (buffer+off+1, len, name, namelen))
452             return 1; /* found */
453         }
454       else
455         {
456           if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len))
457             return 1; /* found */
458         }
459     }
460   return 0; /* not found */
461 }
462
463
464 #ifdef KEYBOX_WITH_X509
465 /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
466    We don't have the keygrips as meta data, thus we need to parse the
467    certificate. Fixme: We might want to return proper error codes
468    instead of failing a search for invalid certificates etc.  */
469 static int
470 blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
471 {
472   int rc;
473   const unsigned char *buffer;
474   size_t length;
475   size_t cert_off, cert_len;
476   ksba_reader_t reader = NULL;
477   ksba_cert_t cert = NULL;
478   ksba_sexp_t p = NULL;
479   gcry_sexp_t s_pkey;
480   unsigned char array[20];
481   unsigned char *rcp;
482   size_t n;
483
484   buffer = _keybox_get_blob_image (blob, &length);
485   if (length < 40)
486     return 0; /* Too short. */
487   cert_off = get32 (buffer+8);
488   cert_len = get32 (buffer+12);
489   if (cert_off+cert_len > length)
490     return 0; /* Too short.  */
491
492   rc = ksba_reader_new (&reader);
493   if (rc)
494     return 0; /* Problem with ksba. */
495   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
496   if (rc)
497     goto failed;
498   rc = ksba_cert_new (&cert);
499   if (rc)
500     goto failed;
501   rc = ksba_cert_read_der (cert, reader);
502   if (rc)
503     goto failed;
504   p = ksba_cert_get_public_key (cert);
505   if (!p)
506     goto failed;
507   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
508   if (!n)
509     goto failed;
510   rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
511   if (rc)
512     {
513       gcry_sexp_release (s_pkey);
514       goto failed;
515     }
516   rcp = gcry_pk_get_keygrip (s_pkey, array);
517   gcry_sexp_release (s_pkey);
518   if (!rcp)
519     goto failed; /* Can't calculate keygrip. */
520
521   xfree (p);
522   ksba_cert_release (cert);
523   ksba_reader_release (reader);
524   return !memcmp (array, grip, 20);
525  failed:
526   xfree (p);
527   ksba_cert_release (cert);
528   ksba_reader_release (reader);
529   return 0;
530 }
531 #endif /*KEYBOX_WITH_X509*/
532
533
534 \f
535 /*
536   The has_foo functions are used as helpers for search
537 */
538 static inline int
539 has_short_kid (KEYBOXBLOB blob, u32 lkid)
540 {
541   unsigned char buf[4];
542   buf[0] = lkid >> 24;
543   buf[1] = lkid >> 16;
544   buf[2] = lkid >> 8;
545   buf[3] = lkid;
546   return blob_cmp_fpr_part (blob, buf, 16, 4);
547 }
548
549 static inline int
550 has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
551 {
552   unsigned char buf[8];
553   buf[0] = mkid >> 24;
554   buf[1] = mkid >> 16;
555   buf[2] = mkid >> 8;
556   buf[3] = mkid;
557   buf[4] = lkid >> 24;
558   buf[5] = lkid >> 16;
559   buf[6] = lkid >> 8;
560   buf[7] = lkid;
561   return blob_cmp_fpr_part (blob, buf, 12, 8);
562 }
563
564 static inline int
565 has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
566 {
567   return blob_cmp_fpr (blob, fpr);
568 }
569
570 static inline int
571 has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
572 {
573 #ifdef KEYBOX_WITH_X509
574   if (blob_get_type (blob) == BLOBTYPE_X509)
575     return blob_x509_has_grip (blob, grip);
576 #endif
577   return 0;
578 }
579
580
581 static inline int
582 has_issuer (KEYBOXBLOB blob, const char *name)
583 {
584   size_t namelen;
585
586   return_val_if_fail (name, 0);
587
588   if (blob_get_type (blob) != BLOBTYPE_X509)
589     return 0;
590
591   namelen = strlen (name);
592   return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0);
593 }
594
595 static inline int
596 has_issuer_sn (KEYBOXBLOB blob, const char *name,
597                const unsigned char *sn, int snlen)
598 {
599   size_t namelen;
600
601   return_val_if_fail (name, 0);
602   return_val_if_fail (sn, 0);
603
604   if (blob_get_type (blob) != BLOBTYPE_X509)
605     return 0;
606
607   namelen = strlen (name);
608
609   return (blob_cmp_sn (blob, sn, snlen)
610           && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0));
611 }
612
613 static inline int
614 has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
615 {
616   return_val_if_fail (sn, 0);
617
618   if (blob_get_type (blob) != BLOBTYPE_X509)
619     return 0;
620   return blob_cmp_sn (blob, sn, snlen);
621 }
622
623 static inline int
624 has_subject (KEYBOXBLOB blob, const char *name)
625 {
626   size_t namelen;
627
628   return_val_if_fail (name, 0);
629
630   if (blob_get_type (blob) != BLOBTYPE_X509)
631     return 0;
632
633   namelen = strlen (name);
634   return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0);
635 }
636
637 static inline int
638 has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr)
639 {
640   size_t namelen;
641
642   return_val_if_fail (name, 0);
643
644   if (blob_get_type (blob) != BLOBTYPE_X509)
645     return 0;
646
647   namelen = strlen (name);
648   return blob_cmp_name (blob, -1 /* all subject names*/, name,
649                         namelen, substr);
650 }
651
652
653 static inline int
654 has_mail (KEYBOXBLOB blob, const char *name, int substr)
655 {
656   size_t namelen;
657
658   return_val_if_fail (name, 0);
659
660   if (blob_get_type (blob) != BLOBTYPE_X509)
661     return 0;
662
663   namelen = strlen (name);
664   if (namelen && name[namelen-1] == '>')
665     namelen--;
666   return blob_cmp_mail (blob, name, namelen, substr);
667 }
668
669
670 static void
671 release_sn_array (struct sn_array_s *array, size_t size)
672 {
673   size_t n;
674
675   for (n=0; n < size; n++)
676     xfree (array[n].sn);
677   xfree (array);
678 }
679
680 \f
681 /*
682
683   The search API
684
685 */
686
687 int
688 keybox_search_reset (KEYBOX_HANDLE hd)
689 {
690   if (!hd)
691     return gpg_error (GPG_ERR_INV_VALUE);
692
693   if (hd->found.blob)
694     {
695       _keybox_release_blob (hd->found.blob);
696       hd->found.blob = NULL;
697     }
698
699   if (hd->fp)
700     {
701       fclose (hd->fp);
702       hd->fp = NULL;
703     }
704   hd->error = 0;
705   hd->eof = 0;
706   return 0;
707 }
708
709
710 /* Note: When in ephemeral mode the search function does visit all
711    blobs but in standard mode, blobs flagged as ephemeral are ignored.  */
712 int
713 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
714 {
715   int rc;
716   size_t n;
717   int need_words, any_skip;
718   KEYBOXBLOB blob = NULL;
719   struct sn_array_s *sn_array = NULL;
720
721   if (!hd)
722     return gpg_error (GPG_ERR_INV_VALUE);
723
724   /* clear last found result */
725   if (hd->found.blob)
726     {
727       _keybox_release_blob (hd->found.blob);
728       hd->found.blob = NULL;
729     }
730
731   if (hd->error)
732     return hd->error; /* still in error state */
733   if (hd->eof)
734     return -1; /* still EOF */
735
736   /* figure out what information we need */
737   need_words = any_skip = 0;
738   for (n=0; n < ndesc; n++)
739     {
740       switch (desc[n].mode)
741         {
742         case KEYDB_SEARCH_MODE_WORDS:
743           need_words = 1;
744           break;
745         case KEYDB_SEARCH_MODE_FIRST:
746           /* always restart the search in this mode */
747           keybox_search_reset (hd);
748           break;
749         default:
750           break;
751         }
752       if (desc[n].skipfnc)
753         any_skip = 1;
754       if (desc[n].snlen == -1 && !sn_array)
755         {
756           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
757           if (!sn_array)
758             return (hd->error = gpg_error_from_syserror ());
759         }
760     }
761
762   (void)need_words;  /* Not yet implemented.  */
763
764   if (!hd->fp)
765     {
766       hd->fp = fopen (hd->kb->fname, "rb");
767       if (!hd->fp)
768         {
769           hd->error = gpg_error_from_syserror ();
770           xfree (sn_array);
771           return hd->error;
772         }
773     }
774
775   /* Kludge: We need to convert an SN given as hexstring to its binary
776      representation - in some cases we are not able to store it in the
777      search descriptor, because due to the way we use it, it is not
778      possible to free allocated memory. */
779   if (sn_array)
780     {
781       const unsigned char *s;
782       int i, odd;
783       size_t snlen;
784
785       for (n=0; n < ndesc; n++)
786         {
787           if (!desc[n].sn)
788             ;
789           else if (desc[n].snlen == -1)
790             {
791               unsigned char *sn;
792
793               s = desc[n].sn;
794               for (i=0; *s && *s != '/'; s++, i++)
795                 ;
796               odd = (i & 1);
797               snlen = (i+1)/2;
798               sn_array[n].sn = xtrymalloc (snlen);
799               if (!sn_array[n].sn)
800                 {
801                   hd->error = gpg_error_from_syserror ();
802                   release_sn_array (sn_array, n);
803                   return hd->error;
804                 }
805               sn_array[n].snlen = snlen;
806               sn = sn_array[n].sn;
807               s = desc[n].sn;
808               if (odd)
809                 {
810                   *sn++ = xtoi_1 (s);
811                   s++;
812                 }
813               for (; *s && *s != '/';  s += 2)
814                 *sn++ = xtoi_2 (s);
815             }
816           else
817             {
818               const unsigned char *sn;
819
820               sn = desc[n].sn;
821               snlen = desc[n].snlen;
822               sn_array[n].sn = xtrymalloc (snlen);
823               if (!sn_array[n].sn)
824                 {
825                   hd->error = gpg_error_from_syserror ();
826                   release_sn_array (sn_array, n);
827                   return hd->error;
828                 }
829               sn_array[n].snlen = snlen;
830               memcpy (sn_array[n].sn, sn, snlen);
831             }
832         }
833     }
834
835
836   for (;;)
837     {
838       unsigned int blobflags;
839
840       _keybox_release_blob (blob); blob = NULL;
841       rc = _keybox_read_blob (&blob, hd->fp);
842       if (rc)
843         break;
844
845       if (blob_get_type (blob) == BLOBTYPE_HEADER)
846         continue;
847
848
849       blobflags = blob_get_blob_flags (blob);
850       if (!hd->ephemeral && (blobflags & 2))
851         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
852
853       for (n=0; n < ndesc; n++)
854         {
855           switch (desc[n].mode)
856             {
857             case KEYDB_SEARCH_MODE_NONE:
858               never_reached ();
859               break;
860             case KEYDB_SEARCH_MODE_EXACT:
861               if (has_subject_or_alt (blob, desc[n].u.name, 0))
862                 goto found;
863               break;
864             case KEYDB_SEARCH_MODE_MAIL:
865               if (has_mail (blob, desc[n].u.name, 0))
866                 goto found;
867               break;
868             case KEYDB_SEARCH_MODE_MAILSUB:
869               if (has_mail (blob, desc[n].u.name, 1))
870                 goto found;
871               break;
872             case KEYDB_SEARCH_MODE_SUBSTR:
873               if (has_subject_or_alt (blob, desc[n].u.name, 1))
874                 goto found;
875               break;
876             case KEYDB_SEARCH_MODE_MAILEND:
877             case KEYDB_SEARCH_MODE_WORDS:
878               never_reached (); /* not yet implemented */
879               break;
880             case KEYDB_SEARCH_MODE_ISSUER:
881               if (has_issuer (blob, desc[n].u.name))
882                 goto found;
883               break;
884             case KEYDB_SEARCH_MODE_ISSUER_SN:
885               if (has_issuer_sn (blob, desc[n].u.name,
886                                  sn_array? sn_array[n].sn : desc[n].sn,
887                                  sn_array? sn_array[n].snlen : desc[n].snlen))
888                 goto found;
889               break;
890             case KEYDB_SEARCH_MODE_SN:
891               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
892                                 sn_array? sn_array[n].snlen : desc[n].snlen))
893                 goto found;
894               break;
895             case KEYDB_SEARCH_MODE_SUBJECT:
896               if (has_subject (blob, desc[n].u.name))
897                 goto found;
898               break;
899             case KEYDB_SEARCH_MODE_SHORT_KID:
900               if (has_short_kid (blob, desc[n].u.kid[1]))
901                 goto found;
902               break;
903             case KEYDB_SEARCH_MODE_LONG_KID:
904               if (has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]))
905                 goto found;
906               break;
907             case KEYDB_SEARCH_MODE_FPR:
908             case KEYDB_SEARCH_MODE_FPR20:
909               if (has_fingerprint (blob, desc[n].u.fpr))
910                 goto found;
911               break;
912             case KEYDB_SEARCH_MODE_KEYGRIP:
913               if (has_keygrip (blob, desc[n].u.grip))
914                 goto found;
915               break;
916             case KEYDB_SEARCH_MODE_FIRST:
917               goto found;
918               break;
919             case KEYDB_SEARCH_MODE_NEXT:
920               goto found;
921               break;
922             default:
923               rc = gpg_error (GPG_ERR_INV_VALUE);
924               goto found;
925             }
926         }
927       continue;
928     found:
929       for (n=any_skip?0:ndesc; n < ndesc; n++)
930         {
931 /*            if (desc[n].skipfnc */
932 /*                && desc[n].skipfnc (desc[n].skipfncvalue, aki, NULL)) */
933 /*              break; */
934         }
935       if (n == ndesc)
936         break; /* got it */
937     }
938
939   if (!rc)
940     {
941       hd->found.blob = blob;
942     }
943   else if (rc == -1)
944     {
945       _keybox_release_blob (blob);
946       hd->eof = 1;
947     }
948   else
949     {
950       _keybox_release_blob (blob);
951       hd->error = rc;
952     }
953
954   if (sn_array)
955     release_sn_array (sn_array, ndesc);
956
957   return rc;
958 }
959
960
961
962 \f
963 /*
964    Functions to return a certificate or a keyblock.  To be used after
965    a successful search operation.
966 */
967
968
969 /* Return the last found keyblock.  Returns 0 on success and stores a
970    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
971    in that case.  */
972 gpg_error_t
973 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, u32 **r_sigstatus)
974 {
975   gpg_error_t err;
976   const unsigned char *buffer, *p;
977   size_t length;
978   size_t image_off, image_len;
979   size_t siginfo_off, siginfo_len;
980   u32 *sigstatus, n, n_sigs, sigilen;
981
982   *r_iobuf = NULL;
983   *r_sigstatus = NULL;
984
985   if (!hd)
986     return gpg_error (GPG_ERR_INV_VALUE);
987   if (!hd->found.blob)
988     return gpg_error (GPG_ERR_NOTHING_FOUND);
989
990   if (blob_get_type (hd->found.blob) != BLOBTYPE_PGP)
991     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
992
993   buffer = _keybox_get_blob_image (hd->found.blob, &length);
994   if (length < 40)
995     return gpg_error (GPG_ERR_TOO_SHORT);
996   image_off = get32 (buffer+8);
997   image_len = get32 (buffer+12);
998   if (image_off+image_len > length)
999     return gpg_error (GPG_ERR_TOO_SHORT);
1000
1001   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1002                                    &siginfo_off, &siginfo_len);
1003   if (err)
1004     return err;
1005   n_sigs  = get16 (buffer + siginfo_off);
1006   sigilen = get16 (buffer + siginfo_off + 2);
1007   p = buffer + siginfo_off + 4;
1008   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
1009   if (!sigstatus)
1010     return gpg_error_from_syserror ();
1011   sigstatus[0] = n_sigs;
1012   for (n=1; n <= n_sigs; n++, p += sigilen)
1013     sigstatus[n] = get32 (p);
1014
1015   *r_sigstatus = sigstatus;
1016   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1017   return 0;
1018 }
1019
1020
1021 #ifdef KEYBOX_WITH_X509
1022 /*
1023   Return the last found cert.  Caller must free it.
1024  */
1025 int
1026 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1027 {
1028   const unsigned char *buffer;
1029   size_t length;
1030   size_t cert_off, cert_len;
1031   ksba_reader_t reader = NULL;
1032   ksba_cert_t cert = NULL;
1033   int rc;
1034
1035   if (!hd)
1036     return gpg_error (GPG_ERR_INV_VALUE);
1037   if (!hd->found.blob)
1038     return gpg_error (GPG_ERR_NOTHING_FOUND);
1039
1040   if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
1041     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1042
1043   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1044   if (length < 40)
1045     return gpg_error (GPG_ERR_TOO_SHORT);
1046   cert_off = get32 (buffer+8);
1047   cert_len = get32 (buffer+12);
1048   if (cert_off+cert_len > length)
1049     return gpg_error (GPG_ERR_TOO_SHORT);
1050
1051   rc = ksba_reader_new (&reader);
1052   if (rc)
1053     return rc;
1054   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1055   if (rc)
1056     {
1057       ksba_reader_release (reader);
1058       /* fixme: need to map the error codes */
1059       return gpg_error (GPG_ERR_GENERAL);
1060     }
1061
1062   rc = ksba_cert_new (&cert);
1063   if (rc)
1064     {
1065       ksba_reader_release (reader);
1066       return rc;
1067     }
1068
1069   rc = ksba_cert_read_der (cert, reader);
1070   if (rc)
1071     {
1072       ksba_cert_release (cert);
1073       ksba_reader_release (reader);
1074       /* fixme: need to map the error codes */
1075       return gpg_error (GPG_ERR_GENERAL);
1076     }
1077
1078   *r_cert = cert;
1079   ksba_reader_release (reader);
1080   return 0;
1081 }
1082
1083 #endif /*KEYBOX_WITH_X509*/
1084
1085 /* Return the flags named WHAT at the address of VALUE. IDX is used
1086    only for certain flags and should be 0 if not required. */
1087 int
1088 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1089 {
1090   const unsigned char *buffer;
1091   size_t length;
1092   gpg_err_code_t ec;
1093
1094   (void)idx; /* Not yet used.  */
1095
1096   if (!hd)
1097     return gpg_error (GPG_ERR_INV_VALUE);
1098   if (!hd->found.blob)
1099     return gpg_error (GPG_ERR_NOTHING_FOUND);
1100
1101   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1102   ec = get_flag_from_image (buffer, length, what, value);
1103   return ec? gpg_error (ec):0;
1104 }