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