diff --git a/g10/ChangeLog b/g10/ChangeLog index ff667db0f..7d7b64370 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,19 @@ +2004-10-14 Werner Koch + + * misc.c (is_secured_filename): New. + * keydb.c (maybe_create_keyring) + * tdbio.c (tdbio_set_dbname) + * plaintext.c (handle_plaintext) + * openfile.c (copy_options_file, open_outfile) + * exec.c (exec_write) + * keygen.c (do_generate_keypair, gen_card_key_with_backup) + * sign.c (sign_file, clearsign_file) + * keyring.c (create_tmp_file, do_copy): Check for secured files + before creating them. + + * keygen.c (print_status_key_created): s/unsigned char/byte/ due + to a strange typedef for RISC OS. Noted by Stefan. + 2004-10-13 David Shaw * armor.c (fake_packet): Allow arbitrary dash-escaped lines as per diff --git a/g10/exec.c b/g10/exec.c index e3a6933d9..408f6d7bf 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -477,13 +477,13 @@ int exec_write(struct exec_info **info,const char *program, log_debug("using temp file `%s'\n",(*info)->tempfile_in); /* It's not fork/exec/pipe, so create a temp file */ - (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w"); - if((*info)->tochild && is_secured_file (fileno ((*info)->tochild))) + if( is_secured_filename ((*info)->tempfile_in) ) { - fclose ((*info)->tochild); (*info)->tochild = NULL; errno = EPERM; } + else + (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w"); if((*info)->tochild==NULL) { log_error(_("can't create file `%s': %s\n"), diff --git a/g10/keydb.c b/g10/keydb.c index 34f0ebcf4..c6dbe8094 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -154,7 +154,13 @@ maybe_create_keyring (char *filename, int force) /* The file does not yet exist, create it now. */ oldmask = umask (077); - iobuf = iobuf_create (filename); + if (is_secured_filename (filename)) + { + iobuf = NULL; + errno = EPERM; + } + else + iobuf = iobuf_create (filename); umask (oldmask); if (!iobuf) { diff --git a/g10/keygen.c b/g10/keygen.c index 6380ca171..42722d9f2 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -167,7 +167,7 @@ copy_mpi (MPI a, unsigned char *buffer, size_t len, size_t *ncopied) static void print_status_key_created (int letter, PKT_public_key *pk, const char *handle) { - unsigned char array[MAX_FINGERPRINT_LEN], *s; + byte array[MAX_FINGERPRINT_LEN], *s; char *buf, *p; size_t i, n; @@ -2683,9 +2683,14 @@ do_generate_keypair( struct para_data_s *para, outctrl->pub.fname = outctrl->pub.newfname; outctrl->pub.newfname = NULL; - outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); + if (is_secured_filename (outctrl->pub.fname) ) { + outctrl->pub.stream = NULL; + errno = EPERM; + } + else + outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); if( !outctrl->pub.stream ) { - log_error("can't create `%s': %s\n", outctrl->pub.newfname, + log_error(_("can't create `%s': %s\n"), outctrl->pub.newfname, strerror(errno) ); return; } @@ -2707,10 +2712,15 @@ do_generate_keypair( struct para_data_s *para, outctrl->sec.newfname = NULL; oldmask = umask (077); - outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); + if (is_secured_filename (outctrl->sec.fname) ) { + outctrl->sec.stream = NULL; + errno = EPERM; + } + else + outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); umask (oldmask); if( !outctrl->sec.stream ) { - log_error("can't create `%s': %s\n", outctrl->sec.newfname, + log_error(_("can't create `%s': %s\n"), outctrl->sec.newfname, strerror(errno) ); return; } @@ -3328,7 +3338,13 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary, fname = make_filename (backup_dir, name_buffer, NULL); oldmask = umask (077); - fp = iobuf_create (fname); + if (is_secured_filename (fname)) + { + fp = NULL; + errno = EPERM; + } + else + fp = iobuf_create (fname); umask (oldmask); if (!fp) { diff --git a/g10/keyring.c b/g10/keyring.c index ae1957398..0d33b59f8 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1185,7 +1185,13 @@ create_tmp_file (const char *template, /* Create the temp file with limited access */ oldmask=umask(077); - *r_fp = iobuf_create (tmpfname); + if (is_secured_filename (tmpfname)) + { + *r_fp = NULL; + errno = EPERM; + } + else + *r_fp = iobuf_create (tmpfname); umask(oldmask); if (!*r_fp) { log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) ); @@ -1467,7 +1473,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, char *bakfname = NULL; char *tmpfname = NULL; - /* Open the source file. Because we do a rname, we have to check the + /* Open the source file. Because we do a rename, we have to check the permissions of the file */ if (access (fname, W_OK)) return G10ERR_WRITE_FILE; @@ -1479,10 +1485,15 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, mode_t oldmask; oldmask=umask(077); - newfp = iobuf_create (fname); + if (!secret && is_secured_filename (fname)) { + newfp = NULL; + errno = EPERM; + } + else + newfp = iobuf_create (fname); umask(oldmask); if( !newfp ) { - log_error (_("%s: can't create: %s\n"), + log_error (_("can't create `%s': %s\n"), fname, strerror(errno)); return G10ERR_OPEN_FILE; } @@ -1506,7 +1517,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, } if( !fp ) { - log_error ("%s: can't open: %s\n", fname, strerror(errno) ); + log_error ("can't open `%s': %s\n", fname, strerror(errno) ); rc = G10ERR_OPEN_FILE; goto leave; } diff --git a/g10/main.h b/g10/main.h index 38750dff8..429eb6403 100644 --- a/g10/main.h +++ b/g10/main.h @@ -75,6 +75,7 @@ int disable_core_dumps(void); void register_secured_file (const char *fname); void unregister_secured_file (const char *fname); int is_secured_file (int fd); +int is_secured_filename (const char *fname); u16 checksum_u16( unsigned n ); u16 checksum( byte *p, unsigned n ); u16 checksum_mpi( MPI a ); diff --git a/g10/misc.c b/g10/misc.c index 207367d7e..110d9128c 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -198,6 +198,41 @@ is_secured_file (int fd) return 0; /* No. */ } +/* Return true if FNAME is corresponds to a secured file. Using NULL, + "" or "-" for FS is allowed and will return false. This function is + used before creating a file, thus it won't fail if the file does + not exist. */ +int +is_secured_filename (const char *fname) +{ +#ifdef ENABLE_SELINUX_HACKS + struct stat buf; + struct secured_file_item *sf; + + if (iobuf_is_pipe_filename (fname) || !*fname) + return 0; + + /* Note that we print out a error here and claim that a file is + secure if something went wrong. */ + if (stat (fname, &buf)) + { + if (errno == ENOENT || errno == EPERM || errno == EACCES) + return 0; + log_error (_("fstat of `%s' failed in %s: %s\n"), fname, + "is_secured_filename", strerror (errno)); + return 1; + } +/* log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */ +/* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ + for (sf=secured_files; sf; sf = sf->next) + { + if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) + return 1; /* Yes. */ + } +#endif /*ENABLE_SELINUX_HACKS*/ + return 0; /* No. */ +} + u16 diff --git a/g10/openfile.c b/g10/openfile.c index 9c305a2f2..59e19a485 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -175,8 +175,9 @@ open_outfile( const char *iname, int mode, IOBUF *a ) *a = NULL; if( iobuf_is_pipe_filename (iname) && !opt.outfile ) { - if( !(*a = iobuf_create(NULL)) ) { - log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); + *a = iobuf_create(NULL); + if( !*a ) { + log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) ); rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) @@ -244,9 +245,16 @@ open_outfile( const char *iname, int mode, IOBUF *a ) if( !rc ) { - if( !(*a = iobuf_create( name )) ) + if (is_secured_filename (name) ) { - log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); + *a = NULL; + errno = EPERM; + } + else + *a = iobuf_create( name ); + if( !*a ) + { + log_error(_("can't create `%s': %s\n"), name, strerror(errno) ); rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) @@ -322,16 +330,22 @@ copy_options_file( const char *destdir ) errno = EPERM; } if( !src ) { - log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); m_free(fname); return; } strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" ); oldmask=umask(077); - dst = fopen( fname, "w" ); + if ( is_secured_filename (fname) ) + { + dst = NULL; + errno = EPERM; + } + else + dst = fopen( fname, "w" ); umask(oldmask); if( !dst ) { - log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); + log_error(_("can't create `%s': %s\n"), fname, strerror(errno) ); fclose( src ); m_free(fname); return; @@ -389,10 +403,10 @@ try_make_homedir( const char *fname ) && !compare_filenames( fname, defhome ) ) ) { if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) ) - log_fatal( _("%s: can't create directory: %s\n"), + log_fatal( _("can't create directory `%s': %s\n"), fname, strerror(errno) ); else if( !opt.quiet ) - log_info( _("%s: directory created\n"), fname ); + log_info( _("directory `%s' created\n"), fname ); copy_options_file( fname ); /* log_info(_("you have to start GnuPG again, " */ /* "so it can read the new configuration file\n") ); */ diff --git a/g10/plaintext.c b/g10/plaintext.c index 8b782add7..2e3c49907 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -128,6 +128,13 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, #ifndef __riscos__ if( fp || nooutput ) ; + else if (is_secured_filename (fname)) + { + errno = EPERM; + log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } else if( !(fp = fopen(fname,"wb")) ) { log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); rc = G10ERR_CREATE_FILE; diff --git a/g10/sign.c b/g10/sign.c index b6f67e55c..6a1e4da22 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -768,7 +768,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { + if (is_secured_filename ( outfile )) { + out = NULL; + errno = EPERM; + } + else + out = iobuf_create( outfile ); + if( !out ) { log_error(_("can't create file `%s': %s\n"), outfile, strerror(errno) ); rc = G10ERR_CREATE_FILE; @@ -1019,7 +1025,13 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) handle_progress (&pfx, inp, fname); if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { + if (is_secured_filename (outfile) ) { + outfile = NULL; + errno = EPERM; + } + else + out = iobuf_create( outfile ); + if( !out ) { log_error(_("can't create file `%s': %s\n"), outfile, strerror(errno) ); rc = G10ERR_CREATE_FILE; diff --git a/g10/tdbio.c b/g10/tdbio.c index 0b182cfad..5b34bc8ed 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -494,7 +494,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) if( access( fname, R_OK ) ) { if( errno != ENOENT ) { - log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); + log_error( _("can't access `%s': %s\n"), fname, strerror(errno) ); m_free(fname); return G10ERR_TRUSTDB; } @@ -519,25 +519,30 @@ tdbio_set_dbname( const char *new_dbname, int create ) if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); if( make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); + log_fatal( _("can't lock `%s'\n"), db_name ); #endif /* __riscos__ */ oldmask=umask(077); - fp =fopen( fname, "wb" ); + if (is_secured_filename (fname)) { + fp = NULL; + errno = EPERM; + } + else + fp =fopen( fname, "wb" ); umask(oldmask); if( !fp ) - log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) ); + log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) ); fclose(fp); db_fd = open( db_name, O_RDWR | MY_O_BINARY ); if( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) ); #ifndef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); #endif /* !__riscos__ */ rc = create_version_record (); @@ -580,10 +585,10 @@ open_db() if (!lockhandle ) lockhandle = create_dotlock( db_name ); if (!lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); #ifdef __riscos__ if (make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); + log_fatal( _("can't lock `%s'\n"), db_name ); #endif /* __riscos__ */ db_fd = open (db_name, O_RDWR | MY_O_BINARY ); if (db_fd == -1 && errno == EACCES) { @@ -592,7 +597,7 @@ open_db() log_info (_("NOTE: trustdb not writable\n")); } if ( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) ); register_secured_file (db_name); /* check whether we need to do a version migration */