config.c 64.8 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
static int option_is_same(or_options_t *o1, or_options_t *o2,const char *name);
164
165
166
167
168
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);

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

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

/** Command-line and config-file options. */
static or_options_t *global_options=NULL;
190
191
/** Name of ost recently read torrc file. */
static char *config_fname = NULL;
192

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

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

/** 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();
226
227

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

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

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

261
  if (set_max_file_descriptors(options->MaxConn) < 0)
262
263
    return -1;

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

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

281
  /* Start backgrounding the process, if requested. */
282

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

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

301
302
303
304
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();

305
306
  init_cookie_authentication(options->CookieAuthentication);

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

313
314
315
316
  /* Set up accounting */
  if (get_options()->AccountingMaxKB)
    configure_accounting(time(NULL));

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

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);
328
    log_fn(LOG_DEBUGS, "We changed these options:\n%s",smin);
329
330
331
332
333
    tor_free(smin);
    tor_free(smax);
  }
#endif

334
335
336
337
338
339
  /* 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();

340
  return 0;
341
342
343
344
345
346
}

/*
 * Functions to parse config options
 */

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

Nick Mathewson's avatar
Nick Mathewson committed
365
/** Helper: Read a list of configuration options from the command line. */
366
367
368
static struct config_line_t *
config_get_commandlines(int argc, char **argv)
{
369
370
  struct config_line_t *new;
  struct config_line_t *front = NULL;
371
372
373
  char *s;
  int i = 1;

374
  while (i < argc-1) {
375
376
377
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
378
      continue;
379
380
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
381
      continue;
382
383
    }

384
    new = tor_malloc(sizeof(struct config_line_t));
385
    s = argv[i];
386

387
388
    while(*s == '-')
      s++;
389

390
    new->key = tor_strdup(expand_abbrev(s, 1));
391
    new->value = tor_strdup(argv[i+1]);
392
393

    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
394
        new->key, new->value);
395
396
397
398
399
400
401
    new->next = front;
    front = new;
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
402
403
/** Helper: allocate a new configuration option mapping 'key' to 'val',
 * prepend it to 'front', and return the newly allocated config_line_t */
404
struct config_line_t *
405
406
407
408
409
config_line_prepend(struct config_line_t *front,
                    const char *key,
                    const char *val)
{
  struct config_line_t *newline;
410

411
412
413
414
415
416
417
  newline = tor_malloc(sizeof(struct config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
  newline->next = front;
  return newline;
}

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

428
429
430
431
432
433
434
435
436
  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);
437

438
  *result = list;
439
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
440
441
}

Nick Mathewson's avatar
Nick Mathewson committed
442
443
444
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
445
void
446
447
config_free_lines(struct config_line_t *front)
{
448
  struct config_line_t *tmp;
449

450
  while (front) {
451
452
453
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
454
455
456
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
457
458
459
  }
}

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

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

499
500
501
502
503
504
505
  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)) {
506
    tor_free(c->key);
507
    c->key = tor_strdup(var->name);
508
509
  }

510
  if (reset && !strlen(c->value)) {
511
    option_reset(options, var);
512
513
514
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
515
  lvalue = ((char*)options) + var->var_offset;
516
  switch(var->type) {
517

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

  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
531
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
532
      return -2;
533
    }
534
    *(int *)lvalue = i;
535
536
537
    break;

  case CONFIG_TYPE_STRING:
538
539
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
540
541
542
    break;

  case CONFIG_TYPE_DOUBLE:
543
    *(double *)lvalue = atof(c->value);
544
545
546
    break;

  case CONFIG_TYPE_CSV:
547
548
    if (*(smartlist_t**)lvalue == NULL)
      *(smartlist_t**)lvalue = smartlist_create();
549

550
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
551
552
553
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

554
555
556
557
558
559
560
561
  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;
562
563
564
565

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
566
567
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
568
    return -2;
569
570
571
  default:
    tor_assert(0);
    break;
572
  }
573
  return 0;
574
575
}

576
577
578
579
580
581
582
583
584
585
/** 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. */

586
  option_reset(options, var);
587
588
}

589
590
591
592
593
594
595
596
/** 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);
}

597
598
599
600
601
602
603
604
605
/** 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;
606
  tor_assert(options && key);
607
608
609
610
611

  var = config_find_option(key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", key);
    return NULL;
612
613
614
  } else if (var->type == CONFIG_TYPE_LINELIST_S) {
    log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key);
    return NULL;
615
616
617
  }
  value = ((char*)options) + var->var_offset;

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

  return result;
}

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

  /* 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);
703
    }
704
705
  }

706
  /* pass 2: if we're reading from a resetting source, clear all mentioned
707
708
709
710
711
   * linelists. */
  if (reset) {
    for (p = list; p; p = p->next)
      config_reset_line(options, p->key);
  }
712

713
714
  /* pass 3: assign. */
  while (list) {
715
716
717
    int r;
    if ((r=config_assign_line(options, list, reset)))
      return r;
718
    list = list->next;
Roger Dingledine's avatar
Roger Dingledine committed
719
  }
720
  return 0;
721
722
}

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

735
  if ((r=config_assign(trial_options, list, reset)) < 0) {
736
    options_free(trial_options);
737
    return r;
738
739
740
741
  }

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
742
    return -2;
743
744
  }

745
  if (options_transition_allowed(get_options(), trial_options) < 0) {
746
    options_free(trial_options);
747
    return -3;
748
749
  }

750
  set_options(trial_options); /* we liked it. put it in place. */
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
787
788
789
790
791
792
  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) {
793
    c = tor_malloc_zero(sizeof(struct config_line_t));
794
795
796
797
798
799
800
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    config_assign_line(options,c,0);
    config_free_lines(c);
  }
}

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

Nick Mathewson's avatar
Nick Mathewson committed
817
/** Print a usage message for tor. */
818
819
820
static void
print_usage(void)
{
821
  printf("tor -f <torrc> [args]\n"
822
823
         "See man page for more options. This -h is obsolete.\n");
#if 0
824
         "-b <bandwidth>\t\tbytes/second rate limiting\n"
825
         "-d <file>\t\tDebug file\n"
826
827
828
829
         "-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"
830
         "-s <IP>\t\t\tPort to bind to for Socks\n");
831
832
  printf("\nServer options:\n"
         "-n <nick>\t\tNickname of router\n"
833
         "-o <port>\t\tOR port to bind to\n"
834
         "-p <file>\t\tPID file\n");
835
#endif
836
837
}

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

850
851
  tor_assert(addr);

852
853
  if (address) {
    strlcpy(hostname, address, sizeof(hostname));
854
  } else { /* then we need to guess our address */
855
    explicit_ip = 0; /* it's implicit */
856

857
    if (gethostname(hostname, sizeof(hostname)) < 0) {
858
859
860
      log_fn(LOG_WARN,"Error obtaining local hostname");
      return -1;
    }
861
    log_fn(LOG_DEBUG,"Guessed local host name as '%s'",hostname);
862
863
  }

864
  /* now we know hostname. resolve it and keep only the IP */
865

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

  if (!explicit_ip && is_internal_IP(htonl(in.s_addr))) {
879
    log_fn(LOG_WARN,"Address '%s' resolves to private IP '%s'. "
880
           "Please set the Address config option to be the IP you want to use.",
881
           hostname, inet_ntoa(in));
882
883
    return -1;
  }
884
885

  log_fn(LOG_DEBUG, "Resolved Address to %s.", inet_ntoa(in));
886
  *addr = ntohl(in.s_addr);
887
888
889
  return 0;
}

890
891
/** Called when we don't have a nickname set.  Try to guess a good
 * nickname based on the hostname, and return it. */
892
893
static char *
get_default_nickname(void)
894
895
896
897
{
  char localhostname[256];
  char *cp, *out, *outp;

898
  if (gethostname(localhostname, sizeof(localhostname)) < 0) {
899
900
901
    log_fn(LOG_WARN,"Error obtaining local hostname");
    return NULL;
  }
902

903
  /* Put it in lowercase; stop at the first dot. */
904
  for (cp = localhostname; *cp; ++cp) {
905
906
907
908
909
910
    if (*cp == '.') {
      *cp = '\0';
      break;
    }
    *cp = tolower(*cp);
  }
911

912
913
  /* Strip invalid characters. */
  cp = localhostname;
914
  out = outp = tor_malloc(strlen(localhostname) + 1);
915
916
917
918
919
920
921
  while (*cp) {
    if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
      *outp++ = *cp++;
    else
      cp++;
  }
  *outp = '\0';
922

923
924
925
926
927
928
929
  /* Enforce length. */
  if (strlen(out) > MAX_NICKNAME_LEN)
    out[MAX_NICKNAME_LEN]='\0';

  return out;
}

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

967
968
969
970
/** 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
971
option_is_same(or_options_t *o1, or_options_t *o2, const char *name)
972
{
973
974
975
976
977
978
979
980
981
  struct config_line_t *c1, *c2;
  int r = 1;
  c1 = config_get_assigned_option(o1, name);
  c2 = config_get_assigned_option(o2, name);
  while (c1 && c2) {
    if (strcasecmp(c1->key, c2->key) ||
        strcmp(c1->value, c2->value)) {
      r = 0;
      break;
982
    }
983
984
985
986
987
988
989
990
991
    c1 = c1->next;
    c2 = c2->next;
  }
  if (r && (c1 || c2)) {
    r = 0;
  }
  config_free_lines(c1);
  config_free_lines(c2);
  return r;
992
993
}

994
995
996
/** Copy storage held by <b>old</b> into a new or_options_t and return it. */
static or_options_t *
options_dup(or_options_t *old)
997
{
Roger Dingledine's avatar
Roger Dingledine committed
998
  or_options_t *newopts;
999
1000
  int i;
  struct config_line_t *line;
For faster browsing, not all history is shown. View entire blame