1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

* keyedit.c (menu_revsig): Properly show a uid is revoked without

restarting gpg.  This is Debian bug 124219, though their supplied patch
will not do the right thing.

* main.h, tdbio.c (tdbio_set_dbname), misc.c (removed check_permissions),
keydb.c (keydb_add_resource), g10.c (main, check_permissions): Significant
reworking of the permission check mechanism.  The new behavior is to check
everything in the homedir by checking the homedir itself.  If the user
wants to put (possibly shared) keyrings outside the homedir, they are not
checked.  The options file and any extension files are checked wherever
they are, as well as their enclosing directories.  This is Debian bug
147760.
This commit is contained in:
David Shaw 2002-08-07 15:53:15 +00:00
parent df50c106f8
commit fee7e35bae
7 changed files with 212 additions and 135 deletions

224
g10/g10.c
View file

@ -28,6 +28,9 @@
#ifdef HAVE_DOSISH_SYSTEM
#include <fcntl.h> /* for setmode() */
#endif
#ifdef HAVE_STAT
#include <sys/stat.h> /* for stat() */
#endif
#define INCLUDED_BY_MAIN_MODULE 1
#include "packet.h"
@ -832,6 +835,180 @@ static void add_group(char *string)
opt.grouplist=item;
}
/* We need to check three things.
0) The homedir. It must be x00, a directory, and owned by the
user.
1) The options file. Okay unless it or its containing directory is
group or other writable or not owned by us. disable exec in this
case.
2) Extensions. Same as #2.
Returns true if the item is unsafe. */
static int
check_permissions(const char *path,int item)
{
#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
static int homedir_cache=-1;
char *tmppath,*isa,*dir;
struct stat statbuf,dirbuf;
int homedir=0,ret=0,checkonly=0;
int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0;
if(opt.no_perm_warn)
return 0;
/* extensions may attach a path */
if(item==2 && path[0]!=DIRSEP_C)
{
if(strchr(path,DIRSEP_C))
tmppath=make_filename(path,NULL);
else
tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
}
else
tmppath=m_strdup(path);
/* If the item is located in the homedir, but isn't the homedir,
don't continue if we already checked the homedir itself. This is
to avoid user confusion with an extra options file warning which
could be rectified if the homedir itself had proper
permissions. */
if(item!=0 && homedir_cache>-1 &&
ascii_memcasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0)
{
ret=homedir_cache;
goto end;
}
/* It's okay if the file or directory doesn't exist */
if(stat(tmppath,&statbuf)!=0)
{
ret=0;
goto end;
}
/* Now check the enclosing directory. Theoretically, we could walk
this test up to the root directory /, but for the sake of sanity,
I'm stopping at one level down. */
dir=make_dirname(tmppath);
if(stat(dir,&dirbuf)!=0 || !S_ISDIR(dirbuf.st_mode))
{
/* Weird error */
ret=1;
goto end;
}
m_free(dir);
/* Assume failure */
ret=1;
if(item==0)
{
isa="homedir";
/* The homedir must be x00, a directory, and owned by the user. */
if(S_ISDIR(statbuf.st_mode))
{
if(statbuf.st_uid==getuid())
{
if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
ret=0;
else
perm=1;
}
else
own=1;
homedir_cache=ret;
}
}
else if(item==1 || item==2)
{
if(item==1)
isa="configuration file";
else
isa="extension";
/* The options or extension file. Okay unless it or its
containing directory is group or other writable or not owned
by us or root. */
if(S_ISREG(statbuf.st_mode))
{
if(statbuf.st_uid==getuid() || statbuf.st_uid==0)
{
if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0)
{
/* it's not writable, so make sure the enclosing
directory is also not writable */
if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0)
{
if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0)
ret=0;
else
enc_dir_perm=1;
}
else
enc_dir_own=1;
}
else
{
/* it's writable, so the enclosing directory had
better not let people get to it. */
if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0)
{
if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
ret=0;
else
perm=enc_dir_perm=1; /* unclear which one to fix! */
}
else
enc_dir_own=1;
}
}
else
own=1;
}
}
else
BUG();
if(!checkonly)
{
if(own)
log_info(_("WARNING: unsafe ownership on %s \"%s\"\n"),
isa,tmppath);
if(perm)
log_info(_("WARNING: unsafe permissions on %s \"%s\"\n"),
isa,tmppath);
if(enc_dir_own)
log_info(_("WARNING: unsafe enclosing directory "
"ownership on %s \"%s\"\n"),
isa,tmppath);
if(enc_dir_perm)
log_info(_("WARNING: unsafe enclosing directory "
"permissions on %s \"%s\"\n"),
isa,tmppath);
}
end:
m_free(tmppath);
if(homedir)
homedir_cache=ret;
return ret;
#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
return 0;
}
int
main( int argc, char **argv )
@ -843,8 +1020,6 @@ main( int argc, char **argv )
char **orig_argv;
const char *fname;
char *username;
STRLIST unsafe_files=NULL;
STRLIST extensions=NULL;
int may_coredump;
STRLIST sl, remusr= NULL, locusr=NULL;
STRLIST nrings=NULL, sec_nrings=NULL;
@ -945,6 +1120,8 @@ main( int argc, char **argv )
default_config = 0; /* --no-options */
else if( pargs.r_opt == oHomedir )
opt.homedir = pargs.r.ret_str;
else if( pargs.r_opt == oNoPermissionWarn )
opt.no_perm_warn=1;
#ifdef USE_SHM_COPROCESSING
else if( pargs.r_opt == oRunAsShmCP ) {
/* does not make sense in a options file, we do it here,
@ -1001,13 +1178,14 @@ main( int argc, char **argv )
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
/* By this point we have a homedir, and cannot change it. */
check_permissions(opt.homedir,0);
next_pass:
if( configname ) {
if(check_permissions(configname,0,1))
if(check_permissions(configname,1))
{
add_to_strlist(&unsafe_files,configname);
/* If any options file is unsafe, then disable any external
programs for keyserver calls or photo IDs. Since the
external program to call is set in the options file, a
@ -1206,9 +1384,14 @@ main( int argc, char **argv )
case oAlwaysTrust: opt.always_trust = 1; break;
case oLoadExtension:
#ifndef __riscos__
add_to_strlist(&extensions,pargs.r.ret_str);
register_cipher_extension(orig_argc? *orig_argv:NULL,
pargs.r.ret_str);
#ifdef USE_DYNAMIC_LINKING
if(check_permissions(pargs.r.ret_str,2))
log_info(_("cipher extension \"%s\" not loaded due to "
"unsafe permissions\n"),pargs.r.ret_str);
else
register_cipher_extension(orig_argc? *orig_argv:NULL,
pargs.r.ret_str);
#endif
#else /* __riscos__ */
not_implemented("load-extension");
#endif /* __riscos__ */
@ -1496,28 +1679,6 @@ main( int argc, char **argv )
}
#endif
check_permissions(opt.homedir,0,0);
if(unsafe_files)
{
STRLIST tmp;
for(tmp=unsafe_files;tmp;tmp=tmp->next)
check_permissions(tmp->d,0,0);
free_strlist(unsafe_files);
}
if(extensions)
{
STRLIST tmp;
for(tmp=extensions;tmp;tmp=tmp->next)
check_permissions(tmp->d,1,0);
free_strlist(extensions);
}
if( may_coredump && !opt.quiet )
log_info(_("WARNING: program may create a core file!\n"));
@ -1723,7 +1884,6 @@ main( int argc, char **argv )
/* set the random seed file */
if( use_random_seed ) {
char *p = make_filename(opt.homedir, "random_seed", NULL );
check_permissions(p,0,0);
set_random_seed_file(p);
m_free(p);
}