config.c 102 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
  VAR("FirewallPorts",       CSV,      FirewallPorts,        ""),
126
  VAR("Group",               STRING,   Group,                NULL),
Nick Mathewson's avatar
Nick Mathewson committed
127
  VAR("HardwareAccel",       BOOL,     HardwareAccel,        "1"),
128
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
Nick Mathewson's avatar
Nick Mathewson committed
129
130
131
132
133
  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),
134
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
135
  VAR("HttpProxyAuthenticator",STRING, HttpProxyAuthenticator,NULL),
136
  VAR("HttpsProxy",          STRING,   HttpsProxy,           NULL),
137
  VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL),
138
  OBSOLETE("IgnoreVersion"),
139
  VAR("KeepalivePeriod",     INTERVAL, KeepalivePeriod,      "5 minutes"),
140
  VAR("Log",                 LINELIST, Logs,                 NULL),
141
  OBSOLETE("LinkPadding"),
Nick Mathewson's avatar
Nick Mathewson committed
142
143
144
145
146
147
  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"),
148
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
149
  OBSOLETE("MonthlyAccountingStart"),
Nick Mathewson's avatar
Nick Mathewson committed
150
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
151
  VAR("NewCircuitPeriod",    INTERVAL, NewCircuitPeriod,     "30 seconds"),
Nick Mathewson's avatar
Nick Mathewson committed
152
153
154
  VAR("Nickname",            STRING,   Nickname,             NULL),
  VAR("NoPublish",           BOOL,     NoPublish,            "0"),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
155
  VAR("NumCpus",             UINT,     NumCpus,              "1"),
Nick Mathewson's avatar
Nick Mathewson committed
156
  VAR("NumHelperNodes",      UINT,     NumHelperNodes,       "3"),
157
  VAR("ORBindAddress",       LINELIST, ORBindAddress,        NULL),
Nick Mathewson's avatar
Nick Mathewson committed
158
  VAR("ORPort",              UINT,     ORPort,               "0"),
159
160
  VAR("OutboundBindAddress", STRING,   OutboundBindAddress,  NULL),
  VAR("PathlenCoinWeight",   DOUBLE,   PathlenCoinWeight,    "0.3"),
Nick Mathewson's avatar
Nick Mathewson committed
161
  VAR("PidFile",             STRING,   PidFile,              NULL),
162
  VAR("ReachableAddresses",  LINELIST, ReachableAddresses,   NULL),
Nick Mathewson's avatar
Nick Mathewson committed
163
  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
static int options_validate(or_options_t *options);
262
static int options_act(or_options_t *old_options);
263
static int options_transition_allowed(or_options_t *old, or_options_t *new);
264
265
266
267
static int options_transition_affects_workers(or_options_t *old_options,
                                              or_options_t *new_options);
static int options_transition_affects_descriptor(or_options_t *old_options,
                                                 or_options_t *new_options);
268
static int check_nickname_list(const char *lst, const char *name);
269
static void config_register_addressmaps(or_options_t *options);
270

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

290
291
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
292
static void print_cvs_version(void);
293
static void parse_reachable_addresses(void);
294
static int init_libevent(void);
295
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
296
static void check_libevent_version(const char *m, const char *v, int server);
297
#endif
298

299
300
/*static*/ or_options_t *options_new(void);

301
302
#define OR_OPTIONS_MAGIC 9090909

303
static config_format_t options_format = {
304
305
306
  sizeof(or_options_t),
  OR_OPTIONS_MAGIC,
  STRUCT_OFFSET(or_options_t, _magic),
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  _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
323
324
};

325
326
327
328
329
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
330
static or_options_t *global_options = NULL;
Roger Dingledine's avatar
Roger Dingledine committed
331
/** Name of most recently read torrc file. */
332
static char *torrc_fname = NULL;
333
334
/** Persistant serialized state. */
static or_state_t *global_state = NULL;
335
336
/** DOCDOC */
static addr_policy_t *reachable_addr_policy = NULL;
337

338
339
340
341
342
343
344
345
346
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;
}

347
348
/** Return the currently configured options. */
or_options_t *
349
350
get_options(void)
{
351
352
353
  tor_assert(global_options);
  return global_options;
}
354

355
356
357
/** Change the current global options to contain <b>new_val</b> instead of
 * their current value; take action based on the new value; free the old value
 * as necessary.
358
359
 */
void
360
361
set_options(or_options_t *new_val)
{
362
  or_options_t *old_options = global_options;
363
  global_options = new_val;
364
365
366
367
368
369
  if (options_act(old_options) < 0) { /* acting on the options failed. die. */
    log_fn(LOG_ERR,"Acting on config options left us in a broken state. Dying.");
    exit(1);
  }
  if (old_options)
    config_free(&options_format, global_options);
370
371
}

372
373
374
void
config_free_all(void)
{
375
  config_free(&options_format, global_options);
376
  tor_free(torrc_fname);
377
378
  addr_policy_free(reachable_addr_policy);
  reachable_addr_policy = NULL;
379
380
}

381
382
383
384
/** If options->SafeLogging is on, return a not very useful string,
 * else return address.
 */
const char *
385
386
safe_str(const char *address)
{
387
388
389
390
391
392
  if (get_options()->SafeLogging)
    return "[scrubbed]";
  else
    return address;
}

393
394
395
/** Fetch the active option list, and take actions based on it. All of the
 * things we do should survive being done repeatedly.  If present,
 * <b>old_options</b> contains the previous value of the options.
396
 *
397
 * Return 0 if all goes well, return -1 if it's time to die.
398
399
400
 *
 * Note 2: We haven't moved all the "act on new configuration" logic
 * here yet.  Some is still in do_hup() and other places.
401
 */
402
403
static int
options_act(or_options_t *old_options)
404
{
405
  config_line_t *cl;
406
  or_options_t *options = get_options();
407
408
409
  static int libevent_initialized = 0;

  if (options->RunAsDaemon) {
410
    start_daemon();
411
  }
412
413

  clear_trusted_dir_servers();
414
  for (cl = options->DirServers; cl; cl = cl->next) {
415
416
    if (parse_dir_server_line(cl->value, 0)<0) {
      log_fn(LOG_ERR,
417
             "Bug: Previously validated DirServer line could not be added!");
418
      return -1;
419
420
421
    }
  }

422
  if (rend_config_services(options, 0)<0) {
423
    log_fn(LOG_ERR,
424
           "Bug: Previously validated hidden services line could not be added!");
425
    return -1;
426
  }
427

428
429
430
  if (options->EntryNodes && strlen(options->EntryNodes))
    options->UseHelperNodes = 0;

431
  /* Setuid/setgid as appropriate */
432
433
  if (options->User || options->Group) {
    if (switch_id(options->User, options->Group) != 0) {
434
435
436
437
438
      return -1;
    }
  }

  /* Ensure data directory is private; create if possible. */
439
  if (check_private_dir(options->DataDirectory, CPD_CREATE) != 0) {
440
    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
441
           options->DataDirectory);
442
443
444
    return -1;
  }

445
446
  /* Bail out at this point if we're not going to be a client or server:
   * we want to not fork, and to log stuff to stderr. */
447
448
449
  if (options->command != CMD_RUN_TOR)
    return 0;

450
  mark_logs_temp(); /* Close current logs once new logs are open. */
451
  if (options_init_logs(options, 0)<0) /* Configure the log(s) */
452
    return -1;
453

454
455
456
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
457
  add_callback_log(LOG_ERR, LOG_ERR, control_event_logmsg);
458
  control_adjust_event_log_severity();
459

460
461
462
463
464
465
466
  /* Set up libevent. */
  if (!libevent_initialized) {
    if (init_libevent())
      return -1;
    libevent_initialized = 1;
  }

467
468
469
470
471
  /* Load state */
  if (! global_state)
    if (or_state_load())
      return -1;

472
  options->_ConnLimit =
473
    set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
474
  if (options->_ConnLimit < 0)
475
476
    return -1;

477
478
479
480
481
482
483
484
485
  {
    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);
  }

486
  /* Finish backgrounding the process */
487
  if (options->RunAsDaemon) {
488
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
489
    finish_daemon(options->DataDirectory);
490
491
492
493
  }

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

497
498
499
  /* Register addressmap directives */
  config_register_addressmaps(options);

500
501
502
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();
503
  parse_reachable_addresses();
504

505
506
  init_cookie_authentication(options->CookieAuthentication);

507
508
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
509
    log_fn(LOG_ERR,"Error loading rendezvous service keys");
510
511
512
    return -1;
  }

513
  /* Set up accounting */
514
  if (accounting_parse_options(options, 0)<0) {
515
    log_fn(LOG_ERR,"Error in accounting options");
516
517
    return -1;
  }
518
  if (accounting_is_enabled(options))
519
520
    configure_accounting(time(NULL));

521
  if (!we_are_hibernating() && retry_all_listeners(0) < 0) {
522
523
524
525
    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
    return -1;
  }

526
527
528
529
530
531
532
533
534
  /* Check for transitions that need action. */
  if (old_options) {
    if (options_transition_affects_workers(old_options, options)) {
      log_fn(LOG_INFO,"Worker-related options changed. Rotating workers.");
      cpuworkers_rotate();
      dnsworkers_rotate();
    }
  }

535
  /* Since our options changed, we might need to regenerate and upload our
536
   * server descriptor.
537
   */
538
539
  if (!old_options || options_transition_affects_descriptor(old_options, options))
    mark_my_descriptor_dirty();
540

541
  return 0;
542
543
544
545
546
547
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
548
/** If <b>option</b> is an official abbreviation for a longer option,
549
550
551
 * 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. */
552
static const char *
553
expand_abbrev(config_format_t *fmt, const char *option, int command_line)
554
555
{
  int i;
556
557
558
  if (! fmt->abbrevs)
    return option;
  for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
559
    /* Abbreviations aren't casei. */
560
561
562
    if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
        (command_line || !fmt->abbrevs[i].commandline_only)) {
      return fmt->abbrevs[i].full;
563
    }
564
565
566
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
567

Nick Mathewson's avatar
Nick Mathewson committed
568
/** Helper: Read a list of configuration options from the command line. */
569
static config_line_t *
570
571
config_get_commandlines(int argc, char **argv)
{
572
573
  config_line_t *front = NULL;
  config_line_t **new = &front;
574
575
576
  char *s;
  int i = 1;

577
  while (i < argc-1) {
578
579
580
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
581
      continue;
582
583
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
584
      continue;
Nick Mathewson's avatar
Nick Mathewson committed
585
586
587
    } else if (!strcmp(argv[i],"--nt-service")) {
      i += 1;
      continue;
588
589
    }

590
    *new = tor_malloc_zero(sizeof(config_line_t));
591
    s = argv[i];
592

593
    while (*s == '-')
594
      s++;
595

596
    (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1));
597
598
    (*new)->value = tor_strdup(argv[i+1]);
    (*new)->next = NULL;
599
    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
600
601
602
        (*new)->key, (*new)->value);

    new = &((*new)->next);
603
604
605
606
607
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
608
/** Helper: allocate a new configuration option mapping 'key' to 'val',
609
610
 * append it to *<b>lst</b>. */
static void
611
config_line_append(config_line_t **lst,
612
613
                   const char *key,
                   const char *val)
614
{
615
  config_line_t *newline;
616

617
  newline = tor_malloc(sizeof(config_line_t));
618
619
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
620
621
622
623
624
  newline->next = NULL;
  while (*lst)
    lst = &((*lst)->next);

  (*lst) = newline;
625
626
}

627
628
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
629
630
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
631
int
632
config_get_lines(char *string, config_line_t **result)
633
{
634
  config_line_t *list = NULL, **next;
635
  char *k, *v;
636

637
  next = &list;
638
639
640
641
642
643
  do {
    string = parse_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      return -1;
    }
644
645
646
647
    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. */
648
      *next = tor_malloc(sizeof(config_line_t));
649
650
651
652
653
      (*next)->key = tor_strdup(k);
      (*next)->value = tor_strdup(v);
      (*next)->next = NULL;
      next = &((*next)->next);
    }
654
  } while (*string);
655

656
  *result = list;
657
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
658
659
}

Nick Mathewson's avatar
Nick Mathewson committed
660
661
662
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
663
void
664
config_free_lines(config_line_t *front)
665
{
666
  config_line_t *tmp;
667

668
  while (front) {
669
670
671
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
672
673
674
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
675
676
677
  }
}

678
679
680
681
682
683
684
685
686
687
688
689
/** 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
690
691
692
693
/** 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.
 */
694
static config_var_t *
695
config_find_option(config_format_t *fmt, const char *key)
696
697
{
  int i;
698
  size_t keylen = strlen(key);
699
  if (!keylen)
700
    return NULL; /* if they say "--" on the commandline, it's not an option */
Nick Mathewson's avatar
Nick Mathewson committed
701
  /* First, check for an exact (case-insensitive) match */
702
  for (i=0; fmt->vars[i].name; ++i) {
703
    if (!strcasecmp(key, fmt->vars[i].name)) {
704
      return &fmt->vars[i];
705
    }
Nick Mathewson's avatar
Nick Mathewson committed
706
707
  }
  /* If none, check for an abbreviated match */
708
709
  for (i=0; fmt->vars[i].name; ++i) {
    if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
710
      log_fn(LOG_WARN, "The abbreviation '%s' is deprecated. "
711
          "Please use '%s' instead",
712
713
             key, fmt->vars[i].name);
      return &fmt->vars[i];
714
715
    }
  }
716
  /* Okay, unrecognized options */
717
718
719
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
720
/** If <b>c</b> is a syntactically valid configuration line, update
721
722
 * <b>options</b> with its value and return 0.  Otherwise return -1 for bad key,
 * -2 for bad value.
723
724
725
726
 *
 * If 'reset' is set, and we get a line containing no value, restore the
 * option to its default value.
 */
727
static int
728
config_assign_line(config_format_t *fmt,
729
                   or_options_t *options, config_line_t *c, int reset)
730
{
731
  int i, ok;
732
733
  config_var_t *var;
  void *lvalue;
734

735
736
737
  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
738
739
740
741
742
743
  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)) {
744
    tor_free(c->key);
745
    c->key = tor_strdup(var->name);
746
747
  }

748
  if (reset && !strlen(c->value)) {
749
    option_reset(fmt, options, var);
750
751
752
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
753
  lvalue = ((char*)options) + var->var_offset;
754
  switch (var->type) {
755

756
757
758
  case CONFIG_TYPE_UINT:
    i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
    if (!ok) {
759
      log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.",
760
          c->key,c->value);
761
      return -2;
762
    }
763
    *(int *)lvalue = i;
764
765
    break;

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
  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;
  }

784
785
786
  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
787
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
788
      return -2;
789
    }
790
    *(int *)lvalue = i;
791
792
793
    break;

  case CONFIG_TYPE_STRING:
794
795
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
796
797
798
    break;

  case CONFIG_TYPE_DOUBLE:
799
    *(double *)lvalue = atof(c->value);
800
801
    break;

802
803
804
805
806
807
808
  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;

809
  case CONFIG_TYPE_CSV:
810
811
812
813
    if (*(smartlist_t**)lvalue) {
      SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
      smartlist_clear(*(smartlist_t**)lvalue);
    } else {
814
      *(smartlist_t**)lvalue = smartlist_create();
815
    }
816

817
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
818
819
820
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

821
822
  case CONFIG_TYPE_LINELIST:
  case CONFIG_TYPE_LINELIST_S:
823
    config_line_append((config_line_t**)lvalue, c->key, c->value);
824
    break;
825
826
827
828

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
829
830
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
831
    return -2;
832
833
834
  default:
    tor_assert(0);
    break;
835
  }
836
  return 0;
837
838
}

839
840
/** restore the option named <b>key</b> in options to its default value. */
static void
841
config_reset_line(config_format_t *fmt, or_options_t *options, const char *key)
842
843
844
{
  config_var_t *var;

845
846
847
  CHECK(fmt, options);

  var = config_find_option(fmt, key);
848
849
850
  if (!var)
    return; /* give error on next pass. */

851
  option_reset(fmt, options, var);
852
853
}

854
855
/** Return true iff key is a valid configuration option. */
int
856
option_is_recognized(const char *key)
857
{
858
  config_var_t *var = config_find_option(&options_format, key);
859
860
861
  return (var != NULL);
}

862
863
/** Return the canonical name of a configuration option. */
const char *
864
option_get_canonical_name(const char *key)
865
{
866
  config_var_t *var = config_find_option(&options_format, key);
867