1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Merge branch 'STABLE-BRANCH-2-4'

--

Fixed conflicts in
        NEWS
	g10/encrypt.c
	sm/encrypt.c
	sm/sign.c
This commit is contained in:
Werner Koch 2023-12-22 13:45:02 +01:00
commit 2764ee309a
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
38 changed files with 1149 additions and 370 deletions

View file

@ -256,6 +256,13 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
if (! initialized)
return 1;
/* Map the the generic ECC algo to ECDSA if requested. */
if ((algo_flags & PK_ALGO_FLAG_ECC18)
&& algo == GCRY_PK_ECC
&& (use == PK_USE_VERIFICATION
|| use == PK_USE_SIGNING))
algo = GCRY_PK_ECDSA;
switch (compliance)
{
case CO_DE_VS:
@ -280,7 +287,6 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
default:
log_assert (!"reached");
}
(void)algo_flags;
break;
case PUBKEY_ALGO_DSA:
@ -301,7 +307,7 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
result = (use == PK_USE_DECRYPTION);
break;
case PUBKEY_ALGO_ECDH:
case PUBKEY_ALGO_ECDH: /* Same value as GCRY_PK_ECC, i.e. 18 */
case GCRY_PK_ECDH:
if (use == PK_USE_DECRYPTION)
result = 1;
@ -549,6 +555,9 @@ gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
int *result;
int res;
/* #warning debug code ahead */
/* return 1; */
result = get_compliance_cache (compliance, 1);
if (result && *result != -1)

View file

@ -50,6 +50,7 @@ enum pk_use_case
/* Flags to distinguish public key algorithm variants. */
#define PK_ALGO_FLAG_RSAPSS 1 /* Use rsaPSS padding. */
#define PK_ALGO_FLAG_ECC18 256 /* GCRY_PK_ECC is used in a generic way. */
int gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,

View file

@ -291,6 +291,7 @@
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/utsname.h>
# include <dirent.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
@ -393,9 +394,18 @@ struct dotlock_handle
unsigned int locked:1; /* Lock status. */
unsigned int disable:1; /* If true, locking is disabled. */
unsigned int use_o_excl:1; /* Use open (O_EXCL) for locking. */
unsigned int by_parent:1; /* Parent does the locking. */
unsigned int no_write:1; /* No write to the lockfile. */
int extra_fd; /* A place for the caller to store an FD. */
/* An optional info callback - see dotlock_set_info_cb. */
int (*info_cb)(dotlock_t, void *,
enum dotlock_reasons reason,
const char *,...);
void *info_cb_value;
#ifdef HAVE_DOSISH_SYSTEM
HANDLE lockhd; /* The W32 handle of the lock file. */
#else /*!HAVE_DOSISH_SYSTEM */
@ -545,8 +555,15 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
{
int e = errno;
my_info_2 ("error opening lockfile '%s': %s\n",
h->lockname, strerror(errno) );
if (errno != ENOENT)
{
my_info_2 ("error opening lockfile '%s': %s\n",
h->lockname, strerror(errno) );
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"error opening lockfile '%s': %s\n",
h->lockname, strerror (errno) );
}
if (buffer != buffer_space)
xfree (buffer);
my_set_errno (e); /* Need to return ERRNO here. */
@ -564,6 +581,10 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
{
int e = errno;
my_info_1 ("error reading lockfile '%s'\n", h->lockname );
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"error reading lockfile '%s': %s\n",
h->lockname, strerror (errno) );
close (fd);
if (buffer != buffer_space)
xfree (buffer);
@ -583,6 +604,9 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
if (nread < 11)
{
my_info_1 ("invalid size of lockfile '%s'\n", h->lockname);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_INV_FILE,
"invalid size of lockfile '%s'\n", h->lockname);
if (buffer != buffer_space)
xfree (buffer);
my_set_errno (EINVAL);
@ -594,6 +618,9 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|| !pid )
{
my_error_2 ("invalid pid %d in lockfile '%s'\n", pid, h->lockname);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_INV_FILE,
"invalid pid %d in lockfile '%s'\n", pid, h->lockname);
if (buffer != buffer_space)
xfree (buffer);
my_set_errno (EINVAL);
@ -655,6 +682,80 @@ use_hardlinks_p (const char *tname)
#ifdef HAVE_POSIX_SYSTEM
static int
dotlock_get_process_id (dotlock_t h)
{
return h->by_parent? (int)getppid(): (int)getpid();
}
static int
dotlock_detect_tname (dotlock_t h)
{
struct stat sb;
DIR *dir;
char *dirname;
char *basename;
struct dirent *d;
int r;
if (stat (h->lockname, &sb))
return -1;
basename = make_basename (h->lockname, NULL);
dirname = make_dirname (h->lockname);
dir = opendir (dirname);
if (dir == NULL)
{
xfree (basename);
xfree (dirname);
return -1;
}
while ((d = readdir (dir)))
if (sb.st_ino == d->d_ino && strcmp (d->d_name, basename))
break;
if (d)
{
int len = strlen (h->tname);
int dlen = strlen (d->d_name);
const char *tname_path;
if (dlen > len)
{
xfree (basename);
xfree (dirname);
return -1;
}
strcpy (stpcpy (stpcpy (h->tname, dirname), DIRSEP_S), d->d_name);
h->use_o_excl = 0;
tname_path = strchr (h->tname + strlen (dirname) + 2, '.');
if (!tname_path)
{
xfree (basename);
xfree (dirname);
return -1;
}
h->nodename_off = tname_path - h->tname + 1;
}
else
h->use_o_excl = 1;
r = closedir (dir);
if (r)
{
xfree (basename);
xfree (dirname);
return r;
}
xfree (basename);
xfree (dirname);
return 0;
}
/* Locking core for Unix. It used a temporary file and the link
system call to make locking an atomic operation. */
static dotlock_t
@ -667,8 +768,10 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
int dirpartlen;
struct utsname utsbuf;
size_t tnamelen;
int pid;
snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
pid = dotlock_get_process_id (h);
snprintf (pidstr, sizeof pidstr, "%10d\n", pid);
/* Create a temporary file. */
if ( uname ( &utsbuf ) )
@ -702,10 +805,17 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
}
h->nodename_len = strlen (nodename);
if (h->no_write)
{
memset (h->tname, '_', tnamelen);
h->tname[tnamelen] = 0;
goto skip_write;
}
snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
h->nodename_off = strlen (h->tname);
snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
"%s.%d", nodename, (int)getpid ());
"%s.%d", nodename, pid);
do
{
@ -722,6 +832,10 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
UNLOCK_all_lockfiles ();
my_error_2 (_("failed to create temporary file '%s': %s\n"),
h->tname, strerror (errno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
_("failed to create temporary file '%s': %s\n"),
h->tname, strerror (errno));
xfree (h->tname);
xfree (h);
my_set_errno (saveerrno);
@ -755,11 +869,16 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
int saveerrno = errno;
my_error_2 ("can't check whether hardlinks are supported for '%s': %s\n"
, h->tname, strerror (saveerrno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_CONFIG_TEST,
"can't check whether hardlinks are supported for '%s': %s\n"
, h->tname, strerror (saveerrno));
my_set_errno (saveerrno);
}
goto write_failed;
}
skip_write:
h->lockname = xtrymalloc (strlen (file_to_lock) + 6 );
if (!h->lockname)
{
@ -775,6 +894,20 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
UNLOCK_all_lockfiles ();
if (h->no_write)
{
if (dotlock_detect_tname (h) < 0)
{
xfree (h->lockname);
xfree (h->tname);
xfree (h);
my_set_errno (EACCES);
return NULL;
}
h->locked = 1;
}
return h;
write_failed:
@ -783,6 +916,11 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
all_lockfiles = h->next;
UNLOCK_all_lockfiles ();
my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
_("error writing to '%s': %s\n"),
h->tname, strerror (errno));
if ( fd != -1 )
close (fd);
unlink (h->tname);
@ -849,6 +987,10 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
all_lockfiles = h->next;
UNLOCK_all_lockfiles ();
my_error_2 (_("can't create '%s': %s\n"), h->lockname, w32_strerror (-1));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
_("can't create '%s': %s\n"),
h->lockname, w32_strerror (-1));
xfree (h->lockname);
xfree (h);
my_set_errno (saveerrno);
@ -873,7 +1015,15 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
used.
FLAGS must be 0.
FLAGS may include DOTLOCK_PREPARE_CREATE bit, which only allocates
the handle and requires a further call to dotlock_finish_create.
This can be used to set a callback between these calls.
FLAGS may include DOTLOCK_LOCK_BY_PARENT bit, when it's the parent
process controlling the lock. This is used by dotlock util.
FLAGS may include DOTLOCK_LOCKED bit, when it should not create the
lockfile, but to unlock. This is used by dotlock util.
The function returns an new handle which needs to be released using
destroy_dotlock but gets also released at the termination of the
@ -885,8 +1035,13 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
{
static int initialized;
dotlock_t h;
#ifndef HAVE_DOSISH_SYSTEM
int by_parent = 0;
int no_write = 0;
#endif
if ( !initialized )
if ( !(flags & DOTLOCK_LOCK_BY_PARENT)
&& !initialized )
{
atexit (dotlock_remove_lockfiles);
initialized = 1;
@ -895,7 +1050,15 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
if ( !file_to_lock )
return NULL; /* Only initialization was requested. */
if (flags)
#ifndef HAVE_DOSISH_SYSTEM
if ((flags & DOTLOCK_LOCK_BY_PARENT) || (flags & DOTLOCK_LOCKED))
{
by_parent = !!(flags & DOTLOCK_LOCK_BY_PARENT);
no_write = !!(flags & DOTLOCK_LOCKED);
flags &= ~(DOTLOCK_LOCK_BY_PARENT | DOTLOCK_LOCKED);
}
#endif
if ((flags & ~DOTLOCK_PREPARE_CREATE))
{
my_set_errno (EINVAL);
return NULL;
@ -905,6 +1068,10 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
if (!h)
return NULL;
h->extra_fd = -1;
#ifndef HAVE_DOSISH_SYSTEM
h->by_parent = by_parent;
h->no_write = no_write;
#endif
if (never_lock)
{
@ -916,6 +1083,24 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
return h;
}
if ((flags & DOTLOCK_PREPARE_CREATE))
return h;
else
return dotlock_finish_create (h, file_to_lock);
}
/* This function may be used along with dotlock_create (file_name,
* DOTLOCK_PREPARE_CREATE) to finish the creation call. The given
* filename shall be the same as passed to dotlock_create. On success
* the same handle H is returned, on error NULL is returned and H is
* released. */
dotlock_t
dotlock_finish_create (dotlock_t h, const char *file_to_lock)
{
if (!h || !file_to_lock)
return NULL;
#ifdef HAVE_DOSISH_SYSTEM
return dotlock_create_w32 (h, file_to_lock);
#else /*!HAVE_DOSISH_SYSTEM */
@ -942,6 +1127,24 @@ dotlock_get_fd (dotlock_t h)
}
/* Set a callback function for info diagnostics. The callback
* function CB is called with the handle, the opaque value OPAQUE, a
* reason code, and a format string with its arguments. The callback
* shall return 0 to continue operation or true in which case the
* current function will be terminated with an error. */
void
dotlock_set_info_cb (dotlock_t h,
int (*cb)(dotlock_t, void *,
enum dotlock_reasons reason,
const char *,...),
void *opaque)
{
h->info_cb = cb;
h->info_cb_value = opaque;
}
#ifdef HAVE_POSIX_SYSTEM
/* Unix specific code of destroy_dotlock. */
@ -952,7 +1155,6 @@ dotlock_destroy_unix (dotlock_t h)
unlink (h->lockname);
if (h->tname && !h->use_o_excl)
unlink (h->tname);
xfree (h->tname);
}
#endif /*HAVE_POSIX_SYSTEM*/
@ -998,15 +1200,28 @@ dotlock_destroy (dotlock_t h)
UNLOCK_all_lockfiles ();
/* Then destroy the lock. */
if (!h->disable)
if (!h->disable
&& (!h->by_parent || h->no_write))
{
/* NOTE: under the condition of (by_parent && !no_write),
it doesn't come here. So, the lock file remains. */
#ifdef HAVE_DOSISH_SYSTEM
dotlock_destroy_w32 (h);
#else /* !HAVE_DOSISH_SYSTEM */
dotlock_destroy_unix (h);
#endif /* HAVE_DOSISH_SYSTEM */
xfree (h->lockname);
}
#ifdef HAVE_POSIX_SYSTEM
/* When DOTLOCK_LOCK_BY_PARENT and lock fails,
the temporary file created should be removed. */
if (h->by_parent && !h->no_write && !h->locked)
if (h->tname && !h->use_o_excl)
unlink (h->tname);
xfree (h->tname);
#endif
xfree (h->lockname);
xfree(h);
}
@ -1061,6 +1276,7 @@ static int
dotlock_take_unix (dotlock_t h, long timeout)
{
int wtime = 0;
int timedout = 0;
int sumtime = 0;
int pid;
int lastpid = -1;
@ -1089,6 +1305,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
saveerrno = errno;
my_error_2 ("lock not made: open(O_EXCL) of '%s' failed: %s\n",
h->lockname, strerror (saveerrno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"lock not made: open(O_EXCL) of '%s' failed: %s\n",
h->lockname, strerror (saveerrno));
my_set_errno (saveerrno);
return -1;
}
@ -1096,7 +1316,8 @@ dotlock_take_unix (dotlock_t h, long timeout)
{
char pidstr[16];
snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid());
snprintf (pidstr, sizeof pidstr, "%10d\n",
dotlock_get_process_id (h));
if (write (fd, pidstr, 11 ) == 11
&& write (fd, h->tname + h->nodename_off,h->nodename_len)
== h->nodename_len
@ -1110,6 +1331,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
saveerrno = errno;
my_error_2 ("lock not made: writing to '%s' failed: %s\n",
h->lockname, strerror (errno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"lock not made: writing to '%s' failed: %s\n",
h->lockname, strerror (errno));
close (fd);
unlink (h->lockname);
my_set_errno (saveerrno);
@ -1128,6 +1353,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
saveerrno = errno;
my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
strerror (errno));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"lock not made: Oops: stat of tmp file failed: %s\n",
strerror (errno));
/* In theory this might be a severe error: It is possible
that link succeeded but stat failed due to changed
permissions. We can't do anything about it, though. */
@ -1149,16 +1378,19 @@ dotlock_take_unix (dotlock_t h, long timeout)
{
saveerrno = errno;
my_info_0 ("cannot read lockfile\n");
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"cannot read lockfile\n");
my_set_errno (saveerrno);
return -1;
}
my_info_0 ("lockfile disappeared\n");
goto again;
}
else if ( (pid == getpid() && same_node)
else if ( (pid == dotlock_get_process_id (h) && same_node && !h->by_parent)
|| (same_node && kill (pid, 0) && errno == ESRCH) )
/* Stale lockfile is detected. */
{
/* Stale lockfile is detected. */
struct stat sb;
/* Check if it's unlocked during examining the lockfile. */
@ -1201,6 +1433,9 @@ dotlock_take_unix (dotlock_t h, long timeout)
unlink (h->lockname);
my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
close (fd);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_STALE_REMOVED,
_("removing stale lockfile (created by %d)\n"), pid);
goto again;
}
@ -1218,6 +1453,8 @@ dotlock_take_unix (dotlock_t h, long timeout)
wtime = 0; /* Reset because owner chnaged. */
wtimereal = next_wait_interval (&wtime, &timeout);
if (!timeout)
timedout = 1; /* remember. */
sumtime += wtimereal;
if (sumtime >= 1500)
@ -1225,6 +1462,15 @@ dotlock_take_unix (dotlock_t h, long timeout)
sumtime = 0;
my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
if (h->info_cb
&& h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
_("waiting for lock (held by %d%s) %s...\n"),
pid, maybe_dead,
maybe_deadlock(h)? _("(deadlock?) "):""))
{
my_set_errno (ECANCELED);
return -1;
}
}
tv.tv_sec = wtimereal / 1000;
@ -1233,7 +1479,7 @@ dotlock_take_unix (dotlock_t h, long timeout)
goto again;
}
my_set_errno (EACCES);
my_set_errno (timedout? ETIMEDOUT : EACCES);
return -1;
}
#endif /*HAVE_POSIX_SYSTEM*/
@ -1246,6 +1492,7 @@ static int
dotlock_take_w32 (dotlock_t h, long timeout)
{
int wtime = 0;
int timedout = 0;
int w32err;
OVERLAPPED ovl;
@ -1264,7 +1511,11 @@ dotlock_take_w32 (dotlock_t h, long timeout)
{
my_error_2 (_("lock '%s' not made: %s\n"),
h->lockname, w32_strerror (w32err));
my_set_errno (map_w32_to_errno (w32err));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
_("lock '%s' not made: %s\n"),
h->lockname, w32_strerror (w32err));
_set_errno (map_w32_to_errno (w32err));
return -1;
}
@ -1273,15 +1524,26 @@ dotlock_take_w32 (dotlock_t h, long timeout)
int wtimereal;
wtimereal = next_wait_interval (&wtime, &timeout);
if (!timeout)
timedout = 1; /* remember. */
if (wtime >= 800)
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
{
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
if (h->info_cb
&& h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
_("waiting for lock %s...\n"), h->lockname))
{
my_set_errno (ECANCELED);
return -1;
}
}
Sleep (wtimereal);
goto again;
}
my_set_errno (EACCES);
my_set_errno (timedout? ETIMEDOUT : EACCES);
return -1;
}
#endif /*HAVE_DOSISH_SYSTEM*/
@ -1328,12 +1590,18 @@ dotlock_release_unix (dotlock_t h)
{
saveerrno = errno;
my_error_0 ("release_dotlock: lockfile error\n");
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"release_dotlock: lockfile error\n");
my_set_errno (saveerrno);
return -1;
}
if ( pid != getpid() || !same_node )
if ( pid != dotlock_get_process_id (h) || !same_node )
{
my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_CONFLICT,
"release_dotlock: not our lock (pid=%d)\n", pid);
my_set_errno (EACCES);
return -1;
}
@ -1343,6 +1611,10 @@ dotlock_release_unix (dotlock_t h)
saveerrno = errno;
my_error_1 ("release_dotlock: error removing lockfile '%s'\n",
h->lockname);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"release_dotlock: error removing lockfile '%s'\n",
h->lockname);
my_set_errno (saveerrno);
return -1;
}
@ -1363,10 +1635,15 @@ dotlock_release_w32 (dotlock_t h)
memset (&ovl, 0, sizeof ovl);
if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
{
int saveerrno = map_w32_to_errno (GetLastError ());
int ec = (int)GetLastError ();
my_error_2 ("release_dotlock: error removing lockfile '%s': %s\n",
h->lockname, w32_strerror (-1));
my_set_errno (saveerrno);
h->lockname, w32_strerror (ec));
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
"release_dotlock: error removing lockfile '%s': %s\n",
h->lockname, w32_strerror (ec));
my_set_errno (map_w32_to_errno (ec));
return -1;
}
@ -1397,6 +1674,9 @@ dotlock_release (dotlock_t h)
if ( !h->locked )
{
my_debug_1 ("Oops, '%s' is not locked\n", h->lockname);
if (h->info_cb)
h->info_cb (h, h->info_cb_value, DOTLOCK_NOT_LOCKED,
"Oops, '%s' is not locked\n", h->lockname);
return 0;
}

View file

@ -97,12 +97,35 @@ extern "C"
struct dotlock_handle;
typedef struct dotlock_handle *dotlock_t;
enum dotlock_reasons
{
DOTLOCK_CONFIG_TEST, /* Can't check system - function terminates. */
DOTLOCK_FILE_ERROR, /* General file error - function terminates. */
DOTLOCK_INV_FILE, /* Invalid file - function terminates. */
DOTLOCK_CONFLICT, /* Something is wrong - function terminates. */
DOTLOCK_NOT_LOCKED, /* Not locked - No action required. */
DOTLOCK_STALE_REMOVED, /* Stale lock file was removed - retrying. */
DOTLOCK_WAITING /* Waiting for the lock - may be terminated. */
};
/* Flags for dotlock_create. */
#define DOTLOCK_PREPARE_CREATE (1U << 5) /* Require dotlock_finish_create. */
#define DOTLOCK_LOCK_BY_PARENT (1U << 6) /* Used by dotlock util. */
#define DOTLOCK_LOCKED (1U << 7) /* Used by dotlock util. */
void dotlock_disable (void);
dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags);
dotlock_t dotlock_finish_create (dotlock_t h, const char *file_to_lock);
void dotlock_set_fd (dotlock_t h, int fd);
int dotlock_get_fd (dotlock_t h);
void dotlock_set_info_cb (dotlock_t h,
int (*cb)(dotlock_t, void *,
enum dotlock_reasons reason,
const char *,...),
void *opaque);
void dotlock_destroy (dotlock_t h);
int dotlock_take (dotlock_t h, long timeout);
int dotlock_is_locked (dotlock_t h);
int dotlock_release (dotlock_t h);
void dotlock_remove_lockfiles (void);

View file

@ -77,6 +77,14 @@
#endif
/* Mode flags for unix_rootdir. */
enum wantdir_values {
WANTDIR_ROOT = 0,
WANTDIR_SYSCONF,
WANTDIR_SOCKET
};
/* The GnuPG homedir. This is only accessed by the functions
* gnupg_homedir and gnupg_set_homedir. Malloced. */
static char *the_gnupg_homedir;
@ -491,11 +499,12 @@ w32_rootdir (void)
* file system. If WANT_SYSCONFDIR is true the optional sysconfdir
* entry is returned. */
static const char *
unix_rootdir (int want_sysconfdir)
unix_rootdir (enum wantdir_values wantdir)
{
static int checked;
static char *dir; /* for the rootdir */
static char *sdir; /* for the sysconfdir */
static char *s2dir; /* for the socketdir */
if (!checked)
{
@ -510,8 +519,10 @@ unix_rootdir (int want_sysconfdir)
estream_t fp;
char *rootdir;
char *sysconfdir;
char *socketdir;
const char *name;
int ignoreall = 0;
int okay;
for (;;)
{
@ -602,45 +613,44 @@ unix_rootdir (int want_sysconfdir)
linelen = 0;
rootdir = NULL;
sysconfdir = NULL;
socketdir = NULL;
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
{
static const char *names[] =
{
"rootdir",
"sysconfdir",
"socketdir",
".enable"
};
int i;
size_t n;
/* Strip NL and CR, if present. */
while (length > 0
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
line[--length] = 0;
trim_spaces (line);
if (!strncmp (line, "rootdir=", 8))
/* Find the stamement. */
name = NULL;
for (i=0; i < DIM (names); i++)
{
name = "rootdir";
p = line + 8;
n = strlen (names[i]);
if (!strncmp (line, names[i], n))
{
while (line[n] == ' ' || line[n] == '\t')
n++;
if (line[n] == '=')
{
name = names[i];
p = line + n + 1;
break;
}
}
}
else if (!strncmp (line, "rootdir =", 9)) /* (What a kludge) */
{
name = "rootdir";
p = line + 9;
}
else if (!strncmp (line, "sysconfdir=", 11))
{
name = "sysconfdir";
p = line + 11;
}
else if (!strncmp (line, "sysconfdir =", 12)) /* (What a kludge) */
{
name = "sysconfdir";
p = line + 12;
}
else if (!strncmp (line, ".enable=", 8))
{
name = ".enable";
p = line + 8;
}
else if (!strncmp (line, ".enable =", 9))
{
name = ".enable";
p = line + 9;
}
else
continue;
if (!name)
continue; /* Statement not known. */
trim_spaces (p);
p = substitute_envvars (p);
if (!p)
@ -665,6 +675,11 @@ unix_rootdir (int want_sysconfdir)
xfree (sysconfdir);
sysconfdir = p;
}
else if (!strcmp (name, "socketdir"))
{
xfree (socketdir);
socketdir = p;
}
else
{
xfree (rootdir);
@ -680,6 +695,7 @@ unix_rootdir (int want_sysconfdir)
xfree (line);
xfree (rootdir);
xfree (sysconfdir);
xfree (socketdir);
checked = 1;
return NULL;
}
@ -687,29 +703,26 @@ unix_rootdir (int want_sysconfdir)
xfree (buffer);
xfree (line);
okay = 0;
if (ignoreall)
{
xfree (rootdir);
xfree (sysconfdir);
sdir = dir = NULL;
}
;
else if (!rootdir || !*rootdir || *rootdir != '/')
{
log_info ("invalid rootdir '%s' specified in gpgconf.ctl\n", rootdir);
xfree (rootdir);
xfree (sysconfdir);
dir = NULL;
}
else if (sysconfdir && (!*sysconfdir || *sysconfdir != '/'))
{
log_info ("invalid sysconfdir '%s' specified in gpgconf.ctl\n",
sysconfdir);
xfree (rootdir);
xfree (sysconfdir);
dir = NULL;
}
else if (socketdir && (!*socketdir || *socketdir != '/'))
{
log_info ("invalid socketdir '%s' specified in gpgconf.ctl\n",
socketdir);
}
else
{
okay = 1;
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
rootdir[strlen (rootdir)-1] = 0;
dir = rootdir;
@ -723,11 +736,34 @@ unix_rootdir (int want_sysconfdir)
gpgrt_annotate_leaked_object (sdir);
/* log_info ("want sysconfdir '%s'\n", sdir); */
}
if (socketdir)
{
while (*socketdir && socketdir[strlen (socketdir)-1] == '/')
socketdir[strlen (socketdir)-1] = 0;
s2dir = socketdir;
gpgrt_annotate_leaked_object (s2dir);
/* log_info ("want socketdir '%s'\n", s2dir); */
}
}
if (!okay)
{
xfree (rootdir);
xfree (sysconfdir);
xfree (socketdir);
dir = sdir = s2dir = NULL;
}
checked = 1;
}
return want_sysconfdir? sdir : dir;
switch (wantdir)
{
case WANTDIR_ROOT: return dir;
case WANTDIR_SYSCONF: return sdir;
case WANTDIR_SOCKET: return s2dir;
}
return NULL; /* Not reached. */
}
#endif /* Unix */
@ -1038,7 +1074,8 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
};
int i;
struct stat sb;
char prefix[19 + 1 + 20 + 6 + 1];
char prefixbuffer[19 + 1 + 20 + 6 + 1];
const char *prefix;
const char *s;
char *name = NULL;
@ -1053,35 +1090,42 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
* as a background process with no (desktop) user logged in. Thus
* we better don't do that. */
/* Check whether we have a /run/[gnupg/]user dir. */
for (i=0; bases[i]; i++)
prefix = unix_rootdir (WANTDIR_SOCKET);
if (!prefix)
{
snprintf (prefix, sizeof prefix, "%s/user/%u",
bases[i], (unsigned int)getuid ());
if (!stat (prefix, &sb) && S_ISDIR(sb.st_mode))
break;
}
if (!bases[i])
{
*r_info |= 2; /* No /run/user directory. */
goto leave;
/* gpgconf.ctl does not specify a directory. Check whether we
* have the usual /run/[gnupg/]user dir. */
for (i=0; bases[i]; i++)
{
snprintf (prefixbuffer, sizeof prefixbuffer, "%s/user/%u",
bases[i], (unsigned int)getuid ());
prefix = prefixbuffer;
if (!stat (prefix, &sb) && S_ISDIR(sb.st_mode))
break;
}
if (!bases[i])
{
*r_info |= 2; /* No /run/user directory. */
goto leave;
}
if (sb.st_uid != getuid ())
{
*r_info |= 4; /* Not owned by the user. */
if (!skip_checks)
goto leave;
}
if (strlen (prefix) + 7 >= sizeof prefixbuffer)
{
*r_info |= 1; /* Ooops: Buffer too short to append "/gnupg". */
goto leave;
}
strcat (prefixbuffer, "/gnupg");
}
if (sb.st_uid != getuid ())
{
*r_info |= 4; /* Not owned by the user. */
if (!skip_checks)
goto leave;
}
if (strlen (prefix) + 7 >= sizeof prefix)
{
*r_info |= 1; /* Ooops: Buffer too short to append "/gnupg". */
goto leave;
}
strcat (prefix, "/gnupg");
/* Check whether the gnupg sub directory has proper permissions. */
/* Check whether the gnupg sub directory (or the specified diretory)
* has proper permissions. */
if (stat (prefix, &sb))
{
if (errno != ENOENT)
@ -1241,7 +1285,7 @@ gnupg_sysconfdir (void)
}
return name;
#else /*!HAVE_W32_SYSTEM*/
const char *dir = unix_rootdir (1);
const char *dir = unix_rootdir (WANTDIR_SYSCONF);
if (dir)
return dir;
else
@ -1270,7 +1314,7 @@ gnupg_bindir (void)
else
return rdir;
#else /*!HAVE_W32_SYSTEM*/
rdir = unix_rootdir (0);
rdir = unix_rootdir (WANTDIR_ROOT);
if (rdir)
{
if (!name)
@ -1297,7 +1341,7 @@ gnupg_libexecdir (void)
static char *name;
const char *rdir;
rdir = unix_rootdir (0);
rdir = unix_rootdir (WANTDIR_ROOT);
if (rdir)
{
if (!name)
@ -1327,7 +1371,7 @@ gnupg_libdir (void)
#else /*!HAVE_W32_SYSTEM*/
const char *rdir;
rdir = unix_rootdir (0);
rdir = unix_rootdir (WANTDIR_ROOT);
if (rdir)
{
if (!name)
@ -1358,7 +1402,7 @@ gnupg_datadir (void)
#else /*!HAVE_W32_SYSTEM*/
const char *rdir;
rdir = unix_rootdir (0);
rdir = unix_rootdir (WANTDIR_ROOT);
if (rdir)
{
if (!name)
@ -1390,7 +1434,7 @@ gnupg_localedir (void)
#else /*!HAVE_W32_SYSTEM*/
const char *rdir;
rdir = unix_rootdir (0);
rdir = unix_rootdir (WANTDIR_ROOT);
if (rdir)
{
if (!name)

View file

@ -48,6 +48,7 @@ struct name_value_container
struct name_value_entry *first;
struct name_value_entry *last;
unsigned int private_key_mode:1;
unsigned int modified:1;
};
@ -87,11 +88,15 @@ my_error (gpg_err_code_t ec)
/* Allocation and deallocation. */
/* Allocate a private key container structure. */
/* Allocate a name value container structure. */
nvc_t
nvc_new (void)
{
return xtrycalloc (1, sizeof (struct name_value_container));
nvc_t nvc;
nvc = xtrycalloc (1, sizeof (struct name_value_container));
if (nvc)
nvc->modified = 1;
return nvc;
}
@ -142,6 +147,24 @@ nvc_release (nvc_t pk)
xfree (pk);
}
/* Return the modified-flag of the container and clear it if CLEAR is
* set. That flag is set for a new container and set with each
* update. */
int
nvc_modified (nvc_t pk, int clear)
{
int modified;
if (!pk)
return 0;
modified = pk->modified;
if (clear)
pk->modified = 0;
return modified;
}
/* Dealing with names and values. */
@ -427,6 +450,8 @@ _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value,
else
pk->first = pk->last = e;
pk->modified = 1;
leave:
if (err)
{
@ -476,36 +501,29 @@ nvc_set (nvc_t pk, const char *name, const char *value)
e = nvc_lookup (pk, name);
if (e)
{
char *v;
v = xtrystrdup (value);
if (v == NULL)
return my_error_from_syserror ();
free_strlist_wipe (e->raw_value);
e->raw_value = NULL;
if (e->value)
wipememory (e->value, strlen (e->value));
xfree (e->value);
e->value = v;
return 0;
}
return nve_set (pk, e, value);
else
return nvc_add (pk, name, value);
}
/* Update entry E to VALUE. */
/* Update entry E to VALUE. PK is optional; if given its modified
* flag will be updated. */
gpg_error_t
nve_set (nve_t e, const char *value)
nve_set (nvc_t pk, nve_t e, const char *value)
{
char *v;
if (!e)
return GPG_ERR_INV_ARG;
if (e->value && value && !strcmp (e->value, value))
{
/* Setting same value - ignore this call and don't set the
* modified flag (if PK is given). */
return 0;
}
v = xtrystrdup (value? value:"");
if (!v)
return my_error_from_syserror ();
@ -516,6 +534,8 @@ nve_set (nve_t e, const char *value)
wipememory (e->value, strlen (e->value));
xfree (e->value);
e->value = v;
if (pk)
pk->modified = 1;
return 0;
}
@ -536,6 +556,7 @@ nvc_delete (nvc_t pk, nve_t entry)
pk->last = entry->prev;
nve_release (entry, pk->private_key_mode);
pk->modified = 1;
}

View file

@ -50,6 +50,9 @@ nvc_t nvc_new_private_key (void);
/* Release a name value container structure. */
void nvc_release (nvc_t pk);
/* Return the modified flag and optionally clear it. */
int nvc_modified (nvc_t pk, int clear);
/* Get the name. */
char *nve_name (nve_t pke);
@ -92,8 +95,8 @@ gpg_error_t nvc_add (nvc_t pk, const char *name, const char *value);
first entry is updated. */
gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value);
/* Update entry E to VALUE. */
gpg_error_t nve_set (nve_t e, const char *value);
/* Update entry E to VALUE. PK is optional. */
gpg_error_t nve_set (nvc_t pk, nve_t e, const char *value);
/* Delete the given entry from PK. */
void nvc_delete (nvc_t pk, nve_t pke);

View file

@ -122,6 +122,9 @@ typedef enum
SIGSUBPKT_ATTST_SIGS = 37, /* Attested Certifications. */
SIGSUBPKT_KEY_BLOCK = 38, /* Entire key used. */
SIGSUBPKT_META_HASH = 40, /* Literal Data Meta Hash. */
SIGSUBPKT_TRUST_ALIAS = 41, /* Trust Alias. */
SIGSUBPKT_FLAG_CRITICAL = 128
}
sigsubpkttype_t;

View file

@ -52,6 +52,7 @@
#ifdef HAVE_W32_SYSTEM
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
const char *
w32_strerror (int ec)
{
@ -174,6 +175,11 @@ strconcat (const char *s1, ...)
#define PGM "t-dotlock"
static int opt_silent;
#ifndef HAVE_W32_SYSTEM
static volatile int ctrl_c_pending_flag;
static void
@ -217,6 +223,9 @@ inf (const char *format, ...)
{
va_list arg_ptr;
if (opt_silent)
return;
va_start (arg_ptr, format);
fprintf (stderr, PGM "[%lu]: ", (unsigned long)getpid ());
vfprintf (stderr, format, arg_ptr);
@ -225,15 +234,35 @@ inf (const char *format, ...)
}
static int
lock_info_cb (dotlock_t h, void *opaque, enum dotlock_reasons reason,
const char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format);
fprintf (stderr, PGM "[%lu]: info_cb: reason %d, ",
(unsigned long)getpid (), (int)reason);
vfprintf (stderr, format, arg_ptr);
va_end (arg_ptr);
return 0;
}
static void
lock_and_unlock (const char *fname)
{
dotlock_t h;
unsigned long usec;
h = dotlock_create (fname, 0);
h = dotlock_create (fname, DOTLOCK_PREPARE_CREATE);
if (!h)
die ("error creating lock file for '%s': %s", fname, strerror (errno));
dotlock_set_info_cb (h, lock_info_cb, NULL);
h = dotlock_finish_create (h, fname);
if (!h)
die ("error finishing lock file creation for '%s': %s",
fname, strerror (errno));
inf ("lock created");
do
@ -270,6 +299,11 @@ main (int argc, char **argv)
ctrl_c_pending_flag = 1;
argc--;
}
if (argc > 1 && !strcmp (argv[1], "--silent"))
{
opt_silent = 1;
argc--;
}
if (argc > 1)
fname = argv[argc-1];