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