summaryrefslogtreecommitdiffstats
path: root/g10/keydb.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2006-04-19 13:26:11 +0200
committerWerner Koch <wk@gnupg.org>2006-04-19 13:26:11 +0200
commit29b23dea9731e8f258211bc6fd733d205c18e2a8 (patch)
treeff2a0f66bda0c1f050e8fa00cbf610e18b91c9f7 /g10/keydb.c
parent2006-04-14 Marcus Brinkmann <marcus@g10code.de> (diff)
downloadgnupg2-29b23dea9731e8f258211bc6fd733d205c18e2a8.tar.xz
gnupg2-29b23dea9731e8f258211bc6fd733d205c18e2a8.zip
Merged with gpg 1.4.3 code.
The gpg part does not yet build.
Diffstat (limited to 'g10/keydb.c')
-rw-r--r--g10/keydb.c233
1 files changed, 158 insertions, 75 deletions
diff --git a/g10/keydb.c b/g10/keydb.c
index b64f38cbc..dbad8435a 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -1,5 +1,5 @@
/* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
*/
#include <config.h>
@@ -71,6 +72,124 @@ static int lock_all (KEYDB_HANDLE hd);
static void unlock_all (KEYDB_HANDLE hd);
+/* Handle the creation of a keyring if it does not yet exist. Take
+ into acount that other processes might have the keyring already
+ locked. This lock check does not work if the directory itself is
+ not yet available. */
+static int
+maybe_create_keyring (char *filename, int force)
+{
+ DOTLOCK lockhd = NULL;
+ IOBUF iobuf;
+ int rc;
+ mode_t oldmask;
+ char *last_slash_in_filename;
+
+ /* A quick test whether the filename already exists. */
+ if (!access (filename, F_OK))
+ return 0;
+
+ /* If we don't want to create a new file at all, there is no need to
+ go any further - bail out right here. */
+ if (!force)
+ return gpg_error (GPG_ERR_ENOENT);
+
+ /* First of all we try to create the home directory. Note, that we
+ don't do any locking here because any sane application of gpg
+ would create the home directory by itself and not rely on gpg's
+ tricky auto-creation which is anyway only done for some home
+ directory name patterns. */
+ last_slash_in_filename = strrchr (filename, DIRSEP_C);
+ *last_slash_in_filename = 0;
+ if (access(filename, F_OK))
+ {
+ static int tried;
+
+ if (!tried)
+ {
+ tried = 1;
+ try_make_homedir (filename);
+ }
+ if (access (filename, F_OK))
+ {
+ rc = gpg_error_from_errno (errno);
+ *last_slash_in_filename = DIRSEP_C;
+ goto leave;
+ }
+ }
+ *last_slash_in_filename = DIRSEP_C;
+
+
+ /* To avoid races with other instances of gpg trying to create or
+ update the keyring (it is removed during an update for a short
+ time), we do the next stuff in a locked state. */
+ lockhd = create_dotlock (filename);
+ if (!lockhd)
+ {
+ /* A reason for this to fail is that the directory is not
+ writable. However, this whole locking stuff does not make
+ sense if this is the case. An empty non-writable directory
+ with no keyring is not really useful at all. */
+ if (opt.verbose)
+ log_info ("can't allocate lock for `%s'\n", filename );
+
+ if (!force)
+ return G10ERR_OPEN_FILE;
+ else
+ return G10ERR_GENERAL;
+ }
+
+ if ( make_dotlock (lockhd, -1) )
+ {
+ /* This is something bad. Probably a stale lockfile. */
+ log_info ("can't lock `%s'\n", filename );
+ rc = G10ERR_GENERAL;
+ goto leave;
+ }
+
+ /* Now the real test while we are locked. */
+ if (!access(filename, F_OK))
+ {
+ rc = 0; /* Okay, we may access the file now. */
+ goto leave;
+ }
+
+ /* The file does not yet exist, create it now. */
+ oldmask = umask (077);
+ if (is_secured_filename (filename))
+ {
+ iobuf = NULL;
+ errno = EPERM;
+ }
+ else
+ iobuf = iobuf_create (filename);
+ umask (oldmask);
+ if (!iobuf)
+ {
+ log_error ( _("error creating keyring `%s': %s\n"),
+ filename, strerror(errno));
+ rc = G10ERR_OPEN_FILE;
+ goto leave;
+ }
+
+ if (!opt.quiet)
+ log_info (_("keyring `%s' created\n"), filename);
+
+ iobuf_close (iobuf);
+ /* Must invalidate that ugly cache */
+ iobuf_ioctl (NULL, 2, 0, filename);
+ rc = 0;
+
+ leave:
+ if (lockhd)
+ {
+ release_dotlock (lockhd);
+ destroy_dotlock (lockhd);
+ }
+ return rc;
+}
+
+
/*
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
@@ -78,14 +197,14 @@ static void unlock_all (KEYDB_HANDLE hd);
* Note: this function may be called before secure memory is
* available.
* Flag 1 == force
- * Flag 2 == default
+ * Flag 2 == mark resource as primary
+ * Flag 4 == This is a default resources
*/
int
keydb_add_resource (const char *url, int flags, int secret)
{
static int any_secret, any_public;
const char *resname = url;
- iobuf_t iobuf = NULL;
char *filename = NULL;
int force=(flags&1);
int rc = 0;
@@ -104,7 +223,7 @@ keydb_add_resource (const char *url, int flags, int secret)
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
else if (strchr (resname, ':')) {
log_error ("invalid key resource URL `%s'\n", url );
- rc = GPG_ERR_GENERAL;
+ rc = G10ERR_GENERAL;
goto leave;
}
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
@@ -146,65 +265,18 @@ keydb_add_resource (const char *url, int flags, int secret)
switch (rt) {
case KEYDB_RESOURCE_TYPE_NONE:
log_error ("unknown type of key resource `%s'\n", url );
- rc = GPG_ERR_GENERAL;
+ rc = G10ERR_GENERAL;
goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING:
- if (access(filename, F_OK))
- { /* file does not exist */
- mode_t oldmask;
- char *last_slash_in_filename;
-
- if (!force)
- {
- rc = gpg_error_from_errno (errno);
- goto leave;
- }
-
- last_slash_in_filename = strrchr (filename, DIRSEP_C);
- *last_slash_in_filename = 0;
- if (access(filename, F_OK))
- { /* On the first time we try to create the default
- homedir and check again. */
- static int tried;
-
- if (!tried)
- {
- tried = 1;
- try_make_homedir (filename);
- }
- if (access (filename, F_OK))
- {
- rc = gpg_error_from_errno (errno);
- *last_slash_in_filename = DIRSEP_C;
- goto leave;
- }
- }
- *last_slash_in_filename = DIRSEP_C;
-
- oldmask=umask(077);
- iobuf = iobuf_create (filename);
- umask(oldmask);
- if (!iobuf)
- {
- log_error ( _("error creating keyring `%s': %s\n"),
- filename, strerror(errno));
- rc = gpg_error_from_errno (errno);
- goto leave;
- }
-
- if (!opt.quiet)
- log_info (_("keyring `%s' created\n"), filename);
- iobuf_close (iobuf);
- iobuf = NULL;
- /* must invalidate that ugly cache */
- iobuf_ioctl (NULL, 2, 0, (char*)filename);
- } /* end file creation */
+ rc = maybe_create_keyring (filename, force);
+ if (rc)
+ goto leave;
if(keyring_register_filename (filename, secret, &token))
{
if (used_resources >= MAX_KEYDB_RESOURCES)
- rc = GPG_ERR_RESOURCE_LIMIT;
+ rc = G10ERR_RESOURCE_LIMIT;
else
{
if(flags&2)
@@ -228,7 +300,7 @@ keydb_add_resource (const char *url, int flags, int secret)
default:
log_error ("resource type of `%s' not supported\n", url);
- rc = GPG_ERR_GENERAL;
+ rc = G10ERR_GENERAL;
goto leave;
}
@@ -236,7 +308,18 @@ keydb_add_resource (const char *url, int flags, int secret)
leave:
if (rc)
- log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror (rc));
+ {
+ /* Secret keyrings are not required in all cases. To avoid
+ having gpg return failure we use log_info here if the
+ rewsource is a secret one and marked as default
+ resource. */
+ if ((flags&4) && secret)
+ log_info (_("keyblock resource `%s': %s\n"),
+ filename, g10_errstr(rc));
+ else
+ log_error (_("keyblock resource `%s': %s\n"),
+ filename, g10_errstr(rc));
+ }
else if (secret)
any_secret = 1;
else
@@ -254,7 +337,7 @@ keydb_new (int secret)
KEYDB_HANDLE hd;
int i, j;
- hd = xcalloc (1,sizeof *hd);
+ hd = xmalloc_clear (sizeof *hd);
hd->found = -1;
assert (used_resources <= MAX_KEYDB_RESOURCES);
@@ -414,14 +497,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
int rc = 0;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
- rc = GPG_ERR_GENERAL; /* oops */
+ rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
@@ -440,7 +523,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
int rc = 0;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
@@ -454,7 +537,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
- rc = GPG_ERR_GENERAL; /* oops */
+ rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
@@ -476,7 +559,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
int idx;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
if( opt.dry_run )
return 0;
@@ -486,7 +569,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
else if ( hd->current >= 0 && hd->current < hd->used)
idx = hd->current;
else
- return GPG_ERR_GENERAL;
+ return G10ERR_GENERAL;
rc = lock_all (hd);
if (rc)
@@ -494,7 +577,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
switch (hd->active[idx].type) {
case KEYDB_RESOURCE_TYPE_NONE:
- rc = GPG_ERR_GENERAL; /* oops */
+ rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
@@ -515,7 +598,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
int rc = -1;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
@@ -529,7 +612,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
- rc = GPG_ERR_GENERAL; /* oops */
+ rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
@@ -552,7 +635,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
int rc;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
rc = keydb_search_reset (hd); /* this does reset hd->current */
if (rc)
@@ -598,7 +681,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
* Rebuild the caches of all key resources.
*/
void
-keydb_rebuild_caches (void)
+keydb_rebuild_caches (int noisy)
{
int i, rc;
@@ -611,10 +694,10 @@ keydb_rebuild_caches (void)
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_rebuild_cache (all_resources[i].token);
+ rc = keyring_rebuild_cache (all_resources[i].token,noisy);
if (rc)
log_error (_("failed to rebuild keyring cache: %s\n"),
- gpg_strerror (rc));
+ g10_errstr (rc));
break;
}
}
@@ -631,7 +714,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
int i, rc = 0;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
hd->current = 0;
hd->found = -1;
@@ -660,7 +743,7 @@ keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
int rc = -1;
if (!hd)
- return GPG_ERR_INV_ARG;
+ return G10ERR_INV_ARG;
while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
switch (hd->active[hd->current].type) {