Move key generation to tincctl.
This commit is contained in:
parent
bf8e3ce13d
commit
e9043e17c7
3 changed files with 68 additions and 194 deletions
63
src/conf.c
63
src/conf.c
|
@ -410,66 +410,3 @@ bool read_server_config() {
|
||||||
|
|
||||||
return x == 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "conf.h"
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
|
@ -49,12 +48,10 @@ int kill_tincd = 0;
|
||||||
/* If nonzero, generate public/private keypair for this host/net. */
|
/* If nonzero, generate public/private keypair for this host/net. */
|
||||||
int generate_keys = 0;
|
int generate_keys = 0;
|
||||||
|
|
||||||
char *identname = NULL; /* program name for syslog */
|
static char *identname = NULL; /* program name for syslog */
|
||||||
char *controlsocketname = NULL; /* pid file location */
|
static char *controlsocketname = NULL; /* pid file location */
|
||||||
char *confbase = NULL;
|
|
||||||
char *netname = NULL;
|
char *netname = NULL;
|
||||||
|
char *confbase = NULL;
|
||||||
static int status;
|
|
||||||
|
|
||||||
static struct option const long_options[] = {
|
static struct option const long_options[] = {
|
||||||
{"config", required_argument, NULL, 'c'},
|
{"config", required_argument, NULL, 'c'},
|
||||||
|
@ -83,7 +80,7 @@ static void usage(bool status) {
|
||||||
" stop Stop tincd.\n"
|
" stop Stop tincd.\n"
|
||||||
" restart Restart tincd.\n"
|
" restart Restart tincd.\n"
|
||||||
" reload Reload configuration of running 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"
|
" dump Dump a list of one of the following things:\n"
|
||||||
" nodes - all known nodes in the VPN\n"
|
" nodes - all known nodes in the VPN\n"
|
||||||
" edges - all known connections 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;
|
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 */
|
/* This function prettyprints the key generation process */
|
||||||
|
|
||||||
static void indicator(int a, int b, void *p) {
|
static void indicator(int a, int b, void *p) {
|
||||||
|
@ -307,6 +357,16 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
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) {
|
if(strlen(controlsocketname) >= sizeof addr.sun_path) {
|
||||||
fprintf(stderr, _("Control socket filename too long!\n"));
|
fprintf(stderr, _("Control socket filename too long!\n"));
|
||||||
return 1;
|
return 1;
|
||||||
|
|
125
src/tincd.c
125
src/tincd.c
|
@ -61,9 +61,6 @@ bool show_help = false;
|
||||||
/* If nonzero, print the version on standard output and exit. */
|
/* If nonzero, print the version on standard output and exit. */
|
||||||
bool show_version = false;
|
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. */
|
/* If nonzero, use null ciphers and skip all key exchanges. */
|
||||||
bool bypass_security = false;
|
bool bypass_security = false;
|
||||||
|
|
||||||
|
@ -86,7 +83,6 @@ static struct option const long_options[] = {
|
||||||
{"help", no_argument, NULL, 1},
|
{"help", no_argument, NULL, 1},
|
||||||
{"version", no_argument, NULL, 2},
|
{"version", no_argument, NULL, 2},
|
||||||
{"no-detach", no_argument, NULL, 'D'},
|
{"no-detach", no_argument, NULL, 'D'},
|
||||||
{"generate-keys", optional_argument, NULL, 'K'},
|
|
||||||
{"debug", optional_argument, NULL, 'd'},
|
{"debug", optional_argument, NULL, 'd'},
|
||||||
{"bypass-security", no_argument, NULL, 3},
|
{"bypass-security", no_argument, NULL, 3},
|
||||||
{"mlock", no_argument, NULL, 'L'},
|
{"mlock", no_argument, NULL, 'L'},
|
||||||
|
@ -110,7 +106,6 @@ static void usage(bool status)
|
||||||
" -D, --no-detach Don't fork and detach.\n"
|
" -D, --no-detach Don't fork and detach.\n"
|
||||||
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
||||||
" -n, --net=NETNAME Connect to net NETNAME.\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"
|
" -L, --mlock Lock tinc into main memory.\n"
|
||||||
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
||||||
" --controlsocket=FILENAME Open control socket at FILENAME.\n"
|
" --controlsocket=FILENAME Open control socket at FILENAME.\n"
|
||||||
|
@ -125,7 +120,7 @@ static bool parse_options(int argc, char **argv)
|
||||||
int r;
|
int r;
|
||||||
int option_index = 0;
|
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) {
|
switch (r) {
|
||||||
case 0: /* long option */
|
case 0: /* long option */
|
||||||
break;
|
break;
|
||||||
|
@ -153,22 +148,6 @@ static bool parse_options(int argc, char **argv)
|
||||||
netname = xstrdup(optarg);
|
netname = xstrdup(optarg);
|
||||||
break;
|
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 */
|
case 1: /* show help */
|
||||||
show_help = true;
|
show_help = true;
|
||||||
break;
|
break;
|
||||||
|
@ -203,103 +182,6 @@ static bool parse_options(int argc, char **argv)
|
||||||
return true;
|
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
|
Set all files and paths according to netname
|
||||||
*/
|
*/
|
||||||
|
@ -419,11 +301,6 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
if(generate_keys) {
|
|
||||||
read_server_config();
|
|
||||||
return !keygen(generate_keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!read_server_config())
|
if(!read_server_config())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue