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