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