[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r9968: Enforce checks for number of arguments to items in directory (in tor/trunk: . src/or)
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] r9968: Enforce checks for number of arguments to items in directory (in tor/trunk: . src/or)
- From: nickm@xxxxxxxx
- Date: Mon, 16 Apr 2007 12:28:08 -0400 (EDT)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Mon, 16 Apr 2007 12:28:38 -0400
- Reply-to: or-talk@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
Author: nickm
Date: 2007-04-16 12:28:06 -0400 (Mon, 16 Apr 2007)
New Revision: 9968
Modified:
tor/trunk/
tor/trunk/src/or/routerparse.c
Log:
r12401@catbus: nickm | 2007-04-16 12:28:01 -0400
Enforce checks for number of arguments to items in directory objects more uniformly.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r12401] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c 2007-04-16 15:38:53 UTC (rev 9967)
+++ tor/trunk/src/or/routerparse.c 2007-04-16 16:28:06 UTC (rev 9968)
@@ -80,20 +80,13 @@
size_t object_size; /**< Bytes in object_body */
char *object_body; /**< Contents of object, base64-decoded. */
crypto_pk_env_t *key; /**< For public keys only. */
- const char *error; /**< For _ERR tokens only. */
+ char *error; /**< For _ERR tokens only. */
} directory_token_t;
/* ********************************************************************** */
/** We use a table of rules to decide how to parse each token type. */
-/** Rules for how many arguments a keyword can take. */
-typedef enum {
- NO_ARGS, /**< No arguments, ever. */
- ARGS, /**< A list of arguments separated by spaces. */
- CONCAT_ARGS, /**< The rest of the line, treated as a single argument. */
-} arg_syntax;
-
/** Rules for whether the keyword needs an object. */
typedef enum {
NO_OBJ, /**< No object, ever. */
@@ -104,38 +97,46 @@
/** DOCDOC */
typedef struct token_rule_t {
- const char *t; directory_keyword v; arg_syntax s; obj_syntax os;
+ const char *t; directory_keyword v;
+ int min_args; int max_args; int concat_args;
+ obj_syntax os;
int min_cnt; int max_cnt;
} token_rule_t;
/** DOCDOC */
-#define END_OF_TABLE { NULL, _NIL, NO_ARGS, NO_OBJ, 0, INT_MAX }
+#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX }
#define T(s,t,a,o) { s, t, a, o, 0, INT_MAX }
#define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX }
#define T1(s,t,a,o) { s, t, a, o, 1, 1 }
#define T01(s,t,a,o) { s, t, a, o, 0, 1 }
+#define ARGS 0,INT_MAX,0
+#define NO_ARGS 0,0,0
+#define CONCAT_ARGS 1,1,1
+#define GE(n) n,INT_MAX,0
+#define EQ(n) n,n,0
+
/** DOCDOC */
static token_rule_t routerdesc_token_table[] = {
T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
T0N("reject", K_REJECT, ARGS, NO_OBJ ),
- T1( "router", K_ROUTER, ARGS, NO_OBJ ),
+ T1( "router", K_ROUTER, GE(5), NO_OBJ ),
T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY ),
T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY ),
T1( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
- T01("uptime", K_UPTIME, ARGS, NO_OBJ ),
+ T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
T01("family", K_FAMILY, ARGS, NO_OBJ ),
T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
- T01("hibernating", K_HIBERNATING, ARGS, NO_OBJ ),
+ T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
- T01("extra-info-digest", K_EXTRA_INFO_DIGEST, ARGS, NO_OBJ ),
+ T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
- T1("bandwidth", K_BANDWIDTH, ARGS, NO_OBJ ),
+ T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
@@ -147,13 +148,13 @@
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
- T1( "extra-info", K_EXTRA_INFO, ARGS, NO_OBJ ),
+ T1( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
END_OF_TABLE
};
static token_rule_t rtrstatus_token_table[] = {
- T1( "r", K_R, ARGS, NO_OBJ ),
+ T1( "r", K_R, GE(8), NO_OBJ ),
T1( "s", K_S, ARGS, NO_OBJ ),
T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
@@ -164,20 +165,21 @@
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
+ /* XXXX should dir-signing-key really have ARGS? */
T1( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, NEED_KEY ),
T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
T1( "network-status-version", K_NETWORK_STATUS_VERSION,
- ARGS, NO_OBJ ),
- T1( "dir-source", K_DIR_SOURCE, ARGS, NO_OBJ ),
+ GE(1), NO_OBJ ),
+ T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
- T01("client-versions", K_CLIENT_VERSIONS, ARGS, NO_OBJ ),
- T01("server-versions", K_SERVER_VERSIONS, ARGS, NO_OBJ ),
+ T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
+ T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
};
static token_rule_t dir_footer_token_table[] = {
- T1( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
+ T1( "directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
END_OF_TABLE
};
@@ -185,12 +187,12 @@
/* don't enforce counts; this is obsolete. */
T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
- T( "recommended-software",K_RECOMMENDED_SOFTWARE,ARGS, NO_OBJ ),
+ T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
- T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
+ T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
@@ -642,10 +644,7 @@
char signed_digest[PK_BYTES];
crypto_pk_env_t *_pkey = NULL;
- if (tok->n_args != 1) {
- log_warn(LD_DIR, "Too many or too few arguments to directory-signature");
- return -1;
- }
+ tor_assert(tok->n_args == 1);
if (declared_key) {
if (!check_authority || dir_signing_key_is_trusted(declared_key))
@@ -827,6 +826,7 @@
log_warn(LD_DIR,"Entry does not start with \"router\"");
goto err;
}
+ tor_assert(tok->n_args >= 5);
router = tor_malloc_zero(sizeof(routerinfo_t));
router->routerlist_index = -1;
@@ -835,70 +835,49 @@
router->cache_info.signed_descriptor_len = end-s;
memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
- if (tok->n_args >= 5) {
- router->nickname = tor_strdup(tok->args[0]);
- if (!is_legal_nickname(router->nickname)) {
- log_warn(LD_DIR,"Router nickname is invalid");
- goto err;
- }
- router->address = tor_strdup(tok->args[1]);
- if (!tor_inet_aton(router->address, &in)) {
- log_warn(LD_DIR,"Router address is not an IP.");
- goto err;
- }
- router->addr = ntohl(in.s_addr);
- router->or_port =
- (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
- router->dir_port =
- (uint16_t) tor_parse_long(tok->args[4],10,0,65535,NULL,NULL);
- } else {
- log_warn(LD_DIR,"Wrong # of arguments to \"router\" (%d)",tok->n_args);
+ router->nickname = tor_strdup(tok->args[0]);
+ if (!is_legal_nickname(router->nickname)) {
+ log_warn(LD_DIR,"Router nickname is invalid");
goto err;
}
-
- tok = find_first_by_keyword(tokens, K_BANDWIDTH);
- if (!tok) {
- log_warn(LD_DIR,"No bandwidth declared; failing.");
+ router->address = tor_strdup(tok->args[1]);
+ if (!tor_inet_aton(router->address, &in)) {
+ log_warn(LD_DIR,"Router address is not an IP.");
goto err;
- } else {
- if (tok->n_args < 3) {
- log_warn(LD_DIR,
- "Not enough arguments to \"bandwidth\" in server descriptor.");
- goto err;
- }
- router->bandwidthrate =
- tor_parse_long(tok->args[0],10,0,INT_MAX,NULL,NULL);
+ }
+ router->addr = ntohl(in.s_addr);
- if (!router->bandwidthrate) {
- log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
- escaped(tok->args[0]));
- goto err;
- }
+ router->or_port =
+ (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
+ router->dir_port =
+ (uint16_t) tor_parse_long(tok->args[4],10,0,65535,NULL,NULL);
- router->bandwidthburst =
- tor_parse_long(tok->args[1],10,0,INT_MAX,NULL,NULL);
- router->bandwidthcapacity =
- tor_parse_long(tok->args[2],10,0,INT_MAX,NULL,NULL);
+ tok = find_first_by_keyword(tokens, K_BANDWIDTH);
+ tor_assert(tok && tok->n_args >= 3);
+ router->bandwidthrate =
+ tor_parse_long(tok->args[0],10,0,INT_MAX,NULL,NULL);
- /* XXX we don't error-check these values? -RD */
+ if (!router->bandwidthrate) {
+ log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
+ escaped(tok->args[0]));
+ goto err;
}
+ router->bandwidthburst =
+ tor_parse_long(tok->args[1],10,0,INT_MAX,NULL,NULL);
+ router->bandwidthcapacity =
+ tor_parse_long(tok->args[2],10,0,INT_MAX,NULL,NULL);
+ /* XXX we don't error-check these values? -RD */
if ((tok = find_first_by_keyword(tokens, K_UPTIME))) {
- if (tok->n_args != 1) {
- log_warn(LD_DIR, "Unrecognized number of args on K_UPTIME; skipping.");
- } else {
- router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL);
- }
+ tor_assert(tok->n_args >= 1);
+ router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL);
}
if ((tok = find_first_by_keyword(tokens, K_HIBERNATING))) {
- if (tok->n_args < 1) {
- log_warn(LD_DIR, "Too few args on 'hibernating' keyword. Skipping.");
- } else {
- router->is_hibernating
- = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
- }
+ tor_assert(tok->n_args >= 1);
+ router->is_hibernating
+ = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
}
tok = find_first_by_keyword(tokens, K_PUBLISHED);
@@ -934,10 +913,7 @@
if ((tok = find_first_by_keyword(tokens, K_FINGERPRINT))) {
/* If there's a fingerprint line, it must match the identity digest. */
char d[DIGEST_LEN];
- if (tok->n_args < 1) {
- log_warn(LD_DIR, "Too few arguments to router fingerprint");
- goto err;
- }
+ tor_assert(tok->n_args == 1);
tor_strstrip(tok->args[0], " ");
if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
@@ -989,8 +965,8 @@
if ((tok = find_first_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
router->caches_extra_info = 1;
- if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST)) &&
- tok->n_args) {
+ if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
+ tor_assert(tok->n_args >= 1);
if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
base16_decode(router->extra_info_digest, DIGEST_LEN, tok->args[0],
HEX_DIGEST_LEN);
@@ -1094,11 +1070,7 @@
extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
extrainfo->cache_info.signed_descriptor_len = end-s;
memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
-
- if (tok->n_args < 2) {
- log_warn(LD_DIR,"Insufficient arguments to \"extra-info\"");
- goto err;
- }
+ tor_assert(tok->n_args >= 2);
if (!is_legal_nickname(tok->args[0])) {
log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
goto err;
@@ -1203,10 +1175,7 @@
}
tok = find_first_by_keyword(tokens, K_R);
tor_assert(tok);
- if (tok->n_args < 8) {
- log_warn(LD_DIR,
- "Too few arguments to 'r' keywork in router status; skipping.");
- }
+ tor_assert(tok->n_args >= 8);
rs = tor_malloc_zero(sizeof(routerstatus_t));
if (!is_legal_nickname(tok->args[0])) {
@@ -1272,7 +1241,8 @@
rs->is_bad_directory = 1;
}
}
- if ((tok = find_first_by_keyword(tokens, K_V)) && tok->n_args) {
+ if ((tok = find_first_by_keyword(tokens, K_V))) {
+ tor_assert(tok->n_args == 1);
rs->version_known = 1;
if (strcmpstart(tok->args[0], "Tor ")) {
rs->version_supports_begindir = 1;
@@ -1352,10 +1322,7 @@
tok = find_first_by_keyword(tokens, K_DIR_SOURCE);
tor_assert(tok);
- if (tok->n_args < 3) {
- log_warn(LD_DIR, "Too few arguments to dir-source keyword");
- goto err;
- }
+ tor_assert(tok->n_args >= 3);
ns->source_address = tok->args[0]; tok->args[0] = NULL;
if (tor_inet_aton(tok->args[1], &in) == 0) {
log_warn(LD_DIR, "Error parsing network-status source address %s",
@@ -1372,10 +1339,7 @@
tok = find_first_by_keyword(tokens, K_FINGERPRINT);
tor_assert(tok);
- if (tok->n_args < 1) {
- log_warn(LD_DIR, "Too few arguments to networkstatus fingerprint");
- goto err;
- }
+ tor_assert(tok->n_args);
if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
strlen(tok->args[0]))) {
log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
@@ -1383,7 +1347,8 @@
goto err;
}
- if ((tok = find_first_by_keyword(tokens, K_CONTACT)) && tok->n_args) {
+ if ((tok = find_first_by_keyword(tokens, K_CONTACT))) {
+ tor_assert(tok->n_args);
ns->contact = tok->args[0];
tok->args[0] = NULL;
}
@@ -1417,8 +1382,7 @@
}
if (ns->recommends_versions) {
- if (!(tok = find_first_by_keyword(tokens, K_CLIENT_VERSIONS)) ||
- tok->n_args<1) {
+ if (!(tok = find_first_by_keyword(tokens, K_CLIENT_VERSIONS))) {
log_warn(LD_DIR, "Missing client-versions");
}
ns->client_versions = tok->args[0];
@@ -1684,6 +1648,7 @@
}
tor_free(tok->object_type);
tor_free(tok->object_body);
+ tor_free(tok->error);
if (tok->key)
crypto_free_pk_env(tok->key);
tor_free(tok);
@@ -1696,17 +1661,19 @@
get_next_token(const char **s, struct token_rule_t *table)
{
const char *next, *obstart;
- int i, done, allocated, is_opt;
+ int i, j, done, allocated, is_opt;
directory_token_t *tok;
- arg_syntax a_syn;
obj_syntax o_syn = NO_OBJ;
+ char ebuf[128];
+ const char *kwd = "";
-#define RET_ERR(msg) \
- do { if (tok) token_free(tok); \
- tok = tor_malloc_zero(sizeof(directory_token_t));\
- tok->tp = _ERR; \
- tok->error = msg; \
- goto done_tokenizing; } while (0)
+#define RET_ERR(msg) \
+ do { \
+ if (tok) token_free(tok); \
+ tok = tor_malloc_zero(sizeof(directory_token_t)); \
+ tok->tp = _ERR; \
+ tok->error = tor_strdup(msg); \
+ goto done_tokenizing; } while (0)
tok = tor_malloc_zero(sizeof(directory_token_t));
tok->tp = _ERR;
@@ -1718,7 +1685,7 @@
}
next = find_whitespace(*s);
if (!next) {
- tok->error = "Unexpected EOF"; return tok;
+ tok->error = tor_strdup("Unexpected EOF"); return tok;
}
/* It's a keyword... but which one? */
is_opt = !strncmp("opt", *s, next-*s);
@@ -1734,12 +1701,22 @@
for (i = 0; table[i].t ; ++i) {
if (!strncmp(table[i].t, *s, next-*s)) {
/* We've found the keyword. */
+ kwd = table[i].t;
tok->tp = table[i].v;
- a_syn = table[i].s;
o_syn = table[i].os;
- if (a_syn == ARGS) {
+ if (table[i].concat_args) {
+ /* The keyword takes the line as a single argument */
+ *s = eat_whitespace_no_nl(next);
+ next = strchr(*s, '\n');
+ if (!next)
+ RET_ERR("Unexpected EOF");
+ tok->args = tor_malloc(sizeof(char*));
+ tok->args[0] = tor_strndup(*s,next-*s);
+ tok->n_args = 1;
+ *s = eat_whitespace_no_nl(next+1);
+ } else {
/* This keyword takes multiple arguments. */
- i = 0;
+ j = 0;
done = (*next == '\n');
allocated = 32;
tok->args = tor_malloc(sizeof(char*)*32);
@@ -1748,34 +1725,23 @@
next = find_whitespace(*s);
if (*next == '\n')
done = 1;
- if (i == allocated) {
+ if (j == allocated) {
allocated *= 2;
tok->args = tor_realloc(tok->args,sizeof(char*)*allocated);
}
- tok->args[i++] = tor_strndup(*s,next-*s);
+ tok->args[j++] = tor_strndup(*s,next-*s);
*s = eat_whitespace_no_nl(next+1);
}
- tok->n_args = i;
- } else if (a_syn == CONCAT_ARGS) {
- /* The keyword takes the line as a single argument */
- *s = eat_whitespace_no_nl(next);
- next = strchr(*s, '\n');
- if (!next)
- RET_ERR("Unexpected EOF");
- tok->args = tor_malloc(sizeof(char*));
- tok->args[0] = tor_strndup(*s,next-*s);
- tok->n_args = 1;
- *s = eat_whitespace_no_nl(next+1);
- } else {
- /* The keyword takes no arguments. */
- tor_assert(a_syn == NO_ARGS);
- *s = eat_whitespace_no_nl(next);
- if (**s != '\n') {
- RET_ERR("Unexpected arguments");
- }
- tok->n_args = 0;
- *s = eat_whitespace_no_nl(*s+1);
+ tok->n_args = j;
}
+ if (tok->n_args < table[i].min_args) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
+ RET_ERR(ebuf);
+ } else if (tok->n_args > table[i].max_args) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
+ RET_ERR(ebuf);
+ }
+
break;
}
}
@@ -1832,18 +1798,26 @@
switch (o_syn)
{
case NO_OBJ:
- if (tok->object_body)
- RET_ERR("Unexpected object for keyword");
- if (tok->key)
- RET_ERR("Unexpected public key for keyword");
+ if (tok->object_body) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
+ RET_ERR(ebuf);
+ }
+ if (tok->key) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
+ RET_ERR(ebuf);
+ }
break;
case NEED_OBJ:
- if (!tok->object_body)
- RET_ERR("Missing object for keyword");
+ if (!tok->object_body) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
+ RET_ERR(ebuf);
+ }
break;
case NEED_KEY:
- if (!tok->key)
- RET_ERR("Missing public key for keyword");
+ if (!tok->key) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
+ RET_ERR(ebuf);
+ }
break;
case OBJ_OK:
break;