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