Disable old RSA keys when generating new ones.
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 3 Feb 2009 13:54:45 +0000 (14:54 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 3 Feb 2009 13:54:45 +0000 (14:54 +0100)
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
src/conf.h
src/tincd.c

index a61a359..803c96c 100644 (file)
@@ -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;
+}
index 1494e96..eb2e0dd 100644 (file)
@@ -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__ */
index 5fedd69..c2660fa 100644 (file)
@@ -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;
 }