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