X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Ftincctl.c;h=2ed286a62d95881ede05da7ddd97e0c7dd7433f7;hb=9235256116574927657a93944ef1b21e255e771b;hp=4a3682f3894d7cdcbb4371faf07b78c1f24eede8;hpb=0289162552cd85375605044c696e2a3294e7aa9a;p=tinc diff --git a/src/tincctl.c b/src/tincctl.c index 4a3682f3..2ed286a6 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -41,7 +41,10 @@ #include "subnet.h" #include "keys.h" #include "random.h" +#include "sandbox.h" #include "pidfile.h" +#include "console.h" +#include "fs.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -79,19 +82,35 @@ char *device = NULL; char *iface = NULL; int debug_level = -1; +typedef enum option_t { + OPT_BAD_OPTION = '?', + OPT_LONG_OPTION = 0, + + // Short options + OPT_BATCH = 'b', + OPT_CONFIG_FILE = 'c', + OPT_NETNAME = 'n', + + // Long options + OPT_HELP = 255, + OPT_VERSION, + OPT_PIDFILE, + OPT_FORCE, +} option_t; + 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}, - {"version", no_argument, NULL, 2}, - {"pidfile", required_argument, NULL, 3}, - {"force", no_argument, NULL, 4}, - {NULL, 0, NULL, 0} + {"batch", no_argument, NULL, OPT_BATCH}, + {"config", required_argument, NULL, OPT_CONFIG_FILE}, + {"net", required_argument, NULL, OPT_NETNAME}, + {"help", no_argument, NULL, OPT_HELP}, + {"version", no_argument, NULL, OPT_VERSION}, + {"pidfile", required_argument, NULL, OPT_PIDFILE}, + {"force", no_argument, NULL, OPT_FORCE}, + {NULL, 0, NULL, 0}, }; static void version(void) { - static const char *message = + fprintf(stdout, "%s version %s (built %s %s, protocol %d.%d)\n" "Features:" #ifdef HAVE_READLINE @@ -102,6 +121,9 @@ static void version(void) { #endif #ifndef DISABLE_LEGACY " legacy_protocol" +#endif +#ifdef HAVE_SANDBOX + " sandbox" #endif "\n\n" "Copyright (C) 1998-2018 Ivo Timmermans, Guus Sliepen and others.\n" @@ -109,16 +131,15 @@ static void version(void) { "\n" "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" "and you are welcome to redistribute it under certain conditions;\n" - "see the file COPYING for details.\n"; - - printf(message, PACKAGE, BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR); + "see the file COPYING for details.\n", + PACKAGE, BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR); } static void usage(bool status) { if(status) { fprintf(stderr, "Try `%s --help\' for more information.\n", program_name); } else { - static const char *message = + fprintf(stdout, "Usage: %s [options] command\n" "\n" "Valid options are:\n" @@ -177,9 +198,8 @@ static void usage(bool status) { " sign [FILE] Generate a signed version of a file.\n" " verify NODE [FILE] Verify that a file was signed by the given NODE.\n" "\n" - "Report bugs to tinc@tinc-vpn.org.\n"; - - printf(message, program_name); + "Report bugs to tinc@tinc-vpn.org.\n", + program_name); } } @@ -188,47 +208,47 @@ static bool parse_options(int argc, char **argv) { int option_index = 0; while((r = getopt_long(argc, argv, "+bc:n:", long_options, &option_index)) != EOF) { - switch(r) { - case 0: /* long option */ + switch((option_t) r) { + case OPT_LONG_OPTION: break; - case 'b': + case OPT_BAD_OPTION: + usage(true); + free_names(); + return false; + + case OPT_BATCH: tty = false; break; - case 'c': /* config file */ + case OPT_CONFIG_FILE: free(confbase); confbase = xstrdup(optarg); confbasegiven = true; break; - case 'n': /* net name given */ + case OPT_NETNAME: free(netname); netname = xstrdup(optarg); break; - case 1: /* show help */ + case OPT_HELP: show_help = true; break; - case 2: /* show version */ + case OPT_VERSION: show_version = true; break; - case 3: /* open control socket here */ + case OPT_PIDFILE: free(pidfilename); pidfilename = xstrdup(optarg); break; - case 4: /* force */ + case OPT_FORCE: force = true; break; - case '?': /* wrong options */ - usage(true); - free_names(); - return false; - default: break; } @@ -612,8 +632,9 @@ static void pcap(int fd, FILE *out, uint32_t snaplen) { } } -static void logcontrol(int fd, FILE *out, int level) { - sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level); +static void log_control(int fd, FILE *out, int level, bool use_color) { + sendline(fd, "%d %d %d %d", CONTROL, REQ_LOG, level, use_color); + char data[1024]; char line[32]; @@ -955,7 +976,7 @@ static int cmd_start(int argc, char *argv[]) { if(!pid) { close(pfd[0]); char buf[100]; - snprintf(buf, sizeof(buf), "%d", pfd[1]); + snprintf(buf, sizeof(buf), "%d %d", pfd[1], use_ansi_escapes(stderr)); setenv("TINC_UMBILICAL", buf, true); exit(execvp(c, nargv)); } else { @@ -1499,7 +1520,10 @@ static int cmd_pcap(int argc, char *argv[]) { static void sigint_handler(int sig) { (void)sig; - fprintf(stderr, "\n"); + if(write(2, "\n", 1) < 0) { + // nothing we can do + } + shutdown(fd, SHUT_RDWR); } #endif @@ -1518,7 +1542,8 @@ static int cmd_log(int argc, char *argv[]) { signal(SIGINT, sigint_handler); #endif - logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1); + bool use_color = use_ansi_escapes(stdout); + log_control(fd, stdout, argc > 1 ? atoi(argv[1]) : DEBUG_UNSET, use_color); #ifdef SIGINT signal(SIGINT, SIG_DFL); @@ -1604,7 +1629,8 @@ char *get_my_name(bool verbose) { return NULL; } -ecdsa_t *get_pubkey(FILE *f) { +static ecdsa_t *get_pubkey(FILE *f) ATTR_MALLOC ATTR_DEALLOCATOR(ecdsa_free); +static ecdsa_t *get_pubkey(FILE *f) { char buf[4096]; char *value; @@ -1677,6 +1703,7 @@ const var_t variables[] = { {"ProcessPriority", VAR_SERVER}, {"Proxy", VAR_SERVER}, {"ReplayWindow", VAR_SERVER | VAR_SAFE}, + {"Sandbox", VAR_SERVER}, {"ScriptsExtension", VAR_SERVER}, {"ScriptsInterpreter", VAR_SERVER}, {"StrictSubnets", VAR_SERVER | VAR_SAFE}, @@ -1908,16 +1935,18 @@ static int cmd_config(int argc, char *argv[]) { char filename[PATH_MAX]; if(node) { - if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node) >= sizeof(filename)) { - fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, node); - free(node); - return 1; - } + size_t wrote = (size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node); if(node != line) { free(node); node = NULL; } + + if(wrote >= sizeof(filename)) { + fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, node); + return 1; + } + } else { snprintf(filename, sizeof(filename), "%s", tinc_conf); } @@ -2206,19 +2235,8 @@ static int cmd_init(int argc, char *argv[]) { return 1; } - if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno)); - return 1; - } - - if(mkdir(confbase, 0777) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno)); - return 1; - } - - if(mkdir(hosts_dir, 0777) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno)); - return 1; + if(!makedirs(DIR_HOSTS | DIR_CONFBASE | DIR_CONFDIR | DIR_CACHE)) { + return false; } FILE *f = fopen(tinc_conf, "w"); @@ -2517,7 +2535,7 @@ static int cmd_export_all(int argc, char *argv[]) { if(first) { first = false; } else { - printf("#---------------------------------------------------------------#\n"); + printf("\n#---------------------------------------------------------------#\n"); } result |= export(ent->d_name, stdout); @@ -3332,6 +3350,9 @@ int main(int argc, char *argv[]) { crypto_init(); prng_init(); + sandbox_set_level(SANDBOX_NORMAL); + sandbox_enter(); + int result = run_command(argc, argv); random_exit();