config.c 69.6 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
25
26
  /* DOCDOC */
  CONFIG_TYPE_INTERVAL,     /**< A non-negative integer less than MAX_INT */
  /* DOCDOC */
  CONFIG_TYPE_MEMUNIT,       /**< A non-negative integer less than MAX_INT */
27
28
29
30
31
  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 */
32
33
34
35
36
  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.
                             */
37
  CONFIG_TYPE_OBSOLETE,     /**< Obsolete (ignored) option. */
Nick Mathewson's avatar
Nick Mathewson committed
38
} config_type_t;
39

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

47
48
49
50
/* 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
51
/* A list of command-line abbreviations. */
52
static config_abbrev_t config_abbrevs[] = {
53
  PLURAL(ExitNode),
54
  PLURAL(EntryNode),
55
56
57
58
59
60
  PLURAL(ExcludeNode),
  PLURAL(FirewallPort),
  PLURAL(HiddenServiceNode),
  PLURAL(HiddenServiceExcludeNode),
  PLURAL(RendNode),
  PLURAL(RendExcludeNode),
61
62
  PLURAL(StrictEntryNode),
  PLURAL(StrictExitNode),
63
  { "l", "Log", 1},
64
65
  { "BandwidthRateBytes", "BandwidthRate", 0},
  { "BandwidthBurstBytes", "BandwidthBurst", 0},
66
  { "DirFetchPostPeriod", "DirFetchPeriod", 0},
67
  { NULL, NULL , 0},
68
};
69
#undef PLURAL
70

71
/** A variable allowed in the configuration file or on the command line. */
72
typedef struct config_var_t {
73
74
75
76
  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. */
77
78
} config_var_t;

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

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

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

172
173
static void option_reset(or_options_t *options, config_var_t *var);
static void options_free(or_options_t *options);
174
static int option_is_same(or_options_t *o1, or_options_t *o2,const char *name);
175
176
177
178
179
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);

180
static int parse_dir_server_line(const char *line, int validate_only);
181
static int parse_redirect_line(smartlist_t *result,
Roger Dingledine's avatar
Roger Dingledine committed
182
                               struct config_line_t *line);
183
184
185
186
187
188
189
190
191
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);
192
static int validate_data_directory(or_options_t *options);
193
static int write_configuration_file(const char *fname, or_options_t *options);
194

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

198
199
200
201
202
203
/*
 * 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
204
/** Name of most recently read torrc file. */
205
static char *config_fname = NULL;
206

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

Roger Dingledine's avatar
Roger Dingledine committed
214
215
216
/** 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
217
218
219
220
221
222
223
224
225
226
227
228
229
 * 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;
230
231
232
233
234
235
236
237
238
239
}

/** 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();
240
241

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

250
  if (rend_config_services(options, 0)<0) {
251
252
    log_fn(LOG_ERR,
           "Previously validated hidden services line could not be added!");
253
    return -1;
254
  }
255
256
257
258
259
260
261
262
263

  /* Setuid/setgid as appropriate */
  if(options->User || options->Group) {
    if(switch_id(options->User, options->Group) != 0) {
      return -1;
    }
  }

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

275
  if (set_max_file_descriptors(options->MaxConn) < 0)
276
277
    return -1;

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

286
287
288
289
290
291
292
293
294
  {
    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);
  }

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

297
298
299
  /* 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 */
300
  if (options->RunAsDaemon) {
301
    start_daemon(options->DataDirectory);
302
303
304
305
  }

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

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

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

319
320
  init_cookie_authentication(options->CookieAuthentication);

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

327
  /* Set up accounting */
328
  if (accounting_is_enabled(options))
329
330
    configure_accounting(time(NULL));

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

336
337
338
339
340
341
#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
342
    log_fn(LOG_DEBUG, "We changed these options:\n%s",smin);
343
344
345
346
347
    tor_free(smin);
    tor_free(smax);
  }
#endif

348
349
350
351
352
353
  /* 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();

354
  return 0;
355
356
357
358
359
360
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
361
/** If <b>option</b> is an official abbreviation for a longer option,
362
363
364
 * 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. */
365
static const char *
366
expand_abbrev(const char *option, int command_line)
367
368
369
370
{
  int i;
  for (i=0; config_abbrevs[i].abbreviated; ++i) {
    /* Abbreviations aren't casei. */
371
    if (!strcasecmp(option,config_abbrevs[i].abbreviated) &&
372
        (command_line || !config_abbrevs[i].commandline_only)) {
373
      return config_abbrevs[i].full;
374
    }
375
376
377
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
378

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

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

398
    new = tor_malloc(sizeof(struct config_line_t));
399
    s = argv[i];
400

401
402
    while(*s == '-')
      s++;
403

404
    new->key = tor_strdup(expand_abbrev(s, 1));
405
    new->value = tor_strdup(argv[i+1]);
406
407

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

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

425
426
427
428
429
430
431
  newline = tor_malloc(sizeof(struct config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
  newline->next = front;
  return newline;
}

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

442
443
444
445
446
447
448
449
450
  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);
451

452
  *result = list;
453
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
454
455
}

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

464
  while (front) {
465
466
467
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
468
469
470
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
471
472
473
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
474
475
476
477
/** 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.
 */
478
479
480
static config_var_t *config_find_option(const char *key)
{
  int i;
Nick Mathewson's avatar
Nick Mathewson committed
481
  /* First, check for an exact (case-insensitive) match */
482
  for (i=0; config_vars[i].name; ++i) {
Nick Mathewson's avatar
Nick Mathewson committed
483
    if (!strcasecmp(key, config_vars[i].name))
484
      return &config_vars[i];
Nick Mathewson's avatar
Nick Mathewson committed
485
486
487
488
  }
  /* If none, check for an abbreviated match */
  for (i=0; config_vars[i].name; ++i) {
    if (!strncasecmp(key, config_vars[i].name, strlen(key))) {
489
490
491
492
493
494
      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
495
  /* Okay, unrecogized options */
496
497
498
  return NULL;
}

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

513
514
515
516
517
518
519
  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)) {
520
    tor_free(c->key);
521
    c->key = tor_strdup(var->name);
522
523
  }

524
  if (reset && !strlen(c->value)) {
525
    option_reset(options, var);
526
527
528
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
529
  lvalue = ((char*)options) + var->var_offset;
530
  switch(var->type) {
531

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

542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  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;
  }

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

  case CONFIG_TYPE_STRING:
570
571
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
572
573
574
    break;

  case CONFIG_TYPE_DOUBLE:
575
    *(double *)lvalue = atof(c->value);
576
577
578
    break;

  case CONFIG_TYPE_CSV:
579
580
    if (*(smartlist_t**)lvalue == NULL)
      *(smartlist_t**)lvalue = smartlist_create();
581

582
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
583
584
585
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

586
587
588
589
590
591
592
593
  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;
594
595
596
597

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

608
609
610
611
612
613
614
615
616
617
/** 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. */

618
  option_reset(options, var);
619
620
}

621
622
623
624
625
626
627
628
/** 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);
}

629
630
631
632
633
634
635
636
637
/** 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;
638
  tor_assert(options && key);
639
640
641
642
643

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

650
651
  if (var->type == CONFIG_TYPE_LINELIST ||
      var->type == CONFIG_TYPE_LINELIST_V) {
652
    /* Linelist requires special handling: we just copy and return it. */
Roger Dingledine's avatar
Roger Dingledine committed
653
    const struct config_line_t *next_in = *(const struct config_line_t**)value;
654
655
656
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);
  switch(var->type)
    {
    case CONFIG_TYPE_STRING:
671
672
673
674
675
676
677
      if (*(char**)value) {
        result->value = tor_strdup(*(char**)value);
      } else {
        tor_free(result->key);
        tor_free(result);
        return NULL;
      }
678
      break;
679
    case CONFIG_TYPE_INTERVAL:
680
    case CONFIG_TYPE_UINT:
681
      /* This means every or_options_t uint or bool element
682
       * needs to be an int. Not, say, a uint16_t or char. */
683
684
685
      tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
      result->value = tor_strdup(buf);
      break;
686
687
688
689
690
    case CONFIG_TYPE_MEMUNIT:
      tor_snprintf(buf, sizeof(buf), U64_FORMAT,
                   U64_PRINTF_ARG(*(uint64_t*)value));
      result->value = tor_strdup(buf);
      break;
691
692
693
694
695
696
697
698
    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
699
700
      if (*(smartlist_t**)value)
        result->value = smartlist_join_strings(*(smartlist_t**)value,",",0,NULL);
701
702
703
      else
        result->value = tor_strdup("");
      break;
704
705
706
707
708
    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;
709
710
711
    default:
      tor_free(result->key);
      tor_free(result);
712
      log_fn(LOG_WARN,"Bug: unknown type %d for known key %s", var->type, key);
713
714
715
716
717
718
      return NULL;
    }

  return result;
}

719
/** Iterate through the linked list of requested options <b>list</b>.
Nick Mathewson's avatar
Nick Mathewson committed
720
 * For each item, convert as appropriate and assign to <b>options</b>.
721
 * If an item is unrecognized, return -1 immediately,
722
723
724
725
 * 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
726
727
 * extending) their previous values.  Return 0 on success, -1 on bad key,
 * -2 on bad value.
728
 */
729
static int
730
config_assign(or_options_t *options, struct config_line_t *list, int reset)
731
{
732
  struct config_line_t *p;
733
  tor_assert(options);
734
735
736
737
738
739
740

  /* 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);
741
    }
742
743
  }

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

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

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

773
  if ((r=config_assign(trial_options, list, reset)) < 0) {
774
    options_free(trial_options);
775
    return r;
776
777
778
779
  }

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
780
    return -2;
781
782
  }

783
  if (options_transition_allowed(get_options(), trial_options) < 0) {
784
    options_free(trial_options);
785
    return -3;
786
787
  }

788
  set_options(trial_options); /* we liked it. put it in place. */
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  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;
808
    case CONFIG_TYPE_INTERVAL:
809
810
811
812
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_BOOL:
      *(int*)lvalue = 0;
      break;
813
814
815
    case CONFIG_TYPE_MEMUNIT:
      *(uint64_t*)lvalue = 0;
      break;
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
    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) {
835
    c = tor_malloc_zero(sizeof(struct config_line_t));
836
837
838
839
840
841
842
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    config_assign_line(options,c,0);
    config_free_lines(c);
  }
}

843
/** Set <b>options</b>-&gt;DirServers to contain the default directory
844
 * servers. */
845
static void
846
add_default_trusted_dirservers(or_options_t *options)
847
{
Nick Mathewson's avatar
Nick Mathewson committed
848
  /* moria1 */
849
850
  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
851
  /* moria2 */
852
853
  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
854
  /* tor26 */
855
856
  options->DirServers = config_line_prepend(options->DirServers, "DirServer",
     "62.116.124.106:9030 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D");
857
858
}

Nick Mathewson's avatar
Nick Mathewson committed
859
/** Print a usage message for tor. */
860
861
862
static void
print_usage(void)
{
863
864
865
866
  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");
867
868
}

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

881
882
  tor_assert(addr);

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

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

895
  /* now we know hostname. resolve it and keep only the IP */
896

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

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

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

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

929
  if (gethostname(localhostname, sizeof(localhostname)) < 0) {
930
931
932
    log_fn(LOG_WARN,"Error obtaining local hostname");
    return NULL;
  }
933

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

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

954
955
956
957
958
959
960
  /* Enforce length. */
  if (strlen(out) > MAX_NICKNAME_LEN)
    out[MAX_NICKNAME_LEN]='\0';

  return out;
}

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

  for (i=0; config_vars[i].name; ++i) {
    lvalue = ((char*)options) + config_vars[i].var_offset;
    switch(config_vars[i].type) {
971
972
      case CONFIG_TYPE_MEMUNIT:
      case CONFIG_TYPE_INTERVAL:
973
974
975
976
977
978
979
980
981
      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:
982
      case CONFIG_TYPE_LINELIST_V:
983
984
985
986
987
988
989
990
991
992
        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;
993
994
995
      case CONFIG_TYPE_LINELIST_S:
        /* will be freed by corresponding LINELIST_V. */
        break;
996
997
    }
  }
998
}
999

1000
/** Return true iff the option <b>var</b> has the same value in <b>o1</b>