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