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