1 /* keydb.c - key database dispatcher
2 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
27 #include <sys/types.h>
33 #include "main.h" /*try_make_homedir ()*/
39 static int active_handles;
42 KEYDB_RESOURCE_TYPE_NONE = 0,
43 KEYDB_RESOURCE_TYPE_KEYRING
45 #define MAX_KEYDB_RESOURCES 20
47 struct resource_item {
48 KeydbResourceType type;
56 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
57 static int used_resources;
63 int used; /* items in active */
64 struct resource_item active[MAX_KEYDB_RESOURCES];
68 static int lock_all (KEYDB_HANDLE hd);
69 static void unlock_all (KEYDB_HANDLE hd);
73 * Register a resource (which currently may only be a keyring file).
74 * The first keyring which is added by this function is
75 * created if it does not exist.
76 * Note: this function may be called before secure memory is
80 keydb_add_resource (const char *url, int force, int secret)
82 static int any_secret, any_public;
83 const char *resname = url;
85 char *filename = NULL;
87 KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
91 * gnupg-ring:filename := this is a plain keyring
92 * filename := See what is is, but create as plain keyring.
94 if (strlen (resname) > 11) {
95 if (!strncmp( resname, "gnupg-ring:", 11) ) {
96 rt = KEYDB_RESOURCE_TYPE_KEYRING;
99 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
100 else if (strchr (resname, ':')) {
101 log_error ("invalid key resource URL `%s'\n", url );
105 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
108 if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
109 if (strchr(resname, DIRSEP_C) )
110 filename = make_filename (resname, NULL);
112 filename = make_filename (opt.homedir, resname, NULL);
115 filename = m_strdup (resname);
118 force = secret? !any_secret : !any_public;
120 /* see whether we can determine the filetype */
121 if (rt == KEYDB_RESOURCE_TYPE_NONE) {
122 FILE *fp = fopen( filename, "rb" );
127 if (fread( &magic, 4, 1, fp) == 1 ) {
128 if (magic == 0x13579ace || magic == 0xce9a5713)
129 ; /* GDBM magic - no more support */
131 rt = KEYDB_RESOURCE_TYPE_KEYRING;
133 else /* maybe empty: assume ring */
134 rt = KEYDB_RESOURCE_TYPE_KEYRING;
137 else /* no file yet: create ring */
138 rt = KEYDB_RESOURCE_TYPE_KEYRING;
142 case KEYDB_RESOURCE_TYPE_NONE:
143 log_error ("unknown type of key resource `%s'\n", url );
147 case KEYDB_RESOURCE_TYPE_KEYRING:
148 if (access(filename, F_OK))
149 { /* file does not exist */
151 char *last_slash_in_filename;
155 rc = G10ERR_OPEN_FILE;
159 last_slash_in_filename = strrchr (filename, DIRSEP_C);
160 *last_slash_in_filename = 0;
161 if (access(filename, F_OK))
162 { /* on the first time we try to create the default
163 homedir and in this case the process will be
164 terminated, so that on the next invocation it can
165 read the options file in on startup */
166 try_make_homedir (filename);
167 rc = G10ERR_OPEN_FILE;
168 *last_slash_in_filename = DIRSEP_C;
171 *last_slash_in_filename = DIRSEP_C;
174 iobuf = iobuf_create (filename);
178 log_error ( _("error creating keyring `%s': %s\n"),
179 filename, strerror(errno));
180 rc = G10ERR_OPEN_FILE;
185 log_info (_("keyring `%s' created\n"), filename);
188 /* must invalidate that ugly cache */
189 iobuf_ioctl (NULL, 2, 0, (char*)filename);
190 } /* end file creation */
192 token = keyring_register_filename (filename, secret);
194 ; /* already registered - ignore it */
195 else if (used_resources >= MAX_KEYDB_RESOURCES)
196 rc = G10ERR_RESOURCE_LIMIT;
199 all_resources[used_resources].type = rt;
200 all_resources[used_resources].u.kr = NULL; /* Not used here */
201 all_resources[used_resources].token = token;
202 all_resources[used_resources].secret = secret;
208 log_error ("resource type of `%s' not supported\n", url);
213 /* fixme: check directory permissions and print a warning */
217 log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
230 keydb_new (int secret)
235 hd = m_alloc_clear (sizeof *hd);
238 assert (used_resources <= MAX_KEYDB_RESOURCES);
239 for (i=j=0; i < used_resources; i++)
241 if (!all_resources[i].secret != !secret)
243 switch (all_resources[i].type)
245 case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
247 case KEYDB_RESOURCE_TYPE_KEYRING:
248 hd->active[j].type = all_resources[i].type;
249 hd->active[j].token = all_resources[i].token;
250 hd->active[j].secret = all_resources[i].secret;
251 hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
252 if (!hd->active[j].u.kr) {
254 return NULL; /* fixme: release all previously allocated handles*/
267 keydb_release (KEYDB_HANDLE hd)
273 assert (active_handles > 0);
277 for (i=0; i < hd->used; i++) {
278 switch (hd->active[i].type) {
279 case KEYDB_RESOURCE_TYPE_NONE:
281 case KEYDB_RESOURCE_TYPE_KEYRING:
282 keyring_release (hd->active[i].u.kr);
292 * Return the name of the current resource. This is function first
293 * looks for the last found found, then for the current search
294 * position, and last returns the first available resource. The
295 * returned string is only valid as long as the handle exists. This
296 * function does only return NULL if no handle is specified, in all
297 * other error cases an empty string is returned.
300 keydb_get_resource_name (KEYDB_HANDLE hd)
303 const char *s = NULL;
308 if ( hd->found >= 0 && hd->found < hd->used)
310 else if ( hd->current >= 0 && hd->current < hd->used)
315 switch (hd->active[idx].type) {
316 case KEYDB_RESOURCE_TYPE_NONE:
319 case KEYDB_RESOURCE_TYPE_KEYRING:
320 s = keyring_get_resource_name (hd->active[idx].u.kr);
330 lock_all (KEYDB_HANDLE hd)
334 for (i=0; !rc && i < hd->used; i++) {
335 switch (hd->active[i].type) {
336 case KEYDB_RESOURCE_TYPE_NONE:
338 case KEYDB_RESOURCE_TYPE_KEYRING:
339 rc = keyring_lock (hd->active[i].u.kr, 1);
345 /* revert the already set locks */
346 for (i--; i >= 0; i--) {
347 switch (hd->active[i].type) {
348 case KEYDB_RESOURCE_TYPE_NONE:
350 case KEYDB_RESOURCE_TYPE_KEYRING:
351 keyring_lock (hd->active[i].u.kr, 0);
363 unlock_all (KEYDB_HANDLE hd)
370 for (i=hd->used-1; i >= 0; i--) {
371 switch (hd->active[i].type) {
372 case KEYDB_RESOURCE_TYPE_NONE:
374 case KEYDB_RESOURCE_TYPE_KEYRING:
375 keyring_lock (hd->active[i].u.kr, 0);
384 * Return the last found keyring. Caller must free it.
385 * The returned keyblock has the kbode flag bit 0 set for the node with
386 * the public key used to locate the keyblock or flag bit 1 set for
390 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
395 return G10ERR_INV_ARG;
397 if ( hd->found < 0 || hd->found >= hd->used)
398 return -1; /* nothing found */
400 switch (hd->active[hd->found].type) {
401 case KEYDB_RESOURCE_TYPE_NONE:
402 rc = G10ERR_GENERAL; /* oops */
404 case KEYDB_RESOURCE_TYPE_KEYRING:
405 rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
413 * update the current keyblock with KB
416 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
421 return G10ERR_INV_ARG;
423 if ( hd->found < 0 || hd->found >= hd->used)
424 return -1; /* nothing found */
433 switch (hd->active[hd->found].type) {
434 case KEYDB_RESOURCE_TYPE_NONE:
435 rc = G10ERR_GENERAL; /* oops */
437 case KEYDB_RESOURCE_TYPE_KEYRING:
438 rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
448 * Insert a new KB into one of the resources.
451 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
457 return G10ERR_INV_ARG;
462 if ( hd->found >= 0 && hd->found < hd->used)
464 else if ( hd->current >= 0 && hd->current < hd->used)
467 return G10ERR_GENERAL;
473 switch (hd->active[idx].type) {
474 case KEYDB_RESOURCE_TYPE_NONE:
475 rc = G10ERR_GENERAL; /* oops */
477 case KEYDB_RESOURCE_TYPE_KEYRING:
478 rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
488 * The current keyblock will be deleted.
491 keydb_delete_keyblock (KEYDB_HANDLE hd)
496 return G10ERR_INV_ARG;
498 if ( hd->found < 0 || hd->found >= hd->used)
499 return -1; /* nothing found */
508 switch (hd->active[hd->found].type) {
509 case KEYDB_RESOURCE_TYPE_NONE:
510 rc = G10ERR_GENERAL; /* oops */
512 case KEYDB_RESOURCE_TYPE_KEYRING:
513 rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
523 * Locate the default writable key resource, so that the next
524 * operation (which is only relevant for inserts) will be done on this
528 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
533 return G10ERR_INV_ARG;
535 rc = keydb_search_reset (hd); /* this does reset hd->current */
539 for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
541 switch (hd->active[hd->current].type)
543 case KEYDB_RESOURCE_TYPE_NONE:
546 case KEYDB_RESOURCE_TYPE_KEYRING:
547 if (keyring_is_writable (hd->active[hd->current].token))
548 return 0; /* found (hd->current is set to it) */
557 * Rebuild the caches of all key resources.
560 keydb_rebuild_caches (void)
564 for (i=0; i < used_resources; i++)
566 if (all_resources[i].secret)
568 switch (all_resources[i].type)
570 case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
572 case KEYDB_RESOURCE_TYPE_KEYRING:
573 rc = keyring_rebuild_cache (all_resources[i].token);
575 log_error (_("failed to rebuild keyring cache: %s\n"),
585 * Start the next search on this handle right at the beginning
588 keydb_search_reset (KEYDB_HANDLE hd)
593 return G10ERR_INV_ARG;
597 /* and reset all resources */
598 for (i=0; !rc && i < hd->used; i++) {
599 switch (hd->active[i].type) {
600 case KEYDB_RESOURCE_TYPE_NONE:
602 case KEYDB_RESOURCE_TYPE_KEYRING:
603 rc = keyring_search_reset (hd->active[i].u.kr);
612 * Search through all keydb resources, starting at the current position,
613 * for a keyblock which contains one of the keys described in the DESC array.
616 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
621 return G10ERR_INV_ARG;
623 while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
624 switch (hd->active[hd->current].type) {
625 case KEYDB_RESOURCE_TYPE_NONE:
626 BUG(); /* we should never see it here */
628 case KEYDB_RESOURCE_TYPE_KEYRING:
629 rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc);
632 if (rc == -1) /* EOF -> switch to next resource */
635 hd->found = hd->current;
643 keydb_search_first (KEYDB_HANDLE hd)
645 KEYDB_SEARCH_DESC desc;
647 memset (&desc, 0, sizeof desc);
648 desc.mode = KEYDB_SEARCH_MODE_FIRST;
649 return keydb_search (hd, &desc, 1);
653 keydb_search_next (KEYDB_HANDLE hd)
655 KEYDB_SEARCH_DESC desc;
657 memset (&desc, 0, sizeof desc);
658 desc.mode = KEYDB_SEARCH_MODE_NEXT;
659 return keydb_search (hd, &desc, 1);
663 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
665 KEYDB_SEARCH_DESC desc;
667 memset (&desc, 0, sizeof desc);
668 desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
669 desc.u.kid[0] = kid[0];
670 desc.u.kid[1] = kid[1];
671 return keydb_search (hd, &desc, 1);
675 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
677 KEYDB_SEARCH_DESC desc;
679 memset (&desc, 0, sizeof desc);
680 desc.mode = KEYDB_SEARCH_MODE_FPR;
681 memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
682 return keydb_search (hd, &desc, 1);