X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Ftincctl.c;h=b15676c88f55f4e9423bd384f5a9e5aba132620e;hb=1ac9a3fbd18f961d604c2c080374b8fc32f155d6;hp=2f7fe6b06fdd7a7f1a37037ef7272fbed89dbd66;hpb=35437a50e2a46861742b6fb8e49d065aa52a04dc;p=tinc diff --git a/src/tincctl.c b/src/tincctl.c index 2f7fe6b0..b15676c8 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -38,6 +38,7 @@ #include "utils.h" #include "tincctl.h" #include "top.h" +#include "version.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -74,6 +75,7 @@ char *scriptextension = ""; static char *prompt; static struct option const long_options[] = { + {"batch", no_argument, NULL, 'b'}, {"config", required_argument, NULL, 'c'}, {"net", required_argument, NULL, 'n'}, {"help", no_argument, NULL, 1}, @@ -85,7 +87,7 @@ static struct option const long_options[] = { static void version(void) { printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE, - VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR); + VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR); printf("Copyright (C) 1998-2012 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" @@ -99,6 +101,7 @@ static void usage(bool status) { } else { printf("Usage: %s [options] command\n\n", program_name); printf("Valid options are:\n" + " -b, --batch Don't ask for anything (non-interactive mode).\n" " -c, --config=DIR Read configuration options from DIR.\n" " -n, --net=NETNAME Connect to net NETNAME.\n" " --pidfile=FILENAME Read control cookie from FILENAME.\n" @@ -116,9 +119,9 @@ static void usage(bool status) { " restart [tincd options] Restart tincd.\n" " reload Partially reload configuration of running tincd.\n" " pid Show PID of currently running tincd.\n" - " generate-keys [bits] Generate new RSA and ECDSA public/private keypairs.\n" + " generate-keys [bits] Generate new RSA and Ed25519 public/private keypairs.\n" " generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n" - " generate-ecdsa-keys Generate a new ECDSA public/private keypair.\n" + " generate-ed25519-keys Generate a new Ed25519 public/private keypair.\n" " dump Dump a list of one of the following things:\n" " [reachable] nodes - all known nodes in the VPN\n" " edges - all known connections in the VPN\n" @@ -157,6 +160,10 @@ static bool parse_options(int argc, char **argv) { case 0: /* long option */ break; + case 'b': + tty = false; + break; + case 'c': /* config file */ confbase = xstrdup(optarg); confbasegiven = true; @@ -246,19 +253,19 @@ static void disable_old_keys(const char *filename, const char *what) { while(fgets(buf, sizeof buf, r)) { if(!block && !strncmp(buf, "-----BEGIN ", 11)) { - if((strstr(buf, " EC ") && strstr(what, "ECDSA")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) { + if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) { disabled = true; block = true; } } - bool ecdsapubkey = !strncasecmp(buf, "ECDSAPublicKey", 14) && strchr(" \t=", buf[14]) && strstr(what, "ECDSA"); + bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519"); - if(ecdsapubkey) + if(ed25519pubkey) disabled = true; if(w) { - if(block || ecdsapubkey) + if(block || ed25519pubkey) fputc('#', w); if(fputs(buf, w) < 0) { error = true; @@ -355,15 +362,15 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo } /* - Generate a public/private ECDSA keypair, and ask for a file to store + Generate a public/private Ed25519 keypair, and ask for a file to store them in. */ -static bool ecdsa_keygen(bool ask) { +static bool ed25519_keygen(bool ask) { ecdsa_t *key; FILE *f; char *pubname, *privname; - fprintf(stderr, "Generating ECDSA keypair:\n"); + fprintf(stderr, "Generating Ed25519 keypair:\n"); if(!(key = ecdsa_generate())) { fprintf(stderr, "Error during key generation!\n"); @@ -371,8 +378,8 @@ static bool ecdsa_keygen(bool ask) { } else fprintf(stderr, "Done.\n"); - xasprintf(&privname, "%s" SLASH "ecdsa_key.priv", confbase); - f = ask_and_open(privname, "private ECDSA key", "a", ask, 0600); + xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase); + f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600); free(privname); if(!f) @@ -390,16 +397,16 @@ static bool ecdsa_keygen(bool ask) { if(name) xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); else - xasprintf(&pubname, "%s" SLASH "ecdsa_key.pub", confbase); + xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase); - f = ask_and_open(pubname, "public ECDSA key", "a", ask, 0666); + f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666); free(pubname); if(!f) return false; char *pubkey = ecdsa_get_base64_public_key(key); - fprintf(f, "ECDSAPublicKey = %s\n", pubkey); + fprintf(f, "Ed25519PublicKey = %s\n", pubkey); free(pubkey); fclose(f); @@ -485,7 +492,7 @@ bool recvline(int fd, char *line, size_t len) { while(!(newline = memchr(buffer, '\n', blen))) { int result = recv(fd, buffer + blen, sizeof buffer - blen, 0); - if(result == -1 && errno == EINTR) + if(result == -1 && sockerrno == EINTR) continue; else if(result <= 0) return false; @@ -511,7 +518,7 @@ bool recvdata(int fd, char *data, size_t len) { while(blen < len) { int result = recv(fd, buffer + blen, sizeof buffer - blen, 0); - if(result == -1 && errno == EINTR) + if(result == -1 && sockerrno == EINTR) continue; else if(result <= 0) return false; @@ -543,7 +550,7 @@ bool sendline(int fd, char *format, ...) { while(blen) { int result = send(fd, p, blen, MSG_NOSIGNAL); - if(result == -1 && errno == EINTR) + if(result == -1 && sockerrno == EINTR) continue; else if(result <= 0) return false; @@ -723,7 +730,7 @@ bool connect_tincd(bool verbose) { if(getaddrinfo(host, port, &hints, &res) || !res) { if(verbose) - fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, strerror(errno)); + fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, sockstrerror(sockerrno)); return false; } @@ -756,7 +763,7 @@ bool connect_tincd(bool verbose) { #ifdef SO_NOSIGPIPE static const int one = 1; - setsockopt(c, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one); + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one); #endif char data[4096]; @@ -809,16 +816,31 @@ static int cmd_start(int argc, char *argv[]) { int nargc = 0; char **nargv = xzalloc((optind + argc) * sizeof *nargv); - nargv[nargc++] = c; + char *arg0 = c; +#ifdef HAVE_MINGW + /* + Windows has no real concept of an "argv array". A command line is just one string. + The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention) + it uses quotes to handle spaces in arguments. + Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN). + If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed + into the next arguments when the spawned process' CRT parses its command line, resulting in chaos. + */ + xasprintf(&arg0, "\"%s\"", arg0); +#endif + nargv[nargc++] = arg0; for(int i = 1; i < optind; i++) nargv[nargc++] = orig_argv[i]; for(int i = 1; i < argc; i++) nargv[nargc++] = argv[i]; #ifdef HAVE_MINGW - execvp(c, nargv); - fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno)); - return 1; + int status = spawnvp(_P_WAIT, c, nargv); + if (status == -1) { + fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno)); + return 1; + } + return status; #else pid_t pid = fork(); if(pid == -1) { @@ -985,6 +1007,8 @@ static int cmd_dump(int argc, char *argv[]) { char subnet[4096]; char host[4096]; char port[4096]; + char local_host[4096]; + char local_port[4096]; char via[4096]; char nexthop[4096]; int cipher, digest, maclength, compression, distance, socket, weight; @@ -1025,8 +1049,8 @@ static int cmd_dump(int argc, char *argv[]) { } break; case REQ_DUMP_EDGES: { - int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight); - if(n != 6) { + int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight); + if(n != 8) { fprintf(stderr, "Unable to parse edge dump from tincd.\n"); return 1; } @@ -1038,7 +1062,7 @@ static int cmd_dump(int argc, char *argv[]) { else if(do_graph == 2) printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w); } else { - printf("%s to %s at %s port %s options %x weight %d\n", from, to, host, port, options, weight); + printf("%s to %s at %s port %s local %s port %s options %x weight %d\n", from, to, host, port, local_host, local_port, options, weight); } } break; @@ -1281,7 +1305,7 @@ char *get_my_name(bool verbose) { continue; if(*value) { fclose(f); - return strdup(value); + return replace_name(value); } } @@ -1303,7 +1327,7 @@ const var_t variables[] = { {"Device", VAR_SERVER}, {"DeviceType", VAR_SERVER}, {"DirectOnly", VAR_SERVER}, - {"ECDSAPrivateKeyFile", VAR_SERVER}, + {"Ed25519PrivateKeyFile", VAR_SERVER}, {"ExperimentalProtocol", VAR_SERVER}, {"Forwarding", VAR_SERVER}, {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE}, @@ -1341,8 +1365,8 @@ const var_t variables[] = { {"ClampMSS", VAR_SERVER | VAR_HOST}, {"Compression", VAR_SERVER | VAR_HOST}, {"Digest", VAR_SERVER | VAR_HOST}, - {"ECDSAPublicKey", VAR_HOST}, - {"ECDSAPublicKeyFile", VAR_SERVER | VAR_HOST}, + {"Ed25519PublicKey", VAR_HOST}, + {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST}, {"IndirectData", VAR_SERVER | VAR_HOST}, {"MACLength", VAR_SERVER | VAR_HOST}, {"PMTU", VAR_SERVER | VAR_HOST}, @@ -1611,9 +1635,12 @@ static int cmd_config(int argc, char *argv[]) { } if(action < -1) { - if(!found) + if(found) { + return 0; + } else { fprintf(stderr, "No matching configuration variables found.\n"); - return 0; + return 1; + } } // Make sure we wrote everything... @@ -1626,7 +1653,7 @@ static int cmd_config(int argc, char *argv[]) { if(action < 0 && !removed) { remove(tmpfile); fprintf(stderr, "No configuration variables deleted.\n"); - return *value != 0; + return 1; } // Replace the configuration file with the new one @@ -1648,18 +1675,6 @@ static int cmd_config(int argc, char *argv[]) { return 0; } -bool check_id(const char *name) { - if(!name || !*name) - return false; - - for(int i = 0; i < strlen(name); i++) { - if(!isalnum(name[i]) && name[i] != '_') - return false; - } - - return true; -} - static bool try_bind(int port) { struct addrinfo *ai = NULL; struct addrinfo hint = { @@ -1782,7 +1797,7 @@ static int cmd_init(int argc, char *argv[]) { fprintf(f, "Name = %s\n", name); fclose(f); - if(!rsa_keygen(2048, false) || !ecdsa_keygen(false)) + if(!rsa_keygen(2048, false) || !ed25519_keygen(false)) return 1; check_port(name); @@ -1814,7 +1829,7 @@ static int cmd_generate_keys(int argc, char *argv[]) { if(!name) name = get_my_name(false); - return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ecdsa_keygen(true)); + return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ed25519_keygen(true)); } static int cmd_generate_rsa_keys(int argc, char *argv[]) { @@ -1829,7 +1844,7 @@ static int cmd_generate_rsa_keys(int argc, char *argv[]) { return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true); } -static int cmd_generate_ecdsa_keys(int argc, char *argv[]) { +static int cmd_generate_ed25519_keys(int argc, char *argv[]) { if(argc > 1) { fprintf(stderr, "Too many arguments!\n"); return 1; @@ -1838,7 +1853,7 @@ static int cmd_generate_ecdsa_keys(int argc, char *argv[]) { if(!name) name = get_my_name(false); - return !ecdsa_keygen(true); + return !ed25519_keygen(true); } static int cmd_help(int argc, char *argv[]) { @@ -2179,7 +2194,7 @@ static const struct { {"init", cmd_init}, {"generate-keys", cmd_generate_keys}, {"generate-rsa-keys", cmd_generate_rsa_keys}, - {"generate-ecdsa-keys", cmd_generate_ecdsa_keys}, + {"generate-ed25519-keys", cmd_generate_ed25519_keys}, {"help", cmd_help}, {"version", cmd_version}, {"info", cmd_info}, @@ -2421,6 +2436,7 @@ int main(int argc, char *argv[]) { program_name = argv[0]; orig_argv = argv; orig_argc = argc; + tty = isatty(0) && isatty(1); if(!parse_options(argc, argv)) return 1; @@ -2451,8 +2467,6 @@ int main(int argc, char *argv[]) { srand(time(NULL)); crypto_init(); - tty = isatty(0) && isatty(1); - if(optind >= argc) return cmd_shell(argc, argv);