22 #define MIN_ANNOTATION A_PURPOSE
23 #define MAX_ANNOTATION A_UNKNOWN_
25 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
26 #define ALLOC(sz) memarea_alloc(area,sz)
27 #define STRDUP(str) memarea_strdup(area,str)
28 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
30 #define RET_ERR(msg) \
32 if (tok) token_clear(tok); \
33 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
35 tok->error = STRDUP(msg); \
36 goto done_tokenizing; \
44 crypto_pk_free(tok->
key);
54 const char *start,
const char *end,
smartlist_t *out,
61 int first_nonannotation;
62 int prev_len = smartlist_len(out);
67 end = start+strlen(start);
70 if (memchr(start,
'\0', end-start)) {
71 log_warn(
LD_DIR,
"parse error: internal NUL character.");
75 for (i = 0; i < NIL_; ++i)
80 while (*s < end && (!tok || tok->
tp != EOF_)) {
82 if (tok->
tp == ERR_) {
92 if (flags & TS_NOCHECK)
95 if ((flags & TS_ANNOTATIONS_OK)) {
96 first_nonannotation = -1;
97 for (i = 0; i < smartlist_len(out); ++i) {
98 tok = smartlist_get(out, i);
99 if (tok->
tp < MIN_ANNOTATION || tok->
tp > MAX_ANNOTATION) {
100 first_nonannotation = i;
104 if (first_nonannotation < 0) {
105 log_warn(
LD_DIR,
"parse error: item contains only annotations");
108 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
109 tok = smartlist_get(out, i);
110 if (tok->
tp >= MIN_ANNOTATION && tok->
tp <= MAX_ANNOTATION) {
111 log_warn(
LD_DIR,
"parse error: Annotations mixed with keywords");
115 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
116 if (first_nonannotation != prev_len) {
117 log_warn(
LD_DIR,
"parse error: Unexpected annotations.");
122 for (i=0; i < smartlist_len(out); ++i) {
123 tok = smartlist_get(out, i);
124 if (tok->
tp >= MIN_ANNOTATION && tok->
tp <= MAX_ANNOTATION) {
125 log_warn(
LD_DIR,
"parse error: no annotations allowed.");
129 first_nonannotation = 0;
131 for (i = 0; table[i].
t; ++i) {
132 if (
counts[table[i].v] < table[i].min_cnt) {
133 log_warn(
LD_DIR,
"Parse error: missing %s element.", table[i].t);
136 if (
counts[table[i].v] > table[i].max_cnt) {
137 log_warn(
LD_DIR,
"Parse error: too many %s elements.", table[i].t);
140 if (table[i].pos & AT_START) {
141 if (smartlist_len(out) < 1 ||
142 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
143 log_warn(
LD_DIR,
"Parse error: first item is not %s.", table[i].t);
147 if (table[i].pos & AT_END) {
148 if (smartlist_len(out) < 1 ||
149 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
150 log_warn(
LD_DIR,
"Parse error: last item is not %s.", table[i].t);
165 const char *s,
const char *eol)
172 char *args[MAX_ARGS];
203 tor_snprintf(ebuf,
sizeof(ebuf),
"Unexpected object for %s", kwd);
207 tor_snprintf(ebuf,
sizeof(ebuf),
"Unexpected public key for %s", kwd);
214 tor_snprintf(ebuf,
sizeof(ebuf),
"Missing object for %s", kwd);
220 tor_snprintf(ebuf,
sizeof(ebuf),
"Wrong size on key for %s: %d bits",
227 tor_snprintf(ebuf,
sizeof(ebuf),
"Missing public key for %s", kwd);
233 "Private key given for %s, which wants a public key", kwd);
252 size_t len = strlen(token);
253 return memlen == len &&
fast_memeq(mem, token, len);
262 const char **s,
const char *eos,
const token_rule_t *table)
266 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
269 #define MAX_LINE_LENGTH (128*1024)
271 const char *next, *eol;
277 const char *kwd =
"";
286 eol = memchr(*s,
'\n', eos-*s);
289 if (eol - *s > MAX_LINE_LENGTH) {
290 RET_ERR(
"Line far too long");
299 }
else if (*s == eos) {
300 RET_ERR(
"Unexpected EOF");
305 for (i = 0; table[i].
t ; ++i) {
309 tok->
tp = table[i].
v;
314 if (table[i].concat_args) {
316 tok->
args = ALLOC(
sizeof(
char*));
317 tok->
args[0] = STRNDUP(*s,eol-*s);
322 tor_snprintf(ebuf,
sizeof(ebuf),
"Far too many arguments to %s", kwd);
328 tor_snprintf(ebuf,
sizeof(ebuf),
"Too few arguments to %s", kwd);
331 tor_snprintf(ebuf,
sizeof(ebuf),
"Too many arguments to %s", kwd);
338 if (tok->
tp == ERR_) {
340 if (*s < eol && **s ==
'@')
341 tok->
tp = A_UNKNOWN_;
344 tok->
args = ALLOC(
sizeof(
char*));
345 tok->
args[0] = STRNDUP(*s, eol-*s);
353 eol = memchr(*s,
'\n', eos-*s);
354 if (!eol || eol-*s<11 ||
strcmpstart(*s,
"-----BEGIN "))
357 if (eol - *s <= 16 || memchr(*s+11,
'\0',eol-*s-16) ||
359 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) {
360 RET_ERR(
"Malformed object: bad begin line");
363 obname_len = eol-*s-16;
367 next = tor_memstr(*s, eos-*s,
"-----END ");
369 RET_ERR(
"Malformed object: missing object end line");
372 eol = memchr(next,
'\n', eos-next);
376 if ((
size_t)(eol-next) != 9+obname_len+5 ||
379 tor_snprintf(ebuf,
sizeof(ebuf),
"Malformed object: mismatched end tag %s",
381 ebuf[
sizeof(ebuf)-1] =
'\0';
384 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
385 RET_ERR(
"Couldn't parse object: missing footer or object much too big.");
393 RET_ERR(
"Malformed object: bad base64-encoded data");
399 RET_ERR(
"Unexpected public key.");
403 RET_ERR(
"Couldn't parse public key.");
425 const char *keyword_as_string)
428 if (PREDICT_UNLIKELY(!tok)) {
429 log_err(
LD_BUG,
"Missing %s [%d] in directory object that should have "
430 "been validated. Internal error.", keyword_as_string, (
int)keyword);
457 out = smartlist_new();
458 smartlist_add(out, t);
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
size_t base64_decode_maxsize(size_t srclen)
static conn_counts_t counts
Headers for crypto_rsa.c.
crypto_pk_t * crypto_pk_asn1_decode(const char *str, size_t len)
int crypto_pk_num_bits(crypto_pk_t *env)
int crypto_pk_key_is_private(const crypto_pk_t *key)
#define fast_memeq(a, b, c)
void * memarea_memdup(memarea_t *area, const void *s, size_t n)
char * memarea_strndup(memarea_t *area, const char *s, size_t n)
void token_clear(directory_token_t *tok)
int tokenize_string(memarea_t *area, const char *start, const char *end, smartlist_t *out, const token_rule_t *table, int flags)
static int get_token_arguments(memarea_t *area, directory_token_t *tok, const char *s, const char *eol)
directory_token_t * find_opt_by_keyword(const smartlist_t *s, directory_keyword keyword)
smartlist_t * find_all_by_keyword(const smartlist_t *s, directory_keyword k)
directory_token_t * get_next_token(memarea_t *area, const char **s, const char *eos, const token_rule_t *table)
static directory_token_t * token_check_object(memarea_t *area, const char *kwd, directory_token_t *tok, obj_syntax o_syn)
static bool mem_eq_token(const void *mem, size_t memlen, const char *token)
directory_token_t * find_by_keyword_(smartlist_t *s, directory_keyword keyword, const char *keyword_as_string)
Header file for parsecommon.c.
int tor_snprintf(char *str, size_t size, const char *format,...)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Macros to manage assertions, fatal and non-fatal.
const char * eat_whitespace_eos_no_nl(const char *s, const char *eos)
int strcmpstart(const char *s1, const char *s2)
const char * find_whitespace_eos(const char *s, const char *eos)
const char * find_whitespace(const char *s)
const char * eat_whitespace_eos(const char *s, const char *eos)
const char * eat_whitespace(const char *s)
Header for util_string.c.