aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2004-08-13 17:00:05 +0000
committerWerner Koch <[email protected]>2004-08-13 17:00:05 +0000
commit620abc1658312d058088cb57372145618146da49 (patch)
treed104377ce927a3eded480f0190c6d45209a361d5
parentlibgnuintl.h get s now build from *.in (diff)
downloadgnupg-620abc1658312d058088cb57372145618146da49.tar.gz
gnupg-620abc1658312d058088cb57372145618146da49.zip
* keydb.c (keydb_add_resource): Factored keyring creation out to ..
(maybe_create_keyring): .. new. Make sure that we do the checks in a locked state. Problem reported by Stefan Haller.
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/gpgv.c1
-rw-r--r--g10/keydb.c161
-rw-r--r--include/util.h1
-rw-r--r--util/ChangeLog7
-rw-r--r--util/dotlock.c33
6 files changed, 149 insertions, 62 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 2f1204475..d874c8385 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,11 @@
+2004-08-11 Werner Koch <[email protected]>
+
+ * gpgv.c (destroy_dotlock): New stub.
+
+ * keydb.c (keydb_add_resource): Factored keyring creation out to ..
+ (maybe_create_keyring): .. new. Make sure that we do the checks
+ in a locked state. Problem reported by Stefan Haller.
+
2004-08-09 Werner Koch <[email protected]>
* Makefile.am (LDADD): Replaced INTLLIBS by LIBINTL.
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 31034f1fe..6337d7242 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -390,6 +390,7 @@ int tty_no_terminal(int onoff) {return 0;}
/* We do not do any locking, so use these stubs here */
void disable_dotlock(void) {}
DOTLOCK create_dotlock( const char *file_to_lock ) { return NULL; }
+void destroy_dotlock (DOTLOCK h) { };
int make_dotlock( DOTLOCK h, long timeout ) { return 0;}
int release_dotlock( DOTLOCK h ) {return 0;}
void remove_lockfiles(void) {}
diff --git a/g10/keydb.c b/g10/keydb.c
index b85d83649..96c37b4d9 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 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -69,6 +69,111 @@ 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 alread
+ 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;
+ 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 G10ERR_OPEN_FILE;
+
+ /* 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. */
+
+ 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 = G10ERR_OPEN_FILE;
+ *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 = 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:
+ 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
@@ -81,7 +186,6 @@ keydb_add_resource (const char *url, int force, int secret)
{
static int any_secret, any_public;
const char *resname = url;
- IOBUF iobuf = NULL;
char *filename = NULL;
int rc = 0;
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
@@ -145,56 +249,9 @@ keydb_add_resource (const char *url, int force, int secret)
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 = G10ERR_OPEN_FILE;
- 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 = G10ERR_OPEN_FILE;
- *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 = G10ERR_OPEN_FILE;
- 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;
token = keyring_register_filename (filename, secret);
if (!token)
diff --git a/include/util.h b/include/util.h
index bbbef0472..8156a7ed7 100644
--- a/include/util.h
+++ b/include/util.h
@@ -144,6 +144,7 @@ typedef struct dotlock_handle *DOTLOCK;
void disable_dotlock(void);
DOTLOCK create_dotlock( const char *file_to_lock );
+void destroy_dotlock ( DOTLOCK h );
int make_dotlock( DOTLOCK h, long timeout );
int release_dotlock( DOTLOCK h );
void remove_lockfiles (void);
diff --git a/util/ChangeLog b/util/ChangeLog
index adfd49191..d151326d1 100644
--- a/util/ChangeLog
+++ b/util/ChangeLog
@@ -1,3 +1,8 @@
+2004-08-11 Werner Koch <[email protected]>
+
+ * dotlock.c (destroy_dotlock): New.
+ (remove_lockfiles): Implement in terms of destroy_dotlock.
+
2004-08-09 Werner Koch <[email protected]>
* Makefile.am (http-test): Replaced INTLLIBS by LIBINTL.
@@ -1105,7 +1110,7 @@ Fri Feb 13 15:14:13 1998 Werner Koch ([email protected])
- Copyright 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright 1998,1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
diff --git a/util/dotlock.c b/util/dotlock.c
index f4ab37327..f28b0e409 100644
--- a/util/dotlock.c
+++ b/util/dotlock.c
@@ -1,5 +1,5 @@
/* dotlock.c - dotfile locking
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -197,6 +197,28 @@ create_dotlock( const char *file_to_lock )
return h;
}
+
+void
+destroy_dotlock ( DOTLOCK h )
+{
+#if !defined (HAVE_DOSISH_SYSTEM)
+ if ( h )
+ {
+ if (!h->disable)
+ {
+ if (h->locked)
+ unlink (h->lockname);
+ unlink (h->tname);
+ m_free (h->tname);
+ m_free (h->lockname);
+ }
+ m_free(h);
+ }
+#endif
+}
+
+
+
static int
maybe_deadlock( DOTLOCK h )
{
@@ -407,14 +429,7 @@ remove_lockfiles()
while( h ) {
h2 = h->next;
- if( !h->disable ) {
- if( h->locked )
- unlink( h->lockname );
- unlink(h->tname);
- m_free(h->tname);
- m_free(h->lockname);
- }
- m_free(h);
+ destroy_dotlock (h);
h = h2;
}
#endif