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