- Check and follow symlinks in is_safe_path
- By default write keys to tinc config directory - Small fix in protocol.c
This commit is contained in:
parent
1398edec37
commit
f7bb205022
3 changed files with 85 additions and 60 deletions
118
src/conf.c
118
src/conf.c
|
@ -19,7 +19,7 @@
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
$Id: conf.c,v 1.9.4.36 2001/01/05 23:53:49 guus Exp $
|
$Id: conf.c,v 1.9.4.37 2001/01/06 18:03:39 guus Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -357,19 +357,18 @@ int isadir(const char* f)
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
if(stat(f, &s) < 0)
|
if(stat(f, &s) < 0)
|
||||||
{
|
return 0;
|
||||||
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
else
|
||||||
f);
|
return S_ISDIR(s.st_mode);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_ISDIR(s.st_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_safe_path(const char *file)
|
int is_safe_path(const char *file)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
const char *f;
|
||||||
|
char x;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
char l[MAXBUFSIZE];
|
||||||
|
|
||||||
if(*file != '/')
|
if(*file != '/')
|
||||||
{
|
{
|
||||||
|
@ -378,52 +377,85 @@ int is_safe_path(const char *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strrchr(file, '/');
|
p = strrchr(file, '/');
|
||||||
|
|
||||||
|
if(p == file) /* It's in the root */
|
||||||
|
p++;
|
||||||
|
|
||||||
|
x = *p;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if(stat(file, &s) < 0)
|
|
||||||
|
f = file;
|
||||||
|
check1:
|
||||||
|
if(lstat(f, &s) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
||||||
file);
|
f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(s.st_uid != geteuid())
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
|
||||||
file, s.st_uid, geteuid());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(S_ISLNK(s.st_mode))
|
|
||||||
{
|
|
||||||
syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
|
|
||||||
file);
|
|
||||||
/* fixme: read the symlink and start again */
|
|
||||||
}
|
|
||||||
|
|
||||||
*p = '/';
|
|
||||||
if(stat(file, &s) < 0 && errno != ENOENT)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
|
||||||
file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(errno == ENOENT)
|
|
||||||
return 1;
|
|
||||||
if(s.st_uid != geteuid())
|
if(s.st_uid != geteuid())
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
||||||
file, s.st_uid, geteuid());
|
f, s.st_uid, geteuid());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(S_ISLNK(s.st_mode))
|
if(S_ISLNK(s.st_mode))
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
|
syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
|
||||||
file);
|
f);
|
||||||
/* fixme: read the symlink and start again */
|
|
||||||
|
if(readlink(f, l, MAXBUFSIZE) < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = l;
|
||||||
|
goto check1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*p = x;
|
||||||
|
f = file;
|
||||||
|
|
||||||
|
check2:
|
||||||
|
if(lstat(f, &s) < 0 && errno != ENOENT)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
||||||
|
f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(errno == ENOENT)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(s.st_uid != geteuid())
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
|
||||||
|
f, s.st_uid, geteuid());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(S_ISLNK(s.st_mode))
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
|
||||||
|
f);
|
||||||
|
|
||||||
|
if(readlink(f, l, MAXBUFSIZE) < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = l;
|
||||||
|
goto check2;
|
||||||
|
}
|
||||||
|
|
||||||
if(s.st_mode & 0007)
|
if(s.st_mode & 0007)
|
||||||
{
|
{
|
||||||
/* Accessible by others */
|
/* Accessible by others */
|
||||||
syslog(LOG_ERR, _("`%s' has unsecure permissions"),
|
syslog(LOG_ERR, _("`%s' has unsecure permissions"),
|
||||||
file);
|
f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +467,6 @@ FILE *ask_and_safe_open(const char* filename, const char* what)
|
||||||
FILE *r;
|
FILE *r;
|
||||||
char *directory;
|
char *directory;
|
||||||
char *fn;
|
char *fn;
|
||||||
int len;
|
|
||||||
|
|
||||||
/* Check stdin and stdout */
|
/* Check stdin and stdout */
|
||||||
if(!isatty(0) || !isatty(1))
|
if(!isatty(0) || !isatty(1))
|
||||||
|
@ -469,25 +500,12 @@ FILE *ask_and_safe_open(const char* filename, const char* what)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
directory = get_current_dir_name();
|
directory = get_current_dir_name();
|
||||||
len = strlen(fn) + strlen(directory) + 2; /* 1 for the / */
|
asprintf(&p, "%s/%s", directory, fn);
|
||||||
p = xmalloc(len);
|
|
||||||
snprintf(p, len, "%s/%s", directory, fn);
|
|
||||||
free(fn);
|
free(fn);
|
||||||
free(directory);
|
free(directory);
|
||||||
fn = p;
|
fn = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isadir(fn) > 0) /* -1 is error */
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
len = strlen(fn) + strlen(filename) + 2; /* 1 for the / */
|
|
||||||
p = xmalloc(len);
|
|
||||||
snprintf(p, len, "%s/%s", fn, filename);
|
|
||||||
free(fn);
|
|
||||||
fn = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
umask(0077); /* Disallow everything for group and other */
|
umask(0077); /* Disallow everything for group and other */
|
||||||
|
|
||||||
/* Open it first to keep the inode busy */
|
/* Open it first to keep the inode busy */
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
$Id: protocol.c,v 1.28.4.71 2001/01/05 23:53:51 guus Exp $
|
$Id: protocol.c,v 1.28.4.72 2001/01/06 18:03:40 guus Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -196,6 +196,7 @@ int id_h(connection_t *cl)
|
||||||
connection_t *old;
|
connection_t *old;
|
||||||
unsigned short int port;
|
unsigned short int port;
|
||||||
char name[MAX_STRING_SIZE];
|
char name[MAX_STRING_SIZE];
|
||||||
|
avl_node_t *node;
|
||||||
cp
|
cp
|
||||||
if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
|
if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
|
||||||
{
|
{
|
||||||
|
@ -256,9 +257,9 @@ cp
|
||||||
|
|
||||||
/* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
|
/* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
|
||||||
|
|
||||||
avl_unlink(connection_tree, cl);
|
node = avl_unlink(connection_tree, cl);
|
||||||
cl->port = port;
|
cl->port = port;
|
||||||
avl_insert(connection_tree, cl);
|
avl_insert_node(connection_tree, node);
|
||||||
|
|
||||||
/* Read in the public key, so that we can send a challenge */
|
/* Read in the public key, so that we can send a challenge */
|
||||||
|
|
||||||
|
|
20
src/tincd.c
20
src/tincd.c
|
@ -17,7 +17,7 @@
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
$Id: tincd.c,v 1.10.4.39 2001/01/05 23:53:53 guus Exp $
|
$Id: tincd.c,v 1.10.4.40 2001/01/06 18:03:41 guus Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -229,9 +229,11 @@ int keygen(int bits)
|
||||||
{
|
{
|
||||||
RSA *rsa_key;
|
RSA *rsa_key;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
fprintf(stderr, _("Generating %d bits keys:\n"), bits);
|
fprintf(stderr, _("Generating %d bits keys:\n"), bits);
|
||||||
rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
|
rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
|
||||||
|
|
||||||
if(!rsa_key)
|
if(!rsa_key)
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("Error during key generation!"));
|
fprintf(stderr, _("Error during key generation!"));
|
||||||
|
@ -240,15 +242,19 @@ int keygen(int bits)
|
||||||
else
|
else
|
||||||
fprintf(stderr, _("Done.\n"));
|
fprintf(stderr, _("Done.\n"));
|
||||||
|
|
||||||
if((f = ask_and_safe_open("rsa_key.pub", _("public RSA key"))) == NULL)
|
asprintf(&filename, "%s/rsa_key.pub", confbase);
|
||||||
|
if((f = ask_and_safe_open(filename, _("public RSA key"))) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
PEM_write_RSAPublicKey(f, rsa_key);
|
PEM_write_RSAPublicKey(f, rsa_key);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
free(filename);
|
||||||
|
|
||||||
if((f = ask_and_safe_open("rsa_key.priv", _("private RSA key"))) == NULL)
|
asprintf(&filename, "%s/rsa_key.priv", confbase);
|
||||||
|
if((f = ask_and_safe_open(filename, _("private RSA key"))) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
|
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
free(filename);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +271,7 @@ void make_names(void)
|
||||||
if(!confbase)
|
if(!confbase)
|
||||||
asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
|
asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
|
||||||
else
|
else
|
||||||
fprintf(stderr, _("Both netname and configuration directory given, using the latter...\n"));
|
syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter..."));
|
||||||
if(!identname)
|
if(!identname)
|
||||||
asprintf(&identname, "tinc.%s", netname);
|
asprintf(&identname, "tinc.%s", netname);
|
||||||
}
|
}
|
||||||
|
@ -283,8 +289,6 @@ void make_names(void)
|
||||||
int
|
int
|
||||||
main(int argc, char **argv, char **envp)
|
main(int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
|
|
||||||
|
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
@ -315,10 +319,12 @@ main(int argc, char **argv, char **envp)
|
||||||
|
|
||||||
if(geteuid())
|
if(geteuid())
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("You must be root to run this program. Sorry.\n"));
|
fprintf(stderr, _("You must be root to run this program.\n"));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
|
||||||
|
|
||||||
g_argv = argv;
|
g_argv = argv;
|
||||||
|
|
||||||
make_names();
|
make_names();
|
||||||
|
|
Loading…
Reference in a new issue