Line | Count | Source |
1 | | /* keyring.c - keyring file handling |
2 | | * Copyright (C) 1998-2010 Free Software Foundation, Inc. |
3 | | * Copyright (C) 1997-2015 Werner Koch |
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 <stdio.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #include <errno.h> |
26 | | #include <unistd.h> |
27 | | #include <sys/types.h> |
28 | | #include <sys/stat.h> |
29 | | |
30 | | #include "gpg.h" |
31 | | #include "../common/util.h" |
32 | | #include "keyring.h" |
33 | | #include "packet.h" |
34 | | #include "keydb.h" |
35 | | #include "options.h" |
36 | | #include "main.h" /*for check_key_signature()*/ |
37 | | #include "../common/i18n.h" |
38 | | #include "../kbx/keybox.h" |
39 | | |
40 | | |
41 | | typedef struct keyring_resource *KR_RESOURCE; |
42 | | struct keyring_resource |
43 | | { |
44 | | struct keyring_resource *next; |
45 | | int read_only; |
46 | | dotlock_t lockhd; |
47 | | int is_locked; |
48 | | int did_full_scan; |
49 | | char fname[1]; |
50 | | }; |
51 | | typedef struct keyring_resource const * CONST_KR_RESOURCE; |
52 | | |
53 | | static KR_RESOURCE kr_resources; |
54 | | |
55 | | struct keyring_handle |
56 | | { |
57 | | CONST_KR_RESOURCE resource; |
58 | | struct { |
59 | | CONST_KR_RESOURCE kr; |
60 | | IOBUF iobuf; |
61 | | int eof; |
62 | | int error; |
63 | | } current; |
64 | | struct { |
65 | | CONST_KR_RESOURCE kr; |
66 | | off_t offset; |
67 | | size_t pk_no; |
68 | | size_t uid_no; |
69 | | unsigned int n_packets; /*used for delete and update*/ |
70 | | } found, saved_found; |
71 | | struct { |
72 | | char *name; |
73 | | char *pattern; |
74 | | } word_match; |
75 | | }; |
76 | | |
77 | | /* The number of extant handles. */ |
78 | | static int active_handles; |
79 | | |
80 | | static int do_copy (int mode, const char *fname, KBNODE root, |
81 | | off_t start_offset, unsigned int n_packets ); |
82 | | |
83 | | |
84 | | |
85 | | /* We keep a cache of entries that we have entered in the DB. This |
86 | | includes not only public keys, but also subkeys. |
87 | | |
88 | | Note: we'd like to keep the offset of the items that are present, |
89 | | however, this doesn't work, because another concurrent GnuPG |
90 | | process could modify the keyring. */ |
91 | | struct key_present { |
92 | | struct key_present *next; |
93 | | u32 kid[2]; |
94 | | }; |
95 | | |
96 | | /* For the hash table, we use separate chaining with linked lists. |
97 | | This means that we have an array of N linked lists (buckets), which |
98 | | is indexed by KEYID[1] mod N. Elements present in the keyring will |
99 | | be on the list; elements not present in the keyring will not be on |
100 | | the list. |
101 | | |
102 | | Note: since the hash table stores both present and not present |
103 | | information, it cannot be used until we complete a full scan of the |
104 | | keyring. This is indicated by key_present_hash_ready. */ |
105 | | typedef struct key_present **key_present_hash_t; |
106 | | static key_present_hash_t key_present_hash; |
107 | | static int key_present_hash_ready; |
108 | | |
109 | 0 | #define KEY_PRESENT_HASH_BUCKETS 2048 |
110 | | |
111 | | /* Allocate a new value for a key present hash table. */ |
112 | | static struct key_present * |
113 | | key_present_value_new (void) |
114 | 0 | { |
115 | 0 | struct key_present *k; |
116 | |
|
117 | 0 | k = xmalloc_clear (sizeof *k); |
118 | 0 | return k; |
119 | 0 | } |
120 | | |
121 | | /* Allocate a new key present hash table. */ |
122 | | static key_present_hash_t |
123 | | key_present_hash_new (void) |
124 | 0 | { |
125 | 0 | struct key_present **tbl; |
126 | |
|
127 | 0 | tbl = xmalloc_clear (KEY_PRESENT_HASH_BUCKETS * sizeof *tbl); |
128 | 0 | return tbl; |
129 | 0 | } |
130 | | |
131 | | /* Return whether the value described by KID if it is in the hash |
132 | | table. Otherwise, return NULL. */ |
133 | | static struct key_present * |
134 | | key_present_hash_lookup (key_present_hash_t tbl, u32 *kid) |
135 | 0 | { |
136 | 0 | struct key_present *k; |
137 | |
|
138 | 0 | for (k = tbl[(kid[1] % (KEY_PRESENT_HASH_BUCKETS - 1))]; k; k = k->next) |
139 | 0 | if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) |
140 | 0 | return k; |
141 | 0 | return NULL; |
142 | 0 | } |
143 | | |
144 | | /* Add the key to the hash table TBL if it is not already present. */ |
145 | | static void |
146 | | key_present_hash_update (key_present_hash_t tbl, u32 *kid) |
147 | 0 | { |
148 | 0 | struct key_present *k; |
149 | |
|
150 | 0 | for (k = tbl[(kid[1] % (KEY_PRESENT_HASH_BUCKETS - 1))]; k; k = k->next) |
151 | 0 | { |
152 | 0 | if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) |
153 | 0 | return; |
154 | 0 | } |
155 | | |
156 | 0 | k = key_present_value_new (); |
157 | 0 | k->kid[0] = kid[0]; |
158 | 0 | k->kid[1] = kid[1]; |
159 | 0 | k->next = tbl[(kid[1] % (KEY_PRESENT_HASH_BUCKETS - 1))]; |
160 | 0 | tbl[(kid[1] % (KEY_PRESENT_HASH_BUCKETS - 1))] = k; |
161 | 0 | } |
162 | | |
163 | | /* Add all the keys (public and subkeys) present in the keyblock to |
164 | | the hash TBL. */ |
165 | | static void |
166 | | key_present_hash_update_from_kb (key_present_hash_t tbl, KBNODE node) |
167 | 0 | { |
168 | 0 | for (; node; node = node->next) |
169 | 0 | { |
170 | 0 | if (node->pkt->pkttype == PKT_PUBLIC_KEY |
171 | 0 | || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) |
172 | 0 | { |
173 | 0 | u32 aki[2]; |
174 | 0 | keyid_from_pk (node->pkt->pkt.public_key, aki); |
175 | 0 | key_present_hash_update (tbl, aki); |
176 | 0 | } |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | | /* |
181 | | * Register a filename for plain keyring files. ptr is set to a |
182 | | * pointer to be used to create a handles etc, or the already-issued |
183 | | * pointer if it has already been registered. The function returns 1 |
184 | | * if a new keyring was registered. |
185 | | */ |
186 | | int |
187 | | keyring_register_filename (const char *fname, int read_only, void **ptr) |
188 | 0 | { |
189 | 0 | KR_RESOURCE kr; |
190 | |
|
191 | 0 | if (active_handles) |
192 | | /* There are open handles. */ |
193 | 0 | BUG (); |
194 | | |
195 | 0 | for (kr=kr_resources; kr; kr = kr->next) |
196 | 0 | { |
197 | 0 | if (same_file_p (kr->fname, fname)) |
198 | 0 | { |
199 | | /* Already registered. */ |
200 | 0 | if (read_only) |
201 | 0 | kr->read_only = 1; |
202 | 0 | *ptr=kr; |
203 | 0 | return 0; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | 0 | kr = xmalloc (sizeof *kr + strlen (fname)); |
208 | 0 | strcpy (kr->fname, fname); |
209 | 0 | kr->read_only = read_only; |
210 | 0 | kr->lockhd = NULL; |
211 | 0 | kr->is_locked = 0; |
212 | 0 | kr->did_full_scan = 0; |
213 | | /* keep a list of all issued pointers */ |
214 | 0 | kr->next = kr_resources; |
215 | 0 | kr_resources = kr; |
216 | | |
217 | | /* create the offset table the first time a function here is used */ |
218 | 0 | if (!key_present_hash) |
219 | 0 | key_present_hash = key_present_hash_new (); |
220 | |
|
221 | 0 | *ptr=kr; |
222 | |
|
223 | 0 | return 1; |
224 | 0 | } |
225 | | |
226 | | int |
227 | | keyring_is_writable (void *token) |
228 | 0 | { |
229 | 0 | KR_RESOURCE r = token; |
230 | |
|
231 | 0 | return r? (r->read_only || !gnupg_access (r->fname, W_OK)) : 0; |
232 | 0 | } |
233 | | |
234 | | |
235 | | |
236 | | /* Create a new handle for the resource associated with TOKEN. |
237 | | On error NULL is returned and ERRNO is set. |
238 | | The returned handle must be released using keyring_release (). */ |
239 | | KEYRING_HANDLE |
240 | | keyring_new (void *token) |
241 | 0 | { |
242 | 0 | KEYRING_HANDLE hd; |
243 | 0 | KR_RESOURCE resource = token; |
244 | |
|
245 | 0 | log_assert (resource); |
246 | | |
247 | 0 | hd = xtrycalloc (1, sizeof *hd); |
248 | 0 | if (!hd) |
249 | 0 | return hd; |
250 | 0 | hd->resource = resource; |
251 | 0 | active_handles++; |
252 | 0 | return hd; |
253 | 0 | } |
254 | | |
255 | | void |
256 | | keyring_fp_close (KEYRING_HANDLE hd) |
257 | 0 | { |
258 | 0 | if (!hd) |
259 | 0 | return; |
260 | 0 | iobuf_close (hd->current.iobuf); |
261 | 0 | } |
262 | | |
263 | | void |
264 | | keyring_release (KEYRING_HANDLE hd) |
265 | 0 | { |
266 | 0 | if (!hd) |
267 | 0 | return; |
268 | 0 | log_assert (active_handles > 0); |
269 | 0 | active_handles--; |
270 | 0 | xfree (hd->word_match.name); |
271 | 0 | xfree (hd->word_match.pattern); |
272 | 0 | xfree (hd); |
273 | 0 | } |
274 | | |
275 | | |
276 | | /* Save the current found state in HD for later retrieval by |
277 | | keybox_pop_found_state. Only one state may be saved. */ |
278 | | void |
279 | | keyring_push_found_state (KEYRING_HANDLE hd) |
280 | 0 | { |
281 | 0 | hd->saved_found = hd->found; |
282 | 0 | hd->found.kr = NULL; |
283 | 0 | } |
284 | | |
285 | | |
286 | | /* Restore the saved found state in HD. */ |
287 | | void |
288 | | keyring_pop_found_state (KEYRING_HANDLE hd) |
289 | 0 | { |
290 | 0 | hd->found = hd->saved_found; |
291 | 0 | hd->saved_found.kr = NULL; |
292 | 0 | } |
293 | | |
294 | | |
295 | | const char * |
296 | | keyring_get_resource_name (KEYRING_HANDLE hd) |
297 | 0 | { |
298 | 0 | if (!hd || !hd->resource) |
299 | 0 | return NULL; |
300 | 0 | return hd->resource->fname; |
301 | 0 | } |
302 | | |
303 | | |
304 | | /* |
305 | | * Lock the keyring with the given handle, or unlock if YES is false. |
306 | | * We ignore the handle and lock all registered files. |
307 | | */ |
308 | | int |
309 | | keyring_lock (KEYRING_HANDLE hd, int yes) |
310 | 0 | { |
311 | 0 | KR_RESOURCE kr; |
312 | 0 | int rc = 0; |
313 | |
|
314 | 0 | (void)hd; |
315 | |
|
316 | 0 | if (yes) { |
317 | | /* first make sure the lock handles are created */ |
318 | 0 | for (kr=kr_resources; kr; kr = kr->next) { |
319 | 0 | if (!keyring_is_writable(kr)) |
320 | 0 | continue; |
321 | 0 | if (!kr->lockhd) { |
322 | 0 | kr->lockhd = dotlock_create (kr->fname, 0); |
323 | 0 | if (!kr->lockhd) { |
324 | 0 | log_info ("can't allocate lock for '%s'\n", kr->fname ); |
325 | 0 | rc = GPG_ERR_GENERAL; |
326 | 0 | } |
327 | 0 | } |
328 | 0 | } |
329 | 0 | if (rc) |
330 | 0 | return rc; |
331 | | |
332 | | /* and now set the locks */ |
333 | 0 | for (kr=kr_resources; kr; kr = kr->next) { |
334 | 0 | if (!keyring_is_writable(kr)) |
335 | 0 | continue; |
336 | 0 | if (kr->is_locked) |
337 | 0 | continue; |
338 | | |
339 | | #ifdef HAVE_W32_SYSTEM |
340 | | /* Under Windows we need to CloseHandle the file before we |
341 | | * try to lock it. This is because another process might |
342 | | * have taken the lock and is using keybox_file_rename to |
343 | | * rename the base file. How if our dotlock_take below is |
344 | | * waiting for the lock but we have the base file still |
345 | | * open, keybox_file_rename will never succeed as we are |
346 | | * in a deadlock. */ |
347 | | iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, |
348 | | (char*)kr->fname); |
349 | | #endif /*HAVE_W32_SYSTEM*/ |
350 | 0 | if (dotlock_take (kr->lockhd, -1) ) { |
351 | 0 | log_info ("can't lock '%s'\n", kr->fname ); |
352 | 0 | rc = GPG_ERR_GENERAL; |
353 | 0 | } |
354 | 0 | else |
355 | 0 | kr->is_locked = 1; |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | 0 | if (rc || !yes) { |
360 | 0 | for (kr=kr_resources; kr; kr = kr->next) { |
361 | 0 | if (!keyring_is_writable(kr)) |
362 | 0 | continue; |
363 | 0 | if (!kr->is_locked) |
364 | 0 | continue; |
365 | | |
366 | 0 | if (dotlock_release (kr->lockhd)) |
367 | 0 | log_info ("can't unlock '%s'\n", kr->fname ); |
368 | 0 | else |
369 | 0 | kr->is_locked = 0; |
370 | 0 | } |
371 | 0 | } |
372 | |
|
373 | 0 | return rc; |
374 | 0 | } |
375 | | |
376 | | |
377 | | |
378 | | /* |
379 | | * Return the last found keyblock. Caller must free it. |
380 | | * The returned keyblock has the kbode flag bit 0 set for the node with |
381 | | * the public key used to locate the keyblock or flag bit 1 set for |
382 | | * the user ID node. |
383 | | */ |
384 | | int |
385 | | keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) |
386 | 0 | { |
387 | 0 | PACKET *pkt; |
388 | 0 | struct parse_packet_ctx_s parsectx; |
389 | 0 | int rc; |
390 | 0 | KBNODE keyblock = NULL, node, lastnode; |
391 | 0 | IOBUF a; |
392 | 0 | int in_cert = 0; |
393 | 0 | int pk_no = 0; |
394 | 0 | int uid_no = 0; |
395 | 0 | int save_mode; |
396 | |
|
397 | 0 | if (ret_kb) |
398 | 0 | *ret_kb = NULL; |
399 | |
|
400 | 0 | if (!hd->found.kr) |
401 | 0 | return -1; /* no successful search */ |
402 | | |
403 | 0 | a = iobuf_open (hd->found.kr->fname); |
404 | 0 | if (!a) |
405 | 0 | { |
406 | 0 | log_error(_("can't open '%s'\n"), hd->found.kr->fname); |
407 | 0 | return GPG_ERR_KEYRING_OPEN; |
408 | 0 | } |
409 | | |
410 | 0 | if (iobuf_seek (a, hd->found.offset) ) { |
411 | 0 | log_error ("can't seek '%s'\n", hd->found.kr->fname); |
412 | 0 | iobuf_close(a); |
413 | 0 | return GPG_ERR_KEYRING_OPEN; |
414 | 0 | } |
415 | | |
416 | 0 | pkt = xmalloc (sizeof *pkt); |
417 | 0 | init_packet (pkt); |
418 | 0 | init_parse_packet (&parsectx, a); |
419 | 0 | hd->found.n_packets = 0; |
420 | 0 | lastnode = NULL; |
421 | 0 | save_mode = set_packet_list_mode(0); |
422 | 0 | while ((rc=parse_packet (&parsectx, pkt)) != -1) { |
423 | 0 | hd->found.n_packets = parsectx.n_parsed_packets; |
424 | 0 | if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) { |
425 | 0 | free_packet (pkt, &parsectx); |
426 | 0 | init_packet (pkt); |
427 | 0 | continue; |
428 | 0 | } |
429 | 0 | if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) |
430 | 0 | { |
431 | 0 | if (in_cert) |
432 | | /* It is not this key that is problematic, but the |
433 | | following key. */ |
434 | 0 | { |
435 | 0 | rc = 0; |
436 | 0 | hd->found.n_packets --; |
437 | 0 | } |
438 | 0 | else |
439 | | /* Upper layer needs to handle this. */ |
440 | 0 | { |
441 | 0 | } |
442 | 0 | break; |
443 | 0 | } |
444 | 0 | if (rc) { |
445 | 0 | log_error ("keyring_get_keyblock: read error: %s\n", |
446 | 0 | gpg_strerror (rc) ); |
447 | 0 | rc = GPG_ERR_INV_KEYRING; |
448 | 0 | break; |
449 | 0 | } |
450 | | |
451 | | /* Filter allowed packets. */ |
452 | 0 | switch (pkt->pkttype) |
453 | 0 | { |
454 | 0 | case PKT_PUBLIC_KEY: |
455 | 0 | case PKT_PUBLIC_SUBKEY: |
456 | 0 | case PKT_SECRET_KEY: |
457 | 0 | case PKT_SECRET_SUBKEY: |
458 | 0 | case PKT_USER_ID: |
459 | 0 | case PKT_ATTRIBUTE: |
460 | 0 | case PKT_SIGNATURE: |
461 | 0 | break; /* Allowed per RFC. */ |
462 | 0 | case PKT_RING_TRUST: |
463 | 0 | case PKT_OLD_COMMENT: |
464 | 0 | case PKT_COMMENT: |
465 | 0 | case PKT_GPG_CONTROL: |
466 | 0 | break; /* Allowed by us. */ |
467 | | |
468 | 0 | default: |
469 | 0 | log_info ("skipped packet of type %d in keyring\n", |
470 | 0 | (int)pkt->pkttype); |
471 | 0 | free_packet(pkt, &parsectx); |
472 | 0 | init_packet(pkt); |
473 | 0 | continue; |
474 | 0 | } |
475 | | |
476 | 0 | if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY |
477 | 0 | || pkt->pkttype == PKT_SECRET_KEY)) { |
478 | 0 | hd->found.n_packets--; /* fix counter */ |
479 | 0 | break; /* ready */ |
480 | 0 | } |
481 | | |
482 | 0 | in_cert = 1; |
483 | 0 | node = new_kbnode (pkt); |
484 | 0 | if (!keyblock) |
485 | 0 | keyblock = lastnode = node; |
486 | 0 | else |
487 | 0 | { |
488 | 0 | lastnode->next = node; |
489 | 0 | lastnode = node; |
490 | 0 | } |
491 | 0 | switch (pkt->pkttype) |
492 | 0 | { |
493 | 0 | case PKT_PUBLIC_KEY: |
494 | 0 | case PKT_PUBLIC_SUBKEY: |
495 | 0 | case PKT_SECRET_KEY: |
496 | 0 | case PKT_SECRET_SUBKEY: |
497 | 0 | if (++pk_no == hd->found.pk_no) |
498 | 0 | node->flag |= 1; |
499 | 0 | break; |
500 | | |
501 | 0 | case PKT_USER_ID: |
502 | 0 | if (++uid_no == hd->found.uid_no) |
503 | 0 | node->flag |= 2; |
504 | 0 | break; |
505 | | |
506 | 0 | default: |
507 | 0 | break; |
508 | 0 | } |
509 | | |
510 | 0 | pkt = xmalloc (sizeof *pkt); |
511 | 0 | init_packet(pkt); |
512 | 0 | } |
513 | 0 | set_packet_list_mode(save_mode); |
514 | |
|
515 | 0 | if (rc == -1 && keyblock) |
516 | 0 | rc = 0; /* got the entire keyblock */ |
517 | |
|
518 | 0 | if (rc || !ret_kb) |
519 | 0 | release_kbnode (keyblock); |
520 | 0 | else { |
521 | 0 | *ret_kb = keyblock; |
522 | 0 | } |
523 | 0 | free_packet (pkt, &parsectx); |
524 | 0 | deinit_parse_packet (&parsectx); |
525 | 0 | xfree (pkt); |
526 | 0 | iobuf_close(a); |
527 | | |
528 | | /* Make sure that future search operations fail immediately when |
529 | | * we know that we are working on a invalid keyring |
530 | | */ |
531 | 0 | if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING) |
532 | 0 | hd->current.error = rc; |
533 | |
|
534 | 0 | return rc; |
535 | 0 | } |
536 | | |
537 | | int |
538 | | keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb) |
539 | 0 | { |
540 | 0 | int rc; |
541 | |
|
542 | 0 | if (!hd->found.kr) |
543 | 0 | return -1; /* no successful prior search */ |
544 | | |
545 | 0 | if (hd->found.kr->read_only) |
546 | 0 | return gpg_error (GPG_ERR_EACCES); |
547 | | |
548 | 0 | if (!hd->found.n_packets) { |
549 | | /* need to know the number of packets - do a dummy get_keyblock*/ |
550 | 0 | rc = keyring_get_keyblock (hd, NULL); |
551 | 0 | if (rc) { |
552 | 0 | log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); |
553 | 0 | return rc; |
554 | 0 | } |
555 | 0 | if (!hd->found.n_packets) |
556 | 0 | BUG (); |
557 | 0 | } |
558 | | |
559 | | /* The open iobuf isn't needed anymore and in fact is a problem when |
560 | | it comes to renaming the keyring files on some operating systems, |
561 | | so close it here */ |
562 | 0 | iobuf_close(hd->current.iobuf); |
563 | 0 | hd->current.iobuf = NULL; |
564 | | |
565 | | /* do the update */ |
566 | 0 | rc = do_copy (3, hd->found.kr->fname, kb, |
567 | 0 | hd->found.offset, hd->found.n_packets ); |
568 | 0 | if (!rc) { |
569 | 0 | if (key_present_hash) |
570 | 0 | { |
571 | 0 | key_present_hash_update_from_kb (key_present_hash, kb); |
572 | 0 | } |
573 | | /* better reset the found info */ |
574 | 0 | hd->found.kr = NULL; |
575 | 0 | hd->found.offset = 0; |
576 | 0 | } |
577 | 0 | return rc; |
578 | 0 | } |
579 | | |
580 | | int |
581 | | keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) |
582 | 0 | { |
583 | 0 | int rc; |
584 | 0 | const char *fname; |
585 | |
|
586 | 0 | if (!hd) |
587 | 0 | fname = NULL; |
588 | 0 | else if (hd->found.kr) |
589 | 0 | { |
590 | 0 | fname = hd->found.kr->fname; |
591 | 0 | if (hd->found.kr->read_only) |
592 | 0 | return gpg_error (GPG_ERR_EACCES); |
593 | 0 | } |
594 | 0 | else if (hd->current.kr) |
595 | 0 | { |
596 | 0 | fname = hd->current.kr->fname; |
597 | 0 | if (hd->current.kr->read_only) |
598 | 0 | return gpg_error (GPG_ERR_EACCES); |
599 | 0 | } |
600 | 0 | else |
601 | 0 | fname = hd->resource? hd->resource->fname:NULL; |
602 | | |
603 | 0 | if (!fname) |
604 | 0 | return GPG_ERR_GENERAL; |
605 | | |
606 | | /* Close this one otherwise we will lose the position for |
607 | | * a next search. Fixme: it would be better to adjust the position |
608 | | * after the write operations. |
609 | | */ |
610 | 0 | iobuf_close (hd->current.iobuf); |
611 | 0 | hd->current.iobuf = NULL; |
612 | | |
613 | | /* do the insert */ |
614 | 0 | rc = do_copy (1, fname, kb, 0, 0 ); |
615 | 0 | if (!rc && key_present_hash) |
616 | 0 | { |
617 | 0 | key_present_hash_update_from_kb (key_present_hash, kb); |
618 | 0 | } |
619 | |
|
620 | 0 | return rc; |
621 | 0 | } |
622 | | |
623 | | |
624 | | int |
625 | | keyring_delete_keyblock (KEYRING_HANDLE hd) |
626 | 0 | { |
627 | 0 | int rc; |
628 | |
|
629 | 0 | if (!hd->found.kr) |
630 | 0 | return -1; /* no successful prior search */ |
631 | | |
632 | 0 | if (hd->found.kr->read_only) |
633 | 0 | return gpg_error (GPG_ERR_EACCES); |
634 | | |
635 | 0 | if (!hd->found.n_packets) { |
636 | | /* need to know the number of packets - do a dummy get_keyblock*/ |
637 | 0 | rc = keyring_get_keyblock (hd, NULL); |
638 | 0 | if (rc) { |
639 | 0 | log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); |
640 | 0 | return rc; |
641 | 0 | } |
642 | 0 | if (!hd->found.n_packets) |
643 | 0 | BUG (); |
644 | 0 | } |
645 | | |
646 | | /* close this one otherwise we will lose the position for |
647 | | * a next search. Fixme: it would be better to adjust the position |
648 | | * after the write operations. |
649 | | */ |
650 | 0 | iobuf_close (hd->current.iobuf); |
651 | 0 | hd->current.iobuf = NULL; |
652 | | |
653 | | /* do the delete */ |
654 | 0 | rc = do_copy (2, hd->found.kr->fname, NULL, |
655 | 0 | hd->found.offset, hd->found.n_packets ); |
656 | 0 | if (!rc) { |
657 | | /* better reset the found info */ |
658 | 0 | hd->found.kr = NULL; |
659 | 0 | hd->found.offset = 0; |
660 | | /* Delete is a rare operations, so we don't remove the keys |
661 | | * from the offset table */ |
662 | 0 | } |
663 | 0 | return rc; |
664 | 0 | } |
665 | | |
666 | | |
667 | | |
668 | | /* |
669 | | * Start the next search on this handle right at the beginning |
670 | | */ |
671 | | int |
672 | | keyring_search_reset (KEYRING_HANDLE hd) |
673 | 0 | { |
674 | 0 | log_assert (hd); |
675 | | |
676 | 0 | iobuf_close (hd->current.iobuf); |
677 | 0 | hd->current.iobuf = NULL; |
678 | 0 | hd->current.eof = 0; |
679 | 0 | hd->current.error = 0; |
680 | |
|
681 | 0 | hd->found.kr = NULL; |
682 | 0 | hd->found.offset = 0; |
683 | |
|
684 | 0 | if (hd->current.kr) |
685 | 0 | iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, |
686 | 0 | (char*)hd->current.kr->fname); |
687 | 0 | hd->current.kr = NULL; |
688 | |
|
689 | 0 | return 0; |
690 | 0 | } |
691 | | |
692 | | |
693 | | static int |
694 | | prepare_search (KEYRING_HANDLE hd) |
695 | 0 | { |
696 | 0 | if (hd->current.error) { |
697 | | /* If the last key was a legacy key, we simply ignore the error so that |
698 | | we can easily use search_next. */ |
699 | 0 | if (gpg_err_code (hd->current.error) == GPG_ERR_LEGACY_KEY) |
700 | 0 | { |
701 | 0 | if (DBG_KEYDB) |
702 | 0 | log_debug ("%s: last error was GPG_ERR_LEGACY_KEY, clearing\n", |
703 | 0 | __func__); |
704 | 0 | hd->current.error = 0; |
705 | 0 | } |
706 | 0 | else |
707 | 0 | { |
708 | 0 | if (DBG_KEYDB) |
709 | 0 | log_debug ("%s: returning last error: %s\n", |
710 | 0 | __func__, gpg_strerror (hd->current.error)); |
711 | 0 | return hd->current.error; /* still in error state */ |
712 | 0 | } |
713 | 0 | } |
714 | | |
715 | 0 | if (hd->current.kr && !hd->current.eof) { |
716 | 0 | if ( !hd->current.iobuf ) |
717 | 0 | { |
718 | 0 | if (DBG_KEYDB) |
719 | 0 | log_debug ("%s: missing iobuf!\n", __func__); |
720 | 0 | return GPG_ERR_GENERAL; /* Position invalid after a modify. */ |
721 | 0 | } |
722 | 0 | return 0; /* okay */ |
723 | 0 | } |
724 | | |
725 | 0 | if (!hd->current.kr && hd->current.eof) |
726 | 0 | { |
727 | 0 | if (DBG_KEYDB) |
728 | 0 | log_debug ("%s: EOF!\n", __func__); |
729 | 0 | return -1; /* still EOF */ |
730 | 0 | } |
731 | | |
732 | 0 | if (!hd->current.kr) { /* start search with first keyring */ |
733 | 0 | hd->current.kr = hd->resource; |
734 | 0 | if (!hd->current.kr) { |
735 | 0 | if (DBG_KEYDB) |
736 | 0 | log_debug ("%s: keyring not available!\n", __func__); |
737 | 0 | hd->current.eof = 1; |
738 | 0 | return -1; /* keyring not available */ |
739 | 0 | } |
740 | 0 | log_assert (!hd->current.iobuf); |
741 | 0 | } |
742 | 0 | else { /* EOF */ |
743 | 0 | if (DBG_KEYDB) |
744 | 0 | log_debug ("%s: EOF\n", __func__); |
745 | 0 | iobuf_close (hd->current.iobuf); |
746 | 0 | hd->current.iobuf = NULL; |
747 | 0 | hd->current.kr = NULL; |
748 | 0 | hd->current.eof = 1; |
749 | 0 | return -1; |
750 | 0 | } |
751 | | |
752 | 0 | hd->current.eof = 0; |
753 | 0 | hd->current.iobuf = iobuf_open (hd->current.kr->fname); |
754 | 0 | if (!hd->current.iobuf) |
755 | 0 | { |
756 | 0 | hd->current.error = gpg_error_from_syserror (); |
757 | 0 | log_error(_("can't open '%s'\n"), hd->current.kr->fname ); |
758 | 0 | return hd->current.error; |
759 | 0 | } |
760 | | |
761 | 0 | return 0; |
762 | 0 | } |
763 | | |
764 | | |
765 | | /* A map of the all characters valid used for word_match() |
766 | | * Valid characters are in this table converted to uppercase. |
767 | | * because the upper 128 bytes have special meaning, we assume |
768 | | * that they are all valid. |
769 | | * Note: We must use numerical values here in case that this program |
770 | | * will be converted to those little blue HAL9000s with their strange |
771 | | * EBCDIC character set (user ids are UTF-8). |
772 | | * wk 2000-04-13: Hmmm, does this really make sense, given the fact that |
773 | | * we can run gpg now on a S/390 running GNU/Linux, where the code |
774 | | * translation is done by the device drivers? |
775 | | */ |
776 | | static const byte word_match_chars[256] = { |
777 | | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
778 | | /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
779 | | /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
780 | | /* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
781 | | /* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
782 | | /* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
783 | | /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
784 | | /* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
785 | | /* 40 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
786 | | /* 48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |
787 | | /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |
788 | | /* 58 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, |
789 | | /* 60 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
790 | | /* 68 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |
791 | | /* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |
792 | | /* 78 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, |
793 | | /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
794 | | /* 88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, |
795 | | /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, |
796 | | /* 98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, |
797 | | /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, |
798 | | /* a8 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, |
799 | | /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, |
800 | | /* b8 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, |
801 | | /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, |
802 | | /* c8 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, |
803 | | /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, |
804 | | /* d8 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, |
805 | | /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, |
806 | | /* e8 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, |
807 | | /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, |
808 | | /* f8 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff |
809 | | }; |
810 | | |
811 | | /**************** |
812 | | * Do a word match (original user id starts with a '+'). |
813 | | * The pattern is already tokenized to a more suitable format: |
814 | | * There are only the real words in it delimited by one space |
815 | | * and all converted to uppercase. |
816 | | * |
817 | | * Returns: 0 if all words match. |
818 | | * |
819 | | * Note: This algorithm is a straightforward one and not very |
820 | | * fast. It works for UTF-8 strings. The uidlen should |
821 | | * be removed but due to the fact that old versions of |
822 | | * pgp don't use UTF-8 we still use the length; this should |
823 | | * be fixed in parse-packet (and replace \0 by some special |
824 | | * UTF-8 encoding) |
825 | | */ |
826 | | static int |
827 | | word_match( const byte *uid, size_t uidlen, const byte *pattern ) |
828 | 0 | { |
829 | 0 | size_t wlen, n; |
830 | 0 | const byte *p; |
831 | 0 | const byte *s; |
832 | |
|
833 | 0 | for( s=pattern; *s; ) { |
834 | 0 | do { |
835 | | /* skip leading delimiters */ |
836 | 0 | while( uidlen && !word_match_chars[*uid] ) |
837 | 0 | uid++, uidlen--; |
838 | | /* get length of the word */ |
839 | 0 | n = uidlen; p = uid; |
840 | 0 | while( n && word_match_chars[*p] ) |
841 | 0 | p++, n--; |
842 | 0 | wlen = p - uid; |
843 | | /* and compare against the current word from pattern */ |
844 | 0 | for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) { |
845 | 0 | if( word_match_chars[*p] != s[n] ) |
846 | 0 | break; |
847 | 0 | } |
848 | 0 | if( n == wlen && (s[n] == ' ' || !s[n]) ) |
849 | 0 | break; /* found */ |
850 | 0 | uid += wlen; |
851 | 0 | uidlen -= wlen; |
852 | 0 | } while( uidlen ); |
853 | 0 | if( !uidlen ) |
854 | 0 | return -1; /* not found */ |
855 | | |
856 | | /* advance to next word in pattern */ |
857 | 0 | for(; *s != ' ' && *s ; s++ ) |
858 | 0 | ; |
859 | 0 | if( *s ) |
860 | 0 | s++ ; |
861 | 0 | } |
862 | 0 | return 0; /* found */ |
863 | 0 | } |
864 | | |
865 | | /**************** |
866 | | * prepare word word_match; that is parse the name and |
867 | | * build the pattern. |
868 | | * caller has to free the returned pattern |
869 | | */ |
870 | | static char* |
871 | | prepare_word_match (const byte *name) |
872 | 0 | { |
873 | 0 | byte *pattern, *p; |
874 | 0 | int c; |
875 | | |
876 | | /* the original length is always enough for the pattern */ |
877 | 0 | p = pattern = xmalloc(strlen(name)+1); |
878 | 0 | do { |
879 | | /* skip leading delimiters */ |
880 | 0 | while( *name && !word_match_chars[*name] ) |
881 | 0 | name++; |
882 | | /* copy as long as we don't have a delimiter and convert |
883 | | * to uppercase. |
884 | | * fixme: how can we handle utf8 uppercasing */ |
885 | 0 | for( ; *name && (c=word_match_chars[*name]); name++ ) |
886 | 0 | *p++ = c; |
887 | 0 | *p++ = ' '; /* append pattern delimiter */ |
888 | 0 | } while( *name ); |
889 | 0 | p[-1] = 0; /* replace last pattern delimiter by EOS */ |
890 | |
|
891 | 0 | return pattern; |
892 | 0 | } |
893 | | |
894 | | |
895 | | |
896 | | |
897 | | static int |
898 | | compare_name (int mode, const char *name, const char *uid, size_t uidlen) |
899 | 0 | { |
900 | 0 | int i; |
901 | 0 | const char *s, *se; |
902 | |
|
903 | 0 | if (mode == KEYDB_SEARCH_MODE_EXACT) { |
904 | 0 | for (i=0; name[i] && uidlen; i++, uidlen--) |
905 | 0 | if (uid[i] != name[i]) |
906 | 0 | break; |
907 | 0 | if (!uidlen && !name[i]) |
908 | 0 | return 0; /* found */ |
909 | 0 | } |
910 | 0 | else if (mode == KEYDB_SEARCH_MODE_SUBSTR) { |
911 | 0 | if (ascii_memistr( uid, uidlen, name )) |
912 | 0 | return 0; |
913 | 0 | } |
914 | 0 | else if ( mode == KEYDB_SEARCH_MODE_MAIL |
915 | 0 | || mode == KEYDB_SEARCH_MODE_MAILSUB |
916 | 0 | || mode == KEYDB_SEARCH_MODE_MAILEND) { |
917 | 0 | int have_angles = 1; |
918 | 0 | for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++) |
919 | 0 | ; |
920 | 0 | if (i == uidlen) |
921 | 0 | { |
922 | | /* The UID is a plain addr-spec (cf. RFC2822 section 4.3). */ |
923 | 0 | have_angles = 0; |
924 | 0 | s = uid; |
925 | 0 | i = 0; |
926 | 0 | } |
927 | 0 | if (i < uidlen) { |
928 | 0 | if (have_angles) |
929 | 0 | { |
930 | | /* skip opening delim and one char and look for the closing one*/ |
931 | 0 | s++; i++; |
932 | 0 | for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++) |
933 | 0 | ; |
934 | 0 | } |
935 | 0 | else |
936 | 0 | se = s + uidlen; |
937 | |
|
938 | 0 | if (i < uidlen) { |
939 | 0 | i = se - s; |
940 | 0 | if (mode == KEYDB_SEARCH_MODE_MAIL) { |
941 | 0 | if( strlen(name)-2 == i |
942 | 0 | && !ascii_memcasecmp( s, name+1, i) ) |
943 | 0 | return 0; |
944 | 0 | } |
945 | 0 | else if (mode == KEYDB_SEARCH_MODE_MAILSUB) { |
946 | 0 | if( ascii_memistr( s, i, name ) ) |
947 | 0 | return 0; |
948 | 0 | } |
949 | 0 | else { /* email from end */ |
950 | | /* nyi */ |
951 | 0 | } |
952 | 0 | } |
953 | 0 | } |
954 | 0 | } |
955 | 0 | else if (mode == KEYDB_SEARCH_MODE_WORDS) |
956 | 0 | return word_match (uid, uidlen, name); |
957 | 0 | else |
958 | 0 | BUG(); |
959 | | |
960 | 0 | return -1; /* not found */ |
961 | 0 | } |
962 | | |
963 | | |
964 | | /* |
965 | | * Search through the keyring(s), starting at the current position, |
966 | | * for a keyblock which contains one of the keys described in the DESC array. |
967 | | */ |
968 | | int |
969 | | keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, |
970 | | size_t ndesc, size_t *descindex, int ignore_legacy) |
971 | 0 | { |
972 | 0 | int rc; |
973 | 0 | PACKET pkt; |
974 | 0 | struct parse_packet_ctx_s parsectx; |
975 | 0 | int save_mode; |
976 | 0 | off_t offset, main_offset; |
977 | 0 | size_t n; |
978 | 0 | int need_uid, need_words, need_keyid, need_fpr, any_skip, need_grip; |
979 | 0 | int pk_no, uid_no; |
980 | 0 | int initial_skip; |
981 | 0 | int scanned_from_start; |
982 | 0 | int use_key_present_hash; |
983 | 0 | PKT_user_id *uid = NULL; |
984 | 0 | PKT_public_key *pk = NULL; |
985 | 0 | u32 aki[2]; |
986 | 0 | unsigned char grip[KEYGRIP_LEN]; |
987 | | |
988 | | /* figure out what information we need */ |
989 | 0 | need_uid = need_words = need_keyid = need_fpr = any_skip = need_grip = 0; |
990 | 0 | for (n=0; n < ndesc; n++) |
991 | 0 | { |
992 | 0 | switch (desc[n].mode) |
993 | 0 | { |
994 | 0 | case KEYDB_SEARCH_MODE_EXACT: |
995 | 0 | case KEYDB_SEARCH_MODE_SUBSTR: |
996 | 0 | case KEYDB_SEARCH_MODE_MAIL: |
997 | 0 | case KEYDB_SEARCH_MODE_MAILSUB: |
998 | 0 | case KEYDB_SEARCH_MODE_MAILEND: |
999 | 0 | need_uid = 1; |
1000 | 0 | break; |
1001 | 0 | case KEYDB_SEARCH_MODE_WORDS: |
1002 | 0 | need_uid = 1; |
1003 | 0 | need_words = 1; |
1004 | 0 | break; |
1005 | 0 | case KEYDB_SEARCH_MODE_SHORT_KID: |
1006 | 0 | case KEYDB_SEARCH_MODE_LONG_KID: |
1007 | 0 | need_keyid = 1; |
1008 | 0 | break; |
1009 | 0 | case KEYDB_SEARCH_MODE_FPR: |
1010 | 0 | need_fpr = 1; |
1011 | 0 | break; |
1012 | 0 | case KEYDB_SEARCH_MODE_FIRST: |
1013 | | /* always restart the search in this mode */ |
1014 | 0 | keyring_search_reset (hd); |
1015 | 0 | break; |
1016 | 0 | case KEYDB_SEARCH_MODE_KEYGRIP: |
1017 | 0 | need_grip = 1; |
1018 | 0 | break; |
1019 | 0 | default: break; |
1020 | 0 | } |
1021 | 0 | if (desc[n].skipfnc) |
1022 | 0 | { |
1023 | 0 | any_skip = 1; |
1024 | 0 | need_keyid = 1; |
1025 | 0 | } |
1026 | 0 | } |
1027 | | |
1028 | 0 | if (DBG_KEYDB) |
1029 | 0 | log_debug ("%s: need_uid = %d; need_words = %d; need_keyid = %d; need_fpr = %d; any_skip = %d\n", |
1030 | 0 | __func__, need_uid, need_words, need_keyid, need_fpr, any_skip); |
1031 | |
|
1032 | 0 | rc = prepare_search (hd); |
1033 | 0 | if (rc) |
1034 | 0 | { |
1035 | 0 | if (DBG_KEYDB) |
1036 | 0 | log_debug ("%s: prepare_search failed: %s (%d)\n", |
1037 | 0 | __func__, gpg_strerror (rc), gpg_err_code (rc)); |
1038 | 0 | return rc; |
1039 | 0 | } |
1040 | | |
1041 | 0 | use_key_present_hash = !!key_present_hash; |
1042 | 0 | if (!use_key_present_hash) |
1043 | 0 | { |
1044 | 0 | if (DBG_KEYDB) |
1045 | 0 | log_debug ("%s: no offset table.\n", __func__); |
1046 | 0 | } |
1047 | 0 | else if (!key_present_hash_ready) |
1048 | 0 | { |
1049 | 0 | if (DBG_KEYDB) |
1050 | 0 | log_debug ("%s: initializing offset table. (need_keyid: %d => 1)\n", |
1051 | 0 | __func__, need_keyid); |
1052 | 0 | need_keyid = 1; |
1053 | 0 | } |
1054 | 0 | else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) |
1055 | 0 | { |
1056 | 0 | struct key_present *oi; |
1057 | |
|
1058 | 0 | if (DBG_KEYDB) |
1059 | 0 | log_debug ("%s: look up by long key id, checking cache\n", __func__); |
1060 | |
|
1061 | 0 | oi = key_present_hash_lookup (key_present_hash, desc[0].u.kid); |
1062 | 0 | if (!oi) |
1063 | 0 | { /* We know that we don't have this key */ |
1064 | 0 | if (DBG_KEYDB) |
1065 | 0 | log_debug ("%s: cache says not present\n", __func__); |
1066 | 0 | hd->found.kr = NULL; |
1067 | 0 | hd->current.eof = 1; |
1068 | 0 | return -1; |
1069 | 0 | } |
1070 | | /* We could now create a positive search status and return. |
1071 | | * However the problem is that another instance of gpg may |
1072 | | * have changed the keyring so that the offsets are not valid |
1073 | | * anymore - therefore we don't do it |
1074 | | */ |
1075 | 0 | } |
1076 | | |
1077 | 0 | if (need_words) |
1078 | 0 | { |
1079 | 0 | const char *name = NULL; |
1080 | |
|
1081 | 0 | log_debug ("word search mode does not yet work\n"); |
1082 | | /* FIXME: here is a long standing bug in our function and in addition we |
1083 | | just use the first search description */ |
1084 | 0 | for (n=0; n < ndesc && !name; n++) |
1085 | 0 | { |
1086 | 0 | if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) |
1087 | 0 | name = desc[n].u.name; |
1088 | 0 | } |
1089 | 0 | log_assert (name); |
1090 | 0 | if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) |
1091 | 0 | { |
1092 | | /* name changed */ |
1093 | 0 | xfree (hd->word_match.name); |
1094 | 0 | xfree (hd->word_match.pattern); |
1095 | 0 | hd->word_match.name = xstrdup (name); |
1096 | 0 | hd->word_match.pattern = prepare_word_match (name); |
1097 | 0 | } |
1098 | | /* name = hd->word_match.pattern; */ |
1099 | 0 | } |
1100 | | |
1101 | 0 | init_packet(&pkt); |
1102 | 0 | save_mode = set_packet_list_mode(0); |
1103 | |
|
1104 | 0 | hd->found.kr = NULL; |
1105 | 0 | main_offset = 0; |
1106 | 0 | pk_no = uid_no = 0; |
1107 | 0 | initial_skip = 1; /* skip until we see the start of a keyblock */ |
1108 | 0 | scanned_from_start = iobuf_tell (hd->current.iobuf) == 0; |
1109 | 0 | if (DBG_KEYDB) |
1110 | 0 | log_debug ("%s: %ssearching from start of resource.\n", |
1111 | 0 | __func__, scanned_from_start ? "" : "not "); |
1112 | 0 | init_parse_packet (&parsectx, hd->current.iobuf); |
1113 | 0 | while (1) |
1114 | 0 | { |
1115 | 0 | byte afp[MAX_FINGERPRINT_LEN]; |
1116 | 0 | size_t an; |
1117 | |
|
1118 | 0 | rc = search_packet (&parsectx, &pkt, &offset, need_uid); |
1119 | 0 | if (ignore_legacy && gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) |
1120 | 0 | { |
1121 | 0 | free_packet (&pkt, &parsectx); |
1122 | 0 | continue; |
1123 | 0 | } |
1124 | 0 | if (rc) |
1125 | 0 | break; |
1126 | | |
1127 | 0 | if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) |
1128 | 0 | { |
1129 | 0 | main_offset = offset; |
1130 | 0 | pk_no = uid_no = 0; |
1131 | 0 | initial_skip = 0; |
1132 | 0 | } |
1133 | 0 | if (initial_skip) |
1134 | 0 | { |
1135 | 0 | free_packet (&pkt, &parsectx); |
1136 | 0 | continue; |
1137 | 0 | } |
1138 | | |
1139 | 0 | pk = NULL; |
1140 | 0 | uid = NULL; |
1141 | 0 | if ( pkt.pkttype == PKT_PUBLIC_KEY |
1142 | 0 | || pkt.pkttype == PKT_PUBLIC_SUBKEY |
1143 | 0 | || pkt.pkttype == PKT_SECRET_KEY |
1144 | 0 | || pkt.pkttype == PKT_SECRET_SUBKEY) |
1145 | 0 | { |
1146 | 0 | pk = pkt.pkt.public_key; |
1147 | 0 | ++pk_no; |
1148 | |
|
1149 | 0 | if (need_fpr) |
1150 | 0 | { |
1151 | 0 | fingerprint_from_pk (pk, afp, &an); |
1152 | 0 | while (an < 32) /* fill up to 32 bytes */ |
1153 | 0 | afp[an++] = 0; |
1154 | 0 | } |
1155 | 0 | if (need_keyid) |
1156 | 0 | keyid_from_pk (pk, aki); |
1157 | 0 | if (need_grip) |
1158 | 0 | keygrip_from_pk (pk, grip, 0); |
1159 | |
|
1160 | 0 | if (use_key_present_hash |
1161 | 0 | && !key_present_hash_ready |
1162 | 0 | && scanned_from_start) |
1163 | 0 | key_present_hash_update (key_present_hash, aki); |
1164 | 0 | } |
1165 | 0 | else if (pkt.pkttype == PKT_USER_ID) |
1166 | 0 | { |
1167 | 0 | uid = pkt.pkt.user_id; |
1168 | 0 | ++uid_no; |
1169 | 0 | } |
1170 | |
|
1171 | 0 | for (n=0; n < ndesc; n++) |
1172 | 0 | { |
1173 | 0 | switch (desc[n].mode) { |
1174 | 0 | case KEYDB_SEARCH_MODE_NONE: |
1175 | 0 | BUG (); |
1176 | 0 | break; |
1177 | 0 | case KEYDB_SEARCH_MODE_EXACT: |
1178 | 0 | case KEYDB_SEARCH_MODE_SUBSTR: |
1179 | 0 | case KEYDB_SEARCH_MODE_MAIL: |
1180 | 0 | case KEYDB_SEARCH_MODE_MAILSUB: |
1181 | 0 | case KEYDB_SEARCH_MODE_MAILEND: |
1182 | 0 | case KEYDB_SEARCH_MODE_WORDS: |
1183 | 0 | if ( uid && !compare_name (desc[n].mode, |
1184 | 0 | desc[n].u.name, |
1185 | 0 | uid->name, uid->len)) |
1186 | 0 | goto found; |
1187 | 0 | break; |
1188 | | |
1189 | 0 | case KEYDB_SEARCH_MODE_SHORT_KID: |
1190 | 0 | if (pk |
1191 | 0 | && ((pk->fprlen == 32 && desc[n].u.kid[1] == aki[0]) |
1192 | 0 | || (pk->fprlen != 32 && desc[n].u.kid[1] == aki[1]))) |
1193 | 0 | goto found; |
1194 | 0 | break; |
1195 | 0 | case KEYDB_SEARCH_MODE_LONG_KID: |
1196 | 0 | if (pk && desc[n].u.kid[0] == aki[0] |
1197 | 0 | && desc[n].u.kid[1] == aki[1]) |
1198 | 0 | goto found; |
1199 | 0 | break; |
1200 | 0 | case KEYDB_SEARCH_MODE_FPR: |
1201 | 0 | if (pk && desc[n].fprlen >= 16 && desc[n].fprlen <= 32 |
1202 | 0 | && !memcmp (desc[n].u.fpr, afp, desc[n].fprlen)) |
1203 | 0 | goto found; |
1204 | 0 | break; |
1205 | 0 | case KEYDB_SEARCH_MODE_FIRST: |
1206 | 0 | if (pk) |
1207 | 0 | goto found; |
1208 | 0 | break; |
1209 | 0 | case KEYDB_SEARCH_MODE_NEXT: |
1210 | 0 | if (pk) |
1211 | 0 | goto found; |
1212 | 0 | break; |
1213 | 0 | case KEYDB_SEARCH_MODE_KEYGRIP: |
1214 | 0 | if (pk && !memcmp (desc[n].u.grip, grip, KEYGRIP_LEN)) |
1215 | 0 | goto found; |
1216 | 0 | break; |
1217 | 0 | default: |
1218 | 0 | rc = GPG_ERR_INV_ARG; |
1219 | 0 | goto found; |
1220 | 0 | } |
1221 | 0 | } |
1222 | 0 | free_packet (&pkt, &parsectx); |
1223 | 0 | continue; |
1224 | 0 | found: |
1225 | 0 | if (rc) |
1226 | 0 | goto real_found; |
1227 | | |
1228 | 0 | if (DBG_KEYDB) |
1229 | 0 | log_debug ("%s: packet starting at offset %lld matched descriptor %zu\n" |
1230 | 0 | , __func__, (long long)offset, n); |
1231 | | |
1232 | | /* Record which desc we matched on. Note this value is only |
1233 | | meaningful if this function returns with no errors. */ |
1234 | 0 | if(descindex) |
1235 | 0 | *descindex=n; |
1236 | 0 | for (n=any_skip?0:ndesc; n < ndesc; n++) |
1237 | 0 | { |
1238 | 0 | if (desc[n].skipfnc |
1239 | 0 | && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid_no)) |
1240 | 0 | { |
1241 | 0 | if (DBG_KEYDB) |
1242 | 0 | log_debug ("%s: skipping match: desc %zd's skip function returned TRUE\n", |
1243 | 0 | __func__, n); |
1244 | 0 | break; |
1245 | 0 | } |
1246 | 0 | } |
1247 | 0 | if (n == ndesc) |
1248 | 0 | goto real_found; |
1249 | 0 | free_packet (&pkt, &parsectx); |
1250 | 0 | } |
1251 | 0 | real_found: |
1252 | 0 | if (!rc) |
1253 | 0 | { |
1254 | 0 | if (DBG_KEYDB) |
1255 | 0 | log_debug ("%s: returning success\n", __func__); |
1256 | 0 | hd->found.offset = main_offset; |
1257 | 0 | hd->found.kr = hd->current.kr; |
1258 | 0 | hd->found.pk_no = pk? pk_no : 0; |
1259 | 0 | hd->found.uid_no = uid? uid_no : 0; |
1260 | 0 | } |
1261 | 0 | else if (rc == -1) |
1262 | 0 | { |
1263 | 0 | if (DBG_KEYDB) |
1264 | 0 | log_debug ("%s: no matches (EOF)\n", __func__); |
1265 | |
|
1266 | 0 | hd->current.eof = 1; |
1267 | | /* if we scanned all keyrings, we are sure that |
1268 | | * all known key IDs are in our offtbl, mark that. */ |
1269 | 0 | if (use_key_present_hash |
1270 | 0 | && !key_present_hash_ready |
1271 | 0 | && scanned_from_start) |
1272 | 0 | { |
1273 | 0 | KR_RESOURCE kr; |
1274 | | |
1275 | | /* First set the did_full_scan flag for this keyring. */ |
1276 | 0 | for (kr=kr_resources; kr; kr = kr->next) |
1277 | 0 | { |
1278 | 0 | if (hd->resource == kr) |
1279 | 0 | { |
1280 | 0 | kr->did_full_scan = 1; |
1281 | 0 | break; |
1282 | 0 | } |
1283 | 0 | } |
1284 | | /* Then check whether all flags are set and if so, mark the |
1285 | | offtbl ready */ |
1286 | 0 | for (kr=kr_resources; kr; kr = kr->next) |
1287 | 0 | { |
1288 | 0 | if (!kr->did_full_scan) |
1289 | 0 | break; |
1290 | 0 | } |
1291 | 0 | if (!kr) |
1292 | 0 | key_present_hash_ready = 1; |
1293 | 0 | } |
1294 | 0 | } |
1295 | 0 | else |
1296 | 0 | { |
1297 | 0 | if (DBG_KEYDB) |
1298 | 0 | log_debug ("%s: error encountered during search: %s (%d)\n", |
1299 | 0 | __func__, gpg_strerror (rc), rc); |
1300 | 0 | hd->current.error = rc; |
1301 | 0 | } |
1302 | |
|
1303 | 0 | free_packet (&pkt, &parsectx); |
1304 | 0 | deinit_parse_packet (&parsectx); |
1305 | 0 | set_packet_list_mode(save_mode); |
1306 | 0 | return rc; |
1307 | 0 | } |
1308 | | |
1309 | | |
1310 | | static int |
1311 | | create_tmp_file (const char *template, |
1312 | | char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) |
1313 | 0 | { |
1314 | 0 | gpg_error_t err; |
1315 | 0 | mode_t oldmask; |
1316 | |
|
1317 | 0 | err = keybox_tmp_names (template, 1, r_bakfname, r_tmpfname); |
1318 | 0 | if (err) |
1319 | 0 | return err; |
1320 | | |
1321 | | /* Create the temp file with limited access. Note that the umask |
1322 | | call is not anymore needed because iobuf_create now takes care of |
1323 | | it. However, it does not harm and thus we keep it. */ |
1324 | 0 | oldmask = umask (077); |
1325 | 0 | if (is_secured_filename (*r_tmpfname)) |
1326 | 0 | { |
1327 | 0 | *r_fp = NULL; |
1328 | 0 | gpg_err_set_errno (EPERM); |
1329 | 0 | } |
1330 | 0 | else |
1331 | 0 | *r_fp = iobuf_create (*r_tmpfname, 1); |
1332 | 0 | umask (oldmask); |
1333 | 0 | if (!*r_fp) |
1334 | 0 | { |
1335 | 0 | err = gpg_error_from_syserror (); |
1336 | 0 | log_error (_("can't create '%s': %s\n"), *r_tmpfname, gpg_strerror (err)); |
1337 | 0 | xfree (*r_tmpfname); |
1338 | 0 | *r_tmpfname = NULL; |
1339 | 0 | xfree (*r_bakfname); |
1340 | 0 | *r_bakfname = NULL; |
1341 | 0 | } |
1342 | |
|
1343 | 0 | return err; |
1344 | 0 | } |
1345 | | |
1346 | | |
1347 | | static int |
1348 | | rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname) |
1349 | 0 | { |
1350 | 0 | int rc = 0; |
1351 | 0 | int block = 0; |
1352 | | |
1353 | | /* Invalidate close caches. */ |
1354 | 0 | if (iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname )) |
1355 | 0 | { |
1356 | 0 | rc = gpg_error_from_syserror (); |
1357 | 0 | goto fail; |
1358 | 0 | } |
1359 | 0 | iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname ); |
1360 | 0 | iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname ); |
1361 | | |
1362 | | /* First make a backup file. */ |
1363 | 0 | block = 1; |
1364 | 0 | rc = gnupg_rename_file (fname, bakfname, &block); |
1365 | 0 | if (rc) |
1366 | 0 | goto fail; |
1367 | | |
1368 | | /* then rename the file */ |
1369 | 0 | rc = gnupg_rename_file (tmpfname, fname, NULL); |
1370 | 0 | if (block) |
1371 | 0 | { |
1372 | 0 | gnupg_unblock_all_signals (); |
1373 | 0 | block = 0; |
1374 | 0 | } |
1375 | 0 | if (rc) |
1376 | 0 | { |
1377 | 0 | register_secured_file (fname); |
1378 | 0 | goto fail; |
1379 | 0 | } |
1380 | | |
1381 | | /* Now make sure the file has the same permissions as the original */ |
1382 | 0 | #ifndef HAVE_DOSISH_SYSTEM |
1383 | 0 | { |
1384 | 0 | struct stat statbuf; |
1385 | |
|
1386 | 0 | statbuf.st_mode=S_IRUSR | S_IWUSR; |
1387 | |
|
1388 | 0 | if (!gnupg_stat (bakfname, &statbuf) && !chmod (fname, statbuf.st_mode)) |
1389 | 0 | ; |
1390 | 0 | else |
1391 | 0 | log_error ("WARNING: unable to restore permissions to '%s': %s", |
1392 | 0 | fname, strerror(errno)); |
1393 | 0 | } |
1394 | 0 | #endif |
1395 | |
|
1396 | 0 | return 0; |
1397 | | |
1398 | 0 | fail: |
1399 | 0 | if (block) |
1400 | 0 | gnupg_unblock_all_signals (); |
1401 | 0 | return rc; |
1402 | 0 | } |
1403 | | |
1404 | | |
1405 | | static int |
1406 | | write_keyblock (IOBUF fp, KBNODE keyblock) |
1407 | 0 | { |
1408 | 0 | KBNODE kbctx = NULL, node; |
1409 | 0 | int rc; |
1410 | |
|
1411 | 0 | while ( (node = walk_kbnode (keyblock, &kbctx, 0)) ) |
1412 | 0 | { |
1413 | 0 | if ( (rc = build_packet_and_meta (fp, node->pkt) )) |
1414 | 0 | { |
1415 | 0 | log_error ("build_packet(%d) failed: %s\n", |
1416 | 0 | node->pkt->pkttype, gpg_strerror (rc) ); |
1417 | 0 | return rc; |
1418 | 0 | } |
1419 | 0 | } |
1420 | 0 | return 0; |
1421 | 0 | } |
1422 | | |
1423 | | /* |
1424 | | * Walk over all public keyrings, check the signatures and replace the |
1425 | | * keyring with a new one where the signature cache is then updated. |
1426 | | * This is only done for the public keyrings. |
1427 | | */ |
1428 | | int |
1429 | | keyring_rebuild_cache (ctrl_t ctrl, void *token, int noisy) |
1430 | 0 | { |
1431 | 0 | KEYRING_HANDLE hd; |
1432 | 0 | KEYDB_SEARCH_DESC desc; |
1433 | 0 | KBNODE keyblock = NULL, node; |
1434 | 0 | const char *lastresname = NULL, *resname; |
1435 | 0 | IOBUF tmpfp = NULL; |
1436 | 0 | char *tmpfilename = NULL; |
1437 | 0 | char *bakfilename = NULL; |
1438 | 0 | int rc; |
1439 | 0 | ulong count = 0, sigcount = 0; |
1440 | |
|
1441 | 0 | hd = keyring_new (token); |
1442 | 0 | if (!hd) |
1443 | 0 | return gpg_error_from_syserror (); |
1444 | 0 | memset (&desc, 0, sizeof desc); |
1445 | 0 | desc.mode = KEYDB_SEARCH_MODE_FIRST; |
1446 | |
|
1447 | 0 | rc=keyring_lock (hd, 1); |
1448 | 0 | if(rc) |
1449 | 0 | goto leave; |
1450 | | |
1451 | 0 | for (;;) |
1452 | 0 | { |
1453 | 0 | rc = keyring_search (hd, &desc, 1, NULL, 1 /* ignore_legacy */); |
1454 | 0 | if (rc) |
1455 | 0 | break; /* ready. */ |
1456 | | |
1457 | 0 | desc.mode = KEYDB_SEARCH_MODE_NEXT; |
1458 | 0 | resname = keyring_get_resource_name (hd); |
1459 | 0 | if (lastresname != resname ) |
1460 | 0 | { /* we have switched to a new keyring - commit changes */ |
1461 | 0 | if (tmpfp) |
1462 | 0 | { |
1463 | 0 | if (iobuf_close (tmpfp)) |
1464 | 0 | { |
1465 | 0 | rc = gpg_error_from_syserror (); |
1466 | 0 | log_error ("error closing '%s': %s\n", |
1467 | 0 | tmpfilename, strerror (errno)); |
1468 | 0 | goto leave; |
1469 | 0 | } |
1470 | | /* because we have switched resources, we can be sure that |
1471 | | * the original file is closed */ |
1472 | 0 | tmpfp = NULL; |
1473 | 0 | } |
1474 | | /* Static analyzer note: BAKFILENAME is never NULL here |
1475 | | because it is controlled by LASTRESNAME. */ |
1476 | 0 | rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, |
1477 | 0 | lastresname) : 0; |
1478 | 0 | xfree (tmpfilename); tmpfilename = NULL; |
1479 | 0 | xfree (bakfilename); bakfilename = NULL; |
1480 | 0 | if (rc) |
1481 | 0 | goto leave; |
1482 | 0 | lastresname = resname; |
1483 | 0 | if (noisy && !opt.quiet) |
1484 | 0 | log_info (_("caching keyring '%s'\n"), resname); |
1485 | 0 | rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp); |
1486 | 0 | if (rc) |
1487 | 0 | goto leave; |
1488 | 0 | } |
1489 | | |
1490 | 0 | release_kbnode (keyblock); |
1491 | 0 | rc = keyring_get_keyblock (hd, &keyblock); |
1492 | 0 | if (rc) |
1493 | 0 | { |
1494 | 0 | if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) |
1495 | 0 | continue; /* Skip legacy keys. */ |
1496 | 0 | log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc)); |
1497 | 0 | goto leave; |
1498 | 0 | } |
1499 | 0 | if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY) |
1500 | 0 | { |
1501 | | /* We had a few reports about corrupted keyrings; if we have |
1502 | | been called directly from the command line we delete such |
1503 | | a keyblock instead of bailing out. */ |
1504 | 0 | log_error ("unexpected keyblock found (pkttype=%d)%s\n", |
1505 | 0 | keyblock->pkt->pkttype, noisy? " - deleted":""); |
1506 | 0 | if (noisy) |
1507 | 0 | continue; |
1508 | 0 | log_info ("Hint: backup your keys and try running '%s'\n", |
1509 | 0 | "gpg --rebuild-keydb-caches"); |
1510 | 0 | rc = gpg_error (GPG_ERR_INV_KEYRING); |
1511 | 0 | goto leave; |
1512 | 0 | } |
1513 | | |
1514 | 0 | if (keyblock->pkt->pkt.public_key->version < 4) |
1515 | 0 | { |
1516 | | /* We do not copy/cache v3 keys or any other unknown |
1517 | | packets. It is better to remove them from the keyring. |
1518 | | The code required to keep them in the keyring would be |
1519 | | too complicated. Given that we do not touch the old |
1520 | | secring.gpg a suitable backup for decryption of v3 stuff |
1521 | | using an older gpg version will always be available. |
1522 | | Note: This test is actually superfluous because we |
1523 | | already acted upon GPG_ERR_LEGACY_KEY. */ |
1524 | 0 | } |
1525 | 0 | else |
1526 | 0 | { |
1527 | | /* Check all signature to set the signature's cache flags. */ |
1528 | 0 | for (node=keyblock; node; node=node->next) |
1529 | 0 | { |
1530 | | /* Note that this doesn't cache the result of a |
1531 | | revocation issued by a designated revoker. This is |
1532 | | because the pk in question does not carry the revkeys |
1533 | | as we haven't merged the key and selfsigs. It is |
1534 | | questionable whether this matters very much since |
1535 | | there are very very few designated revoker revocation |
1536 | | packets out there. */ |
1537 | 0 | if (node->pkt->pkttype == PKT_SIGNATURE) |
1538 | 0 | { |
1539 | 0 | PKT_signature *sig=node->pkt->pkt.signature; |
1540 | |
|
1541 | 0 | if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid |
1542 | 0 | && (openpgp_md_test_algo(sig->digest_algo) |
1543 | 0 | || openpgp_pk_test_algo(sig->pubkey_algo))) |
1544 | 0 | sig->flags.checked=sig->flags.valid=0; |
1545 | 0 | else |
1546 | 0 | check_key_signature (ctrl, keyblock, node, NULL); |
1547 | |
|
1548 | 0 | sigcount++; |
1549 | 0 | } |
1550 | 0 | } |
1551 | | |
1552 | | /* Write the keyblock to the temporary file. */ |
1553 | 0 | rc = write_keyblock (tmpfp, keyblock); |
1554 | 0 | if (rc) |
1555 | 0 | goto leave; |
1556 | | |
1557 | 0 | if ( !(++count % 50) && noisy && !opt.quiet) |
1558 | 0 | log_info (ngettext("%lu keys cached so far (%lu signature)\n", |
1559 | 0 | "%lu keys cached so far (%lu signatures)\n", |
1560 | 0 | sigcount), |
1561 | 0 | count, sigcount); |
1562 | 0 | } |
1563 | 0 | } /* end main loop */ |
1564 | 0 | if (rc == -1) |
1565 | 0 | rc = 0; |
1566 | 0 | if (rc) |
1567 | 0 | { |
1568 | 0 | log_error ("keyring_search failed: %s\n", gpg_strerror (rc)); |
1569 | 0 | goto leave; |
1570 | 0 | } |
1571 | | |
1572 | 0 | if (noisy || opt.verbose) |
1573 | 0 | { |
1574 | 0 | log_info (ngettext("%lu key cached", |
1575 | 0 | "%lu keys cached", count), count); |
1576 | 0 | log_printf (ngettext(" (%lu signature)\n", |
1577 | 0 | " (%lu signatures)\n", sigcount), sigcount); |
1578 | 0 | } |
1579 | |
|
1580 | 0 | if (tmpfp) |
1581 | 0 | { |
1582 | 0 | if (iobuf_close (tmpfp)) |
1583 | 0 | { |
1584 | 0 | rc = gpg_error_from_syserror (); |
1585 | 0 | log_error ("error closing '%s': %s\n", |
1586 | 0 | tmpfilename, strerror (errno)); |
1587 | 0 | goto leave; |
1588 | 0 | } |
1589 | | /* because we have switched resources, we can be sure that |
1590 | | * the original file is closed */ |
1591 | 0 | tmpfp = NULL; |
1592 | 0 | } |
1593 | 0 | rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, |
1594 | 0 | lastresname) : 0; |
1595 | 0 | xfree (tmpfilename); tmpfilename = NULL; |
1596 | 0 | xfree (bakfilename); bakfilename = NULL; |
1597 | |
|
1598 | 0 | leave: |
1599 | 0 | if (tmpfp) |
1600 | 0 | iobuf_cancel (tmpfp); |
1601 | 0 | xfree (tmpfilename); |
1602 | 0 | xfree (bakfilename); |
1603 | 0 | release_kbnode (keyblock); |
1604 | 0 | keyring_fp_close (hd); |
1605 | 0 | keyring_lock (hd, 0); |
1606 | 0 | keyring_release (hd); |
1607 | 0 | return rc; |
1608 | 0 | } |
1609 | | |
1610 | | |
1611 | | |
1612 | | /**************** |
1613 | | * Perform insert/delete/update operation. |
1614 | | * mode 1 = insert |
1615 | | * 2 = delete |
1616 | | * 3 = update |
1617 | | */ |
1618 | | static int |
1619 | | do_copy (int mode, const char *fname, KBNODE root, |
1620 | | off_t start_offset, unsigned int n_packets ) |
1621 | 0 | { |
1622 | 0 | gpg_err_code_t ec; |
1623 | 0 | IOBUF fp, newfp; |
1624 | 0 | int rc=0; |
1625 | 0 | char *bakfname = NULL; |
1626 | 0 | char *tmpfname = NULL; |
1627 | | |
1628 | | /* Open the source file. Because we do a rename, we have to check the |
1629 | | permissions of the file */ |
1630 | 0 | if ((ec = gnupg_access (fname, W_OK))) |
1631 | 0 | return gpg_error (ec); |
1632 | | |
1633 | 0 | fp = iobuf_open (fname); |
1634 | 0 | if (mode == 1 && !fp && errno == ENOENT) { |
1635 | | /* insert mode but file does not exist: create a new file */ |
1636 | 0 | KBNODE kbctx, node; |
1637 | 0 | mode_t oldmask; |
1638 | |
|
1639 | 0 | oldmask=umask(077); |
1640 | 0 | if (is_secured_filename (fname)) { |
1641 | 0 | newfp = NULL; |
1642 | 0 | gpg_err_set_errno (EPERM); |
1643 | 0 | } |
1644 | 0 | else |
1645 | 0 | newfp = iobuf_create (fname, 1); |
1646 | 0 | umask(oldmask); |
1647 | 0 | if( !newfp ) |
1648 | 0 | { |
1649 | 0 | rc = gpg_error_from_syserror (); |
1650 | 0 | log_error (_("can't create '%s': %s\n"), fname, strerror(errno)); |
1651 | 0 | return rc; |
1652 | 0 | } |
1653 | 0 | if( !opt.quiet ) |
1654 | 0 | log_info(_("%s: keyring created\n"), fname ); |
1655 | |
|
1656 | 0 | kbctx=NULL; |
1657 | 0 | while ( (node = walk_kbnode( root, &kbctx, 0 )) ) { |
1658 | 0 | if( (rc = build_packet( newfp, node->pkt )) ) { |
1659 | 0 | log_error("build_packet(%d) failed: %s\n", |
1660 | 0 | node->pkt->pkttype, gpg_strerror (rc) ); |
1661 | 0 | iobuf_cancel(newfp); |
1662 | 0 | return rc; |
1663 | 0 | } |
1664 | 0 | } |
1665 | 0 | if( iobuf_close(newfp) ) { |
1666 | 0 | rc = gpg_error_from_syserror (); |
1667 | 0 | log_error ("%s: close failed: %s\n", fname, strerror(errno)); |
1668 | 0 | return rc; |
1669 | 0 | } |
1670 | 0 | return 0; /* ready */ |
1671 | 0 | } |
1672 | | |
1673 | 0 | if( !fp ) |
1674 | 0 | { |
1675 | 0 | rc = gpg_error_from_syserror (); |
1676 | 0 | log_error(_("can't open '%s': %s\n"), fname, strerror(errno) ); |
1677 | 0 | goto leave; |
1678 | 0 | } |
1679 | | |
1680 | | /* Create the new file. */ |
1681 | 0 | rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); |
1682 | 0 | if (rc) { |
1683 | 0 | iobuf_close(fp); |
1684 | 0 | goto leave; |
1685 | 0 | } |
1686 | | |
1687 | 0 | if( mode == 1 ) { /* insert */ |
1688 | | /* copy everything to the new file */ |
1689 | 0 | rc = copy_all_packets (fp, newfp); |
1690 | 0 | if( rc != -1 ) { |
1691 | 0 | log_error("%s: copy to '%s' failed: %s\n", |
1692 | 0 | fname, tmpfname, gpg_strerror (rc) ); |
1693 | 0 | iobuf_close(fp); |
1694 | 0 | iobuf_cancel(newfp); |
1695 | 0 | goto leave; |
1696 | 0 | } |
1697 | 0 | } |
1698 | | |
1699 | 0 | if( mode == 2 || mode == 3 ) { /* delete or update */ |
1700 | | /* copy first part to the new file */ |
1701 | 0 | rc = copy_some_packets( fp, newfp, start_offset ); |
1702 | 0 | if( rc ) { /* should never get EOF here */ |
1703 | 0 | log_error ("%s: copy to '%s' failed: %s\n", |
1704 | 0 | fname, tmpfname, gpg_strerror (rc) ); |
1705 | 0 | iobuf_close(fp); |
1706 | 0 | iobuf_cancel(newfp); |
1707 | 0 | goto leave; |
1708 | 0 | } |
1709 | | /* skip this keyblock */ |
1710 | 0 | log_assert( n_packets ); |
1711 | 0 | rc = skip_some_packets( fp, n_packets ); |
1712 | 0 | if( rc ) { |
1713 | 0 | log_error("%s: skipping %u packets failed: %s\n", |
1714 | 0 | fname, n_packets, gpg_strerror (rc)); |
1715 | 0 | iobuf_close(fp); |
1716 | 0 | iobuf_cancel(newfp); |
1717 | 0 | goto leave; |
1718 | 0 | } |
1719 | 0 | } |
1720 | | |
1721 | 0 | if( mode == 1 || mode == 3 ) { /* insert or update */ |
1722 | 0 | rc = write_keyblock (newfp, root); |
1723 | 0 | if (rc) { |
1724 | 0 | iobuf_close(fp); |
1725 | 0 | iobuf_cancel(newfp); |
1726 | 0 | goto leave; |
1727 | 0 | } |
1728 | 0 | } |
1729 | | |
1730 | 0 | if( mode == 2 || mode == 3 ) { /* delete or update */ |
1731 | | /* copy the rest */ |
1732 | 0 | rc = copy_all_packets( fp, newfp ); |
1733 | 0 | if( rc != -1 ) { |
1734 | 0 | log_error("%s: copy to '%s' failed: %s\n", |
1735 | 0 | fname, tmpfname, gpg_strerror (rc) ); |
1736 | 0 | iobuf_close(fp); |
1737 | 0 | iobuf_cancel(newfp); |
1738 | 0 | goto leave; |
1739 | 0 | } |
1740 | 0 | } |
1741 | | |
1742 | | /* close both files */ |
1743 | 0 | if( iobuf_close(fp) ) { |
1744 | 0 | rc = gpg_error_from_syserror (); |
1745 | 0 | log_error("%s: close failed: %s\n", fname, strerror(errno) ); |
1746 | 0 | goto leave; |
1747 | 0 | } |
1748 | 0 | if( iobuf_close(newfp) ) { |
1749 | 0 | rc = gpg_error_from_syserror (); |
1750 | 0 | log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); |
1751 | 0 | goto leave; |
1752 | 0 | } |
1753 | | |
1754 | 0 | rc = rename_tmp_file (bakfname, tmpfname, fname); |
1755 | |
|
1756 | 0 | leave: |
1757 | 0 | xfree(bakfname); |
1758 | 0 | xfree(tmpfname); |
1759 | 0 | return rc; |
1760 | 0 | } |