agent/
[gnupg.git] / kbx / keybox-search.c
blob1680dd732f663c99bb6398436ad168af843a79fa
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 we 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 (void)need_words; /* Not yet implemented. */
744 if (!hd->fp)
746 hd->fp = fopen (hd->kb->fname, "rb");
747 if (!hd->fp)
749 hd->error = gpg_error_from_syserror ();
750 xfree (sn_array);
751 return hd->error;
755 /* Kludge: We need to convert an SN given as hexstring to its binary
756 representation - in some cases we are not able to store it in the
757 search descriptor, because due to the way we use it, it is not
758 possible to free allocated memory. */
759 if (sn_array)
761 const unsigned char *s;
762 int i, odd;
763 size_t snlen;
765 for (n=0; n < ndesc; n++)
767 if (!desc[n].sn)
769 else if (desc[n].snlen == -1)
771 unsigned char *sn;
773 s = desc[n].sn;
774 for (i=0; *s && *s != '/'; s++, i++)
776 odd = (i & 1);
777 snlen = (i+1)/2;
778 sn_array[n].sn = xtrymalloc (snlen);
779 if (!sn_array[n].sn)
781 hd->error = gpg_error_from_syserror ();
782 release_sn_array (sn_array, n);
783 return hd->error;
785 sn_array[n].snlen = snlen;
786 sn = sn_array[n].sn;
787 s = desc[n].sn;
788 if (odd)
790 *sn++ = xtoi_1 (s);
791 s++;
793 for (; *s && *s != '/'; s += 2)
794 *sn++ = xtoi_2 (s);
796 else
798 const unsigned char *sn;
800 sn = desc[n].sn;
801 snlen = desc[n].snlen;
802 sn_array[n].sn = xtrymalloc (snlen);
803 if (!sn_array[n].sn)
805 hd->error = gpg_error_from_syserror ();
806 release_sn_array (sn_array, n);
807 return hd->error;
809 sn_array[n].snlen = snlen;
810 memcpy (sn_array[n].sn, sn, snlen);
816 for (;;)
818 unsigned int blobflags;
820 _keybox_release_blob (blob); blob = NULL;
821 rc = _keybox_read_blob (&blob, hd->fp);
822 if (rc)
823 break;
825 if (blob_get_type (blob) == BLOBTYPE_HEADER)
826 continue;
829 blobflags = blob_get_blob_flags (blob);
830 if (!hd->ephemeral && (blobflags & 2))
831 continue; /* Not in ephemeral mode but blob is flagged ephemeral. */
833 for (n=0; n < ndesc; n++)
835 switch (desc[n].mode)
837 case KEYDB_SEARCH_MODE_NONE:
838 never_reached ();
839 break;
840 case KEYDB_SEARCH_MODE_EXACT:
841 if (has_subject_or_alt (blob, desc[n].u.name, 0))
842 goto found;
843 break;
844 case KEYDB_SEARCH_MODE_MAIL:
845 if (has_mail (blob, desc[n].u.name, 0))
846 goto found;
847 break;
848 case KEYDB_SEARCH_MODE_MAILSUB:
849 if (has_mail (blob, desc[n].u.name, 1))
850 goto found;
851 break;
852 case KEYDB_SEARCH_MODE_SUBSTR:
853 if (has_subject_or_alt (blob, desc[n].u.name, 1))
854 goto found;
855 break;
856 case KEYDB_SEARCH_MODE_MAILEND:
857 case KEYDB_SEARCH_MODE_WORDS:
858 never_reached (); /* not yet implemented */
859 break;
860 case KEYDB_SEARCH_MODE_ISSUER:
861 if (has_issuer (blob, desc[n].u.name))
862 goto found;
863 break;
864 case KEYDB_SEARCH_MODE_ISSUER_SN:
865 if (has_issuer_sn (blob, desc[n].u.name,
866 sn_array? sn_array[n].sn : desc[n].sn,
867 sn_array? sn_array[n].snlen : desc[n].snlen))
868 goto found;
869 break;
870 case KEYDB_SEARCH_MODE_SN:
871 if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
872 sn_array? sn_array[n].snlen : desc[n].snlen))
873 goto found;
874 break;
875 case KEYDB_SEARCH_MODE_SUBJECT:
876 if (has_subject (blob, desc[n].u.name))
877 goto found;
878 break;
879 case KEYDB_SEARCH_MODE_SHORT_KID:
880 if (has_short_kid (blob, desc[n].u.kid))
881 goto found;
882 break;
883 case KEYDB_SEARCH_MODE_LONG_KID:
884 if (has_long_kid (blob, desc[n].u.kid))
885 goto found;
886 break;
887 case KEYDB_SEARCH_MODE_FPR:
888 case KEYDB_SEARCH_MODE_FPR20:
889 if (has_fingerprint (blob, desc[n].u.fpr))
890 goto found;
891 break;
892 case KEYDB_SEARCH_MODE_KEYGRIP:
893 if (has_keygrip (blob, desc[n].u.grip))
894 goto found;
895 break;
896 case KEYDB_SEARCH_MODE_FIRST:
897 goto found;
898 break;
899 case KEYDB_SEARCH_MODE_NEXT:
900 goto found;
901 break;
902 default:
903 rc = gpg_error (GPG_ERR_INV_VALUE);
904 goto found;
907 continue;
908 found:
909 for (n=any_skip?0:ndesc; n < ndesc; n++)
911 /* if (desc[n].skipfnc */
912 /* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */
913 /* break; */
915 if (n == ndesc)
916 break; /* got it */
919 if (!rc)
921 hd->found.blob = blob;
923 else if (rc == -1)
925 _keybox_release_blob (blob);
926 hd->eof = 1;
928 else
930 _keybox_release_blob (blob);
931 hd->error = rc;
934 if (sn_array)
935 release_sn_array (sn_array, ndesc);
937 return rc;
944 Functions to return a certificate or a keyblock. To be used after
945 a successful search operation.
947 #ifdef KEYBOX_WITH_X509
949 Return the last found cert. Caller must free it.
952 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
954 const unsigned char *buffer;
955 size_t length;
956 size_t cert_off, cert_len;
957 ksba_reader_t reader = NULL;
958 ksba_cert_t cert = NULL;
959 int rc;
961 if (!hd)
962 return gpg_error (GPG_ERR_INV_VALUE);
963 if (!hd->found.blob)
964 return gpg_error (GPG_ERR_NOTHING_FOUND);
966 if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
967 return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
969 buffer = _keybox_get_blob_image (hd->found.blob, &length);
970 if (length < 40)
971 return gpg_error (GPG_ERR_TOO_SHORT);
972 cert_off = get32 (buffer+8);
973 cert_len = get32 (buffer+12);
974 if (cert_off+cert_len > length)
975 return gpg_error (GPG_ERR_TOO_SHORT);
977 rc = ksba_reader_new (&reader);
978 if (rc)
979 return rc;
980 rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
981 if (rc)
983 ksba_reader_release (reader);
984 /* fixme: need to map the error codes */
985 return gpg_error (GPG_ERR_GENERAL);
988 rc = ksba_cert_new (&cert);
989 if (rc)
991 ksba_reader_release (reader);
992 return rc;
995 rc = ksba_cert_read_der (cert, reader);
996 if (rc)
998 ksba_cert_release (cert);
999 ksba_reader_release (reader);
1000 /* fixme: need to map the error codes */
1001 return gpg_error (GPG_ERR_GENERAL);
1004 *r_cert = cert;
1005 ksba_reader_release (reader);
1006 return 0;
1009 #endif /*KEYBOX_WITH_X509*/
1011 /* Return the flags named WHAT at the address of VALUE. IDX is used
1012 only for certain flags and should be 0 if not required. */
1014 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1016 const unsigned char *buffer;
1017 size_t length;
1018 gpg_err_code_t ec;
1020 (void)idx; /* Not yet used. */
1022 if (!hd)
1023 return gpg_error (GPG_ERR_INV_VALUE);
1024 if (!hd->found.blob)
1025 return gpg_error (GPG_ERR_NOTHING_FOUND);
1027 buffer = _keybox_get_blob_image (hd->found.blob, &length);
1028 ec = get_flag_from_image (buffer, length, what, value);
1029 return ec? gpg_error (ec):0;