config.c 63.7 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
23
24
25
26
27
  CONFIG_TYPE_STRING = 0,   /**< An arbitrary string. */
  CONFIG_TYPE_UINT,         /**< A non-negative integer less than MAX_INT */
  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 */
28
29
30
31
32
  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.
                             */
33
  CONFIG_TYPE_OBSOLETE,     /**< Obsolete (ignored) option. */
Nick Mathewson's avatar
Nick Mathewson committed
34
} config_type_t;
35

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

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

64
/** A variable allowed in the configuration file or on the command line. */
65
typedef struct config_var_t {
66
67
68
69
  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. */
70
71
} config_var_t;

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

Nick Mathewson's avatar
Nick Mathewson committed
83
84
85
86
/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
87
static config_var_t config_vars[] = {
88
  VAR("Address",             STRING,   Address,              NULL),
89
  VAR("AllowUnverifiedNodes",CSV,      AllowUnverifiedNodes, "middle,rendezvous"),
90
  VAR("AuthoritativeDirectory",BOOL,   AuthoritativeDir,     "0"),
91
92
  VAR("BandwidthRateBytes",  UINT,     BandwidthRateBytes,   "800000"),
  VAR("BandwidthBurstBytes", UINT,     BandwidthBurstBytes,  "50000000"),
93
94
  VAR("ClientOnly",          BOOL,     ClientOnly,           "0"),
  VAR("ContactInfo",         STRING,   ContactInfo,          NULL),
95
  VAR("ControlPort",         UINT,     ControlPort,          "0"),
96
  VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  VAR("DebugLogFile",        STRING,   DebugLogFile,         NULL),
  VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
  VAR("DirPort",             UINT,     DirPort,              "0"),
  VAR("DirBindAddress",      LINELIST, DirBindAddress,       NULL),
  VAR("DirFetchPostPeriod",  UINT,     DirFetchPostPeriod,   "600"),
  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"),
111
  VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
112
113
114
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
  VAR("Group",               STRING,   Group,                NULL),
115
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
116
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
117
118
119
120
121
  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),
122
123
  VAR("IgnoreVersion",       BOOL,     IgnoreVersion,        "0"),
  VAR("KeepalivePeriod",     UINT,     KeepalivePeriod,      "300"),
124
125
126
  VAR("Log",                 LINELIST, Logs,                 NULL),
  VAR("LogLevel",            LINELIST_S, OldLogOptions,      NULL),
  VAR("LogFile",             LINELIST_S, OldLogOptions,      NULL),
127
  OBSOLETE("LinkPadding"),
128
129
  VAR("MaxConn",             UINT,     MaxConn,              "1024"),
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
Nick Mathewson's avatar
Nick Mathewson committed
130
  VAR("MonthlyAccountingStart",UINT,   AccountingStart,      "1"),
131
132
133
134
135
136
137
138
139
140
  VAR("AccountingMaxKB",     UINT,     AccountingMaxKB,      "0"),
  VAR("Nickname",            STRING,   Nickname,             NULL),
  VAR("NewCircuitPeriod",    UINT,     NewCircuitPeriod,     "30"),
  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),
141
  OBSOLETE("RouterFile"),
142
143
144
145
146
  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),
147
  VAR("SocksPort",           UINT,     SocksPort,            "9050"),
148
149
  VAR("SocksBindAddress",    LINELIST, SocksBindAddress,     NULL),
  VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),
150
  VAR("SysLog",              LINELIST_S, OldLogOptions,      NULL),
151
  OBSOLETE("TrafficShaping"),
152
153
  VAR("User",                STRING,   User,                 NULL),
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
154
155
156
157
};
#undef VAR
#undef OBSOLETE

Nick Mathewson's avatar
Nick Mathewson committed
158
/** Largest allowed config line */
159
#define CONFIG_LINE_T_MAXLEN 4096
160

161
162
static void option_reset(or_options_t *options, config_var_t *var);
static void options_free(or_options_t *options);
163
164
static int option_is_same(or_options_t *o1, or_options_t *o2,
                          config_var_t *var);
165
166
167
168
169
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);

170
static int parse_dir_server_line(const char *line, int validate_only);
171
static int parse_redirect_line(smartlist_t *result,
Roger Dingledine's avatar
Roger Dingledine committed
172
                               struct config_line_t *line);
173
174
175
176
177
178
179
180
181
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);
182
static int validate_data_directory(or_options_t *options);
183

184
185
186
187
188
189
190
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
static or_options_t *global_options=NULL;

191
192
193
/** Return the currently configured options. */
or_options_t *
get_options(void) {
194
195
196
  tor_assert(global_options);
  return global_options;
}
197

Roger Dingledine's avatar
Roger Dingledine committed
198
199
200
/** 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
201
202
203
204
205
206
207
208
209
210
211
212
213
 * 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;
214
215
216
217
218
219
220
221
222
223
}

/** 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();
224
225

  clear_trusted_dir_servers();
226
  for (cl = options->DirServers; cl; cl = cl->next) {
227
228
229
    if (parse_dir_server_line(cl->value, 0)<0) {
      log_fn(LOG_ERR,
             "Previously validated DirServer line could not be added!");
230
      return -1;
231
232
233
    }
  }

234
  if (rend_config_services(options, 0)<0) {
235
236
    log_fn(LOG_ERR,
           "Previously validated hidden services line could not be added!");
237
    return -1;
238
  }
239
240
241
242
243
244
245
246
247

  /* 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. */
248
  if (check_private_dir(options->DataDirectory, CPD_CREATE) != 0) {
249
    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
250
           options->DataDirectory);
251
252
253
254
255
256
257
258
    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;

259
  if (set_max_file_descriptors(options->MaxConn) < 0)
260
261
    return -1;

262
  mark_logs_temp(); /* Close current logs once new logs are open. */
263
  if (config_init_logs(options, 0)<0) /* Configure the log(s) */
264
265
266
267
    return -1;
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
268
  add_callback_log(LOG_NOTICE, LOG_ERR, control_event_logmsg);
269

270
271
272
273
274
275
276
277
278
  {
    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);
  }

279
  /* Start backgrounding the process, if requested. */
280

281
282
283
  /* 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 */
284
  if (options->RunAsDaemon) {
285
    start_daemon(options->DataDirectory);
286
287
288
289
  }

  /* Finish backgrounding the process */
  if(options->RunAsDaemon) {
290
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
291
292
293
294
295
296
297
298
    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);

299
300
301
302
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();

303
304
  init_cookie_authentication(options->CookieAuthentication);

305
306
307
308
309
310
311
312
313
314
315
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
    log_fn(LOG_ERR,"Error reloading rendezvous service keys");
    return -1;
  }

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

316
317
318
319
320
321
322
323
324
325
326
327
#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);
    log_fn(LOG_DEBUG, "We changed these options:\n%s",smin);
    tor_free(smin);
    tor_free(smax);
  }
#endif

328
329
330
331
332
333
  /* 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();

334
  return 0;
335
336
337
338
339
340
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
341
/** If <b>option</b> is an official abbreviation for a longer option,
342
343
344
 * 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. */
345
static const char *
346
expand_abbrev(const char *option, int command_line)
347
348
349
350
{
  int i;
  for (i=0; config_abbrevs[i].abbreviated; ++i) {
    /* Abbreviations aren't casei. */
351
    if (!strcasecmp(option,config_abbrevs[i].abbreviated) &&
352
        (command_line || !config_abbrevs[i].commandline_only)) {
353
      return config_abbrevs[i].full;
354
    }
355
356
357
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
358

Nick Mathewson's avatar
Nick Mathewson committed
359
/** Helper: Read a list of configuration options from the command line. */
360
361
362
static struct config_line_t *
config_get_commandlines(int argc, char **argv)
{
363
364
  struct config_line_t *new;
  struct config_line_t *front = NULL;
365
366
367
  char *s;
  int i = 1;

368
  while (i < argc-1) {
369
370
371
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
372
      continue;
373
374
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
375
      continue;
376
377
    }

378
    new = tor_malloc(sizeof(struct config_line_t));
379
    s = argv[i];
380

381
382
    while(*s == '-')
      s++;
383

384
    new->key = tor_strdup(expand_abbrev(s, 1));
385
    new->value = tor_strdup(argv[i+1]);
386
387

    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
388
        new->key, new->value);
389
390
391
392
393
394
395
    new->next = front;
    front = new;
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
396
397
/** Helper: allocate a new configuration option mapping 'key' to 'val',
 * prepend it to 'front', and return the newly allocated config_line_t */
398
struct config_line_t *
399
400
401
402
403
config_line_prepend(struct config_line_t *front,
                    const char *key,
                    const char *val)
{
  struct config_line_t *newline;
404

405
406
407
408
409
410
411
  newline = tor_malloc(sizeof(struct config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
  newline->next = front;
  return newline;
}

412
413
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
414
415
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
416
417
int
config_get_lines(char *string, struct config_line_t **result)
418
{
419
420
  struct config_line_t *list = NULL;
  char *k, *v;
421

422
423
424
425
426
427
428
429
430
  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);
431

432
  *result = list;
433
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
434
435
}

Nick Mathewson's avatar
Nick Mathewson committed
436
437
438
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
439
void
440
441
config_free_lines(struct config_line_t *front)
{
442
  struct config_line_t *tmp;
443

444
  while (front) {
445
446
447
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
448
449
450
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
451
452
453
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
454
455
456
457
/** 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.
 */
458
459
460
static config_var_t *config_find_option(const char *key)
{
  int i;
Nick Mathewson's avatar
Nick Mathewson committed
461
  /* First, check for an exact (case-insensitive) match */
462
  for (i=0; config_vars[i].name; ++i) {
Nick Mathewson's avatar
Nick Mathewson committed
463
    if (!strcasecmp(key, config_vars[i].name))
464
      return &config_vars[i];
Nick Mathewson's avatar
Nick Mathewson committed
465
466
467
468
  }
  /* If none, check for an abbreviated match */
  for (i=0; config_vars[i].name; ++i) {
    if (!strncasecmp(key, config_vars[i].name, strlen(key))) {
469
470
471
472
473
474
      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
475
  /* Okay, unrecogized options */
476
477
478
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
479
/** If <b>c</b> is a syntactically valid configuration line, update
480
481
 * <b>options</b> with its value and return 0.  Otherwise return -1 for bad key,
 * -2 for bad value.
482
483
484
485
 *
 * If 'reset' is set, and we get a line containing no value, restore the
 * option to its default value.
 */
486
static int
487
config_assign_line(or_options_t *options, struct config_line_t *c, int reset)
488
{
489
  int i, ok;
490
491
  config_var_t *var;
  void *lvalue;
492

493
494
495
496
497
498
499
  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)) {
500
    tor_free(c->key);
501
    c->key = tor_strdup(var->name);
502
503
  }

504
  if (reset && !strlen(c->value)) {
505
    option_reset(options, var);
506
507
508
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
509
  lvalue = ((char*)options) + var->var_offset;
510
  switch(var->type) {
511

512
513
514
  case CONFIG_TYPE_UINT:
    i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
    if (!ok) {
515
      log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.",
516
          c->key,c->value);
517
      return -2;
518
    }
519
    *(int *)lvalue = i;
520
521
522
523
524
    break;

  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
525
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
526
      return -2;
527
    }
528
    *(int *)lvalue = i;
529
530
531
    break;

  case CONFIG_TYPE_STRING:
532
533
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
534
535
536
    break;

  case CONFIG_TYPE_DOUBLE:
537
    *(double *)lvalue = atof(c->value);
538
539
540
    break;

  case CONFIG_TYPE_CSV:
541
542
    if (*(smartlist_t**)lvalue == NULL)
      *(smartlist_t**)lvalue = smartlist_create();
543

544
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
545
546
547
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

548
549
550
551
552
553
554
555
  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;
556
557
558
559

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
560
561
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
562
    return -2;
563
564
565
  default:
    tor_assert(0);
    break;
566
  }
567
  return 0;
568
569
}

570
571
572
573
574
575
576
577
578
579
/** 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. */

580
  option_reset(options, var);
581
582
}

583
584
585
586
587
588
589
590
/** 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);
}

591
592
593
594
595
596
597
598
599
/** 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;
600
  tor_assert(options && key);
601
602
603
604
605

  var = config_find_option(key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", key);
    return NULL;
606
607
608
  } else if (var->type == CONFIG_TYPE_LINELIST_S) {
    log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key);
    return NULL;
609
610
611
  }
  value = ((char*)options) + var->var_offset;

612
613
  if (var->type == CONFIG_TYPE_LINELIST ||
      var->type == CONFIG_TYPE_LINELIST_V) {
614
    /* Linelist requires special handling: we just copy and return it. */
Roger Dingledine's avatar
Roger Dingledine committed
615
    const struct config_line_t *next_in = *(const struct config_line_t**)value;
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    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:
633
634
635
636
637
638
639
      if (*(char**)value) {
        result->value = tor_strdup(*(char**)value);
      } else {
        tor_free(result->key);
        tor_free(result);
        return NULL;
      }
640
641
      break;
    case CONFIG_TYPE_UINT:
642
      /* This means every or_options_t uint or bool element
643
       * needs to be an int. Not, say, a uint16_t or char. */
644
645
646
647
648
649
650
651
652
653
654
      tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
      result->value = tor_strdup(buf);
      break;
    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
655
656
      if (*(smartlist_t**)value)
        result->value = smartlist_join_strings(*(smartlist_t**)value,",",0,NULL);
657
658
659
      else
        result->value = tor_strdup("");
      break;
660
661
662
663
664
    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;
665
666
667
    default:
      tor_free(result->key);
      tor_free(result);
668
      log_fn(LOG_WARN,"Bug: unknown type %d for known key %s", var->type, key);
669
670
671
672
673
674
      return NULL;
    }

  return result;
}

675
/** Iterate through the linked list of requested options <b>list</b>.
Nick Mathewson's avatar
Nick Mathewson committed
676
 * For each item, convert as appropriate and assign to <b>options</b>.
677
 * If an item is unrecognized, return -1 immediately,
678
679
680
681
 * 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
682
683
 * extending) their previous values.  Return 0 on success, -1 on bad key,
 * -2 on bad value.
684
 */
685
static int
686
config_assign(or_options_t *options, struct config_line_t *list, int reset)
687
{
688
  struct config_line_t *p;
689
  tor_assert(options);
690
691
692
693
694
695
696

  /* 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);
697
    }
698
699
  }

700
  /* pass 2: if we're reading from a resetting source, clear all mentioned
701
702
703
704
705
   * linelists. */
  if (reset) {
    for (p = list; p; p = p->next)
      config_reset_line(options, p->key);
  }
706

707
708
  /* pass 3: assign. */
  while (list) {
709
710
711
    int r;
    if ((r=config_assign_line(options, list, reset)))
      return r;
712
    list = list->next;
Roger Dingledine's avatar
Roger Dingledine committed
713
  }
714
  return 0;
715
716
}

717
/** Try assigning <b>list</b> to the global options. You do this by duping
718
 * options, assigning list to the new one, then validating it. If it's
719
 * ok, then throw out the old one and stick with the new one. Else,
720
721
 * revert to old and return failure.  Return 0 on success, -1 on bad
 * keys, -2 on bad values, -3 on bad transition.
722
723
 */
int
724
config_trial_assign(struct config_line_t *list, int reset)
725
{
726
  int r;
727
  or_options_t *trial_options = options_dup(get_options());
728

729
  if ((r=config_assign(trial_options, list, reset)) < 0) {
730
    options_free(trial_options);
731
    return r;
732
733
734
735
  }

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
736
    return -2;
737
738
  }

739
  if (options_transition_allowed(get_options(), trial_options) < 0) {
740
    options_free(trial_options);
741
    return -3;
742
743
  }

744
  set_options(trial_options); /* we liked it. put it in place. */
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  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;
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_BOOL:
      *(int*)lvalue = 0;
      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;
    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) {
787
    c = tor_malloc_zero(sizeof(struct config_line_t));
788
789
790
791
792
793
794
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    config_assign_line(options,c,0);
    config_free_lines(c);
  }
}

795
/** Set <b>options</b>-&gt;DirServers to contain the default directory
796
 * servers. */
797
static void
798
add_default_trusted_dirservers(or_options_t *options)
799
{
Nick Mathewson's avatar
Nick Mathewson committed
800
  /* moria1 */
801
802
  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
803
  /* moria2 */
804
805
  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
806
  /* tor26 */
807
808
  options->DirServers = config_line_prepend(options->DirServers, "DirServer",
     "62.116.124.106:9030 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D");
809
810
}

Nick Mathewson's avatar
Nick Mathewson committed
811
/** Print a usage message for tor. */
812
813
814
static void
print_usage(void)
{
815
  printf("tor -f <torrc> [args]\n"
816
817
         "See man page for more options. This -h is obsolete.\n");
#if 0
818
         "-b <bandwidth>\t\tbytes/second rate limiting\n"
819
         "-d <file>\t\tDebug file\n"
820
821
822
823
         "-l <level>\t\tLog level\n"
         "-r <file>\t\tList of known routers\n");
  printf("\nClient options:\n"
         "-e \"nick1 nick2 ...\"\t\tExit nodes\n"
824
         "-s <IP>\t\t\tPort to bind to for Socks\n");
825
826
  printf("\nServer options:\n"
         "-n <nick>\t\tNickname of router\n"
827
         "-o <port>\t\tOR port to bind to\n"
828
         "-p <file>\t\tPID file\n");
829
#endif
830
831
}

Nick Mathewson's avatar
Nick Mathewson committed
832
/**
833
834
 * Based on <b>address</b>, guess our public IP address and put it
 * in <b>addr</b>.
Nick Mathewson's avatar
Nick Mathewson committed
835
 */
836
837
838
int
resolve_my_address(const char *address, uint32_t *addr)
{
839
840
  struct in_addr in;
  struct hostent *rent;
841
  char hostname[256];
842
  int explicit_ip=1;
843

844
845
  tor_assert(addr);

846
847
  if (address) {
    strlcpy(hostname, address, sizeof(hostname));
848
  } else { /* then we need to guess our address */
849
    explicit_ip = 0; /* it's implicit */
850

851
    if (gethostname(hostname, sizeof(hostname)) < 0) {
852
853
854
      log_fn(LOG_WARN,"Error obtaining local hostname");
      return -1;
    }
855
    log_fn(LOG_DEBUG,"Guessed local host name as '%s'",hostname);
856
857
  }

858
  /* now we know hostname. resolve it and keep only the IP */
859

860
  if (tor_inet_aton(hostname, &in) == 0) {
861
862
    /* then we have to resolve it */
    explicit_ip = 0;
863
    rent = (struct hostent *)gethostbyname(hostname);
864
    if (!rent) {
865
      log_fn(LOG_WARN,"Could not resolve local Address %s. Failing.", hostname);
866
867
      return -1;
    }
Roger Dingledine's avatar
Roger Dingledine committed
868
    tor_assert(rent->h_length == 4);
869
    memcpy(&in.s_addr, rent->h_addr, rent->h_length);
870
  }
871
872

  if (!explicit_ip && is_internal_IP(htonl(in.s_addr))) {
873
    log_fn(LOG_WARN,"Address '%s' resolves to private IP '%s'. "
874
           "Please set the Address config option to be the IP you want to use.",
875
           hostname, inet_ntoa(in));
876
877
    return -1;
  }
878
879

  log_fn(LOG_DEBUG, "Resolved Address to %s.", inet_ntoa(in));
880
  *addr = ntohl(in.s_addr);
881
882
883
  return 0;
}

884
885
/** Called when we don't have a nickname set.  Try to guess a good
 * nickname based on the hostname, and return it. */
886
887
static char *
get_default_nickname(void)
888
889
890
891
{
  char localhostname[256];
  char *cp, *out, *outp;

892
  if (gethostname(localhostname, sizeof(localhostname)) < 0) {
893
894
895
    log_fn(LOG_WARN,"Error obtaining local hostname");
    return NULL;
  }
896

897
  /* Put it in lowercase; stop at the first dot. */
898
  for (cp = localhostname; *cp; ++cp) {
899
900
901
902
903
904
    if (*cp == '.') {
      *cp = '\0';
      break;
    }
    *cp = tolower(*cp);
  }
905

906
907
  /* Strip invalid characters. */
  cp = localhostname;
908
  out = outp = tor_malloc(strlen(localhostname) + 1);
909
910
911
912
913
914
915
  while (*cp) {
    if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
      *outp++ = *cp++;
    else
      cp++;
  }
  *outp = '\0';
916

917
918
919
920
921
922
923
  /* Enforce length. */
  if (strlen(out) > MAX_NICKNAME_LEN)
    out[MAX_NICKNAME_LEN]='\0';

  return out;
}

Nick Mathewson's avatar
Nick Mathewson committed
924
/** Release storage held by <b>options</b> */
925
static void
926
options_free(or_options_t *options)
927
{
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  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) {
      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:
943
      case CONFIG_TYPE_LINELIST_V:
944
945
946
947
948
949
950
951
952
953
        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;
954
955
956
      case CONFIG_TYPE_LINELIST_S:
        /* will be freed by corresponding LINELIST_V. */
        break;
957
958
    }
  }
959
}
960

961
962
963
964
965
966
967
968
969
970
971
972
973
/** 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.
 */
static int
option_is_same(or_options_t *o1, or_options_t *o2, config_var_t *var)
{
  void *v1, *v2;
  tor_assert(o1);
  tor_assert(o2);
  tor_assert(var);

  v1 = ((char*)o1) + var-> var_offset;
  v2 = ((char*)o2) + var-> var_offset;
Nick Mathewson's avatar
Nick Mathewson committed
974
  switch (var->type)
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
    {
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_BOOL:
      return (*(int*)v1) == (*(int*)v2);
    case CONFIG_TYPE_STRING: {
      const char *s1 = *(const char**)v1;
      const char *s2 = *(const char**)v2;
      return (!s1 && !s2) || (s1 && s2 && !strcmp(s1, s2));
    }
    case CONFIG_TYPE_DOUBLE:
      return (*(double*)v1) == (*(double*)v2);
    case CONFIG_TYPE_CSV: {
      smartlist_t *sl1 = *(smartlist_t**)v1;
      smartlist_t *sl2 = *(smartlist_t**)v2;
      int i;
      if ((sl1 && !sl2) || (!sl1 && sl2))
        return 0;
      else if (!sl1 && !sl2)
        return 1;
      else if (smartlist_len(sl1) != smartlist_len(sl2))
        return 0;
      for (i=0;i<smartlist_len(sl1);++i) {
        if (strcmp(smartlist_get(sl1,i), smartlist_get(sl2,i)))
          return 0;
      }
      return 1;
For faster browsing, not all history is shown. View entire blame