X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Ftincctl.c;h=14faf6454c38bedb97e8b0f72c531d2d3d31d30f;hb=7208397398f7e08d741bfa83594a88e5d01b6220;hp=97b08cb55abe7f5815b25d72aaedacadfc08b096;hpb=0345a1468613e1ba4a4aa6dbbef44a26f1eb42d9;p=tinc diff --git a/src/tincctl.c b/src/tincctl.c index 97b08cb5..14faf645 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -41,6 +41,7 @@ #include "top.h" #include "version.h" #include "subnet.h" +#include "keys.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -93,6 +94,17 @@ static struct option const long_options[] = { static void version(void) { printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE, BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR); + printf("Features:" +#ifdef HAVE_READLINE + " readline" +#endif +#ifdef HAVE_CURSES + " curses" +#endif +#ifndef DISABLE_LEGACY + " legacy_protocol" +#endif + "\n\n"); printf("Copyright (C) 1998-2018 Ivo Timmermans, Guus Sliepen and others.\n" "See the AUTHORS file for a complete list.\n\n" "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" @@ -179,11 +191,13 @@ static bool parse_options(int argc, char **argv) { break; case 'c': /* config file */ + free(confbase); confbase = xstrdup(optarg); confbasegiven = true; break; case 'n': /* net name given */ + free(netname); netname = xstrdup(optarg); break; @@ -196,6 +210,7 @@ static bool parse_options(int argc, char **argv) { break; case 3: /* open control socket here */ + free(pidfilename); pidfilename = xstrdup(optarg); break; @@ -205,6 +220,7 @@ static bool parse_options(int argc, char **argv) { case '?': /* wrong options */ usage(true); + free_names(); return false; default: @@ -225,133 +241,13 @@ static bool parse_options(int argc, char **argv) { if(netname && (strpbrk(netname, "\\/") || *netname == '.')) { fprintf(stderr, "Invalid character in netname!\n"); + free_names(); return false; } return true; } -/* Open a file with the desired permissions, minus the umask. - Also, if we want to create an executable file, we call fchmod() - to set the executable bits. */ - -FILE *fopenmask(const char *filename, const char *mode, mode_t perms) { - mode_t mask = umask(0); - perms &= ~mask; - umask(~perms & 0777); - FILE *f = fopen(filename, mode); - - if(!f) { - fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); - return NULL; - } - -#ifdef HAVE_FCHMOD - - if((perms & 0444) && f) { - fchmod(fileno(f), perms); - } - -#endif - umask(mask); - return f; -} - -static void disable_old_keys(const char *filename, const char *what) { - char tmpfile[PATH_MAX] = ""; - char buf[1024]; - bool disabled = false; - bool block = false; - bool error = false; - - FILE *r = fopen(filename, "r"); - FILE *w = NULL; - - if(!r) { - return; - } - - int result = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); - - if(result < sizeof(tmpfile)) { - struct stat st = {.st_mode = 0600}; - fstat(fileno(r), &st); - w = fopenmask(tmpfile, "w", st.st_mode); - } - - while(fgets(buf, sizeof(buf), r)) { - if(!block && !strncmp(buf, "-----BEGIN ", 11)) { - if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) { - disabled = true; - block = true; - } - } - - bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519"); - - if(ed25519pubkey) { - disabled = true; - } - - if(w) { - if(block || ed25519pubkey) { - fputc('#', w); - } - - if(fputs(buf, w) < 0) { - error = true; - break; - } - } - - if(block && !strncmp(buf, "-----END ", 9)) { - block = false; - } - } - - if(w) - if(fclose(w) < 0) { - error = true; - } - - if(ferror(r) || fclose(r) < 0) { - error = true; - } - - if(disabled) { - if(!w || error) { - fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); - - if(w) { - unlink(tmpfile); - } - - return; - } - -#ifdef HAVE_MINGW - // We cannot atomically replace files on Windows. - char bakfile[PATH_MAX] = ""; - snprintf(bakfile, sizeof(bakfile), "%s.bak", filename); - - if(rename(filename, bakfile) || rename(tmpfile, filename)) { - rename(bakfile, filename); -#else - - if(rename(tmpfile, filename)) { -#endif - fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); - } else { -#ifdef HAVE_MINGW - unlink(bakfile); -#endif - fprintf(stderr, "Warning: old key(s) found and disabled.\n"); - } - } - - unlink(tmpfile); -} - static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) { FILE *r; char directory[PATH_MAX] = "."; @@ -853,14 +749,17 @@ bool connect_tincd(bool verbose) { return false; } - struct sockaddr_un sa; + struct sockaddr_un sa = { + .sun_family = AF_UNIX, + }; - sa.sun_family = AF_UNIX; + if(strlen(unixsocketname) >= sizeof(sa.sun_path)) { + fprintf(stderr, "UNIX socket filename %s is too long!", unixsocketname); + return false; + } strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path)); - sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - fd = socket(AF_UNIX, SOCK_STREAM, 0); if(fd < 0) { @@ -986,10 +885,12 @@ static int cmd_start(int argc, char *argv[]) { #endif + char *default_c = "tincd"; + if(slash++) { xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name); } else { - c = "tincd"; + c = default_c; } int nargc = 0; @@ -1020,6 +921,12 @@ static int cmd_start(int argc, char *argv[]) { #ifdef HAVE_MINGW int status = spawnvp(_P_WAIT, c, nargv); + free(nargv); + + if(c != default_c) { + free(c); + } + if(status == -1) { fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno)); return 1; @@ -1032,6 +939,11 @@ static int cmd_start(int argc, char *argv[]) { if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) { fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno)); free(nargv); + + if(c != default_c) { + free(c); + } + return 1; } @@ -1040,6 +952,11 @@ static int cmd_start(int argc, char *argv[]) { if(pid == -1) { fprintf(stderr, "Could not fork: %s\n", strerror(errno)); free(nargv); + + if(c != default_c) { + free(c); + } + return 1; } @@ -1089,12 +1006,17 @@ static int cmd_start(int argc, char *argv[]) { signal(SIGINT, SIG_DFL); #endif - if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) { + bool failed = failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status); + + if(failed) { fprintf(stderr, "Error starting %s\n", c); - return 1; } - return 0; + if(c != default_c) { + free(c); + } + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; #endif } @@ -1107,7 +1029,7 @@ static int cmd_stop(int argc, char *argv[]) { } #ifdef HAVE_MINGW - return remove_service(); + return remove_service() ? EXIT_SUCCESS : EXIT_FAILURE; #else if(!stop_tincd()) { @@ -1842,7 +1764,7 @@ static int cmd_config(int argc, char *argv[]) { char *node = NULL; char *variable; char *value; - int len; + size_t len; len = strcspn(line, "\t ="); value = line + len; @@ -1889,11 +1811,12 @@ static int cmd_config(int argc, char *argv[]) { found = true; variable = (char *)variables[i].name; - if(!strcasecmp(variable, "Subnet")) { + if(!strcasecmp(variable, "Subnet") && *value) { subnet_t s = {0}; if(!str2net(&s, value)) { fprintf(stderr, "Malformed subnet definition %s\n", value); + return 1; } if(!subnetcheck(s)) { @@ -1949,6 +1872,11 @@ static int cmd_config(int argc, char *argv[]) { if(node && !check_id(node)) { fprintf(stderr, "Invalid name for node.\n"); + + if(node != line) { + free(node); + } + return 1; } @@ -1957,6 +1885,11 @@ static int cmd_config(int argc, char *argv[]) { fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable); } else { fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable); + + if(node && node != line) { + free(node); + } + return 1; } } @@ -1966,6 +1899,11 @@ static int cmd_config(int argc, char *argv[]) { if(node) { snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node); + + if(node != line) { + free(node); + node = NULL; + } } else { snprintf(filename, sizeof(filename), "%s", tinc_conf); } @@ -3325,6 +3263,11 @@ static int cmd_shell(int argc, char *argv[]) { return result; } +static void cleanup() { + free(tinc_conf); + free(hosts_dir); + free_names(); +} int main(int argc, char *argv[]) { program_name = argv[0]; @@ -3339,6 +3282,7 @@ int main(int argc, char *argv[]) { make_names(false); xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase); xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase); + atexit(cleanup); if(show_version) { version(); @@ -3360,7 +3304,8 @@ int main(int argc, char *argv[]) { #endif - srand(time(NULL)); + gettimeofday(&now, NULL); + srand(now.tv_sec + now.tv_usec); crypto_init(); if(optind >= argc) {