aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2007-12-09 04:59:27 +0000
committerRoger Dingledine <arma@torproject.org>2007-12-09 04:59:27 +0000
commit6dfd47467eb7628c1d87e0b9235880564b31d85c (patch)
tree658f3df9f080a3fd7048f82b8f74c3302b152d8e /src/or
parent9b162ef4302881de7c8da7712fedbdd6da9c95df (diff)
downloadtor-6dfd47467eb7628c1d87e0b9235880564b31d85c.tar
tor-6dfd47467eb7628c1d87e0b9235880564b31d85c.tar.gz
Allow multiple HashedControlPassword config lines, to support
multiple controller passwords. svn:r12732
Diffstat (limited to 'src/or')
-rw-r--r--src/or/config.c9
-rw-r--r--src/or/control.c72
-rw-r--r--src/or/or.h7
3 files changed, 58 insertions, 30 deletions
diff --git a/src/or/config.c b/src/or/config.c
index d37bb64f7..f6f7b78b6 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -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) {
diff --git a/src/or/control.c b/src/or/control.c
index 5bb024ba7..468b622b5 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -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");
diff --git a/src/or/or.h b/src/or/or.h
index 8aa17a7cf..d8c44e002 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -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);