Merge branch 'master' into 1.1
[tinc] / src / tincd.c
index bec16cd..76053a0 100644 (file)
 #include <sys/mman.h>
 #endif
 
-#include <openssl/rand.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-
 #include LZO1X_H
 
 #ifndef HAVE_MINGW
 #endif
 
 #include <getopt.h>
-#include "pidfile.h"
 
 #include "conf.h"
+#include "control.h"
+#include "crypto.h"
 #include "device.h"
 #include "logger.h"
 #include "net.h"
@@ -67,12 +62,6 @@ bool show_help = false;
 /* If nonzero, print the version on standard output and exit.  */
 bool show_version = false;
 
-/* If nonzero, it will attempt to kill a running tincd and exit. */
-int kill_tincd = 0;
-
-/* If nonzero, generate public/private keypair for this host/net. */
-int generate_keys = 0;
-
 /* If nonzero, use null ciphers and skip all key exchanges. */
 bool bypass_security = false;
 
@@ -89,7 +78,7 @@ static const char *switchuser = NULL;
 bool use_logfile = false;
 
 char *identname = NULL;                                /* program name for syslog */
-char *pidfilename = NULL;                      /* pid file location */
+char *controlsocketname = NULL;                        /* control socket location */
 char *logfilename = NULL;                      /* log file location */
 char **g_argv;                                 /* a copy of the cmdline arguments */
 
@@ -97,19 +86,17 @@ static int status;
 
 static struct option const long_options[] = {
        {"config", required_argument, NULL, 'c'},
-       {"kill", optional_argument, NULL, 'k'},
        {"net", required_argument, NULL, 'n'},
        {"help", no_argument, NULL, 1},
        {"version", no_argument, NULL, 2},
        {"no-detach", no_argument, NULL, 'D'},
-       {"generate-keys", optional_argument, NULL, 'K'},
        {"debug", optional_argument, NULL, 'd'},
        {"bypass-security", no_argument, NULL, 3},
        {"mlock", no_argument, NULL, 'L'},
        {"chroot", no_argument, NULL, 'R'},
        {"user", required_argument, NULL, 'U'},
        {"logfile", optional_argument, NULL, 4},
-       {"pidfile", required_argument, NULL, 5},
+       {"controlsocket", required_argument, NULL, 5},
        {NULL, 0, NULL, 0}
 };
 
@@ -124,19 +111,17 @@ static void usage(bool status)
                                program_name);
        else {
                printf(_("Usage: %s [option]...\n\n"), program_name);
-               printf(_("  -c, --config=DIR           Read configuration options from DIR.\n"
-                               "  -D, --no-detach            Don't fork and detach.\n"
-                               "  -d, --debug[=LEVEL]        Increase debug level or set it to LEVEL.\n"
-                               "  -k, --kill[=SIGNAL]        Attempt to kill a running tincd and exit.\n"
-                               "  -n, --net=NETNAME          Connect to net NETNAME.\n"
-                               "  -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
-                               "  -L, --mlock                Lock tinc into main memory.\n"
-                               "      --logfile[=FILENAME]   Write log entries to a logfile.\n"
-                               "      --pidfile=FILENAME     Write PID to FILENAME.\n"
-                               "  -R, --chroot               chroot to NET dir at startup.\n"
-                               "  -U, --user=USER            setuid to given USER at startup.\n"
-                               "      --help                 Display this help and exit.\n"
-                               "      --version              Output version information and exit.\n\n"));
+               printf(_(       "  -c, --config=DIR              Read configuration options from DIR.\n"
+                               "  -D, --no-detach               Don't fork and detach.\n"
+                               "  -d, --debug[=LEVEL]           Increase debug level or set it to LEVEL.\n"
+                               "  -n, --net=NETNAME             Connect to net NETNAME.\n"
+                               "  -L, --mlock                   Lock tinc into main memory.\n"
+                               "      --logfile[=FILENAME]      Write log entries to a logfile.\n"
+                               "      --controlsocket=FILENAME  Open control socket at FILENAME.\n"
+                               "      --bypass-security         Disables meta protocol security, for debugging.\n"
+                               "  -R, --chroot                  chroot to NET dir at startup.\n"
+                               "  -U, --user=USER               setuid to given USER at startup.\n"                            "      --help                    Display this help and exit.\n"
+                               "      --version                 Output version information and exit.\n\n"));
                printf(_("Report bugs to tinc@tinc-vpn.org.\n"));
        }
 }
@@ -146,7 +131,7 @@ static bool parse_options(int argc, char **argv)
        int r;
        int option_index = 0;
 
-       while((r = getopt_long(argc, argv, "c:DLd::k::n:K::RU:", long_options, &option_index)) != EOF) {
+       while((r = getopt_long(argc, argv, "c:DLd::n:RU:", long_options, &option_index)) != EOF) {
                switch (r) {
                        case 0:                         /* long option */
                                break;
@@ -175,62 +160,10 @@ static bool parse_options(int argc, char **argv)
                                        debug_level++;
                                break;
 
-                       case 'k':                               /* kill old tincds */
-#ifndef HAVE_MINGW
-                               if(optarg) {
-                                       if(!strcasecmp(optarg, "HUP"))
-                                               kill_tincd = SIGHUP;
-                                       else if(!strcasecmp(optarg, "TERM"))
-                                               kill_tincd = SIGTERM;
-                                       else if(!strcasecmp(optarg, "KILL"))
-                                               kill_tincd = SIGKILL;
-                                       else if(!strcasecmp(optarg, "USR1"))
-                                               kill_tincd = SIGUSR1;
-                                       else if(!strcasecmp(optarg, "USR2"))
-                                               kill_tincd = SIGUSR2;
-                                       else if(!strcasecmp(optarg, "WINCH"))
-                                               kill_tincd = SIGWINCH;
-                                       else if(!strcasecmp(optarg, "INT"))
-                                               kill_tincd = SIGINT;
-                                       else if(!strcasecmp(optarg, "ALRM"))
-                                               kill_tincd = SIGALRM;
-                                       else {
-                                               kill_tincd = atoi(optarg);
-
-                                               if(!kill_tincd) {
-                                                       fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"),
-                                                                       optarg);
-                                                       usage(true);
-                                                       return false;
-                                               }
-                                       }
-                               } else
-                                       kill_tincd = SIGTERM;
-#else
-                                       kill_tincd = 1;
-#endif
-                               break;
-
                        case 'n':                               /* net name given */
                                netname = xstrdup(optarg);
                                break;
 
-                       case 'K':                               /* generate public/private keypair */
-                               if(optarg) {
-                                       generate_keys = atoi(optarg);
-
-                                       if(generate_keys < 512) {
-                                               fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"),
-                                                               optarg);
-                                               usage(true);
-                                               return false;
-                                       }
-
-                                       generate_keys &= ~7;    /* Round it to bytes */
-                               } else
-                                       generate_keys = 1024;
-                               break;
-
                        case 'R':                               /* chroot to NETNAME dir */
                                do_chroot = true;
                                break;
@@ -257,8 +190,8 @@ static bool parse_options(int argc, char **argv)
                                        logfilename = xstrdup(optarg);
                                break;
 
-                       case 5:                                 /* write PID to a file */
-                               pidfilename = xstrdup(optarg);
+                       case 5:                                 /* open control socket here */
+                               controlsocketname = xstrdup(optarg);
                                break;
 
                        case '?':
@@ -273,110 +206,6 @@ static bool parse_options(int argc, char **argv)
        return true;
 }
 
-/* This function prettyprints the key generation process */
-
-static void indicator(int a, int b, void *p)
-{
-       switch (a) {
-               case 0:
-                       fprintf(stderr, ".");
-                       break;
-
-               case 1:
-                       fprintf(stderr, "+");
-                       break;
-
-               case 2:
-                       fprintf(stderr, "-");
-                       break;
-
-               case 3:
-                       switch (b) {
-                               case 0:
-                                       fprintf(stderr, " p\n");
-                                       break;
-
-                               case 1:
-                                       fprintf(stderr, " q\n");
-                                       break;
-
-                               default:
-                                       fprintf(stderr, "?");
-                       }
-                       break;
-
-               default:
-                       fprintf(stderr, "?");
-       }
-}
-
-/*
-  Generate a public/private RSA keypair, and ask for a file to store
-  them in.
-*/
-static bool keygen(int bits)
-{
-       RSA *rsa_key;
-       FILE *f;
-       char *name = NULL;
-       char *filename;
-
-       get_config_string(lookup_config(config_tree, "Name"), &name);
-
-       if(name && !check_id(name)) {
-               fprintf(stderr, _("Invalid name for myself!\n"));
-               return false;
-       }
-
-       fprintf(stderr, _("Generating %d bits keys:\n"), bits);
-       rsa_key = RSA_generate_key(bits, 0x10001, indicator, NULL);
-
-       if(!rsa_key) {
-               fprintf(stderr, _("Error during key generation!\n"));
-               return false;
-       } else
-               fprintf(stderr, _("Done.\n"));
-
-       asprintf(&filename, "%s/rsa_key.priv", confbase);
-       f = ask_and_open(filename, _("private RSA key"));
-
-       if(!f)
-               return false;
-
-       if(disable_old_keys(f))
-               fprintf(stderr, _("Warning: old key(s) found and disabled.\n"));
-  
-#ifdef HAVE_FCHMOD
-       /* Make it unreadable for others. */
-       fchmod(fileno(f), 0600);
-#endif
-               
-       PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
-       fclose(f);
-       free(filename);
-
-       if(name)
-               asprintf(&filename, "%s/hosts/%s", confbase, name);
-       else
-               asprintf(&filename, "%s/rsa_key.pub", confbase);
-
-       f = ask_and_open(filename, _("public RSA key"));
-
-       if(!f)
-               return false;
-
-       if(disable_old_keys(f))
-               fprintf(stderr, _("Warning: old key(s) found and disabled.\n"));
-
-       PEM_write_RSAPublicKey(f, rsa_key);
-       fclose(f);
-       free(filename);
-       if(name)
-               free(name);
-
-       return true;
-}
-
 /*
   Set all files and paths according to netname
 */
@@ -385,7 +214,7 @@ static void make_names(void)
 #ifdef HAVE_MINGW
        HKEY key;
        char installdir[1024] = "";
-       long len = sizeof(installdir);
+       long len = sizeof installdir;
 #endif
 
        if(netname)
@@ -411,8 +240,8 @@ static void make_names(void)
        }
 #endif
 
-       if(!pidfilename)
-               asprintf(&pidfilename, LOCALSTATEDIR "/run/%s.pid", identname);
+       if(!controlsocketname)
+               asprintf(&controlsocketname, "%s/run/%s.control/socket", LOCALSTATEDIR, identname);
 
        if(!logfilename)
                asprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname);
@@ -431,7 +260,7 @@ static void make_names(void)
 static void free_names() {
        if (identname) free(identname);
        if (netname) free(netname);
-       if (pidfilename) free(pidfilename);
+       if (controlsocketname) free(controlsocketname);
        if (logfilename) free(logfilename);
        if (confbase) free(confbase);
 }
@@ -523,28 +352,24 @@ int main(int argc, char **argv)
                return 0;
        }
 
-       if(kill_tincd)
-               return !kill_other(kill_tincd);
-
        openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR);
 
+       if(!event_init()) {
+               logger(LOG_ERR, _("Error initializing libevent!"));
+               return 1;
+       }
+
+       if(!init_control())
+               return 1;
+
        g_argv = argv;
 
        init_configuration(&config_tree);
 
        /* Slllluuuuuuurrrrp! */
 
-       RAND_load_file("/dev/urandom", 1024);
-
-       ENGINE_load_builtin_engines();
-       ENGINE_register_all_complete();
-
-       OpenSSL_add_all_algorithms();
-
-       if(generate_keys) {
-               read_server_config();
-               return !keygen(generate_keys);
-       }
+       srand(time(NULL));
+       crypto_init();
 
        if(!read_server_config())
                return 1;
@@ -629,14 +454,10 @@ end:
        logger(LOG_NOTICE, _("Terminating"));
 
 #ifndef HAVE_MINGW
-       remove_pid(pidfilename);
+       exit_control();
 #endif
 
-       EVP_cleanup();
-       ENGINE_cleanup();
-       CRYPTO_cleanup_all_ex_data();
-       ERR_remove_state(0);
-       ERR_free_strings();
+       crypto_exit();
 
        exit_configuration(&config_tree);
        free_names();