confparse.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  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-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file confparse.c
  8. *
  9. * \brief Back-end for parsing and generating key-value files, used to
  10. * implement the torrc file format and the state file.
  11. *
  12. * This module is used by config.c to parse and encode torrc
  13. * configuration files, and by statefile.c to parse and encode the
  14. * $DATADIR/state file.
  15. *
  16. * To use this module, its callers provide an instance of
  17. * config_format_t to describe the mappings from a set of configuration
  18. * options to a number of fields in a C structure. With this mapping,
  19. * the functions here can convert back and forth between the C structure
  20. * specified, and a linked list of key-value pairs.
  21. */
  22. #define CONFPARSE_PRIVATE
  23. #include "core/or/or.h"
  24. #include "app/config/confparse.h"
  25. #include "feature/nodelist/routerset.h"
  26. #include "lib/confmgt/unitparse.h"
  27. #include "lib/container/bitarray.h"
  28. #include "lib/encoding/confline.h"
  29. static void config_reset(const config_format_t *fmt, void *options,
  30. const config_var_t *var, int use_defaults);
  31. /** Allocate an empty configuration object of a given format type. */
  32. void *
  33. config_new(const config_format_t *fmt)
  34. {
  35. void *opts = tor_malloc_zero(fmt->size);
  36. *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
  37. CONFIG_CHECK(fmt, opts);
  38. return opts;
  39. }
  40. /*
  41. * Functions to parse config options
  42. */
  43. /** If <b>option</b> is an official abbreviation for a longer option,
  44. * return the longer option. Otherwise return <b>option</b>.
  45. * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
  46. * apply abbreviations that work for the config file and the command line.
  47. * If <b>warn_obsolete</b> is set, warn about deprecated names. */
  48. const char *
  49. config_expand_abbrev(const config_format_t *fmt, const char *option,
  50. int command_line, int warn_obsolete)
  51. {
  52. int i;
  53. if (! fmt->abbrevs)
  54. return option;
  55. for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
  56. /* Abbreviations are case insensitive. */
  57. if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
  58. (command_line || !fmt->abbrevs[i].commandline_only)) {
  59. if (warn_obsolete && fmt->abbrevs[i].warn) {
  60. log_warn(LD_CONFIG,
  61. "The configuration option '%s' is deprecated; "
  62. "use '%s' instead.",
  63. fmt->abbrevs[i].abbreviated,
  64. fmt->abbrevs[i].full);
  65. }
  66. /* Keep going through the list in case we want to rewrite it more.
  67. * (We could imagine recursing here, but I don't want to get the
  68. * user into an infinite loop if we craft our list wrong.) */
  69. option = fmt->abbrevs[i].full;
  70. }
  71. }
  72. return option;
  73. }
  74. /** If <b>key</b> is a deprecated configuration option, return the message
  75. * explaining why it is deprecated (which may be an empty string). Return NULL
  76. * if it is not deprecated. The <b>key</b> field must be fully expanded. */
  77. const char *
  78. config_find_deprecation(const config_format_t *fmt, const char *key)
  79. {
  80. if (BUG(fmt == NULL) || BUG(key == NULL))
  81. return NULL; // LCOV_EXCL_LINE
  82. if (fmt->deprecations == NULL)
  83. return NULL;
  84. const config_deprecation_t *d;
  85. for (d = fmt->deprecations; d->name; ++d) {
  86. if (!strcasecmp(d->name, key)) {
  87. return d->why_deprecated ? d->why_deprecated : "";
  88. }
  89. }
  90. return NULL;
  91. }
  92. /** As config_find_option, but return a non-const pointer. */
  93. config_var_t *
  94. config_find_option_mutable(config_format_t *fmt, const char *key)
  95. {
  96. int i;
  97. size_t keylen = strlen(key);
  98. if (!keylen)
  99. return NULL; /* if they say "--" on the command line, it's not an option */
  100. /* First, check for an exact (case-insensitive) match */
  101. for (i=0; fmt->vars[i].name; ++i) {
  102. if (!strcasecmp(key, fmt->vars[i].name)) {
  103. return &fmt->vars[i];
  104. }
  105. }
  106. /* If none, check for an abbreviated match */
  107. for (i=0; fmt->vars[i].name; ++i) {
  108. if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
  109. log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
  110. "Please use '%s' instead",
  111. key, fmt->vars[i].name);
  112. return &fmt->vars[i];
  113. }
  114. }
  115. /* Okay, unrecognized option */
  116. return NULL;
  117. }
  118. /** If <b>key</b> is a configuration option, return the corresponding const
  119. * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
  120. * warn, and return the corresponding const config_var_t. Otherwise return
  121. * NULL.
  122. */
  123. const config_var_t *
  124. config_find_option(const config_format_t *fmt, const char *key)
  125. {
  126. return config_find_option_mutable((config_format_t*)fmt, key);
  127. }
  128. /** Return the number of option entries in <b>fmt</b>. */
  129. static int
  130. config_count_options(const config_format_t *fmt)
  131. {
  132. int i;
  133. for (i=0; fmt->vars[i].name; ++i)
  134. ;
  135. return i;
  136. }
  137. /*
  138. * Functions to assign config options.
  139. */
  140. /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
  141. * with <b>c</b>-\>value and return 0, or return -1 if bad value.
  142. *
  143. * Called from config_assign_line() and option_reset().
  144. */
  145. static int
  146. config_assign_value(const config_format_t *fmt, void *options,
  147. config_line_t *c, char **msg)
  148. {
  149. int i, ok;
  150. const config_var_t *var;
  151. void *lvalue;
  152. CONFIG_CHECK(fmt, options);
  153. var = config_find_option(fmt, c->key);
  154. tor_assert(var);
  155. lvalue = STRUCT_VAR_P(options, var->var_offset);
  156. switch (var->type) {
  157. case CONFIG_TYPE_INT:
  158. case CONFIG_TYPE_POSINT:
  159. i = (int)tor_parse_long(c->value, 10,
  160. var->type==CONFIG_TYPE_INT ? INT_MIN : 0,
  161. INT_MAX,
  162. &ok, NULL);
  163. if (!ok) {
  164. tor_asprintf(msg,
  165. "Int keyword '%s %s' is malformed or out of bounds.",
  166. c->key, c->value);
  167. return -1;
  168. }
  169. *(int *)lvalue = i;
  170. break;
  171. case CONFIG_TYPE_UINT64: {
  172. uint64_t u64 = tor_parse_uint64(c->value, 10,
  173. 0, UINT64_MAX, &ok, NULL);
  174. if (!ok) {
  175. tor_asprintf(msg,
  176. "uint64 keyword '%s %s' is malformed or out of bounds.",
  177. c->key, c->value);
  178. return -1;
  179. }
  180. *(uint64_t *)lvalue = u64;
  181. break;
  182. }
  183. case CONFIG_TYPE_CSV_INTERVAL: {
  184. /* We used to have entire smartlists here. But now that all of our
  185. * download schedules use exponential backoff, only the first part
  186. * matters. */
  187. const char *comma = strchr(c->value, ',');
  188. const char *val = c->value;
  189. char *tmp = NULL;
  190. if (comma) {
  191. tmp = tor_strndup(c->value, comma - c->value);
  192. val = tmp;
  193. }
  194. i = config_parse_interval(val, &ok);
  195. if (!ok) {
  196. tor_asprintf(msg,
  197. "Interval '%s %s' is malformed or out of bounds.",
  198. c->key, c->value);
  199. tor_free(tmp);
  200. return -1;
  201. }
  202. *(int *)lvalue = i;
  203. tor_free(tmp);
  204. break;
  205. }
  206. case CONFIG_TYPE_INTERVAL: {
  207. i = config_parse_interval(c->value, &ok);
  208. if (!ok) {
  209. tor_asprintf(msg,
  210. "Interval '%s %s' is malformed or out of bounds.",
  211. c->key, c->value);
  212. return -1;
  213. }
  214. *(int *)lvalue = i;
  215. break;
  216. }
  217. case CONFIG_TYPE_MSEC_INTERVAL: {
  218. i = config_parse_msec_interval(c->value, &ok);
  219. if (!ok) {
  220. tor_asprintf(msg,
  221. "Msec interval '%s %s' is malformed or out of bounds.",
  222. c->key, c->value);
  223. return -1;
  224. }
  225. *(int *)lvalue = i;
  226. break;
  227. }
  228. case CONFIG_TYPE_MEMUNIT: {
  229. uint64_t u64 = config_parse_memunit(c->value, &ok);
  230. if (!ok) {
  231. tor_asprintf(msg,
  232. "Value '%s %s' is malformed or out of bounds.",
  233. c->key, c->value);
  234. return -1;
  235. }
  236. *(uint64_t *)lvalue = u64;
  237. break;
  238. }
  239. case CONFIG_TYPE_BOOL:
  240. i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
  241. if (!ok) {
  242. tor_asprintf(msg,
  243. "Boolean '%s %s' expects 0 or 1.",
  244. c->key, c->value);
  245. return -1;
  246. }
  247. *(int *)lvalue = i;
  248. break;
  249. case CONFIG_TYPE_AUTOBOOL:
  250. if (!strcasecmp(c->value, "auto"))
  251. *(int *)lvalue = -1;
  252. else if (!strcmp(c->value, "0"))
  253. *(int *)lvalue = 0;
  254. else if (!strcmp(c->value, "1"))
  255. *(int *)lvalue = 1;
  256. else {
  257. tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
  258. c->key, c->value);
  259. return -1;
  260. }
  261. break;
  262. case CONFIG_TYPE_STRING:
  263. case CONFIG_TYPE_FILENAME:
  264. tor_free(*(char **)lvalue);
  265. *(char **)lvalue = tor_strdup(c->value);
  266. break;
  267. case CONFIG_TYPE_DOUBLE:
  268. *(double *)lvalue = atof(c->value);
  269. break;
  270. case CONFIG_TYPE_ISOTIME:
  271. if (parse_iso_time(c->value, (time_t *)lvalue)) {
  272. tor_asprintf(msg,
  273. "Invalid time '%s' for keyword '%s'", c->value, c->key);
  274. return -1;
  275. }
  276. break;
  277. case CONFIG_TYPE_ROUTERSET:
  278. if (*(routerset_t**)lvalue) {
  279. routerset_free(*(routerset_t**)lvalue);
  280. }
  281. *(routerset_t**)lvalue = routerset_new();
  282. if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
  283. tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
  284. c->value, c->key);
  285. return -1;
  286. }
  287. break;
  288. case CONFIG_TYPE_CSV:
  289. if (*(smartlist_t**)lvalue) {
  290. SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
  291. smartlist_clear(*(smartlist_t**)lvalue);
  292. } else {
  293. *(smartlist_t**)lvalue = smartlist_new();
  294. }
  295. smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
  296. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  297. break;
  298. case CONFIG_TYPE_LINELIST:
  299. case CONFIG_TYPE_LINELIST_S:
  300. {
  301. config_line_t *lastval = *(config_line_t**)lvalue;
  302. if (lastval && lastval->fragile) {
  303. if (c->command != CONFIG_LINE_APPEND) {
  304. config_free_lines(lastval);
  305. *(config_line_t**)lvalue = NULL;
  306. } else {
  307. lastval->fragile = 0;
  308. }
  309. }
  310. config_line_append((config_line_t**)lvalue, c->key, c->value);
  311. }
  312. break;
  313. case CONFIG_TYPE_OBSOLETE:
  314. log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
  315. break;
  316. case CONFIG_TYPE_LINELIST_V:
  317. tor_asprintf(msg,
  318. "You may not provide a value for virtual option '%s'", c->key);
  319. return -1;
  320. // LCOV_EXCL_START
  321. default:
  322. tor_assert_unreached();
  323. break;
  324. // LCOV_EXCL_STOP
  325. }
  326. return 0;
  327. }
  328. /** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
  329. * to it will replace old ones. */
  330. static void
  331. config_mark_lists_fragile(const config_format_t *fmt, void *options)
  332. {
  333. int i;
  334. tor_assert(fmt);
  335. tor_assert(options);
  336. for (i = 0; fmt->vars[i].name; ++i) {
  337. const config_var_t *var = &fmt->vars[i];
  338. config_line_t *list;
  339. if (var->type != CONFIG_TYPE_LINELIST &&
  340. var->type != CONFIG_TYPE_LINELIST_V)
  341. continue;
  342. list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
  343. if (list)
  344. list->fragile = 1;
  345. }
  346. }
  347. void
  348. warn_deprecated_option(const char *what, const char *why)
  349. {
  350. const char *space = (why && strlen(why)) ? " " : "";
  351. log_warn(LD_CONFIG, "The %s option is deprecated, and will most likely "
  352. "be removed in a future version of Tor.%s%s (If you think this is "
  353. "a mistake, please let us know!)",
  354. what, space, why);
  355. }
  356. /** If <b>c</b> is a syntactically valid configuration line, update
  357. * <b>options</b> with its value and return 0. Otherwise return -1 for bad
  358. * key, -2 for bad value.
  359. *
  360. * If <b>clear_first</b> is set, clear the value first. Then if
  361. * <b>use_defaults</b> is set, set the value to the default.
  362. *
  363. * Called from config_assign().
  364. */
  365. static int
  366. config_assign_line(const config_format_t *fmt, void *options,
  367. config_line_t *c, unsigned flags,
  368. bitarray_t *options_seen, char **msg)
  369. {
  370. const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
  371. const unsigned clear_first = flags & CAL_CLEAR_FIRST;
  372. const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
  373. const config_var_t *var;
  374. CONFIG_CHECK(fmt, options);
  375. var = config_find_option(fmt, c->key);
  376. if (!var) {
  377. if (fmt->extra) {
  378. void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
  379. log_info(LD_CONFIG,
  380. "Found unrecognized option '%s'; saving it.", c->key);
  381. config_line_append((config_line_t**)lvalue, c->key, c->value);
  382. return 0;
  383. } else {
  384. tor_asprintf(msg,
  385. "Unknown option '%s'. Failing.", c->key);
  386. return -1;
  387. }
  388. }
  389. /* Put keyword into canonical case. */
  390. if (strcmp(var->name, c->key)) {
  391. tor_free(c->key);
  392. c->key = tor_strdup(var->name);
  393. }
  394. const char *deprecation_msg;
  395. if (warn_deprecations &&
  396. (deprecation_msg = config_find_deprecation(fmt, var->name))) {
  397. warn_deprecated_option(var->name, deprecation_msg);
  398. }
  399. if (!strlen(c->value)) {
  400. /* reset or clear it, then return */
  401. if (!clear_first) {
  402. if ((var->type == CONFIG_TYPE_LINELIST ||
  403. var->type == CONFIG_TYPE_LINELIST_S) &&
  404. c->command != CONFIG_LINE_CLEAR) {
  405. /* We got an empty linelist from the torrc or command line.
  406. As a special case, call this an error. Warn and ignore. */
  407. log_warn(LD_CONFIG,
  408. "Linelist option '%s' has no value. Skipping.", c->key);
  409. } else { /* not already cleared */
  410. config_reset(fmt, options, var, use_defaults);
  411. }
  412. }
  413. return 0;
  414. } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
  415. // XXXX This is unreachable, since a CLEAR line always has an
  416. // XXXX empty value.
  417. config_reset(fmt, options, var, use_defaults); // LCOV_EXCL_LINE
  418. }
  419. if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
  420. var->type != CONFIG_TYPE_LINELIST_S)) {
  421. /* We're tracking which options we've seen, and this option is not
  422. * supposed to occur more than once. */
  423. int var_index = (int)(var - fmt->vars);
  424. if (bitarray_is_set(options_seen, var_index)) {
  425. log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
  426. "value will be ignored.", var->name);
  427. }
  428. bitarray_set(options_seen, var_index);
  429. }
  430. if (config_assign_value(fmt, options, c, msg) < 0)
  431. return -2;
  432. return 0;
  433. }
  434. /** Restore the option named <b>key</b> in options to its default value.
  435. * Called from config_assign(). */
  436. STATIC void
  437. config_reset_line(const config_format_t *fmt, void *options,
  438. const char *key, int use_defaults)
  439. {
  440. const config_var_t *var;
  441. CONFIG_CHECK(fmt, options);
  442. var = config_find_option(fmt, key);
  443. if (!var)
  444. return; /* give error on next pass. */
  445. config_reset(fmt, options, var, use_defaults);
  446. }
  447. /** Return true iff value needs to be quoted and escaped to be used in
  448. * a configuration file. */
  449. static int
  450. config_value_needs_escape(const char *value)
  451. {
  452. if (*value == '\"')
  453. return 1;
  454. while (*value) {
  455. switch (*value)
  456. {
  457. case '\r':
  458. case '\n':
  459. case '#':
  460. /* Note: quotes and backspaces need special handling when we are using
  461. * quotes, not otherwise, so they don't trigger escaping on their
  462. * own. */
  463. return 1;
  464. default:
  465. if (!TOR_ISPRINT(*value))
  466. return 1;
  467. }
  468. ++value;
  469. }
  470. return 0;
  471. }
  472. /** Return newly allocated line or lines corresponding to <b>key</b> in the
  473. * configuration <b>options</b>. If <b>escape_val</b> is true and a
  474. * value needs to be quoted before it's put in a config file, quote and
  475. * escape that value. Return NULL if no such key exists. */
  476. config_line_t *
  477. config_get_assigned_option(const config_format_t *fmt, const void *options,
  478. const char *key, int escape_val)
  479. {
  480. const config_var_t *var;
  481. const void *value;
  482. config_line_t *result;
  483. tor_assert(options && key);
  484. CONFIG_CHECK(fmt, options);
  485. var = config_find_option(fmt, key);
  486. if (!var) {
  487. log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
  488. return NULL;
  489. }
  490. value = STRUCT_VAR_P(options, var->var_offset);
  491. result = tor_malloc_zero(sizeof(config_line_t));
  492. result->key = tor_strdup(var->name);
  493. switch (var->type)
  494. {
  495. case CONFIG_TYPE_STRING:
  496. case CONFIG_TYPE_FILENAME:
  497. if (*(char**)value) {
  498. result->value = tor_strdup(*(char**)value);
  499. } else {
  500. tor_free(result->key);
  501. tor_free(result);
  502. return NULL;
  503. }
  504. break;
  505. case CONFIG_TYPE_ISOTIME:
  506. if (*(time_t*)value) {
  507. result->value = tor_malloc(ISO_TIME_LEN+1);
  508. format_iso_time(result->value, *(time_t*)value);
  509. } else {
  510. tor_free(result->key);
  511. tor_free(result);
  512. }
  513. escape_val = 0; /* Can't need escape. */
  514. break;
  515. case CONFIG_TYPE_CSV_INTERVAL:
  516. case CONFIG_TYPE_INTERVAL:
  517. case CONFIG_TYPE_MSEC_INTERVAL:
  518. case CONFIG_TYPE_POSINT:
  519. case CONFIG_TYPE_INT:
  520. /* This means every or_options_t uint or bool element
  521. * needs to be an int. Not, say, a uint16_t or char. */
  522. tor_asprintf(&result->value, "%d", *(int*)value);
  523. escape_val = 0; /* Can't need escape. */
  524. break;
  525. case CONFIG_TYPE_UINT64: /* Fall through */
  526. case CONFIG_TYPE_MEMUNIT:
  527. tor_asprintf(&result->value, "%"PRIu64,
  528. (*(uint64_t*)value));
  529. escape_val = 0; /* Can't need escape. */
  530. break;
  531. case CONFIG_TYPE_DOUBLE:
  532. tor_asprintf(&result->value, "%f", *(double*)value);
  533. escape_val = 0; /* Can't need escape. */
  534. break;
  535. case CONFIG_TYPE_AUTOBOOL:
  536. if (*(int*)value == -1) {
  537. result->value = tor_strdup("auto");
  538. escape_val = 0;
  539. break;
  540. }
  541. /* fall through */
  542. case CONFIG_TYPE_BOOL:
  543. result->value = tor_strdup(*(int*)value ? "1" : "0");
  544. escape_val = 0; /* Can't need escape. */
  545. break;
  546. case CONFIG_TYPE_ROUTERSET:
  547. result->value = routerset_to_string(*(routerset_t**)value);
  548. break;
  549. case CONFIG_TYPE_CSV:
  550. if (*(smartlist_t**)value)
  551. result->value =
  552. smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
  553. else
  554. result->value = tor_strdup("");
  555. break;
  556. case CONFIG_TYPE_OBSOLETE:
  557. log_fn(LOG_INFO, LD_CONFIG,
  558. "You asked me for the value of an obsolete config option '%s'.",
  559. key);
  560. tor_free(result->key);
  561. tor_free(result);
  562. return NULL;
  563. case CONFIG_TYPE_LINELIST_S:
  564. tor_free(result->key);
  565. tor_free(result);
  566. result = config_lines_dup_and_filter(*(const config_line_t **)value,
  567. key);
  568. break;
  569. case CONFIG_TYPE_LINELIST:
  570. case CONFIG_TYPE_LINELIST_V:
  571. tor_free(result->key);
  572. tor_free(result);
  573. result = config_lines_dup(*(const config_line_t**)value);
  574. break;
  575. // LCOV_EXCL_START
  576. default:
  577. tor_free(result->key);
  578. tor_free(result);
  579. log_warn(LD_BUG,"Unknown type %d for known key '%s'",
  580. var->type, key);
  581. return NULL;
  582. // LCOV_EXCL_STOP
  583. }
  584. if (escape_val) {
  585. config_line_t *line;
  586. for (line = result; line; line = line->next) {
  587. if (line->value && config_value_needs_escape(line->value)) {
  588. char *newval = esc_for_log(line->value);
  589. tor_free(line->value);
  590. line->value = newval;
  591. }
  592. }
  593. }
  594. return result;
  595. }
  596. /** Iterate through the linked list of requested options <b>list</b>.
  597. * For each item, convert as appropriate and assign to <b>options</b>.
  598. * If an item is unrecognized, set *msg and return -1 immediately,
  599. * else return 0 for success.
  600. *
  601. * If <b>clear_first</b>, interpret config options as replacing (not
  602. * extending) their previous values. If <b>clear_first</b> is set,
  603. * then <b>use_defaults</b> to decide if you set to defaults after
  604. * clearing, or make the value 0 or NULL.
  605. *
  606. * Here are the use cases:
  607. * 1. A non-empty AllowInvalid line in your torrc. Appends to current
  608. * if linelist, replaces current if csv.
  609. * 2. An empty AllowInvalid line in your torrc. Should clear it.
  610. * 3. "RESETCONF AllowInvalid" sets it to default.
  611. * 4. "SETCONF AllowInvalid" makes it NULL.
  612. * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
  613. *
  614. * Use_defaults Clear_first
  615. * 0 0 "append"
  616. * 1 0 undefined, don't use
  617. * 0 1 "set to null first"
  618. * 1 1 "set to defaults first"
  619. * Return 0 on success, -1 on bad key, -2 on bad value.
  620. *
  621. * As an additional special case, if a LINELIST config option has
  622. * no value and clear_first is 0, then warn and ignore it.
  623. */
  624. /*
  625. There are three call cases for config_assign() currently.
  626. Case one: Torrc entry
  627. options_init_from_torrc() calls config_assign(0, 0)
  628. calls config_assign_line(0, 0).
  629. if value is empty, calls config_reset(0) and returns.
  630. calls config_assign_value(), appends.
  631. Case two: setconf
  632. options_trial_assign() calls config_assign(0, 1)
  633. calls config_reset_line(0)
  634. calls config_reset(0)
  635. calls option_clear().
  636. calls config_assign_line(0, 1).
  637. if value is empty, returns.
  638. calls config_assign_value(), appends.
  639. Case three: resetconf
  640. options_trial_assign() calls config_assign(1, 1)
  641. calls config_reset_line(1)
  642. calls config_reset(1)
  643. calls option_clear().
  644. calls config_assign_value(default)
  645. calls config_assign_line(1, 1).
  646. returns.
  647. */
  648. int
  649. config_assign(const config_format_t *fmt, void *options, config_line_t *list,
  650. unsigned config_assign_flags, char **msg)
  651. {
  652. config_line_t *p;
  653. bitarray_t *options_seen;
  654. const int n_options = config_count_options(fmt);
  655. const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
  656. const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
  657. CONFIG_CHECK(fmt, options);
  658. /* pass 1: normalize keys */
  659. for (p = list; p; p = p->next) {
  660. const char *full = config_expand_abbrev(fmt, p->key, 0, 1);
  661. if (strcmp(full,p->key)) {
  662. tor_free(p->key);
  663. p->key = tor_strdup(full);
  664. }
  665. }
  666. /* pass 2: if we're reading from a resetting source, clear all
  667. * mentioned config options, and maybe set to their defaults. */
  668. if (clear_first) {
  669. for (p = list; p; p = p->next)
  670. config_reset_line(fmt, options, p->key, use_defaults);
  671. }
  672. options_seen = bitarray_init_zero(n_options);
  673. /* pass 3: assign. */
  674. while (list) {
  675. int r;
  676. if ((r=config_assign_line(fmt, options, list, config_assign_flags,
  677. options_seen, msg))) {
  678. bitarray_free(options_seen);
  679. return r;
  680. }
  681. list = list->next;
  682. }
  683. bitarray_free(options_seen);
  684. /** Now we're done assigning a group of options to the configuration.
  685. * Subsequent group assignments should _replace_ linelists, not extend
  686. * them. */
  687. config_mark_lists_fragile(fmt, options);
  688. return 0;
  689. }
  690. /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
  691. * Called from config_reset() and config_free(). */
  692. static void
  693. config_clear(const config_format_t *fmt, void *options,
  694. const config_var_t *var)
  695. {
  696. void *lvalue = STRUCT_VAR_P(options, var->var_offset);
  697. (void)fmt; /* unused */
  698. switch (var->type) {
  699. case CONFIG_TYPE_STRING:
  700. case CONFIG_TYPE_FILENAME:
  701. tor_free(*(char**)lvalue);
  702. break;
  703. case CONFIG_TYPE_DOUBLE:
  704. *(double*)lvalue = 0.0;
  705. break;
  706. case CONFIG_TYPE_ISOTIME:
  707. *(time_t*)lvalue = 0;
  708. break;
  709. case CONFIG_TYPE_CSV_INTERVAL:
  710. case CONFIG_TYPE_INTERVAL:
  711. case CONFIG_TYPE_MSEC_INTERVAL:
  712. case CONFIG_TYPE_POSINT:
  713. case CONFIG_TYPE_INT:
  714. case CONFIG_TYPE_BOOL:
  715. *(int*)lvalue = 0;
  716. break;
  717. case CONFIG_TYPE_AUTOBOOL:
  718. *(int*)lvalue = -1;
  719. break;
  720. case CONFIG_TYPE_UINT64:
  721. case CONFIG_TYPE_MEMUNIT:
  722. *(uint64_t*)lvalue = 0;
  723. break;
  724. case CONFIG_TYPE_ROUTERSET:
  725. if (*(routerset_t**)lvalue) {
  726. routerset_free(*(routerset_t**)lvalue);
  727. *(routerset_t**)lvalue = NULL;
  728. }
  729. break;
  730. case CONFIG_TYPE_CSV:
  731. if (*(smartlist_t**)lvalue) {
  732. SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
  733. smartlist_free(*(smartlist_t **)lvalue);
  734. *(smartlist_t **)lvalue = NULL;
  735. }
  736. break;
  737. case CONFIG_TYPE_LINELIST:
  738. case CONFIG_TYPE_LINELIST_S:
  739. config_free_lines(*(config_line_t **)lvalue);
  740. *(config_line_t **)lvalue = NULL;
  741. break;
  742. case CONFIG_TYPE_LINELIST_V:
  743. /* handled by linelist_s. */
  744. break;
  745. case CONFIG_TYPE_OBSOLETE:
  746. break;
  747. }
  748. }
  749. /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
  750. * <b>use_defaults</b>, set it to its default value.
  751. * Called by config_init() and option_reset_line() and option_assign_line(). */
  752. static void
  753. config_reset(const config_format_t *fmt, void *options,
  754. const config_var_t *var, int use_defaults)
  755. {
  756. config_line_t *c;
  757. char *msg = NULL;
  758. CONFIG_CHECK(fmt, options);
  759. config_clear(fmt, options, var); /* clear it first */
  760. if (!use_defaults)
  761. return; /* all done */
  762. if (var->initvalue) {
  763. c = tor_malloc_zero(sizeof(config_line_t));
  764. c->key = tor_strdup(var->name);
  765. c->value = tor_strdup(var->initvalue);
  766. if (config_assign_value(fmt, options, c, &msg) < 0) {
  767. // LCOV_EXCL_START
  768. log_warn(LD_BUG, "Failed to assign default: %s", msg);
  769. tor_free(msg); /* if this happens it's a bug */
  770. // LCOV_EXCL_STOP
  771. }
  772. config_free_lines(c);
  773. }
  774. }
  775. /** Release storage held by <b>options</b>. */
  776. void
  777. config_free_(const config_format_t *fmt, void *options)
  778. {
  779. int i;
  780. if (!options)
  781. return;
  782. tor_assert(fmt);
  783. for (i=0; fmt->vars[i].name; ++i)
  784. config_clear(fmt, options, &(fmt->vars[i]));
  785. if (fmt->extra) {
  786. config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
  787. config_free_lines(*linep);
  788. *linep = NULL;
  789. }
  790. tor_free(options);
  791. }
  792. /** Return true iff the option <b>name</b> has the same value in <b>o1</b>
  793. * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
  794. */
  795. int
  796. config_is_same(const config_format_t *fmt,
  797. const void *o1, const void *o2,
  798. const char *name)
  799. {
  800. config_line_t *c1, *c2;
  801. int r = 1;
  802. CONFIG_CHECK(fmt, o1);
  803. CONFIG_CHECK(fmt, o2);
  804. c1 = config_get_assigned_option(fmt, o1, name, 0);
  805. c2 = config_get_assigned_option(fmt, o2, name, 0);
  806. r = config_lines_eq(c1, c2);
  807. config_free_lines(c1);
  808. config_free_lines(c2);
  809. return r;
  810. }
  811. /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
  812. void *
  813. config_dup(const config_format_t *fmt, const void *old)
  814. {
  815. void *newopts;
  816. int i;
  817. config_line_t *line;
  818. newopts = config_new(fmt);
  819. for (i=0; fmt->vars[i].name; ++i) {
  820. if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
  821. continue;
  822. if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
  823. continue;
  824. line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0);
  825. if (line) {
  826. char *msg = NULL;
  827. if (config_assign(fmt, newopts, line, 0, &msg) < 0) {
  828. // LCOV_EXCL_START
  829. log_err(LD_BUG, "config_get_assigned_option() generated "
  830. "something we couldn't config_assign(): %s", msg);
  831. tor_free(msg);
  832. tor_assert(0);
  833. // LCOV_EXCL_STOP
  834. }
  835. }
  836. config_free_lines(line);
  837. }
  838. return newopts;
  839. }
  840. /** Set all vars in the configuration object <b>options</b> to their default
  841. * values. */
  842. void
  843. config_init(const config_format_t *fmt, void *options)
  844. {
  845. int i;
  846. const config_var_t *var;
  847. CONFIG_CHECK(fmt, options);
  848. for (i=0; fmt->vars[i].name; ++i) {
  849. var = &fmt->vars[i];
  850. if (!var->initvalue)
  851. continue; /* defaults to NULL or 0 */
  852. config_reset(fmt, options, var, 1);
  853. }
  854. }
  855. /** Allocate and return a new string holding the written-out values of the vars
  856. * in 'options'. If 'minimal', do not write out any default-valued vars.
  857. * Else, if comment_defaults, write default values as comments.
  858. */
  859. char *
  860. config_dump(const config_format_t *fmt, const void *default_options,
  861. const void *options, int minimal,
  862. int comment_defaults)
  863. {
  864. smartlist_t *elements;
  865. const void *defaults = default_options;
  866. void *defaults_tmp = NULL;
  867. config_line_t *line, *assigned;
  868. char *result;
  869. int i;
  870. char *msg = NULL;
  871. if (defaults == NULL) {
  872. defaults = defaults_tmp = config_new(fmt);
  873. config_init(fmt, defaults_tmp);
  874. }
  875. /* XXX use a 1 here so we don't add a new log line while dumping */
  876. if (default_options == NULL) {
  877. if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) {
  878. // LCOV_EXCL_START
  879. log_err(LD_BUG, "Failed to validate default config: %s", msg);
  880. tor_free(msg);
  881. tor_assert(0);
  882. // LCOV_EXCL_STOP
  883. }
  884. }
  885. elements = smartlist_new();
  886. for (i=0; fmt->vars[i].name; ++i) {
  887. int comment_option = 0;
  888. if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
  889. fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
  890. continue;
  891. /* Don't save 'hidden' control variables. */
  892. if (!strcmpstart(fmt->vars[i].name, "__"))
  893. continue;
  894. if (minimal && config_is_same(fmt, options, defaults, fmt->vars[i].name))
  895. continue;
  896. else if (comment_defaults &&
  897. config_is_same(fmt, options, defaults, fmt->vars[i].name))
  898. comment_option = 1;
  899. line = assigned =
  900. config_get_assigned_option(fmt, options, fmt->vars[i].name, 1);
  901. for (; line; line = line->next) {
  902. if (!strcmpstart(line->key, "__")) {
  903. /* This check detects "hidden" variables inside LINELIST_V structures.
  904. */
  905. continue;
  906. }
  907. smartlist_add_asprintf(elements, "%s%s %s\n",
  908. comment_option ? "# " : "",
  909. line->key, line->value);
  910. }
  911. config_free_lines(assigned);
  912. }
  913. if (fmt->extra) {
  914. line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
  915. for (; line; line = line->next) {
  916. smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
  917. }
  918. }
  919. result = smartlist_join_strings(elements, "", 0, NULL);
  920. SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
  921. smartlist_free(elements);
  922. if (defaults_tmp) {
  923. fmt->free_fn(defaults_tmp);
  924. }
  925. return result;
  926. }