Commit 6dfd4746 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

Allow multiple HashedControlPassword config lines, to support

multiple controller passwords.


svn:r12732
parent 9b162ef4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ Changes in version 0.2.0.13-alpha - 2007-12-??
      ask about source, timestamp of arrival, purpose, etc. We need
      something like this to help Vidalia not do GeoIP lookups on bridge
      addresses.
    - Allow multiple HashedControlPassword config lines, to support
      multiple controller passwords.


Changes in version 0.2.0.12-alpha - 2007-11-16
+2 −1
Original line number Diff line number Diff line
@@ -159,7 +159,8 @@ socket. (Unix and Unix-like systems only.)
Don't allow any connections on the control port except when the other process
knows the password whose one-way hash is \fIhashed_password\fP.  You can
compute the hash of a password by running "tor --hash-password
\fIpassword\fP".
\fIpassword\fP". You can provide several acceptable passwords by using
more than HashedControlPassword line.
.LP
.TP
\fBCookieAuthentication \fR\fB0\fR|\fB1\fP
+7 −2
Original line number Diff line number Diff line
@@ -187,7 +187,7 @@ static config_var_t _option_vars[] = {
  V(FetchUselessDescriptors,     BOOL,     "0"),
  V(Group,                       STRING,   NULL),
  V(HardwareAccel,               BOOL,     "0"),
  V(HashedControlPassword,       STRING,   NULL),
  V(HashedControlPassword,       LINELIST, NULL),
  V(HidServDirectoryV2,          BOOL,     "0"),
  VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
@@ -2939,8 +2939,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
  }

  if (options->HashedControlPassword) {
    if (decode_hashed_password(NULL, options->HashedControlPassword)<0)
    smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword);
    if (!sl) {
      REJECT("Bad HashedControlPassword: wrong length or bad encoding");
    } else {
      SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
      smartlist_free(sl);
    }
  }

  if (options->ControlListenAddress) {
+47 −25
Original line number Diff line number Diff line
@@ -912,29 +912,42 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
  return 0;
}

/** Decode the hashed, base64'd password stored in <b>hashed</b>.  If
 * <b>buf</b> is provided, store the hashed password in the first
 * S2K_SPECIFIER_LEN+DIGEST_LEN bytes of <b>buf</b>.  Return 0 on
 * success, -1 on failure.
/** Decode the hashed, base64'd passwords stored in <b>passwords</b>.
 * Return a smartlist of acceptable passwords (unterminated strings of
 * length S2K_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on failure.
 */
int
decode_hashed_password(char *buf, const char *hashed)
smartlist_t *
decode_hashed_passwords(config_line_t *passwords)
{
  char decoded[64];
  config_line_t *cl;
  smartlist_t *sl = smartlist_create();

  tor_assert(passwords);

  for (cl = passwords; cl; cl = cl->next) {
    const char *hashed = cl->value;

    if (!strcmpstart(hashed, "16:")) {
      if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0
          || strlen(hashed+3) != (S2K_SPECIFIER_LEN+DIGEST_LEN)*2) {
      return -1;
        goto err;
      }
    } else {
        if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
            != S2K_SPECIFIER_LEN+DIGEST_LEN) {
        return -1;
          goto err;
        }
    }
  if (buf)
    memcpy(buf, decoded, S2K_SPECIFIER_LEN+DIGEST_LEN);
  return 0;
    smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN));
  }

  return sl;

 err:
  SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
  smartlist_free(sl);
  return NULL;
}

/** Called when we get an AUTHENTICATE message.  Check whether the
@@ -953,6 +966,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
  const char *cp;
  int i;
  int bad_cookie=0, bad_password=0;
  smartlist_t *sl = NULL;

  if (TOR_ISXDIGIT(body[0])) {
    cp = body;
@@ -1013,10 +1027,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
  }

  if (options->HashedControlPassword) {
    char expected[S2K_SPECIFIER_LEN+DIGEST_LEN];
    char received[DIGEST_LEN];
    int also_cookie = options->CookieAuthentication;
    if (decode_hashed_password(expected, options->HashedControlPassword)<0) {
    sl = decode_hashed_passwords(options->HashedControlPassword);
    if (!sl) {
      if (!also_cookie) {
        log_warn(LD_CONTROL,
                 "Couldn't decode HashedControlPassword: invalid base16");
@@ -1024,9 +1038,14 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
      }
      bad_password = 1;
    } else {
      SMARTLIST_FOREACH(sl, char *, expected,
      {
        secret_to_key(received,DIGEST_LEN,password,password_len,expected);
        if (!memcmp(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN))
          goto ok;
      });
      SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
      smartlist_free(sl);

      if (used_quoted_string)
        errstr = "Password did not match HashedControlPassword value from "
@@ -1060,6 +1079,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
  send_control_done(conn);
  conn->_base.state = CONTROL_CONN_STATE_OPEN;
  tor_free(password);
  if (sl) { /* clean up */
    SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
    smartlist_free(sl);
  }
  return 0;
}

@@ -2435,8 +2458,7 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
    char *esc_cfile = esc_for_log(cfile);
    char *methods;
    {
      int passwd = (options->HashedControlPassword != NULL) &&
        strlen(options->HashedControlPassword);
      int passwd = (options->HashedControlPassword != NULL);
      smartlist_t *mlist = smartlist_create();
      if (cookies)
        smartlist_add(mlist, (char*)"COOKIE");
+4 −3
Original line number Diff line number Diff line
@@ -2211,8 +2211,9 @@ typedef struct {
                           * interval before hibernation?  0 for "never
                           * hibernate." */

  char *HashedControlPassword; /**< Base64-encoded hash of a password for
                                * the control system. */
  /** Base64-encoded hash of accepted passwords for the control system. */
  config_line_t *HashedControlPassword;

  int CookieAuthentication; /**< Boolean: do we enable cookie-based auth for
                             * the control system? */
  char *CookieAuthFile; /**< Location of a cookie authentication file. */
@@ -2920,7 +2921,7 @@ int control_event_guard(const char *nickname, const char *digest,
                        const char *status);

int init_cookie_authentication(int enabled);
int decode_hashed_password(char *buf, const char *hashed);
smartlist_t *decode_hashed_passwords(config_line_t *passwords);
void disable_control_logging(void);
void enable_control_logging(void);