gpg: Consider a mailbox only userid in mail search mode.
[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 #endif
615   return 0;
616 }
617
618
619 static inline int
620 has_issuer (KEYBOXBLOB blob, const char *name)
621 {
622   size_t namelen;
623
624   return_val_if_fail (name, 0);
625
626   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
627     return 0;
628
629   namelen = strlen (name);
630   return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
631 }
632
633 static inline int
634 has_issuer_sn (KEYBOXBLOB blob, const char *name,
635                const unsigned char *sn, int snlen)
636 {
637   size_t namelen;
638
639   return_val_if_fail (name, 0);
640   return_val_if_fail (sn, 0);
641
642   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
643     return 0;
644
645   namelen = strlen (name);
646
647   return (blob_cmp_sn (blob, sn, snlen)
648           && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
649 }
650
651 static inline int
652 has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
653 {
654   return_val_if_fail (sn, 0);
655
656   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
657     return 0;
658   return blob_cmp_sn (blob, sn, snlen);
659 }
660
661 static inline int
662 has_subject (KEYBOXBLOB blob, const char *name)
663 {
664   size_t namelen;
665
666   return_val_if_fail (name, 0);
667
668   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
669     return 0;
670
671   namelen = strlen (name);
672   return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
673 }
674
675
676 static inline int
677 has_username (KEYBOXBLOB blob, const char *name, int substr)
678 {
679   size_t namelen;
680   int btype;
681
682   return_val_if_fail (name, 0);
683
684   btype = blob_get_type (blob);
685   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
686     return 0;
687
688   namelen = strlen (name);
689   return blob_cmp_name (blob, -1 /* all subject/user names */, name,
690                         namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
691 }
692
693
694 static inline int
695 has_mail (KEYBOXBLOB blob, const char *name, int substr)
696 {
697   size_t namelen;
698   int btype;
699
700   return_val_if_fail (name, 0);
701
702   btype = blob_get_type (blob);
703   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
704     return 0;
705
706   if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
707     name++; /* Hack to remove the leading '<' for gpg.  */
708
709   namelen = strlen (name);
710   if (namelen && name[namelen-1] == '>')
711     namelen--;
712   return blob_cmp_mail (blob, name, namelen, substr,
713                         (btype == KEYBOX_BLOBTYPE_X509));
714 }
715
716
717 static void
718 release_sn_array (struct sn_array_s *array, size_t size)
719 {
720   size_t n;
721
722   for (n=0; n < size; n++)
723     xfree (array[n].sn);
724   xfree (array);
725 }
726
727 \f
728 /*
729
730   The search API
731
732 */
733
734 int
735 keybox_search_reset (KEYBOX_HANDLE hd)
736 {
737   if (!hd)
738     return gpg_error (GPG_ERR_INV_VALUE);
739
740   if (hd->found.blob)
741     {
742       _keybox_release_blob (hd->found.blob);
743       hd->found.blob = NULL;
744     }
745
746   if (hd->fp)
747     {
748       fclose (hd->fp);
749       hd->fp = NULL;
750     }
751   hd->error = 0;
752   hd->eof = 0;
753   return 0;
754 }
755
756
757 /* Note: When in ephemeral mode the search function does visit all
758    blobs but in standard mode, blobs flagged as ephemeral are ignored.
759    If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
760    The value at R_SKIPPED is updated by the number of skipped long
761    records (counts PGP and X.509). */
762 int
763 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
764                keybox_blobtype_t want_blobtype,
765                size_t *r_descindex, unsigned long *r_skipped)
766 {
767   int rc;
768   size_t n;
769   int need_words, any_skip;
770   KEYBOXBLOB blob = NULL;
771   struct sn_array_s *sn_array = NULL;
772   int pk_no, uid_no;
773
774   if (!hd)
775     return gpg_error (GPG_ERR_INV_VALUE);
776
777   /* clear last found result */
778   if (hd->found.blob)
779     {
780       _keybox_release_blob (hd->found.blob);
781       hd->found.blob = NULL;
782     }
783
784   if (hd->error)
785     return hd->error; /* still in error state */
786   if (hd->eof)
787     return -1; /* still EOF */
788
789   /* figure out what information we need */
790   need_words = any_skip = 0;
791   for (n=0; n < ndesc; n++)
792     {
793       switch (desc[n].mode)
794         {
795         case KEYDB_SEARCH_MODE_WORDS:
796           need_words = 1;
797           break;
798         case KEYDB_SEARCH_MODE_FIRST:
799           /* always restart the search in this mode */
800           keybox_search_reset (hd);
801           break;
802         default:
803           break;
804         }
805       if (desc[n].skipfnc)
806         any_skip = 1;
807       if (desc[n].snlen == -1 && !sn_array)
808         {
809           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
810           if (!sn_array)
811             return (hd->error = gpg_error_from_syserror ());
812         }
813     }
814
815   (void)need_words;  /* Not yet implemented.  */
816
817   if (!hd->fp)
818     {
819       hd->fp = fopen (hd->kb->fname, "rb");
820       if (!hd->fp)
821         {
822           hd->error = gpg_error_from_syserror ();
823           xfree (sn_array);
824           return hd->error;
825         }
826     }
827
828   /* Kludge: We need to convert an SN given as hexstring to its binary
829      representation - in some cases we are not able to store it in the
830      search descriptor, because due to the way we use it, it is not
831      possible to free allocated memory. */
832   if (sn_array)
833     {
834       const unsigned char *s;
835       int i, odd;
836       size_t snlen;
837
838       for (n=0; n < ndesc; n++)
839         {
840           if (!desc[n].sn)
841             ;
842           else if (desc[n].snlen == -1)
843             {
844               unsigned char *sn;
845
846               s = desc[n].sn;
847               for (i=0; *s && *s != '/'; s++, i++)
848                 ;
849               odd = (i & 1);
850               snlen = (i+1)/2;
851               sn_array[n].sn = xtrymalloc (snlen);
852               if (!sn_array[n].sn)
853                 {
854                   hd->error = gpg_error_from_syserror ();
855                   release_sn_array (sn_array, n);
856                   return hd->error;
857                 }
858               sn_array[n].snlen = snlen;
859               sn = sn_array[n].sn;
860               s = desc[n].sn;
861               if (odd)
862                 {
863                   *sn++ = xtoi_1 (s);
864                   s++;
865                 }
866               for (; *s && *s != '/';  s += 2)
867                 *sn++ = xtoi_2 (s);
868             }
869           else
870             {
871               const unsigned char *sn;
872
873               sn = desc[n].sn;
874               snlen = desc[n].snlen;
875               sn_array[n].sn = xtrymalloc (snlen);
876               if (!sn_array[n].sn)
877                 {
878                   hd->error = gpg_error_from_syserror ();
879                   release_sn_array (sn_array, n);
880                   return hd->error;
881                 }
882               sn_array[n].snlen = snlen;
883               memcpy (sn_array[n].sn, sn, snlen);
884             }
885         }
886     }
887
888
889   pk_no = uid_no = 0;
890   for (;;)
891     {
892       unsigned int blobflags;
893       int blobtype;
894
895       _keybox_release_blob (blob); blob = NULL;
896       rc = _keybox_read_blob (&blob, hd->fp);
897       if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
898           && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
899         {
900           ++*r_skipped;
901           continue; /* Skip too large records.  */
902         }
903
904       if (rc)
905         break;
906
907       blobtype = blob_get_type (blob);
908       if (blobtype == KEYBOX_BLOBTYPE_HEADER)
909         continue;
910       if (want_blobtype && blobtype != want_blobtype)
911         continue;
912
913       blobflags = blob_get_blob_flags (blob);
914       if (!hd->ephemeral && (blobflags & 2))
915         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
916
917       for (n=0; n < ndesc; n++)
918         {
919           switch (desc[n].mode)
920             {
921             case KEYDB_SEARCH_MODE_NONE:
922               never_reached ();
923               break;
924             case KEYDB_SEARCH_MODE_EXACT:
925               uid_no = has_username (blob, desc[n].u.name, 0);
926               if (uid_no)
927                 goto found;
928               break;
929             case KEYDB_SEARCH_MODE_MAIL:
930               uid_no = has_mail (blob, desc[n].u.name, 0);
931               if (uid_no)
932                 goto found;
933               break;
934             case KEYDB_SEARCH_MODE_MAILSUB:
935               uid_no = has_mail (blob, desc[n].u.name, 1);
936               if (uid_no)
937                 goto found;
938               break;
939             case KEYDB_SEARCH_MODE_SUBSTR:
940               uid_no =  has_username (blob, desc[n].u.name, 1);
941               if (uid_no)
942                 goto found;
943               break;
944             case KEYDB_SEARCH_MODE_MAILEND:
945             case KEYDB_SEARCH_MODE_WORDS:
946               /* not yet implemented */
947               break;
948             case KEYDB_SEARCH_MODE_ISSUER:
949               if (has_issuer (blob, desc[n].u.name))
950                 goto found;
951               break;
952             case KEYDB_SEARCH_MODE_ISSUER_SN:
953               if (has_issuer_sn (blob, desc[n].u.name,
954                                  sn_array? sn_array[n].sn : desc[n].sn,
955                                  sn_array? sn_array[n].snlen : desc[n].snlen))
956                 goto found;
957               break;
958             case KEYDB_SEARCH_MODE_SN:
959               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
960                                 sn_array? sn_array[n].snlen : desc[n].snlen))
961                 goto found;
962               break;
963             case KEYDB_SEARCH_MODE_SUBJECT:
964               if (has_subject (blob, desc[n].u.name))
965                 goto found;
966               break;
967             case KEYDB_SEARCH_MODE_SHORT_KID:
968               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
969               if (pk_no)
970                 goto found;
971               break;
972             case KEYDB_SEARCH_MODE_LONG_KID:
973               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
974               if (pk_no)
975                 goto found;
976               break;
977             case KEYDB_SEARCH_MODE_FPR:
978             case KEYDB_SEARCH_MODE_FPR20:
979               pk_no = has_fingerprint (blob, desc[n].u.fpr);
980               if (pk_no)
981                 goto found;
982               break;
983             case KEYDB_SEARCH_MODE_KEYGRIP:
984               if (has_keygrip (blob, desc[n].u.grip))
985                 goto found;
986               break;
987             case KEYDB_SEARCH_MODE_FIRST:
988               goto found;
989               break;
990             case KEYDB_SEARCH_MODE_NEXT:
991               goto found;
992               break;
993             default:
994               rc = gpg_error (GPG_ERR_INV_VALUE);
995               goto found;
996             }
997         }
998       continue;
999     found:
1000       /* Record which DESC we matched on.  Note this value is only
1001          meaningful if this function returns with no errors. */
1002       if(r_descindex)
1003         *r_descindex = n;
1004       for (n=any_skip?0:ndesc; n < ndesc; n++)
1005         {
1006           u32 kid[2];
1007
1008           if (desc[n].skipfnc
1009               && blob_get_first_keyid (blob, kid)
1010               && desc[n].skipfnc (desc[n].skipfncvalue, kid, NULL))
1011             break;
1012         }
1013       if (n == ndesc)
1014         break; /* got it */
1015     }
1016
1017   if (!rc)
1018     {
1019       hd->found.blob = blob;
1020       hd->found.pk_no = pk_no;
1021       hd->found.uid_no = uid_no;
1022     }
1023   else if (rc == -1)
1024     {
1025       _keybox_release_blob (blob);
1026       hd->eof = 1;
1027     }
1028   else
1029     {
1030       _keybox_release_blob (blob);
1031       hd->error = rc;
1032     }
1033
1034   if (sn_array)
1035     release_sn_array (sn_array, ndesc);
1036
1037   return rc;
1038 }
1039
1040
1041
1042 \f
1043 /*
1044    Functions to return a certificate or a keyblock.  To be used after
1045    a successful search operation.
1046 */
1047
1048
1049 /* Return the last found keyblock.  Returns 0 on success and stores a
1050    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
1051    in that case.  R_UID_NO and R_PK_NO are used to retun the number of
1052    the key or user id which was matched the search criteria; if not
1053    known they are set to 0. */
1054 gpg_error_t
1055 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
1056                      int *r_pk_no, int *r_uid_no, u32 **r_sigstatus)
1057 {
1058   gpg_error_t err;
1059   const unsigned char *buffer, *p;
1060   size_t length;
1061   size_t image_off, image_len;
1062   size_t siginfo_off, siginfo_len;
1063   u32 *sigstatus, n, n_sigs, sigilen;
1064
1065   *r_iobuf = NULL;
1066   *r_sigstatus = NULL;
1067
1068   if (!hd)
1069     return gpg_error (GPG_ERR_INV_VALUE);
1070   if (!hd->found.blob)
1071     return gpg_error (GPG_ERR_NOTHING_FOUND);
1072
1073   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1074     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1075
1076   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1077   if (length < 40)
1078     return gpg_error (GPG_ERR_TOO_SHORT);
1079   image_off = get32 (buffer+8);
1080   image_len = get32 (buffer+12);
1081   if (image_off+image_len > length)
1082     return gpg_error (GPG_ERR_TOO_SHORT);
1083
1084   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1085                                    &siginfo_off, &siginfo_len);
1086   if (err)
1087     return err;
1088   n_sigs  = get16 (buffer + siginfo_off);
1089   sigilen = get16 (buffer + siginfo_off + 2);
1090   p = buffer + siginfo_off + 4;
1091   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
1092   if (!sigstatus)
1093     return gpg_error_from_syserror ();
1094   sigstatus[0] = n_sigs;
1095   for (n=1; n <= n_sigs; n++, p += sigilen)
1096     sigstatus[n] = get32 (p);
1097
1098   *r_pk_no  = hd->found.pk_no;
1099   *r_uid_no = hd->found.uid_no;
1100   *r_sigstatus = sigstatus;
1101   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1102   return 0;
1103 }
1104
1105
1106 #ifdef KEYBOX_WITH_X509
1107 /*
1108   Return the last found cert.  Caller must free it.
1109  */
1110 int
1111 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1112 {
1113   const unsigned char *buffer;
1114   size_t length;
1115   size_t cert_off, cert_len;
1116   ksba_reader_t reader = NULL;
1117   ksba_cert_t cert = NULL;
1118   int rc;
1119
1120   if (!hd)
1121     return gpg_error (GPG_ERR_INV_VALUE);
1122   if (!hd->found.blob)
1123     return gpg_error (GPG_ERR_NOTHING_FOUND);
1124
1125   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
1126     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1127
1128   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1129   if (length < 40)
1130     return gpg_error (GPG_ERR_TOO_SHORT);
1131   cert_off = get32 (buffer+8);
1132   cert_len = get32 (buffer+12);
1133   if (cert_off+cert_len > length)
1134     return gpg_error (GPG_ERR_TOO_SHORT);
1135
1136   rc = ksba_reader_new (&reader);
1137   if (rc)
1138     return rc;
1139   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1140   if (rc)
1141     {
1142       ksba_reader_release (reader);
1143       /* fixme: need to map the error codes */
1144       return gpg_error (GPG_ERR_GENERAL);
1145     }
1146
1147   rc = ksba_cert_new (&cert);
1148   if (rc)
1149     {
1150       ksba_reader_release (reader);
1151       return rc;
1152     }
1153
1154   rc = ksba_cert_read_der (cert, reader);
1155   if (rc)
1156     {
1157       ksba_cert_release (cert);
1158       ksba_reader_release (reader);
1159       /* fixme: need to map the error codes */
1160       return gpg_error (GPG_ERR_GENERAL);
1161     }
1162
1163   *r_cert = cert;
1164   ksba_reader_release (reader);
1165   return 0;
1166 }
1167
1168 #endif /*KEYBOX_WITH_X509*/
1169
1170 /* Return the flags named WHAT at the address of VALUE. IDX is used
1171    only for certain flags and should be 0 if not required. */
1172 int
1173 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1174 {
1175   const unsigned char *buffer;
1176   size_t length;
1177   gpg_err_code_t ec;
1178
1179   (void)idx; /* Not yet used.  */
1180
1181   if (!hd)
1182     return gpg_error (GPG_ERR_INV_VALUE);
1183   if (!hd->found.blob)
1184     return gpg_error (GPG_ERR_NOTHING_FOUND);
1185
1186   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1187   ec = get_flag_from_image (buffer, length, what, value);
1188   return ec? gpg_error (ec):0;
1189 }