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; }