agent: Keep some permissions of private-keys-v1.d.

* common/sysutils.c (modestr_to_mode): Re-implement.
(gnupg_chmod): Support keeping of permissions.
--

GnuPG-bug-id: 2312
This commit is contained in:
Werner Koch 2020-09-09 20:33:06 +02:00
parent adec6a84f6
commit 8ed85ef3de
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 54 additions and 26 deletions

View File

@ -2273,10 +2273,20 @@ create_private_keys_directory (const char *home)
fname, strerror (errno) );
else if (!opt.quiet)
log_info (_("directory '%s' created\n"), fname);
if (gnupg_chmod (fname, "-rwx"))
log_error (_("can't set permissions of '%s': %s\n"),
fname, strerror (errno));
}
else
{
/* The file exists or another error. Make sure we have sensible
* permissions. We enforce rwx for user but keep existing group
* permissions. Permissions for other are always cleared. */
if (gnupg_chmod (fname, "-rwx...---"))
log_error (_("can't set permissions of '%s': %s\n"),
fname, strerror (errno));
}
if (gnupg_chmod (fname, "-rwx"))
log_error (_("can't set permissions of '%s': %s\n"),
fname, strerror (errno));
xfree (fname);
}

View File

@ -749,33 +749,38 @@ gnupg_rename_file (const char *oldname, const char *newname, int *block_signals)
#ifndef HAVE_W32_SYSTEM
static mode_t
modestr_to_mode (const char *modestr)
modestr_to_mode (const char *modestr, mode_t oldmode)
{
static struct {
char letter;
mode_t value;
} table[] = { { '-', 0 },
{ 'r', S_IRUSR }, { 'w', S_IWUSR }, { 'x', S_IXUSR },
{ 'r', S_IRGRP }, { 'w', S_IWGRP }, { 'x', S_IXGRP },
{ 'r', S_IROTH }, { 'w', S_IWOTH }, { 'x', S_IXOTH } };
int idx;
mode_t mode = 0;
if (modestr && *modestr)
/* For now we only support a string as used by ls(1) and no octal
* numbers. The first character must be a dash. */
for (idx=0; idx < 10 && *modestr; idx++, modestr++)
{
modestr++;
if (*modestr && *modestr++ == 'r')
mode |= S_IRUSR;
if (*modestr && *modestr++ == 'w')
mode |= S_IWUSR;
if (*modestr && *modestr++ == 'x')
mode |= S_IXUSR;
if (*modestr && *modestr++ == 'r')
mode |= S_IRGRP;
if (*modestr && *modestr++ == 'w')
mode |= S_IWGRP;
if (*modestr && *modestr++ == 'x')
mode |= S_IXGRP;
if (*modestr && *modestr++ == 'r')
mode |= S_IROTH;
if (*modestr && *modestr++ == 'w')
mode |= S_IWOTH;
if (*modestr && *modestr++ == 'x')
mode |= S_IXOTH;
if (*modestr == table[idx].letter)
mode |= table[idx].value;
else if (*modestr == '.')
{
if (!idx)
; /* Skip the dummy. */
else if ((oldmode & table[idx].value))
mode |= (oldmode & table[idx].value);
else
mode &= ~(oldmode & table[idx].value);
}
else if (*modestr != '-')
break;
}
return mode;
}
#endif
@ -815,7 +820,8 @@ gnupg_chdir (const char *name)
/* A wrapper around chmod which takes a string for the mode argument.
This makes it easier to handle the mode argument which is not
defined on all systems. The format of the modestring is the same
as for gnupg_mkdir. */
as for gnupg_mkdir with extra feature that a '.' keeps the original
mode bit. */
int
gnupg_chmod (const char *name, const char *modestr)
{
@ -824,7 +830,19 @@ gnupg_chmod (const char *name, const char *modestr)
(void)modestr;
return 0;
#else
return chmod (name, modestr_to_mode (modestr));
mode_t oldmode;
if (strchr (modestr, '.'))
{
/* Get the old mode so that a '.' can copy that bit. */
struct stat st;
if (stat (name, &st))
return -1;
oldmode = st.st_mode;
}
else
oldmode = 0;
return chmod (name, modestr_to_mode (modestr, oldmode));
#endif
}