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