Add sanity checks when generating new RSA keys.
[tinc] / src / tincctl.c
index c3fa2fa..2f7fe6b 100644 (file)
 #include "tincctl.h"
 #include "top.h"
 
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
 static char **orig_argv;
 static int orig_argc;
 
@@ -67,6 +71,7 @@ bool confbasegiven = false;
 bool netnamegiven = false;
 char *scriptinterpreter = NULL;
 char *scriptextension = "";
+static char *prompt;
 
 static struct option const long_options[] = {
        {"config", required_argument, NULL, 'c'},
@@ -137,6 +142,7 @@ static void usage(bool status) {
                                "  exchange-all [--force]     Same as export-all followed by import\n"
                                "  invite NODE [...]          Generate an invitation for NODE\n"
                                "  join INVITATION            Join a VPN using an INVITIATION\n"
+                               "  network [NETNAME]          List all known networks, or switch to the one named NETNAME.\n"
                                "\n");
                printf("Report bugs to tinc@tinc-vpn.org.\n");
        }
@@ -411,6 +417,15 @@ static bool rsa_keygen(int bits, bool ask) {
        FILE *f;
        char *pubname, *privname;
 
+       // Make sure the key size is a multiple of 8 bits.
+       bits &= ~0x7;
+
+       // Force them to be between 1024 and 8192 bits long.
+       if(bits < 1024)
+               bits = 1024;
+       if(bits > 8192)
+               bits = 8192;
+
        fprintf(stderr, "Generating %d bits keys:\n", bits);
 
        if(!(key = rsa_generate(bits, 0x10001))) {
@@ -527,7 +542,7 @@ bool sendline(int fd, char *format, ...) {
        blen++;
 
        while(blen) {
-               int result = send(fd, p, blen, 0);
+               int result = send(fd, p, blen, MSG_NOSIGNAL);
                if(result == -1 && errno == EINTR)
                        continue;
                else if(result <= 0)
@@ -739,6 +754,11 @@ bool connect_tincd(bool verbose) {
        freeaddrinfo(res);
 #endif
 
+#ifdef SO_NOSIGPIPE
+       static const int one = 1;
+       setsockopt(c, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one);
+#endif
+
        char data[4096];
        int version;
 
@@ -2066,6 +2086,72 @@ static int cmd_exchange_all(int argc, char *argv[]) {
        return cmd_export_all(argc, argv) ?: cmd_import(argc, argv);
 }
 
+static int switch_network(char *name) {
+       if(fd >= 0) {
+               close(fd);
+               fd = -1;
+       }
+
+       free(confbase);
+       confbase = NULL;
+       free(pidfilename);
+       pidfilename = NULL;
+       free(logfilename);
+       logfilename = NULL;
+       free(unixsocketname);
+       unixsocketname = NULL;
+       free(tinc_conf);
+       free(hosts_dir);
+       free(prompt);
+
+       free(netname);
+       netname = strcmp(name, ".") ? xstrdup(name) : NULL;
+
+       make_names();
+        xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
+        xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
+       xasprintf(&prompt, "%s> ", identname);
+
+       return 0;
+}
+
+static int cmd_network(int argc, char *argv[]) {
+       if(argc > 2) {
+               fprintf(stderr, "Too many arguments!\n");
+               return 1;
+       }
+
+       if(argc == 2)
+               return switch_network(argv[1]);
+
+       DIR *dir = opendir(confdir);
+       if(!dir) {
+               fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
+                return 1;
+        }
+
+       struct dirent *ent;
+       while((ent = readdir(dir))) {
+               if(*ent->d_name == '.')
+                       continue;
+
+               if(!strcmp(ent->d_name, "tinc.conf")) {
+                       printf(".\n");
+                       continue;
+               }
+
+               char *fname;
+               xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
+               if(!access(fname, R_OK))
+                       printf("%s\n", ent->d_name);
+               free(fname);
+       }
+
+       closedir(dir);
+
+       return 0;
+}
+
 static const struct {
        const char *command;
        int (*function)(int argc, char *argv[]);
@@ -2105,6 +2191,7 @@ static const struct {
        {"exchange-all", cmd_exchange_all},
        {"invite", cmd_invite},
        {"join", cmd_join},
+       {"network", cmd_network},
        {NULL, NULL},
 };
 
@@ -2231,7 +2318,6 @@ static char **completion (const char *text, int start, int end) {
 #endif
 
 static int cmd_shell(int argc, char *argv[]) {
-       char *prompt;
        xasprintf(&prompt, "%s> ", identname);
        int result = 0;
        char buf[4096];