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

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

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

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

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

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

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

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

/** 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();
238
239

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

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

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

273
  if (set_max_file_descriptors(options->MaxConn) < 0)
274
275
    return -1;

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

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

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

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

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

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

317
318
  init_cookie_authentication(options->CookieAuthentication);

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

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

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

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

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

352
  return 0;
353
354
355
356
357
358
}

/*
 * Functions to parse config options
 */

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

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

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

396
    new = tor_malloc(sizeof(struct config_line_t));
397
    s = argv[i];
398

399
400
    while(*s == '-')
      s++;
401

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

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

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

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

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

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

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

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

462
  while (front) {
463
464
465
    tmp = front;
    front = tmp->next;

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

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

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

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

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

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

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

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

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

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

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

  case CONFIG_TYPE_CSV:
577
578
    if (*(smartlist_t**)lvalue == NULL)
      *(smartlist_t**)lvalue = smartlist_create();
579

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

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

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

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

616
  option_reset(options, var);
617
618
}

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

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

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

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

  return result;
}

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

  /* 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);
739
    }
740
741
  }

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

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

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

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

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
778
    return -2;
779
780
  }

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

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

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

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

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

879
880
  tor_assert(addr);

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

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

893
  /* now we know hostname. resolve it and keep only the IP */
894

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

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

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

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

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

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

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

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

  return out;
}

Nick Mathewson's avatar
Nick Mathewson committed
959
/** Release storage held by <b>options</b> */
960
static void
961
options_free(or_options_t *options)
962
{
963
964
965
966
967
968
  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) {
969
970
      case CONFIG_TYPE_MEMUNIT:
      case CONFIG_TYPE_INTERVAL:
971
972
973
974
975
976
977
978
979
      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:
980
      case CONFIG_TYPE_LINELIST_V:
981
982
983
984
985
986
987
988
989
990
        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;
991
992
993
      case CONFIG_TYPE_LINELIST_S:
        /* will be freed by corresponding LINELIST_V. */
        break;
994
995
    }
  }
996
}
997

998
999
1000
/** Return true iff the option <b>var</b> has the same value in <b>o1</b>
 * and <b>o2</b>.  Must not be called for LINELIST_S or OBSOLETE options.
 */
For faster browsing, not all history is shown. View entire blame