Fix bug#998.
[gnupg.git] / kbx / keybox-search.c
blob927399d482192063b3eb4feb15579263df659cac
1 /* keybox-search.c - Search operations
2 * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
27 #include "../jnlib/stringhelp.h" /* ascii_xxxx() */
29 #include "keybox-defs.h"
30 #include <gcrypt.h>
33 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
34 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
35 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
38 struct sn_array_s {
39 int snlen;
40 unsigned char *sn;
45 static inline ulong
46 get32 (const byte *buffer)
48 ulong a;
49 a = *buffer << 24;
50 a |= buffer[1] << 16;
51 a |= buffer[2] << 8;
52 a |= buffer[3];
53 return a;
56 static inline ulong
57 get16 (const byte *buffer)
59 ulong a;
60 a = *buffer << 8;
61 a |= buffer[1];
62 return a;
67 static inline int
68 blob_get_type (KEYBOXBLOB blob)
70 const unsigned char *buffer;
71 size_t length;
73 buffer = _keybox_get_blob_image (blob, &length);
74 if (length < 32)
75 return -1; /* blob too short */
77 return buffer[4];
80 static inline unsigned int
81 blob_get_blob_flags (KEYBOXBLOB blob)
83 const unsigned char *buffer;
84 size_t length;
86 buffer = _keybox_get_blob_image (blob, &length);
87 if (length < 8)
88 return 0; /* oops */
90 return get16 (buffer + 6);
94 /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
95 Return the offset and the length (in bytes) of the flag in
96 FLAGOFF,FLAG_SIZE. */
97 gpg_err_code_t
98 _keybox_get_flag_location (const unsigned char *buffer, size_t length,
99 int what, size_t *flag_off, size_t *flag_size)
101 size_t pos;
102 size_t nkeys, keyinfolen;
103 size_t nuids, uidinfolen;
104 size_t nserial;
105 size_t nsigs, siginfolen;
107 switch (what)
109 case KEYBOX_FLAG_BLOB:
110 if (length < 8)
111 return GPG_ERR_INV_OBJ;
112 *flag_off = 6;
113 *flag_size = 2;
114 break;
116 case KEYBOX_FLAG_OWNERTRUST:
117 case KEYBOX_FLAG_VALIDITY:
118 case KEYBOX_FLAG_CREATED_AT:
119 if (length < 20)
120 return GPG_ERR_INV_OBJ;
121 /* Key info. */
122 nkeys = get16 (buffer + 16);
123 keyinfolen = get16 (buffer + 18 );
124 if (keyinfolen < 28)
125 return GPG_ERR_INV_OBJ;
126 pos = 20 + keyinfolen*nkeys;
127 if (pos+2 > length)
128 return GPG_ERR_INV_OBJ; /* Out of bounds. */
129 /* Serial number. */
130 nserial = get16 (buffer+pos);
131 pos += 2 + nserial;
132 if (pos+4 > length)
133 return GPG_ERR_INV_OBJ; /* Out of bounds. */
134 /* User IDs. */
135 nuids = get16 (buffer + pos); pos += 2;
136 uidinfolen = get16 (buffer + pos); pos += 2;
137 if (uidinfolen < 12 )
138 return GPG_ERR_INV_OBJ;
139 pos += uidinfolen*nuids;
140 if (pos+4 > length)
141 return GPG_ERR_INV_OBJ ; /* Out of bounds. */
142 /* Signature info. */
143 nsigs = get16 (buffer + pos); pos += 2;
144 siginfolen = get16 (buffer + pos); pos += 2;
145 if (siginfolen < 4 )
146 return GPG_ERR_INV_OBJ;
147 pos += siginfolen*nsigs;
148 if (pos+1+1+2+4+4+4+4 > length)
149 return GPG_ERR_INV_OBJ ; /* Out of bounds. */
150 *flag_size = 1;
151 *flag_off = pos;
152 switch (what)
154 case KEYBOX_FLAG_VALIDITY:
155 *flag_off += 1;
156 break;
157 case KEYBOX_FLAG_CREATED_AT:
158 *flag_size = 4;
159 *flag_off += 1+2+4+4+4;
160 break;
161 default:
162 break;
164 break;
166 default:
167 return GPG_ERR_INV_FLAG;
169 return 0;
174 /* Return one of the flags WHAT in VALUE from teh blob BUFFER of
175 LENGTH bytes. Return 0 on success or an raw error code. */
176 static gpg_err_code_t
177 get_flag_from_image (const unsigned char *buffer, size_t length,
178 int what, unsigned int *value)
180 gpg_err_code_t ec;
181 size_t pos, size;
183 *value = 0;
184 ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
185 if (!ec)
186 switch (size)
188 case 1: *value = buffer[pos]; break;
189 case 2: *value = get16 (buffer + pos); break;
190 case 4: *value = get32 (buffer + pos); break;
191 default: ec = GPG_ERR_BUG; break;
194 return ec;
198 static int
199 blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
201 const unsigned char *buffer;
202 size_t length;
203 size_t pos, off;
204 size_t nkeys, keyinfolen;
205 size_t nserial;
207 buffer = _keybox_get_blob_image (blob, &length);
208 if (length < 40)
209 return 0; /* blob too short */
211 /*keys*/
212 nkeys = get16 (buffer + 16);
213 keyinfolen = get16 (buffer + 18 );
214 if (keyinfolen < 28)
215 return 0; /* invalid blob */
216 pos = 20 + keyinfolen*nkeys;
217 if (pos+2 > length)
218 return 0; /* out of bounds */
220 /*serial*/
221 nserial = get16 (buffer+pos);
222 off = pos + 2;
223 if (off+nserial > length)
224 return 0; /* out of bounds */
226 return nserial == snlen && !memcmp (buffer+off, sn, snlen);
230 static int
231 blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
233 const unsigned char *buffer;
234 size_t length;
235 size_t pos, off;
236 size_t nkeys, keyinfolen;
237 int idx;
239 buffer = _keybox_get_blob_image (blob, &length);
240 if (length < 40)
241 return 0; /* blob too short */
243 /*keys*/
244 nkeys = get16 (buffer + 16);
245 keyinfolen = get16 (buffer + 18 );
246 if (keyinfolen < 28)
247 return 0; /* invalid blob */
248 pos = 20;
249 if (pos + keyinfolen*nkeys > length)
250 return 0; /* out of bounds */
252 for (idx=0; idx < nkeys; idx++)
254 off = pos + idx*keyinfolen;
255 if (!memcmp (buffer + off, fpr, 20))
256 return 1; /* found */
258 return 0; /* not found */
261 static int
262 blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
263 int fproff, int fprlen)
265 const unsigned char *buffer;
266 size_t length;
267 size_t pos, off;
268 size_t nkeys, keyinfolen;
269 int idx;
271 buffer = _keybox_get_blob_image (blob, &length);
272 if (length < 40)
273 return 0; /* blob too short */
275 /*keys*/
276 nkeys = get16 (buffer + 16);
277 keyinfolen = get16 (buffer + 18 );
278 if (keyinfolen < 28)
279 return 0; /* invalid blob */
280 pos = 20;
281 if (pos + keyinfolen*nkeys > length)
282 return 0; /* out of bounds */
284 for (idx=0; idx < nkeys; idx++)
286 off = pos + idx*keyinfolen;
287 if (!memcmp (buffer + off + fproff, fpr, fprlen))
288 return 1; /* found */
290 return 0; /* not found */
294 static int
295 blob_cmp_name (KEYBOXBLOB blob, int idx,
296 const char *name, size_t namelen, int substr)
298 const unsigned char *buffer;
299 size_t length;
300 size_t pos, off, len;
301 size_t nkeys, keyinfolen;
302 size_t nuids, uidinfolen;
303 size_t nserial;
305 buffer = _keybox_get_blob_image (blob, &length);
306 if (length < 40)
307 return 0; /* blob too short */
309 /*keys*/
310 nkeys = get16 (buffer + 16);
311 keyinfolen = get16 (buffer + 18 );
312 if (keyinfolen < 28)
313 return 0; /* invalid blob */
314 pos = 20 + keyinfolen*nkeys;
315 if (pos+2 > length)
316 return 0; /* out of bounds */
318 /*serial*/
319 nserial = get16 (buffer+pos);
320 pos += 2 + nserial;
321 if (pos+4 > length)
322 return 0; /* out of bounds */
324 /* user ids*/
325 nuids = get16 (buffer + pos); pos += 2;
326 uidinfolen = get16 (buffer + pos); pos += 2;
327 if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
328 return 0; /* invalid blob */
329 if (pos + uidinfolen*nuids > length)
330 return 0; /* out of bounds */
332 if (idx < 0)
333 { /* compare all names starting with that (negated) index */
334 idx = -idx;
336 for ( ;idx < nuids; idx++)
338 size_t mypos = pos;
340 mypos += idx*uidinfolen;
341 off = get32 (buffer+mypos);
342 len = get32 (buffer+mypos+4);
343 if (off+len > length)
344 return 0; /* error: better stop here out of bounds */
345 if (len < 1)
346 continue; /* empty name */
347 if (substr)
349 if (ascii_memcasemem (buffer+off, len, name, namelen))
350 return 1; /* found */
352 else
354 if (len == namelen && !memcmp (buffer+off, name, len))
355 return 1; /* found */
358 return 0; /* not found */
360 else
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 */
372 if (substr)
374 return !!ascii_memcasemem (buffer+off, len, name, namelen);
376 else
378 return len == namelen && !memcmp (buffer+off, name, len);
384 /* compare all email addresses of the subject. With SUBSTR given as
385 True a substring search is done in the mail address */
386 static int
387 blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr)
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;
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 */
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 */
411 /*serial*/
412 nserial = get16 (buffer+pos);
413 pos += 2 + nserial;
414 if (pos+4 > length)
415 return 0; /* out of bounds */
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 */
425 if (namelen < 1)
426 return 0;
428 for (idx=1 ;idx < nuids; idx++)
430 size_t mypos = pos;
432 mypos += idx*uidinfolen;
433 off = get32 (buffer+mypos);
434 len = get32 (buffer+mypos+4);
435 if (off+len > length)
436 return 0; /* error: better stop here out of bounds */
437 if (len < 2 || buffer[off] != '<')
438 continue; /* empty name or trailing 0 not stored */
439 len--; /* one back */
440 if ( len < 3 || buffer[off+len] != '>')
441 continue; /* not a proper email address */
442 len--;
443 if (substr)
445 if (ascii_memcasemem (buffer+off+1, len, name, namelen))
446 return 1; /* found */
448 else
450 if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len))
451 return 1; /* found */
454 return 0; /* not found */
458 #ifdef KEYBOX_WITH_X509
459 /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
460 We don't have the keygrips as meta data, thus wen need to parse the
461 certificate. Fixme: We might want to return proper error codes
462 instead of failing a search for invalid certificates etc. */
463 static int
464 blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
466 int rc;
467 const unsigned char *buffer;
468 size_t length;
469 size_t cert_off, cert_len;
470 ksba_reader_t reader = NULL;
471 ksba_cert_t cert = NULL;
472 ksba_sexp_t p = NULL;
473 gcry_sexp_t s_pkey;
474 unsigned char array[20];
475 unsigned char *rcp;
476 size_t n;
478 buffer = _keybox_get_blob_image (blob, &length);
479 if (length < 40)
480 return 0; /* Too short. */
481 cert_off = get32 (buffer+8);
482 cert_len = get32 (buffer+12);
483 if (cert_off+cert_len > length)
484 return 0; /* Too short. */
486 rc = ksba_reader_new (&reader);
487 if (rc)
488 return 0; /* Problem with ksba. */
489 rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
490 if (rc)
491 goto failed;
492 rc = ksba_cert_new (&cert);
493 if (rc)
494 goto failed;
495 rc = ksba_cert_read_der (cert, reader);
496 if (rc)
497 goto failed;
498 p = ksba_cert_get_public_key (cert);
499 if (!p)
500 goto failed;
501 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
502 if (!n)
503 goto failed;
504 rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
505 if (rc)
507 gcry_sexp_release (s_pkey);
508 goto failed;
510 rcp = gcry_pk_get_keygrip (s_pkey, array);
511 gcry_sexp_release (s_pkey);
512 if (!rcp)
513 goto failed; /* Can't calculate keygrip. */
515 xfree (p);
516 ksba_cert_release (cert);
517 ksba_reader_release (reader);
518 return !memcmp (array, grip, 20);
519 failed:
520 xfree (p);
521 ksba_cert_release (cert);
522 ksba_reader_release (reader);
523 return 0;
525 #endif /*KEYBOX_WITH_X509*/
530 The has_foo functions are used as helpers for search
532 static inline int
533 has_short_kid (KEYBOXBLOB blob, const unsigned char *kid)
535 return blob_cmp_fpr_part (blob, kid+4, 16, 4);
538 static inline int
539 has_long_kid (KEYBOXBLOB blob, const unsigned char *kid)
541 return blob_cmp_fpr_part (blob, kid, 12, 8);
544 static inline int
545 has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
547 return blob_cmp_fpr (blob, fpr);
550 static inline int
551 has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
553 #ifdef KEYBOX_WITH_X509
554 if (blob_get_type (blob) == BLOBTYPE_X509)
555 return blob_x509_has_grip (blob, grip);
556 #endif
557 return 0;
561 static inline int
562 has_issuer (KEYBOXBLOB blob, const char *name)
564 size_t namelen;
566 return_val_if_fail (name, 0);
568 if (blob_get_type (blob) != BLOBTYPE_X509)
569 return 0;
571 namelen = strlen (name);
572 return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0);
575 static inline int
576 has_issuer_sn (KEYBOXBLOB blob, const char *name,
577 const unsigned char *sn, int snlen)
579 size_t namelen;
581 return_val_if_fail (name, 0);
582 return_val_if_fail (sn, 0);
584 if (blob_get_type (blob) != BLOBTYPE_X509)
585 return 0;
587 namelen = strlen (name);
589 return (blob_cmp_sn (blob, sn, snlen)
590 && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0));
593 static inline int
594 has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
596 return_val_if_fail (sn, 0);
598 if (blob_get_type (blob) != BLOBTYPE_X509)
599 return 0;
600 return blob_cmp_sn (blob, sn, snlen);
603 static inline int
604 has_subject (KEYBOXBLOB blob, const char *name)
606 size_t namelen;
608 return_val_if_fail (name, 0);
610 if (blob_get_type (blob) != BLOBTYPE_X509)
611 return 0;
613 namelen = strlen (name);
614 return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0);
617 static inline int
618 has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr)
620 size_t namelen;
622 return_val_if_fail (name, 0);
624 if (blob_get_type (blob) != BLOBTYPE_X509)
625 return 0;
627 namelen = strlen (name);
628 return blob_cmp_name (blob, -1 /* all subject names*/, name,
629 namelen, substr);
633 static inline int
634 has_mail (KEYBOXBLOB blob, const char *name, int substr)
636 size_t namelen;
638 return_val_if_fail (name, 0);
640 if (blob_get_type (blob) != BLOBTYPE_X509)
641 return 0;
643 namelen = strlen (name);
644 if (namelen && name[namelen-1] == '>')
645 namelen--;
646 return blob_cmp_mail (blob, name, namelen, substr);
650 static void
651 release_sn_array (struct sn_array_s *array, size_t size)
653 size_t n;
655 for (n=0; n < size; n++)
656 xfree (array[n].sn);
657 xfree (array);
663 The search API
667 int
668 keybox_search_reset (KEYBOX_HANDLE hd)
670 if (!hd)
671 return gpg_error (GPG_ERR_INV_VALUE);
673 if (hd->found.blob)
675 _keybox_release_blob (hd->found.blob);
676 hd->found.blob = NULL;
679 if (hd->fp)
681 fclose (hd->fp);
682 hd->fp = NULL;
684 hd->error = 0;
685 hd->eof = 0;
686 return 0;
690 /* Note: When in ephemeral mode the search function does visit all
691 blobs but in standard mode, blobs flagged as ephemeral are ignored. */
692 int
693 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
695 int rc;
696 size_t n;
697 int need_words, any_skip;
698 KEYBOXBLOB blob = NULL;
699 struct sn_array_s *sn_array = NULL;
701 if (!hd)
702 return gpg_error (GPG_ERR_INV_VALUE);
704 /* clear last found result */
705 if (hd->found.blob)
707 _keybox_release_blob (hd->found.blob);
708 hd->found.blob = NULL;
711 if (hd->error)
712 return hd->error; /* still in error state */
713 if (hd->eof)
714 return -1; /* still EOF */
716 /* figure out what information we need */
717 need_words = any_skip = 0;
718 for (n=0; n < ndesc; n++)
720 switch (desc[n].mode)
722 case KEYDB_SEARCH_MODE_WORDS:
723 need_words = 1;
724 break;
725 case KEYDB_SEARCH_MODE_FIRST:
726 /* always restart the search in this mode */
727 keybox_search_reset (hd);
728 break;
729 default:
730 break;
732 if (desc[n].skipfnc)
733 any_skip = 1;
734 if (desc[n].snlen == -1 && !sn_array)
736 sn_array = xtrycalloc (ndesc, sizeof *sn_array);
737 if (!sn_array)
738 return (hd->error = gpg_error_from_syserror ());
742 if (!hd->fp)
744 hd->fp = fopen (hd->kb->fname, "rb");
745 if (!hd->fp)
747 hd->error = gpg_error_from_syserror ();
748 xfree (sn_array);
749 return hd->error;
753 /* Kludge: We need to convert an SN given as hexstring to its binary
754 representation - in some cases we are not able to store it in the
755 search descriptor, because due to the way we use it, it is not
756 possible to free allocated memory. */
757 if (sn_array)
759 const unsigned char *s;
760 int i, odd;
761 size_t snlen;
763 for (n=0; n < ndesc; n++)
765 if (!desc[n].sn)
767 else if (desc[n].snlen == -1)
769 unsigned char *sn;
771 s = desc[n].sn;
772 for (i=0; *s && *s != '/'; s++, i++)
774 odd = (i & 1);
775 snlen = (i+1)/2;
776 sn_array[n].sn = xtrymalloc (snlen);
777 if (!sn_array[n].sn)
779 hd->error = gpg_error_from_syserror ();
780 release_sn_array (sn_array, n);
781 return hd->error;
783 sn_array[n].snlen = snlen;
784 sn = sn_array[n].sn;
785 s = desc[n].sn;
786 if (odd)
788 *sn++ = xtoi_1 (s);
789 s++;
791 for (; *s && *s != '/'; s += 2)
792 *sn++ = xtoi_2 (s);
794 else
796 const unsigned char *sn;
798 sn = desc[n].sn;
799 snlen = desc[n].snlen;
800 sn_array[n].sn = xtrymalloc (snlen);
801 if (!sn_array[n].sn)
803 hd->error = gpg_error_from_syserror ();
804 release_sn_array (sn_array, n);
805 return hd->error;
807 sn_array[n].snlen = snlen;
808 memcpy (sn_array[n].sn, sn, snlen);
814 for (;;)
816 unsigned int blobflags;
818 _keybox_release_blob (blob); blob = NULL;
819 rc = _keybox_read_blob (&blob, hd->fp);
820 if (rc)
821 break;
823 if (blob_get_type (blob) == BLOBTYPE_HEADER)
824 continue;
827 blobflags = blob_get_blob_flags (blob);
828 if (!hd->ephemeral && (blobflags & 2))
829 continue; /* Not in ephemeral mode but blob is flagged ephemeral. */
831 for (n=0; n < ndesc; n++)
833 switch (desc[n].mode)
835 case KEYDB_SEARCH_MODE_NONE:
836 never_reached ();
837 break;
838 case KEYDB_SEARCH_MODE_EXACT:
839 if (has_subject_or_alt (blob, desc[n].u.name, 0))
840 goto found;
841 break;
842 case KEYDB_SEARCH_MODE_MAIL:
843 if (has_mail (blob, desc[n].u.name, 0))
844 goto found;
845 break;
846 case KEYDB_SEARCH_MODE_MAILSUB:
847 if (has_mail (blob, desc[n].u.name, 1))
848 goto found;
849 break;
850 case KEYDB_SEARCH_MODE_SUBSTR:
851 if (has_subject_or_alt (blob, desc[n].u.name, 1))
852 goto found;
853 break;
854 case KEYDB_SEARCH_MODE_MAILEND:
855 case KEYDB_SEARCH_MODE_WORDS:
856 never_reached (); /* not yet implemented */
857 break;
858 case KEYDB_SEARCH_MODE_ISSUER:
859 if (has_issuer (blob, desc[n].u.name))
860 goto found;
861 break;
862 case KEYDB_SEARCH_MODE_ISSUER_SN:
863 if (has_issuer_sn (blob, desc[n].u.name,
864 sn_array? sn_array[n].sn : desc[n].sn,
865 sn_array? sn_array[n].snlen : desc[n].snlen))
866 goto found;
867 break;
868 case KEYDB_SEARCH_MODE_SN:
869 if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
870 sn_array? sn_array[n].snlen : desc[n].snlen))
871 goto found;
872 break;
873 case KEYDB_SEARCH_MODE_SUBJECT:
874 if (has_subject (blob, desc[n].u.name))
875 goto found;
876 break;
877 case KEYDB_SEARCH_MODE_SHORT_KID:
878 if (has_short_kid (blob, desc[n].u.kid))
879 goto found;
880 break;
881 case KEYDB_SEARCH_MODE_LONG_KID:
882 if (has_long_kid (blob, desc[n].u.kid))
883 goto found;
884 break;
885 case KEYDB_SEARCH_MODE_FPR:
886 case KEYDB_SEARCH_MODE_FPR20:
887 if (has_fingerprint (blob, desc[n].u.fpr))
888 goto found;
889 break;
890 case KEYDB_SEARCH_MODE_KEYGRIP:
891 if (has_keygrip (blob, desc[n].u.grip))
892 goto found;
893 break;
894 case KEYDB_SEARCH_MODE_FIRST:
895 goto found;
896 break;
897 case KEYDB_SEARCH_MODE_NEXT:
898 goto found;
899 break;
900 default:
901 rc = gpg_error (GPG_ERR_INV_VALUE);
902 goto found;
905 continue;
906 found:
907 for (n=any_skip?0:ndesc; n < ndesc; n++)
909 /* if (desc[n].skipfnc */
910 /* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */
911 /* break; */
913 if (n == ndesc)
914 break; /* got it */
917 if (!rc)
919 hd->found.blob = blob;
921 else if (rc == -1)
923 _keybox_release_blob (blob);
924 hd->eof = 1;
926 else
928 _keybox_release_blob (blob);
929 hd->error = rc;
932 if (sn_array)
933 release_sn_array (sn_array, ndesc);
935 return rc;
942 Functions to return a certificate or a keyblock. To be used after
943 a successful search operation.
945 #ifdef KEYBOX_WITH_X509
947 Return the last found cert. Caller must free it.
950 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
952 const unsigned char *buffer;
953 size_t length;
954 size_t cert_off, cert_len;
955 ksba_reader_t reader = NULL;
956 ksba_cert_t cert = NULL;
957 int rc;
959 if (!hd)
960 return gpg_error (GPG_ERR_INV_VALUE);
961 if (!hd->found.blob)
962 return gpg_error (GPG_ERR_NOTHING_FOUND);
964 if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
965 return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
967 buffer = _keybox_get_blob_image (hd->found.blob, &length);
968 if (length < 40)
969 return gpg_error (GPG_ERR_TOO_SHORT);
970 cert_off = get32 (buffer+8);
971 cert_len = get32 (buffer+12);
972 if (cert_off+cert_len > length)
973 return gpg_error (GPG_ERR_TOO_SHORT);
975 rc = ksba_reader_new (&reader);
976 if (rc)
977 return rc;
978 rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
979 if (rc)
981 ksba_reader_release (reader);
982 /* fixme: need to map the error codes */
983 return gpg_error (GPG_ERR_GENERAL);
986 rc = ksba_cert_new (&cert);
987 if (rc)
989 ksba_reader_release (reader);
990 return rc;
993 rc = ksba_cert_read_der (cert, reader);
994 if (rc)
996 ksba_cert_release (cert);
997 ksba_reader_release (reader);
998 /* fixme: need to map the error codes */
999 return gpg_error (GPG_ERR_GENERAL);
1002 *r_cert = cert;
1003 ksba_reader_release (reader);
1004 return 0;
1007 #endif /*KEYBOX_WITH_X509*/
1009 /* Return the flags named WHAT at the address of VALUE. IDX is used
1010 only for certain flags and should be 0 if not required. */
1012 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1014 const unsigned char *buffer;
1015 size_t length;
1016 gpg_err_code_t ec;
1018 (void)idx; /* Not yet used. */
1020 if (!hd)
1021 return gpg_error (GPG_ERR_INV_VALUE);
1022 if (!hd->found.blob)
1023 return gpg_error (GPG_ERR_NOTHING_FOUND);
1025 buffer = _keybox_get_blob_image (hd->found.blob, &length);
1026 ec = get_flag_from_image (buffer, length, what, value);
1027 return ec? gpg_error (ec):0;