mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 15:10:48 +01:00
Fix various issues pointed out by Nick and Andrea.
- Document the key=value format. - Constify equal_sign_pos. - Pass some strings that are about to be logged to escape(). - Update documentation and fix some bugs in tor_escape_str_for_socks_arg(). - Use string_is_key_value() in parse_bridge_line(). - Parenthesize a forgotten #define - Add some more comments. - Add some more unit test cases.
This commit is contained in:
parent
d54efda869
commit
b5dceab175
4 changed files with 39 additions and 20 deletions
|
@ -865,30 +865,30 @@ tor_digest_is_zero(const char *digest)
|
||||||
return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
|
return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true if <b>string</b> is a valid '<key>=<value>' string.
|
/** Return true if <b>string</b> is a valid '<key>=[<value>]' string.
|
||||||
* <value> is optional, to indicate the empty string. */
|
* <value> is optional, to indicate the empty string. */
|
||||||
int
|
int
|
||||||
string_is_key_value(const char *string)
|
string_is_key_value(const char *string)
|
||||||
{
|
{
|
||||||
/* position of equal sign in string */
|
/* position of equal sign in string */
|
||||||
char *equal_sign_pos = NULL;
|
const char *equal_sign_pos = NULL;
|
||||||
|
|
||||||
tor_assert(string);
|
tor_assert(string);
|
||||||
|
|
||||||
if (strlen(string) < 2) { /* "x=a" is shortest args string */
|
if (strlen(string) < 2) { /* "x=" is shortest args string */
|
||||||
log_warn(LD_GENERAL, "'%s' is too short to be a k=v value.", string);
|
log_warn(LD_GENERAL, "'%s' is too short to be a k=v value.", escaped(string));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
equal_sign_pos = strchr(string, '=');
|
equal_sign_pos = strchr(string, '=');
|
||||||
if (!equal_sign_pos) {
|
if (!equal_sign_pos) {
|
||||||
log_warn(LD_GENERAL, "'%s' is not a k=v value.", string);
|
log_warn(LD_GENERAL, "'%s' is not a k=v value.", escaped(string));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate that the '=' is not in the beginning of the string. */
|
/* validate that the '=' is not in the beginning of the string. */
|
||||||
if (equal_sign_pos == string) {
|
if (equal_sign_pos == string) {
|
||||||
log_warn(LD_GENERAL, "'%s' is not a valid k=v value.", string);
|
log_warn(LD_GENERAL, "'%s' is not a valid k=v value.", escaped(string));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,9 +1279,10 @@ wrap_string(smartlist_t *out, const char *string, size_t width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Escape every character of <b>string</b> that belongs to the set of
|
/** Escape every ";" or "\" character of <b>string</b>. Use
|
||||||
* characters <b>set</b>. Use <b>escape_char</b> as the character to
|
* <b>escape_char</b> as the character to use for escaping.
|
||||||
* use for escaping. */
|
* The returned string is allocated on the heap and it's the
|
||||||
|
* responsibility of the caller to free it. */
|
||||||
char *
|
char *
|
||||||
tor_escape_str_for_socks_arg(const char *string)
|
tor_escape_str_for_socks_arg(const char *string)
|
||||||
{
|
{
|
||||||
|
@ -1294,8 +1295,8 @@ tor_escape_str_for_socks_arg(const char *string)
|
||||||
|
|
||||||
length = strlen(string);
|
length = strlen(string);
|
||||||
|
|
||||||
if (!length)
|
if (!length) /* If we were given the empty string, return the same. */
|
||||||
return NULL;
|
return tor_strdup("");
|
||||||
/* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
|
/* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
|
||||||
(length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
|
(length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
|
||||||
if (length > (SIZE_MAX - 1)/2) /* check for overflow */
|
if (length > (SIZE_MAX - 1)/2) /* check for overflow */
|
||||||
|
@ -1304,7 +1305,7 @@ tor_escape_str_for_socks_arg(const char *string)
|
||||||
/* this should be enough even if all characters must be escaped */
|
/* this should be enough even if all characters must be escaped */
|
||||||
new_length = (length * 2) + 1;
|
new_length = (length * 2) + 1;
|
||||||
|
|
||||||
new_string = new_cp = tor_malloc_zero(new_length);
|
new_string = new_cp = tor_malloc(new_length);
|
||||||
|
|
||||||
while (*string) {
|
while (*string) {
|
||||||
if (strchr(chars_to_escape, *string))
|
if (strchr(chars_to_escape, *string))
|
||||||
|
@ -1313,6 +1314,8 @@ tor_escape_str_for_socks_arg(const char *string)
|
||||||
*new_cp++ = *string++;
|
*new_cp++ = *string++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*new_cp = '\0'; /* NUL-terminate the new string */
|
||||||
|
|
||||||
return new_string;
|
return new_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2875,14 +2875,14 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
len = strlen(options->Socks5ProxyUsername);
|
len = strlen(options->Socks5ProxyUsername);
|
||||||
if (len < 1 || len > 255)
|
if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE)
|
||||||
REJECT("Socks5ProxyUsername must be between 1 and 255 characters.");
|
REJECT("Socks5ProxyUsername must be between 1 and 255 characters.");
|
||||||
|
|
||||||
if (!options->Socks5ProxyPassword)
|
if (!options->Socks5ProxyPassword)
|
||||||
REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
|
REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
|
||||||
|
|
||||||
len = strlen(options->Socks5ProxyPassword);
|
len = strlen(options->Socks5ProxyPassword);
|
||||||
if (len < 1 || len > 255)
|
if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE)
|
||||||
REJECT("Socks5ProxyPassword must be between 1 and 255 characters.");
|
REJECT("Socks5ProxyPassword must be between 1 and 255 characters.");
|
||||||
} else if (options->Socks5ProxyPassword)
|
} else if (options->Socks5ProxyPassword)
|
||||||
REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
|
REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
|
||||||
|
@ -4120,11 +4120,12 @@ parse_bridge_line(const char *line, int validate_only)
|
||||||
field = smartlist_get(items, 0);
|
field = smartlist_get(items, 0);
|
||||||
smartlist_del_keeporder(items, 0);
|
smartlist_del_keeporder(items, 0);
|
||||||
|
|
||||||
/* If '=', it's a k=v value pair. */
|
/* If it's a key=value pair, then it's a SOCKS argument for the
|
||||||
if (strchr(field, '=')) {
|
transport proxy... */
|
||||||
|
if (string_is_key_value(field)) {
|
||||||
socks_args = smartlist_new();
|
socks_args = smartlist_new();
|
||||||
smartlist_add(socks_args, field);
|
smartlist_add(socks_args, field);
|
||||||
} else { /* If no '=', it's the fingerprint. */
|
} else { /* ...otherwise, it's the bridge fingerprint. */
|
||||||
fingerprint = field;
|
fingerprint = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1585,7 +1585,7 @@ get_proxy_type(void)
|
||||||
/* One byte for the version, one for the command, two for the
|
/* One byte for the version, one for the command, two for the
|
||||||
port, and four for the addr... and, one more for the
|
port, and four for the addr... and, one more for the
|
||||||
username NUL: */
|
username NUL: */
|
||||||
#define SOCKS4_STANDARD_BUFFER_SIZE 1 + 1 + 2 + 4 + 1
|
#define SOCKS4_STANDARD_BUFFER_SIZE (1 + 1 + 2 + 4 + 1)
|
||||||
|
|
||||||
/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn
|
/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn
|
||||||
* for conn->addr:conn->port, authenticating with the auth details given
|
* for conn->addr:conn->port, authenticating with the auth details given
|
||||||
|
@ -1688,6 +1688,9 @@ connection_proxy_connect(connection_t *conn, int type)
|
||||||
memcpy(buf + 2, &portn, 2); /* port */
|
memcpy(buf + 2, &portn, 2); /* port */
|
||||||
memcpy(buf + 4, &ip4addr, 4); /* addr */
|
memcpy(buf + 4, &ip4addr, 4); /* addr */
|
||||||
|
|
||||||
|
/* Next packet field is the userid. If we have pluggable
|
||||||
|
transport SOCKS arguments, we have to embed them
|
||||||
|
there. Otherwise, we use an empty userid. */
|
||||||
if (socks_args_string) { /* place the SOCKS args string: */
|
if (socks_args_string) { /* place the SOCKS args string: */
|
||||||
tor_assert(strlen(socks_args_string) > 0);
|
tor_assert(strlen(socks_args_string) > 0);
|
||||||
tor_assert(buf_size >=
|
tor_assert(buf_size >=
|
||||||
|
@ -1951,6 +1954,8 @@ connection_read_proxy_handshake(connection_t *conn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Username and password lengths should have been checked
|
||||||
|
above and during torrc parsing. */
|
||||||
tor_assert(usize <= MAX_SOCKS5_AUTH_FIELD_SIZE &&
|
tor_assert(usize <= MAX_SOCKS5_AUTH_FIELD_SIZE &&
|
||||||
psize <= MAX_SOCKS5_AUTH_FIELD_SIZE);
|
psize <= MAX_SOCKS5_AUTH_FIELD_SIZE);
|
||||||
reqsize = 3 + usize + psize;
|
reqsize = 3 + usize + psize;
|
||||||
|
|
|
@ -813,9 +813,11 @@ test_util_escape_string_socks(void)
|
||||||
test_streq(escaped_string, "First rule: Do not use \\;");
|
test_streq(escaped_string, "First rule: Do not use \\;");
|
||||||
tor_free(escaped_string);
|
tor_free(escaped_string);
|
||||||
|
|
||||||
/** Ilegal: Empty string. */
|
/** Empty string. */
|
||||||
escaped_string = tor_escape_str_for_socks_arg("");
|
escaped_string = tor_escape_str_for_socks_arg("");
|
||||||
test_assert(!escaped_string);
|
test_assert(escaped_string);
|
||||||
|
test_streq(escaped_string, "");
|
||||||
|
tor_free(escaped_string);
|
||||||
|
|
||||||
/** Escape all characters. */
|
/** Escape all characters. */
|
||||||
escaped_string = tor_escape_str_for_socks_arg(";\\;\\");
|
escaped_string = tor_escape_str_for_socks_arg(";\\;\\");
|
||||||
|
@ -823,6 +825,11 @@ test_util_escape_string_socks(void)
|
||||||
test_streq(escaped_string, "\\;\\\\\\;\\\\");
|
test_streq(escaped_string, "\\;\\\\\\;\\\\");
|
||||||
tor_free(escaped_string);
|
tor_free(escaped_string);
|
||||||
|
|
||||||
|
escaped_string = tor_escape_str_for_socks_arg(";");
|
||||||
|
test_assert(escaped_string);
|
||||||
|
test_streq(escaped_string, "\\;");
|
||||||
|
tor_free(escaped_string);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
tor_free(escaped_string);
|
tor_free(escaped_string);
|
||||||
}
|
}
|
||||||
|
@ -834,7 +841,10 @@ test_util_string_is_key_value(void *ptr)
|
||||||
test_assert(string_is_key_value("key=value"));
|
test_assert(string_is_key_value("key=value"));
|
||||||
test_assert(string_is_key_value("k=v"));
|
test_assert(string_is_key_value("k=v"));
|
||||||
test_assert(string_is_key_value("key="));
|
test_assert(string_is_key_value("key="));
|
||||||
|
test_assert(string_is_key_value("x="));
|
||||||
|
test_assert(string_is_key_value("xx="));
|
||||||
test_assert(!string_is_key_value("=value"));
|
test_assert(!string_is_key_value("=value"));
|
||||||
|
test_assert(!string_is_key_value("=x"));
|
||||||
test_assert(!string_is_key_value("="));
|
test_assert(!string_is_key_value("="));
|
||||||
|
|
||||||
/* ??? */
|
/* ??? */
|
||||||
|
|
Loading…
Add table
Reference in a new issue