2017-03-15 21:13:17 +01:00
|
|
|
/* Copyright (c) 2016-2017, The Tor Project, Inc. */
|
2016-03-11 19:26:04 +01:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file parsecommon.h
|
|
|
|
* \brief Header file for parsecommon.c
|
|
|
|
**/
|
|
|
|
|
|
|
|
#ifndef TOR_PARSECOMMON_H
|
|
|
|
#define TOR_PARSECOMMON_H
|
|
|
|
|
|
|
|
#include "container.h"
|
|
|
|
#include "crypto.h"
|
|
|
|
#include "memarea.h"
|
|
|
|
|
|
|
|
/** Enumeration of possible token types. The ones starting with K_ correspond
|
|
|
|
* to directory 'keywords'. A_ is for an annotation, R or C is related to
|
|
|
|
* hidden services, ERR_ is an error in the tokenizing process, EOF_ is an
|
|
|
|
* end-of-file marker, and NIL_ is used to encode not-a-token.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
K_ACCEPT = 0,
|
|
|
|
K_ACCEPT6,
|
|
|
|
K_DIRECTORY_SIGNATURE,
|
|
|
|
K_RECOMMENDED_SOFTWARE,
|
|
|
|
K_REJECT,
|
|
|
|
K_REJECT6,
|
|
|
|
K_ROUTER,
|
|
|
|
K_SIGNED_DIRECTORY,
|
|
|
|
K_SIGNING_KEY,
|
|
|
|
K_ONION_KEY,
|
|
|
|
K_ONION_KEY_NTOR,
|
|
|
|
K_ROUTER_SIGNATURE,
|
|
|
|
K_PUBLISHED,
|
|
|
|
K_RUNNING_ROUTERS,
|
|
|
|
K_ROUTER_STATUS,
|
|
|
|
K_PLATFORM,
|
2016-11-04 18:26:37 +01:00
|
|
|
K_PROTO,
|
2016-03-11 19:26:04 +01:00
|
|
|
K_OPT,
|
|
|
|
K_BANDWIDTH,
|
|
|
|
K_CONTACT,
|
|
|
|
K_NETWORK_STATUS,
|
|
|
|
K_UPTIME,
|
|
|
|
K_DIR_SIGNING_KEY,
|
|
|
|
K_FAMILY,
|
|
|
|
K_FINGERPRINT,
|
|
|
|
K_HIBERNATING,
|
|
|
|
K_READ_HISTORY,
|
|
|
|
K_WRITE_HISTORY,
|
|
|
|
K_NETWORK_STATUS_VERSION,
|
|
|
|
K_DIR_SOURCE,
|
|
|
|
K_DIR_OPTIONS,
|
|
|
|
K_CLIENT_VERSIONS,
|
|
|
|
K_SERVER_VERSIONS,
|
2016-11-04 18:26:37 +01:00
|
|
|
K_RECOMMENDED_CLIENT_PROTOCOLS,
|
|
|
|
K_RECOMMENDED_RELAY_PROTOCOLS,
|
|
|
|
K_REQUIRED_CLIENT_PROTOCOLS,
|
|
|
|
K_REQUIRED_RELAY_PROTOCOLS,
|
2016-03-11 19:26:04 +01:00
|
|
|
K_OR_ADDRESS,
|
|
|
|
K_ID,
|
|
|
|
K_P,
|
|
|
|
K_P6,
|
|
|
|
K_R,
|
|
|
|
K_A,
|
|
|
|
K_S,
|
|
|
|
K_V,
|
|
|
|
K_W,
|
|
|
|
K_M,
|
|
|
|
K_EXTRA_INFO,
|
|
|
|
K_EXTRA_INFO_DIGEST,
|
|
|
|
K_CACHES_EXTRA_INFO,
|
|
|
|
K_HIDDEN_SERVICE_DIR,
|
|
|
|
K_ALLOW_SINGLE_HOP_EXITS,
|
|
|
|
K_IPV6_POLICY,
|
|
|
|
K_ROUTER_SIG_ED25519,
|
|
|
|
K_IDENTITY_ED25519,
|
|
|
|
K_MASTER_KEY_ED25519,
|
|
|
|
K_ONION_KEY_CROSSCERT,
|
|
|
|
K_NTOR_ONION_KEY_CROSSCERT,
|
|
|
|
|
|
|
|
K_DIRREQ_END,
|
|
|
|
K_DIRREQ_V2_IPS,
|
|
|
|
K_DIRREQ_V3_IPS,
|
|
|
|
K_DIRREQ_V2_REQS,
|
|
|
|
K_DIRREQ_V3_REQS,
|
|
|
|
K_DIRREQ_V2_SHARE,
|
|
|
|
K_DIRREQ_V3_SHARE,
|
|
|
|
K_DIRREQ_V2_RESP,
|
|
|
|
K_DIRREQ_V3_RESP,
|
|
|
|
K_DIRREQ_V2_DIR,
|
|
|
|
K_DIRREQ_V3_DIR,
|
|
|
|
K_DIRREQ_V2_TUN,
|
|
|
|
K_DIRREQ_V3_TUN,
|
|
|
|
K_ENTRY_END,
|
|
|
|
K_ENTRY_IPS,
|
|
|
|
K_CELL_END,
|
|
|
|
K_CELL_PROCESSED,
|
|
|
|
K_CELL_QUEUED,
|
|
|
|
K_CELL_TIME,
|
|
|
|
K_CELL_CIRCS,
|
|
|
|
K_EXIT_END,
|
|
|
|
K_EXIT_WRITTEN,
|
|
|
|
K_EXIT_READ,
|
|
|
|
K_EXIT_OPENED,
|
|
|
|
|
|
|
|
K_DIR_KEY_CERTIFICATE_VERSION,
|
|
|
|
K_DIR_IDENTITY_KEY,
|
|
|
|
K_DIR_KEY_PUBLISHED,
|
|
|
|
K_DIR_KEY_EXPIRES,
|
|
|
|
K_DIR_KEY_CERTIFICATION,
|
|
|
|
K_DIR_KEY_CROSSCERT,
|
|
|
|
K_DIR_ADDRESS,
|
|
|
|
K_DIR_TUNNELLED,
|
|
|
|
|
|
|
|
K_VOTE_STATUS,
|
|
|
|
K_VALID_AFTER,
|
|
|
|
K_FRESH_UNTIL,
|
|
|
|
K_VALID_UNTIL,
|
|
|
|
K_VOTING_DELAY,
|
|
|
|
|
|
|
|
K_KNOWN_FLAGS,
|
|
|
|
K_PARAMS,
|
|
|
|
K_BW_WEIGHTS,
|
|
|
|
K_VOTE_DIGEST,
|
|
|
|
K_CONSENSUS_DIGEST,
|
|
|
|
K_ADDITIONAL_DIGEST,
|
|
|
|
K_ADDITIONAL_SIGNATURE,
|
|
|
|
K_CONSENSUS_METHODS,
|
|
|
|
K_CONSENSUS_METHOD,
|
|
|
|
K_LEGACY_DIR_KEY,
|
|
|
|
K_DIRECTORY_FOOTER,
|
|
|
|
K_SIGNING_CERT_ED,
|
|
|
|
K_SR_FLAG,
|
|
|
|
K_COMMIT,
|
|
|
|
K_PREVIOUS_SRV,
|
|
|
|
K_CURRENT_SRV,
|
|
|
|
K_PACKAGE,
|
|
|
|
|
|
|
|
A_PURPOSE,
|
|
|
|
A_LAST_LISTED,
|
|
|
|
A_UNKNOWN_,
|
|
|
|
|
|
|
|
R_RENDEZVOUS_SERVICE_DESCRIPTOR,
|
|
|
|
R_VERSION,
|
|
|
|
R_PERMANENT_KEY,
|
|
|
|
R_SECRET_ID_PART,
|
|
|
|
R_PUBLICATION_TIME,
|
|
|
|
R_PROTOCOL_VERSIONS,
|
|
|
|
R_INTRODUCTION_POINTS,
|
|
|
|
R_SIGNATURE,
|
|
|
|
|
2016-06-28 22:27:01 +02:00
|
|
|
R_HS_DESCRIPTOR, /* From version 3, this MUST be generic to all future
|
|
|
|
descriptor versions thus making it R_. */
|
|
|
|
R3_DESC_LIFETIME,
|
|
|
|
R3_DESC_SIGNING_CERT,
|
|
|
|
R3_REVISION_COUNTER,
|
2016-12-21 15:07:07 +01:00
|
|
|
R3_SUPERENCRYPTED,
|
2016-06-28 22:27:01 +02:00
|
|
|
R3_SIGNATURE,
|
|
|
|
R3_CREATE2_FORMATS,
|
2017-02-02 12:58:20 +01:00
|
|
|
R3_INTRO_AUTH_REQUIRED,
|
2016-11-08 19:22:42 +01:00
|
|
|
R3_SINGLE_ONION_SERVICE,
|
2016-06-28 22:27:01 +02:00
|
|
|
R3_INTRODUCTION_POINT,
|
|
|
|
R3_INTRO_AUTH_KEY,
|
|
|
|
R3_INTRO_ENC_KEY,
|
|
|
|
R3_INTRO_ENC_KEY_CERTIFICATION,
|
2017-02-08 13:42:12 +01:00
|
|
|
R3_DESC_AUTH_TYPE,
|
|
|
|
R3_DESC_AUTH_KEY,
|
|
|
|
R3_DESC_AUTH_CLIENT,
|
|
|
|
R3_ENCRYPTED,
|
2016-06-28 22:27:01 +02:00
|
|
|
|
2016-03-11 19:26:04 +01:00
|
|
|
R_IPO_IDENTIFIER,
|
|
|
|
R_IPO_IP_ADDRESS,
|
|
|
|
R_IPO_ONION_PORT,
|
|
|
|
R_IPO_ONION_KEY,
|
|
|
|
R_IPO_SERVICE_KEY,
|
|
|
|
|
|
|
|
C_CLIENT_NAME,
|
|
|
|
C_DESCRIPTOR_COOKIE,
|
|
|
|
C_CLIENT_KEY,
|
|
|
|
|
|
|
|
ERR_,
|
|
|
|
EOF_,
|
|
|
|
NIL_
|
|
|
|
} directory_keyword;
|
|
|
|
|
|
|
|
/** Structure to hold a single directory token.
|
|
|
|
*
|
|
|
|
* We parse a directory by breaking it into "tokens", each consisting
|
|
|
|
* of a keyword, a line full of arguments, and a binary object. The
|
|
|
|
* arguments and object are both optional, depending on the keyword
|
|
|
|
* type.
|
|
|
|
*
|
|
|
|
* This structure is only allocated in memareas; do not allocate it on
|
|
|
|
* the heap, or token_clear() won't work.
|
|
|
|
*/
|
|
|
|
typedef struct directory_token_t {
|
|
|
|
directory_keyword tp; /**< Type of the token. */
|
|
|
|
int n_args:30; /**< Number of elements in args */
|
|
|
|
char **args; /**< Array of arguments from keyword line. */
|
|
|
|
|
|
|
|
char *object_type; /**< -----BEGIN [object_type]-----*/
|
|
|
|
size_t object_size; /**< Bytes in object_body */
|
|
|
|
char *object_body; /**< Contents of object, base64-decoded. */
|
|
|
|
|
|
|
|
crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
|
|
|
|
|
|
|
|
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 whether the keyword needs an object. */
|
|
|
|
typedef enum {
|
|
|
|
NO_OBJ, /**< No object, ever. */
|
|
|
|
NEED_OBJ, /**< Object is required. */
|
|
|
|
NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
|
|
|
|
NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
|
|
|
|
NEED_KEY, /**< Object is required, and must be a public key. */
|
|
|
|
OBJ_OK, /**< Object is optional. */
|
|
|
|
} obj_syntax;
|
|
|
|
|
|
|
|
#define AT_START 1
|
|
|
|
#define AT_END 2
|
|
|
|
|
|
|
|
#define TS_ANNOTATIONS_OK 1
|
|
|
|
#define TS_NOCHECK 2
|
|
|
|
#define TS_NO_NEW_ANNOTATIONS 4
|
|
|
|
|
2016-11-04 18:26:37 +01:00
|
|
|
/**
|
|
|
|
* @name macros for defining token rules
|
|
|
|
*
|
2016-03-11 19:26:04 +01:00
|
|
|
* Helper macros to define token tables. 's' is a string, 't' is a
|
|
|
|
* directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
|
|
|
|
* object syntax.
|
|
|
|
*/
|
2016-11-04 18:26:37 +01:00
|
|
|
/**@{*/
|
2016-03-11 19:26:04 +01:00
|
|
|
|
|
|
|
/** Appears to indicate the end of a table. */
|
|
|
|
#define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
|
|
|
|
/** An item with no restrictions: used for obsolete document types */
|
|
|
|
#define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
|
|
|
|
/** An item with no restrictions on multiplicity or location. */
|
|
|
|
#define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
|
|
|
|
/** An item that must appear exactly once */
|
|
|
|
#define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
|
|
|
|
/** An item that must appear exactly once, at the start of the document */
|
|
|
|
#define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
|
|
|
|
/** An item that must appear exactly once, at the end of the document */
|
|
|
|
#define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
|
|
|
|
/** An item that must appear one or more times */
|
|
|
|
#define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
|
|
|
|
/** An item that must appear no more than once */
|
|
|
|
#define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
|
|
|
|
/** An annotation that must appear no more than once */
|
|
|
|
#define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
|
|
|
|
|
2016-11-04 18:26:37 +01:00
|
|
|
/** Argument multiplicity: any number of arguments. */
|
2016-03-11 19:26:04 +01:00
|
|
|
#define ARGS 0,INT_MAX,0
|
2016-11-04 18:26:37 +01:00
|
|
|
/** Argument multiplicity: no arguments. */
|
2016-03-11 19:26:04 +01:00
|
|
|
#define NO_ARGS 0,0,0
|
2016-11-04 18:26:37 +01:00
|
|
|
/** Argument multiplicity: concatenate all arguments. */
|
2016-03-11 19:26:04 +01:00
|
|
|
#define CONCAT_ARGS 1,1,1
|
2016-11-04 18:26:37 +01:00
|
|
|
/** Argument multiplicity: at least <b>n</b> arguments. */
|
2016-03-11 19:26:04 +01:00
|
|
|
#define GE(n) n,INT_MAX,0
|
2016-11-04 18:26:37 +01:00
|
|
|
/** Argument multiplicity: exactly <b>n</b> arguments. */
|
2016-03-11 19:26:04 +01:00
|
|
|
#define EQ(n) n,n,0
|
2016-11-04 18:26:37 +01:00
|
|
|
/**@}*/
|
2016-03-11 19:26:04 +01:00
|
|
|
|
|
|
|
/** Determines the parsing rules for a single token type. */
|
|
|
|
typedef struct token_rule_t {
|
|
|
|
/** The string value of the keyword identifying the type of item. */
|
|
|
|
const char *t;
|
|
|
|
/** The corresponding directory_keyword enum. */
|
|
|
|
directory_keyword v;
|
|
|
|
/** Minimum number of arguments for this item */
|
|
|
|
int min_args;
|
|
|
|
/** Maximum number of arguments for this item */
|
|
|
|
int max_args;
|
|
|
|
/** If true, we concatenate all arguments for this item into a single
|
|
|
|
* string. */
|
|
|
|
int concat_args;
|
|
|
|
/** Requirements on object syntax for this item. */
|
|
|
|
obj_syntax os;
|
|
|
|
/** Lowest number of times this item may appear in a document. */
|
|
|
|
int min_cnt;
|
|
|
|
/** Highest number of times this item may appear in a document. */
|
|
|
|
int max_cnt;
|
|
|
|
/** One or more of AT_START/AT_END to limit where the item may appear in a
|
|
|
|
* document. */
|
|
|
|
int pos;
|
|
|
|
/** True iff this token is an annotation. */
|
|
|
|
int is_annotation;
|
|
|
|
} token_rule_t;
|
|
|
|
|
|
|
|
void token_clear(directory_token_t *tok);
|
|
|
|
|
|
|
|
int tokenize_string(memarea_t *area,
|
|
|
|
const char *start, const char *end,
|
|
|
|
smartlist_t *out,
|
|
|
|
token_rule_t *table,
|
|
|
|
int flags);
|
|
|
|
directory_token_t *get_next_token(memarea_t *area,
|
|
|
|
const char **s,
|
|
|
|
const char *eos,
|
|
|
|
token_rule_t *table);
|
|
|
|
|
|
|
|
directory_token_t *find_by_keyword_(smartlist_t *s,
|
|
|
|
directory_keyword keyword,
|
|
|
|
const char *keyword_str);
|
|
|
|
|
|
|
|
#define find_by_keyword(s, keyword) \
|
|
|
|
find_by_keyword_((s), (keyword), #keyword)
|
|
|
|
|
|
|
|
directory_token_t *find_opt_by_keyword(smartlist_t *s,
|
|
|
|
directory_keyword keyword);
|
|
|
|
smartlist_t * find_all_by_keyword(smartlist_t *s, directory_keyword k);
|
|
|
|
|
|
|
|
#endif /* TOR_PARSECOMMON_H */
|
2016-08-25 00:44:34 +02:00
|
|
|
|