From: Guus Sliepen Date: Sat, 6 Jan 2001 18:03:41 +0000 (+0000) Subject: - Check and follow symlinks in is_safe_path X-Git-Tag: release-1.0pre4~78 X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=f7bb205022e02c02c02733cd43544c231373115d;hp=1398edec37336853bfca6ea3dcca7c402f102ea2 - Check and follow symlinks in is_safe_path - By default write keys to tinc config directory - Small fix in protocol.c --- diff --git a/src/conf.c b/src/conf.c index 5aaa22a0..61f0cf0e 100644 --- a/src/conf.c +++ b/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.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" @@ -357,19 +357,18 @@ int isadir(const char* f) struct stat s; if(stat(f, &s) < 0) - { - syslog(LOG_ERR, _("Couldn't stat `%s': %m"), - f); - return -1; - } - - return S_ISDIR(s.st_mode); + return 0; + else + return S_ISDIR(s.st_mode); } int is_safe_path(const char *file) { char *p; + const char *f; + char x; struct stat s; + char l[MAXBUFSIZE]; if(*file != '/') { @@ -378,52 +377,85 @@ int is_safe_path(const char *file) } p = strrchr(file, '/'); + + if(p == file) /* It's in the root */ + p++; + + x = *p; *p = '\0'; - if(stat(file, &s) < 0) + + f = file; +check1: + if(lstat(f, &s) < 0) { syslog(LOG_ERR, _("Couldn't stat `%s': %m"), - file); + f); return 0; } + if(s.st_uid != geteuid()) { syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), - file, s.st_uid, geteuid()); + f, 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 */ + f); + + if(readlink(f, l, MAXBUFSIZE) < 0) + { + syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f); + return 0; + } + + f = l; + goto check1; } - *p = '/'; - if(stat(file, &s) < 0 && errno != ENOENT) + *p = x; + f = file; + +check2: + if(lstat(f, &s) < 0 && errno != ENOENT) { syslog(LOG_ERR, _("Couldn't stat `%s': %m"), - file); + 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"), - file, s.st_uid, geteuid()); + f, 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 */ + 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) { /* Accessible by others */ syslog(LOG_ERR, _("`%s' has unsecure permissions"), - file); + f); return 0; } @@ -435,7 +467,6 @@ FILE *ask_and_safe_open(const char* filename, const char* what) FILE *r; char *directory; char *fn; - int len; /* Check stdin and stdout */ if(!isatty(0) || !isatty(1)) @@ -469,25 +500,12 @@ FILE *ask_and_safe_open(const char* filename, const char* what) char *p; directory = get_current_dir_name(); - len = strlen(fn) + strlen(directory) + 2; /* 1 for the / */ - p = xmalloc(len); - snprintf(p, len, "%s/%s", directory, fn); + asprintf(&p, "%s/%s", directory, fn); free(fn); free(directory); 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 */ /* Open it first to keep the inode busy */ diff --git a/src/protocol.c b/src/protocol.c index 85a4047c..72f8c3d0 100644 --- a/src/protocol.c +++ b/src/protocol.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: 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" @@ -196,6 +196,7 @@ int id_h(connection_t *cl) connection_t *old; unsigned short int port; char name[MAX_STRING_SIZE]; + avl_node_t *node; cp 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... */ - avl_unlink(connection_tree, cl); + node = avl_unlink(connection_tree, cl); 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 */ diff --git a/src/tincd.c b/src/tincd.c index 535fdb32..3e02e699 100644 --- a/src/tincd.c +++ b/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.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" @@ -229,9 +229,11 @@ int keygen(int bits) { RSA *rsa_key; FILE *f; + char *filename; fprintf(stderr, _("Generating %d bits keys:\n"), bits); rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL); + if(!rsa_key) { fprintf(stderr, _("Error during key generation!")); @@ -240,15 +242,19 @@ int keygen(int bits) else 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; PEM_write_RSAPublicKey(f, rsa_key); 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; PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); fclose(f); + free(filename); return 0; } @@ -265,7 +271,7 @@ void make_names(void) if(!confbase) asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname); 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) asprintf(&identname, "tinc.%s", netname); } @@ -283,8 +289,6 @@ void make_names(void) int main(int argc, char **argv, char **envp) { - openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ - program_name = argv[0]; setlocale (LC_ALL, ""); @@ -315,10 +319,12 @@ main(int argc, char **argv, char **envp) 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; } + openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ + g_argv = argv; make_names();