diff --git a/src/conf.c b/src/conf.c index 1560541a..b7c0179e 100644 --- a/src/conf.c +++ b/src/conf.c @@ -400,6 +400,70 @@ bool read_connection_config(connection_t *c) { return x; } +static void disable_old_keys(const char *filename) { + char tmpfile[PATH_MAX] = ""; + char buf[1024]; + bool disabled = false; + FILE *r, *w; + + r = fopen(filename, "r"); + if(!r) + return; + + snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename); + + w = fopen(tmpfile, "w"); + + while(fgets(buf, sizeof buf, r)) { + if(!strncmp(buf, "-----BEGIN RSA", 14)) { + buf[11] = 'O'; + buf[12] = 'L'; + buf[13] = 'D'; + disabled = true; + } + else if(!strncmp(buf, "-----END RSA", 12)) { + buf[ 9] = 'O'; + buf[10] = 'L'; + buf[11] = 'D'; + disabled = true; + } + if(w && fputs(buf, w) < 0) { + disabled = false; + break; + } + } + + if(w) + fclose(w); + fclose(r); + + if(!w && disabled) { + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + return; + } + + if(disabled) { +#ifdef HAVE_MINGW + // We cannot atomically replace files on Windows. + char bakfile[PATH_MAX] = ""; + snprintf(bakfile, sizeof bakfile, "%s.bak", filename); + if(rename(filename, bakfile) || rename(tmpfile, filename)) { + rename(bakfile, filename); +#else + if(rename(tmpfile, filename)) { +#endif + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + } else { +#ifdef HAVE_MINGW + unlink(bakfile); +#endif + fprintf(stderr, "Warning: old key(s) found and disabled.\n"); + } + } + + unlink(tmpfile); +} + FILE *ask_and_open(const char *filename, const char *what) { FILE *r; char *directory; @@ -447,9 +511,11 @@ FILE *ask_and_open(const char *filename, const char *what) { umask(0077); /* Disallow everything for group and other */ + disable_old_keys(fn); + /* Open it first to keep the inode busy */ - r = fopen(fn, "r+") ?: fopen(fn, "w+"); + r = fopen(fn, "a"); if(!r) { fprintf(stderr, "Error opening file `%s': %s\n", @@ -460,42 +526,4 @@ FILE *ask_and_open(const char *filename, const char *what) { return r; } -bool disable_old_keys(FILE *f) { - char buf[100]; - long pos; - bool disabled = false; - rewind(f); - pos = ftell(f); - - if(pos < 0) - return false; - - while(fgets(buf, sizeof buf, f)) { - if(!strncmp(buf, "-----BEGIN RSA", 14)) { - buf[11] = 'O'; - buf[12] = 'L'; - buf[13] = 'D'; - if(fseek(f, pos, SEEK_SET)) - break; - if(fputs(buf, f) <= 0) - break; - disabled = true; - } - else if(!strncmp(buf, "-----END RSA", 12)) { - buf[ 9] = 'O'; - buf[10] = 'L'; - buf[11] = 'D'; - if(fseek(f, pos, SEEK_SET)) - break; - if(fputs(buf, f) <= 0) - break; - disabled = true; - } - pos = ftell(f); - if(pos < 0) - break; - } - - return disabled; -} diff --git a/src/conf.h b/src/conf.h index 5b0796e5..46a42b1d 100644 --- a/src/conf.h +++ b/src/conf.h @@ -63,6 +63,5 @@ extern bool read_server_config(void); extern bool read_connection_config(struct connection_t *); 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 a1be971a..d0b00b0d 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -362,9 +362,6 @@ static bool keygen(int bits) { 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); @@ -385,9 +382,6 @@ static bool keygen(int bits) { if(!f) return false; - if(disable_old_keys(f)) - fprintf(stderr, "Warning: old key(s) found and disabled.\n"); - fputc('\n', f); PEM_write_RSAPublicKey(f, rsa_key); fclose(f);