Line data Source code
1 : /* keydb.c - key database dispatcher
2 : * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
3 : * Copyright (C) 2014 g10 Code GmbH
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 <assert.h>
27 : #include <sys/types.h>
28 : #include <sys/stat.h>
29 : #include <unistd.h>
30 :
31 : #include "gpgsm.h"
32 : #include "../kbx/keybox.h"
33 : #include "keydb.h"
34 : #include "i18n.h"
35 :
36 : static int active_handles;
37 :
38 : typedef enum {
39 : KEYDB_RESOURCE_TYPE_NONE = 0,
40 : KEYDB_RESOURCE_TYPE_KEYBOX
41 : } KeydbResourceType;
42 : #define MAX_KEYDB_RESOURCES 20
43 :
44 : struct resource_item {
45 : KeydbResourceType type;
46 : union {
47 : KEYBOX_HANDLE kr;
48 : } u;
49 : void *token;
50 : dotlock_t lockhandle;
51 : };
52 :
53 : static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
54 : static int used_resources;
55 :
56 : /* Whether we have successfully registered any resource. */
57 : static int any_registered;
58 :
59 :
60 : struct keydb_handle {
61 : int locked;
62 : int found;
63 : int saved_found;
64 : int current;
65 : int is_ephemeral;
66 : int used; /* items in active */
67 : struct resource_item active[MAX_KEYDB_RESOURCES];
68 : };
69 :
70 :
71 : static int lock_all (KEYDB_HANDLE hd);
72 : static void unlock_all (KEYDB_HANDLE hd);
73 :
74 :
75 : static void
76 0 : try_make_homedir (const char *fname)
77 : {
78 0 : const char *defhome = standard_homedir ();
79 :
80 : /* Create the directory only if the supplied directory name is the
81 : same as the default one. This way we avoid to create arbitrary
82 : directories when a non-default home directory is used. To cope
83 : with HOME, we do compare only the suffix if we see that the
84 : default homedir does start with a tilde. */
85 0 : if ( opt.dry_run || opt.no_homedir_creation )
86 0 : return;
87 :
88 0 : if (
89 : #ifdef HAVE_W32_SYSTEM
90 : ( !compare_filenames (fname, defhome) )
91 : #else
92 0 : ( *defhome == '~'
93 0 : && (strlen(fname) >= strlen (defhome+1)
94 0 : && !strcmp(fname+strlen(fname)-strlen(defhome+1), defhome+1 ) ))
95 0 : || (*defhome != '~' && !compare_filenames( fname, defhome ) )
96 : #endif
97 : )
98 : {
99 0 : if (gnupg_mkdir (fname, "-rwx"))
100 0 : log_info (_("can't create directory '%s': %s\n"),
101 0 : fname, strerror(errno) );
102 0 : else if (!opt.quiet )
103 0 : log_info (_("directory '%s' created\n"), fname);
104 : }
105 : }
106 :
107 :
108 : /* Handle the creation of a keybox if it does not yet exist. Take
109 : into acount that other processes might have the keybox already
110 : locked. This lock check does not work if the directory itself is
111 : not yet available. If R_CREATED is not NULL it will be set to true
112 : if the function created a new keybox. */
113 : static gpg_error_t
114 3 : maybe_create_keybox (char *filename, int force, int *r_created)
115 : {
116 3 : dotlock_t lockhd = NULL;
117 : FILE *fp;
118 : int rc;
119 : mode_t oldmask;
120 : char *last_slash_in_filename;
121 : int save_slash;
122 :
123 3 : if (r_created)
124 3 : *r_created = 0;
125 :
126 : /* A quick test whether the filename already exists. */
127 3 : if (!access (filename, F_OK))
128 2 : return !access (filename, R_OK)? 0 : gpg_error (GPG_ERR_EACCES);
129 :
130 : /* If we don't want to create a new file at all, there is no need to
131 : go any further - bail out right here. */
132 1 : if (!force)
133 0 : return gpg_error (GPG_ERR_ENOENT);
134 :
135 : /* First of all we try to create the home directory. Note, that we
136 : don't do any locking here because any sane application of gpg
137 : would create the home directory by itself and not rely on gpg's
138 : tricky auto-creation which is anyway only done for some home
139 : directory name patterns. */
140 1 : last_slash_in_filename = strrchr (filename, DIRSEP_C);
141 : #if HAVE_W32_SYSTEM
142 : {
143 : /* Windows may either have a slash or a backslash. Take care of it. */
144 : char *p = strrchr (filename, '/');
145 : if (!last_slash_in_filename || p > last_slash_in_filename)
146 : last_slash_in_filename = p;
147 : }
148 : #endif /*HAVE_W32_SYSTEM*/
149 1 : if (!last_slash_in_filename)
150 0 : return gpg_error (GPG_ERR_ENOENT); /* No slash at all - should
151 : not happen though. */
152 1 : save_slash = *last_slash_in_filename;
153 1 : *last_slash_in_filename = 0;
154 1 : if (access(filename, F_OK))
155 : {
156 : static int tried;
157 :
158 0 : if (!tried)
159 : {
160 0 : tried = 1;
161 0 : try_make_homedir (filename);
162 : }
163 0 : if (access (filename, F_OK))
164 : {
165 0 : rc = gpg_error_from_syserror ();
166 0 : *last_slash_in_filename = save_slash;
167 0 : goto leave;
168 : }
169 : }
170 1 : *last_slash_in_filename = save_slash;
171 :
172 : /* To avoid races with other instances of gpg trying to create or
173 : update the keybox (it is removed during an update for a short
174 : time), we do the next stuff in a locked state. */
175 1 : lockhd = dotlock_create (filename, 0);
176 1 : if (!lockhd)
177 : {
178 : /* A reason for this to fail is that the directory is not
179 : writable. However, this whole locking stuff does not make
180 : sense if this is the case. An empty non-writable directory
181 : with no keyring is not really useful at all. */
182 0 : if (opt.verbose)
183 0 : log_info ("can't allocate lock for '%s'\n", filename );
184 :
185 0 : if (!force)
186 0 : return gpg_error (GPG_ERR_ENOENT);
187 : else
188 0 : return gpg_error (GPG_ERR_GENERAL);
189 : }
190 :
191 1 : if ( dotlock_take (lockhd, -1) )
192 : {
193 : /* This is something bad. Probably a stale lockfile. */
194 0 : log_info ("can't lock '%s'\n", filename);
195 0 : rc = gpg_error (GPG_ERR_GENERAL);
196 0 : goto leave;
197 : }
198 :
199 : /* Now the real test while we are locked. */
200 1 : if (!access(filename, F_OK))
201 : {
202 0 : rc = 0; /* Okay, we may access the file now. */
203 0 : goto leave;
204 : }
205 :
206 : /* The file does not yet exist, create it now. */
207 1 : oldmask = umask (077);
208 1 : fp = fopen (filename, "w");
209 1 : if (!fp)
210 : {
211 0 : rc = gpg_error_from_syserror ();
212 0 : umask (oldmask);
213 0 : log_error (_("error creating keybox '%s': %s\n"),
214 : filename, gpg_strerror (rc));
215 0 : goto leave;
216 : }
217 1 : umask (oldmask);
218 :
219 : /* Make sure that at least one record is in a new keybox file, so
220 : that the detection magic for OpenPGP keyboxes works the next time
221 : it is used. */
222 1 : rc = _keybox_write_header_blob (fp, 0);
223 1 : if (rc)
224 : {
225 0 : fclose (fp);
226 0 : log_error (_("error creating keybox '%s': %s\n"),
227 : filename, gpg_strerror (rc));
228 0 : goto leave;
229 : }
230 :
231 1 : if (!opt.quiet)
232 1 : log_info (_("keybox '%s' created\n"), filename);
233 1 : if (r_created)
234 1 : *r_created = 1;
235 :
236 1 : fclose (fp);
237 1 : rc = 0;
238 :
239 : leave:
240 1 : if (lockhd)
241 : {
242 1 : dotlock_release (lockhd);
243 1 : dotlock_destroy (lockhd);
244 : }
245 1 : return rc;
246 : }
247 :
248 :
249 : /*
250 : * Register a resource (which currently may only be a keybox file).
251 : * The first keybox which is added by this function is created if it
252 : * does not exist. If AUTO_CREATED is not NULL it will be set to true
253 : * if the function has created a new keybox.
254 : */
255 : gpg_error_t
256 3 : keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created)
257 : {
258 3 : const char *resname = url;
259 3 : char *filename = NULL;
260 3 : gpg_error_t err = 0;
261 3 : KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
262 :
263 3 : if (auto_created)
264 3 : *auto_created = 0;
265 :
266 : /* Do we have an URL?
267 : gnupg-kbx:filename := this is a plain keybox
268 : filename := See what is is, but create as plain keybox.
269 : */
270 3 : if (strlen (resname) > 10)
271 : {
272 3 : if (!strncmp (resname, "gnupg-kbx:", 10) )
273 : {
274 0 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
275 0 : resname += 10;
276 : }
277 : #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
278 3 : else if (strchr (resname, ':'))
279 : {
280 0 : log_error ("invalid key resource URL '%s'\n", url );
281 0 : err = gpg_error (GPG_ERR_GENERAL);
282 0 : goto leave;
283 : }
284 : #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
285 : }
286 :
287 3 : if (*resname != DIRSEP_C )
288 : { /* do tilde expansion etc */
289 3 : if (strchr(resname, DIRSEP_C) )
290 0 : filename = make_filename (resname, NULL);
291 : else
292 3 : filename = make_filename (gnupg_homedir (), resname, NULL);
293 : }
294 : else
295 0 : filename = xstrdup (resname);
296 :
297 3 : if (!force)
298 3 : force = !any_registered;
299 :
300 : /* see whether we can determine the filetype */
301 3 : if (rt == KEYDB_RESOURCE_TYPE_NONE)
302 : {
303 3 : FILE *fp = fopen( filename, "rb" );
304 :
305 3 : if (fp)
306 : {
307 : u32 magic;
308 :
309 : /* FIXME: check for the keybox magic */
310 2 : if (fread (&magic, 4, 1, fp) == 1 )
311 : {
312 2 : if (magic == 0x13579ace || magic == 0xce9a5713)
313 : ; /* GDBM magic - no more support */
314 : else
315 2 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
316 : }
317 : else /* maybe empty: assume keybox */
318 0 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
319 2 : fclose (fp);
320 : }
321 : else /* no file yet: create keybox */
322 1 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
323 : }
324 :
325 3 : switch (rt)
326 : {
327 : case KEYDB_RESOURCE_TYPE_NONE:
328 0 : log_error ("unknown type of key resource '%s'\n", url );
329 0 : err = gpg_error (GPG_ERR_GENERAL);
330 0 : goto leave;
331 :
332 : case KEYDB_RESOURCE_TYPE_KEYBOX:
333 3 : err = maybe_create_keybox (filename, force, auto_created);
334 3 : if (err)
335 0 : goto leave;
336 : /* Now register the file */
337 : {
338 : void *token;
339 :
340 3 : err = keybox_register_file (filename, 0, &token);
341 3 : if (gpg_err_code (err) == GPG_ERR_EEXIST)
342 : ; /* Already registered - ignore. */
343 3 : else if (err)
344 : ; /* Other error. */
345 3 : else if (used_resources >= MAX_KEYDB_RESOURCES)
346 0 : err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
347 : else
348 : {
349 3 : all_resources[used_resources].type = rt;
350 3 : all_resources[used_resources].u.kr = NULL; /* Not used here */
351 3 : all_resources[used_resources].token = token;
352 :
353 3 : all_resources[used_resources].lockhandle
354 3 : = dotlock_create (filename, 0);
355 3 : if (!all_resources[used_resources].lockhandle)
356 0 : log_fatal ( _("can't create lock for '%s'\n"), filename);
357 :
358 : /* Do a compress run if needed and the file is not locked. */
359 3 : if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
360 : {
361 3 : KEYBOX_HANDLE kbxhd = keybox_new_x509 (token, 0);
362 :
363 3 : if (kbxhd)
364 : {
365 3 : keybox_compress (kbxhd);
366 3 : keybox_release (kbxhd);
367 : }
368 3 : dotlock_release (all_resources[used_resources].lockhandle);
369 : }
370 :
371 3 : used_resources++;
372 : }
373 : }
374 3 : break;
375 :
376 : default:
377 0 : log_error ("resource type of '%s' not supported\n", url);
378 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
379 0 : goto leave;
380 : }
381 :
382 : /* fixme: check directory permissions and print a warning */
383 :
384 : leave:
385 3 : if (err)
386 : {
387 0 : log_error ("keyblock resource '%s': %s\n", filename, gpg_strerror (err));
388 0 : gpgsm_status_with_error (ctrl, STATUS_ERROR,
389 : "add_keyblock_resource", err);
390 : }
391 : else
392 3 : any_registered = 1;
393 3 : xfree (filename);
394 3 : return err;
395 : }
396 :
397 :
398 : KEYDB_HANDLE
399 9 : keydb_new (void)
400 : {
401 : KEYDB_HANDLE hd;
402 : int i, j;
403 :
404 9 : hd = xcalloc (1, sizeof *hd);
405 9 : hd->found = -1;
406 9 : hd->saved_found = -1;
407 :
408 9 : assert (used_resources <= MAX_KEYDB_RESOURCES);
409 18 : for (i=j=0; i < used_resources; i++)
410 : {
411 9 : switch (all_resources[i].type)
412 : {
413 : case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
414 0 : break;
415 : case KEYDB_RESOURCE_TYPE_KEYBOX:
416 9 : hd->active[j].type = all_resources[i].type;
417 9 : hd->active[j].token = all_resources[i].token;
418 9 : hd->active[j].lockhandle = all_resources[i].lockhandle;
419 9 : hd->active[j].u.kr = keybox_new_x509 (all_resources[i].token, 0);
420 9 : if (!hd->active[j].u.kr)
421 : {
422 0 : xfree (hd);
423 0 : return NULL; /* fixme: release all previously allocated handles*/
424 : }
425 9 : j++;
426 9 : break;
427 : }
428 : }
429 9 : hd->used = j;
430 :
431 9 : active_handles++;
432 9 : return hd;
433 : }
434 :
435 : void
436 9 : keydb_release (KEYDB_HANDLE hd)
437 : {
438 : int i;
439 :
440 9 : if (!hd)
441 9 : return;
442 9 : assert (active_handles > 0);
443 9 : active_handles--;
444 :
445 9 : unlock_all (hd);
446 18 : for (i=0; i < hd->used; i++)
447 : {
448 9 : switch (hd->active[i].type)
449 : {
450 : case KEYDB_RESOURCE_TYPE_NONE:
451 0 : break;
452 : case KEYDB_RESOURCE_TYPE_KEYBOX:
453 9 : keybox_release (hd->active[i].u.kr);
454 9 : break;
455 : }
456 : }
457 :
458 9 : xfree (hd);
459 : }
460 :
461 :
462 : /* Return the name of the current resource. This is function first
463 : looks for the last found found, then for the current search
464 : position, and last returns the first available resource. The
465 : returned string is only valid as long as the handle exists. This
466 : function does only return NULL if no handle is specified, in all
467 : other error cases an empty string is returned. */
468 : const char *
469 0 : keydb_get_resource_name (KEYDB_HANDLE hd)
470 : {
471 : int idx;
472 0 : const char *s = NULL;
473 :
474 0 : if (!hd)
475 0 : return NULL;
476 :
477 0 : if ( hd->found >= 0 && hd->found < hd->used)
478 0 : idx = hd->found;
479 0 : else if ( hd->current >= 0 && hd->current < hd->used)
480 0 : idx = hd->current;
481 : else
482 0 : idx = 0;
483 :
484 0 : switch (hd->active[idx].type)
485 : {
486 : case KEYDB_RESOURCE_TYPE_NONE:
487 0 : s = NULL;
488 0 : break;
489 : case KEYDB_RESOURCE_TYPE_KEYBOX:
490 0 : s = keybox_get_resource_name (hd->active[idx].u.kr);
491 0 : break;
492 : }
493 :
494 0 : return s? s: "";
495 : }
496 :
497 : /* Switch the handle into ephemeral mode and return the original value. */
498 : int
499 6 : keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
500 : {
501 : int i;
502 :
503 6 : if (!hd)
504 0 : return 0;
505 :
506 6 : yes = !!yes;
507 6 : if (hd->is_ephemeral != yes)
508 : {
509 12 : for (i=0; i < hd->used; i++)
510 : {
511 6 : switch (hd->active[i].type)
512 : {
513 : case KEYDB_RESOURCE_TYPE_NONE:
514 0 : break;
515 : case KEYDB_RESOURCE_TYPE_KEYBOX:
516 6 : keybox_set_ephemeral (hd->active[i].u.kr, yes);
517 6 : break;
518 : }
519 : }
520 : }
521 :
522 6 : i = hd->is_ephemeral;
523 6 : hd->is_ephemeral = yes;
524 6 : return i;
525 : }
526 :
527 :
528 : /* If the keyring has not yet been locked, lock it now. This
529 : operation is required before any update operation; it is optional
530 : for an insert operation. The lock is released with
531 : keydb_released. */
532 : gpg_error_t
533 0 : keydb_lock (KEYDB_HANDLE hd)
534 : {
535 0 : if (!hd)
536 0 : return gpg_error (GPG_ERR_INV_HANDLE);
537 0 : if (hd->locked)
538 0 : return 0; /* Already locked. */
539 0 : return lock_all (hd);
540 : }
541 :
542 :
543 :
544 : static int
545 3 : lock_all (KEYDB_HANDLE hd)
546 : {
547 3 : int i, rc = 0;
548 :
549 : /* Fixme: This locking scheme may lead to deadlock if the resources
550 : are not added in the same order by all processes. We are
551 : currently only allowing one resource so it is not a problem. */
552 6 : for (i=0; i < hd->used; i++)
553 : {
554 3 : switch (hd->active[i].type)
555 : {
556 : case KEYDB_RESOURCE_TYPE_NONE:
557 0 : break;
558 : case KEYDB_RESOURCE_TYPE_KEYBOX:
559 3 : if (hd->active[i].lockhandle)
560 3 : rc = dotlock_take (hd->active[i].lockhandle, -1);
561 3 : break;
562 : }
563 3 : if (rc)
564 0 : break;
565 : }
566 :
567 3 : if (rc)
568 : {
569 : /* revert the already set locks */
570 0 : for (i--; i >= 0; i--)
571 : {
572 0 : switch (hd->active[i].type)
573 : {
574 : case KEYDB_RESOURCE_TYPE_NONE:
575 0 : break;
576 : case KEYDB_RESOURCE_TYPE_KEYBOX:
577 0 : if (hd->active[i].lockhandle)
578 0 : dotlock_release (hd->active[i].lockhandle);
579 0 : break;
580 : }
581 : }
582 : }
583 : else
584 3 : hd->locked = 1;
585 :
586 : /* make_dotlock () does not yet guarantee that errno is set, thus
587 : we can't rely on the error reason and will simply use
588 : EACCES. */
589 3 : return rc? gpg_error (GPG_ERR_EACCES) : 0;
590 : }
591 :
592 : static void
593 12 : unlock_all (KEYDB_HANDLE hd)
594 : {
595 : int i;
596 :
597 12 : if (!hd->locked)
598 21 : return;
599 :
600 6 : for (i=hd->used-1; i >= 0; i--)
601 : {
602 3 : switch (hd->active[i].type)
603 : {
604 : case KEYDB_RESOURCE_TYPE_NONE:
605 0 : break;
606 : case KEYDB_RESOURCE_TYPE_KEYBOX:
607 3 : if (hd->active[i].lockhandle)
608 3 : dotlock_release (hd->active[i].lockhandle);
609 3 : break;
610 : }
611 : }
612 3 : hd->locked = 0;
613 : }
614 :
615 :
616 :
617 : /* Push the last found state if any. */
618 : void
619 0 : keydb_push_found_state (KEYDB_HANDLE hd)
620 : {
621 0 : if (!hd)
622 0 : return;
623 :
624 0 : if (hd->found < 0 || hd->found >= hd->used)
625 : {
626 0 : hd->saved_found = -1;
627 0 : return;
628 : }
629 :
630 0 : switch (hd->active[hd->found].type)
631 : {
632 : case KEYDB_RESOURCE_TYPE_NONE:
633 0 : break;
634 : case KEYDB_RESOURCE_TYPE_KEYBOX:
635 0 : keybox_push_found_state (hd->active[hd->found].u.kr);
636 0 : break;
637 : }
638 :
639 0 : hd->saved_found = hd->found;
640 0 : hd->found = -1;
641 : }
642 :
643 :
644 : /* Pop the last found state. */
645 : void
646 0 : keydb_pop_found_state (KEYDB_HANDLE hd)
647 : {
648 0 : if (!hd)
649 0 : return;
650 :
651 0 : hd->found = hd->saved_found;
652 0 : hd->saved_found = -1;
653 0 : if (hd->found < 0 || hd->found >= hd->used)
654 0 : return;
655 :
656 0 : switch (hd->active[hd->found].type)
657 : {
658 : case KEYDB_RESOURCE_TYPE_NONE:
659 0 : break;
660 : case KEYDB_RESOURCE_TYPE_KEYBOX:
661 0 : keybox_pop_found_state (hd->active[hd->found].u.kr);
662 0 : break;
663 : }
664 : }
665 :
666 :
667 :
668 : /*
669 : Return the last found object. Caller must free it. The returned
670 : keyblock has the kbode flag bit 0 set for the node with the public
671 : key used to locate the keyblock or flag bit 1 set for the user ID
672 : node. */
673 : int
674 0 : keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
675 : {
676 0 : int rc = 0;
677 :
678 0 : if (!hd)
679 0 : return gpg_error (GPG_ERR_INV_VALUE);
680 :
681 0 : if ( hd->found < 0 || hd->found >= hd->used)
682 0 : return -1; /* nothing found */
683 :
684 0 : switch (hd->active[hd->found].type)
685 : {
686 : case KEYDB_RESOURCE_TYPE_NONE:
687 0 : rc = gpg_error (GPG_ERR_GENERAL); /* oops */
688 0 : break;
689 : case KEYDB_RESOURCE_TYPE_KEYBOX:
690 0 : rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
691 0 : break;
692 : }
693 :
694 0 : return rc;
695 : }
696 :
697 : /* Return a flag of the last found object. WHICH is the flag requested;
698 : it should be one of the KEYBOX_FLAG_ values. If the operation is
699 : successful, the flag value will be stored at the address given by
700 : VALUE. Return 0 on success or an error code. */
701 : gpg_error_t
702 0 : keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
703 : {
704 0 : int err = 0;
705 :
706 0 : if (!hd)
707 0 : return gpg_error (GPG_ERR_INV_VALUE);
708 :
709 0 : if ( hd->found < 0 || hd->found >= hd->used)
710 0 : return gpg_error (GPG_ERR_NOTHING_FOUND);
711 :
712 0 : switch (hd->active[hd->found].type)
713 : {
714 : case KEYDB_RESOURCE_TYPE_NONE:
715 0 : err = gpg_error (GPG_ERR_GENERAL); /* oops */
716 0 : break;
717 : case KEYDB_RESOURCE_TYPE_KEYBOX:
718 0 : err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value);
719 0 : break;
720 : }
721 :
722 0 : return err;
723 : }
724 :
725 : /* Set a flag of the last found object. WHICH is the flag to be set; it
726 : should be one of the KEYBOX_FLAG_ values. If the operation is
727 : successful, the flag value will be stored in the keybox. Note,
728 : that some flag values can't be updated and thus may return an
729 : error, some other flag values may be masked out before an update.
730 : Returns 0 on success or an error code. */
731 : gpg_error_t
732 0 : keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
733 : {
734 0 : int err = 0;
735 :
736 0 : if (!hd)
737 0 : return gpg_error (GPG_ERR_INV_VALUE);
738 :
739 0 : if ( hd->found < 0 || hd->found >= hd->used)
740 0 : return gpg_error (GPG_ERR_NOTHING_FOUND);
741 :
742 0 : if (!hd->locked)
743 0 : return gpg_error (GPG_ERR_NOT_LOCKED);
744 :
745 0 : switch (hd->active[hd->found].type)
746 : {
747 : case KEYDB_RESOURCE_TYPE_NONE:
748 0 : err = gpg_error (GPG_ERR_GENERAL); /* oops */
749 0 : break;
750 : case KEYDB_RESOURCE_TYPE_KEYBOX:
751 0 : err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value);
752 0 : break;
753 : }
754 :
755 0 : return err;
756 : }
757 :
758 : /*
759 : * Insert a new Certificate into one of the resources.
760 : */
761 : int
762 3 : keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
763 : {
764 3 : int rc = -1;
765 : int idx;
766 : unsigned char digest[20];
767 :
768 3 : if (!hd)
769 0 : return gpg_error (GPG_ERR_INV_VALUE);
770 :
771 3 : if (opt.dry_run)
772 0 : return 0;
773 :
774 3 : if ( hd->found >= 0 && hd->found < hd->used)
775 0 : idx = hd->found;
776 3 : else if ( hd->current >= 0 && hd->current < hd->used)
777 3 : idx = hd->current;
778 : else
779 0 : return gpg_error (GPG_ERR_GENERAL);
780 :
781 3 : if (!hd->locked)
782 0 : return gpg_error (GPG_ERR_NOT_LOCKED);
783 :
784 3 : gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
785 :
786 3 : switch (hd->active[idx].type)
787 : {
788 : case KEYDB_RESOURCE_TYPE_NONE:
789 0 : rc = gpg_error (GPG_ERR_GENERAL);
790 0 : break;
791 : case KEYDB_RESOURCE_TYPE_KEYBOX:
792 3 : rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
793 3 : break;
794 : }
795 :
796 3 : unlock_all (hd);
797 3 : return rc;
798 : }
799 :
800 :
801 :
802 : /* Update the current keyblock with KB. */
803 : int
804 0 : keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
805 : {
806 0 : int rc = 0;
807 : unsigned char digest[20];
808 :
809 0 : if (!hd)
810 0 : return gpg_error (GPG_ERR_INV_VALUE);
811 :
812 0 : if ( hd->found < 0 || hd->found >= hd->used)
813 0 : return -1; /* nothing found */
814 :
815 0 : if (opt.dry_run)
816 0 : return 0;
817 :
818 0 : rc = lock_all (hd);
819 0 : if (rc)
820 0 : return rc;
821 :
822 0 : gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
823 :
824 0 : switch (hd->active[hd->found].type)
825 : {
826 : case KEYDB_RESOURCE_TYPE_NONE:
827 0 : rc = gpg_error (GPG_ERR_GENERAL); /* oops */
828 0 : break;
829 : case KEYDB_RESOURCE_TYPE_KEYBOX:
830 0 : rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
831 0 : break;
832 : }
833 :
834 0 : unlock_all (hd);
835 0 : return rc;
836 : }
837 :
838 :
839 : /*
840 : * The current keyblock or cert will be deleted.
841 : */
842 : int
843 0 : keydb_delete (KEYDB_HANDLE hd, int unlock)
844 : {
845 0 : int rc = -1;
846 :
847 0 : if (!hd)
848 0 : return gpg_error (GPG_ERR_INV_VALUE);
849 :
850 0 : if ( hd->found < 0 || hd->found >= hd->used)
851 0 : return -1; /* nothing found */
852 :
853 0 : if( opt.dry_run )
854 0 : return 0;
855 :
856 0 : if (!hd->locked)
857 0 : return gpg_error (GPG_ERR_NOT_LOCKED);
858 :
859 0 : switch (hd->active[hd->found].type)
860 : {
861 : case KEYDB_RESOURCE_TYPE_NONE:
862 0 : rc = gpg_error (GPG_ERR_GENERAL);
863 0 : break;
864 : case KEYDB_RESOURCE_TYPE_KEYBOX:
865 0 : rc = keybox_delete (hd->active[hd->found].u.kr);
866 0 : break;
867 : }
868 :
869 0 : if (unlock)
870 0 : unlock_all (hd);
871 0 : return rc;
872 : }
873 :
874 :
875 :
876 : /*
877 : * Locate the default writable key resource, so that the next
878 : * operation (which is only relevant for inserts) will be done on this
879 : * resource.
880 : */
881 : int
882 3 : keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
883 : {
884 : int rc;
885 :
886 : (void)reserved;
887 :
888 3 : if (!hd)
889 0 : return gpg_error (GPG_ERR_INV_VALUE);
890 :
891 3 : rc = keydb_search_reset (hd); /* this does reset hd->current */
892 3 : if (rc)
893 0 : return rc;
894 :
895 3 : for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
896 : {
897 3 : switch (hd->active[hd->current].type)
898 : {
899 : case KEYDB_RESOURCE_TYPE_NONE:
900 0 : BUG();
901 : break;
902 : case KEYDB_RESOURCE_TYPE_KEYBOX:
903 3 : if (keybox_is_writable (hd->active[hd->current].token))
904 3 : return 0; /* found (hd->current is set to it) */
905 0 : break;
906 : }
907 : }
908 :
909 0 : return -1;
910 : }
911 :
912 : /*
913 : * Rebuild the caches of all key resources.
914 : */
915 : void
916 0 : keydb_rebuild_caches (void)
917 : {
918 : int i;
919 :
920 0 : for (i=0; i < used_resources; i++)
921 : {
922 0 : switch (all_resources[i].type)
923 : {
924 : case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
925 0 : break;
926 : case KEYDB_RESOURCE_TYPE_KEYBOX:
927 : /* rc = keybox_rebuild_cache (all_resources[i].token); */
928 : /* if (rc) */
929 : /* log_error (_("failed to rebuild keybox cache: %s\n"), */
930 : /* g10_errstr (rc)); */
931 0 : break;
932 : }
933 : }
934 0 : }
935 :
936 :
937 :
938 : /*
939 : * Start the next search on this handle right at the beginning
940 : */
941 : gpg_error_t
942 3 : keydb_search_reset (KEYDB_HANDLE hd)
943 : {
944 : int i;
945 3 : gpg_error_t rc = 0;
946 :
947 3 : if (!hd)
948 0 : return gpg_error (GPG_ERR_INV_VALUE);
949 :
950 3 : hd->current = 0;
951 3 : hd->found = -1;
952 : /* and reset all resources */
953 6 : for (i=0; !rc && i < hd->used; i++)
954 : {
955 3 : switch (hd->active[i].type)
956 : {
957 : case KEYDB_RESOURCE_TYPE_NONE:
958 0 : break;
959 : case KEYDB_RESOURCE_TYPE_KEYBOX:
960 3 : rc = keybox_search_reset (hd->active[i].u.kr);
961 3 : break;
962 : }
963 : }
964 3 : return rc;
965 : }
966 :
967 : /*
968 : * Search through all keydb resources, starting at the current position,
969 : * for a keyblock which contains one of the keys described in the DESC array.
970 : */
971 : int
972 3 : keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
973 : KEYDB_SEARCH_DESC *desc, size_t ndesc)
974 : {
975 3 : int rc = -1;
976 : unsigned long skipped;
977 :
978 3 : if (!hd)
979 0 : return gpg_error (GPG_ERR_INV_VALUE);
980 :
981 3 : if (!any_registered)
982 : {
983 0 : gpgsm_status_with_error (ctrl, STATUS_ERROR, "keydb_search",
984 : gpg_error (GPG_ERR_KEYRING_OPEN));
985 0 : return gpg_error (GPG_ERR_NOT_FOUND);
986 : }
987 :
988 9 : while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
989 : {
990 3 : switch (hd->active[hd->current].type)
991 : {
992 : case KEYDB_RESOURCE_TYPE_NONE:
993 0 : BUG(); /* we should never see it here */
994 : break;
995 : case KEYDB_RESOURCE_TYPE_KEYBOX:
996 3 : rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
997 : KEYBOX_BLOBTYPE_X509,
998 : NULL, &skipped);
999 3 : break;
1000 : }
1001 3 : if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
1002 : { /* EOF -> switch to next resource */
1003 3 : hd->current++;
1004 : }
1005 0 : else if (!rc)
1006 0 : hd->found = hd->current;
1007 : }
1008 :
1009 3 : return rc;
1010 : }
1011 :
1012 :
1013 : int
1014 0 : keydb_search_first (ctrl_t ctrl, KEYDB_HANDLE hd)
1015 : {
1016 : KEYDB_SEARCH_DESC desc;
1017 :
1018 0 : memset (&desc, 0, sizeof desc);
1019 0 : desc.mode = KEYDB_SEARCH_MODE_FIRST;
1020 0 : return keydb_search (ctrl, hd, &desc, 1);
1021 : }
1022 :
1023 : int
1024 0 : keydb_search_next (ctrl_t ctrl, KEYDB_HANDLE hd)
1025 : {
1026 : KEYDB_SEARCH_DESC desc;
1027 :
1028 0 : memset (&desc, 0, sizeof desc);
1029 0 : desc.mode = KEYDB_SEARCH_MODE_NEXT;
1030 0 : return keydb_search (ctrl, hd, &desc, 1);
1031 : }
1032 :
1033 : int
1034 0 : keydb_search_kid (ctrl_t ctrl, KEYDB_HANDLE hd, u32 *kid)
1035 : {
1036 : KEYDB_SEARCH_DESC desc;
1037 :
1038 : (void)kid;
1039 :
1040 0 : memset (&desc, 0, sizeof desc);
1041 0 : desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
1042 0 : desc.u.kid[0] = kid[0];
1043 0 : desc.u.kid[1] = kid[1];
1044 0 : return keydb_search (ctrl, hd, &desc, 1);
1045 : }
1046 :
1047 : int
1048 3 : keydb_search_fpr (ctrl_t ctrl, KEYDB_HANDLE hd, const byte *fpr)
1049 : {
1050 : KEYDB_SEARCH_DESC desc;
1051 :
1052 3 : memset (&desc, 0, sizeof desc);
1053 3 : desc.mode = KEYDB_SEARCH_MODE_FPR;
1054 3 : memcpy (desc.u.fpr, fpr, 20);
1055 3 : return keydb_search (ctrl, hd, &desc, 1);
1056 : }
1057 :
1058 : int
1059 0 : keydb_search_issuer (ctrl_t ctrl, KEYDB_HANDLE hd, const char *issuer)
1060 : {
1061 : KEYDB_SEARCH_DESC desc;
1062 : int rc;
1063 :
1064 0 : memset (&desc, 0, sizeof desc);
1065 0 : desc.mode = KEYDB_SEARCH_MODE_ISSUER;
1066 0 : desc.u.name = issuer;
1067 0 : rc = keydb_search (ctrl, hd, &desc, 1);
1068 0 : return rc;
1069 : }
1070 :
1071 : int
1072 0 : keydb_search_issuer_sn (ctrl_t ctrl, KEYDB_HANDLE hd,
1073 : const char *issuer, ksba_const_sexp_t serial)
1074 : {
1075 : KEYDB_SEARCH_DESC desc;
1076 : int rc;
1077 : const unsigned char *s;
1078 :
1079 0 : memset (&desc, 0, sizeof desc);
1080 0 : desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
1081 0 : s = serial;
1082 0 : if (*s !='(')
1083 0 : return gpg_error (GPG_ERR_INV_VALUE);
1084 0 : s++;
1085 0 : for (desc.snlen = 0; digitp (s); s++)
1086 0 : desc.snlen = 10*desc.snlen + atoi_1 (s);
1087 0 : if (*s !=':')
1088 0 : return gpg_error (GPG_ERR_INV_VALUE);
1089 0 : desc.sn = s+1;
1090 0 : desc.u.name = issuer;
1091 0 : rc = keydb_search (ctrl, hd, &desc, 1);
1092 0 : return rc;
1093 : }
1094 :
1095 : int
1096 0 : keydb_search_subject (ctrl_t ctrl, KEYDB_HANDLE hd, const char *name)
1097 : {
1098 : KEYDB_SEARCH_DESC desc;
1099 : int rc;
1100 :
1101 0 : memset (&desc, 0, sizeof desc);
1102 0 : desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
1103 0 : desc.u.name = name;
1104 0 : rc = keydb_search (ctrl, hd, &desc, 1);
1105 0 : return rc;
1106 : }
1107 :
1108 :
1109 :
1110 : /* Store the certificate in the key DB but make sure that it does not
1111 : already exists. We do this simply by comparing the fingerprint.
1112 : If EXISTED is not NULL it will be set to true if the certificate
1113 : was already in the DB. */
1114 : int
1115 3 : keydb_store_cert (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, int *existed)
1116 : {
1117 : KEYDB_HANDLE kh;
1118 : int rc;
1119 : unsigned char fpr[20];
1120 :
1121 3 : if (existed)
1122 3 : *existed = 0;
1123 :
1124 3 : if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1125 : {
1126 0 : log_error (_("failed to get the fingerprint\n"));
1127 0 : return gpg_error (GPG_ERR_GENERAL);
1128 : }
1129 :
1130 3 : kh = keydb_new ();
1131 3 : if (!kh)
1132 : {
1133 0 : log_error (_("failed to allocate keyDB handle\n"));
1134 0 : return gpg_error (GPG_ERR_ENOMEM);;
1135 : }
1136 :
1137 : /* Set the ephemeral flag so that the search looks at all
1138 : records. */
1139 3 : keydb_set_ephemeral (kh, 1);
1140 :
1141 3 : rc = lock_all (kh);
1142 3 : if (rc)
1143 0 : return rc;
1144 :
1145 3 : rc = keydb_search_fpr (ctrl, kh, fpr);
1146 3 : if (rc != -1)
1147 : {
1148 0 : keydb_release (kh);
1149 0 : if (!rc)
1150 : {
1151 0 : if (existed)
1152 0 : *existed = 1;
1153 0 : if (!ephemeral)
1154 : {
1155 : /* Remove ephemeral flags from existing certificate to "store"
1156 : it permanently. */
1157 0 : rc = keydb_set_cert_flags (ctrl, cert, 1, KEYBOX_FLAG_BLOB, 0,
1158 : KEYBOX_FLAG_BLOB_EPHEMERAL, 0);
1159 0 : if (rc)
1160 : {
1161 0 : log_error ("clearing ephemeral flag failed: %s\n",
1162 : gpg_strerror (rc));
1163 0 : return rc;
1164 : }
1165 : }
1166 0 : return 0; /* okay */
1167 : }
1168 0 : log_error (_("problem looking for existing certificate: %s\n"),
1169 : gpg_strerror (rc));
1170 0 : return rc;
1171 : }
1172 :
1173 : /* Reset the ephemeral flag if not requested. */
1174 3 : if (!ephemeral)
1175 3 : keydb_set_ephemeral (kh, 0);
1176 :
1177 3 : rc = keydb_locate_writable (kh, 0);
1178 3 : if (rc)
1179 : {
1180 0 : log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
1181 0 : keydb_release (kh);
1182 0 : return rc;
1183 : }
1184 :
1185 3 : rc = keydb_insert_cert (kh, cert);
1186 3 : if (rc)
1187 : {
1188 0 : log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
1189 0 : keydb_release (kh);
1190 0 : return rc;
1191 : }
1192 3 : keydb_release (kh);
1193 3 : return 0;
1194 : }
1195 :
1196 :
1197 : /* This is basically keydb_set_flags but it implements a complete
1198 : transaction by locating the certificate in the DB and updating the
1199 : flags. */
1200 : gpg_error_t
1201 0 : keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
1202 : int which, int idx,
1203 : unsigned int mask, unsigned int value)
1204 : {
1205 : KEYDB_HANDLE kh;
1206 : gpg_error_t err;
1207 : unsigned char fpr[20];
1208 : unsigned int old_value;
1209 :
1210 0 : if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1211 : {
1212 0 : log_error (_("failed to get the fingerprint\n"));
1213 0 : return gpg_error (GPG_ERR_GENERAL);
1214 : }
1215 :
1216 0 : kh = keydb_new ();
1217 0 : if (!kh)
1218 : {
1219 0 : log_error (_("failed to allocate keyDB handle\n"));
1220 0 : return gpg_error (GPG_ERR_ENOMEM);;
1221 : }
1222 :
1223 0 : if (ephemeral)
1224 0 : keydb_set_ephemeral (kh, 1);
1225 :
1226 0 : err = keydb_lock (kh);
1227 0 : if (err)
1228 : {
1229 0 : log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1230 0 : keydb_release (kh);
1231 0 : return err;
1232 : }
1233 :
1234 0 : err = keydb_search_fpr (ctrl, kh, fpr);
1235 0 : if (err)
1236 : {
1237 0 : if (err == -1)
1238 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
1239 : else
1240 0 : log_error (_("problem re-searching certificate: %s\n"),
1241 : gpg_strerror (err));
1242 0 : keydb_release (kh);
1243 0 : return err;
1244 : }
1245 :
1246 0 : err = keydb_get_flags (kh, which, idx, &old_value);
1247 0 : if (err)
1248 : {
1249 0 : log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
1250 0 : keydb_release (kh);
1251 0 : return err;
1252 : }
1253 :
1254 0 : value = ((old_value & ~mask) | (value & mask));
1255 :
1256 0 : if (value != old_value)
1257 : {
1258 0 : err = keydb_set_flags (kh, which, idx, value);
1259 0 : if (err)
1260 : {
1261 0 : log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1262 0 : keydb_release (kh);
1263 0 : return err;
1264 : }
1265 : }
1266 :
1267 0 : keydb_release (kh);
1268 0 : return 0;
1269 : }
1270 :
1271 :
1272 : /* Reset all the certificate flags we have stored with the certificates
1273 : for performance reasons. */
1274 : void
1275 0 : keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
1276 : {
1277 : gpg_error_t err;
1278 0 : KEYDB_HANDLE hd = NULL;
1279 0 : KEYDB_SEARCH_DESC *desc = NULL;
1280 : int ndesc;
1281 : strlist_t sl;
1282 0 : int rc=0;
1283 : unsigned int old_value, value;
1284 :
1285 : (void)ctrl;
1286 :
1287 0 : hd = keydb_new ();
1288 0 : if (!hd)
1289 : {
1290 0 : log_error ("keydb_new failed\n");
1291 0 : goto leave;
1292 : }
1293 :
1294 0 : if (!names)
1295 0 : ndesc = 1;
1296 : else
1297 : {
1298 0 : for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
1299 : ;
1300 : }
1301 :
1302 0 : desc = xtrycalloc (ndesc, sizeof *desc);
1303 0 : if (!ndesc)
1304 : {
1305 0 : log_error ("allocating memory failed: %s\n",
1306 : gpg_strerror (out_of_core ()));
1307 0 : goto leave;
1308 : }
1309 :
1310 0 : if (!names)
1311 0 : desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1312 : else
1313 : {
1314 0 : for (ndesc=0, sl=names; sl; sl = sl->next)
1315 : {
1316 0 : rc = classify_user_id (sl->d, desc+ndesc, 0);
1317 0 : if (rc)
1318 0 : log_error ("key '%s' not found: %s\n", sl->d, gpg_strerror (rc));
1319 : else
1320 0 : ndesc++;
1321 : }
1322 : }
1323 :
1324 0 : err = keydb_lock (hd);
1325 0 : if (err)
1326 : {
1327 0 : log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1328 0 : goto leave;
1329 : }
1330 :
1331 0 : while (!(rc = keydb_search (ctrl, hd, desc, ndesc)))
1332 : {
1333 0 : if (!names)
1334 0 : desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1335 :
1336 0 : err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
1337 0 : if (err)
1338 : {
1339 0 : log_error (_("error getting stored flags: %s\n"),
1340 : gpg_strerror (err));
1341 0 : goto leave;
1342 : }
1343 :
1344 0 : value = (old_value & ~VALIDITY_REVOKED);
1345 0 : if (value != old_value)
1346 : {
1347 0 : err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
1348 0 : if (err)
1349 : {
1350 0 : log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1351 0 : goto leave;
1352 : }
1353 : }
1354 : }
1355 0 : if (rc && rc != -1)
1356 0 : log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1357 :
1358 : leave:
1359 0 : xfree (desc);
1360 0 : keydb_release (hd);
1361 0 : }
|