0bd4e01828b0b75d0b0bb3d4907c57fcc39930f5
[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 <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 "../common/host2net.h"
31 #include "../common/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       if (fseeko (hd->fp, 0, SEEK_SET))
750         {
751           /* Ooops.  Seek did not work.  Close so that the search will
752            * open the file again.  */
753           fclose (hd->fp);
754           hd->fp = NULL;
755         }
756     }
757   hd->error = 0;
758   hd->eof = 0;
759   return 0;
760 }
761
762
763 /* Note: When in ephemeral mode the search function does visit all
764    blobs but in standard mode, blobs flagged as ephemeral are ignored.
765    If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
766    The value at R_SKIPPED is updated by the number of skipped long
767    records (counts PGP and X.509). */
768 gpg_error_t
769 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
770                keybox_blobtype_t want_blobtype,
771                size_t *r_descindex, unsigned long *r_skipped)
772 {
773   gpg_error_t rc;
774   size_t n;
775   int need_words, any_skip;
776   KEYBOXBLOB blob = NULL;
777   struct sn_array_s *sn_array = NULL;
778   int pk_no, uid_no;
779
780   if (!hd)
781     return gpg_error (GPG_ERR_INV_VALUE);
782
783   /* clear last found result */
784   if (hd->found.blob)
785     {
786       _keybox_release_blob (hd->found.blob);
787       hd->found.blob = NULL;
788     }
789
790   if (hd->error)
791     return hd->error; /* still in error state */
792   if (hd->eof)
793     return -1; /* still EOF */
794
795   /* figure out what information we need */
796   need_words = any_skip = 0;
797   for (n=0; n < ndesc; n++)
798     {
799       switch (desc[n].mode)
800         {
801         case KEYDB_SEARCH_MODE_WORDS:
802           need_words = 1;
803           break;
804         case KEYDB_SEARCH_MODE_FIRST:
805           /* always restart the search in this mode */
806           keybox_search_reset (hd);
807           break;
808         default:
809           break;
810         }
811       if (desc[n].skipfnc)
812         any_skip = 1;
813       if (desc[n].snlen == -1 && !sn_array)
814         {
815           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
816           if (!sn_array)
817             return (hd->error = gpg_error_from_syserror ());
818         }
819     }
820
821   (void)need_words;  /* Not yet implemented.  */
822
823   if (!hd->fp)
824     {
825       hd->fp = fopen (hd->kb->fname, "rb");
826       if (!hd->fp)
827         {
828           hd->error = gpg_error_from_syserror ();
829           xfree (sn_array);
830           return hd->error;
831         }
832     }
833
834   /* Kludge: We need to convert an SN given as hexstring to its binary
835      representation - in some cases we are not able to store it in the
836      search descriptor, because due to the way we use it, it is not
837      possible to free allocated memory. */
838   if (sn_array)
839     {
840       const unsigned char *s;
841       int i, odd;
842       size_t snlen;
843
844       for (n=0; n < ndesc; n++)
845         {
846           if (!desc[n].sn)
847             ;
848           else if (desc[n].snlen == -1)
849             {
850               unsigned char *sn;
851
852               s = desc[n].sn;
853               for (i=0; *s && *s != '/'; s++, i++)
854                 ;
855               odd = (i & 1);
856               snlen = (i+1)/2;
857               sn_array[n].sn = xtrymalloc (snlen);
858               if (!sn_array[n].sn)
859                 {
860                   hd->error = gpg_error_from_syserror ();
861                   release_sn_array (sn_array, n);
862                   return hd->error;
863                 }
864               sn_array[n].snlen = snlen;
865               sn = sn_array[n].sn;
866               s = desc[n].sn;
867               if (odd)
868                 {
869                   *sn++ = xtoi_1 (s);
870                   s++;
871                 }
872               for (; *s && *s != '/';  s += 2)
873                 *sn++ = xtoi_2 (s);
874             }
875           else
876             {
877               const unsigned char *sn;
878
879               sn = desc[n].sn;
880               snlen = desc[n].snlen;
881               sn_array[n].sn = xtrymalloc (snlen);
882               if (!sn_array[n].sn)
883                 {
884                   hd->error = gpg_error_from_syserror ();
885                   release_sn_array (sn_array, n);
886                   return hd->error;
887                 }
888               sn_array[n].snlen = snlen;
889               memcpy (sn_array[n].sn, sn, snlen);
890             }
891         }
892     }
893
894
895   pk_no = uid_no = 0;
896   for (;;)
897     {
898       unsigned int blobflags;
899       int blobtype;
900
901       _keybox_release_blob (blob); blob = NULL;
902       rc = _keybox_read_blob (&blob, hd->fp);
903       if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
904           && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
905         {
906           ++*r_skipped;
907           continue; /* Skip too large records.  */
908         }
909
910       if (rc)
911         break;
912
913       blobtype = blob_get_type (blob);
914       if (blobtype == KEYBOX_BLOBTYPE_HEADER)
915         continue;
916       if (want_blobtype && blobtype != want_blobtype)
917         continue;
918
919       blobflags = blob_get_blob_flags (blob);
920       if (!hd->ephemeral && (blobflags & 2))
921         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
922
923       for (n=0; n < ndesc; n++)
924         {
925           switch (desc[n].mode)
926             {
927             case KEYDB_SEARCH_MODE_NONE:
928               never_reached ();
929               break;
930             case KEYDB_SEARCH_MODE_EXACT:
931               uid_no = has_username (blob, desc[n].u.name, 0);
932               if (uid_no)
933                 goto found;
934               break;
935             case KEYDB_SEARCH_MODE_MAIL:
936               uid_no = has_mail (blob, desc[n].u.name, 0);
937               if (uid_no)
938                 goto found;
939               break;
940             case KEYDB_SEARCH_MODE_MAILSUB:
941               uid_no = has_mail (blob, desc[n].u.name, 1);
942               if (uid_no)
943                 goto found;
944               break;
945             case KEYDB_SEARCH_MODE_SUBSTR:
946               uid_no =  has_username (blob, desc[n].u.name, 1);
947               if (uid_no)
948                 goto found;
949               break;
950             case KEYDB_SEARCH_MODE_MAILEND:
951             case KEYDB_SEARCH_MODE_WORDS:
952               /* not yet implemented */
953               break;
954             case KEYDB_SEARCH_MODE_ISSUER:
955               if (has_issuer (blob, desc[n].u.name))
956                 goto found;
957               break;
958             case KEYDB_SEARCH_MODE_ISSUER_SN:
959               if (has_issuer_sn (blob, desc[n].u.name,
960                                  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_SN:
965               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
966                                 sn_array? sn_array[n].snlen : desc[n].snlen))
967                 goto found;
968               break;
969             case KEYDB_SEARCH_MODE_SUBJECT:
970               if (has_subject (blob, desc[n].u.name))
971                 goto found;
972               break;
973             case KEYDB_SEARCH_MODE_SHORT_KID:
974               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
975               if (pk_no)
976                 goto found;
977               break;
978             case KEYDB_SEARCH_MODE_LONG_KID:
979               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
980               if (pk_no)
981                 goto found;
982               break;
983             case KEYDB_SEARCH_MODE_FPR:
984             case KEYDB_SEARCH_MODE_FPR20:
985               pk_no = has_fingerprint (blob, desc[n].u.fpr);
986               if (pk_no)
987                 goto found;
988               break;
989             case KEYDB_SEARCH_MODE_KEYGRIP:
990               if (has_keygrip (blob, desc[n].u.grip))
991                 goto found;
992               break;
993             case KEYDB_SEARCH_MODE_FIRST:
994               goto found;
995               break;
996             case KEYDB_SEARCH_MODE_NEXT:
997               goto found;
998               break;
999             default:
1000               rc = gpg_error (GPG_ERR_INV_VALUE);
1001               goto found;
1002             }
1003         }
1004       continue;
1005     found:
1006       /* Record which DESC we matched on.  Note this value is only
1007          meaningful if this function returns with no errors. */
1008       if(r_descindex)
1009         *r_descindex = n;
1010       for (n=any_skip?0:ndesc; n < ndesc; n++)
1011         {
1012           u32 kid[2];
1013
1014           if (desc[n].skipfnc
1015               && blob_get_first_keyid (blob, kid)
1016               && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
1017                 break;
1018         }
1019       if (n == ndesc)
1020         break; /* got it */
1021     }
1022
1023   if (!rc)
1024     {
1025       hd->found.blob = blob;
1026       hd->found.pk_no = pk_no;
1027       hd->found.uid_no = uid_no;
1028     }
1029   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
1030     {
1031       _keybox_release_blob (blob);
1032       hd->eof = 1;
1033     }
1034   else
1035     {
1036       _keybox_release_blob (blob);
1037       hd->error = rc;
1038     }
1039
1040   if (sn_array)
1041     release_sn_array (sn_array, ndesc);
1042
1043   return rc;
1044 }
1045
1046
1047
1048 \f
1049 /*
1050    Functions to return a certificate or a keyblock.  To be used after
1051    a successful search operation.
1052 */
1053
1054
1055 /* Return the last found keyblock.  Returns 0 on success and stores a
1056  * new iobuf at R_IOBUF.  R_UID_NO and R_PK_NO are used to retun the
1057  * number of the key or user id which was matched the search criteria;
1058  * if not known they are set to 0. */
1059 gpg_error_t
1060 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
1061                      int *r_pk_no, int *r_uid_no)
1062 {
1063   gpg_error_t err;
1064   const unsigned char *buffer;
1065   size_t length;
1066   size_t image_off, image_len;
1067   size_t siginfo_off, siginfo_len;
1068
1069   *r_iobuf = NULL;
1070
1071   if (!hd)
1072     return gpg_error (GPG_ERR_INV_VALUE);
1073   if (!hd->found.blob)
1074     return gpg_error (GPG_ERR_NOTHING_FOUND);
1075
1076   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1077     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1078
1079   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1080   if (length < 40)
1081     return gpg_error (GPG_ERR_TOO_SHORT);
1082   image_off = get32 (buffer+8);
1083   image_len = get32 (buffer+12);
1084   if (image_off+image_len > length)
1085     return gpg_error (GPG_ERR_TOO_SHORT);
1086
1087   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1088                                    &siginfo_off, &siginfo_len);
1089   if (err)
1090     return err;
1091
1092   *r_pk_no  = hd->found.pk_no;
1093   *r_uid_no = hd->found.uid_no;
1094   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1095   return 0;
1096 }
1097
1098
1099 #ifdef KEYBOX_WITH_X509
1100 /*
1101   Return the last found cert.  Caller must free it.
1102  */
1103 int
1104 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1105 {
1106   const unsigned char *buffer;
1107   size_t length;
1108   size_t cert_off, cert_len;
1109   ksba_reader_t reader = NULL;
1110   ksba_cert_t cert = NULL;
1111   int rc;
1112
1113   if (!hd)
1114     return gpg_error (GPG_ERR_INV_VALUE);
1115   if (!hd->found.blob)
1116     return gpg_error (GPG_ERR_NOTHING_FOUND);
1117
1118   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
1119     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1120
1121   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1122   if (length < 40)
1123     return gpg_error (GPG_ERR_TOO_SHORT);
1124   cert_off = get32 (buffer+8);
1125   cert_len = get32 (buffer+12);
1126   if (cert_off+cert_len > length)
1127     return gpg_error (GPG_ERR_TOO_SHORT);
1128
1129   rc = ksba_reader_new (&reader);
1130   if (rc)
1131     return rc;
1132   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1133   if (rc)
1134     {
1135       ksba_reader_release (reader);
1136       /* fixme: need to map the error codes */
1137       return gpg_error (GPG_ERR_GENERAL);
1138     }
1139
1140   rc = ksba_cert_new (&cert);
1141   if (rc)
1142     {
1143       ksba_reader_release (reader);
1144       return rc;
1145     }
1146
1147   rc = ksba_cert_read_der (cert, reader);
1148   if (rc)
1149     {
1150       ksba_cert_release (cert);
1151       ksba_reader_release (reader);
1152       /* fixme: need to map the error codes */
1153       return gpg_error (GPG_ERR_GENERAL);
1154     }
1155
1156   *r_cert = cert;
1157   ksba_reader_release (reader);
1158   return 0;
1159 }
1160
1161 #endif /*KEYBOX_WITH_X509*/
1162
1163 /* Return the flags named WHAT at the address of VALUE. IDX is used
1164    only for certain flags and should be 0 if not required. */
1165 int
1166 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1167 {
1168   const unsigned char *buffer;
1169   size_t length;
1170   gpg_err_code_t ec;
1171
1172   (void)idx; /* Not yet used.  */
1173
1174   if (!hd)
1175     return gpg_error (GPG_ERR_INV_VALUE);
1176   if (!hd->found.blob)
1177     return gpg_error (GPG_ERR_NOTHING_FOUND);
1178
1179   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1180   ec = get_flag_from_image (buffer, length, what, value);
1181   return ec? gpg_error (ec):0;
1182 }
1183
1184 off_t
1185 keybox_offset (KEYBOX_HANDLE hd)
1186 {
1187   if (!hd->fp)
1188     return 0;
1189   return ftello (hd->fp);
1190 }
1191
1192 gpg_error_t
1193 keybox_seek (KEYBOX_HANDLE hd, off_t offset)
1194 {
1195   int err;
1196
1197   if (hd->error)
1198     return hd->error; /* still in error state */
1199
1200   if (! hd->fp)
1201     {
1202       if (offset == 0)
1203         /* No need to open the file.  An unopened file is effectively at
1204            offset 0.  */
1205         return 0;
1206
1207       hd->fp = fopen (hd->kb->fname, "rb");
1208       if (!hd->fp)
1209         {
1210           hd->error = gpg_error_from_syserror ();
1211           return hd->error;
1212         }
1213     }
1214
1215   err = fseeko (hd->fp, offset, SEEK_SET);
1216   hd->error = gpg_error_from_errno (err);
1217
1218   return hd->error;
1219 }