From e9043e17c76f92b787c9ecdaf1a2ae7916f690a6 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 19 May 2007 14:55:35 +0000 Subject: [PATCH] Move key generation to tincctl. --- src/conf.c | 63 ------------------------- src/tincctl.c | 74 +++++++++++++++++++++++++++--- src/tincd.c | 125 +------------------------------------------------- 3 files changed, 68 insertions(+), 194 deletions(-) diff --git a/src/conf.c b/src/conf.c index 49b78bbc..4108d8ba 100644 --- a/src/conf.c +++ b/src/conf.c @@ -410,66 +410,3 @@ bool read_server_config() { return x == 0; } - -FILE *ask_and_open(const char *filename, const char *what, const char *mode) { - FILE *r; - char *directory; - char *fn; - - /* Check stdin and stdout */ - if(!isatty(0) || !isatty(1)) { - /* Argh, they are running us from a script or something. Write - the files to the current directory and let them burn in hell - for ever. */ - fn = xstrdup(filename); - } else { - /* Ask for a file and/or directory name. */ - fprintf(stdout, _("Please enter a file to save %s to [%s]: "), - what, filename); - fflush(stdout); - - fn = readline(stdin, NULL, NULL); - - if(!fn) { - fprintf(stderr, _("Error while reading stdin: %s\n"), - strerror(errno)); - return NULL; - } - - if(!strlen(fn)) - /* User just pressed enter. */ - fn = xstrdup(filename); - } - -#ifdef HAVE_MINGW - if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) { -#else - if(fn[0] != '/') { -#endif - /* The directory is a relative path or a filename. */ - char *p; - - directory = get_current_dir_name(); - asprintf(&p, "%s/%s", directory, fn); - free(fn); - free(directory); - fn = p; - } - - umask(0077); /* Disallow everything for group and other */ - - /* Open it first to keep the inode busy */ - - r = fopen(fn, mode); - - if(!r) { - fprintf(stderr, _("Error opening file `%s': %s\n"), - fn, strerror(errno)); - free(fn); - return NULL; - } - - free(fn); - - return r; -} diff --git a/src/tincctl.c b/src/tincctl.c index a90f7a28..c4a96663 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -30,7 +30,6 @@ #include -#include "conf.h" #include "protocol.h" #include "xalloc.h" @@ -49,12 +48,10 @@ int kill_tincd = 0; /* If nonzero, generate public/private keypair for this host/net. */ int generate_keys = 0; -char *identname = NULL; /* program name for syslog */ -char *controlsocketname = NULL; /* pid file location */ -char *confbase = NULL; +static char *identname = NULL; /* program name for syslog */ +static char *controlsocketname = NULL; /* pid file location */ char *netname = NULL; - -static int status; +char *confbase = NULL; static struct option const long_options[] = { {"config", required_argument, NULL, 'c'}, @@ -83,7 +80,7 @@ static void usage(bool status) { " stop Stop tincd.\n" " restart Restart tincd.\n" " reload Reload configuration of running tincd.\n" - " genkey [bits] Generate a new public/private keypair.\n" + " generate-keys [bits] Generate a new public/private keypair.\n" " dump Dump a list of one of the following things:\n" " nodes - all known nodes in the VPN\n" " edges - all known connections in the VPN\n" @@ -136,6 +133,59 @@ static bool parse_options(int argc, char **argv) { return true; } +FILE *ask_and_open(const char *filename, const char *what, const char *mode) { + FILE *r; + char *directory; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + size_t len; + + /* Check stdin and stdout */ + if(isatty(0) && isatty(1)) { + /* Ask for a file and/or directory name. */ + fprintf(stdout, _("Please enter a file to save %s to [%s]: "), + what, filename); + fflush(stdout); + + if(fgets(buf, sizeof buf, stdin) < 0) { + fprintf(stderr, _("Error while reading stdin: %s\n"), + strerror(errno)); + return NULL; + } + + len = strlen(buf); + if(len) + buf[--len] = 0; + + if(len) + filename = buf; + } + +#ifdef HAVE_MINGW + if(filename[0] != '\\' && filename[0] != '/' && !strchr(filename, ':')) { +#else + if(filename[0] != '/') { +#endif + /* The directory is a relative path or a filename. */ + directory = get_current_dir_name(); + snprintf(buf2, sizeof buf2, "%s/%s", directory, filename); + filename = buf2; + } + + umask(0077); /* Disallow everything for group and other */ + + /* Open it first to keep the inode busy */ + + r = fopen(filename, mode); + + if(!r) { + fprintf(stderr, _("Error opening file `%s': %s\n"), filename, strerror(errno)); + return NULL; + } + + return r; +} + /* This function prettyprints the key generation process */ static void indicator(int a, int b, void *p) { @@ -307,6 +357,16 @@ int main(int argc, char **argv) { return 0; } + if(optind >= argc) { + fprintf(stderr, _("Not enough arguments.\n")); + usage(true); + return 1; + } + + if(!strcasecmp(argv[optind], "generate-keys")) { + return !keygen(optind > argc ? atoi(argv[optind + 1]) : 1024); + } + if(strlen(controlsocketname) >= sizeof addr.sun_path) { fprintf(stderr, _("Control socket filename too long!\n")); return 1; diff --git a/src/tincd.c b/src/tincd.c index 7efc6324..95c45d3b 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -61,9 +61,6 @@ bool show_help = false; /* If nonzero, print the version on standard output and exit. */ bool show_version = false; -/* 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; @@ -86,7 +83,6 @@ static struct option const long_options[] = { {"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'}, @@ -110,7 +106,6 @@ static void usage(bool status) " -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" - " -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" " --controlsocket=FILENAME Open control socket at FILENAME.\n" @@ -125,7 +120,7 @@ static bool parse_options(int argc, char **argv) int r; int option_index = 0; - while((r = getopt_long(argc, argv, "c:DLd::n:K::", long_options, &option_index)) != EOF) { + while((r = getopt_long(argc, argv, "c:DLd::n:", long_options, &option_index)) != EOF) { switch (r) { case 0: /* long option */ break; @@ -153,22 +148,6 @@ static bool parse_options(int argc, char **argv) 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 1: /* show help */ show_help = true; break; @@ -203,103 +182,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; - - 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"), "a"); - - if(!f) - return false; - -#ifdef HAVE_FCHMOD - /* Make it unreadable for others. */ - fchmod(fileno(f), 0600); -#endif - - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); - - PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); - fclose(f); - free(filename); - - get_config_string(lookup_config(config_tree, "Name"), &name); - - 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"), "a"); - - if(!f) - return false; - - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); - - PEM_write_RSAPublicKey(f, rsa_key); - fclose(f); - free(filename); - - return true; -} - /* Set all files and paths according to netname */ @@ -419,11 +301,6 @@ int main(int argc, char **argv) OpenSSL_add_all_algorithms(); - if(generate_keys) { - read_server_config(); - return !keygen(generate_keys); - } - if(!read_server_config()) return 1;