Allow multiple HashedControlPassword config lines, to support
multiple controller passwords. svn:r12732
This commit is contained in:
parent
9b162ef430
commit
6dfd47467e
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue