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