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