From 23730375f27c32e0fe1a59c7a761dd85296a7a4a Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 3 Feb 2009 14:54:45 +0100 Subject: [PATCH] Disable old RSA keys when generating new ones. When generating an RSA keypair, the new public and private keys are appended to files. However, when OpenSSL reads keys it only reads the first in a file, not the last. Instead of printing an easily ignored warning, tinc now disables old keys when appending new ones. --- src/conf.c | 35 +++++++++++++++++++++++++++++++++-- src/conf.h | 3 ++- src/tincd.c | 34 ++++++++++++++++++---------------- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/conf.c b/src/conf.c index a61a3591..803c96c2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -429,7 +429,7 @@ bool read_server_config() return x == 0; } -FILE *ask_and_open(const char *filename, const char *what, const char *mode) +FILE *ask_and_open(const char *filename, const char *what) { FILE *r; char *directory; @@ -479,7 +479,7 @@ FILE *ask_and_open(const char *filename, const char *what, const char *mode) /* Open it first to keep the inode busy */ - r = fopen(fn, mode); + r = fopen(fn, "r+") ?: fopen(fn, "w+"); if(!r) { fprintf(stderr, _("Error opening file `%s': %s\n"), @@ -492,3 +492,34 @@ FILE *ask_and_open(const char *filename, const char *what, const char *mode) return r; } + +bool disable_old_keys(FILE *f) { + char buf[100]; + long pos; + bool disabled = false; + + rewind(f); + pos = ftell(f); + + while(fgets(buf, sizeof buf, f)) { + if(!strncmp(buf, "-----BEGIN RSA", 14)) { + buf[11] = 'O'; + buf[12] = 'L'; + buf[13] = 'D'; + fseek(f, pos, SEEK_SET); + fputs(buf, f); + disabled = true; + } + else if(!strncmp(buf, "-----END RSA", 12)) { + buf[ 9] = 'O'; + buf[10] = 'L'; + buf[11] = 'D'; + fseek(f, pos, SEEK_SET); + fputs(buf, f); + disabled = true; + } + pos = ftell(f); + } + + return disabled; +} diff --git a/src/conf.h b/src/conf.h index 1494e961..eb2e0dd6 100644 --- a/src/conf.h +++ b/src/conf.h @@ -58,7 +58,8 @@ extern bool get_config_subnet(const config_t *, struct subnet_t **); extern int read_config_file(avl_tree_t *, const char *); extern bool read_server_config(void); -extern FILE *ask_and_open(const char *, const char *, const char *); +extern FILE *ask_and_open(const char *, const char *); extern bool is_safe_path(const char *); +extern bool disable_old_keys(FILE *); #endif /* __TINC_CONF_H__ */ diff --git a/src/tincd.c b/src/tincd.c index 5fedd692..c2660fa3 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -294,15 +294,10 @@ static bool keygen(int bits) get_config_string(lookup_config(config_tree, "Name"), &name); - if(name) { - if(!check_id(name)) { - fprintf(stderr, _("Invalid name for myself!\n")); - return false; - } - asprintf(&filename, "%s/hosts/%s", confbase, name); - free(name); - } else - asprintf(&filename, "%s/rsa_key.pub", confbase); + 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); @@ -314,34 +309,41 @@ static bool keygen(int bits) fprintf(stderr, _("Done.\n")); asprintf(&filename, "%s/rsa_key.priv", confbase); - f = ask_and_open(filename, _("private RSA key"), "a"); + 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 - 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); - f = ask_and_open(filename, _("public RSA key"), "a"); + 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(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + 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; } -- 2.20.1