Simpler checking of permissions on private RSA key and other fixes.
This commit is contained in:
parent
96f5d98fc2
commit
9bde92ce97
6 changed files with 52 additions and 143 deletions
105
src/conf.c
105
src/conf.c
|
@ -19,7 +19,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: conf.c,v 1.9.4.74 2003/08/08 14:59:27 guus Exp $
|
||||
$Id: conf.c,v 1.9.4.75 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -424,97 +424,7 @@ bool read_server_config()
|
|||
return x == 0;
|
||||
}
|
||||
|
||||
bool is_safe_path(const char *file)
|
||||
{
|
||||
#if !(defined(HAVE_CYGWIN) || defined(HAVE_MINGW))
|
||||
char *p;
|
||||
const char *f;
|
||||
char x;
|
||||
struct stat s;
|
||||
char l[MAXBUFSIZE];
|
||||
|
||||
if(*file != '/') {
|
||||
logger(LOG_ERR, _("`%s' is not an absolute path"), file);
|
||||
return false;
|
||||
}
|
||||
|
||||
p = strrchr(file, '/');
|
||||
|
||||
if(p == file) /* It's in the root */
|
||||
p++;
|
||||
|
||||
x = *p;
|
||||
*p = '\0';
|
||||
|
||||
f = file;
|
||||
|
||||
check1:
|
||||
if(lstat(f, &s) < 0) {
|
||||
logger(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(s.st_uid != geteuid()) {
|
||||
logger(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
||||
f, s.st_uid, geteuid());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(S_ISLNK(s.st_mode)) {
|
||||
logger(LOG_WARNING, _("Warning: `%s' is a symlink"), f);
|
||||
|
||||
if(readlink(f, l, MAXBUFSIZE) < 0) {
|
||||
logger(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
f = l;
|
||||
goto check1;
|
||||
}
|
||||
|
||||
*p = x;
|
||||
f = file;
|
||||
|
||||
check2:
|
||||
if(lstat(f, &s) < 0 && errno != ENOENT) {
|
||||
logger(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(errno == ENOENT)
|
||||
return true;
|
||||
|
||||
if(s.st_uid != geteuid()) {
|
||||
logger(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
||||
f, s.st_uid, geteuid());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(S_ISLNK(s.st_mode)) {
|
||||
logger(LOG_WARNING, _("Warning: `%s' is a symlink"), f);
|
||||
|
||||
if(readlink(f, l, MAXBUFSIZE) < 0) {
|
||||
logger(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
f = l;
|
||||
goto check2;
|
||||
}
|
||||
|
||||
if(s.st_mode & 0007) {
|
||||
/* Accessible by others */
|
||||
logger(LOG_ERR, _("`%s' has unsecure permissions"), f);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE *ask_and_safe_open(const char *filename, const char *what, bool safe, const char *mode)
|
||||
FILE *ask_and_open(const char *filename, const char *what, const char *mode)
|
||||
{
|
||||
FILE *r;
|
||||
char *directory;
|
||||
|
@ -573,17 +483,6 @@ FILE *ask_and_safe_open(const char *filename, const char *what, bool safe, const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Then check the file for nasty attacks */
|
||||
if(safe) {
|
||||
if(!is_safe_path(fn)) { /* Do not permit any directories that are readable or writeable by other users. */
|
||||
fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n"
|
||||
"I will not create or overwrite this file.\n"), fn);
|
||||
fclose(r);
|
||||
free(fn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(fn);
|
||||
|
||||
return r;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: conf.h,v 1.6.4.42 2003/07/30 21:52:41 guus Exp $
|
||||
$Id: conf.h,v 1.6.4.43 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_CONF_H__
|
||||
|
@ -57,7 +57,7 @@ extern bool get_config_subnet(const config_t *, struct subnet_t **);
|
|||
|
||||
extern int read_config_file(avl_tree_t *, const char *);
|
||||
extern bool read_server_config(void);
|
||||
extern FILE *ask_and_safe_open(const char *, const char *, bool, const char *);
|
||||
extern FILE *ask_and_open(const char *, const char *, const char *);
|
||||
extern bool is_safe_path(const char *);
|
||||
|
||||
#endif /* __TINC_CONF_H__ */
|
||||
|
|
10
src/meta.c
10
src/meta.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: meta.c,v 1.1.2.39 2003/08/08 14:24:09 guus Exp $
|
||||
$Id: meta.c,v 1.1.2.40 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -54,10 +54,10 @@ bool send_meta(connection_t *c, char *buffer, int length)
|
|||
while(length) {
|
||||
result = send(c->socket, bufp, length, 0);
|
||||
if(result <= 0) {
|
||||
if(!errno || errno == EPIPE)
|
||||
if(!errno || errno == EPIPE) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, _("Connection closed by %s (%s)"),
|
||||
c->name, c->hostname);
|
||||
else if(errno == EINTR)
|
||||
} else if(errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
logger(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name,
|
||||
|
@ -121,10 +121,10 @@ bool receive_meta(connection_t *c)
|
|||
lenin = recv(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen, 0);
|
||||
|
||||
if(lenin <= 0) {
|
||||
if(!lenin || !errno)
|
||||
if(!lenin || !errno) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, _("Connection closed by %s (%s)"),
|
||||
c->name, c->hostname);
|
||||
else if(errno == EINTR)
|
||||
} else if(errno == EINTR)
|
||||
return true;
|
||||
else
|
||||
logger(LOG_ERR, _("Metadata socket read error for %s (%s): %s"),
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net_setup.c,v 1.1.2.41 2003/07/30 11:50:45 guus Exp $
|
||||
$Id: net_setup.c,v 1.1.2.42 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -149,6 +149,7 @@ bool read_rsa_private_key(void)
|
|||
{
|
||||
FILE *fp;
|
||||
char *fname, *key;
|
||||
struct stat s;
|
||||
|
||||
cp();
|
||||
|
||||
|
@ -164,32 +165,39 @@ bool read_rsa_private_key(void)
|
|||
if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
|
||||
asprintf(&fname, "%s/rsa_key.priv", confbase);
|
||||
|
||||
if(is_safe_path(fname)) {
|
||||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
return false;
|
||||
}
|
||||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
myself->connection->rsa_key =
|
||||
PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!myself->connection->rsa_key) {
|
||||
logger(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
|
||||
fname, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
|
||||
if(fstat(fileno(fp), &s)) {
|
||||
logger(LOG_ERR, _("Could not stat RSA private key file `%s': %s'"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if(s.st_mode & ~0700)
|
||||
logger(LOG_WARNING, _("Warning: insecure file permissions for RSA private key file `%s'!"), fname);
|
||||
#endif
|
||||
|
||||
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||
fclose(fp);
|
||||
|
||||
if(!myself->connection->rsa_key) {
|
||||
logger(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(fname);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: process.c,v 1.1.2.68 2003/08/08 19:56:11 guus Exp $
|
||||
$Id: process.c,v 1.1.2.69 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -359,7 +359,6 @@ bool detach(void)
|
|||
bool execute_script(const char *name, char **envp)
|
||||
{
|
||||
#ifdef HAVE_SYSTEM
|
||||
pid_t pid;
|
||||
int status;
|
||||
struct stat s;
|
||||
char *scriptname;
|
||||
|
@ -394,22 +393,20 @@ bool execute_script(const char *name, char **envp)
|
|||
if(status != -1) {
|
||||
if(WIFEXITED(status)) { /* Child exited by itself */
|
||||
if(WEXITSTATUS(status)) {
|
||||
logger(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"),
|
||||
pid, name, WEXITSTATUS(status));
|
||||
logger(LOG_ERR, _("Script %s exited with non-zero status %d"),
|
||||
name, WEXITSTATUS(status));
|
||||
return false;
|
||||
}
|
||||
} else if(WIFSIGNALED(status)) { /* Child was killed by a signal */
|
||||
logger(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), pid,
|
||||
logger(LOG_ERR, _("Script %s was killed by signal %d (%s)"),
|
||||
name, WTERMSIG(status), strsignal(WTERMSIG(status)));
|
||||
return false;
|
||||
} else { /* Something strange happened */
|
||||
logger(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid,
|
||||
name);
|
||||
logger(LOG_ERR, _("Script %s terminated abnormally"), name);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "system",
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "system", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
13
src/tincd.c
13
src/tincd.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tincd.c,v 1.10.4.84 2003/08/08 19:45:21 guus Exp $
|
||||
$Id: tincd.c,v 1.10.4.85 2003/08/08 22:11:54 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -300,11 +300,16 @@ static bool keygen(int bits)
|
|||
fprintf(stderr, _("Done.\n"));
|
||||
|
||||
asprintf(&filename, "%s/rsa_key.priv", confbase);
|
||||
f = ask_and_safe_open(filename, _("private RSA key"), true, "a");
|
||||
f = ask_and_open(filename, _("private RSA key"), "a");
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
|
||||
|
||||
#ifdef HAVE_FCHMOD
|
||||
/* Make it unreadable for others. */
|
||||
fchmod(fileno(f), 0600);
|
||||
#endif
|
||||
|
||||
if(ftell(f))
|
||||
fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
|
||||
|
||||
|
@ -319,7 +324,7 @@ static bool keygen(int bits)
|
|||
else
|
||||
asprintf(&filename, "%s/rsa_key.pub", confbase);
|
||||
|
||||
f = ask_and_safe_open(filename, _("public RSA key"), false, "a");
|
||||
f = ask_and_open(filename, _("public RSA key"), "a");
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue