config.c 97.3 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
/* Copyright 2001 Matej Pfajfar.
 * Copyright 2001-2004 Roger Dingledine.
Nick Mathewson's avatar
Nick Mathewson committed
3
 * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
4
5
/* See LICENSE for licensing information */
/* $Id$ */
6
const char config_c_id[] = "$Id$";
7

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

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

Nick Mathewson's avatar
Nick Mathewson committed
19
20
/** Enumeration of types which option values can take */
typedef enum config_type_t {
21
22
  CONFIG_TYPE_STRING = 0,   /**< An arbitrary string. */
  CONFIG_TYPE_UINT,         /**< A non-negative integer less than MAX_INT */
23
24
  CONFIG_TYPE_INTERVAL,     /**< A number of seconds, with optional units*/
  CONFIG_TYPE_MEMUNIT,      /**< A number of bytes, with optional units*/
25
26
  CONFIG_TYPE_DOUBLE,       /**< A floating-point value */
  CONFIG_TYPE_BOOL,         /**< A boolean value, expressed as 0 or 1. */
27
  CONFIG_TYPE_ISOTIME,      /**< An ISO-formated time relative to GMT. */
28
29
30
  CONFIG_TYPE_CSV,          /**< A list of strings, separated by commas and optional
                              * whitespace. */
  CONFIG_TYPE_LINELIST,     /**< Uninterpreted config lines */
31
32
33
34
35
  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.
                             */
36
  CONFIG_TYPE_OBSOLETE,     /**< Obsolete (ignored) option. */
Nick Mathewson's avatar
Nick Mathewson committed
37
} config_type_t;
38

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

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

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

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

Nick Mathewson's avatar
Nick Mathewson committed
93
94
95
96
/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
97
static config_var_t _option_vars[] = {
Nick Mathewson's avatar
Nick Mathewson committed
98
99
  VAR("AccountingMax",       MEMUNIT,   AccountingMax,        "0 bytes"),
  VAR("AccountingMaxKB",     UINT,     _AccountingMaxKB,     "0"),
100
  VAR("AccountingStart",     STRING,   AccountingStart,      NULL),
Nick Mathewson's avatar
Nick Mathewson committed
101
  VAR("Address",             STRING,   Address,              NULL),
102
  VAR("AllowUnverifiedNodes",CSV,      AllowUnverifiedNodes, "middle,rendezvous"),
103
  VAR("AuthoritativeDirectory",BOOL,   AuthoritativeDir,     "0"),
104
  VAR("BandwidthBurst",      MEMUNIT,  BandwidthBurst,       "5 MB"),
Nick Mathewson's avatar
Nick Mathewson committed
105
  VAR("BandwidthRate",       MEMUNIT,  BandwidthRate,        "2 MB"),
106
  VAR("ClientOnly",          BOOL,     ClientOnly,           "0"),
Nick Mathewson's avatar
Nick Mathewson committed
107
  VAR("ConnLimit",           UINT,     ConnLimit,            "1024"),
108
  VAR("ContactInfo",         STRING,   ContactInfo,          NULL),
109
  VAR("ControlPort",         UINT,     ControlPort,          "0"),
110
  VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
111
  VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
Nick Mathewson's avatar
Nick Mathewson committed
112
  VAR("DebugLogFile",        STRING,   DebugLogFile,         NULL),
113
  VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
114
  VAR("DirBindAddress",      LINELIST, DirBindAddress,       NULL),
Nick Mathewson's avatar
Nick Mathewson committed
115
  VAR("DirFetchPeriod",      INTERVAL, DirFetchPeriod,       "0 seconds"),  /** DOCDOC **/
116
  VAR("DirPolicy",           LINELIST, DirPolicy,            NULL),
Nick Mathewson's avatar
Nick Mathewson committed
117
118
  VAR("DirPort",             UINT,     DirPort,              "0"),
  VAR("DirPostPeriod",       INTERVAL, DirPostPeriod,        "20 minutes"),
119
120
121
  VAR("DirServer",           LINELIST, DirServers,           NULL),
  VAR("EntryNodes",          STRING,   EntryNodes,           NULL),
  VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
Nick Mathewson's avatar
Nick Mathewson committed
122
123
  VAR("ExitNodes",           STRING,   ExitNodes,            NULL),
  VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
124
  VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
125
126
  VAR("FirewallPorts",       CSV,      FirewallPorts,        ""),
  VAR("FirewallIPs",         CSV,      FirewallIPs,          NULL),
127
  VAR("Group",               STRING,   Group,                NULL),
Nick Mathewson's avatar
Nick Mathewson committed
128
  VAR("HardwareAccel",       BOOL,     HardwareAccel,        "1"),
129
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
Nick Mathewson's avatar
Nick Mathewson committed
130
131
132
133
134
  VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
  VAR("HiddenServiceNodes",  LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
  VAR("HiddenServicePort",   LINELIST_S, RendConfigLines,    NULL),
135
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
136
  VAR("HttpProxyAuthenticator",STRING, HttpProxyAuthenticator,NULL),
137
  VAR("HttpsProxy",          STRING,   HttpsProxy,           NULL),
138
  VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL),
139
  OBSOLETE("IgnoreVersion"),
140
  VAR("KeepalivePeriod",     INTERVAL, KeepalivePeriod,      "5 minutes"),
141
  VAR("Log",                 LINELIST, Logs,                 NULL),
142
  OBSOLETE("LinkPadding"),
Nick Mathewson's avatar
Nick Mathewson committed
143
144
145
146
147
148
  VAR("LogFile",             LINELIST_S, OldLogOptions,      NULL),
  VAR("LogLevel",            LINELIST_S, OldLogOptions,      NULL),
  VAR("LongLivedPorts",      CSV,      LongLivedPorts,       "21,22,706,1863,5050,5190,5222,5223,6667,8300,8888"),
  VAR("MapAddress",          LINELIST, AddressMap,           NULL),
  VAR("MaxAdvertisedBandwidth",MEMUNIT,MaxAdvertisedBandwidth,"128 TB"),
  VAR("MaxCircuitDirtiness", INTERVAL, MaxCircuitDirtiness,  "10 minutes"),
149
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
150
  VAR("MonthlyAccountingStart",UINT,   _MonthlyAccountingStart,"0"),
Nick Mathewson's avatar
Nick Mathewson committed
151
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
152
  VAR("NewCircuitPeriod",    INTERVAL, NewCircuitPeriod,     "30 seconds"),
Nick Mathewson's avatar
Nick Mathewson committed
153
154
155
  VAR("Nickname",            STRING,   Nickname,             NULL),
  VAR("NoPublish",           BOOL,     NoPublish,            "0"),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
156
  VAR("NumCpus",             UINT,     NumCpus,              "1"),
Nick Mathewson's avatar
Nick Mathewson committed
157
  VAR("NumHelperNodes",      UINT,     NumHelperNodes,       "3"),
158
  VAR("ORBindAddress",       LINELIST, ORBindAddress,        NULL),
Nick Mathewson's avatar
Nick Mathewson committed
159
  VAR("ORPort",              UINT,     ORPort,               "0"),
160
161
  VAR("OutboundBindAddress", STRING,   OutboundBindAddress,  NULL),
  VAR("PathlenCoinWeight",   DOUBLE,   PathlenCoinWeight,    "0.3"),
Nick Mathewson's avatar
Nick Mathewson committed
162
163
  VAR("PidFile",             STRING,   PidFile,              NULL),
  VAR("RecommendedVersions", LINELIST, RecommendedVersions,  NULL),
164
  VAR("RedirectExit",        LINELIST, RedirectExit,         NULL),
Nick Mathewson's avatar
Nick Mathewson committed
165
166
167
  VAR("RendExcludeNodes",    STRING,   RendExcludeNodes,     NULL),
  VAR("RendNodes",           STRING,   RendNodes,            NULL),
  VAR("RendPostPeriod",      INTERVAL, RendPostPeriod,       "20 minutes"),
168
  VAR("RephistTrackTime",    INTERVAL, RephistTrackTime,     "24 hours"),
169
  OBSOLETE("RouterFile"),
170
171
  VAR("RunAsDaemon",         BOOL,     RunAsDaemon,          "0"),
  VAR("RunTesting",          BOOL,     RunTesting,           "0"),
172
  VAR("SafeLogging",         BOOL,     SafeLogging,          "1"),
173
  VAR("ShutdownWaitLength",  INTERVAL, ShutdownWaitLength,   "30 seconds"),
174
175
  VAR("SocksBindAddress",    LINELIST, SocksBindAddress,     NULL),
  VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),
Nick Mathewson's avatar
Nick Mathewson committed
176
177
178
179
  VAR("SocksPort",           UINT,     SocksPort,            "9050"),
  VAR("StatusFetchPeriod",   INTERVAL, StatusFetchPeriod,    "0 seconds"),  /** DOCDOC */
  VAR("StrictEntryNodes",    BOOL,     StrictEntryNodes,     "0"),
  VAR("StrictExitNodes",     BOOL,     StrictExitNodes,      "0"),
180
  VAR("SysLog",              LINELIST_S, OldLogOptions,      NULL),
Nick Mathewson's avatar
Nick Mathewson committed
181
182
  VAR("TrackHostExits",      CSV,      TrackHostExits,       NULL),
  VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
183
  OBSOLETE("TrafficShaping"),
184
  VAR("UseHelperNodes",      BOOL,     UseHelperNodes,       "0"),
Nick Mathewson's avatar
Nick Mathewson committed
185
  VAR("User",                STRING,   User,                 NULL),
186
  VAR("__LeaveStreamsUnattached", BOOL,LeaveStreamsUnattached, "0"),
187
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
188
};
189
190
191
192
193
#undef VAR

#define VAR(name,conftype,member,initvalue) \
  { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), initvalue }
static config_var_t _state_vars[] = {
Nick Mathewson's avatar
Nick Mathewson committed
194
  VAR("AccountingBytesReadInterval", MEMUNIT, AccountingBytesReadInInterval,NULL),
195
196
197
  VAR("AccountingBytesWrittenInInterval", MEMUNIT,
      AccountingBytesWrittenInInterval, NULL),
  VAR("AccountingExpectedUsage", MEMUNIT,     AccountingExpectedUsage, NULL),
Nick Mathewson's avatar
Nick Mathewson committed
198
199
  VAR("AccountingIntervalStart", ISOTIME,  AccountingIntervalStart, NULL),
  VAR("AccountingSecondsActive", INTERVAL,    AccountingSecondsActive, NULL),
200
201
202
  VAR("HelperNode",              LINELIST_S,  HelperNodes,          NULL),
  VAR("HelperNodeDownSince",     LINELIST_S,  HelperNodes,          NULL),
  VAR("HelperNodeUnlistedSince", LINELIST_S,  HelperNodes,          NULL),
Nick Mathewson's avatar
Nick Mathewson committed
203
204
205
  VAR("HelperNodes",             LINELIST_V,  HelperNodes,          NULL),
  VAR("LastWritten",             ISOTIME,     LastWritten,          NULL),

206
207
208
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};

209
210
211
#undef VAR
#undef OBSOLETE

212
213
214
215
216
217
218
/** DOCDOC*/
typedef struct config_var_description_t {
  const char *name;
  const char *description;
} config_var_description_t;

static config_var_description_t options_description[] = {
219
  { "Address", "The advertised (external) address we should use." },
220
221
222
223
224
225
226
227
228
229
230
231
232
  // { "AccountingStart", ""},
  { NULL, NULL },
};

static config_var_description_t state_description[] = {
  { "HelperNode", "One of the nodes we have chosen as a fixed entry" },
  { "HelperNodeDownSince",
    "The last helper node has been down since this time." },
  { "HelperNodeUnlistedSince",
    "The last helper node has been unlisted since this time." },
  { NULL, NULL },
};

233
234
235
236
237
238
239
240
241
typedef int (*validate_fn_t)(void*);

typedef struct {
  size_t size;
  uint32_t magic;
  off_t magic_offset;
  config_abbrev_t *abbrevs;
  config_var_t *vars;
  validate_fn_t validate_fn;
242
  config_var_description_t *descriptions;
243
244
245
246
247
248
249
} config_format_t;

#define CHECK(fmt, cfg) do {                                            \
    tor_assert(fmt && cfg);                                             \
    tor_assert((fmt)->magic == *(uint32_t*)(((char*)(cfg))+fmt->magic_offset)); \
  } while (0)

Nick Mathewson's avatar
Nick Mathewson committed
250
/** Largest allowed config line */
251
#define CONFIG_LINE_T_MAXLEN 4096
252

253
static void config_line_append(config_line_t **lst,
254
                               const char *key, const char *val);
255
256
static void option_reset(config_format_t *fmt, or_options_t *options,
                         config_var_t *var);
257
static void config_free(config_format_t *fmt, void *options);
258
259
260
static int option_is_same(config_format_t *fmt,
                          or_options_t *o1, or_options_t *o2,const char *name);
static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
261
262
263
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);
264
static void config_register_addressmaps(or_options_t *options);
265

266
static int parse_dir_server_line(const char *line, int validate_only);
267
static int parse_redirect_line(smartlist_t *result,
268
                               config_line_t *line);
269
270
271
static int parse_log_severity_range(const char *range, int *min_out,
                                    int *max_out);
static int convert_log_option(or_options_t *options,
272
273
                              config_line_t *level_opt,
                              config_line_t *file_opt, int isDaemon);
274
275
276
277
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);
278
static int validate_data_directory(or_options_t *options);
279
static int write_configuration_file(const char *fname, or_options_t *options);
280
static config_line_t *get_assigned_option(config_format_t *fmt,
281
                                     or_options_t *options, const char *key);
282
283
static void config_init(config_format_t *fmt, void *options);
static int or_state_validate(or_state_t *options);
284

285
286
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
287
static void print_cvs_version(void);
288
static int init_libevent(void);
289
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
290
static void check_libevent_version(const char *m, const char *v, int server);
291
#endif
292

293
294
#define OR_OPTIONS_MAGIC 9090909

295
static config_format_t options_format = {
296
297
298
  sizeof(or_options_t),
  OR_OPTIONS_MAGIC,
  STRUCT_OFFSET(or_options_t, _magic),
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  _option_abbrevs,
  _option_vars,
  (validate_fn_t)options_validate,
  options_description
};

#define OR_STATE_MAGIC 0x57A73f57

static config_format_t state_format = {
  sizeof(or_state_t),
  OR_STATE_MAGIC,
  STRUCT_OFFSET(or_state_t, _magic),
  NULL,
  _state_vars,
  (validate_fn_t)or_state_validate,
  state_description
315
316
};

317
318
319
320
321
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
322
static or_options_t *global_options = NULL;
Roger Dingledine's avatar
Roger Dingledine committed
323
/** Name of most recently read torrc file. */
324
static char *config_fname = NULL;
325
326
/** Persistant serialized state. */
static or_state_t *global_state = NULL;
327

328
329
330
331
332
333
334
335
336
static void *
config_alloc(config_format_t *fmt)
{
  void *opts = opts = tor_malloc_zero(fmt->size);
  *(uint32_t*)(((char*)opts)+fmt->magic_offset) = fmt->magic;
  CHECK(fmt, opts);
  return opts;
}

337
338
/** Return the currently configured options. */
or_options_t *
339
340
get_options(void)
{
341
342
343
  tor_assert(global_options);
  return global_options;
}
344

Roger Dingledine's avatar
Roger Dingledine committed
345
/** Change the current global options to contain <b>new_val</b> instead
346
 * of their current value; free the old value as necessary.
347
348
 */
void
349
350
set_options(or_options_t *new_val)
{
351
  if (global_options)
352
    config_free(&options_format, global_options);
353
  global_options = new_val;
354
355
}

356
357
358
void
config_free_all(void)
{
359
  config_free(&options_format, global_options);
360
361
362
  tor_free(config_fname);
}

363
364
365
366
/** If options->SafeLogging is on, return a not very useful string,
 * else return address.
 */
const char *
367
368
safe_str(const char *address)
{
369
370
371
372
373
374
  if (get_options()->SafeLogging)
    return "[scrubbed]";
  else
    return address;
}

375
376
377
/** 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.
378
379
380
381
382
383
 *
 * 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.
384
385
 */
int
386
387
options_act(void)
{
388
  config_line_t *cl;
389
  or_options_t *options = get_options();
390
391
392
  static int libevent_initialized = 0;

  if (options->RunAsDaemon) {
393
    start_daemon();
394
  }
395
396

  clear_trusted_dir_servers();
397
  for (cl = options->DirServers; cl; cl = cl->next) {
398
399
    if (parse_dir_server_line(cl->value, 0)<0) {
      log_fn(LOG_ERR,
400
             "Bug: Previously validated DirServer line could not be added!");
401
      return -1;
402
403
404
    }
  }

405
  if (rend_config_services(options, 0)<0) {
406
    log_fn(LOG_ERR,
407
           "Bug: Previously validated hidden services line could not be added!");
408
    return -1;
409
  }
410

411
412
413
  if (options->EntryNodes && strlen(options->EntryNodes))
    options->UseHelperNodes = 0;

414
  /* Setuid/setgid as appropriate */
415
416
  if (options->User || options->Group) {
    if (switch_id(options->User, options->Group) != 0) {
417
418
419
420
421
      return -1;
    }
  }

  /* Ensure data directory is private; create if possible. */
422
  if (check_private_dir(options->DataDirectory, CPD_CREATE) != 0) {
423
    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
424
           options->DataDirectory);
425
426
427
428
429
430
431
432
    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;

433
  mark_logs_temp(); /* Close current logs once new logs are open. */
434
  if (options_init_logs(options, 0)<0) /* Configure the log(s) */
435
    return -1;
436

437
438
439
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
440
  add_callback_log(LOG_ERR, LOG_ERR, control_event_logmsg);
441
  control_adjust_event_log_severity();
442

443
444
445
446
447
448
449
  /* Set up libevent. */
  if (!libevent_initialized) {
    if (init_libevent())
      return -1;
    libevent_initialized = 1;
  }

450
451
452
453
454
  /* Load state */
  if (! global_state)
    if (or_state_load())
      return -1;

455
  options->_ConnLimit =
456
    set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
457
  if (options->_ConnLimit < 0)
458
459
    return -1;

460
461
462
463
464
465
466
467
468
  {
    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);
  }

469
  /* Finish backgrounding the process */
470
  if (options->RunAsDaemon) {
471
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
472
    finish_daemon(options->DataDirectory);
473
474
475
476
  }

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

480
481
482
  /* Register addressmap directives */
  config_register_addressmaps(options);

483
484
485
486
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();

487
488
  init_cookie_authentication(options->CookieAuthentication);

489
490
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
491
    log_fn(LOG_ERR,"Error loading rendezvous service keys");
492
493
494
    return -1;
  }

495
  /* Set up accounting */
496
  if (accounting_parse_options(options, 0)<0) {
497
    log_fn(LOG_ERR,"Error in accounting options");
498
499
    return -1;
  }
500
  if (accounting_is_enabled(options))
501
502
    configure_accounting(time(NULL));

503
  if (!we_are_hibernating() && retry_all_listeners(0) < 0) {
504
505
506
507
    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
    return -1;
  }

508
509
510
511
512
513
  /* 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();

514
  return 0;
515
516
517
518
519
520
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
521
/** If <b>option</b> is an official abbreviation for a longer option,
522
523
524
 * 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. */
525
static const char *
526
expand_abbrev(config_format_t *fmt, const char *option, int command_line)
527
528
{
  int i;
529
530
531
  if (! fmt->abbrevs)
    return option;
  for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
532
    /* Abbreviations aren't casei. */
533
534
535
    if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
        (command_line || !fmt->abbrevs[i].commandline_only)) {
      return fmt->abbrevs[i].full;
536
    }
537
538
539
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
540

Nick Mathewson's avatar
Nick Mathewson committed
541
/** Helper: Read a list of configuration options from the command line. */
542
static config_line_t *
543
544
config_get_commandlines(int argc, char **argv)
{
545
546
  config_line_t *front = NULL;
  config_line_t **new = &front;
547
548
549
  char *s;
  int i = 1;

550
  while (i < argc-1) {
551
552
553
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
554
      continue;
555
556
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
557
      continue;
Nick Mathewson's avatar
Nick Mathewson committed
558
559
560
    } else if (!strcmp(argv[i],"--nt-service")) {
      i += 1;
      continue;
561
562
    }

563
    *new = tor_malloc_zero(sizeof(config_line_t));
564
    s = argv[i];
565

566
    while (*s == '-')
567
      s++;
568

569
    (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1));
570
571
    (*new)->value = tor_strdup(argv[i+1]);
    (*new)->next = NULL;
572
    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
573
574
575
        (*new)->key, (*new)->value);

    new = &((*new)->next);
576
577
578
579
580
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
581
/** Helper: allocate a new configuration option mapping 'key' to 'val',
582
583
 * append it to *<b>lst</b>. */
static void
584
config_line_append(config_line_t **lst,
585
586
                   const char *key,
                   const char *val)
587
{
588
  config_line_t *newline;
589

590
  newline = tor_malloc(sizeof(config_line_t));
591
592
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
593
594
595
596
597
  newline->next = NULL;
  while (*lst)
    lst = &((*lst)->next);

  (*lst) = newline;
598
599
}

600
601
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
602
603
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
604
int
605
config_get_lines(char *string, config_line_t **result)
606
{
607
  config_line_t *list = NULL, **next;
608
  char *k, *v;
609

610
  next = &list;
611
612
613
614
615
616
  do {
    string = parse_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      return -1;
    }
617
618
619
620
    if (k && v) {
      /* This list can get long, so we keep a pointer to the end of it
       * rather than using config_line_append over and over and getting n^2
       * performance.  This is the only really long list. */
621
      *next = tor_malloc(sizeof(config_line_t));
622
623
624
625
626
      (*next)->key = tor_strdup(k);
      (*next)->value = tor_strdup(v);
      (*next)->next = NULL;
      next = &((*next)->next);
    }
627
  } while (*string);
628

629
  *result = list;
630
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
631
632
}

Nick Mathewson's avatar
Nick Mathewson committed
633
634
635
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
636
void
637
config_free_lines(config_line_t *front)
638
{
639
  config_line_t *tmp;
640

641
  while (front) {
642
643
644
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
645
646
647
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
648
649
650
  }
}

651
652
653
654
655
656
657
658
659
660
661
662
/** DOCDOC */
static const char *
config_find_description(config_format_t *fmt, const char *name)
{
  int i;
  for (i=0; fmt->descriptions[i].name; ++i) {
    if (!strcasecmp(name, fmt->descriptions[i].name))
      return fmt->descriptions[i].description;
  }
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
663
664
665
666
/** 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.
 */
667
static config_var_t *
668
config_find_option(config_format_t *fmt, const char *key)
669
670
{
  int i;
671
  size_t keylen = strlen(key);
672
  if (!keylen)
673
    return NULL; /* if they say "--" on the commandline, it's not an option */
Nick Mathewson's avatar
Nick Mathewson committed
674
  /* First, check for an exact (case-insensitive) match */
675
  for (i=0; fmt->vars[i].name; ++i) {
676
    if (!strcasecmp(key, fmt->vars[i].name)) {
677
      return &fmt->vars[i];
678
    }
Nick Mathewson's avatar
Nick Mathewson committed
679
680
  }
  /* If none, check for an abbreviated match */
681
682
  for (i=0; fmt->vars[i].name; ++i) {
    if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
683
      log_fn(LOG_WARN, "The abbreviation '%s' is deprecated. "
684
          "Please use '%s' instead",
685
686
             key, fmt->vars[i].name);
      return &fmt->vars[i];
687
688
    }
  }
689
  /* Okay, unrecognized options */
690
691
692
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
693
/** If <b>c</b> is a syntactically valid configuration line, update
694
695
 * <b>options</b> with its value and return 0.  Otherwise return -1 for bad key,
 * -2 for bad value.
696
697
698
699
 *
 * If 'reset' is set, and we get a line containing no value, restore the
 * option to its default value.
 */
700
static int
701
config_assign_line(config_format_t *fmt,
702
                   or_options_t *options, config_line_t *c, int reset)
703
{
704
  int i, ok;
705
706
  config_var_t *var;
  void *lvalue;
707

708
709
710
  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
711
712
713
714
715
716
  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)) {
717
    tor_free(c->key);
718
    c->key = tor_strdup(var->name);
719
720
  }

721
  if (reset && !strlen(c->value)) {
722
    option_reset(fmt, options, var);
723
724
725
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
726
  lvalue = ((char*)options) + var->var_offset;
727
  switch (var->type) {
728

729
730
731
  case CONFIG_TYPE_UINT:
    i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
    if (!ok) {
732
      log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.",
733
          c->key,c->value);
734
      return -2;
735
    }
736
    *(int *)lvalue = i;
737
738
    break;

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
  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;
  }

757
758
759
  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
760
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
761
      return -2;
762
    }
763
    *(int *)lvalue = i;
764
765
766
    break;

  case CONFIG_TYPE_STRING:
767
768
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
769
770
771
    break;

  case CONFIG_TYPE_DOUBLE:
772
    *(double *)lvalue = atof(c->value);
773
774
    break;

775
776
777
778
779
780
781
  case CONFIG_TYPE_ISOTIME:
    if (parse_iso_time(c->value, (time_t *)lvalue)) {
      log(LOG_WARN, "Invalid time '%s' for keyword '%s'", c->value, c->key);
      return -2;
    }
    break;

782
  case CONFIG_TYPE_CSV:
783
784
785
786
    if (*(smartlist_t**)lvalue) {
      SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
      smartlist_clear(*(smartlist_t**)lvalue);
    } else {
787
      *(smartlist_t**)lvalue = smartlist_create();
788
    }
789

790
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
791
792
793
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

794
795
  case CONFIG_TYPE_LINELIST:
  case CONFIG_TYPE_LINELIST_S:
796
    config_line_append((config_line_t**)lvalue, c->key, c->value);
797
    break;
798
799
800
801

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
802
803
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
804
    return -2;
805
806
807
  default:
    tor_assert(0);
    break;
808
  }
809
  return 0;
810
811
}

812
813
/** restore the option named <b>key</b> in options to its default value. */
static void
814
config_reset_line(config_format_t *fmt, or_options_t *options, const char *key)
815
816
817
{
  config_var_t *var;

818
819
820
  CHECK(fmt, options);

  var = config_find_option(fmt, key);
821
822
823
  if (!var)
    return; /* give error on next pass. */

824
  option_reset(fmt, options, var);
825
826
}

827
828
/** Return true iff key is a valid configuration option. */
int
829
option_is_recognized(const char *key)
830
{
831
  config_var_t *var = config_find_option(&options_format, key);
832
833
834
  return (var != NULL);
}

835
836
/** Return the canonical name of a configuration option. */
const char *
837
option_get_canonical_name(const char *key)
838
{
839
  config_var_t *var = config_find_option(&options_format, key);
840
841
842
  return var->name;
}

843
844
/** Return a canonicalized list of the options assigned for key.
 */
845
config_line_t *
846
option_get_assignment(or_options_t *options, const char *key)
847
{
848
  return get_assigned_option(&options_format, options, key);
849
850
}

851
static config_line_t *
852
get_assigned_option(config_format_t *fmt, or_options_t *options, const char *key)
853
854
855
856
{
  config_var_t *var;
  const void *value;
  char buf[32];
857
  config_line_t *result;
858
  tor_assert(options && key);
859

860
861
862
  CHECK(fmt, options);

  var = config_find_option(fmt, key);
863
864
865
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", key);
    return NULL;
866
867
868
  } else if (var->type == CONFIG_TYPE_LINELIST_S) {
    log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key);
    return NULL;
869
870
871
  }
  value = ((char*)options) + var->var_offset;

872
873
  if (var->type == CONFIG_TYPE_LINELIST ||
      var->type == CONFIG_TYPE_LINELIST_V) {
874
    /* Linelist requires special handling: we just copy and return it. */
875
876
    const config_line_t *next_in = *(const config_line_t**)value;
    config_line_t **next_out = &result;
877
    while (next_in) {