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 <http://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 : int secret;
51 : dotlock_t lockhandle;
52 : };
53 :
54 : static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
55 : static int used_resources;
56 :
57 : struct keydb_handle {
58 : int locked;
59 : int found;
60 : int saved_found;
61 : int current;
62 : int is_ephemeral;
63 : int used; /* items in active */
64 : struct resource_item active[MAX_KEYDB_RESOURCES];
65 : };
66 :
67 :
68 : static int lock_all (KEYDB_HANDLE hd);
69 : static void unlock_all (KEYDB_HANDLE hd);
70 :
71 :
72 : static void
73 0 : try_make_homedir (const char *fname)
74 : {
75 0 : const char *defhome = standard_homedir ();
76 :
77 : /* Create the directory only if the supplied directory name is the
78 : same as the default one. This way we avoid to create arbitrary
79 : directories when a non-default home directory is used. To cope
80 : with HOME, we do compare only the suffix if we see that the
81 : default homedir does start with a tilde. */
82 0 : if ( opt.dry_run || opt.no_homedir_creation )
83 0 : return;
84 :
85 0 : if (
86 : #ifdef HAVE_W32_SYSTEM
87 : ( !compare_filenames (fname, defhome) )
88 : #else
89 0 : ( *defhome == '~'
90 0 : && (strlen(fname) >= strlen (defhome+1)
91 0 : && !strcmp(fname+strlen(fname)-strlen(defhome+1), defhome+1 ) ))
92 0 : || (*defhome != '~' && !compare_filenames( fname, defhome ) )
93 : #endif
94 : )
95 : {
96 0 : if (gnupg_mkdir (fname, "-rwx"))
97 0 : log_info (_("can't create directory '%s': %s\n"),
98 0 : fname, strerror(errno) );
99 0 : else if (!opt.quiet )
100 0 : log_info (_("directory '%s' created\n"), fname);
101 : }
102 : }
103 :
104 :
105 : /* Handle the creation of a keybox if it does not yet exist. Take
106 : into acount that other processes might have the keybox already
107 : locked. This lock check does not work if the directory itself is
108 : not yet available. If R_CREATED is not NULL it will be set to true
109 : if the function created a new keybox. */
110 : static gpg_error_t
111 3 : maybe_create_keybox (char *filename, int force, int *r_created)
112 : {
113 3 : dotlock_t lockhd = NULL;
114 : FILE *fp;
115 : int rc;
116 : mode_t oldmask;
117 : char *last_slash_in_filename;
118 : int save_slash;
119 :
120 3 : if (r_created)
121 3 : *r_created = 0;
122 :
123 : /* A quick test whether the filename already exists. */
124 3 : if (!access (filename, F_OK))
125 2 : return 0;
126 :
127 : /* If we don't want to create a new file at all, there is no need to
128 : go any further - bail out right here. */
129 1 : if (!force)
130 0 : return gpg_error (GPG_ERR_ENOENT);
131 :
132 : /* First of all we try to create the home directory. Note, that we
133 : don't do any locking here because any sane application of gpg
134 : would create the home directory by itself and not rely on gpg's
135 : tricky auto-creation which is anyway only done for some home
136 : directory name patterns. */
137 1 : last_slash_in_filename = strrchr (filename, DIRSEP_C);
138 : #if HAVE_W32_SYSTEM
139 : {
140 : /* Windows may either have a slash or a backslash. Take care of it. */
141 : char *p = strrchr (filename, '/');
142 : if (!last_slash_in_filename || p > last_slash_in_filename)
143 : last_slash_in_filename = p;
144 : }
145 : #endif /*HAVE_W32_SYSTEM*/
146 1 : if (!last_slash_in_filename)
147 0 : return gpg_error (GPG_ERR_ENOENT); /* No slash at all - should
148 : not happen though. */
149 1 : save_slash = *last_slash_in_filename;
150 1 : *last_slash_in_filename = 0;
151 1 : if (access(filename, F_OK))
152 : {
153 : static int tried;
154 :
155 0 : if (!tried)
156 : {
157 0 : tried = 1;
158 0 : try_make_homedir (filename);
159 : }
160 0 : if (access (filename, F_OK))
161 : {
162 0 : rc = gpg_error_from_syserror ();
163 0 : *last_slash_in_filename = save_slash;
164 0 : goto leave;
165 : }
166 : }
167 1 : *last_slash_in_filename = save_slash;
168 :
169 : /* To avoid races with other instances of gpg trying to create or
170 : update the keybox (it is removed during an update for a short
171 : time), we do the next stuff in a locked state. */
172 1 : lockhd = dotlock_create (filename, 0);
173 1 : if (!lockhd)
174 : {
175 : /* A reason for this to fail is that the directory is not
176 : writable. However, this whole locking stuff does not make
177 : sense if this is the case. An empty non-writable directory
178 : with no keyring is not really useful at all. */
179 0 : if (opt.verbose)
180 0 : log_info ("can't allocate lock for '%s'\n", filename );
181 :
182 0 : if (!force)
183 0 : return gpg_error (GPG_ERR_ENOENT);
184 : else
185 0 : return gpg_error (GPG_ERR_GENERAL);
186 : }
187 :
188 1 : if ( dotlock_take (lockhd, -1) )
189 : {
190 : /* This is something bad. Probably a stale lockfile. */
191 0 : log_info ("can't lock '%s'\n", filename);
192 0 : rc = gpg_error (GPG_ERR_GENERAL);
193 0 : goto leave;
194 : }
195 :
196 : /* Now the real test while we are locked. */
197 1 : if (!access(filename, F_OK))
198 : {
199 0 : rc = 0; /* Okay, we may access the file now. */
200 0 : goto leave;
201 : }
202 :
203 : /* The file does not yet exist, create it now. */
204 1 : oldmask = umask (077);
205 1 : fp = fopen (filename, "w");
206 1 : if (!fp)
207 : {
208 0 : rc = gpg_error_from_syserror ();
209 0 : umask (oldmask);
210 0 : log_error (_("error creating keybox '%s': %s\n"),
211 : filename, gpg_strerror (rc));
212 0 : goto leave;
213 : }
214 1 : umask (oldmask);
215 :
216 : /* Make sure that at least one record is in a new keybox file, so
217 : that the detection magic for OpenPGP keyboxes works the next time
218 : it is used. */
219 1 : rc = _keybox_write_header_blob (fp, 0);
220 1 : if (rc)
221 : {
222 0 : fclose (fp);
223 0 : log_error (_("error creating keybox '%s': %s\n"),
224 : filename, gpg_strerror (rc));
225 0 : goto leave;
226 : }
227 :
228 1 : if (!opt.quiet)
229 1 : log_info (_("keybox '%s' created\n"), filename);
230 1 : if (r_created)
231 1 : *r_created = 1;
232 :
233 1 : fclose (fp);
234 1 : rc = 0;
235 :
236 : leave:
237 1 : if (lockhd)
238 : {
239 1 : dotlock_release (lockhd);
240 1 : dotlock_destroy (lockhd);
241 : }
242 1 : return rc;
243 : }
244 :
245 :
246 : /*
247 : * Register a resource (which currently may only be a keybox file).
248 : * The first keybox which is added by this function is created if it
249 : * does not exist. If AUTO_CREATED is not NULL it will be set to true
250 : * if the function has created a new keybox.
251 : */
252 : gpg_error_t
253 3 : keydb_add_resource (const char *url, int force, int secret, int *auto_created)
254 : {
255 : static int any_secret, any_public;
256 3 : const char *resname = url;
257 3 : char *filename = NULL;
258 3 : gpg_error_t err = 0;
259 3 : KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
260 :
261 3 : if (auto_created)
262 3 : *auto_created = 0;
263 :
264 : /* Do we have an URL?
265 : gnupg-kbx:filename := this is a plain keybox
266 : filename := See what is is, but create as plain keybox.
267 : */
268 3 : if (strlen (resname) > 10)
269 : {
270 3 : if (!strncmp (resname, "gnupg-kbx:", 10) )
271 : {
272 0 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
273 0 : resname += 10;
274 : }
275 : #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
276 3 : else if (strchr (resname, ':'))
277 : {
278 0 : log_error ("invalid key resource URL '%s'\n", url );
279 0 : err = gpg_error (GPG_ERR_GENERAL);
280 0 : goto leave;
281 : }
282 : #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
283 : }
284 :
285 3 : if (*resname != DIRSEP_C )
286 : { /* do tilde expansion etc */
287 3 : if (strchr(resname, DIRSEP_C) )
288 0 : filename = make_filename (resname, NULL);
289 : else
290 3 : filename = make_filename (gnupg_homedir (), resname, NULL);
291 : }
292 : else
293 0 : filename = xstrdup (resname);
294 :
295 3 : if (!force)
296 3 : force = secret? !any_secret : !any_public;
297 :
298 : /* see whether we can determine the filetype */
299 3 : if (rt == KEYDB_RESOURCE_TYPE_NONE)
300 : {
301 3 : FILE *fp = fopen( filename, "rb" );
302 :
303 3 : if (fp)
304 : {
305 : u32 magic;
306 :
307 : /* FIXME: check for the keybox magic */
308 2 : if (fread (&magic, 4, 1, fp) == 1 )
309 : {
310 2 : if (magic == 0x13579ace || magic == 0xce9a5713)
311 : ; /* GDBM magic - no more support */
312 : else
313 2 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
314 : }
315 : else /* maybe empty: assume keybox */
316 0 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
317 2 : fclose (fp);
318 : }
319 : else /* no file yet: create keybox */
320 1 : rt = KEYDB_RESOURCE_TYPE_KEYBOX;
321 : }
322 :
323 3 : switch (rt)
324 : {
325 : case KEYDB_RESOURCE_TYPE_NONE:
326 0 : log_error ("unknown type of key resource '%s'\n", url );
327 0 : err = gpg_error (GPG_ERR_GENERAL);
328 0 : goto leave;
329 :
330 : case KEYDB_RESOURCE_TYPE_KEYBOX:
331 3 : err = maybe_create_keybox (filename, force, auto_created);
332 3 : if (err)
333 0 : goto leave;
334 : /* Now register the file */
335 : {
336 : void *token;
337 :
338 3 : err = keybox_register_file (filename, secret, &token);
339 3 : if (gpg_err_code (err) == GPG_ERR_EEXIST)
340 : ; /* Already registered - ignore. */
341 3 : else if (err)
342 : ; /* Other error. */
343 3 : else if (used_resources >= MAX_KEYDB_RESOURCES)
344 0 : err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
345 : else
346 : {
347 3 : all_resources[used_resources].type = rt;
348 3 : all_resources[used_resources].u.kr = NULL; /* Not used here */
349 3 : all_resources[used_resources].token = token;
350 3 : all_resources[used_resources].secret = secret;
351 :
352 3 : all_resources[used_resources].lockhandle
353 3 : = dotlock_create (filename, 0);
354 3 : if (!all_resources[used_resources].lockhandle)
355 0 : log_fatal ( _("can't create lock for '%s'\n"), filename);
356 :
357 : /* Do a compress run if needed and the file is not locked. */
358 3 : if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
359 : {
360 3 : KEYBOX_HANDLE kbxhd = keybox_new_x509 (token, secret);
361 :
362 3 : if (kbxhd)
363 : {
364 3 : keybox_compress (kbxhd);
365 3 : keybox_release (kbxhd);
366 : }
367 3 : dotlock_release (all_resources[used_resources].lockhandle);
368 : }
369 :
370 3 : used_resources++;
371 : }
372 : }
373 3 : break;
374 :
375 : default:
376 0 : log_error ("resource type of '%s' not supported\n", url);
377 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
378 0 : goto leave;
379 : }
380 :
381 : /* fixme: check directory permissions and print a warning */
382 :
383 : leave:
384 3 : if (err)
385 0 : log_error ("keyblock resource '%s': %s\n", filename, gpg_strerror (err));
386 3 : else if (secret)
387 0 : any_secret = 1;
388 : else
389 3 : any_public = 1;
390 3 : xfree (filename);
391 3 : return err;
392 : }
393 :
394 :
395 : KEYDB_HANDLE
396 9 : keydb_new (int secret)
397 : {
398 : KEYDB_HANDLE hd;
399 : int i, j;
400 :
401 9 : hd = xcalloc (1, sizeof *hd);
402 9 : hd->found = -1;
403 9 : hd->saved_found = -1;
404 :
405 9 : assert (used_resources <= MAX_KEYDB_RESOURCES);
406 18 : for (i=j=0; i < used_resources; i++)
407 : {
408 9 : if (!all_resources[i].secret != !secret)
409 0 : continue;
410 9 : switch (all_resources[i].type)
411 : {
412 : case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
413 0 : break;
414 : case KEYDB_RESOURCE_TYPE_KEYBOX:
415 9 : hd->active[j].type = all_resources[i].type;
416 9 : hd->active[j].token = all_resources[i].token;
417 9 : hd->active[j].secret = all_resources[i].secret;
418 9 : hd->active[j].lockhandle = all_resources[i].lockhandle;
419 9 : hd->active[j].u.kr = keybox_new_x509 (all_resources[i].token, secret);
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 : if (all_resources[i].secret)
923 0 : continue;
924 0 : switch (all_resources[i].type)
925 : {
926 : case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
927 0 : break;
928 : case KEYDB_RESOURCE_TYPE_KEYBOX:
929 : /* rc = keybox_rebuild_cache (all_resources[i].token); */
930 : /* if (rc) */
931 : /* log_error (_("failed to rebuild keybox cache: %s\n"), */
932 : /* g10_errstr (rc)); */
933 0 : break;
934 : }
935 : }
936 0 : }
937 :
938 :
939 :
940 : /*
941 : * Start the next search on this handle right at the beginning
942 : */
943 : gpg_error_t
944 3 : keydb_search_reset (KEYDB_HANDLE hd)
945 : {
946 : int i;
947 3 : gpg_error_t rc = 0;
948 :
949 3 : if (!hd)
950 0 : return gpg_error (GPG_ERR_INV_VALUE);
951 :
952 3 : hd->current = 0;
953 3 : hd->found = -1;
954 : /* and reset all resources */
955 6 : for (i=0; !rc && i < hd->used; i++)
956 : {
957 3 : switch (hd->active[i].type)
958 : {
959 : case KEYDB_RESOURCE_TYPE_NONE:
960 0 : break;
961 : case KEYDB_RESOURCE_TYPE_KEYBOX:
962 3 : rc = keybox_search_reset (hd->active[i].u.kr);
963 3 : break;
964 : }
965 : }
966 3 : return rc;
967 : }
968 :
969 : /*
970 : * Search through all keydb resources, starting at the current position,
971 : * for a keyblock which contains one of the keys described in the DESC array.
972 : */
973 : int
974 3 : keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
975 : {
976 3 : int rc = -1;
977 : unsigned long skipped;
978 :
979 3 : if (!hd)
980 0 : return gpg_error (GPG_ERR_INV_VALUE);
981 :
982 9 : while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
983 : {
984 3 : switch (hd->active[hd->current].type)
985 : {
986 : case KEYDB_RESOURCE_TYPE_NONE:
987 0 : BUG(); /* we should never see it here */
988 : break;
989 : case KEYDB_RESOURCE_TYPE_KEYBOX:
990 3 : rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
991 : KEYBOX_BLOBTYPE_X509,
992 : NULL, &skipped);
993 3 : break;
994 : }
995 3 : if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
996 : { /* EOF -> switch to next resource */
997 3 : hd->current++;
998 : }
999 0 : else if (!rc)
1000 0 : hd->found = hd->current;
1001 : }
1002 :
1003 3 : return rc;
1004 : }
1005 :
1006 :
1007 : int
1008 0 : keydb_search_first (KEYDB_HANDLE hd)
1009 : {
1010 : KEYDB_SEARCH_DESC desc;
1011 :
1012 0 : memset (&desc, 0, sizeof desc);
1013 0 : desc.mode = KEYDB_SEARCH_MODE_FIRST;
1014 0 : return keydb_search (hd, &desc, 1);
1015 : }
1016 :
1017 : int
1018 0 : keydb_search_next (KEYDB_HANDLE hd)
1019 : {
1020 : KEYDB_SEARCH_DESC desc;
1021 :
1022 0 : memset (&desc, 0, sizeof desc);
1023 0 : desc.mode = KEYDB_SEARCH_MODE_NEXT;
1024 0 : return keydb_search (hd, &desc, 1);
1025 : }
1026 :
1027 : int
1028 0 : keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
1029 : {
1030 : KEYDB_SEARCH_DESC desc;
1031 :
1032 : (void)kid;
1033 :
1034 0 : memset (&desc, 0, sizeof desc);
1035 0 : desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
1036 0 : desc.u.kid[0] = kid[0];
1037 0 : desc.u.kid[1] = kid[1];
1038 0 : return keydb_search (hd, &desc, 1);
1039 : }
1040 :
1041 : int
1042 3 : keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
1043 : {
1044 : KEYDB_SEARCH_DESC desc;
1045 :
1046 3 : memset (&desc, 0, sizeof desc);
1047 3 : desc.mode = KEYDB_SEARCH_MODE_FPR;
1048 3 : memcpy (desc.u.fpr, fpr, 20);
1049 3 : return keydb_search (hd, &desc, 1);
1050 : }
1051 :
1052 : int
1053 0 : keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
1054 : {
1055 : KEYDB_SEARCH_DESC desc;
1056 : int rc;
1057 :
1058 0 : memset (&desc, 0, sizeof desc);
1059 0 : desc.mode = KEYDB_SEARCH_MODE_ISSUER;
1060 0 : desc.u.name = issuer;
1061 0 : rc = keydb_search (hd, &desc, 1);
1062 0 : return rc;
1063 : }
1064 :
1065 : int
1066 0 : keydb_search_issuer_sn (KEYDB_HANDLE hd,
1067 : const char *issuer, ksba_const_sexp_t serial)
1068 : {
1069 : KEYDB_SEARCH_DESC desc;
1070 : int rc;
1071 : const unsigned char *s;
1072 :
1073 0 : memset (&desc, 0, sizeof desc);
1074 0 : desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
1075 0 : s = serial;
1076 0 : if (*s !='(')
1077 0 : return gpg_error (GPG_ERR_INV_VALUE);
1078 0 : s++;
1079 0 : for (desc.snlen = 0; digitp (s); s++)
1080 0 : desc.snlen = 10*desc.snlen + atoi_1 (s);
1081 0 : if (*s !=':')
1082 0 : return gpg_error (GPG_ERR_INV_VALUE);
1083 0 : desc.sn = s+1;
1084 0 : desc.u.name = issuer;
1085 0 : rc = keydb_search (hd, &desc, 1);
1086 0 : return rc;
1087 : }
1088 :
1089 : int
1090 0 : keydb_search_subject (KEYDB_HANDLE hd, const char *name)
1091 : {
1092 : KEYDB_SEARCH_DESC desc;
1093 : int rc;
1094 :
1095 0 : memset (&desc, 0, sizeof desc);
1096 0 : desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
1097 0 : desc.u.name = name;
1098 0 : rc = keydb_search (hd, &desc, 1);
1099 0 : return rc;
1100 : }
1101 :
1102 :
1103 :
1104 : /* Store the certificate in the key DB but make sure that it does not
1105 : already exists. We do this simply by comparing the fingerprint.
1106 : If EXISTED is not NULL it will be set to true if the certificate
1107 : was already in the DB. */
1108 : int
1109 3 : keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed)
1110 : {
1111 : KEYDB_HANDLE kh;
1112 : int rc;
1113 : unsigned char fpr[20];
1114 :
1115 3 : if (existed)
1116 3 : *existed = 0;
1117 :
1118 3 : if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1119 : {
1120 0 : log_error (_("failed to get the fingerprint\n"));
1121 0 : return gpg_error (GPG_ERR_GENERAL);
1122 : }
1123 :
1124 3 : kh = keydb_new (0);
1125 3 : if (!kh)
1126 : {
1127 0 : log_error (_("failed to allocate keyDB handle\n"));
1128 0 : return gpg_error (GPG_ERR_ENOMEM);;
1129 : }
1130 :
1131 : /* Set the ephemeral flag so that the search looks at all
1132 : records. */
1133 3 : keydb_set_ephemeral (kh, 1);
1134 :
1135 3 : rc = lock_all (kh);
1136 3 : if (rc)
1137 0 : return rc;
1138 :
1139 3 : rc = keydb_search_fpr (kh, fpr);
1140 3 : if (rc != -1)
1141 : {
1142 0 : keydb_release (kh);
1143 0 : if (!rc)
1144 : {
1145 0 : if (existed)
1146 0 : *existed = 1;
1147 0 : if (!ephemeral)
1148 : {
1149 : /* Remove ephemeral flags from existing certificate to "store"
1150 : it permanently. */
1151 0 : rc = keydb_set_cert_flags (cert, 1, KEYBOX_FLAG_BLOB, 0,
1152 : KEYBOX_FLAG_BLOB_EPHEMERAL, 0);
1153 0 : if (rc)
1154 : {
1155 0 : log_error ("clearing ephemeral flag failed: %s\n",
1156 : gpg_strerror (rc));
1157 0 : return rc;
1158 : }
1159 : }
1160 0 : return 0; /* okay */
1161 : }
1162 0 : log_error (_("problem looking for existing certificate: %s\n"),
1163 : gpg_strerror (rc));
1164 0 : return rc;
1165 : }
1166 :
1167 : /* Reset the ephemeral flag if not requested. */
1168 3 : if (!ephemeral)
1169 3 : keydb_set_ephemeral (kh, 0);
1170 :
1171 3 : rc = keydb_locate_writable (kh, 0);
1172 3 : if (rc)
1173 : {
1174 0 : log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
1175 0 : keydb_release (kh);
1176 0 : return rc;
1177 : }
1178 :
1179 3 : rc = keydb_insert_cert (kh, cert);
1180 3 : if (rc)
1181 : {
1182 0 : log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
1183 0 : keydb_release (kh);
1184 0 : return rc;
1185 : }
1186 3 : keydb_release (kh);
1187 3 : return 0;
1188 : }
1189 :
1190 :
1191 : /* This is basically keydb_set_flags but it implements a complete
1192 : transaction by locating the certificate in the DB and updating the
1193 : flags. */
1194 : gpg_error_t
1195 0 : keydb_set_cert_flags (ksba_cert_t cert, int ephemeral,
1196 : int which, int idx,
1197 : unsigned int mask, unsigned int value)
1198 : {
1199 : KEYDB_HANDLE kh;
1200 : gpg_error_t err;
1201 : unsigned char fpr[20];
1202 : unsigned int old_value;
1203 :
1204 0 : if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1205 : {
1206 0 : log_error (_("failed to get the fingerprint\n"));
1207 0 : return gpg_error (GPG_ERR_GENERAL);
1208 : }
1209 :
1210 0 : kh = keydb_new (0);
1211 0 : if (!kh)
1212 : {
1213 0 : log_error (_("failed to allocate keyDB handle\n"));
1214 0 : return gpg_error (GPG_ERR_ENOMEM);;
1215 : }
1216 :
1217 0 : if (ephemeral)
1218 0 : keydb_set_ephemeral (kh, 1);
1219 :
1220 0 : err = keydb_lock (kh);
1221 0 : if (err)
1222 : {
1223 0 : log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1224 0 : keydb_release (kh);
1225 0 : return err;
1226 : }
1227 :
1228 0 : err = keydb_search_fpr (kh, fpr);
1229 0 : if (err)
1230 : {
1231 0 : if (err == -1)
1232 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
1233 : else
1234 0 : log_error (_("problem re-searching certificate: %s\n"),
1235 : gpg_strerror (err));
1236 0 : keydb_release (kh);
1237 0 : return err;
1238 : }
1239 :
1240 0 : err = keydb_get_flags (kh, which, idx, &old_value);
1241 0 : if (err)
1242 : {
1243 0 : log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
1244 0 : keydb_release (kh);
1245 0 : return err;
1246 : }
1247 :
1248 0 : value = ((old_value & ~mask) | (value & mask));
1249 :
1250 0 : if (value != old_value)
1251 : {
1252 0 : err = keydb_set_flags (kh, which, idx, value);
1253 0 : if (err)
1254 : {
1255 0 : log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1256 0 : keydb_release (kh);
1257 0 : return err;
1258 : }
1259 : }
1260 :
1261 0 : keydb_release (kh);
1262 0 : return 0;
1263 : }
1264 :
1265 :
1266 : /* Reset all the certificate flags we have stored with the certificates
1267 : for performance reasons. */
1268 : void
1269 0 : keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
1270 : {
1271 : gpg_error_t err;
1272 0 : KEYDB_HANDLE hd = NULL;
1273 0 : KEYDB_SEARCH_DESC *desc = NULL;
1274 : int ndesc;
1275 : strlist_t sl;
1276 0 : int rc=0;
1277 : unsigned int old_value, value;
1278 :
1279 : (void)ctrl;
1280 :
1281 0 : hd = keydb_new (0);
1282 0 : if (!hd)
1283 : {
1284 0 : log_error ("keydb_new failed\n");
1285 0 : goto leave;
1286 : }
1287 :
1288 0 : if (!names)
1289 0 : ndesc = 1;
1290 : else
1291 : {
1292 0 : for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
1293 : ;
1294 : }
1295 :
1296 0 : desc = xtrycalloc (ndesc, sizeof *desc);
1297 0 : if (!ndesc)
1298 : {
1299 0 : log_error ("allocating memory failed: %s\n",
1300 : gpg_strerror (out_of_core ()));
1301 0 : goto leave;
1302 : }
1303 :
1304 0 : if (!names)
1305 0 : desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1306 : else
1307 : {
1308 0 : for (ndesc=0, sl=names; sl; sl = sl->next)
1309 : {
1310 0 : rc = classify_user_id (sl->d, desc+ndesc, 0);
1311 0 : if (rc)
1312 0 : log_error ("key '%s' not found: %s\n", sl->d, gpg_strerror (rc));
1313 : else
1314 0 : ndesc++;
1315 : }
1316 : }
1317 :
1318 0 : err = keydb_lock (hd);
1319 0 : if (err)
1320 : {
1321 0 : log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1322 0 : goto leave;
1323 : }
1324 :
1325 0 : while (!(rc = keydb_search (hd, desc, ndesc)))
1326 : {
1327 0 : if (!names)
1328 0 : desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1329 :
1330 0 : err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
1331 0 : if (err)
1332 : {
1333 0 : log_error (_("error getting stored flags: %s\n"),
1334 : gpg_strerror (err));
1335 0 : goto leave;
1336 : }
1337 :
1338 0 : value = (old_value & ~VALIDITY_REVOKED);
1339 0 : if (value != old_value)
1340 : {
1341 0 : err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
1342 0 : if (err)
1343 : {
1344 0 : log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1345 0 : goto leave;
1346 : }
1347 : }
1348 : }
1349 0 : if (rc && rc != -1)
1350 0 : log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1351 :
1352 : leave:
1353 0 : xfree (desc);
1354 0 : keydb_release (hd);
1355 0 : }
|