config.c 69.9 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
3
/* Copyright 2001 Matej Pfajfar.
 * Copyright 2001-2004 Roger Dingledine.
 * Copyright 2004 Roger Dingledine, Nick Mathewson. */
4
5
6
/* See LICENSE for licensing information */
/* $Id$ */

Nick Mathewson's avatar
Nick Mathewson committed
7
8
9
10
11
12
13
/**
 * /file config.c
 *
 * /brief Code to parse and interpret configuration files.
 *
 **/

Roger Dingledine's avatar
Roger Dingledine committed
14
#include "or.h"
15
16
17
#ifdef MS_WINDOWS
#include <shlobj.h>
#endif
Roger Dingledine's avatar
Roger Dingledine committed
18

Nick Mathewson's avatar
Nick Mathewson committed
19
20
/** Enumeration of types which option values can take */
typedef enum config_type_t {
21
22
  CONFIG_TYPE_STRING = 0,   /**< An arbitrary string. */
  CONFIG_TYPE_UINT,         /**< A non-negative integer less than MAX_INT */
23
24
  CONFIG_TYPE_INTERVAL,     /**< A number of seconds, with optional units*/
  CONFIG_TYPE_MEMUNIT,      /**< A number of bytes, with optional units*/
25
26
27
28
29
  CONFIG_TYPE_DOUBLE,       /**< A floating-point value */
  CONFIG_TYPE_BOOL,         /**< A boolean value, expressed as 0 or 1. */
  CONFIG_TYPE_CSV,          /**< A list of strings, separated by commas and optional
                              * whitespace. */
  CONFIG_TYPE_LINELIST,     /**< Uninterpreted config lines */
30
31
32
33
34
  CONFIG_TYPE_LINELIST_S,   /**< Uninterpreted, context-sensitive config lines,
                             * mixed with other keywords. */
  CONFIG_TYPE_LINELIST_V,   /**< Catch-all "virtual" option to summarize
                             * context-sensitive config lines when fetching.
                             */
35
  CONFIG_TYPE_OBSOLETE,     /**< Obsolete (ignored) option. */
Nick Mathewson's avatar
Nick Mathewson committed
36
} config_type_t;
37

Nick Mathewson's avatar
Nick Mathewson committed
38
/* An abbreviation for a configuration option allowed on the command line */
39
typedef struct config_abbrev_t {
40
41
  const char *abbreviated;
  const char *full;
42
  int commandline_only;
43
44
} config_abbrev_t;

45
46
47
48
/* Handy macro for declaring "In the config file or on the command line,
 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
#define PLURAL(tok) { #tok, #tok "s", 0 }

Nick Mathewson's avatar
Nick Mathewson committed
49
/* A list of command-line abbreviations. */
50
static config_abbrev_t config_abbrevs[] = {
51
  PLURAL(ExitNode),
52
  PLURAL(EntryNode),
53
54
55
56
57
58
  PLURAL(ExcludeNode),
  PLURAL(FirewallPort),
  PLURAL(HiddenServiceNode),
  PLURAL(HiddenServiceExcludeNode),
  PLURAL(RendNode),
  PLURAL(RendExcludeNode),
59
60
  PLURAL(StrictEntryNode),
  PLURAL(StrictExitNode),
61
  { "l", "Log", 1},
62
63
  { "BandwidthRateBytes", "BandwidthRate", 0},
  { "BandwidthBurstBytes", "BandwidthBurst", 0},
64
  { "DirFetchPostPeriod", "DirFetchPeriod", 0},
65
  { NULL, NULL , 0},
66
};
67
#undef PLURAL
68

69
/** A variable allowed in the configuration file or on the command line. */
70
typedef struct config_var_t {
71
72
73
74
  const char *name; /**< The full keyword (case insensitive). */
  config_type_t type; /**< How to interpret the type and turn it into a value. */
  off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
  const char *initvalue; /**< String (or null) describing initial value. */
75
76
} config_var_t;

Nick Mathewson's avatar
Nick Mathewson committed
77
/** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
Nick Mathewson's avatar
Nick Mathewson committed
78
#define STRUCT_OFFSET(tp, member) ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
Nick Mathewson's avatar
Nick Mathewson committed
79
80
81
82
/** An entry for config_vars: "The option <b>name</b> has type
 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
 * or_options_t.<b>member</b>"
 */
83
84
#define VAR(name,conftype,member,initvalue) \
  { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), initvalue }
Nick Mathewson's avatar
Nick Mathewson committed
85
/** An entry for config_vars: "The option <b>name</b> is obsolete." */
86
#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
87

Nick Mathewson's avatar
Nick Mathewson committed
88
89
90
91
/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
92
static config_var_t config_vars[] = {
93
  VAR("Address",             STRING,   Address,              NULL),
94
  VAR("AccountingStart",     STRING,   AccountingStart,      NULL),
95
  VAR("AllowUnverifiedNodes",CSV,      AllowUnverifiedNodes, "middle,rendezvous"),
96
  VAR("AuthoritativeDirectory",BOOL,   AuthoritativeDir,     "0"),
97
98
  VAR("BandwidthRate",       MEMUNIT,  BandwidthRate,        "780 KB"),
  VAR("BandwidthBurst",      MEMUNIT,  BandwidthBurst,       "48 MB"),
99
100
  VAR("ClientOnly",          BOOL,     ClientOnly,           "0"),
  VAR("ContactInfo",         STRING,   ContactInfo,          NULL),
101
  VAR("ControlPort",         UINT,     ControlPort,          "0"),
102
  VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
103
104
105
106
  VAR("DebugLogFile",        STRING,   DebugLogFile,         NULL),
  VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
  VAR("DirPort",             UINT,     DirPort,              "0"),
  VAR("DirBindAddress",      LINELIST, DirBindAddress,       NULL),
107
  VAR("DirFetchPeriod",      INTERVAL, DirFetchPeriod,       "1 hour"),
108
  VAR("DirPostPeriod",       INTERVAL, DirPostPeriod,        "10 minutes"),
109
  VAR("RendPostPeriod",      INTERVAL, RendPostPeriod,       "10 minutes"),
110
111
112
113
114
115
116
117
118
  VAR("DirPolicy",           LINELIST, DirPolicy,            NULL),
  VAR("DirServer",           LINELIST, DirServers,           NULL),
  VAR("ExitNodes",           STRING,   ExitNodes,            NULL),
  VAR("EntryNodes",          STRING,   EntryNodes,           NULL),
  VAR("StrictExitNodes",     BOOL,     StrictExitNodes,      "0"),
  VAR("StrictEntryNodes",    BOOL,     StrictEntryNodes,     "0"),
  VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
  VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
  VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
119
  VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
120
121
122
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
  VAR("Group",               STRING,   Group,                NULL),
123
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
124
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
125
126
127
128
129
  VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
  VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServicePort",   LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceNodes",  LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
130
  VAR("IgnoreVersion",       BOOL,     IgnoreVersion,        "0"),
131
  VAR("KeepalivePeriod",     INTERVAL, KeepalivePeriod,      "5 minutes"),
132
133
134
  VAR("Log",                 LINELIST, Logs,                 NULL),
  VAR("LogLevel",            LINELIST_S, OldLogOptions,      NULL),
  VAR("LogFile",             LINELIST_S, OldLogOptions,      NULL),
135
  OBSOLETE("LinkPadding"),
136
137
  VAR("MaxConn",             UINT,     MaxConn,              "1024"),
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
138
  VAR("MonthlyAccountingStart",UINT,   _MonthlyAccountingStart,"0"),
139
140
  VAR("AccountingMaxKB",     UINT,     _AccountingMaxKB,     "0"),
  VAR("AccountingMax",       MEMUNIT,   AccountingMax,        "0 bytes"),
141
  VAR("Nickname",            STRING,   Nickname,             NULL),
142
  VAR("NewCircuitPeriod",    INTERVAL, NewCircuitPeriod,     "30 seconds"),
143
144
145
146
147
148
149
  VAR("NumCpus",             UINT,     NumCpus,              "1"),
  VAR("ORPort",              UINT,     ORPort,               "0"),
  VAR("ORBindAddress",       LINELIST, ORBindAddress,        NULL),
  VAR("OutboundBindAddress", STRING,   OutboundBindAddress,  NULL),
  VAR("PidFile",             STRING,   PidFile,              NULL),
  VAR("PathlenCoinWeight",   DOUBLE,   PathlenCoinWeight,    "0.3"),
  VAR("RedirectExit",        LINELIST, RedirectExit,         NULL),
150
  OBSOLETE("RouterFile"),
151
152
153
154
155
  VAR("RunAsDaemon",         BOOL,     RunAsDaemon,          "0"),
  VAR("RunTesting",          BOOL,     RunTesting,           "0"),
  VAR("RecommendedVersions", LINELIST, RecommendedVersions,  NULL),
  VAR("RendNodes",           STRING,   RendNodes,            NULL),
  VAR("RendExcludeNodes",    STRING,   RendExcludeNodes,     NULL),
156
  VAR("SocksPort",           UINT,     SocksPort,            "9050"),
157
158
  VAR("SocksBindAddress",    LINELIST, SocksBindAddress,     NULL),
  VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),
159
  VAR("StatusFetchPeriod",   INTERVAL, StatusFetchPeriod,    "20 minutes"),
160
  VAR("SysLog",              LINELIST_S, OldLogOptions,      NULL),
161
  OBSOLETE("TrafficShaping"),
162
163
  VAR("User",                STRING,   User,                 NULL),
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
164
165
166
167
};
#undef VAR
#undef OBSOLETE

Nick Mathewson's avatar
Nick Mathewson committed
168
/** Largest allowed config line */
169
#define CONFIG_LINE_T_MAXLEN 4096
170

171
172
static void option_reset(or_options_t *options, config_var_t *var);
static void options_free(or_options_t *options);
173
static int option_is_same(or_options_t *o1, or_options_t *o2,const char *name);
174
175
176
177
178
static or_options_t *options_dup(or_options_t *old);
static int options_validate(or_options_t *options);
static int options_transition_allowed(or_options_t *old, or_options_t *new);
static int check_nickname_list(const char *lst, const char *name);

179
static int parse_dir_server_line(const char *line, int validate_only);
180
static int parse_redirect_line(smartlist_t *result,
Roger Dingledine's avatar
Roger Dingledine committed
181
                               struct config_line_t *line);
182
183
184
185
186
187
188
189
190
static int parse_log_severity_range(const char *range, int *min_out,
                                    int *max_out);
static int convert_log_option(or_options_t *options,
                              struct config_line_t *level_opt,
                              struct config_line_t *file_opt, int isDaemon);
static int add_single_log_option(or_options_t *options, int minSeverity,
                                 int maxSeverity,
                                 const char *type, const char *fname);
static int normalize_log_options(or_options_t *options);
191
static int validate_data_directory(or_options_t *options);
192
static int write_configuration_file(const char *fname, or_options_t *options);
193

194
195
196
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);

197
198
199
200
201
202
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
static or_options_t *global_options=NULL;
Roger Dingledine's avatar
Roger Dingledine committed
203
/** Name of most recently read torrc file. */
204
static char *config_fname = NULL;
205

206
207
208
/** Return the currently configured options. */
or_options_t *
get_options(void) {
209
210
211
  tor_assert(global_options);
  return global_options;
}
212

Roger Dingledine's avatar
Roger Dingledine committed
213
214
215
/** Change the current global options to contain <b>new_val</b> instead
 * of their current value; free the old value as necessary.  Where
 * <b>new_val</b> is different from the old value, update the process to
216
217
218
219
220
221
222
223
224
225
226
227
228
 * use the new value instead.
 *
 * Note 1: <b>new_val</b> must have previously been validated with
 * options_validate(), or Tor may freak out and exit.
 *
 * Note 2: We haven't moved all the "act on new configuration" logic
 * here yet.  Some is still in do_hup() and other places.
 */
void
set_options(or_options_t *new_val) {
  if (global_options)
    options_free(global_options);
  global_options = new_val;
229
230
231
232
233
234
235
236
237
238
}

/** Fetch the active option list, and take actions based on it. All
 * of the things we do should survive being done repeatedly.
 * Return 0 if all goes well, return -1 if it's time to die.
 */
int
options_act(void) {
  struct config_line_t *cl;
  or_options_t *options = get_options();
239
240

  clear_trusted_dir_servers();
241
  for (cl = options->DirServers; cl; cl = cl->next) {
242
243
244
    if (parse_dir_server_line(cl->value, 0)<0) {
      log_fn(LOG_ERR,
             "Previously validated DirServer line could not be added!");
245
      return -1;
246
247
248
    }
  }

249
  if (rend_config_services(options, 0)<0) {
250
251
    log_fn(LOG_ERR,
           "Previously validated hidden services line could not be added!");
252
    return -1;
253
  }
254
255

  /* Setuid/setgid as appropriate */
256
257
  if (options->User || options->Group) {
    if (switch_id(options->User, options->Group) != 0) {
258
259
260
261
262
      return -1;
    }
  }

  /* Ensure data directory is private; create if possible. */
263
  if (check_private_dir(options->DataDirectory, CPD_CREATE) != 0) {
264
    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
265
           options->DataDirectory);
266
267
268
269
270
271
272
273
    return -1;
  }

  /* Bail out at this point if we're not going to be a server: we want
   * to not fork, and to log stuff to stderr. */
  if (options->command != CMD_RUN_TOR)
    return 0;

274
  mark_logs_temp(); /* Close current logs once new logs are open. */
275
  if (config_init_logs(options, 0)<0) /* Configure the log(s) */
276
277
278
279
    return -1;
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
280
  add_callback_log(LOG_NOTICE, LOG_ERR, control_event_logmsg);
281

282
283
284
  if (set_max_file_descriptors(options->MaxConn) < 0)
    return -1;

285
286
287
288
289
290
291
292
293
  {
    smartlist_t *sl = smartlist_create();
    for (cl = options->RedirectExit; cl; cl = cl->next) {
      if (parse_redirect_line(sl, cl)<0)
        return -1;
    }
    set_exit_redirects(sl);
  }

294
  /* Start backgrounding the process, if requested. */
295

296
297
298
  /* XXXX009 We once had a reason to separate start_daemon and finish_daemon:
   *    It let us have the parent process stick around until we were sure Tor
   *    was started.  Should we make start_daemon get called earlier? -NM */
299
  if (options->RunAsDaemon) {
300
    start_daemon(options->DataDirectory);
301
302
303
  }

  /* Finish backgrounding the process */
304
  if (options->RunAsDaemon) {
305
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
306
307
308
309
310
    finish_daemon();
  }

  /* Write our pid to the pid file. If we do not have write permissions we
   * will log a warning */
311
  if (options->PidFile)
312
313
    write_pidfile(options->PidFile);

314
315
316
317
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();

318
319
  init_cookie_authentication(options->CookieAuthentication);

320
321
322
323
324
325
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
    log_fn(LOG_ERR,"Error reloading rendezvous service keys");
    return -1;
  }

326
  /* Set up accounting */
327
328
329
330
  if (accounting_parse_options(options, 0)<0) {
    log_fn(LOG_ERR,"Error in accouting options");
    return -1;
  }
331
  if (accounting_is_enabled(options))
332
333
    configure_accounting(time(NULL));

334
  if (retry_all_listeners(1) < 0) {
335
336
337
338
    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
    return -1;
  }

339
340
341
342
343
344
#if 0
  {
    char *smin, *smax;
    smin = config_dump_options(options, 1);
    smax = config_dump_options(options, 0);
    log_fn(LOG_DEBUG, "These are our options:\n%s",smax);
Roger Dingledine's avatar
Roger Dingledine committed
345
    log_fn(LOG_DEBUG, "We changed these options:\n%s",smin);
346
347
348
349
350
    tor_free(smin);
    tor_free(smax);
  }
#endif

351
352
353
354
355
356
  /* Since our options changed, we might need to regenerate and upload our
   * server descriptor.  (We could probably be more clever about only calling
   * this when something significant changed.)
   */
  mark_my_descriptor_dirty();

357
  return 0;
358
359
360
361
362
363
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
364
/** If <b>option</b> is an official abbreviation for a longer option,
365
366
367
 * return the longer option.  Otherwise return <b>option</b>.
 * If <b>command_line</b> is set, apply all abbreviations.  Otherwise, only
 * apply abbreviations that work for the config file and the command line. */
368
static const char *
369
expand_abbrev(const char *option, int command_line)
370
371
372
373
{
  int i;
  for (i=0; config_abbrevs[i].abbreviated; ++i) {
    /* Abbreviations aren't casei. */
374
    if (!strcasecmp(option,config_abbrevs[i].abbreviated) &&
375
        (command_line || !config_abbrevs[i].commandline_only)) {
376
      return config_abbrevs[i].full;
377
    }
378
379
380
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
381

Nick Mathewson's avatar
Nick Mathewson committed
382
/** Helper: Read a list of configuration options from the command line. */
383
384
385
static struct config_line_t *
config_get_commandlines(int argc, char **argv)
{
386
387
  struct config_line_t *new;
  struct config_line_t *front = NULL;
388
389
390
  char *s;
  int i = 1;

391
  while (i < argc-1) {
392
393
394
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
395
      continue;
396
397
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
398
      continue;
399
400
    }

401
    new = tor_malloc(sizeof(struct config_line_t));
402
    s = argv[i];
403

404
    while (*s == '-')
405
      s++;
406

407
    new->key = tor_strdup(expand_abbrev(s, 1));
408
    new->value = tor_strdup(argv[i+1]);
409
410

    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
411
        new->key, new->value);
412
413
414
415
416
417
418
    new->next = front;
    front = new;
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
419
420
/** Helper: allocate a new configuration option mapping 'key' to 'val',
 * prepend it to 'front', and return the newly allocated config_line_t */
421
struct config_line_t *
422
423
424
425
426
config_line_prepend(struct config_line_t *front,
                    const char *key,
                    const char *val)
{
  struct config_line_t *newline;
427

428
429
430
431
432
433
434
  newline = tor_malloc(sizeof(struct config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
  newline->next = front;
  return newline;
}

435
436
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
437
438
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
439
440
int
config_get_lines(char *string, struct config_line_t **result)
441
{
442
443
  struct config_line_t *list = NULL;
  char *k, *v;
444

445
446
447
448
449
450
451
452
453
  do {
    string = parse_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      return -1;
    }
    if (k && v)
      list = config_line_prepend(list, k, v);
  } while (*string);
454

455
  *result = list;
456
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
457
458
}

Nick Mathewson's avatar
Nick Mathewson committed
459
460
461
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
462
void
463
464
config_free_lines(struct config_line_t *front)
{
465
  struct config_line_t *tmp;
466

467
  while (front) {
468
469
470
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
471
472
473
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
474
475
476
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
477
478
479
480
/** If <b>key</b> is a configuration option, return the corresponding
 * config_var_t.  Otherwise, if <b>key</b> is a non-standard abbreviation,
 * warn, and return the corresponding config_var_t.  Otherwise return NULL.
 */
481
482
483
static config_var_t *config_find_option(const char *key)
{
  int i;
Nick Mathewson's avatar
Nick Mathewson committed
484
  /* First, check for an exact (case-insensitive) match */
485
  for (i=0; config_vars[i].name; ++i) {
Nick Mathewson's avatar
Nick Mathewson committed
486
    if (!strcasecmp(key, config_vars[i].name))
487
      return &config_vars[i];
Nick Mathewson's avatar
Nick Mathewson committed
488
489
490
491
  }
  /* If none, check for an abbreviated match */
  for (i=0; config_vars[i].name; ++i) {
    if (!strncasecmp(key, config_vars[i].name, strlen(key))) {
492
493
494
495
496
497
      log_fn(LOG_WARN, "The abbreviation '%s' is deprecated. "
          "Tell Nick and Roger to make it official, or just use '%s' instead",
             key, config_vars[i].name);
      return &config_vars[i];
    }
  }
Nick Mathewson's avatar
Nick Mathewson committed
498
  /* Okay, unrecogized options */
499
500
501
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
502
/** If <b>c</b> is a syntactically valid configuration line, update
503
504
 * <b>options</b> with its value and return 0.  Otherwise return -1 for bad key,
 * -2 for bad value.
505
506
507
508
 *
 * If 'reset' is set, and we get a line containing no value, restore the
 * option to its default value.
 */
509
static int
510
config_assign_line(or_options_t *options, struct config_line_t *c, int reset)
511
{
512
  int i, ok;
513
514
  config_var_t *var;
  void *lvalue;
515

516
517
518
519
520
521
522
  var = config_find_option(c->key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", c->key);
    return -1;
  }
  /* Put keyword into canonical case. */
  if (strcmp(var->name, c->key)) {
523
    tor_free(c->key);
524
    c->key = tor_strdup(var->name);
525
526
  }

527
  if (reset && !strlen(c->value)) {
528
    option_reset(options, var);
529
530
531
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
532
  lvalue = ((char*)options) + var->var_offset;
533
  switch (var->type) {
534

535
536
537
  case CONFIG_TYPE_UINT:
    i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
    if (!ok) {
538
      log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.",
539
          c->key,c->value);
540
      return -2;
541
    }
542
    *(int *)lvalue = i;
543
544
    break;

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
  case CONFIG_TYPE_INTERVAL: {
    i = config_parse_interval(c->value, &ok);
    if (!ok) {
      return -2;
    }
    *(int *)lvalue = i;
    break;
  }

  case CONFIG_TYPE_MEMUNIT: {
    uint64_t u64 = config_parse_memunit(c->value, &ok);
    if (!ok) {
      return -2;
    }
    *(uint64_t *)lvalue = u64;
    break;
  }

563
564
565
  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
566
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
567
      return -2;
568
    }
569
    *(int *)lvalue = i;
570
571
572
    break;

  case CONFIG_TYPE_STRING:
573
574
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
575
576
577
    break;

  case CONFIG_TYPE_DOUBLE:
578
    *(double *)lvalue = atof(c->value);
579
580
581
    break;

  case CONFIG_TYPE_CSV:
582
583
    if (*(smartlist_t**)lvalue == NULL)
      *(smartlist_t**)lvalue = smartlist_create();
584

585
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
586
587
588
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

589
590
591
592
593
594
595
596
  case CONFIG_TYPE_LINELIST:
  case CONFIG_TYPE_LINELIST_S:
    /* Note: this reverses the order that the lines appear in.  That's
     * just fine, since we build up the list of lines reversed in the
     * first place. */
    *(struct config_line_t**)lvalue =
      config_line_prepend(*(struct config_line_t**)lvalue, c->key, c->value);
    break;
597
598
599
600

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
601
602
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
603
    return -2;
604
605
606
  default:
    tor_assert(0);
    break;
607
  }
608
  return 0;
609
610
}

611
612
613
614
615
616
617
618
619
620
/** restore the option named <b>key</b> in options to its default value. */
static void
config_reset_line(or_options_t *options, const char *key)
{
  config_var_t *var;

  var = config_find_option(key);
  if (!var)
    return; /* give error on next pass. */

621
  option_reset(options, var);
622
623
}

624
625
626
627
628
629
630
631
/** Return true iff key is a valid configuration option. */
int
config_option_is_recognized(const char *key)
{
  config_var_t *var = config_find_option(key);
  return (var != NULL);
}

632
633
634
635
636
637
638
639
640
/** Return a canonicalized list of the options assigned for key.
 */
struct config_line_t *
config_get_assigned_option(or_options_t *options, const char *key)
{
  config_var_t *var;
  const void *value;
  char buf[32];
  struct config_line_t *result;
641
  tor_assert(options && key);
642
643
644
645
646

  var = config_find_option(key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", key);
    return NULL;
647
648
649
  } else if (var->type == CONFIG_TYPE_LINELIST_S) {
    log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key);
    return NULL;
650
651
652
  }
  value = ((char*)options) + var->var_offset;

653
654
  if (var->type == CONFIG_TYPE_LINELIST ||
      var->type == CONFIG_TYPE_LINELIST_V) {
655
    /* Linelist requires special handling: we just copy and return it. */
Roger Dingledine's avatar
Roger Dingledine committed
656
    const struct config_line_t *next_in = *(const struct config_line_t**)value;
657
658
659
660
661
662
663
664
665
666
667
668
669
670
    struct config_line_t **next_out = &result;
    while (next_in) {
      *next_out = tor_malloc(sizeof(struct config_line_t));
      (*next_out)->key = tor_strdup(next_in->key);
      (*next_out)->value = tor_strdup(next_in->value);
      next_in = next_in->next;
      next_out = &((*next_out)->next);
    }
    (*next_out) = NULL;
    return result;
  }

  result = tor_malloc_zero(sizeof(struct config_line_t));
  result->key = tor_strdup(var->name);
671
  switch (var->type)
672
673
    {
    case CONFIG_TYPE_STRING:
674
675
676
677
678
679
680
      if (*(char**)value) {
        result->value = tor_strdup(*(char**)value);
      } else {
        tor_free(result->key);
        tor_free(result);
        return NULL;
      }
681
      break;
682
    case CONFIG_TYPE_INTERVAL:
683
    case CONFIG_TYPE_UINT:
684
      /* This means every or_options_t uint or bool element
685
       * needs to be an int. Not, say, a uint16_t or char. */
686
687
688
      tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
      result->value = tor_strdup(buf);
      break;
689
690
691
692
693
    case CONFIG_TYPE_MEMUNIT:
      tor_snprintf(buf, sizeof(buf), U64_FORMAT,
                   U64_PRINTF_ARG(*(uint64_t*)value));
      result->value = tor_strdup(buf);
      break;
694
695
696
697
698
699
700
701
    case CONFIG_TYPE_DOUBLE:
      tor_snprintf(buf, sizeof(buf), "%f", *(double*)value);
      result->value = tor_strdup(buf);
      break;
    case CONFIG_TYPE_BOOL:
      result->value = tor_strdup(*(int*)value ? "1" : "0");
      break;
    case CONFIG_TYPE_CSV:
Roger Dingledine's avatar
Roger Dingledine committed
702
703
      if (*(smartlist_t**)value)
        result->value = smartlist_join_strings(*(smartlist_t**)value,",",0,NULL);
704
705
706
      else
        result->value = tor_strdup("");
      break;
707
708
709
710
711
    case CONFIG_TYPE_OBSOLETE:
      log_fn(LOG_WARN,"You asked me for the value of an obsolete config option %s.", key);
      tor_free(result->key);
      tor_free(result);
      return NULL;
712
713
714
    default:
      tor_free(result->key);
      tor_free(result);
715
      log_fn(LOG_WARN,"Bug: unknown type %d for known key %s", var->type, key);
716
717
718
719
720
721
      return NULL;
    }

  return result;
}

722
/** Iterate through the linked list of requested options <b>list</b>.
Nick Mathewson's avatar
Nick Mathewson committed
723
 * For each item, convert as appropriate and assign to <b>options</b>.
724
 * If an item is unrecognized, return -1 immediately,
725
726
727
728
 * else return 0 for success.
 *
 * If <b>reset</b>, then interpret empty lines as meaning "restore to
 * default value", and interpret LINELIST* options as replacing (not
729
730
 * extending) their previous values.  Return 0 on success, -1 on bad key,
 * -2 on bad value.
731
 */
732
static int
733
config_assign(or_options_t *options, struct config_line_t *list, int reset)
734
{
735
  struct config_line_t *p;
736
  tor_assert(options);
737
738
739
740
741
742
743

  /* pass 1: normalize keys */
  for (p = list; p; p = p->next) {
    const char *full = expand_abbrev(p->key, 0);
    if (strcmp(full,p->key)) {
      tor_free(p->key);
      p->key = tor_strdup(full);
744
    }
745
746
  }

747
  /* pass 2: if we're reading from a resetting source, clear all mentioned
748
749
750
751
752
   * linelists. */
  if (reset) {
    for (p = list; p; p = p->next)
      config_reset_line(options, p->key);
  }
753

754
755
  /* pass 3: assign. */
  while (list) {
756
757
758
    int r;
    if ((r=config_assign_line(options, list, reset)))
      return r;
759
    list = list->next;
Roger Dingledine's avatar
Roger Dingledine committed
760
  }
761
  return 0;
762
763
}

764
/** Try assigning <b>list</b> to the global options. You do this by duping
765
 * options, assigning list to the new one, then validating it. If it's
766
 * ok, then throw out the old one and stick with the new one. Else,
767
768
 * revert to old and return failure.  Return 0 on success, -1 on bad
 * keys, -2 on bad values, -3 on bad transition.
769
770
 */
int
771
config_trial_assign(struct config_line_t *list, int reset)
772
{
773
  int r;
774
  or_options_t *trial_options = options_dup(get_options());
775

776
  if ((r=config_assign(trial_options, list, reset)) < 0) {
777
    options_free(trial_options);
778
    return r;
779
780
781
782
  }

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
783
    return -2;
784
785
  }

786
  if (options_transition_allowed(get_options(), trial_options) < 0) {
787
    options_free(trial_options);
788
    return -3;
789
790
  }

791
  set_options(trial_options); /* we liked it. put it in place. */
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
  return 0;
}

/** Replace the option indexed by <b>var</b> in <b>options</b> with its
 * default value. */
static void
option_reset(or_options_t *options, config_var_t *var)
{
  struct config_line_t *c;
  void *lvalue;

  lvalue = ((char*)options) + var->var_offset;
  switch (var->type) {
    case CONFIG_TYPE_STRING:
      tor_free(*(char**)lvalue);
      break;
    case CONFIG_TYPE_DOUBLE:
      *(double*)lvalue = 0.0;
      break;
811
    case CONFIG_TYPE_INTERVAL:
812
813
814
815
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_BOOL:
      *(int*)lvalue = 0;
      break;
816
817
818
    case CONFIG_TYPE_MEMUNIT:
      *(uint64_t*)lvalue = 0;
      break;
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
    case CONFIG_TYPE_CSV:
      if (*(smartlist_t**)lvalue) {
        SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
        smartlist_free(*(smartlist_t **)lvalue);
        *(smartlist_t **)lvalue = NULL;
      }
      break;
    case CONFIG_TYPE_LINELIST:
    case CONFIG_TYPE_LINELIST_S:
      config_free_lines(*(struct config_line_t **)lvalue);
      *(struct config_line_t **)lvalue = NULL;
      break;
    case CONFIG_TYPE_LINELIST_V:
      /* handled by linelist_s. */
      break;
    case CONFIG_TYPE_OBSOLETE:
      break;
  }
  if (var->initvalue) {
838
    c = tor_malloc_zero(sizeof(struct config_line_t));
839
840
841
842
843
844
845
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    config_assign_line(options,c,0);
    config_free_lines(c);
  }
}

846
/** Set <b>options</b>-&gt;DirServers to contain the default directory
847
 * servers. */
848
static void
849
add_default_trusted_dirservers(or_options_t *options)
850
{
Nick Mathewson's avatar
Nick Mathewson committed
851
  /* moria1 */
852
853
  options->DirServers = config_line_prepend(options->DirServers, "DirServer",
       "18.244.0.188:9031 FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441");
Nick Mathewson's avatar
Nick Mathewson committed
854
  /* moria2 */
855
856
  options->DirServers = config_line_prepend(options->DirServers, "DirServer",
         "18.244.0.114:80 719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF");
Nick Mathewson's avatar
Nick Mathewson committed
857
  /* tor26 */
858
859
  options->DirServers = config_line_prepend(options->DirServers, "DirServer",
     "62.116.124.106:9030 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D");
860
861
}

Nick Mathewson's avatar
Nick Mathewson committed
862
/** Print a usage message for tor. */
863
864
865
static void
print_usage(void)
{
866
867
868
869
  printf(
"Copyright 2001-2004 Roger Dingledine, Nick Mathewson, Matej Pfajfar.\n\n"
"tor -f <torrc> [args]\n"
"See man page for options, or http://freehaven.net/tor/ for documentation.\n");
870
871
}

Nick Mathewson's avatar
Nick Mathewson committed
872
/**
873
874
 * Based on <b>address</b>, guess our public IP address and put it
 * in <b>addr</b>.
Nick Mathewson's avatar
Nick Mathewson committed
875
 */
876
877
878
int
resolve_my_address(const char *address, uint32_t *addr)
{
879
880
  struct in_addr in;
  struct hostent *rent;
881
  char hostname[256];
882
  int explicit_ip=1;
883

884
885
  tor_assert(addr);

886
887
  if (address) {
    strlcpy(hostname, address, sizeof(hostname));
888
  } else { /* then we need to guess our address */
889
    explicit_ip = 0; /* it's implicit */
890

891
    if (gethostname(hostname, sizeof(hostname)) < 0) {
892
893
894
      log_fn(LOG_WARN,"Error obtaining local hostname");
      return -1;
    }
895
    log_fn(LOG_DEBUG,"Guessed local host name as '%s'",hostname);
896
897
  }

898
  /* now we know hostname. resolve it and keep only the IP */
899

900
  if (tor_inet_aton(hostname, &in) == 0) {
901
902
    /* then we have to resolve it */
    explicit_ip = 0;
903
    rent = (struct hostent *)gethostbyname(hostname);
904
    if (!rent) {
905
      log_fn(LOG_WARN,"Could not resolve local Address %s. Failing.", hostname);
906
907
      return -1;
    }
Roger Dingledine's avatar
Roger Dingledine committed
908
    tor_assert(rent->h_length == 4);
909
    memcpy(&in.s_addr, rent->h_addr, rent->h_length);
910
  }
911
912

  if (!explicit_ip && is_internal_IP(htonl(in.s_addr))) {
913
    log_fn(LOG_WARN,"Address '%s' resolves to private IP '%s'. "
914
           "Please set the Address config option to be the IP you want to use.",
915
           hostname, inet_ntoa(in));
916
917
    return -1;
  }
918
919

  log_fn(LOG_DEBUG, "Resolved Address to %s.", inet_ntoa(in));
920
  *addr = ntohl(in.s_addr);
921
922
923
  return 0;
}

924
925
/** Called when we don't have a nickname set.  Try to guess a good
 * nickname based on the hostname, and return it. */
926
927
static char *
get_default_nickname(void)
928
929
930
931
{
  char localhostname[256];
  char *cp, *out, *outp;

932
  if (gethostname(localhostname, sizeof(localhostname)) < 0) {
933
934
935
    log_fn(LOG_WARN,"Error obtaining local hostname");
    return NULL;
  }
936

937
  /* Put it in lowercase; stop at the first dot. */
938
  for (cp = localhostname; *cp; ++cp) {
939
940
941
942
943
944
    if (*cp == '.') {
      *cp = '\0';
      break;
    }
    *cp = tolower(*cp);
  }
945

946
947
  /* Strip invalid characters. */
  cp = localhostname;
948
  out = outp = tor_malloc(strlen(localhostname) + 1);
949
950
951
952
953
954
955
  while (*cp) {
    if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
      *outp++ = *cp++;
    else
      cp++;
  }
  *outp = '\0';
956

957
958
959
960
961
962
963
  /* Enforce length. */
  if (strlen(out) > MAX_NICKNAME_LEN)
    out[MAX_NICKNAME_LEN]='\0';

  return out;
}

Nick Mathewson's avatar
Nick Mathewson committed
964
/** Release storage held by <b>options</b> */
965
static void
966
options_free(or_options_t *options)
967
{
968
969
970
971
972
  int i;
  void *lvalue;

  for (i=0; config_vars[i].name; ++i) {
    lvalue = ((char*)options) + config_vars[i].var_offset;
973
    switch (config_vars[i].type) {
974
975
      case CONFIG_TYPE_MEMUNIT:
      case CONFIG_TYPE_INTERVAL:
976
977
978
979
980
981
982
983
984
      case CONFIG_TYPE_UINT:
      case CONFIG_TYPE_BOOL:
      case CONFIG_TYPE_DOUBLE:
      case CONFIG_TYPE_OBSOLETE:
        break; /* nothing to free for these config types */
      case CONFIG_TYPE_STRING:
        tor_free(*(char **)lvalue);
        break;
      case CONFIG_TYPE_LINELIST:
985
      case CONFIG_TYPE_LINELIST_V:
986
987
988
989
990
991
992
993
994
995
        config_free_lines(*(struct config_line_t**)lvalue);
        *(struct config_line_t**)lvalue = NULL;
        break;
      case CONFIG_TYPE_CSV:
        if (*(smartlist_t**)lvalue) {
          SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
          smartlist_free(*(smartlist_t**)lvalue);
          *(smartlist_t**)lvalue = NULL;
        }
        break;
Nick Mathewson's avatar