File: | lib/opencdk/keydb.c |
Location: | line 1278, column 7 |
Description: | Dereference of null pointer |
1 | /* keydb.c - Key database routines | ||
2 | * Copyright (C) 2002-2003, 2007-2010, 2012 Free Software Foundation, | ||
3 | * Inc. | ||
4 | * | ||
5 | * Author: Timo Schulz | ||
6 | * | ||
7 | * This file is part of OpenCDK. | ||
8 | * | ||
9 | * The OpenCDK library is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 3 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This library is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/> | ||
21 | * | ||
22 | */ | ||
23 | #ifdef HAVE_CONFIG_H1 | ||
24 | #include <config.h> | ||
25 | #endif | ||
26 | #include <sys/stat.h> | ||
27 | #include <stdio.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <string.h> | ||
30 | #include <ctype.h> | ||
31 | |||
32 | #include "opencdk.h" | ||
33 | #include "main.h" | ||
34 | #include "packet.h" | ||
35 | #include "filters.h" | ||
36 | #include "stream.h" | ||
37 | #include "keydb.h" | ||
38 | |||
39 | #define KEYID_CMP(a, b)((a[0]) == (b[0]) && (a[1]) == (b[1])) ((a[0]) == (b[0]) && (a[1]) == (b[1])) | ||
40 | #define KEYDB_CACHE_ENTRIES8 8 | ||
41 | |||
42 | static void keydb_cache_free (key_table_t cache); | ||
43 | static int classify_data (const byte * buf, size_t len); | ||
44 | static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk); | ||
45 | |||
46 | static char * | ||
47 | keydb_idx_mkname (const char *file) | ||
48 | { | ||
49 | static const char *fmt = "%s.idx"; | ||
50 | char *fname; | ||
51 | size_t len = strlen (file) + strlen (fmt); | ||
52 | |||
53 | fname = cdk_callocgnutls_calloc (1, len + 1); | ||
54 | if (!fname) | ||
55 | return NULL((void*)0); | ||
56 | if (snprintf (fname, len, fmt, file) <= 0) | ||
57 | return NULL((void*)0); | ||
58 | return fname; | ||
59 | } | ||
60 | |||
61 | |||
62 | /* This functions builds an index of the keyring into a separate file | ||
63 | with the name keyring.ext.idx. It contains the offset of all public- | ||
64 | and public subkeys. The format of the file is: | ||
65 | -------- | ||
66 | 4 octets offset of the packet | ||
67 | 8 octets keyid | ||
68 | 20 octets fingerprint | ||
69 | -------- | ||
70 | We store the keyid and the fingerprint due to the fact we can't get | ||
71 | the keyid from a v3 fingerprint directly. | ||
72 | */ | ||
73 | static cdk_error_t | ||
74 | keydb_idx_build (const char *file) | ||
75 | { | ||
76 | cdk_packet_t pkt; | ||
77 | cdk_stream_t inp, out = NULL((void*)0); | ||
78 | byte buf[4 + 8 + KEY_FPR_LEN20]; | ||
79 | char *idx_name; | ||
80 | u32 keyid[2]; | ||
81 | cdk_error_t rc; | ||
82 | |||
83 | if (!file) | ||
84 | { | ||
85 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",85); } while(0);; | ||
86 | return CDK_Inv_Value; | ||
87 | } | ||
88 | |||
89 | rc = cdk_stream_open (file, &inp); | ||
90 | if (rc) | ||
91 | { | ||
92 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",92); } while(0);; | ||
93 | return rc; | ||
94 | } | ||
95 | |||
96 | idx_name = keydb_idx_mkname (file); | ||
97 | if (!idx_name) | ||
98 | { | ||
99 | cdk_stream_close (inp); | ||
100 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",100); } while(0);; | ||
101 | return CDK_Out_Of_Core; | ||
102 | } | ||
103 | rc = cdk_stream_create (idx_name, &out); | ||
104 | cdk_freegnutls_free (idx_name); | ||
105 | if (rc) | ||
106 | { | ||
107 | cdk_stream_close (inp); | ||
108 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",108); } while(0);; | ||
109 | return rc; | ||
110 | } | ||
111 | |||
112 | cdk_pkt_new (&pkt); | ||
113 | while (!cdk_stream_eof (inp)) | ||
114 | { | ||
115 | off_t pos = cdk_stream_tell (inp); | ||
116 | |||
117 | rc = cdk_pkt_read (inp, pkt); | ||
118 | if (rc) | ||
119 | { | ||
120 | _cdk_log_debug ("index build failed packet off=%lu\n", pos)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "index build failed packet off=%lu\n", pos); } while(0); | ||
121 | /* FIXME: The index is incomplete */ | ||
122 | break; | ||
123 | } | ||
124 | if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
125 | pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
126 | { | ||
127 | _cdk_u32tobuf (pos, buf); | ||
128 | cdk_pk_get_keyid (pkt->pkt.public_key, keyid); | ||
129 | _cdk_u32tobuf (keyid[0], buf + 4); | ||
130 | _cdk_u32tobuf (keyid[1], buf + 8); | ||
131 | cdk_pk_get_fingerprint (pkt->pkt.public_key, buf + 12); | ||
132 | cdk_stream_write (out, buf, 4 + 8 + KEY_FPR_LEN20); | ||
133 | } | ||
134 | cdk_pkt_free (pkt); | ||
135 | } | ||
136 | |||
137 | cdk_pkt_release (pkt); | ||
138 | |||
139 | cdk_stream_close (out); | ||
140 | cdk_stream_close (inp); | ||
141 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",141); } while(0);; | ||
142 | return rc; | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * cdk_keydb_idx_rebuild: | ||
148 | * @hd: key database handle | ||
149 | * | ||
150 | * Rebuild the key index files for the given key database. | ||
151 | **/ | ||
152 | cdk_error_t | ||
153 | cdk_keydb_idx_rebuild (cdk_keydb_hd_t db, cdk_keydb_search_t dbs) | ||
154 | { | ||
155 | struct stat stbuf; | ||
156 | char *tmp_idx_name; | ||
157 | cdk_error_t rc; | ||
158 | int err; | ||
159 | |||
160 | if (!db || !db->name || !dbs) | ||
161 | { | ||
162 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",162); } while(0);; | ||
163 | return CDK_Inv_Value; | ||
164 | } | ||
165 | if (db->secret) | ||
166 | return 0; | ||
167 | |||
168 | tmp_idx_name = keydb_idx_mkname (db->name); | ||
169 | if (!tmp_idx_name) | ||
170 | { | ||
171 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",171); } while(0);; | ||
172 | return CDK_Out_Of_Core; | ||
173 | } | ||
174 | err = stat (tmp_idx_name, &stbuf); | ||
175 | cdk_freegnutls_free (tmp_idx_name); | ||
176 | /* This function expects an existing index which can be rebuild, | ||
177 | if no index exists we do not build one and just return. */ | ||
178 | if (err) | ||
179 | return 0; | ||
180 | |||
181 | cdk_stream_close (dbs->idx); | ||
182 | dbs->idx = NULL((void*)0); | ||
183 | if (!dbs->idx_name) | ||
184 | { | ||
185 | dbs->idx_name = keydb_idx_mkname (db->name); | ||
186 | if (!dbs->idx_name) | ||
187 | { | ||
188 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",188); } while(0);; | ||
189 | return CDK_Out_Of_Core; | ||
190 | } | ||
191 | } | ||
192 | rc = keydb_idx_build (db->name); | ||
193 | if (!rc) | ||
194 | rc = cdk_stream_open (dbs->idx_name, &dbs->idx); | ||
195 | else | ||
196 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",196); } while(0);; | ||
197 | return rc; | ||
198 | } | ||
199 | |||
200 | |||
201 | static cdk_error_t | ||
202 | keydb_idx_parse (cdk_stream_t inp, key_idx_t * r_idx) | ||
203 | { | ||
204 | key_idx_t idx; | ||
205 | byte buf[4]; | ||
206 | |||
207 | if (!inp || !r_idx) | ||
208 | { | ||
209 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",209); } while(0);; | ||
210 | return CDK_Inv_Value; | ||
211 | } | ||
212 | |||
213 | idx = cdk_callocgnutls_calloc (1, sizeof *idx); | ||
214 | if (!idx) | ||
215 | { | ||
216 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",216); } while(0);; | ||
217 | return CDK_Out_Of_Core; | ||
218 | } | ||
219 | |||
220 | while (!cdk_stream_eof (inp)) | ||
221 | { | ||
222 | if (cdk_stream_read (inp, buf, 4) == CDK_EOF) | ||
223 | break; | ||
224 | idx->offset = _cdk_buftou32 (buf); | ||
225 | cdk_stream_read (inp, buf, 4); | ||
226 | idx->keyid[0] = _cdk_buftou32 (buf); | ||
227 | cdk_stream_read (inp, buf, 4); | ||
228 | idx->keyid[1] = _cdk_buftou32 (buf); | ||
229 | cdk_stream_read (inp, idx->fpr, KEY_FPR_LEN20); | ||
230 | break; | ||
231 | } | ||
232 | *r_idx = idx; | ||
233 | return cdk_stream_eof (inp) ? CDK_EOF : 0; | ||
234 | } | ||
235 | |||
236 | |||
237 | static cdk_error_t | ||
238 | keydb_idx_search (cdk_stream_t inp, u32 * keyid, const byte * fpr, | ||
239 | off_t * r_off) | ||
240 | { | ||
241 | key_idx_t idx; | ||
242 | |||
243 | if (!inp || !r_off) | ||
244 | { | ||
245 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",245); } while(0);; | ||
246 | return CDK_Inv_Value; | ||
247 | } | ||
248 | if ((keyid && fpr) || (!keyid && !fpr)) | ||
249 | { | ||
250 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",250); } while(0);; | ||
251 | return CDK_Inv_Mode; | ||
252 | } | ||
253 | |||
254 | /* We need an initialize the offset var with a value | ||
255 | because it might be possible the returned offset will | ||
256 | be 0 and then we cannot differ between the begin and an EOF. */ | ||
257 | *r_off = 0xFFFFFFFF; | ||
258 | cdk_stream_seek (inp, 0); | ||
259 | while (keydb_idx_parse (inp, &idx) != CDK_EOF) | ||
260 | { | ||
261 | if (keyid && KEYID_CMP (keyid, idx->keyid)((keyid[0]) == (idx->keyid[0]) && (keyid[1]) == (idx ->keyid[1]))) | ||
262 | { | ||
263 | *r_off = idx->offset; | ||
264 | break; | ||
265 | } | ||
266 | else if (fpr && !memcmp (idx->fpr, fpr, KEY_FPR_LEN20)) | ||
267 | { | ||
268 | *r_off = idx->offset; | ||
269 | break; | ||
270 | } | ||
271 | cdk_freegnutls_free (idx); | ||
272 | idx = NULL((void*)0); | ||
273 | } | ||
274 | cdk_freegnutls_free (idx); | ||
275 | return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF; | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * cdk_keydb_new_from_mem: | ||
281 | * @r_hd: The keydb output handle. | ||
282 | * @secret: does the stream contain secret key data | ||
283 | * @armor: the stream is base64 | ||
284 | * @data: The raw key data. | ||
285 | * @datlen: The length of the raw data. | ||
286 | * | ||
287 | * Create a new keyring db handle from the contents of a buffer. | ||
288 | */ | ||
289 | cdk_error_t | ||
290 | cdk_keydb_new_from_mem (cdk_keydb_hd_t * r_db, int secret, int armor, | ||
291 | const void *data, size_t datlen) | ||
292 | { | ||
293 | cdk_keydb_hd_t db; | ||
294 | cdk_error_t rc; | ||
295 | |||
296 | if (!r_db) | ||
297 | { | ||
298 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",298); } while(0);; | ||
299 | return CDK_Inv_Value; | ||
300 | } | ||
301 | *r_db = NULL((void*)0); | ||
302 | db = calloc (1, sizeof *db); | ||
303 | rc = cdk_stream_tmp_from_mem (data, datlen, &db->fp); | ||
304 | if (!db->fp) | ||
305 | { | ||
306 | cdk_freegnutls_free (db); | ||
307 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",307); } while(0);; | ||
308 | return rc; | ||
309 | } | ||
310 | |||
311 | if (armor) | ||
312 | cdk_stream_set_armor_flag (db->fp, 0); | ||
313 | db->type = CDK_DBTYPE_DATA; | ||
314 | db->secret = secret; | ||
315 | *r_db = db; | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * cdk_keydb_free: | ||
321 | * @hd: the keydb object | ||
322 | * | ||
323 | * Free the keydb object. | ||
324 | **/ | ||
325 | void | ||
326 | cdk_keydb_free (cdk_keydb_hd_t hd) | ||
327 | { | ||
328 | if (!hd) | ||
329 | return; | ||
330 | |||
331 | if (hd->name) | ||
332 | { | ||
333 | cdk_freegnutls_free (hd->name); | ||
334 | hd->name = NULL((void*)0); | ||
335 | } | ||
336 | |||
337 | if (hd->fp && !hd->fp_ref) | ||
338 | { | ||
339 | cdk_stream_close (hd->fp); | ||
340 | hd->fp = NULL((void*)0); | ||
341 | } | ||
342 | |||
343 | |||
344 | hd->isopen = 0; | ||
345 | hd->secret = 0; | ||
346 | cdk_freegnutls_free (hd); | ||
347 | } | ||
348 | |||
349 | |||
350 | static cdk_error_t | ||
351 | _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t * ret_kr) | ||
352 | { | ||
353 | cdk_error_t rc; | ||
354 | cdk_stream_t kr; | ||
355 | |||
356 | if (!hd || !ret_kr) | ||
357 | { | ||
358 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",358); } while(0);; | ||
359 | return CDK_Inv_Value; | ||
360 | } | ||
361 | |||
362 | rc = 0; | ||
363 | if ((hd->type == CDK_DBTYPE_DATA) | ||
364 | && hd->fp) | ||
365 | { | ||
366 | kr = hd->fp; | ||
367 | cdk_stream_seek (kr, 0); | ||
368 | } | ||
369 | else if (hd->type == CDK_DBTYPE_PK_KEYRING || | ||
370 | hd->type == CDK_DBTYPE_SK_KEYRING) | ||
371 | { | ||
372 | rc = cdk_stream_open (hd->name, &kr); | ||
373 | |||
374 | if (rc) | ||
375 | goto leave; | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",379); } while(0);; | ||
380 | return CDK_Inv_Mode; | ||
381 | } | ||
382 | |||
383 | leave: | ||
384 | |||
385 | *ret_kr = kr; | ||
386 | return rc; | ||
387 | } | ||
388 | |||
389 | |||
390 | static int | ||
391 | find_by_keyid (cdk_kbnode_t knode, cdk_keydb_search_t ks) | ||
392 | { | ||
393 | cdk_kbnode_t node; | ||
394 | u32 keyid[2]; | ||
395 | |||
396 | for (node = knode; node; node = node->next) | ||
397 | { | ||
398 | if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
399 | node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || | ||
400 | node->pkt->pkttype == CDK_PKT_SECRET_KEY || | ||
401 | node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
402 | { | ||
403 | _cdk_pkt_get_keyid (node->pkt, keyid); | ||
404 | switch (ks->type) | ||
405 | { | ||
406 | case CDK_DBSEARCH_SHORT_KEYID: | ||
407 | if (keyid[1] == ks->u.keyid[1]) | ||
408 | return 1; | ||
409 | break; | ||
410 | |||
411 | case CDK_DBSEARCH_KEYID: | ||
412 | if (KEYID_CMP (keyid, ks->u.keyid)((keyid[0]) == (ks->u.keyid[0]) && (keyid[1]) == ( ks->u.keyid[1]))) | ||
413 | return 1; | ||
414 | break; | ||
415 | |||
416 | default: | ||
417 | _cdk_log_debug ("find_by_keyid: invalid mode = %d\n", ks->type)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "find_by_keyid: invalid mode = %d\n", ks->type); } while (0); | ||
418 | return 0; | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | |||
426 | static int | ||
427 | find_by_fpr (cdk_kbnode_t knode, cdk_keydb_search_t ks) | ||
428 | { | ||
429 | cdk_kbnode_t node; | ||
430 | byte fpr[KEY_FPR_LEN20]; | ||
431 | |||
432 | if (ks->type != CDK_DBSEARCH_FPR) | ||
433 | return 0; | ||
434 | |||
435 | for (node = knode; node; node = node->next) | ||
436 | { | ||
437 | if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
438 | node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || | ||
439 | node->pkt->pkttype == CDK_PKT_SECRET_KEY || | ||
440 | node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
441 | { | ||
442 | _cdk_pkt_get_fingerprint (node->pkt, fpr); | ||
443 | if (!memcmp (ks->u.fpr, fpr, KEY_FPR_LEN20)) | ||
444 | return 1; | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | |||
453 | static int | ||
454 | find_by_pattern (cdk_kbnode_t knode, cdk_keydb_search_t ks) | ||
455 | { | ||
456 | cdk_kbnode_t node; | ||
457 | size_t uidlen; | ||
458 | char *name; | ||
459 | |||
460 | for (node = knode; node; node = node->next) | ||
461 | { | ||
462 | if (node->pkt->pkttype != CDK_PKT_USER_ID) | ||
463 | continue; | ||
464 | if (node->pkt->pkt.user_id->attrib_img != NULL((void*)0)) | ||
465 | continue; /* Skip attribute packets. */ | ||
466 | uidlen = node->pkt->pkt.user_id->len; | ||
467 | name = node->pkt->pkt.user_id->name; | ||
468 | switch (ks->type) | ||
469 | { | ||
470 | case CDK_DBSEARCH_EXACT: | ||
471 | if (name && | ||
472 | (strlen (ks->u.pattern) == uidlen && | ||
473 | !strncmp (ks->u.pattern, name, uidlen))) | ||
474 | return 1; | ||
475 | break; | ||
476 | |||
477 | case CDK_DBSEARCH_SUBSTR: | ||
478 | if (uidlen > 65536) | ||
479 | break; | ||
480 | if (name && strlen (ks->u.pattern) > uidlen) | ||
481 | break; | ||
482 | if (name && _cdk_memistr (name, uidlen, ks->u.pattern)) | ||
483 | return 1; | ||
484 | break; | ||
485 | |||
486 | default: /* Invalid mode */ | ||
487 | return 0; | ||
488 | } | ||
489 | } | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | |||
494 | static void | ||
495 | keydb_cache_free (key_table_t cache) | ||
496 | { | ||
497 | key_table_t c2; | ||
498 | |||
499 | while (cache) | ||
500 | { | ||
501 | c2 = cache->next; | ||
502 | cache->offset = 0; | ||
503 | cdk_freegnutls_free (cache); | ||
504 | cache = c2; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | |||
509 | static key_table_t | ||
510 | keydb_cache_find (cdk_keydb_search_t desc) | ||
511 | { | ||
512 | key_table_t cache = desc->cache; | ||
513 | key_table_t t; | ||
514 | |||
515 | for (t = cache; t; t = t->next) | ||
516 | { | ||
517 | switch (desc->type) | ||
518 | { | ||
519 | case CDK_DBSEARCH_SHORT_KEYID: | ||
520 | case CDK_DBSEARCH_KEYID: | ||
521 | if (KEYID_CMP (desc->u.keyid, desc->u.keyid)((desc->u.keyid[0]) == (desc->u.keyid[0]) && (desc ->u.keyid[1]) == (desc->u.keyid[1]))) | ||
522 | return t; | ||
523 | break; | ||
524 | |||
525 | case CDK_DBSEARCH_EXACT: | ||
526 | if (strlen (desc->u.pattern) == strlen (desc->u.pattern) && | ||
527 | !strcmp (desc->u.pattern, desc->u.pattern)) | ||
528 | return t; | ||
529 | break; | ||
530 | |||
531 | case CDK_DBSEARCH_SUBSTR: | ||
532 | if (strstr (desc->u.pattern, desc->u.pattern)) | ||
533 | return t; | ||
534 | break; | ||
535 | |||
536 | case CDK_DBSEARCH_FPR: | ||
537 | if (!memcmp (desc->u.fpr, desc->u.fpr, KEY_FPR_LEN20)) | ||
538 | return t; | ||
539 | break; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | return NULL((void*)0); | ||
544 | } | ||
545 | |||
546 | |||
547 | static cdk_error_t | ||
548 | keydb_cache_add (cdk_keydb_search_t dbs, off_t offset) | ||
549 | { | ||
550 | key_table_t k; | ||
551 | |||
552 | if (dbs->ncache > KEYDB_CACHE_ENTRIES8) | ||
553 | return 0; /* FIXME: we should replace the last entry. */ | ||
554 | k = cdk_callocgnutls_calloc (1, sizeof *k); | ||
555 | if (!k) | ||
556 | { | ||
557 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",557); } while(0);; | ||
558 | return CDK_Out_Of_Core; | ||
559 | } | ||
560 | |||
561 | k->offset = offset; | ||
562 | |||
563 | k->next = dbs->cache; | ||
564 | dbs->cache = k; | ||
565 | dbs->ncache++; | ||
566 | _cdk_log_debug ("cache: add entry off=%d type=%d\n", (int) offset,do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cache: add entry off=%d type=%d\n", (int) offset, (int) dbs->type); } while(0) | ||
567 | (int) dbs->type)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cache: add entry off=%d type=%d\n", (int) offset, (int) dbs->type); } while(0); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static cdk_error_t | ||
572 | idx_init (cdk_keydb_hd_t db, cdk_keydb_search_t dbs) | ||
573 | { | ||
574 | cdk_error_t ec, rc = 0; | ||
575 | |||
576 | if (cdk_stream_get_length (db->fp) < 524288) | ||
577 | { | ||
578 | dbs->no_cache = 1; | ||
579 | goto leave; | ||
580 | } | ||
581 | |||
582 | dbs->idx_name = keydb_idx_mkname (db->name); | ||
583 | if (!dbs->idx_name) | ||
584 | { | ||
585 | rc = CDK_Out_Of_Core; | ||
586 | goto leave; | ||
587 | } | ||
588 | ec = cdk_stream_open (dbs->idx_name, &dbs->idx); | ||
589 | |||
590 | if (ec && !db->secret) | ||
591 | { | ||
592 | rc = keydb_idx_build (db->name); | ||
593 | if (!rc) | ||
594 | rc = cdk_stream_open (dbs->idx_name, &dbs->idx); | ||
595 | if (!rc) | ||
596 | { | ||
597 | _cdk_log_debug ("create key index table\n")do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "create key index table\n"); } while(0); | ||
598 | } | ||
599 | else | ||
600 | { | ||
601 | /* This is no real error, it just means we can't create | ||
602 | the index at the given directory. maybe we've no write | ||
603 | access. in this case, we simply disable the index. */ | ||
604 | _cdk_log_debug ("disable key index table err=%d\n", rc)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "disable key index table err=%d\n", rc); } while(0); | ||
605 | rc = 0; | ||
606 | dbs->no_cache = 1; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | leave: | ||
611 | |||
612 | return rc; | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * cdk_keydb_search_start: | ||
617 | * @st: search handle | ||
618 | * @db: key database handle | ||
619 | * @type: specifies the search type | ||
620 | * @desc: description which depends on the type | ||
621 | * | ||
622 | * Create a new keydb search object. | ||
623 | **/ | ||
624 | cdk_error_t | ||
625 | cdk_keydb_search_start (cdk_keydb_search_t * st, cdk_keydb_hd_t db, int type, | ||
626 | void *desc) | ||
627 | { | ||
628 | u32 *keyid; | ||
629 | char *p, tmp[3]; | ||
630 | int i; | ||
631 | cdk_error_t rc; | ||
632 | |||
633 | if (!db) | ||
634 | { | ||
635 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",635); } while(0);; | ||
636 | return CDK_Inv_Value; | ||
637 | } | ||
638 | if (type != CDK_DBSEARCH_NEXT && !desc) | ||
639 | { | ||
640 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",640); } while(0);; | ||
641 | return CDK_Inv_Mode; | ||
642 | } | ||
643 | |||
644 | *st = cdk_callocgnutls_calloc (1, sizeof (cdk_keydb_search_s)); | ||
645 | if (!(*st)) | ||
646 | { | ||
647 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",647); } while(0);; | ||
648 | return CDK_Out_Of_Core; | ||
649 | } | ||
650 | |||
651 | rc = idx_init (db, *st); | ||
652 | if (rc != CDK_Success) | ||
653 | { | ||
654 | free (*st); | ||
655 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",655); } while(0);; | ||
656 | return rc; | ||
657 | } | ||
658 | |||
659 | (*st)->type = type; | ||
660 | switch (type) | ||
661 | { | ||
662 | case CDK_DBSEARCH_EXACT: | ||
663 | case CDK_DBSEARCH_SUBSTR: | ||
664 | cdk_freegnutls_free ((*st)->u.pattern); | ||
665 | (*st)->u.pattern = cdk_strdupgnutls_strdup (desc); | ||
666 | if (!(*st)->u.pattern) | ||
667 | { | ||
668 | cdk_freegnutls_free (*st); | ||
669 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",669); } while(0);; | ||
670 | return CDK_Out_Of_Core; | ||
671 | } | ||
672 | break; | ||
673 | |||
674 | case CDK_DBSEARCH_SHORT_KEYID: | ||
675 | keyid = desc; | ||
676 | (*st)->u.keyid[1] = keyid[0]; | ||
677 | break; | ||
678 | |||
679 | case CDK_DBSEARCH_KEYID: | ||
680 | keyid = desc; | ||
681 | (*st)->u.keyid[0] = keyid[0]; | ||
682 | (*st)->u.keyid[1] = keyid[1]; | ||
683 | break; | ||
684 | |||
685 | case CDK_DBSEARCH_FPR: | ||
686 | memcpy ((*st)->u.fpr, desc, KEY_FPR_LEN20); | ||
687 | break; | ||
688 | |||
689 | case CDK_DBSEARCH_NEXT: | ||
690 | break; | ||
691 | |||
692 | case CDK_DBSEARCH_AUTO: | ||
693 | /* Override the type with the actual db search type. */ | ||
694 | (*st)->type = classify_data (desc, strlen (desc)); | ||
695 | switch ((*st)->type) | ||
696 | { | ||
697 | case CDK_DBSEARCH_SUBSTR: | ||
698 | case CDK_DBSEARCH_EXACT: | ||
699 | cdk_freegnutls_free ((*st)->u.pattern); | ||
700 | p = (*st)->u.pattern = cdk_strdupgnutls_strdup (desc); | ||
701 | if (!p) | ||
702 | { | ||
703 | cdk_freegnutls_free (*st); | ||
704 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",704); } while(0);; | ||
705 | return CDK_Out_Of_Core; | ||
706 | } | ||
707 | break; | ||
708 | |||
709 | case CDK_DBSEARCH_SHORT_KEYID: | ||
710 | case CDK_DBSEARCH_KEYID: | ||
711 | p = desc; | ||
712 | if (!strncmp (p, "0x", 2)) | ||
713 | p += 2; | ||
714 | if (strlen (p) == 8) | ||
715 | { | ||
716 | (*st)->u.keyid[0] = 0; | ||
717 | (*st)->u.keyid[1] = strtoul (p, NULL((void*)0), 16); | ||
718 | } | ||
719 | else if (strlen (p) == 16) | ||
720 | { | ||
721 | (*st)->u.keyid[0] = strtoul (p, NULL((void*)0), 16); | ||
722 | (*st)->u.keyid[1] = strtoul (p + 8, NULL((void*)0), 16); | ||
723 | } | ||
724 | else | ||
725 | { /* Invalid key ID object. */ | ||
726 | cdk_freegnutls_free (*st); | ||
727 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",727); } while(0);; | ||
728 | return CDK_Inv_Mode; | ||
729 | } | ||
730 | break; | ||
731 | |||
732 | case CDK_DBSEARCH_FPR: | ||
733 | p = desc; | ||
734 | if (strlen (p) != 2 * KEY_FPR_LEN20) | ||
735 | { | ||
736 | cdk_freegnutls_free (*st); | ||
737 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",737); } while(0);; | ||
738 | return CDK_Inv_Mode; | ||
739 | } | ||
740 | for (i = 0; i < KEY_FPR_LEN20; i++) | ||
741 | { | ||
742 | tmp[0] = p[2 * i]; | ||
743 | tmp[1] = p[2 * i + 1]; | ||
744 | tmp[2] = 0x00; | ||
745 | (*st)->u.fpr[i] = strtoul (tmp, NULL((void*)0), 16); | ||
746 | } | ||
747 | break; | ||
748 | } | ||
749 | break; | ||
750 | |||
751 | default: | ||
752 | cdk_freegnutls_free (*st); | ||
753 | _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cdk_keydb_search_start: invalid mode = %d\n", type); } while (0); | ||
754 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",754); } while(0);; | ||
755 | return CDK_Inv_Mode; | ||
756 | } | ||
757 | |||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | |||
762 | static cdk_error_t | ||
763 | keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_keydb_search_t ks, | ||
764 | int *r_cache_hit, off_t * r_off) | ||
765 | { | ||
766 | key_table_t c; | ||
767 | |||
768 | if (!hd || !r_cache_hit || !r_off) | ||
769 | { | ||
770 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",770); } while(0);; | ||
771 | return CDK_Inv_Value; | ||
772 | } | ||
773 | |||
774 | /* Reset the values. */ | ||
775 | *r_cache_hit = 0; | ||
776 | *r_off = 0; | ||
777 | |||
778 | c = keydb_cache_find (ks); | ||
779 | if (c != NULL((void*)0)) | ||
780 | { | ||
781 | _cdk_log_debug ("cache: found entry in cache.\n")do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cache: found entry in cache.\n"); } while(0); | ||
782 | *r_cache_hit = 1; | ||
783 | *r_off = c->offset; | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | /* No index cache available so we just return here. */ | ||
788 | if (!ks->idx) | ||
789 | return 0; | ||
790 | |||
791 | if (ks->idx) | ||
792 | { | ||
793 | if (ks->type == CDK_DBSEARCH_KEYID) | ||
794 | { | ||
795 | if (keydb_idx_search (ks->idx, ks->u.keyid, NULL((void*)0), r_off)) | ||
796 | { | ||
797 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",797); } while(0);; | ||
798 | return CDK_Error_No_Key; | ||
799 | } | ||
800 | _cdk_log_debug ("cache: found keyid entry in idx table.\n")do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cache: found keyid entry in idx table.\n"); } while(0); | ||
801 | *r_cache_hit = 1; | ||
802 | } | ||
803 | else if (ks->type == CDK_DBSEARCH_FPR) | ||
804 | { | ||
805 | if (keydb_idx_search (ks->idx, NULL((void*)0), ks->u.fpr, r_off)) | ||
806 | { | ||
807 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",807); } while(0);; | ||
808 | return CDK_Error_No_Key; | ||
809 | } | ||
810 | _cdk_log_debug ("cache: found fpr entry in idx table.\n")do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "cache: found fpr entry in idx table.\n"); } while(0); | ||
811 | *r_cache_hit = 1; | ||
812 | } | ||
813 | } | ||
814 | |||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | void | ||
819 | cdk_keydb_search_release (cdk_keydb_search_t st) | ||
820 | { | ||
821 | keydb_cache_free (st->cache); | ||
822 | |||
823 | if (st->idx) | ||
824 | cdk_stream_close (st->idx); | ||
825 | |||
826 | if (!st) | ||
827 | return; | ||
828 | if (st->type == CDK_DBSEARCH_EXACT || st->type == CDK_DBSEARCH_SUBSTR) | ||
829 | cdk_freegnutls_free (st->u.pattern); | ||
830 | |||
831 | cdk_freegnutls_free (st); | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * cdk_keydb_search: | ||
836 | * @st: the search handle | ||
837 | * @hd: the keydb object | ||
838 | * @ret_key: kbnode object to store the key | ||
839 | * | ||
840 | * Search for a key in the given keyring. The search mode is handled | ||
841 | * via @ks. If the key was found, @ret_key contains the key data. | ||
842 | **/ | ||
843 | cdk_error_t | ||
844 | cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, | ||
845 | cdk_kbnode_t * ret_key) | ||
846 | { | ||
847 | cdk_stream_t kr; | ||
848 | cdk_kbnode_t knode; | ||
849 | cdk_error_t rc = 0; | ||
850 | off_t pos = 0, off = 0; | ||
851 | int key_found = 0, cache_hit = 0; | ||
852 | |||
853 | if (!hd || !ret_key || !st) | ||
854 | { | ||
855 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",855); } while(0);; | ||
856 | return CDK_Inv_Value; | ||
857 | } | ||
858 | |||
859 | *ret_key = NULL((void*)0); | ||
860 | kr = NULL((void*)0); | ||
861 | |||
862 | rc = _cdk_keydb_open (hd, &kr); | ||
863 | if (rc) | ||
864 | { | ||
865 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",865); } while(0);; | ||
866 | return rc; | ||
867 | } | ||
868 | |||
869 | if (!st->no_cache) | ||
870 | { | ||
871 | /* It is possible the index is not up-to-date and thus we do | ||
872 | not find the requesed key. In this case, we reset cache hit | ||
873 | and continue our normal search procedure. */ | ||
874 | rc = keydb_pos_from_cache (hd, st, &cache_hit, &off); | ||
875 | if (rc) | ||
876 | cache_hit = 0; | ||
877 | } | ||
878 | |||
879 | knode = NULL((void*)0); | ||
880 | |||
881 | while (!key_found && !rc) | ||
882 | { | ||
883 | if (cache_hit && st->type != CDK_DBSEARCH_NEXT) | ||
884 | cdk_stream_seek (kr, off); | ||
885 | else if (st->type == CDK_DBSEARCH_NEXT) | ||
886 | cdk_stream_seek (kr, st->off); | ||
887 | |||
888 | pos = cdk_stream_tell (kr); | ||
889 | |||
890 | rc = cdk_keydb_get_keyblock (kr, &knode); | ||
891 | |||
892 | if (rc) | ||
893 | { | ||
894 | if (rc == CDK_EOF) | ||
895 | break; | ||
896 | else | ||
897 | { | ||
898 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",898); } while(0);; | ||
899 | return rc; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | switch (st->type) | ||
904 | { | ||
905 | case CDK_DBSEARCH_SHORT_KEYID: | ||
906 | case CDK_DBSEARCH_KEYID: | ||
907 | key_found = find_by_keyid (knode, st); | ||
908 | break; | ||
909 | |||
910 | case CDK_DBSEARCH_FPR: | ||
911 | key_found = find_by_fpr (knode, st); | ||
912 | break; | ||
913 | |||
914 | case CDK_DBSEARCH_EXACT: | ||
915 | case CDK_DBSEARCH_SUBSTR: | ||
916 | key_found = find_by_pattern (knode, st); | ||
917 | break; | ||
918 | |||
919 | case CDK_DBSEARCH_NEXT: | ||
920 | st->off = cdk_stream_tell (kr); | ||
921 | key_found = knode ? 1 : 0; | ||
922 | break; | ||
923 | } | ||
924 | |||
925 | if (key_found) | ||
926 | { | ||
927 | if (!keydb_cache_find (st)) | ||
928 | keydb_cache_add (st, pos); | ||
929 | break; | ||
930 | } | ||
931 | |||
932 | cdk_kbnode_release (knode); | ||
933 | knode = NULL((void*)0); | ||
934 | } | ||
935 | |||
936 | if (key_found && rc == CDK_EOF) | ||
937 | rc = 0; | ||
938 | else if (rc == CDK_EOF && !key_found) | ||
939 | { | ||
940 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",940); } while(0);; | ||
941 | rc = CDK_Error_No_Key; | ||
942 | } | ||
943 | *ret_key = key_found ? knode : NULL((void*)0); | ||
944 | return rc; | ||
945 | } | ||
946 | |||
947 | cdk_error_t | ||
948 | cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, u32 * keyid, cdk_kbnode_t * ret_key) | ||
949 | { | ||
950 | cdk_error_t rc; | ||
951 | cdk_keydb_search_t st; | ||
952 | |||
953 | if (!hd || !keyid || !ret_key) | ||
954 | { | ||
955 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",955); } while(0);; | ||
956 | return CDK_Inv_Value; | ||
957 | } | ||
958 | |||
959 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid); | ||
960 | if (!rc) | ||
961 | rc = cdk_keydb_search (st, hd, ret_key); | ||
962 | |||
963 | cdk_keydb_search_release (st); | ||
964 | return rc; | ||
965 | } | ||
966 | |||
967 | |||
968 | cdk_error_t | ||
969 | cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const byte * fpr, | ||
970 | cdk_kbnode_t * r_key) | ||
971 | { | ||
972 | cdk_error_t rc; | ||
973 | cdk_keydb_search_t st; | ||
974 | |||
975 | if (!hd || !fpr || !r_key) | ||
976 | { | ||
977 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",977); } while(0);; | ||
978 | return CDK_Inv_Value; | ||
979 | } | ||
980 | |||
981 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_FPR, (byte *) fpr); | ||
982 | if (!rc) | ||
983 | rc = cdk_keydb_search (st, hd, r_key); | ||
984 | |||
985 | cdk_keydb_search_release (st); | ||
986 | return rc; | ||
987 | } | ||
988 | |||
989 | |||
990 | cdk_error_t | ||
991 | cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt, | ||
992 | cdk_kbnode_t * ret_key) | ||
993 | { | ||
994 | cdk_error_t rc; | ||
995 | cdk_keydb_search_t st; | ||
996 | |||
997 | if (!hd || !patt || !ret_key) | ||
998 | { | ||
999 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",999); } while(0);; | ||
1000 | return CDK_Inv_Value; | ||
1001 | } | ||
1002 | |||
1003 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_SUBSTR, (char *) patt); | ||
1004 | if (!rc) | ||
1005 | rc = cdk_keydb_search (st, hd, ret_key); | ||
1006 | |||
1007 | if (rc) | ||
1008 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1008); } while(0);; | ||
1009 | |||
1010 | cdk_keydb_search_release (st); | ||
1011 | return rc; | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | static int | ||
1016 | keydb_check_key (cdk_packet_t pkt) | ||
1017 | { | ||
1018 | cdk_pkt_pubkey_t pk; | ||
1019 | int is_sk, valid; | ||
1020 | |||
1021 | if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1022 | pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
1023 | { | ||
1024 | pk = pkt->pkt.public_key; | ||
1025 | is_sk = 0; | ||
1026 | } | ||
1027 | else if (pkt->pkttype == CDK_PKT_SECRET_KEY || | ||
1028 | pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
1029 | { | ||
1030 | pk = pkt->pkt.secret_key->pk; | ||
1031 | is_sk = 1; | ||
1032 | } | ||
1033 | else /* No key object. */ | ||
1034 | return 0; | ||
1035 | valid = !pk->is_revoked && !pk->has_expired; | ||
1036 | if (is_sk) | ||
1037 | return valid; | ||
1038 | return valid && !pk->is_invalid; | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | /* Find the first kbnode with the requested packet type | ||
1043 | that represents a valid key. */ | ||
1044 | static cdk_kbnode_t | ||
1045 | kbnode_find_valid (cdk_kbnode_t root, cdk_packet_type_t pkttype) | ||
1046 | { | ||
1047 | cdk_kbnode_t n; | ||
1048 | |||
1049 | for (n = root; n; n = n->next) | ||
1050 | { | ||
1051 | if (n->pkt->pkttype != pkttype) | ||
1052 | continue; | ||
1053 | if (keydb_check_key (n->pkt)) | ||
1054 | return n; | ||
1055 | } | ||
1056 | |||
1057 | return NULL((void*)0); | ||
1058 | } | ||
1059 | |||
1060 | |||
1061 | static cdk_kbnode_t | ||
1062 | keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk) | ||
1063 | { | ||
1064 | cdk_kbnode_t node, key; | ||
1065 | int req_type; | ||
1066 | long timestamp; | ||
1067 | |||
1068 | req_type = is_pk ? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY; | ||
1069 | if (!req_usage) | ||
1070 | return kbnode_find_valid (root, req_type); | ||
1071 | |||
1072 | node = cdk_kbnode_find (root, req_type); | ||
1073 | if (node && !keydb_check_key (node->pkt)) | ||
1074 | return NULL((void*)0); | ||
1075 | |||
1076 | key = NULL((void*)0); | ||
1077 | timestamp = 0; | ||
1078 | /* We iteratre over the all nodes and search for keys or | ||
1079 | subkeys which match the usage and which are not invalid. | ||
1080 | A timestamp is used to figure out the newest valid key. */ | ||
1081 | for (node = root; node; node = node->next) | ||
1082 | { | ||
1083 | if (is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1084 | node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
1085 | && keydb_check_key (node->pkt) | ||
1086 | && (node->pkt->pkt.public_key->pubkey_usage & req_usage)) | ||
1087 | { | ||
1088 | if (node->pkt->pkt.public_key->timestamp > timestamp) | ||
1089 | key = node; | ||
1090 | } | ||
1091 | if (!is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY || | ||
1092 | node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
1093 | && keydb_check_key (node->pkt) | ||
1094 | && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage)) | ||
1095 | { | ||
1096 | if (node->pkt->pkt.secret_key->pk->timestamp > timestamp) | ||
1097 | key = node; | ||
1098 | } | ||
1099 | |||
1100 | } | ||
1101 | return key; | ||
1102 | } | ||
1103 | |||
1104 | |||
1105 | static cdk_kbnode_t | ||
1106 | keydb_find_bykeyid (cdk_kbnode_t root, const u32 * keyid, int search_mode) | ||
1107 | { | ||
1108 | cdk_kbnode_t node; | ||
1109 | u32 kid[2]; | ||
1110 | |||
1111 | for (node = root; node; node = node->next) | ||
1112 | { | ||
1113 | if (!_cdk_pkt_get_keyid (node->pkt, kid)) | ||
1114 | continue; | ||
1115 | if (search_mode == CDK_DBSEARCH_SHORT_KEYID && kid[1] == keyid[1]) | ||
1116 | return node; | ||
1117 | else if (kid[0] == keyid[0] && kid[1] == keyid[1]) | ||
1118 | return node; | ||
1119 | } | ||
1120 | return NULL((void*)0); | ||
1121 | } | ||
1122 | |||
1123 | |||
1124 | cdk_error_t | ||
1125 | _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name, | ||
1126 | cdk_seckey_t * ret_sk, int usage) | ||
1127 | { | ||
1128 | cdk_kbnode_t knode = NULL((void*)0); | ||
1129 | cdk_kbnode_t node, sk_node, pk_node; | ||
1130 | cdk_pkt_seckey_t sk; | ||
1131 | cdk_error_t rc; | ||
1132 | const char *s; | ||
1133 | int pkttype; | ||
1134 | cdk_keydb_search_t st; | ||
1135 | |||
1136 | if (!ret_sk || !usage) | ||
1137 | { | ||
1138 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1138); } while(0);; | ||
1139 | return CDK_Inv_Value; | ||
1140 | } | ||
1141 | |||
1142 | if (!hd) | ||
1143 | { | ||
1144 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1144); } while(0);; | ||
1145 | return CDK_Error_No_Keyring; | ||
1146 | } | ||
1147 | |||
1148 | *ret_sk = NULL((void*)0); | ||
1149 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name); | ||
1150 | if (rc) | ||
1151 | { | ||
1152 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1152); } while(0);; | ||
1153 | return rc; | ||
1154 | } | ||
1155 | |||
1156 | rc = cdk_keydb_search (st, hd, &knode); | ||
1157 | if (rc) | ||
1158 | { | ||
1159 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1159); } while(0);; | ||
1160 | return rc; | ||
1161 | } | ||
1162 | |||
1163 | cdk_keydb_search_release (st); | ||
1164 | |||
1165 | sk_node = keydb_find_byusage (knode, usage, 0); | ||
1166 | if (!sk_node) | ||
1167 | { | ||
1168 | cdk_kbnode_release (knode); | ||
1169 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1169); } while(0);; | ||
1170 | return CDK_Unusable_Key; | ||
1171 | } | ||
1172 | |||
1173 | /* We clone the node with the secret key to avoid that the | ||
1174 | packet will be released. */ | ||
1175 | _cdk_kbnode_clone (sk_node); | ||
1176 | sk = sk_node->pkt->pkt.secret_key; | ||
1177 | |||
1178 | for (node = knode; node; node = node->next) | ||
1179 | { | ||
1180 | if (node->pkt->pkttype == CDK_PKT_USER_ID) | ||
1181 | { | ||
1182 | s = node->pkt->pkt.user_id->name; | ||
1183 | if (sk && !sk->pk->uid && _cdk_memistr (s, strlen (s), name)) | ||
1184 | { | ||
1185 | _cdk_copy_userid (&sk->pk->uid, node->pkt->pkt.user_id); | ||
1186 | break; | ||
1187 | } | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | /* To find the self signature, we need the primary public key because | ||
1192 | the selected secret key might be different from the primary key. */ | ||
1193 | pk_node = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY); | ||
1194 | if (!pk_node) | ||
1195 | { | ||
1196 | cdk_kbnode_release (knode); | ||
1197 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1197); } while(0);; | ||
1198 | return CDK_Unusable_Key; | ||
1199 | } | ||
1200 | node = find_selfsig_node (knode, pk_node->pkt->pkt.secret_key->pk); | ||
1201 | if (sk->pk->uid && node) | ||
1202 | _cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature); | ||
1203 | |||
1204 | /* We only release the outer packet. */ | ||
1205 | _cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void *) &sk); | ||
1206 | cdk_kbnode_release (knode); | ||
1207 | *ret_sk = sk; | ||
1208 | return rc; | ||
1209 | } | ||
1210 | |||
1211 | |||
1212 | cdk_error_t | ||
1213 | _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name, | ||
1214 | cdk_pubkey_t * ret_pk, int usage) | ||
1215 | { | ||
1216 | cdk_kbnode_t knode, node, pk_node; | ||
1217 | cdk_pkt_pubkey_t pk; | ||
1218 | const char *s; | ||
1219 | cdk_error_t rc; | ||
1220 | cdk_keydb_search_t st; | ||
1221 | |||
1222 | if (!ret_pk || !usage) | ||
| |||
1223 | { | ||
1224 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1224); } while(0);; | ||
1225 | return CDK_Inv_Value; | ||
1226 | } | ||
1227 | if (!hd) | ||
| |||
1228 | { | ||
1229 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1229); } while(0);; | ||
1230 | return CDK_Error_No_Keyring; | ||
1231 | } | ||
1232 | |||
1233 | *ret_pk = NULL((void*)0); | ||
1234 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name); | ||
1235 | if (!rc) | ||
| |||
1236 | rc = cdk_keydb_search (st, hd, &knode); | ||
1237 | if (rc) | ||
| |||
1238 | { | ||
1239 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1239); } while(0);; | ||
1240 | return rc; | ||
1241 | } | ||
1242 | |||
1243 | cdk_keydb_search_release (st); | ||
1244 | |||
1245 | node = keydb_find_byusage (knode, usage, 1); | ||
1246 | if (!node) | ||
| |||
1247 | { | ||
1248 | cdk_kbnode_release (knode); | ||
1249 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1249); } while(0);; | ||
1250 | return CDK_Unusable_Key; | ||
1251 | } | ||
1252 | |||
1253 | pk = NULL((void*)0); | ||
1254 | _cdk_copy_pubkey (&pk, node->pkt->pkt.public_key); | ||
1255 | for (node = knode; node; node = node->next) | ||
| |||
| |||
1256 | { | ||
1257 | if (node->pkt->pkttype == CDK_PKT_USER_ID) | ||
| |||
1258 | { | ||
1259 | s = node->pkt->pkt.user_id->name; | ||
1260 | if (pk && !pk->uid && _cdk_memistr (s, strlen (s), name)) | ||
| |||
| |||
1261 | { | ||
1262 | _cdk_copy_userid (&pk->uid, node->pkt->pkt.user_id); | ||
1263 | break; | ||
1264 | } | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | /* Same as in the sk code, the selected key can be a sub key | ||
1269 | and thus we need the primary key to find the self sig. */ | ||
1270 | pk_node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); | ||
1271 | if (!pk_node) | ||
| |||
1272 | { | ||
1273 | cdk_kbnode_release (knode); | ||
1274 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1274); } while(0);; | ||
1275 | return CDK_Unusable_Key; | ||
1276 | } | ||
1277 | node = find_selfsig_node (knode, pk_node->pkt->pkt.public_key); | ||
1278 | if (pk->uid && node) | ||
| |||
1279 | _cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature); | ||
1280 | cdk_kbnode_release (knode); | ||
1281 | |||
1282 | *ret_pk = pk; | ||
1283 | return rc; | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * cdk_keydb_get_pk: | ||
1289 | * @hd: key db handle | ||
1290 | * @keyid: keyid of the key | ||
1291 | * @r_pk: the allocated public key | ||
1292 | * | ||
1293 | * Perform a key database search by keyid and return the raw public | ||
1294 | * key without any signatures or user id's. | ||
1295 | **/ | ||
1296 | cdk_error_t | ||
1297 | cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 * keyid, cdk_pubkey_t * r_pk) | ||
1298 | { | ||
1299 | cdk_kbnode_t knode = NULL((void*)0), node; | ||
1300 | cdk_pubkey_t pk; | ||
1301 | cdk_error_t rc; | ||
1302 | size_t s_type; | ||
1303 | int pkttype; | ||
1304 | cdk_keydb_search_t st; | ||
1305 | |||
1306 | if (!keyid || !r_pk) | ||
1307 | { | ||
1308 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1308); } while(0);; | ||
1309 | return CDK_Inv_Value; | ||
1310 | } | ||
1311 | if (!hd) | ||
1312 | { | ||
1313 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1313); } while(0);; | ||
1314 | return CDK_Error_No_Keyring; | ||
1315 | } | ||
1316 | |||
1317 | *r_pk = NULL((void*)0); | ||
1318 | s_type = !keyid[0] ? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID; | ||
1319 | rc = cdk_keydb_search_start (&st, hd, s_type, keyid); | ||
1320 | if (rc) | ||
1321 | { | ||
1322 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1322); } while(0);; | ||
1323 | return rc; | ||
1324 | } | ||
1325 | rc = cdk_keydb_search (st, hd, &knode); | ||
1326 | cdk_keydb_search_release (st); | ||
1327 | if (rc) | ||
1328 | { | ||
1329 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1329); } while(0);; | ||
1330 | return rc; | ||
1331 | } | ||
1332 | |||
1333 | node = keydb_find_bykeyid (knode, keyid, s_type); | ||
1334 | if (!node) | ||
1335 | { | ||
1336 | cdk_kbnode_release (knode); | ||
1337 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1337); } while(0);; | ||
1338 | return CDK_Error_No_Key; | ||
1339 | } | ||
1340 | |||
1341 | /* See comment in cdk_keydb_get_sk() */ | ||
1342 | _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &pk); | ||
1343 | *r_pk = pk; | ||
1344 | _cdk_kbnode_clone (node); | ||
1345 | cdk_kbnode_release (knode); | ||
1346 | |||
1347 | return rc; | ||
1348 | } | ||
1349 | |||
1350 | |||
1351 | /** | ||
1352 | * cdk_keydb_get_sk: | ||
1353 | * @hd: key db handle | ||
1354 | * @keyid: the keyid of the key | ||
1355 | * @ret_sk: the allocated secret key | ||
1356 | * | ||
1357 | * Perform a key database search by keyid and return | ||
1358 | * only the raw secret key without the additional nodes, | ||
1359 | * like the user id or the signatures. | ||
1360 | **/ | ||
1361 | cdk_error_t | ||
1362 | cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 * keyid, cdk_seckey_t * ret_sk) | ||
1363 | { | ||
1364 | cdk_kbnode_t snode, node; | ||
1365 | cdk_seckey_t sk; | ||
1366 | cdk_error_t rc; | ||
1367 | int pkttype; | ||
1368 | |||
1369 | if (!keyid || !ret_sk) | ||
1370 | { | ||
1371 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1371); } while(0);; | ||
1372 | return CDK_Inv_Value; | ||
1373 | } | ||
1374 | if (!hd) | ||
1375 | { | ||
1376 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1376); } while(0);; | ||
1377 | return CDK_Error_No_Keyring; | ||
1378 | } | ||
1379 | |||
1380 | *ret_sk = NULL((void*)0); | ||
1381 | rc = cdk_keydb_get_bykeyid (hd, keyid, &snode); | ||
1382 | if (rc) | ||
1383 | { | ||
1384 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1384); } while(0);; | ||
1385 | return rc; | ||
1386 | } | ||
1387 | |||
1388 | node = keydb_find_bykeyid (snode, keyid, CDK_DBSEARCH_KEYID); | ||
1389 | if (!node) | ||
1390 | { | ||
1391 | cdk_kbnode_release (snode); | ||
1392 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1392); } while(0);; | ||
1393 | return CDK_Error_No_Key; | ||
1394 | } | ||
1395 | |||
1396 | /* We need to release the packet itself but not its contents | ||
1397 | and thus we detach the openpgp packet and release the structure. */ | ||
1398 | _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &sk); | ||
1399 | _cdk_kbnode_clone (node); | ||
1400 | cdk_kbnode_release (snode); | ||
1401 | |||
1402 | *ret_sk = sk; | ||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | |||
1407 | static int | ||
1408 | is_selfsig (cdk_kbnode_t node, const u32 * keyid) | ||
1409 | { | ||
1410 | cdk_pkt_signature_t sig; | ||
1411 | |||
1412 | if (node->pkt->pkttype != CDK_PKT_SIGNATURE) | ||
1413 | return 0; | ||
1414 | sig = node->pkt->pkt.signature; | ||
1415 | if ((sig->sig_class >= 0x10 && sig->sig_class <= 0x13) && | ||
1416 | sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1]) | ||
1417 | return 1; | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | |||
1423 | /* Find the newest self signature for the public key @pk | ||
1424 | and return the signature node. */ | ||
1425 | static cdk_kbnode_t | ||
1426 | find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk) | ||
1427 | { | ||
1428 | cdk_kbnode_t n, sig; | ||
1429 | unsigned int ts; | ||
1430 | u32 keyid[2]; | ||
1431 | |||
1432 | cdk_pk_get_keyid (pk, keyid); | ||
1433 | sig = NULL((void*)0); | ||
1434 | ts = 0; | ||
1435 | for (n = key; n; n = n->next) | ||
1436 | { | ||
1437 | if (is_selfsig (n, keyid) && n->pkt->pkt.signature->timestamp > ts) | ||
1438 | { | ||
1439 | ts = n->pkt->pkt.signature->timestamp; | ||
1440 | sig = n; | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1444 | return sig; | ||
1445 | } | ||
1446 | |||
1447 | static unsigned int | ||
1448 | key_usage_to_cdk_usage (unsigned int usage) | ||
1449 | { | ||
1450 | unsigned key_usage = 0; | ||
1451 | |||
1452 | if (usage & 0x01) /* cert + sign data */ | ||
1453 | key_usage |= CDK_KEY_USG_CERT_SIGN; | ||
1454 | if (usage & 0x02) /* cert + sign data */ | ||
1455 | key_usage |= CDK_KEY_USG_DATA_SIGN; | ||
1456 | if (usage & 0x04) /* encrypt comm. + storage */ | ||
1457 | key_usage |= CDK_KEY_USG_COMM_ENCR; | ||
1458 | if (usage & 0x08) /* encrypt comm. + storage */ | ||
1459 | key_usage |= CDK_KEY_USG_STORAGE_ENCR; | ||
1460 | if (usage & 0x10) /* encrypt comm. + storage */ | ||
1461 | key_usage |= CDK_KEY_USG_SPLIT_KEY; | ||
1462 | if (usage & 0x20) | ||
1463 | key_usage |= CDK_KEY_USG_AUTH; | ||
1464 | if (usage & 0x80) /* encrypt comm. + storage */ | ||
1465 | key_usage |= CDK_KEY_USG_SHARED_KEY; | ||
1466 | |||
1467 | return key_usage; | ||
1468 | } | ||
1469 | |||
1470 | static cdk_error_t | ||
1471 | keydb_merge_selfsig (cdk_kbnode_t key, u32 * keyid) | ||
1472 | { | ||
1473 | cdk_kbnode_t node, kbnode, unode; | ||
1474 | cdk_subpkt_t s = NULL((void*)0); | ||
1475 | cdk_pkt_signature_t sig = NULL((void*)0); | ||
1476 | cdk_pkt_userid_t uid = NULL((void*)0); | ||
1477 | const byte *symalg = NULL((void*)0), *hashalg = NULL((void*)0), *compalg = NULL((void*)0); | ||
1478 | size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0; | ||
1479 | size_t key_expire = 0; | ||
1480 | |||
1481 | if (!key) | ||
1482 | { | ||
1483 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1483); } while(0);; | ||
1484 | return CDK_Inv_Value; | ||
1485 | } | ||
1486 | |||
1487 | for (node = key; node; node = node->next) | ||
1488 | { | ||
1489 | if (!is_selfsig (node, keyid)) | ||
1490 | continue; | ||
1491 | unode = cdk_kbnode_find_prev (key, node, CDK_PKT_USER_ID); | ||
1492 | if (!unode) | ||
1493 | { | ||
1494 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1494); } while(0);; | ||
1495 | return CDK_Error_No_Key; | ||
1496 | } | ||
1497 | uid = unode->pkt->pkt.user_id; | ||
1498 | sig = node->pkt->pkt.signature; | ||
1499 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID); | ||
1500 | if (s) | ||
1501 | uid->is_primary = 1; | ||
1502 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_FEATURES); | ||
1503 | if (s && s->size == 1 && s->d[0] & 0x01) | ||
1504 | uid->mdc_feature = 1; | ||
1505 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE); | ||
1506 | if (s && s->size == 4) | ||
1507 | key_expire = _cdk_buftou32 (s->d); | ||
1508 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM); | ||
1509 | if (s) | ||
1510 | { | ||
1511 | symalg = s->d; | ||
1512 | nsymalg = s->size; | ||
1513 | n += s->size + 1; | ||
1514 | } | ||
1515 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_HASH); | ||
1516 | if (s) | ||
1517 | { | ||
1518 | hashalg = s->d; | ||
1519 | nhashalg = s->size; | ||
1520 | n += s->size + 1; | ||
1521 | } | ||
1522 | s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP); | ||
1523 | if (s) | ||
1524 | { | ||
1525 | compalg = s->d; | ||
1526 | ncompalg = s->size; | ||
1527 | n += s->size + 1; | ||
1528 | } | ||
1529 | if (uid->prefs != NULL((void*)0)) | ||
1530 | cdk_freegnutls_free (uid->prefs); | ||
1531 | if (!n || !hashalg || !compalg || !symalg) | ||
1532 | uid->prefs = NULL((void*)0); | ||
1533 | else | ||
1534 | { | ||
1535 | uid->prefs = cdk_callocgnutls_calloc (1, sizeof (*uid->prefs) * (n + 1)); | ||
1536 | if (!uid->prefs) | ||
1537 | { | ||
1538 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1538); } while(0);; | ||
1539 | return CDK_Out_Of_Core; | ||
1540 | } | ||
1541 | n = 0; | ||
1542 | for (; nsymalg; nsymalg--, n++) | ||
1543 | { | ||
1544 | uid->prefs[n].type = CDK_PREFTYPE_SYM; | ||
1545 | uid->prefs[n].value = *symalg++; | ||
1546 | } | ||
1547 | for (; nhashalg; nhashalg--, n++) | ||
1548 | { | ||
1549 | uid->prefs[n].type = CDK_PREFTYPE_HASH; | ||
1550 | uid->prefs[n].value = *hashalg++; | ||
1551 | } | ||
1552 | for (; ncompalg; ncompalg--, n++) | ||
1553 | { | ||
1554 | uid->prefs[n].type = CDK_PREFTYPE_ZIP; | ||
1555 | uid->prefs[n].value = *compalg++; | ||
1556 | } | ||
1557 | |||
1558 | uid->prefs[n].type = CDK_PREFTYPE_NONE; /* end of list marker */ | ||
1559 | uid->prefs[n].value = 0; | ||
1560 | uid->prefs_size = n; | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | /* Now we add the extracted information to the primary key. */ | ||
1565 | kbnode = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY); | ||
1566 | if (kbnode) | ||
1567 | { | ||
1568 | cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key; | ||
1569 | if (uid && uid->prefs && n) | ||
1570 | { | ||
1571 | if (pk->prefs != NULL((void*)0)) | ||
1572 | cdk_freegnutls_free (pk->prefs); | ||
1573 | pk->prefs = _cdk_copy_prefs (uid->prefs); | ||
1574 | pk->prefs_size = n; | ||
1575 | } | ||
1576 | if (key_expire) | ||
1577 | { | ||
1578 | pk->expiredate = pk->timestamp + key_expire; | ||
1579 | pk->has_expired = pk->expiredate > (u32) gnutls_time (NULL((void*)0)) ? 0 : 1; | ||
1580 | } | ||
1581 | |||
1582 | pk->is_invalid = 0; | ||
1583 | } | ||
1584 | |||
1585 | return 0; | ||
1586 | } | ||
1587 | |||
1588 | |||
1589 | static cdk_error_t | ||
1590 | keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check) | ||
1591 | { | ||
1592 | cdk_kbnode_t node, kb; | ||
1593 | cdk_pkt_signature_t sig; | ||
1594 | cdk_pkt_pubkey_t pk; | ||
1595 | cdk_subpkt_t s = NULL((void*)0); | ||
1596 | u32 expiredate = 0, curtime = (u32) gnutls_time (NULL((void*)0)); | ||
1597 | u32 keyid[2]; | ||
1598 | |||
1599 | if (!knode) | ||
1600 | { | ||
1601 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1601); } while(0);; | ||
1602 | return CDK_Inv_Value; | ||
1603 | } | ||
1604 | if (check && !hd) | ||
1605 | { | ||
1606 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1606); } while(0);; | ||
1607 | return CDK_Inv_Mode; | ||
1608 | } | ||
1609 | |||
1610 | kb = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY); | ||
1611 | if (kb) | ||
1612 | return 0; | ||
1613 | |||
1614 | /* Reset */ | ||
1615 | for (node = knode; node; node = node->next) | ||
1616 | { | ||
1617 | if (node->pkt->pkttype == CDK_PKT_USER_ID) | ||
1618 | node->pkt->pkt.user_id->is_revoked = 0; | ||
1619 | else if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1620 | node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
1621 | node->pkt->pkt.public_key->is_revoked = 0; | ||
1622 | } | ||
1623 | |||
1624 | kb = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); | ||
1625 | if (!kb) | ||
1626 | { | ||
1627 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1627); } while(0);; | ||
1628 | return CDK_Wrong_Format; | ||
1629 | } | ||
1630 | cdk_pk_get_keyid (kb->pkt->pkt.public_key, keyid); | ||
1631 | |||
1632 | for (node = knode; node; node = node->next) | ||
1633 | { | ||
1634 | if (node->pkt->pkttype == CDK_PKT_SIGNATURE) | ||
1635 | { | ||
1636 | sig = node->pkt->pkt.signature; | ||
1637 | /* Revocation certificates for primary keys */ | ||
1638 | if (sig->sig_class == 0x20) | ||
1639 | { | ||
1640 | kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY); | ||
1641 | if (kb) | ||
1642 | { | ||
1643 | kb->pkt->pkt.public_key->is_revoked = 1; | ||
1644 | if (check) | ||
1645 | _cdk_pk_check_sig (hd, kb, node, NULL((void*)0), NULL((void*)0)); | ||
1646 | } | ||
1647 | else | ||
1648 | { | ||
1649 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1649); } while(0);; | ||
1650 | return CDK_Error_No_Key; | ||
1651 | } | ||
1652 | } | ||
1653 | /* Revocation certificates for subkeys */ | ||
1654 | else if (sig->sig_class == 0x28) | ||
1655 | { | ||
1656 | kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY); | ||
1657 | if (kb) | ||
1658 | { | ||
1659 | kb->pkt->pkt.public_key->is_revoked = 1; | ||
1660 | if (check) | ||
1661 | _cdk_pk_check_sig (hd, kb, node, NULL((void*)0), NULL((void*)0)); | ||
1662 | } | ||
1663 | else | ||
1664 | { | ||
1665 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1665); } while(0);; | ||
1666 | return CDK_Error_No_Key; | ||
1667 | } | ||
1668 | } | ||
1669 | /* Revocation certifcates for user ID's */ | ||
1670 | else if (sig->sig_class == 0x30) | ||
1671 | { | ||
1672 | if (sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1]) | ||
1673 | continue; /* revokes an earlier signature, no userID. */ | ||
1674 | kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID); | ||
1675 | if (kb) | ||
1676 | { | ||
1677 | kb->pkt->pkt.user_id->is_revoked = 1; | ||
1678 | if (check) | ||
1679 | _cdk_pk_check_sig (hd, kb, node, NULL((void*)0), NULL((void*)0)); | ||
1680 | } | ||
1681 | else | ||
1682 | { | ||
1683 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1683); } while(0);; | ||
1684 | return CDK_Error_No_Key; | ||
1685 | } | ||
1686 | } | ||
1687 | /* Direct certificates for primary keys */ | ||
1688 | else if (sig->sig_class == 0x1F) | ||
1689 | { | ||
1690 | kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY); | ||
1691 | if (kb) | ||
1692 | { | ||
1693 | pk = kb->pkt->pkt.public_key; | ||
1694 | pk->is_invalid = 0; | ||
1695 | s = cdk_subpkt_find (node->pkt->pkt.signature->hashed, | ||
1696 | CDK_SIGSUBPKT_KEY_EXPIRE); | ||
1697 | if (s) | ||
1698 | { | ||
1699 | expiredate = _cdk_buftou32 (s->d); | ||
1700 | pk->expiredate = pk->timestamp + expiredate; | ||
1701 | pk->has_expired = pk->expiredate > curtime ? 0 : 1; | ||
1702 | } | ||
1703 | if (check) | ||
1704 | _cdk_pk_check_sig (hd, kb, node, NULL((void*)0), NULL((void*)0)); | ||
1705 | } | ||
1706 | else | ||
1707 | { | ||
1708 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1708); } while(0);; | ||
1709 | return CDK_Error_No_Key; | ||
1710 | } | ||
1711 | } | ||
1712 | /* Direct certificates for subkeys */ | ||
1713 | else if (sig->sig_class == 0x18) | ||
1714 | { | ||
1715 | kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY); | ||
1716 | if (kb) | ||
1717 | { | ||
1718 | pk = kb->pkt->pkt.public_key; | ||
1719 | pk->is_invalid = 0; | ||
1720 | s = cdk_subpkt_find (node->pkt->pkt.signature->hashed, | ||
1721 | CDK_SIGSUBPKT_KEY_EXPIRE); | ||
1722 | if (s) | ||
1723 | { | ||
1724 | expiredate = _cdk_buftou32 (s->d); | ||
1725 | pk->expiredate = pk->timestamp + expiredate; | ||
1726 | pk->has_expired = pk->expiredate > curtime ? 0 : 1; | ||
1727 | } | ||
1728 | if (check) | ||
1729 | _cdk_pk_check_sig (hd, kb, node, NULL((void*)0), NULL((void*)0)); | ||
1730 | } | ||
1731 | else | ||
1732 | { | ||
1733 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1733); } while(0);; | ||
1734 | return CDK_Error_No_Key; | ||
1735 | } | ||
1736 | } | ||
1737 | } | ||
1738 | } | ||
1739 | node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); | ||
1740 | if (node && node->pkt->pkt.public_key->version == 3) | ||
1741 | { | ||
1742 | /* v3 public keys have no additonal signatures for the key directly. | ||
1743 | we say the key is valid when we have at least a self signature. */ | ||
1744 | pk = node->pkt->pkt.public_key; | ||
1745 | for (node = knode; node; node = node->next) | ||
1746 | { | ||
1747 | if (is_selfsig (node, keyid)) | ||
1748 | { | ||
1749 | pk->is_invalid = 0; | ||
1750 | break; | ||
1751 | } | ||
1752 | } | ||
1753 | } | ||
1754 | if (node && (node->pkt->pkt.public_key->is_revoked || | ||
1755 | node->pkt->pkt.public_key->has_expired)) | ||
1756 | { | ||
1757 | /* If the primary key has been revoked, mark all subkeys as invalid | ||
1758 | because without a primary key they are not useable */ | ||
1759 | for (node = knode; node; node = node->next) | ||
1760 | { | ||
1761 | if (node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
1762 | node->pkt->pkt.public_key->is_invalid = 1; | ||
1763 | } | ||
1764 | } | ||
1765 | |||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | static void | ||
1770 | add_key_usage (cdk_kbnode_t knode, u32 keyid[2], unsigned int usage) | ||
1771 | { | ||
1772 | cdk_kbnode_t p, ctx; | ||
1773 | cdk_packet_t pkt; | ||
1774 | |||
1775 | ctx = NULL((void*)0); | ||
1776 | while ((p = cdk_kbnode_walk (knode, &ctx, 0))) | ||
1777 | { | ||
1778 | pkt = cdk_kbnode_get_packet (p); | ||
1779 | if ((pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY | ||
1780 | || pkt->pkttype == CDK_PKT_PUBLIC_KEY) | ||
1781 | && pkt->pkt.public_key->keyid[0] == keyid[0] | ||
1782 | && pkt->pkt.public_key->keyid[1] == keyid[1]) | ||
1783 | { | ||
1784 | pkt->pkt.public_key->pubkey_usage = usage; | ||
1785 | return; | ||
1786 | } | ||
1787 | } | ||
1788 | return; | ||
1789 | } | ||
1790 | |||
1791 | cdk_error_t | ||
1792 | cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * r_knode) | ||
1793 | { | ||
1794 | cdk_packet_t pkt; | ||
1795 | cdk_kbnode_t knode, node; | ||
1796 | cdk_desig_revoker_t revkeys; | ||
1797 | cdk_error_t rc; | ||
1798 | u32 keyid[2], main_keyid[2]; | ||
1799 | off_t old_off; | ||
1800 | int key_seen, got_key; | ||
1801 | |||
1802 | if (!inp || !r_knode) | ||
1803 | { | ||
1804 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1804); } while(0);; | ||
1805 | return CDK_Inv_Value; | ||
1806 | } | ||
1807 | |||
1808 | /* Reset all values. */ | ||
1809 | keyid[0] = keyid[1] = 0; | ||
1810 | main_keyid[0] = main_keyid[1] = 0; | ||
1811 | revkeys = NULL((void*)0); | ||
1812 | knode = NULL((void*)0); | ||
1813 | key_seen = got_key = 0; | ||
1814 | |||
1815 | *r_knode = NULL((void*)0); | ||
1816 | rc = CDK_EOF; | ||
1817 | while (!cdk_stream_eof (inp)) | ||
1818 | { | ||
1819 | cdk_pkt_new (&pkt); | ||
1820 | old_off = cdk_stream_tell (inp); | ||
1821 | rc = cdk_pkt_read (inp, pkt); | ||
1822 | if (rc) | ||
1823 | { | ||
1824 | cdk_pkt_release (pkt); | ||
1825 | if (rc == CDK_EOF) | ||
1826 | break; | ||
1827 | else | ||
1828 | { /* Release all packets we reached so far. */ | ||
1829 | _cdk_log_debug ("keydb_get_keyblock: error %d\n", rc)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "keydb_get_keyblock: error %d\n", rc); } while(0); | ||
1830 | cdk_kbnode_release (knode); | ||
1831 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1831); } while(0);; | ||
1832 | return rc; | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1837 | pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || | ||
1838 | pkt->pkttype == CDK_PKT_SECRET_KEY || | ||
1839 | pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
1840 | { | ||
1841 | if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1842 | pkt->pkttype == CDK_PKT_SECRET_KEY)) | ||
1843 | { | ||
1844 | /* The next key starts here so set the file pointer | ||
1845 | and leave the loop. */ | ||
1846 | cdk_stream_seek (inp, old_off); | ||
1847 | cdk_pkt_release (pkt); | ||
1848 | break; | ||
1849 | } | ||
1850 | if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || | ||
1851 | pkt->pkttype == CDK_PKT_SECRET_KEY) | ||
1852 | { | ||
1853 | _cdk_pkt_get_keyid (pkt, main_keyid); | ||
1854 | key_seen = 1; | ||
1855 | } | ||
1856 | else if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || | ||
1857 | pkt->pkttype == CDK_PKT_SECRET_SUBKEY) | ||
1858 | { | ||
1859 | if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) | ||
1860 | { | ||
1861 | pkt->pkt.public_key->main_keyid[0] = main_keyid[0]; | ||
1862 | pkt->pkt.public_key->main_keyid[1] = main_keyid[1]; | ||
1863 | } | ||
1864 | else | ||
1865 | { | ||
1866 | pkt->pkt.secret_key->main_keyid[0] = main_keyid[0]; | ||
1867 | pkt->pkt.secret_key->main_keyid[1] = main_keyid[1]; | ||
1868 | } | ||
1869 | } | ||
1870 | /* We save this for the signature */ | ||
1871 | _cdk_pkt_get_keyid (pkt, keyid); | ||
1872 | got_key = 1; | ||
1873 | } | ||
1874 | else if (pkt->pkttype == CDK_PKT_USER_ID) | ||
1875 | ; | ||
1876 | else if (pkt->pkttype == CDK_PKT_SIGNATURE) | ||
1877 | { | ||
1878 | cdk_subpkt_t s; | ||
1879 | |||
1880 | pkt->pkt.signature->key[0] = keyid[0]; | ||
1881 | pkt->pkt.signature->key[1] = keyid[1]; | ||
1882 | if (pkt->pkt.signature->sig_class == 0x1F && | ||
1883 | pkt->pkt.signature->revkeys) | ||
1884 | revkeys = pkt->pkt.signature->revkeys; | ||
1885 | |||
1886 | s = | ||
1887 | cdk_subpkt_find (pkt->pkt.signature->hashed, | ||
1888 | CDK_SIGSUBPKT_KEY_FLAGS); | ||
1889 | if (s) | ||
1890 | { | ||
1891 | unsigned int key_usage = key_usage_to_cdk_usage (s->d[0]); | ||
1892 | add_key_usage (knode, pkt->pkt.signature->key, key_usage); | ||
1893 | } | ||
1894 | } | ||
1895 | node = cdk_kbnode_new (pkt); | ||
1896 | if (!knode) | ||
1897 | knode = node; | ||
1898 | else | ||
1899 | _cdk_kbnode_add (knode, node); | ||
1900 | } | ||
1901 | |||
1902 | if (got_key) | ||
1903 | { | ||
1904 | keydb_merge_selfsig (knode, main_keyid); | ||
1905 | rc = keydb_parse_allsigs (knode, NULL((void*)0), 0); | ||
1906 | if (revkeys) | ||
1907 | { | ||
1908 | node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); | ||
1909 | if (node) | ||
1910 | node->pkt->pkt.public_key->revkeys = revkeys; | ||
1911 | } | ||
1912 | } | ||
1913 | else | ||
1914 | cdk_kbnode_release (knode); | ||
1915 | *r_knode = got_key ? knode : NULL((void*)0); | ||
1916 | |||
1917 | /* It is possible that we are in an EOF condition after we | ||
1918 | successfully read a keyblock. For example if the requested | ||
1919 | key is the last in the file. */ | ||
1920 | if (rc == CDK_EOF && got_key) | ||
1921 | rc = 0; | ||
1922 | return rc; | ||
1923 | } | ||
1924 | |||
1925 | |||
1926 | /* Return the type of the given data. In case it cannot be classified, | ||
1927 | a substring search will be performed. */ | ||
1928 | static int | ||
1929 | classify_data (const byte * buf, size_t len) | ||
1930 | { | ||
1931 | int type; | ||
1932 | unsigned int i; | ||
1933 | |||
1934 | if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) | ||
1935 | { /* Skip hex prefix. */ | ||
1936 | buf += 2; | ||
1937 | len -= 2; | ||
1938 | } | ||
1939 | |||
1940 | /* The length of the data does not match either a keyid or a fingerprint. */ | ||
1941 | if (len != 8 && len != 16 && len != 40) | ||
1942 | return CDK_DBSEARCH_SUBSTR; | ||
1943 | |||
1944 | for (i = 0; i < len; i++) | ||
1945 | { | ||
1946 | if (!isxdigit (buf[i])((*__ctype_b_loc ())[(int) ((buf[i]))] & (unsigned short int ) _ISxdigit)) | ||
1947 | return CDK_DBSEARCH_SUBSTR; | ||
1948 | } | ||
1949 | if (i != len) | ||
1950 | return CDK_DBSEARCH_SUBSTR; | ||
1951 | switch (len) | ||
1952 | { | ||
1953 | case 8: | ||
1954 | type = CDK_DBSEARCH_SHORT_KEYID; | ||
1955 | break; | ||
1956 | case 16: | ||
1957 | type = CDK_DBSEARCH_KEYID; | ||
1958 | break; | ||
1959 | case 40: | ||
1960 | type = CDK_DBSEARCH_FPR; | ||
1961 | break; | ||
1962 | default: | ||
1963 | type = CDK_DBSEARCH_SUBSTR; | ||
1964 | break; | ||
1965 | } | ||
1966 | |||
1967 | return type; | ||
1968 | } | ||
1969 | |||
1970 | |||
1971 | /** | ||
1972 | * cdk_keydb_export: | ||
1973 | * @hd: the keydb handle | ||
1974 | * @out: the output stream | ||
1975 | * @remusr: the list of key pattern to export | ||
1976 | * | ||
1977 | * Export a list of keys to the given output stream. | ||
1978 | * Use string list with names for pattering searching. | ||
1979 | * This procedure strips local signatures. | ||
1980 | **/ | ||
1981 | cdk_error_t | ||
1982 | cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr) | ||
1983 | { | ||
1984 | cdk_kbnode_t knode, node; | ||
1985 | cdk_strlist_t r; | ||
1986 | cdk_error_t rc; | ||
1987 | int old_ctb; | ||
1988 | cdk_keydb_search_t st; | ||
1989 | |||
1990 | for (r = remusr; r; r = r->next) | ||
1991 | { | ||
1992 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, r->d); | ||
1993 | if (rc) | ||
1994 | { | ||
1995 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",1995); } while(0);; | ||
1996 | return rc; | ||
1997 | } | ||
1998 | rc = cdk_keydb_search (st, hd, &knode); | ||
1999 | cdk_keydb_search_release (st); | ||
2000 | |||
2001 | if (rc) | ||
2002 | { | ||
2003 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2003); } while(0);; | ||
2004 | return rc; | ||
2005 | } | ||
2006 | |||
2007 | node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); | ||
2008 | if (!node) | ||
2009 | { | ||
2010 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2010); } while(0);; | ||
2011 | return CDK_Error_No_Key; | ||
2012 | } | ||
2013 | |||
2014 | /* If the key is a version 3 key, use the old packet | ||
2015 | format for the output. */ | ||
2016 | if (node->pkt->pkt.public_key->version == 3) | ||
2017 | old_ctb = 1; | ||
2018 | else | ||
2019 | old_ctb = 0; | ||
2020 | |||
2021 | for (node = knode; node; node = node->next) | ||
2022 | { | ||
2023 | /* No specified format; skip them */ | ||
2024 | if (node->pkt->pkttype == CDK_PKT_RING_TRUST) | ||
2025 | continue; | ||
2026 | /* We never export local signed signatures */ | ||
2027 | if (node->pkt->pkttype == CDK_PKT_SIGNATURE && | ||
2028 | !node->pkt->pkt.signature->flags.exportable) | ||
2029 | continue; | ||
2030 | /* Filter out invalid signatures */ | ||
2031 | if (node->pkt->pkttype == CDK_PKT_SIGNATURE && | ||
2032 | (!KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo)((_cdk_pk_algo_usage ((node->pkt->pkt.signature->pubkey_algo ))) & (CDK_KEY_USG_DATA_SIGN | CDK_KEY_USG_CERT_SIGN)))) | ||
2033 | continue; | ||
2034 | |||
2035 | /* Adjust the ctb flag if needed. */ | ||
2036 | node->pkt->old_ctb = old_ctb; | ||
2037 | rc = cdk_pkt_write (out, node->pkt); | ||
2038 | if (rc) | ||
2039 | { | ||
2040 | cdk_kbnode_release (knode); | ||
2041 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2041); } while(0);; | ||
2042 | return rc; | ||
2043 | } | ||
2044 | } | ||
2045 | cdk_kbnode_release (knode); | ||
2046 | knode = NULL((void*)0); | ||
2047 | } | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | |||
2052 | static cdk_packet_t | ||
2053 | find_key_packet (cdk_kbnode_t knode, int *r_is_sk) | ||
2054 | { | ||
2055 | cdk_packet_t pkt; | ||
2056 | |||
2057 | pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY); | ||
2058 | if (!pkt) | ||
2059 | { | ||
2060 | pkt = cdk_kbnode_find_packet (knode, CDK_PKT_SECRET_KEY); | ||
2061 | if (r_is_sk) | ||
2062 | *r_is_sk = pkt ? 1 : 0; | ||
2063 | } | ||
2064 | return pkt; | ||
2065 | } | ||
2066 | |||
2067 | |||
2068 | /* Return 1 if the is allowd in a key node. */ | ||
2069 | static int | ||
2070 | is_key_node (cdk_kbnode_t node) | ||
2071 | { | ||
2072 | switch (node->pkt->pkttype) | ||
2073 | { | ||
2074 | case CDK_PKT_SIGNATURE: | ||
2075 | case CDK_PKT_SECRET_KEY: | ||
2076 | case CDK_PKT_PUBLIC_KEY: | ||
2077 | case CDK_PKT_SECRET_SUBKEY: | ||
2078 | case CDK_PKT_PUBLIC_SUBKEY: | ||
2079 | case CDK_PKT_USER_ID: | ||
2080 | case CDK_PKT_ATTRIBUTE: | ||
2081 | return 1; | ||
2082 | |||
2083 | default: | ||
2084 | return 0; | ||
2085 | } | ||
2086 | |||
2087 | return 0; | ||
2088 | } | ||
2089 | |||
2090 | |||
2091 | cdk_error_t | ||
2092 | cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode) | ||
2093 | { | ||
2094 | cdk_kbnode_t node, chk; | ||
2095 | cdk_packet_t pkt; | ||
2096 | cdk_stream_t out; | ||
2097 | cdk_error_t rc; | ||
2098 | u32 keyid[2]; | ||
2099 | |||
2100 | if (!hd || !knode) | ||
2101 | { | ||
2102 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2102); } while(0);; | ||
2103 | return CDK_Inv_Value; | ||
2104 | } | ||
2105 | |||
2106 | pkt = find_key_packet (knode, NULL((void*)0)); | ||
2107 | if (!pkt) | ||
2108 | { | ||
2109 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2109); } while(0);; | ||
2110 | return CDK_Inv_Packet; | ||
2111 | } | ||
2112 | |||
2113 | _cdk_pkt_get_keyid (pkt, keyid); | ||
2114 | chk = NULL((void*)0); | ||
2115 | cdk_keydb_get_bykeyid (hd, keyid, &chk); | ||
2116 | if (chk) | ||
2117 | { /* FIXME: search for new signatures */ | ||
2118 | cdk_kbnode_release (chk); | ||
2119 | return 0; | ||
2120 | } | ||
2121 | |||
2122 | /* We append data to the stream so we need to close | ||
2123 | the stream here to re-open it later. */ | ||
2124 | if (hd->fp) | ||
2125 | { | ||
2126 | cdk_stream_close (hd->fp); | ||
2127 | hd->fp = NULL((void*)0); | ||
2128 | } | ||
2129 | |||
2130 | rc = _cdk_stream_append (hd->name, &out); | ||
2131 | if (rc) | ||
2132 | { | ||
2133 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2133); } while(0);; | ||
2134 | return rc; | ||
2135 | } | ||
2136 | |||
2137 | for (node = knode; node; node = node->next) | ||
2138 | { | ||
2139 | if (node->pkt->pkttype == CDK_PKT_RING_TRUST) | ||
2140 | continue; /* No uniformed syntax for this packet */ | ||
2141 | if (node->pkt->pkttype == CDK_PKT_SIGNATURE && | ||
2142 | !node->pkt->pkt.signature->flags.exportable) | ||
2143 | { | ||
2144 | _cdk_log_debug ("key db import: skip local signature\n")do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "key db import: skip local signature\n"); } while(0); | ||
2145 | continue; | ||
2146 | } | ||
2147 | |||
2148 | if (!is_key_node (node)) | ||
2149 | { | ||
2150 | _cdk_log_debug ("key db import: skip invalid node of type %d\n",do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "key db import: skip invalid node of type %d\n", node-> pkt->pkttype); } while(0) | ||
2151 | node->pkt->pkttype)do { if (__builtin_expect((_gnutls_log_level >= 9), 0)) _gnutls_log ( 9, "key db import: skip invalid node of type %d\n", node-> pkt->pkttype); } while(0); | ||
2152 | continue; | ||
2153 | } | ||
2154 | |||
2155 | rc = cdk_pkt_write (out, node->pkt); | ||
2156 | if (rc) | ||
2157 | { | ||
2158 | cdk_stream_close (out); | ||
2159 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2159); } while(0);; | ||
2160 | return rc; | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | cdk_stream_close (out); | ||
2165 | hd->stats.new_keys++; | ||
2166 | |||
2167 | return 0; | ||
2168 | } | ||
2169 | |||
2170 | |||
2171 | cdk_error_t | ||
2172 | _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id) | ||
2173 | { | ||
2174 | cdk_kbnode_t knode = NULL((void*)0), unode = NULL((void*)0); | ||
2175 | cdk_error_t rc; | ||
2176 | int check; | ||
2177 | cdk_keydb_search_t st; | ||
2178 | |||
2179 | if (!hd) | ||
2180 | { | ||
2181 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2181); } while(0);; | ||
2182 | return CDK_Inv_Value; | ||
2183 | } | ||
2184 | |||
2185 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid); | ||
2186 | if (rc) | ||
2187 | { | ||
2188 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2188); } while(0);; | ||
2189 | return rc; | ||
2190 | } | ||
2191 | rc = cdk_keydb_search (st, hd, &knode); | ||
2192 | cdk_keydb_search_release (st); | ||
2193 | |||
2194 | if (rc) | ||
2195 | { | ||
2196 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2196); } while(0);; | ||
2197 | return rc; | ||
2198 | } | ||
2199 | |||
2200 | rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id); | ||
2201 | if (!rc) | ||
2202 | { | ||
2203 | rc = cdk_keydb_search (st, hd, &unode); | ||
2204 | cdk_keydb_search_release (st); | ||
2205 | } | ||
2206 | if (rc) | ||
2207 | { | ||
2208 | cdk_kbnode_release (knode); | ||
2209 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2209); } while(0);; | ||
2210 | return rc; | ||
2211 | } | ||
2212 | |||
2213 | check = 0; | ||
2214 | cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid); | ||
2215 | if (unode && find_by_keyid (unode, st)) | ||
2216 | check++; | ||
2217 | cdk_keydb_search_release (st); | ||
2218 | cdk_kbnode_release (unode); | ||
2219 | |||
2220 | cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id); | ||
2221 | if (knode && find_by_pattern (knode, st)) | ||
2222 | check++; | ||
2223 | cdk_keydb_search_release (st); | ||
2224 | cdk_kbnode_release (knode); | ||
2225 | |||
2226 | return check == 2 ? 0 : CDK_Inv_Value; | ||
2227 | } | ||
2228 | |||
2229 | |||
2230 | /** | ||
2231 | * cdk_keydb_check_sk: | ||
2232 | * @hd: the key db handle | ||
2233 | * @keyid: the 64-bit keyid | ||
2234 | * | ||
2235 | * Check if a secret key with the given key ID is available | ||
2236 | * in the key database. | ||
2237 | **/ | ||
2238 | cdk_error_t | ||
2239 | cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 * keyid) | ||
2240 | { | ||
2241 | cdk_stream_t db; | ||
2242 | cdk_packet_t pkt; | ||
2243 | cdk_error_t rc; | ||
2244 | u32 kid[2]; | ||
2245 | |||
2246 | if (!hd || !keyid) | ||
2247 | { | ||
2248 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2248); } while(0);; | ||
2249 | return CDK_Inv_Value; | ||
2250 | } | ||
2251 | if (!hd->secret) | ||
2252 | { | ||
2253 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2253); } while(0);; | ||
2254 | return CDK_Inv_Mode; | ||
2255 | } | ||
2256 | |||
2257 | rc = _cdk_keydb_open (hd, &db); | ||
2258 | if (rc) | ||
2259 | { | ||
2260 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2260); } while(0);; | ||
2261 | return rc; | ||
2262 | } | ||
2263 | cdk_pkt_new (&pkt); | ||
2264 | while (!cdk_pkt_read (db, pkt)) | ||
2265 | { | ||
2266 | if (pkt->pkttype != CDK_PKT_SECRET_KEY && | ||
2267 | pkt->pkttype != CDK_PKT_SECRET_SUBKEY) | ||
2268 | { | ||
2269 | cdk_pkt_free (pkt); | ||
2270 | continue; | ||
2271 | } | ||
2272 | cdk_sk_get_keyid (pkt->pkt.secret_key, kid); | ||
2273 | if (KEYID_CMP (kid, keyid)((kid[0]) == (keyid[0]) && (kid[1]) == (keyid[1]))) | ||
2274 | { | ||
2275 | cdk_pkt_release (pkt); | ||
2276 | return 0; | ||
2277 | } | ||
2278 | cdk_pkt_free (pkt); | ||
2279 | } | ||
2280 | cdk_pkt_release (pkt); | ||
2281 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2281); } while(0);; | ||
2282 | return CDK_Error_No_Key; | ||
2283 | } | ||
2284 | |||
2285 | |||
2286 | /** | ||
2287 | * cdk_listkey_start: | ||
2288 | * @r_ctx: pointer to store the new context | ||
2289 | * @db: the key database handle | ||
2290 | * @patt: string pattern | ||
2291 | * @fpatt: recipients from a stringlist to show | ||
2292 | * | ||
2293 | * Prepare a key listing with the given parameters. Two modes are supported. | ||
2294 | * The first mode uses string pattern to determine if the key should be | ||
2295 | * returned or not. The other mode uses a string list to request the key | ||
2296 | * which should be listed. | ||
2297 | **/ | ||
2298 | cdk_error_t | ||
2299 | cdk_listkey_start (cdk_listkey_t * r_ctx, cdk_keydb_hd_t db, | ||
2300 | const char *patt, cdk_strlist_t fpatt) | ||
2301 | { | ||
2302 | cdk_listkey_t ctx; | ||
2303 | cdk_stream_t inp; | ||
2304 | cdk_error_t rc; | ||
2305 | |||
2306 | if (!r_ctx || !db) | ||
2307 | { | ||
2308 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2308); } while(0);; | ||
2309 | return CDK_Inv_Value; | ||
2310 | } | ||
2311 | if ((patt && fpatt) || (!patt && !fpatt)) | ||
2312 | { | ||
2313 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2313); } while(0);; | ||
2314 | return CDK_Inv_Mode; | ||
2315 | } | ||
2316 | rc = _cdk_keydb_open (db, &inp); | ||
2317 | if (rc) | ||
2318 | { | ||
2319 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2319); } while(0);; | ||
2320 | return rc; | ||
2321 | } | ||
2322 | ctx = cdk_callocgnutls_calloc (1, sizeof *ctx); | ||
2323 | if (!ctx) | ||
2324 | { | ||
2325 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2325); } while(0);; | ||
2326 | return CDK_Out_Of_Core; | ||
2327 | } | ||
2328 | ctx->db = db; | ||
2329 | ctx->inp = inp; | ||
2330 | if (patt) | ||
2331 | { | ||
2332 | ctx->u.patt = cdk_strdupgnutls_strdup (patt); | ||
2333 | if (!ctx->u.patt) | ||
2334 | { | ||
2335 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2335); } while(0);; | ||
2336 | return CDK_Out_Of_Core; | ||
2337 | } | ||
2338 | } | ||
2339 | else if (fpatt) | ||
2340 | { | ||
2341 | cdk_strlist_t l; | ||
2342 | for (l = fpatt; l; l = l->next) | ||
2343 | cdk_strlist_add (&ctx->u.fpatt, l->d); | ||
2344 | } | ||
2345 | ctx->type = patt ? 1 : 0; | ||
2346 | ctx->init = 1; | ||
2347 | *r_ctx = ctx; | ||
2348 | return 0; | ||
2349 | } | ||
2350 | |||
2351 | |||
2352 | /** | ||
2353 | * cdk_listkey_close: | ||
2354 | * @ctx: the list key context | ||
2355 | * | ||
2356 | * Free the list key context. | ||
2357 | **/ | ||
2358 | void | ||
2359 | cdk_listkey_close (cdk_listkey_t ctx) | ||
2360 | { | ||
2361 | if (!ctx) | ||
2362 | return; | ||
2363 | |||
2364 | if (ctx->type) | ||
2365 | cdk_freegnutls_free (ctx->u.patt); | ||
2366 | else | ||
2367 | cdk_strlist_free (ctx->u.fpatt); | ||
2368 | cdk_freegnutls_free (ctx); | ||
2369 | } | ||
2370 | |||
2371 | |||
2372 | /** | ||
2373 | * cdk_listkey_next: | ||
2374 | * @ctx: list key context | ||
2375 | * @r_key: the pointer to the new key node object | ||
2376 | * | ||
2377 | * Retrieve the next key from the pattern of the key list context. | ||
2378 | **/ | ||
2379 | cdk_error_t | ||
2380 | cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t * ret_key) | ||
2381 | { | ||
2382 | if (!ctx || !ret_key) | ||
2383 | { | ||
2384 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2384); } while(0);; | ||
2385 | return CDK_Inv_Value; | ||
2386 | } | ||
2387 | if (!ctx->init) | ||
2388 | { | ||
2389 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2389); } while(0);; | ||
2390 | return CDK_Inv_Mode; | ||
2391 | } | ||
2392 | |||
2393 | if (ctx->type && ctx->u.patt[0] == '*') | ||
2394 | return cdk_keydb_get_keyblock (ctx->inp, ret_key); | ||
2395 | else if (ctx->type) | ||
2396 | { | ||
2397 | cdk_kbnode_t node; | ||
2398 | struct cdk_keydb_search_s ks; | ||
2399 | cdk_error_t rc; | ||
2400 | |||
2401 | for (;;) | ||
2402 | { | ||
2403 | rc = cdk_keydb_get_keyblock (ctx->inp, &node); | ||
2404 | if (rc) | ||
2405 | { | ||
2406 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2406); } while(0);; | ||
2407 | return rc; | ||
2408 | } | ||
2409 | memset (&ks, 0, sizeof (ks)); | ||
2410 | ks.type = CDK_DBSEARCH_SUBSTR; | ||
2411 | ks.u.pattern = ctx->u.patt; | ||
2412 | if (find_by_pattern (node, &ks)) | ||
2413 | { | ||
2414 | *ret_key = node; | ||
2415 | return 0; | ||
2416 | } | ||
2417 | cdk_kbnode_release (node); | ||
2418 | node = NULL((void*)0); | ||
2419 | } | ||
2420 | } | ||
2421 | else | ||
2422 | { | ||
2423 | if (!ctx->t) | ||
2424 | ctx->t = ctx->u.fpatt; | ||
2425 | else if (ctx->t->next) | ||
2426 | ctx->t = ctx->t->next; | ||
2427 | else | ||
2428 | return CDK_EOF; | ||
2429 | return cdk_keydb_get_bypattern (ctx->db, ctx->t->d, ret_key); | ||
2430 | } | ||
2431 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "keydb.c",2431); } while(0);; | ||
2432 | return CDK_General_Error; | ||
2433 | } | ||
2434 | |||
2435 | |||
2436 | int | ||
2437 | _cdk_keydb_is_secret (cdk_keydb_hd_t db) | ||
2438 | { | ||
2439 | return db->secret; | ||
2440 | } |