confline.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. #include "lib/encoding/confline.h"
  7. #include "lib/encoding/cstring.h"
  8. #include "lib/log/torlog.h"
  9. #include "lib/log/util_bug.h"
  10. #include "lib/malloc/util_malloc.h"
  11. #include "lib/string/compat_ctype.h"
  12. #include "lib/string/compat_string.h"
  13. #include "lib/string/util_string.h"
  14. #include <string.h>
  15. /** Helper: allocate a new configuration option mapping 'key' to 'val',
  16. * append it to *<b>lst</b>. */
  17. void
  18. config_line_append(config_line_t **lst,
  19. const char *key,
  20. const char *val)
  21. {
  22. tor_assert(lst);
  23. config_line_t *newline;
  24. newline = tor_malloc_zero(sizeof(config_line_t));
  25. newline->key = tor_strdup(key);
  26. newline->value = tor_strdup(val);
  27. newline->next = NULL;
  28. while (*lst)
  29. lst = &((*lst)->next);
  30. (*lst) = newline;
  31. }
  32. /** Helper: allocate a new configuration option mapping 'key' to 'val',
  33. * and prepend it to *<b>lst</b> */
  34. void
  35. config_line_prepend(config_line_t **lst,
  36. const char *key,
  37. const char *val)
  38. {
  39. tor_assert(lst);
  40. config_line_t *newline;
  41. newline = tor_malloc_zero(sizeof(config_line_t));
  42. newline->key = tor_strdup(key);
  43. newline->value = tor_strdup(val);
  44. newline->next = *lst;
  45. *lst = newline;
  46. }
  47. /** Return the first line in <b>lines</b> whose key is exactly <b>key</b>, or
  48. * NULL if no such key exists.
  49. *
  50. * (In options parsing, this is for handling commandline-only options only;
  51. * other options should be looked up in the appropriate data structure.) */
  52. const config_line_t *
  53. config_line_find(const config_line_t *lines,
  54. const char *key)
  55. {
  56. const config_line_t *cl;
  57. for (cl = lines; cl; cl = cl->next) {
  58. if (!strcmp(cl->key, key))
  59. return cl;
  60. }
  61. return NULL;
  62. }
  63. /** Auxiliary function that does all the work of config_get_lines.
  64. * <b>recursion_level</b> is the count of how many nested %includes we have.
  65. * <b>opened_lst</b> will have a list of opened files if provided.
  66. * Returns the a pointer to the last element of the <b>result</b> in
  67. * <b>last</b>. */
  68. int
  69. config_get_lines_aux(const char *string, config_line_t **result, int extended,
  70. int allow_include, int *has_include,
  71. struct smartlist_t *opened_lst, int recursion_level,
  72. config_line_t **last,
  73. include_handler_fn handle_include)
  74. {
  75. config_line_t *list = NULL, **next, *list_last = NULL;
  76. char *k, *v;
  77. const char *parse_err;
  78. int include_used = 0;
  79. if (recursion_level > MAX_INCLUDE_RECURSION_LEVEL) {
  80. log_warn(LD_CONFIG, "Error while parsing configuration: more than %d "
  81. "nested %%includes.", MAX_INCLUDE_RECURSION_LEVEL);
  82. return -1;
  83. }
  84. next = &list;
  85. do {
  86. k = v = NULL;
  87. string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
  88. if (!string) {
  89. log_warn(LD_CONFIG, "Error while parsing configuration: %s",
  90. parse_err?parse_err:"<unknown>");
  91. config_free_lines(list);
  92. tor_free(k);
  93. tor_free(v);
  94. return -1;
  95. }
  96. if (k && v) {
  97. unsigned command = CONFIG_LINE_NORMAL;
  98. if (extended) {
  99. if (k[0] == '+') {
  100. char *k_new = tor_strdup(k+1);
  101. tor_free(k);
  102. k = k_new;
  103. command = CONFIG_LINE_APPEND;
  104. } else if (k[0] == '/') {
  105. char *k_new = tor_strdup(k+1);
  106. tor_free(k);
  107. k = k_new;
  108. tor_free(v);
  109. v = tor_strdup("");
  110. command = CONFIG_LINE_CLEAR;
  111. }
  112. }
  113. if (allow_include && !strcmp(k, "%include") && handle_include) {
  114. tor_free(k);
  115. include_used = 1;
  116. config_line_t *include_list;
  117. if (handle_include(v, recursion_level, extended, &include_list,
  118. &list_last, opened_lst) < 0) {
  119. log_warn(LD_CONFIG, "Error reading included configuration "
  120. "file or directory: \"%s\".", v);
  121. config_free_lines(list);
  122. tor_free(v);
  123. return -1;
  124. }
  125. *next = include_list;
  126. if (list_last)
  127. next = &list_last->next;
  128. tor_free(v);
  129. } else {
  130. /* This list can get long, so we keep a pointer to the end of it
  131. * rather than using config_line_append over and over and getting
  132. * n^2 performance. */
  133. *next = tor_malloc_zero(sizeof(**next));
  134. (*next)->key = k;
  135. (*next)->value = v;
  136. (*next)->next = NULL;
  137. (*next)->command = command;
  138. list_last = *next;
  139. next = &((*next)->next);
  140. }
  141. } else {
  142. tor_free(k);
  143. tor_free(v);
  144. }
  145. } while (*string);
  146. if (last) {
  147. *last = list_last;
  148. }
  149. if (has_include) {
  150. *has_include = include_used;
  151. }
  152. *result = list;
  153. return 0;
  154. }
  155. /** Same as config_get_lines_include but does not allow %include */
  156. int
  157. config_get_lines(const char *string, config_line_t **result, int extended)
  158. {
  159. return config_get_lines_aux(string, result, extended, 0, NULL, NULL, 1,
  160. NULL, NULL);
  161. }
  162. /**
  163. * Free all the configuration lines on the linked list <b>front</b>.
  164. */
  165. void
  166. config_free_lines_(config_line_t *front)
  167. {
  168. config_line_t *tmp;
  169. while (front) {
  170. tmp = front;
  171. front = tmp->next;
  172. tor_free(tmp->key);
  173. tor_free(tmp->value);
  174. tor_free(tmp);
  175. }
  176. }
  177. /** Return a newly allocated deep copy of the lines in <b>inp</b>. */
  178. config_line_t *
  179. config_lines_dup(const config_line_t *inp)
  180. {
  181. return config_lines_dup_and_filter(inp, NULL);
  182. }
  183. /** Return a newly allocated deep copy of the lines in <b>inp</b>,
  184. * but only the ones whose keys begin with <b>key</b> (case-insensitive).
  185. * If <b>key</b> is NULL, do not filter. */
  186. config_line_t *
  187. config_lines_dup_and_filter(const config_line_t *inp,
  188. const char *key)
  189. {
  190. config_line_t *result = NULL;
  191. config_line_t **next_out = &result;
  192. while (inp) {
  193. if (key && strcasecmpstart(inp->key, key)) {
  194. inp = inp->next;
  195. continue;
  196. }
  197. *next_out = tor_malloc_zero(sizeof(config_line_t));
  198. (*next_out)->key = tor_strdup(inp->key);
  199. (*next_out)->value = tor_strdup(inp->value);
  200. inp = inp->next;
  201. next_out = &((*next_out)->next);
  202. }
  203. (*next_out) = NULL;
  204. return result;
  205. }
  206. /** Return true iff a and b contain identical keys and values in identical
  207. * order. */
  208. int
  209. config_lines_eq(config_line_t *a, config_line_t *b)
  210. {
  211. while (a && b) {
  212. if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
  213. return 0;
  214. a = a->next;
  215. b = b->next;
  216. }
  217. if (a || b)
  218. return 0;
  219. return 1;
  220. }
  221. /** Return the number of lines in <b>a</b> whose key is <b>key</b>. */
  222. int
  223. config_count_key(const config_line_t *a, const char *key)
  224. {
  225. int n = 0;
  226. while (a) {
  227. if (!strcasecmp(a->key, key)) {
  228. ++n;
  229. }
  230. a = a->next;
  231. }
  232. return n;
  233. }
  234. /** Given a string containing part of a configuration file or similar format,
  235. * advance past comments and whitespace and try to parse a single line. If we
  236. * parse a line successfully, set *<b>key_out</b> to a new string holding the
  237. * key portion and *<b>value_out</b> to a new string holding the value portion
  238. * of the line, and return a pointer to the start of the next line. If we run
  239. * out of data, return a pointer to the end of the string. If we encounter an
  240. * error, return NULL and set *<b>err_out</b> (if provided) to an error
  241. * message.
  242. */
  243. const char *
  244. parse_config_line_from_str_verbose(const char *line, char **key_out,
  245. char **value_out,
  246. const char **err_out)
  247. {
  248. /*
  249. See torrc_format.txt for a description of the (silly) format this parses.
  250. */
  251. const char *key, *val, *cp;
  252. int continuation = 0;
  253. tor_assert(key_out);
  254. tor_assert(value_out);
  255. *key_out = *value_out = NULL;
  256. key = val = NULL;
  257. /* Skip until the first keyword. */
  258. while (1) {
  259. while (TOR_ISSPACE(*line))
  260. ++line;
  261. if (*line == '#') {
  262. while (*line && *line != '\n')
  263. ++line;
  264. } else {
  265. break;
  266. }
  267. }
  268. if (!*line) { /* End of string? */
  269. *key_out = *value_out = NULL;
  270. return line;
  271. }
  272. /* Skip until the next space or \ followed by newline. */
  273. key = line;
  274. while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
  275. ! (line[0] == '\\' && line[1] == '\n'))
  276. ++line;
  277. *key_out = tor_strndup(key, line-key);
  278. /* Skip until the value. */
  279. while (*line == ' ' || *line == '\t')
  280. ++line;
  281. val = line;
  282. /* Find the end of the line. */
  283. if (*line == '\"') { // XXX No continuation handling is done here
  284. if (!(line = unescape_string(line, value_out, NULL))) {
  285. if (err_out)
  286. *err_out = "Invalid escape sequence in quoted string";
  287. return NULL;
  288. }
  289. while (*line == ' ' || *line == '\t')
  290. ++line;
  291. if (*line == '\r' && *(++line) == '\n')
  292. ++line;
  293. if (*line && *line != '#' && *line != '\n') {
  294. if (err_out)
  295. *err_out = "Excess data after quoted string";
  296. return NULL;
  297. }
  298. } else {
  299. /* Look for the end of the line. */
  300. while (*line && *line != '\n' && (*line != '#' || continuation)) {
  301. if (*line == '\\' && line[1] == '\n') {
  302. continuation = 1;
  303. line += 2;
  304. } else if (*line == '#') {
  305. do {
  306. ++line;
  307. } while (*line && *line != '\n');
  308. if (*line == '\n')
  309. ++line;
  310. } else {
  311. ++line;
  312. }
  313. }
  314. if (*line == '\n') {
  315. cp = line++;
  316. } else {
  317. cp = line;
  318. }
  319. /* Now back cp up to be the last nonspace character */
  320. while (cp>val && TOR_ISSPACE(*(cp-1)))
  321. --cp;
  322. tor_assert(cp >= val);
  323. /* Now copy out and decode the value. */
  324. *value_out = tor_strndup(val, cp-val);
  325. if (continuation) {
  326. char *v_out, *v_in;
  327. v_out = v_in = *value_out;
  328. while (*v_in) {
  329. if (*v_in == '#') {
  330. do {
  331. ++v_in;
  332. } while (*v_in && *v_in != '\n');
  333. if (*v_in == '\n')
  334. ++v_in;
  335. } else if (v_in[0] == '\\' && v_in[1] == '\n') {
  336. v_in += 2;
  337. } else {
  338. *v_out++ = *v_in++;
  339. }
  340. }
  341. *v_out = '\0';
  342. }
  343. }
  344. if (*line == '#') {
  345. do {
  346. ++line;
  347. } while (*line && *line != '\n');
  348. }
  349. while (TOR_ISSPACE(*line)) ++line;
  350. return line;
  351. }