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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 "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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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.  */
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue