gpgsm: Add a way to save a found state.
[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) == 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) != 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) != 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) != 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) != 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 != BLOBTYPE_PGP && btype != 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 == 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 != BLOBTYPE_PGP && btype != BLOBTYPE_X509)
668     return 0;
669
670   if (btype == 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, (btype == BLOBTYPE_X509));
677 }
678
679
680 static void
681 release_sn_array (struct sn_array_s *array, size_t size)
682 {
683   size_t n;
684
685   for (n=0; n < size; n++)
686     xfree (array[n].sn);
687   xfree (array);
688 }
689
690 \f
691 /*
692
693   The search API
694
695 */
696
697 int
698 keybox_search_reset (KEYBOX_HANDLE hd)
699 {
700   if (!hd)
701     return gpg_error (GPG_ERR_INV_VALUE);
702
703   if (hd->found.blob)
704     {
705       _keybox_release_blob (hd->found.blob);
706       hd->found.blob = NULL;
707     }
708
709   if (hd->fp)
710     {
711       fclose (hd->fp);
712       hd->fp = NULL;
713     }
714   hd->error = 0;
715   hd->eof = 0;
716   return 0;
717 }
718
719
720 /* Note: When in ephemeral mode the search function does visit all
721    blobs but in standard mode, blobs flagged as ephemeral are ignored.  */
722 int
723 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
724                size_t *r_descindex)
725 {
726   int rc;
727   size_t n;
728   int need_words, any_skip;
729   KEYBOXBLOB blob = NULL;
730   struct sn_array_s *sn_array = NULL;
731   int pk_no, uid_no;
732
733   if (!hd)
734     return gpg_error (GPG_ERR_INV_VALUE);
735
736   /* clear last found result */
737   if (hd->found.blob)
738     {
739       _keybox_release_blob (hd->found.blob);
740       hd->found.blob = NULL;
741     }
742
743   if (hd->error)
744     return hd->error; /* still in error state */
745   if (hd->eof)
746     return -1; /* still EOF */
747
748   /* figure out what information we need */
749   need_words = any_skip = 0;
750   for (n=0; n < ndesc; n++)
751     {
752       switch (desc[n].mode)
753         {
754         case KEYDB_SEARCH_MODE_WORDS:
755           need_words = 1;
756           break;
757         case KEYDB_SEARCH_MODE_FIRST:
758           /* always restart the search in this mode */
759           keybox_search_reset (hd);
760           break;
761         default:
762           break;
763         }
764       if (desc[n].skipfnc)
765         any_skip = 1;
766       if (desc[n].snlen == -1 && !sn_array)
767         {
768           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
769           if (!sn_array)
770             return (hd->error = gpg_error_from_syserror ());
771         }
772     }
773
774   (void)need_words;  /* Not yet implemented.  */
775
776   if (!hd->fp)
777     {
778       hd->fp = fopen (hd->kb->fname, "rb");
779       if (!hd->fp)
780         {
781           hd->error = gpg_error_from_syserror ();
782           xfree (sn_array);
783           return hd->error;
784         }
785     }
786
787   /* Kludge: We need to convert an SN given as hexstring to its binary
788      representation - in some cases we are not able to store it in the
789      search descriptor, because due to the way we use it, it is not
790      possible to free allocated memory. */
791   if (sn_array)
792     {
793       const unsigned char *s;
794       int i, odd;
795       size_t snlen;
796
797       for (n=0; n < ndesc; n++)
798         {
799           if (!desc[n].sn)
800             ;
801           else if (desc[n].snlen == -1)
802             {
803               unsigned char *sn;
804
805               s = desc[n].sn;
806               for (i=0; *s && *s != '/'; s++, i++)
807                 ;
808               odd = (i & 1);
809               snlen = (i+1)/2;
810               sn_array[n].sn = xtrymalloc (snlen);
811               if (!sn_array[n].sn)
812                 {
813                   hd->error = gpg_error_from_syserror ();
814                   release_sn_array (sn_array, n);
815                   return hd->error;
816                 }
817               sn_array[n].snlen = snlen;
818               sn = sn_array[n].sn;
819               s = desc[n].sn;
820               if (odd)
821                 {
822                   *sn++ = xtoi_1 (s);
823                   s++;
824                 }
825               for (; *s && *s != '/';  s += 2)
826                 *sn++ = xtoi_2 (s);
827             }
828           else
829             {
830               const unsigned char *sn;
831
832               sn = desc[n].sn;
833               snlen = desc[n].snlen;
834               sn_array[n].sn = xtrymalloc (snlen);
835               if (!sn_array[n].sn)
836                 {
837                   hd->error = gpg_error_from_syserror ();
838                   release_sn_array (sn_array, n);
839                   return hd->error;
840                 }
841               sn_array[n].snlen = snlen;
842               memcpy (sn_array[n].sn, sn, snlen);
843             }
844         }
845     }
846
847
848   pk_no = uid_no = 0;
849   for (;;)
850     {
851       unsigned int blobflags;
852
853       _keybox_release_blob (blob); blob = NULL;
854       rc = _keybox_read_blob (&blob, hd->fp);
855       if (rc)
856         break;
857
858       if (blob_get_type (blob) == BLOBTYPE_HEADER)
859         continue;
860
861
862       blobflags = blob_get_blob_flags (blob);
863       if (!hd->ephemeral && (blobflags & 2))
864         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
865
866       for (n=0; n < ndesc; n++)
867         {
868           switch (desc[n].mode)
869             {
870             case KEYDB_SEARCH_MODE_NONE:
871               never_reached ();
872               break;
873             case KEYDB_SEARCH_MODE_EXACT:
874               uid_no = has_username (blob, desc[n].u.name, 0);
875               if (uid_no)
876                 goto found;
877               break;
878             case KEYDB_SEARCH_MODE_MAIL:
879               uid_no = has_mail (blob, desc[n].u.name, 0);
880               if (uid_no)
881                 goto found;
882               break;
883             case KEYDB_SEARCH_MODE_MAILSUB:
884               uid_no = has_mail (blob, desc[n].u.name, 1);
885               if (uid_no)
886                 goto found;
887               break;
888             case KEYDB_SEARCH_MODE_SUBSTR:
889               uid_no =  has_username (blob, desc[n].u.name, 1);
890               if (uid_no)
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               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
918               if (pk_no)
919                 goto found;
920               break;
921             case KEYDB_SEARCH_MODE_LONG_KID:
922               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
923               if (pk_no)
924                 goto found;
925               break;
926             case KEYDB_SEARCH_MODE_FPR:
927             case KEYDB_SEARCH_MODE_FPR20:
928               pk_no = has_fingerprint (blob, desc[n].u.fpr);
929               if (pk_no)
930                 goto found;
931               break;
932             case KEYDB_SEARCH_MODE_KEYGRIP:
933               if (has_keygrip (blob, desc[n].u.grip))
934                 goto found;
935               break;
936             case KEYDB_SEARCH_MODE_FIRST:
937               goto found;
938               break;
939             case KEYDB_SEARCH_MODE_NEXT:
940               goto found;
941               break;
942             default:
943               rc = gpg_error (GPG_ERR_INV_VALUE);
944               goto found;
945             }
946         }
947       continue;
948     found:
949       /* Record which DESC we matched on.  Note this value is only
950          meaningful if this function returns with no errors. */
951       if(r_descindex)
952         *r_descindex = n;
953       for (n=any_skip?0:ndesc; n < ndesc; n++)
954         {
955 /*            if (desc[n].skipfnc */
956 /*                && desc[n].skipfnc (desc[n].skipfncvalue, aki, NULL)) */
957 /*              break; */
958         }
959       if (n == ndesc)
960         break; /* got it */
961     }
962
963   if (!rc)
964     {
965       hd->found.blob = blob;
966       hd->found.pk_no = pk_no;
967       hd->found.uid_no = uid_no;
968     }
969   else if (rc == -1)
970     {
971       _keybox_release_blob (blob);
972       hd->eof = 1;
973     }
974   else
975     {
976       _keybox_release_blob (blob);
977       hd->error = rc;
978     }
979
980   if (sn_array)
981     release_sn_array (sn_array, ndesc);
982
983   return rc;
984 }
985
986
987
988 \f
989 /*
990    Functions to return a certificate or a keyblock.  To be used after
991    a successful search operation.
992 */
993
994
995 /* Return the last found keyblock.  Returns 0 on success and stores a
996    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
997    in that case.  R_UID_NO and R_PK_NO are used to retun the number of
998    the key or user id which was matched the search criteria; if not
999    known they are set to 0. */
1000 gpg_error_t
1001 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
1002                      int *r_pk_no, int *r_uid_no, u32 **r_sigstatus)
1003 {
1004   gpg_error_t err;
1005   const unsigned char *buffer, *p;
1006   size_t length;
1007   size_t image_off, image_len;
1008   size_t siginfo_off, siginfo_len;
1009   u32 *sigstatus, n, n_sigs, sigilen;
1010
1011   *r_iobuf = NULL;
1012   *r_sigstatus = NULL;
1013
1014   if (!hd)
1015     return gpg_error (GPG_ERR_INV_VALUE);
1016   if (!hd->found.blob)
1017     return gpg_error (GPG_ERR_NOTHING_FOUND);
1018
1019   if (blob_get_type (hd->found.blob) != BLOBTYPE_PGP)
1020     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1021
1022   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1023   if (length < 40)
1024     return gpg_error (GPG_ERR_TOO_SHORT);
1025   image_off = get32 (buffer+8);
1026   image_len = get32 (buffer+12);
1027   if (image_off+image_len > length)
1028     return gpg_error (GPG_ERR_TOO_SHORT);
1029
1030   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1031                                    &siginfo_off, &siginfo_len);
1032   if (err)
1033     return err;
1034   n_sigs  = get16 (buffer + siginfo_off);
1035   sigilen = get16 (buffer + siginfo_off + 2);
1036   p = buffer + siginfo_off + 4;
1037   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
1038   if (!sigstatus)
1039     return gpg_error_from_syserror ();
1040   sigstatus[0] = n_sigs;
1041   for (n=1; n <= n_sigs; n++, p += sigilen)
1042     sigstatus[n] = get32 (p);
1043
1044   *r_pk_no  = hd->found.pk_no;
1045   *r_uid_no = hd->found.uid_no;
1046   *r_sigstatus = sigstatus;
1047   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1048   return 0;
1049 }
1050
1051
1052 #ifdef KEYBOX_WITH_X509
1053 /*
1054   Return the last found cert.  Caller must free it.
1055  */
1056 int
1057 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1058 {
1059   const unsigned char *buffer;
1060   size_t length;
1061   size_t cert_off, cert_len;
1062   ksba_reader_t reader = NULL;
1063   ksba_cert_t cert = NULL;
1064   int rc;
1065
1066   if (!hd)
1067     return gpg_error (GPG_ERR_INV_VALUE);
1068   if (!hd->found.blob)
1069     return gpg_error (GPG_ERR_NOTHING_FOUND);
1070
1071   if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
1072     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1073
1074   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1075   if (length < 40)
1076     return gpg_error (GPG_ERR_TOO_SHORT);
1077   cert_off = get32 (buffer+8);
1078   cert_len = get32 (buffer+12);
1079   if (cert_off+cert_len > length)
1080     return gpg_error (GPG_ERR_TOO_SHORT);
1081
1082   rc = ksba_reader_new (&reader);
1083   if (rc)
1084     return rc;
1085   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1086   if (rc)
1087     {
1088       ksba_reader_release (reader);
1089       /* fixme: need to map the error codes */
1090       return gpg_error (GPG_ERR_GENERAL);
1091     }
1092
1093   rc = ksba_cert_new (&cert);
1094   if (rc)
1095     {
1096       ksba_reader_release (reader);
1097       return rc;
1098     }
1099
1100   rc = ksba_cert_read_der (cert, reader);
1101   if (rc)
1102     {
1103       ksba_cert_release (cert);
1104       ksba_reader_release (reader);
1105       /* fixme: need to map the error codes */
1106       return gpg_error (GPG_ERR_GENERAL);
1107     }
1108
1109   *r_cert = cert;
1110   ksba_reader_release (reader);
1111   return 0;
1112 }
1113
1114 #endif /*KEYBOX_WITH_X509*/
1115
1116 /* Return the flags named WHAT at the address of VALUE. IDX is used
1117    only for certain flags and should be 0 if not required. */
1118 int
1119 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1120 {
1121   const unsigned char *buffer;
1122   size_t length;
1123   gpg_err_code_t ec;
1124
1125   (void)idx; /* Not yet used.  */
1126
1127   if (!hd)
1128     return gpg_error (GPG_ERR_INV_VALUE);
1129   if (!hd->found.blob)
1130     return gpg_error (GPG_ERR_NOTHING_FOUND);
1131
1132   buffer = _keybox_get_blob_image (hd->found.blob, &length);
1133   ec = get_flag_from_image (buffer, length, what, value);
1134   return ec? gpg_error (ec):0;
1135 }