1 /* keybox-search.c - Search operations
2 * Copyright (C) 2001 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 2 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
27 #include "../jnlib/stringhelp.h" /* ascii_xxxx() */
28 #include "keybox-defs.h"
30 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
31 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
32 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
42 get32 (const byte
*buffer
)
53 get16 (const byte
*buffer
)
64 blob_get_type (KEYBOXBLOB blob
)
66 const unsigned char *buffer
;
69 buffer
= _keybox_get_blob_image (blob
, &length
);
71 return -1; /* blob too short */
78 blob_cmp_sn (KEYBOXBLOB blob
, const unsigned char *sn
, int snlen
)
80 const unsigned char *buffer
;
83 size_t nkeys
, keyinfolen
;
86 buffer
= _keybox_get_blob_image (blob
, &length
);
88 return 0; /* blob too short */
91 nkeys
= get16 (buffer
+ 16);
92 keyinfolen
= get16 (buffer
+ 18 );
94 return 0; /* invalid blob */
95 pos
= 20 + keyinfolen
*nkeys
;
97 return 0; /* out of bounds */
100 nserial
= get16 (buffer
+pos
);
102 if (off
+nserial
> length
)
103 return 0; /* out of bounds */
105 return nserial
== snlen
&& !memcmp (buffer
+off
, sn
, snlen
);
110 blob_cmp_fpr (KEYBOXBLOB blob
, const unsigned char *fpr
)
112 const unsigned char *buffer
;
115 size_t nkeys
, keyinfolen
;
118 buffer
= _keybox_get_blob_image (blob
, &length
);
120 return 0; /* blob too short */
123 nkeys
= get16 (buffer
+ 16);
124 keyinfolen
= get16 (buffer
+ 18 );
126 return 0; /* invalid blob */
128 if (pos
+ keyinfolen
*nkeys
> length
)
129 return 0; /* out of bounds */
131 for (idx
=0; idx
< nkeys
; idx
++)
133 off
= pos
+ idx
*keyinfolen
;
134 if (!memcmp (buffer
+ off
, fpr
, 20))
135 return 1; /* found */
137 return 0; /* not found */
142 blob_cmp_name (KEYBOXBLOB blob
, int idx
,
143 const char *name
, size_t namelen
, int substr
)
145 const unsigned char *buffer
;
147 size_t pos
, off
, len
;
148 size_t nkeys
, keyinfolen
;
149 size_t nuids
, uidinfolen
;
152 buffer
= _keybox_get_blob_image (blob
, &length
);
154 return 0; /* blob too short */
157 nkeys
= get16 (buffer
+ 16);
158 keyinfolen
= get16 (buffer
+ 18 );
160 return 0; /* invalid blob */
161 pos
= 20 + keyinfolen
*nkeys
;
163 return 0; /* out of bounds */
166 nserial
= get16 (buffer
+pos
);
169 return 0; /* out of bounds */
172 nuids
= get16 (buffer
+ pos
); pos
+= 2;
173 uidinfolen
= get16 (buffer
+ pos
); pos
+= 2;
174 if (uidinfolen
< 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
175 return 0; /* invalid blob */
176 if (pos
+ uidinfolen
*nuids
> length
)
177 return 0; /* out of bounds */
180 { /* compare all names starting with that (negated) index */
183 for ( ;idx
< nuids
; idx
++)
187 mypos
+= idx
*uidinfolen
;
188 off
= get32 (buffer
+mypos
);
189 len
= get32 (buffer
+mypos
+4);
190 if (off
+len
> length
)
191 return 0; /* error: better stop here out of bounds */
193 continue; /* empty name or 0 not stored */
197 if (ascii_memcasemem (buffer
+off
, len
, name
, namelen
))
198 return 1; /* found */
202 if (len
== namelen
&& !memcmp (buffer
+off
, name
, len
))
203 return 1; /* found */
206 return 0; /* not found */
211 return 0; /* no user ID with that idx */
212 pos
+= idx
*uidinfolen
;
213 off
= get32 (buffer
+pos
);
214 len
= get32 (buffer
+pos
+4);
215 if (off
+len
> length
)
216 return 0; /* out of bounds */
218 return 0; /* empty name */
222 return !!ascii_memcasemem (buffer
+off
, len
, name
, namelen
);
226 return len
== namelen
&& !memcmp (buffer
+off
, name
, len
);
232 /* compare all email addresses of the subject. With SUBSTR given as
233 True a substring search is done in the mail address */
235 blob_cmp_mail (KEYBOXBLOB blob
, const char *name
, size_t namelen
, int substr
)
237 const unsigned char *buffer
;
239 size_t pos
, off
, len
;
240 size_t nkeys
, keyinfolen
;
241 size_t nuids
, uidinfolen
;
245 /* fixme: this code is common to blob_cmp_mail */
246 buffer
= _keybox_get_blob_image (blob
, &length
);
248 return 0; /* blob too short */
251 nkeys
= get16 (buffer
+ 16);
252 keyinfolen
= get16 (buffer
+ 18 );
254 return 0; /* invalid blob */
255 pos
= 20 + keyinfolen
*nkeys
;
257 return 0; /* out of bounds */
260 nserial
= get16 (buffer
+pos
);
263 return 0; /* out of bounds */
266 nuids
= get16 (buffer
+ pos
); pos
+= 2;
267 uidinfolen
= get16 (buffer
+ pos
); pos
+= 2;
268 if (uidinfolen
< 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
269 return 0; /* invalid blob */
270 if (pos
+ uidinfolen
*nuids
> length
)
271 return 0; /* out of bounds */
276 for (idx
=1 ;idx
< nuids
; idx
++)
280 mypos
+= idx
*uidinfolen
;
281 off
= get32 (buffer
+mypos
);
282 len
= get32 (buffer
+mypos
+4);
283 if (off
+len
> length
)
284 return 0; /* error: better stop here out of bounds */
285 if (len
< 2 || buffer
[off
] != '<')
286 continue; /* empty name or trailing 0 not stored */
287 len
--; /* one back */
288 if ( len
< 3 || buffer
[off
+len
] != '>')
289 continue; /* not a proper email address */
293 if (ascii_memcasemem (buffer
+off
+1, len
, name
, namelen
))
294 return 1; /* found */
298 if (len
== namelen
&& !ascii_memcasecmp (buffer
+off
+1, name
, len
))
299 return 1; /* found */
302 return 0; /* not found */
309 The has_foo functions are used as helpers for search
313 has_short_kid (KEYBOXBLOB blob
, u32 kid
)
319 has_long_kid (KEYBOXBLOB blob
, u32
*kid
)
326 has_fingerprint (KEYBOXBLOB blob
, const unsigned char *fpr
)
328 return blob_cmp_fpr (blob
, fpr
);
333 has_issuer (KEYBOXBLOB blob
, const char *name
)
337 return_val_if_fail (name
, 0);
339 if (blob_get_type (blob
) != BLOBTYPE_X509
)
342 namelen
= strlen (name
);
343 return blob_cmp_name (blob
, 0 /* issuer */, name
, namelen
, 0);
347 has_issuer_sn (KEYBOXBLOB blob
, const char *name
,
348 const unsigned char *sn
, int snlen
)
352 return_val_if_fail (name
, 0);
353 return_val_if_fail (sn
, 0);
355 if (blob_get_type (blob
) != BLOBTYPE_X509
)
358 namelen
= strlen (name
);
360 return (blob_cmp_sn (blob
, sn
, snlen
)
361 && blob_cmp_name (blob
, 0 /* issuer */, name
, namelen
, 0));
365 has_sn (KEYBOXBLOB blob
, const unsigned char *sn
, int snlen
)
367 return_val_if_fail (sn
, 0);
369 if (blob_get_type (blob
) != BLOBTYPE_X509
)
371 return blob_cmp_sn (blob
, sn
, snlen
);
375 has_subject (KEYBOXBLOB blob
, const char *name
)
379 return_val_if_fail (name
, 0);
381 if (blob_get_type (blob
) != BLOBTYPE_X509
)
384 namelen
= strlen (name
);
385 return blob_cmp_name (blob
, 1 /* subject */, name
, namelen
, 0);
389 has_subject_or_alt (KEYBOXBLOB blob
, const char *name
, int substr
)
393 return_val_if_fail (name
, 0);
395 if (blob_get_type (blob
) != BLOBTYPE_X509
)
398 namelen
= strlen (name
);
399 return blob_cmp_name (blob
, -1 /* all subject names*/, name
,
405 has_mail (KEYBOXBLOB blob
, const char *name
, int substr
)
409 return_val_if_fail (name
, 0);
411 if (blob_get_type (blob
) != BLOBTYPE_X509
)
414 namelen
= strlen (name
);
415 if (namelen
&& name
[namelen
-1] == '>')
417 return blob_cmp_mail (blob
, name
, namelen
, substr
);
422 release_sn_array (struct sn_array_s
*array
, size_t size
)
426 for (n
=0; n
< size
; n
++)
439 keybox_search_reset (KEYBOX_HANDLE hd
)
442 return KEYBOX_Invalid_Value
;
446 _keybox_release_blob (hd
->found
.blob
);
447 hd
->found
.blob
= NULL
;
461 keybox_search (KEYBOX_HANDLE hd
, KEYBOX_SEARCH_DESC
*desc
, size_t ndesc
)
465 int need_words
, any_skip
;
466 KEYBOXBLOB blob
= NULL
;
467 struct sn_array_s
*sn_array
= NULL
;
470 return KEYBOX_Invalid_Value
;
472 /* clear last found result */
475 _keybox_release_blob (hd
->found
.blob
);
476 hd
->found
.blob
= NULL
;
480 return hd
->error
; /* still in error state */
482 return -1; /* still EOF */
484 /* figure out what information we need */
485 need_words
= any_skip
= 0;
486 for (n
=0; n
< ndesc
; n
++)
488 switch (desc
[n
].mode
)
490 case KEYDB_SEARCH_MODE_WORDS
:
493 case KEYDB_SEARCH_MODE_FIRST
:
494 /* always restart the search in this mode */
495 keybox_search_reset (hd
);
502 if (desc
[n
].snlen
== -1 && !sn_array
)
504 sn_array
= xtrycalloc (ndesc
, sizeof *sn_array
);
506 return (hd
->error
= KEYBOX_Out_Of_Core
);
512 hd
->fp
= fopen (hd
->kb
->fname
, "rb");
516 return (hd
->error
= KEYBOX_File_Open_Error
);
520 /* kludge: we need to convert an SN given as hexstring to it's
521 binary representation - in some cases we are not able to store it
522 in the search descriptor, because due to its usgae it is not
523 possible to free allocated memory */
526 const unsigned char *s
;
530 for (n
=0; n
< ndesc
; n
++)
534 else if (desc
[n
].snlen
== -1)
539 for (i
=0; *s
&& *s
!= '/'; s
++, i
++)
543 sn_array
[n
].sn
= xtrymalloc (snlen
);
546 release_sn_array (sn_array
, n
);
547 return (hd
->error
= KEYBOX_Out_Of_Core
);
549 sn_array
[n
].snlen
= snlen
;
557 for (; *s
&& *s
!= '/'; s
+= 2)
562 const unsigned char *sn
;
565 snlen
= desc
[n
].snlen
;
566 sn_array
[n
].sn
= xtrymalloc (snlen
);
569 release_sn_array (sn_array
, n
);
570 return (hd
->error
= KEYBOX_Out_Of_Core
);
572 sn_array
[n
].snlen
= snlen
;
573 memcpy (sn_array
[n
].sn
, sn
, snlen
);
581 _keybox_release_blob (blob
); blob
= NULL
;
582 rc
= _keybox_read_blob (&blob
, hd
->fp
);
586 for (n
=0; n
< ndesc
; n
++)
588 switch (desc
[n
].mode
)
590 case KEYDB_SEARCH_MODE_NONE
:
593 case KEYDB_SEARCH_MODE_EXACT
:
594 if (has_subject_or_alt (blob
, desc
[n
].u
.name
, 0))
597 case KEYDB_SEARCH_MODE_MAIL
:
598 if (has_mail (blob
, desc
[n
].u
.name
, 0))
601 case KEYDB_SEARCH_MODE_MAILSUB
:
602 if (has_mail (blob
, desc
[n
].u
.name
, 1))
605 case KEYDB_SEARCH_MODE_SUBSTR
:
606 if (has_subject_or_alt (blob
, desc
[n
].u
.name
, 1))
609 case KEYDB_SEARCH_MODE_MAILEND
:
610 case KEYDB_SEARCH_MODE_WORDS
:
611 never_reached (); /* not yet implemented */
613 case KEYDB_SEARCH_MODE_ISSUER
:
614 if (has_issuer (blob
, desc
[n
].u
.name
))
617 case KEYDB_SEARCH_MODE_ISSUER_SN
:
618 if (has_issuer_sn (blob
, desc
[n
].u
.name
,
619 sn_array
? sn_array
[n
].sn
: desc
[n
].sn
,
620 sn_array
? sn_array
[n
].snlen
: desc
[n
].snlen
))
623 case KEYDB_SEARCH_MODE_SN
:
624 if (has_sn (blob
, sn_array
? sn_array
[n
].sn
: desc
[n
].sn
,
625 sn_array
? sn_array
[n
].snlen
: desc
[n
].snlen
))
628 case KEYDB_SEARCH_MODE_SUBJECT
:
629 if (has_subject (blob
, desc
[n
].u
.name
))
632 case KEYDB_SEARCH_MODE_SHORT_KID
:
633 /* if (has_short_kid (blob, desc[n].u.kid[1])) */
636 case KEYDB_SEARCH_MODE_LONG_KID
:
637 /* if (has_long_kid (blob, desc[n].u.kid)) */
640 case KEYDB_SEARCH_MODE_FPR
:
641 case KEYDB_SEARCH_MODE_FPR20
:
642 if (has_fingerprint (blob
, desc
[n
].u
.fpr
))
645 case KEYDB_SEARCH_MODE_FIRST
:
648 case KEYDB_SEARCH_MODE_NEXT
:
652 rc
= KEYBOX_Invalid_Value
;
658 for (n
=any_skip
?0:ndesc
; n
< ndesc
; n
++)
660 /* if (desc[n].skipfnc */
661 /* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */
670 hd
->found
.blob
= blob
;
674 _keybox_release_blob (blob
);
679 _keybox_release_blob (blob
);
684 release_sn_array (sn_array
, ndesc
);
693 Functions to return a certificate or a keyblock. To be used after
694 a successful search operation.
696 #ifdef KEYBOX_WITH_X509
698 Return the last found cert. Caller must free it.
701 keybox_get_cert (KEYBOX_HANDLE hd
, KsbaCert
*r_cert
)
703 const unsigned char *buffer
;
705 size_t cert_off
, cert_len
;
706 KsbaReader reader
= NULL
;
707 KsbaCert cert
= NULL
;
711 return KEYBOX_Invalid_Value
;
713 return KEYBOX_Nothing_Found
;
715 if (blob_get_type (hd
->found
.blob
) != BLOBTYPE_X509
)
716 return KEYBOX_Wrong_Blob_Type
;
718 buffer
= _keybox_get_blob_image (hd
->found
.blob
, &length
);
720 return KEYBOX_Blob_Too_Short
;
721 cert_off
= get32 (buffer
+8);
722 cert_len
= get32 (buffer
+12);
723 if (cert_off
+cert_len
> length
)
724 return KEYBOX_Blob_Too_Short
;
726 reader
= ksba_reader_new ();
728 return KEYBOX_Out_Of_Core
;
729 rc
= ksba_reader_set_mem (reader
, buffer
+cert_off
, cert_len
);
732 ksba_reader_release (reader
);
733 /* fixme: need to map the error codes */
734 return KEYBOX_General_Error
;
737 cert
= ksba_cert_new ();
740 ksba_reader_release (reader
);
741 return KEYBOX_Out_Of_Core
;
744 rc
= ksba_cert_read_der (cert
, reader
);
747 ksba_cert_release (cert
);
748 ksba_reader_release (reader
);
749 /* fixme: need to map the error codes */
750 return KEYBOX_General_Error
;
754 ksba_reader_release (reader
);
758 #endif /*KEYBOX_WITH_X509*/