gpg: Allow searching for user ids in a keybox.
[gnupg.git] / kbx / keybox-search.c
1 /* keybox-search.c - Search operations
2  * Copyright (C) 2001, 2002, 2003, 2004, 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
26
27 #include "../common/stringhelp.h" /* ascii_xxxx() */
28
29 #include "keybox-defs.h"
30 #include <gcrypt.h>
31
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
45 static inline ulong
46 get32 (const byte *buffer)
47 {
48   ulong a;
49   a =  *buffer << 24;
50   a |= buffer[1] << 16;
51   a |= buffer[2] << 8;
52   a |= buffer[3];
53   return a;
54 }
55
56 static inline ulong
57 get16 (const byte *buffer)
58 {
59   ulong a;
60   a =  *buffer << 8;
61   a |= buffer[1];
62   return a;
63 }
64
65
66
67 static inline int
68 blob_get_type (KEYBOXBLOB blob)
69 {
70   const unsigned char *buffer;
71   size_t length;
72
73   buffer = _keybox_get_blob_image (blob, &length);
74   if (length < 32)
75     return -1; /* blob too short */
76
77   return buffer[4];
78 }
79
80 static inline unsigned int
81 blob_get_blob_flags (KEYBOXBLOB blob)
82 {
83   const unsigned char *buffer;
84   size_t length;
85
86   buffer = _keybox_get_blob_image (blob, &length);
87   if (length < 8)
88     return 0; /* oops */
89
90   return get16 (buffer + 6);
91 }
92
93
94 /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
95    Return the offset and the length (in bytes) of the flag in
96    FLAGOFF,FLAG_SIZE. */
97 gpg_err_code_t
98 _keybox_get_flag_location (const unsigned char *buffer, size_t length,
99                            int what, size_t *flag_off, size_t *flag_size)
100 {
101   size_t pos;
102   size_t nkeys, keyinfolen;
103   size_t nuids, uidinfolen;
104   size_t nserial;
105   size_t nsigs, siginfolen, siginfooff;
106
107   switch (what)
108     {
109     case KEYBOX_FLAG_BLOB:
110       if (length < 8)
111         return GPG_ERR_INV_OBJ;
112       *flag_off = 6;
113       *flag_size = 2;
114       break;
115
116     case KEYBOX_FLAG_OWNERTRUST:
117     case KEYBOX_FLAG_VALIDITY:
118     case KEYBOX_FLAG_CREATED_AT:
119     case KEYBOX_FLAG_SIG_INFO:
120       if (length < 20)
121         return GPG_ERR_INV_OBJ;
122       /* Key info. */
123       nkeys = get16 (buffer + 16);
124       keyinfolen = get16 (buffer + 18 );
125       if (keyinfolen < 28)
126         return GPG_ERR_INV_OBJ;
127       pos = 20 + keyinfolen*nkeys;
128       if (pos+2 > length)
129         return GPG_ERR_INV_OBJ; /* Out of bounds. */
130       /* Serial number. */
131       nserial = get16 (buffer+pos);
132       pos += 2 + nserial;
133       if (pos+4 > length)
134         return GPG_ERR_INV_OBJ; /* Out of bounds. */
135       /* User IDs. */
136       nuids = get16 (buffer + pos); pos += 2;
137       uidinfolen = get16 (buffer + pos); pos += 2;
138       if (uidinfolen < 12 )
139         return GPG_ERR_INV_OBJ;
140       pos += uidinfolen*nuids;
141       if (pos+4 > length)
142         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
143       /* Signature info. */
144       siginfooff = pos;
145       nsigs = get16 (buffer + pos); pos += 2;
146       siginfolen = get16 (buffer + pos); pos += 2;
147       if (siginfolen < 4 )
148         return GPG_ERR_INV_OBJ;
149       pos += siginfolen*nsigs;
150       if (pos+1+1+2+4+4+4+4 > length)
151         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
152       *flag_size = 1;
153       *flag_off = pos;
154       switch (what)
155         {
156         case KEYBOX_FLAG_VALIDITY:
157           *flag_off += 1;
158           break;
159         case KEYBOX_FLAG_CREATED_AT:
160           *flag_size = 4;
161           *flag_off += 1+2+4+4+4;
162           break;
163         case KEYBOX_FLAG_SIG_INFO:
164           *flag_size = siginfolen * nsigs;
165           *flag_off = siginfooff;
166           break;
167         default:
168           break;
169         }
170       break;
171
172     default:
173       return GPG_ERR_INV_FLAG;
174     }
175   return 0;
176 }
177
178
179
180 /* Return one of the flags WHAT in VALUE from teh blob BUFFER of
181    LENGTH bytes.  Return 0 on success or an raw error code. */
182 static gpg_err_code_t
183 get_flag_from_image (const unsigned char *buffer, size_t length,
184                      int what, unsigned int *value)
185 {
186   gpg_err_code_t ec;
187   size_t pos, size;
188
189   *value = 0;
190   ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
191   if (!ec)
192     switch (size)
193       {
194       case 1: *value = buffer[pos]; break;
195       case 2: *value = get16 (buffer + pos); break;
196       case 4: *value = get32 (buffer + pos); break;
197       default: ec = GPG_ERR_BUG; break;
198       }
199
200   return ec;
201 }
202
203
204 static int
205 blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
206 {
207   const unsigned char *buffer;
208   size_t length;
209   size_t pos, off;
210   size_t nkeys, keyinfolen;
211   size_t nserial;
212
213   buffer = _keybox_get_blob_image (blob, &length);
214   if (length < 40)
215     return 0; /* blob too short */
216
217   /*keys*/
218   nkeys = get16 (buffer + 16);
219   keyinfolen = get16 (buffer + 18 );
220   if (keyinfolen < 28)
221     return 0; /* invalid blob */
222   pos = 20 + keyinfolen*nkeys;
223   if (pos+2 > length)
224     return 0; /* out of bounds */
225
226   /*serial*/
227   nserial = get16 (buffer+pos);
228   off = pos + 2;
229   if (off+nserial > length)
230     return 0; /* out of bounds */
231
232   return nserial == snlen && !memcmp (buffer+off, sn, snlen);
233 }
234
235
236 static int
237 blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
238 {
239   const unsigned char *buffer;
240   size_t length;
241   size_t pos, off;
242   size_t nkeys, keyinfolen;
243   int idx;
244
245   buffer = _keybox_get_blob_image (blob, &length);
246   if (length < 40)
247     return 0; /* blob too short */
248
249   /*keys*/
250   nkeys = get16 (buffer + 16);
251   keyinfolen = get16 (buffer + 18 );
252   if (keyinfolen < 28)
253     return 0; /* invalid blob */
254   pos = 20;
255   if (pos + keyinfolen*nkeys > length)
256     return 0; /* out of bounds */
257
258   for (idx=0; idx < nkeys; idx++)
259     {
260       off = pos + idx*keyinfolen;
261       if (!memcmp (buffer + off, fpr, 20))
262         return 1; /* found */
263     }
264   return 0; /* not found */
265 }
266
267 static int
268 blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
269                    int fproff, int fprlen)
270 {
271   const unsigned char *buffer;
272   size_t length;
273   size_t pos, off;
274   size_t nkeys, keyinfolen;
275   int idx;
276
277   buffer = _keybox_get_blob_image (blob, &length);
278   if (length < 40)
279     return 0; /* blob too short */
280
281   /*keys*/
282   nkeys = get16 (buffer + 16);
283   keyinfolen = get16 (buffer + 18 );
284   if (keyinfolen < 28)
285     return 0; /* invalid blob */
286   pos = 20;
287   if (pos + keyinfolen*nkeys > length)
288     return 0; /* out of bounds */
289
290   for (idx=0; idx < nkeys; idx++)
291     {
292       off = pos + idx*keyinfolen;
293       if (!memcmp (buffer + off + fproff, fpr, fprlen))
294         return 1; /* found */
295     }
296   return 0; /* not found */
297 }
298
299
300 static int
301 blob_cmp_name (KEYBOXBLOB blob, int idx,
302                const char *name, size_t namelen, int substr, int x509)
303 {
304   const unsigned char *buffer;
305   size_t length;
306   size_t pos, off, len;
307   size_t nkeys, keyinfolen;
308   size_t nuids, uidinfolen;
309   size_t nserial;
310
311   buffer = _keybox_get_blob_image (blob, &length);
312   if (length < 40)
313     return 0; /* blob too short */
314
315   /*keys*/
316   nkeys = get16 (buffer + 16);
317   keyinfolen = get16 (buffer + 18 );
318   if (keyinfolen < 28)
319     return 0; /* invalid blob */
320   pos = 20 + keyinfolen*nkeys;
321   if (pos+2 > length)
322     return 0; /* out of bounds */
323
324   /*serial*/
325   nserial = get16 (buffer+pos);
326   pos += 2 + nserial;
327   if (pos+4 > length)
328     return 0; /* out of bounds */
329
330   /* user ids*/
331   nuids = get16 (buffer + pos);  pos += 2;
332   uidinfolen = get16 (buffer + pos);  pos += 2;
333   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
334     return 0; /* invalid blob */
335   if (pos + uidinfolen*nuids > length)
336     return 0; /* out of bounds */
337
338   if (idx < 0)
339     { /* Compare all names.  Note that for X.509 we start with index 1
340          so to skip the issuer at index 0.  */
341       for (idx = !!x509; idx < nuids; idx++)
342         {
343           size_t mypos = pos;
344
345           mypos += idx*uidinfolen;
346           off = get32 (buffer+mypos);
347           len = get32 (buffer+mypos+4);
348           if (off+len > length)
349             return 0; /* error: better stop here out of bounds */
350           if (len < 1)
351             continue; /* empty name */
352           if (substr)
353             {
354               if (ascii_memcasemem (buffer+off, len, name, namelen))
355                 return 1; /* found */
356             }
357           else
358             {
359               if (len == namelen && !memcmp (buffer+off, name, len))
360                 return 1; /* found */
361             }
362         }
363       return 0; /* not found */
364     }
365   else
366     {
367       if (idx > nuids)
368         return 0; /* no user ID with that idx */
369       pos += idx*uidinfolen;
370       off = get32 (buffer+pos);
371       len = get32 (buffer+pos+4);
372       if (off+len > length)
373         return 0; /* out of bounds */
374       if (len < 1)
375         return 0; /* empty name */
376
377       if (substr)
378         {
379           return !!ascii_memcasemem (buffer+off, len, name, namelen);
380         }
381       else
382         {
383           return len == namelen && !memcmp (buffer+off, name, len);
384         }
385     }
386 }
387
388
389 /* Compare all email addresses of the subject.  With SUBSTR given as
390    True a substring search is done in the mail address.  If X509
391    states whether thr search is done on an X.509 blob.  */
392 static int
393 blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
394                int x509)
395 {
396   const unsigned char *buffer;
397   size_t length;
398   size_t pos, off, len;
399   size_t nkeys, keyinfolen;
400   size_t nuids, uidinfolen;
401   size_t nserial;
402   int idx;
403
404   /* fixme: this code is common to blob_cmp_mail */
405   buffer = _keybox_get_blob_image (blob, &length);
406   if (length < 40)
407     return 0; /* blob too short */
408
409   /*keys*/
410   nkeys = get16 (buffer + 16);
411   keyinfolen = get16 (buffer + 18 );
412   if (keyinfolen < 28)
413     return 0; /* invalid blob */
414   pos = 20 + keyinfolen*nkeys;
415   if (pos+2 > length)
416     return 0; /* out of bounds */
417
418   /*serial*/
419   nserial = get16 (buffer+pos);
420   pos += 2 + nserial;
421   if (pos+4 > length)
422     return 0; /* out of bounds */
423
424   /* user ids*/
425   nuids = get16 (buffer + pos);  pos += 2;
426   uidinfolen = get16 (buffer + pos);  pos += 2;
427   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
428     return 0; /* invalid blob */
429   if (pos + uidinfolen*nuids > length)
430     return 0; /* out of bounds */
431
432   if (namelen < 1)
433     return 0;
434
435   /* Note that for X.509 we start at index 1 becuase index 0 is used
436      for the issuer name.  */
437   for (idx=!!x509 ;idx < nuids; idx++)
438     {
439       size_t mypos = pos;
440
441       mypos += idx*uidinfolen;
442       off = get32 (buffer+mypos);
443       len = get32 (buffer+mypos+4);
444       if (off+len > length)
445         return 0; /* error: better stop here out of bounds */
446       if (!x509)
447         {
448           /* For OpenPGP we need to forward to the mailbox part.  */
449           for ( ;len && buffer[off] != '<'; len--, off++)
450             ;
451         }
452       if (len < 2 || buffer[off] != '<')
453         continue; /* empty name or trailing 0 not stored */
454       len--; /* one back */
455       if ( len < 3 || buffer[off+len] != '>')
456         continue; /* not a proper email address */
457       len--;
458       if (substr)
459         {
460           if (ascii_memcasemem (buffer+off+1, len, name, namelen))
461             return 1; /* found */
462         }
463       else
464         {
465           if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len))
466             return 1; /* found */
467         }
468     }
469   return 0; /* not found */
470 }
471
472
473 #ifdef KEYBOX_WITH_X509
474 /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
475    We don't have the keygrips as meta data, thus we need to parse the
476    certificate. Fixme: We might want to return proper error codes
477    instead of failing a search for invalid certificates etc.  */
478 static int
479 blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
480 {
481   int rc;
482   const unsigned char *buffer;
483   size_t length;
484   size_t cert_off, cert_len;
485   ksba_reader_t reader = NULL;
486   ksba_cert_t cert = NULL;
487   ksba_sexp_t p = NULL;
488   gcry_sexp_t s_pkey;
489   unsigned char array[20];
490   unsigned char *rcp;
491   size_t n;
492
493   buffer = _keybox_get_blob_image (blob, &length);
494   if (length < 40)
495     return 0; /* Too short. */
496   cert_off = get32 (buffer+8);
497   cert_len = get32 (buffer+12);
498   if (cert_off+cert_len > length)
499     return 0; /* Too short.  */
500
501   rc = ksba_reader_new (&reader);
502   if (rc)
503     return 0; /* Problem with ksba. */
504   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
505   if (rc)
506     goto failed;
507   rc = ksba_cert_new (&cert);
508   if (rc)
509     goto failed;
510   rc = ksba_cert_read_der (cert, reader);
511   if (rc)
512     goto failed;
513   p = ksba_cert_get_public_key (cert);
514   if (!p)
515     goto failed;
516   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
517   if (!n)
518     goto failed;
519   rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
520   if (rc)
521     {
522       gcry_sexp_release (s_pkey);
523       goto failed;
524     }
525   rcp = gcry_pk_get_keygrip (s_pkey, array);
526   gcry_sexp_release (s_pkey);
527   if (!rcp)
528     goto failed; /* Can't calculate keygrip. */
529
530   xfree (p);
531   ksba_cert_release (cert);
532   ksba_reader_release (reader);
533   return !memcmp (array, grip, 20);
534  failed:
535   xfree (p);
536   ksba_cert_release (cert);
537   ksba_reader_release (reader);
538   return 0;
539 }
540 #endif /*KEYBOX_WITH_X509*/
541
542
543 \f
544 /*
545   The has_foo functions are used as helpers for search
546 */
547 static inline int
548 has_short_kid (KEYBOXBLOB blob, u32 lkid)
549 {
550   unsigned char buf[4];
551   buf[0] = lkid >> 24;
552   buf[1] = lkid >> 16;
553   buf[2] = lkid >> 8;
554   buf[3] = lkid;
555   return blob_cmp_fpr_part (blob, buf, 16, 4);
556 }
557
558 static inline int
559 has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
560 {
561   unsigned char buf[8];
562   buf[0] = mkid >> 24;
563   buf[1] = mkid >> 16;
564   buf[2] = mkid >> 8;
565   buf[3] = mkid;
566   buf[4] = lkid >> 24;
567   buf[5] = lkid >> 16;
568   buf[6] = lkid >> 8;
569   buf[7] = lkid;
570   return blob_cmp_fpr_part (blob, buf, 12, 8);
571 }
572
573 static inline int
574 has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
575 {
576   return blob_cmp_fpr (blob, fpr);
577 }
578
579 static inline int
580 has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
581 {
582 #ifdef KEYBOX_WITH_X509
583   if (blob_get_type (blob) == BLOBTYPE_X509)
584     return blob_x509_has_grip (blob, grip);
585 #endif
586   return 0;
587 }
588
589
590 static inline int
591 has_issuer (KEYBOXBLOB blob, const char *name)
592 {
593   size_t namelen;
594
595   return_val_if_fail (name, 0);
596
597   if (blob_get_type (blob) != BLOBTYPE_X509)
598     return 0;
599
600   namelen = strlen (name);
601   return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
602 }
603
604 static inline int
605 has_issuer_sn (KEYBOXBLOB blob, const char *name,
606                const unsigned char *sn, int snlen)
607 {
608   size_t namelen;
609
610   return_val_if_fail (name, 0);
611   return_val_if_fail (sn, 0);
612
613   if (blob_get_type (blob) != BLOBTYPE_X509)
614     return 0;
615
616   namelen = strlen (name);
617
618   return (blob_cmp_sn (blob, sn, snlen)
619           && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
620 }
621
622 static inline int
623 has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
624 {
625   return_val_if_fail (sn, 0);
626
627   if (blob_get_type (blob) != BLOBTYPE_X509)
628     return 0;
629   return blob_cmp_sn (blob, sn, snlen);
630 }
631
632 static inline int
633 has_subject (KEYBOXBLOB blob, const char *name)
634 {
635   size_t namelen;
636
637   return_val_if_fail (name, 0);
638
639   if (blob_get_type (blob) != BLOBTYPE_X509)
640     return 0;
641
642   namelen = strlen (name);
643   return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
644 }
645
646
647 static inline int
648 has_username (KEYBOXBLOB blob, const char *name, int substr)
649 {
650   size_t namelen;
651   int btype;
652
653   return_val_if_fail (name, 0);
654
655   btype = blob_get_type (blob);
656   if (btype != BLOBTYPE_PGP && btype != BLOBTYPE_X509)
657     return 0;
658
659   namelen = strlen (name);
660   return blob_cmp_name (blob, -1 /* all subject/user names */, name,
661                         namelen, substr, (btype == BLOBTYPE_X509));
662 }
663
664
665 static inline int
666 has_mail (KEYBOXBLOB blob, const char *name, int substr)
667 {
668   size_t namelen;
669   int btype;
670
671   return_val_if_fail (name, 0);
672
673   btype = blob_get_type (blob);
674   if (btype != BLOBTYPE_PGP && btype != BLOBTYPE_X509)
675     return 0;
676
677   if (btype == BLOBTYPE_PGP && *name == '<')
678     name++; /* Hack to remove the leading '<' for gpg.  */
679
680   namelen = strlen (name);
681   if (namelen && name[namelen-1] == '>')
682     namelen--;
683   return blob_cmp_mail (blob, name, namelen, substr, (btype == BLOBTYPE_X509));
684 }
685
686
687 static void
688 release_sn_array (struct sn_array_s *array, size_t size)
689 {
690   size_t n;
691
692   for (n=0; n < size; n++)
693     xfree (array[n].sn);
694   xfree (array);
695 }
696
697 \f
698 /*
699
700   The search API
701
702 */
703
704 int
705 keybox_search_reset (KEYBOX_HANDLE hd)
706 {
707   if (!hd)
708     return gpg_error (GPG_ERR_INV_VALUE);
709
710   if (hd->found.blob)
711     {
712       _keybox_release_blob (hd->found.blob);
713       hd->found.blob = NULL;
714     }
715
716   if (hd->fp)
717     {
718       fclose (hd->fp);
719       hd->fp = NULL;
720     }
721   hd->error = 0;
722   hd->eof = 0;
723   return 0;
724 }
725
726
727 /* Note: When in ephemeral mode the search function does visit all
728    blobs but in standard mode, blobs flagged as ephemeral are ignored.  */
729 int
730 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
731 {
732   int rc;
733   size_t n;
734   int need_words, any_skip;
735   KEYBOXBLOB blob = NULL;
736   struct sn_array_s *sn_array = NULL;
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   for (;;)
854     {
855       unsigned int blobflags;
856
857       _keybox_release_blob (blob); blob = NULL;
858       rc = _keybox_read_blob (&blob, hd->fp);
859       if (rc)
860         break;
861
862       if (blob_get_type (blob) == BLOBTYPE_HEADER)
863         continue;
864
865
866       blobflags = blob_get_blob_flags (blob);
867       if (!hd->ephemeral && (blobflags & 2))
868         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
869
870       for (n=0; n < ndesc; n++)
871         {
872           switch (desc[n].mode)
873             {
874             case KEYDB_SEARCH_MODE_NONE:
875               never_reached ();
876               break;
877             case KEYDB_SEARCH_MODE_EXACT:
878               if (has_username (blob, desc[n].u.name, 0))
879                 goto found;
880               break;
881             case KEYDB_SEARCH_MODE_MAIL:
882               if (has_mail (blob, desc[n].u.name, 0))
883                 goto found;
884               break;
885             case KEYDB_SEARCH_MODE_MAILSUB:
886               if (has_mail (blob, desc[n].u.name, 1))
887                 goto found;
888               break;
889             case KEYDB_SEARCH_MODE_SUBSTR:
890               if (has_username (blob, desc[n].u.name, 1))
891                 goto found;
892               break;
893             case KEYDB_SEARCH_MODE_MAILEND:
894             case KEYDB_SEARCH_MODE_WORDS:
895               never_reached (); /* not yet implemented */
896               break;
897             case KEYDB_SEARCH_MODE_ISSUER:
898               if (has_issuer (blob, desc[n].u.name))
899                 goto found;
900               break;
901             case KEYDB_SEARCH_MODE_ISSUER_SN:
902               if (has_issuer_sn (blob, desc[n].u.name,
903                                  sn_array? sn_array[n].sn : desc[n].sn,
904                                  sn_array? sn_array[n].snlen : desc[n].snlen))
905                 goto found;
906               break;
907             case KEYDB_SEARCH_MODE_SN:
908               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
909                                 sn_array? sn_array[n].snlen : desc[n].snlen))
910                 goto found;
911               break;
912             case KEYDB_SEARCH_MODE_SUBJECT:
913               if (has_subject (blob, desc[n].u.name))
914                 goto found;
915               break;
916             case KEYDB_SEARCH_MODE_SHORT_KID:
917               if (has_short_kid (blob, desc[n].u.kid[1]))
918                 goto found;
919               break;
920             case KEYDB_SEARCH_MODE_LONG_KID:
921               if (has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]))
922                 goto found;
923               break;
924             case KEYDB_SEARCH_MODE_FPR:
925             case KEYDB_SEARCH_MODE_FPR20:
926               if (has_fingerprint (blob, desc[n].u.fpr))
927                 goto found;
928               break;
929             case KEYDB_SEARCH_MODE_KEYGRIP:
930               if (has_keygrip (blob, desc[n].u.grip))
931                 goto found;
932               break;
933             case KEYDB_SEARCH_MODE_FIRST:
934               goto found;
935               break;
936             case KEYDB_SEARCH_MODE_NEXT:
937               goto found;
938               break;
939             default:
940               rc = gpg_error (GPG_ERR_INV_VALUE);
941               goto found;
942             }
943         }
944       continue;
945     found:
946       for (n=any_skip?0:ndesc; n < ndesc; n++)
947         {
948 /*            if (desc[n].skipfnc */
949 /*                && desc[n].skipfnc (desc[n].skipfncvalue, aki, NULL)) */
950 /*              break; */
951         }
952       if (n == ndesc)
953         break; /* got it */
954     }
955
956   if (!rc)
957     {
958       hd->found.blob = blob;
959     }
960   else if (rc == -1)
961     {
962       _keybox_release_blob (blob);
963       hd->eof = 1;
964     }
965   else
966     {
967       _keybox_release_blob (blob);
968       hd->error = rc;
969     }
970
971   if (sn_array)
972     release_sn_array (sn_array, ndesc);
973
974   return rc;
975 }
976
977
978
979 \f
980 /*
981    Functions to return a certificate or a keyblock.  To be used after
982    a successful search operation.
983 */
984
985
986 /* Return the last found keyblock.  Returns 0 on success and stores a
987    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
988    in that case.  */
989 gpg_error_t
990 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, u32 **r_sigstatus)
991 {
992   gpg_error_t err;
993   const unsigned char *buffer, *p;
994   size_t length;
995   size_t image_off, image_len;
996   size_t siginfo_off, siginfo_len;
997   u32 *sigstatus, n, n_sigs, sigilen;
998
999   *r_iobuf = NULL;
1000   *r_sigstatus = NULL;
1001
1002   if (!hd)
1003     return gpg_error (GPG_ERR_INV_VALUE);
1004   if (!hd->found.blob)
1005     return gpg_error (GPG_ERR_NOTHING_FOUND);
1006
1007   if (blob_get_type (hd->found.blob) != BLOBTYPE_PGP)
1008     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1009
1010   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1011   if (length < 40)
1012     return gpg_error (GPG_ERR_TOO_SHORT);
1013   image_off = get32 (buffer+8);
1014   image_len = get32 (buffer+12);
1015   if (image_off+image_len > length)
1016     return gpg_error (GPG_ERR_TOO_SHORT);
1017
1018   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1019                                    &siginfo_off, &siginfo_len);
1020   if (err)
1021     return err;
1022   n_sigs  = get16 (buffer + siginfo_off);
1023   sigilen = get16 (buffer + siginfo_off + 2);
1024   p = buffer + siginfo_off + 4;
1025   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
1026   if (!sigstatus)
1027     return gpg_error_from_syserror ();
1028   sigstatus[0] = n_sigs;
1029   for (n=1; n <= n_sigs; n++, p += sigilen)
1030     sigstatus[n] = get32 (p);
1031
1032   *r_sigstatus = sigstatus;
1033   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1034   return 0;
1035 }
1036
1037
1038 #ifdef KEYBOX_WITH_X509
1039 /*
1040   Return the last found cert.  Caller must free it.
1041  */
1042 int
1043 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1044 {
1045   const unsigned char *buffer;
1046   size_t length;
1047   size_t cert_off, cert_len;
1048   ksba_reader_t reader = NULL;
1049   ksba_cert_t cert = NULL;
1050   int rc;
1051
1052   if (!hd)
1053     return gpg_error (GPG_ERR_INV_VALUE);
1054   if (!hd->found.blob)
1055     return gpg_error (GPG_ERR_NOTHING_FOUND);
1056
1057   if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
1058     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1059
1060   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1061   if (length < 40)
1062     return gpg_error (GPG_ERR_TOO_SHORT);
1063   cert_off = get32 (buffer+8);
1064   cert_len = get32 (buffer+12);
1065   if (cert_off+cert_len > length)
1066     return gpg_error (GPG_ERR_TOO_SHORT);
1067
1068   rc = ksba_reader_new (&reader);
1069   if (rc)
1070     return rc;
1071   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1072   if (rc)
1073     {
1074       ksba_reader_release (reader);
1075       /* fixme: need to map the error codes */
1076       return gpg_error (GPG_ERR_GENERAL);
1077     }
1078
1079   rc = ksba_cert_new (&cert);
1080   if (rc)
1081     {
1082       ksba_reader_release (reader);
1083       return rc;
1084     }
1085
1086   rc = ksba_cert_read_der (cert, reader);
1087   if (rc)
1088     {
1089       ksba_cert_release (cert);
1090       ksba_reader_release (reader);
1091       /* fixme: need to map the error codes */
1092       return gpg_error (GPG_ERR_GENERAL);
1093     }
1094
1095   *r_cert = cert;
1096   ksba_reader_release (reader);
1097   return 0;
1098 }
1099
1100 #endif /*KEYBOX_WITH_X509*/
1101
1102 /* Return the flags named WHAT at the address of VALUE. IDX is used
1103    only for certain flags and should be 0 if not required. */
1104 int
1105 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1106 {
1107   const unsigned char *buffer;
1108   size_t length;
1109   gpg_err_code_t ec;
1110
1111   (void)idx; /* Not yet used.  */
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   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1119   ec = get_flag_from_image (buffer, length, what, value);
1120   return ec? gpg_error (ec):0;
1121 }