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
......@@ -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
......
......@@ -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
......
......@@ -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) {
......
......@@ -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];
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;
}
} else {
if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
!= S2K_SPECIFIER_LEN+DIGEST_LEN) {
return -1;
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) {
goto err;
}
} else {
if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
!= S2K_SPECIFIER_LEN+DIGEST_LEN) {
goto err;
}
}
smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN));
}
if (buf)
memcpy(buf, decoded, S2K_SPECIFIER_LEN+DIGEST_LEN);
return 0;
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 {
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 *, 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");
......
......@@ -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);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment