Browse Source

Merge branch 'feature16769_squashed'

Nick Mathewson 8 years ago
parent
commit
df0b4f0342
5 changed files with 71 additions and 9 deletions
  1. 4 0
      changes/feature16769
  2. 29 0
      src/or/config.c
  3. 2 1
      src/or/or.h
  4. 35 8
      src/or/routerkeys.c
  5. 1 0
      src/or/routerkeys.h

+ 4 - 0
changes/feature16769

@@ -0,0 +1,4 @@
+  o Minor features (ed25519):
+    - Add a --newpass option to allow changing or removing the
+      passphrase of an encrypted key with tor --keygen. Implements
+      part of ticket 16769.

+ 29 - 0
src/or/config.c

@@ -763,6 +763,7 @@ or_options_free(or_options_t *options)
   }
   tor_free(options->BridgePassword_AuthDigest_);
   tor_free(options->command_arg);
+  tor_free(options->master_key_fname);
   config_free(&options_format, options);
 }
 
@@ -1919,6 +1920,12 @@ static const struct {
   { "--dump-config",          ARGUMENT_OPTIONAL },
   { "--list-fingerprint",     TAKES_NO_ARGUMENT },
   { "--keygen",               TAKES_NO_ARGUMENT },
+  { "--newpass",              TAKES_NO_ARGUMENT },
+#if 0
+/* XXXX028: This is not working yet in 0.2.7, so disabling with the
+ * minimal code modification. */
+  { "--master-key",           ARGUMENT_NECESSARY },
+#endif
   { "--no-passphrase",        TAKES_NO_ARGUMENT },
   { "--passphrase-fd",        ARGUMENT_NECESSARY },
   { "--verify-config",        TAKES_NO_ARGUMENT },
@@ -4528,6 +4535,15 @@ options_init_from_torrc(int argc, char **argv)
     }
   }
 
+  if (config_line_find(cmdline_only_options, "--newpass")) {
+    if (command == CMD_KEYGEN) {
+      get_options_mutable()->change_key_passphrase = 1;
+    } else {
+      log_err(LD_CONFIG, "--newpass specified without --keygen!");
+      exit(1);
+    }
+  }
+
   {
     const config_line_t *fd_line = config_line_find(cmdline_only_options,
                                                     "--passphrase-fd");
@@ -4553,6 +4569,19 @@ options_init_from_torrc(int argc, char **argv)
     }
   }
 
+  {
+    const config_line_t *key_line = config_line_find(cmdline_only_options,
+                                                     "--master-key");
+    if (key_line) {
+      if (command != CMD_KEYGEN) {
+        log_err(LD_CONFIG, "--master-key without --keygen!");
+        exit(1);
+      } else {
+        get_options_mutable()->master_key_fname = tor_strdup(key_line->value);
+      }
+    }
+  }
+
  err:
 
   tor_free(cf);

+ 2 - 1
src/or/or.h

@@ -4313,7 +4313,8 @@ typedef struct {
   } keygen_force_passphrase;
   int use_keygen_passphrase_fd;
   int keygen_passphrase_fd;
-
+  int change_key_passphrase;
+  char *master_key_fname;
 } or_options_t;
 
 /** Persistent state for an onion router, as saved to disk. */

+ 35 - 8
src/or/routerkeys.c

@@ -200,8 +200,17 @@ write_secret_key(const ed25519_secret_key_t *key, int encrypted,
 {
   if (encrypted) {
     int r = write_encrypted_secret_key(key, encrypted_fname);
-    if (r != 0)
-      return r; /* Either succeeded or failed unrecoverably */
+    if (r == 1) {
+      /* Success! */
+
+      /* Try to unlink the unencrypted key, if any existed before */
+      if (strcmp(fname, encrypted_fname))
+        unlink(fname);
+      return r;
+    } else if (r != 0) {
+      /* Unrecoverable failure! */
+      return r;
+    }
 
     fprintf(stderr, "Not encrypting the secret key.\n");
   }
@@ -253,6 +262,9 @@ write_secret_key(const ed25519_secret_key_t *key, int encrypted,
  *
  * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures
  * refer to the --keygen option.
+ *
+ * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the
+ * secret key file, encrypted or not.
  */
 ed25519_keypair_t *
 ed_key_init_from_file(const char *fname, uint32_t flags,
@@ -275,6 +287,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
   const int split = !! (flags & INIT_ED_KEY_SPLIT);
   const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
   const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
+  const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);
 
   /* we don't support setting both of these flags at once. */
   tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
@@ -287,8 +300,13 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
   char *got_tag = NULL;
   ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
 
-  tor_asprintf(&secret_fname, "%s_secret_key", fname);
-  tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
+  if (explicit_fname) {
+    secret_fname = tor_strdup(fname);
+    encrypted_secret_fname = tor_strdup(fname);
+  } else {
+    tor_asprintf(&secret_fname, "%s_secret_key", fname);
+    tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
+  }
   tor_asprintf(&public_fname, "%s_public_key", fname);
   tor_asprintf(&cert_fname, "%s_cert", fname);
 
@@ -441,7 +459,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
     goto err;
   }
 
-  /* if it's absent, make a new keypair and save it. */
+  /* if it's absent, make a new keypair... */
   if (!have_secret && !found_public) {
     tor_free(keypair);
     keypair = ed_key_new(signing_key, flags, now, lifetime,
@@ -450,8 +468,12 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
       tor_log(severity, LD_OR, "Couldn't create keypair");
       goto err;
     }
-
     created_pk = created_sk = created_cert = 1;
+  }
+
+  /* Write it to disk if we're supposed to do with a new passphrase, or if
+   * we just created it. */
+  if (created_sk || (have_secret && get_options()->change_key_passphrase)) {
     if (write_secret_key(&keypair->seckey,
                          encrypt_key,
                          secret_fname, tag, encrypted_secret_fname) < 0
@@ -686,7 +708,7 @@ load_ed_keys(const or_options_t *options, time_t now)
   const int need_new_signing_key =
     NULL == use_signing ||
     EXPIRES_SOON(check_signing_cert, 0) ||
-    options->command == CMD_KEYGEN;
+    (options->command == CMD_KEYGEN && ! options->change_key_passphrase);
   const int want_new_signing_key =
     need_new_signing_key ||
     EXPIRES_SOON(check_signing_cert, options->TestingSigningKeySlop);
@@ -747,7 +769,12 @@ load_ed_keys(const or_options_t *options, time_t now)
       goto err;
     }
     tor_free(fname);
-    fname = options_get_datadir_fname2(options, "keys", "ed25519_master_id");
+    if (options->master_key_fname) {
+      fname = tor_strdup(options->master_key_fname);
+      flags |= INIT_ED_KEY_EXPLICIT_FNAME;
+    } else {
+      fname = options_get_datadir_fname2(options, "keys", "ed25519_master_id");
+    }
     id = ed_key_init_from_file(
              fname,
              flags,

+ 1 - 0
src/or/routerkeys.h

@@ -18,6 +18,7 @@
 #define INIT_ED_KEY_NO_REPAIR                   (1u<<9)
 #define INIT_ED_KEY_SUGGEST_KEYGEN              (1u<<10)
 #define INIT_ED_KEY_OFFLINE_SECRET              (1u<<11)
+#define INIT_ED_KEY_EXPLICIT_FNAME              (1u<<12)
 
 struct tor_cert_st;
 ed25519_keypair_t *ed_key_init_from_file(const char *fname, uint32_t flags,