config.c 110 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

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
  int warn;
45
46
} config_abbrev_t;

47
48
/* Handy macro for declaring "In the config file or on the command line,
 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
49
#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
50

Nick Mathewson's avatar
Nick Mathewson committed
51
/* A list of command-line abbreviations. */
52
static config_abbrev_t _option_abbrevs[] = {
53
  PLURAL(ExitNode),
54
  PLURAL(EntryNode),
55
56
  PLURAL(ExcludeNode),
  PLURAL(FirewallPort),
57
  PLURAL(LongLivedPort),
58
59
  PLURAL(HiddenServiceNode),
  PLURAL(HiddenServiceExcludeNode),
60
  PLURAL(NumCpu),
61
62
  PLURAL(RendNode),
  PLURAL(RendExcludeNode),
63
64
  PLURAL(StrictEntryNode),
  PLURAL(StrictExitNode),
65
  { "l", "Log", 1, 0},
66
67
68
69
  { "BandwidthRateBytes", "BandwidthRate", 0, 0},
  { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
  { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
  { "MaxConn", "ConnLimit", 0, 1},
70
71
72
  { "ORBindAddress", "ORListenAddress", 0, 0},
  { "DirBindAddress", "DirListenAddress", 0, 0},
  { "SocksBindAddress", "SocksListenAddress", 0, 0},
73
  { NULL, NULL, 0, 0},
74
};
75
#undef PLURAL
76

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

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

Nick Mathewson's avatar
Nick Mathewson committed
97
98
99
100
/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
101
static config_var_t _option_vars[] = {
Roger Dingledine's avatar
Roger Dingledine committed
102
  VAR("AccountingMax",       MEMUNIT,  AccountingMax,        "0 bytes"),
Nick Mathewson's avatar
Nick Mathewson committed
103
  VAR("AccountingMaxKB",     UINT,     _AccountingMaxKB,     "0"),
104
  VAR("AccountingStart",     STRING,   AccountingStart,      NULL),
Nick Mathewson's avatar
Nick Mathewson committed
105
  VAR("Address",             STRING,   Address,              NULL),
106
  VAR("AllowUnverifiedNodes",CSV,      AllowUnverifiedNodes, "middle,rendezvous"),
107
  VAR("AssumeReachable",     BOOL,     AssumeReachable,      "0"),
108
109
  VAR("AuthDirInvalid",      LINELIST, AuthDirInvalid,       NULL),
  VAR("AuthDirReject",       LINELIST, AuthDirReject,        NULL),
110
  VAR("AuthoritativeDirectory",BOOL,   AuthoritativeDir,     "0"),
111
  VAR("BandwidthBurst",      MEMUNIT,  BandwidthBurst,       "5 MB"),
Nick Mathewson's avatar
Nick Mathewson committed
112
  VAR("BandwidthRate",       MEMUNIT,  BandwidthRate,        "2 MB"),
113
  VAR("ClientOnly",          BOOL,     ClientOnly,           "0"),
Nick Mathewson's avatar
Nick Mathewson committed
114
  VAR("ConnLimit",           UINT,     ConnLimit,            "1024"),
115
  VAR("ContactInfo",         STRING,   ContactInfo,          NULL),
116
  VAR("ControlPort",         UINT,     ControlPort,          "0"),
117
  VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
118
  VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
Nick Mathewson's avatar
Nick Mathewson committed
119
  VAR("DebugLogFile",        STRING,   DebugLogFile,         NULL),
120
  VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
121
122
123
  VAR("DirListenAddress",    LINELIST, DirListenAddress,     NULL),
  /* if DirFetchPeriod is 0, see get_dir_fetch_period() in main.c */
  VAR("DirFetchPeriod",      INTERVAL, DirFetchPeriod,       "0 seconds"),
124
  VAR("DirPolicy",           LINELIST, DirPolicy,            NULL),
Nick Mathewson's avatar
Nick Mathewson committed
125
  VAR("DirPort",             UINT,     DirPort,              "0"),
126
  OBSOLETE("DirPostPeriod"),
127
128
129
  VAR("DirServer",           LINELIST, DirServers,           NULL),
  VAR("EntryNodes",          STRING,   EntryNodes,           NULL),
  VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
Nick Mathewson's avatar
Nick Mathewson committed
130
131
  VAR("ExitNodes",           STRING,   ExitNodes,            NULL),
  VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
132
  VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
133
  VAR("FirewallPorts",       CSV,      FirewallPorts,        ""),
134
  VAR("FastFirstHopPK",      BOOL,     FastFirstHopPK,       "1"),
135
  VAR("Group",               STRING,   Group,                NULL),
Nick Mathewson's avatar
Nick Mathewson committed
136
  VAR("HardwareAccel",       BOOL,     HardwareAccel,        "1"),
137
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
Nick Mathewson's avatar
Nick Mathewson committed
138
139
140
141
142
  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),
143
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
144
  VAR("HttpProxyAuthenticator",STRING, HttpProxyAuthenticator,NULL),
145
  VAR("HttpsProxy",          STRING,   HttpsProxy,           NULL),
146
  VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL),
147
  OBSOLETE("IgnoreVersion"),
148
  VAR("KeepalivePeriod",     INTERVAL, KeepalivePeriod,      "5 minutes"),
149
  VAR("Log",                 LINELIST, Logs,                 NULL),
150
  OBSOLETE("LinkPadding"),
Nick Mathewson's avatar
Nick Mathewson committed
151
152
153
154
155
156
  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"),
157
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
158
  OBSOLETE("MonthlyAccountingStart"),
Nick Mathewson's avatar
Nick Mathewson committed
159
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
160
  VAR("NewCircuitPeriod",    INTERVAL, NewCircuitPeriod,     "30 seconds"),
161
  VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
Nick Mathewson's avatar
Nick Mathewson committed
162
163
164
  VAR("Nickname",            STRING,   Nickname,             NULL),
  VAR("NoPublish",           BOOL,     NoPublish,            "0"),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
165
  VAR("NumCpus",             UINT,     NumCpus,              "1"),
Nick Mathewson's avatar
Nick Mathewson committed
166
  VAR("NumHelperNodes",      UINT,     NumHelperNodes,       "3"),
167
  VAR("ORListenAddress",     LINELIST, ORListenAddress,     NULL),
Nick Mathewson's avatar
Nick Mathewson committed
168
  VAR("ORPort",              UINT,     ORPort,               "0"),
169
170
  VAR("OutboundBindAddress", STRING,   OutboundBindAddress,  NULL),
  VAR("PathlenCoinWeight",   DOUBLE,   PathlenCoinWeight,    "0.3"),
Nick Mathewson's avatar
Nick Mathewson committed
171
  VAR("PidFile",             STRING,   PidFile,              NULL),
172
  VAR("ProtocolWarnings",    BOOL,     ProtocolWarnings,     "0"),
173
  VAR("ReachableAddresses",  LINELIST, ReachableAddresses,   NULL),
Nick Mathewson's avatar
Nick Mathewson committed
174
  VAR("RecommendedVersions", LINELIST, RecommendedVersions,  NULL),
175
176
  VAR("RecommendedClientVersions", LINELIST, RecommendedClientVersions,  NULL),
  VAR("RecommendedServerVersions", LINELIST, RecommendedServerVersions,  NULL),
177
  VAR("RedirectExit",        LINELIST, RedirectExit,         NULL),
Nick Mathewson's avatar
Nick Mathewson committed
178
179
180
  VAR("RendExcludeNodes",    STRING,   RendExcludeNodes,     NULL),
  VAR("RendNodes",           STRING,   RendNodes,            NULL),
  VAR("RendPostPeriod",      INTERVAL, RendPostPeriod,       "20 minutes"),
181
  VAR("RephistTrackTime",    INTERVAL, RephistTrackTime,     "24 hours"),
182
  OBSOLETE("RouterFile"),
183
184
  VAR("RunAsDaemon",         BOOL,     RunAsDaemon,          "0"),
  VAR("RunTesting",          BOOL,     RunTesting,           "0"),
185
  VAR("SafeLogging",         BOOL,     SafeLogging,          "1"),
186
  VAR("ShutdownWaitLength",  INTERVAL, ShutdownWaitLength,   "30 seconds"),
187
  VAR("SocksListenAddress",  LINELIST, SocksListenAddress,   NULL),
188
  VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),
Nick Mathewson's avatar
Nick Mathewson committed
189
  VAR("SocksPort",           UINT,     SocksPort,            "9050"),
190
191
  /* if StatusFetchPeriod is 0, see get_status_fetch_period() in main.c */
  VAR("StatusFetchPeriod",   INTERVAL, StatusFetchPeriod,    "0 seconds"),
Nick Mathewson's avatar
Nick Mathewson committed
192
193
  VAR("StrictEntryNodes",    BOOL,     StrictEntryNodes,     "0"),
  VAR("StrictExitNodes",     BOOL,     StrictExitNodes,      "0"),
194
  VAR("SysLog",              LINELIST_S, OldLogOptions,      NULL),
195
  VAR("TestSocks",           BOOL,     TestSocks,            "0"),
Nick Mathewson's avatar
Nick Mathewson committed
196
197
  VAR("TrackHostExits",      CSV,      TrackHostExits,       NULL),
  VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
198
  OBSOLETE("TrafficShaping"),
199
  VAR("UseHelperNodes",      BOOL,     UseHelperNodes,       "0"),
Nick Mathewson's avatar
Nick Mathewson committed
200
  VAR("User",                STRING,   User,                 NULL),
201
  VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir,   "0"),
202
  VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
203
  VAR("__LeaveStreamsUnattached", BOOL,LeaveStreamsUnattached, "0"),
204
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, NULL }
205
};
206
207
208
#undef VAR

#define VAR(name,conftype,member,initvalue) \
209
  { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), initvalue, NULL }
210
static config_var_t _state_vars[] = {
Nick Mathewson's avatar
Nick Mathewson committed
211
  VAR("AccountingBytesReadInterval", MEMUNIT, AccountingBytesReadInInterval,NULL),
212
213
214
  VAR("AccountingBytesWrittenInInterval", MEMUNIT,
      AccountingBytesWrittenInInterval, NULL),
  VAR("AccountingExpectedUsage", MEMUNIT,     AccountingExpectedUsage, NULL),
Nick Mathewson's avatar
Nick Mathewson committed
215
216
  VAR("AccountingIntervalStart", ISOTIME,  AccountingIntervalStart, NULL),
  VAR("AccountingSecondsActive", INTERVAL,    AccountingSecondsActive, NULL),
217
218
219
  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
220
221
222
  VAR("HelperNodes",             LINELIST_V,  HelperNodes,          NULL),
  VAR("LastWritten",             ISOTIME,     LastWritten,          NULL),

223
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, NULL }
224
225
};

226
227
228
#undef VAR
#undef OBSOLETE

229
230
231
232
233
234
235
/** DOCDOC*/
typedef struct config_var_description_t {
  const char *name;
  const char *description;
} config_var_description_t;

static config_var_description_t options_description[] = {
236
  { "Address", "The advertised (external) address we should use." },
237
238
239
240
241
242
243
244
245
246
247
248
249
  // { "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 },
};

250
251
typedef int (*validate_fn_t)(void*);

252
253
254
/** Information on the keys, value types, key-to-struct-member mappings,
 * variable descriptions, validation functions, and abbreviations for a
 * configuration or storage format. */
255
256
257
258
259
260
261
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;
262
  config_var_description_t *descriptions;
263
264
265
266
267
268
269
} 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
270
/** Largest allowed config line */
271
#define CONFIG_LINE_T_MAXLEN 4096
272

273
static void config_line_append(config_line_t **lst,
274
                               const char *key, const char *val);
275
276
static void option_clear(config_format_t *fmt, or_options_t *options,
                         config_var_t *var);
277
static void option_reset(config_format_t *fmt, or_options_t *options,
278
                         config_var_t *var, int use_defaults);
279
static void config_free(config_format_t *fmt, void *options);
280
static int option_is_same(config_format_t *fmt,
281
                          or_options_t *o1, or_options_t *o2, const char *name);
282
static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
283
static int options_validate(or_options_t *options);
284
static int options_act_reversible(or_options_t *old_options);
285
static int options_act(or_options_t *old_options);
286
static int options_transition_allowed(or_options_t *old, or_options_t *new);
287
288
289
290
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);
291
static int check_nickname_list(const char *lst, const char *name);
292
static void config_register_addressmaps(or_options_t *options);
293

294
static int parse_dir_server_line(const char *line, int validate_only);
295
static int parse_redirect_line(smartlist_t *result,
296
                               config_line_t *line);
297
298
299
static int parse_log_severity_range(const char *range, int *min_out,
                                    int *max_out);
static int convert_log_option(or_options_t *options,
300
301
                              config_line_t *level_opt,
                              config_line_t *file_opt, int isDaemon);
302
303
304
305
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);
306
static int validate_data_directory(or_options_t *options);
307
static int write_configuration_file(const char *fname, or_options_t *options);
308
static config_line_t *get_assigned_option(config_format_t *fmt,
309
                                     or_options_t *options, const char *key);
310
311
static void config_init(config_format_t *fmt, void *options);
static int or_state_validate(or_state_t *options);
312

313
314
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
315
static void print_cvs_version(void);
316
static void parse_reachable_addresses(void);
317
static int init_libevent(void);
318
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
319
static void check_libevent_version(const char *m, const char *v, int server);
320
#endif
321

322
323
/*static*/ or_options_t *options_new(void);

324
325
#define OR_OPTIONS_MAGIC 9090909

326
static config_format_t options_format = {
327
328
329
  sizeof(or_options_t),
  OR_OPTIONS_MAGIC,
  STRUCT_OFFSET(or_options_t, _magic),
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  _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
346
347
};

348
349
350
351
352
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
353
static or_options_t *global_options = NULL;
Roger Dingledine's avatar
Roger Dingledine committed
354
/** Name of most recently read torrc file. */
355
static char *torrc_fname = NULL;
356
357
/** Persistant serialized state. */
static or_state_t *global_state = NULL;
358
359
/** DOCDOC */
static addr_policy_t *reachable_addr_policy = NULL;
360

361
362
363
364
365
366
367
368
369
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;
}

370
371
/** Return the currently configured options. */
or_options_t *
372
373
get_options(void)
{
374
375
376
  tor_assert(global_options);
  return global_options;
}
377

378
379
380
/** 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.
381
 */
382
int
383
384
set_options(or_options_t *new_val)
{
385
  or_options_t *old_options = global_options;
386
  global_options = new_val;
387
388
  /* Note that we pass the *old* options below, for comparison. It
   * pulls the new options directly out of global_options. */
389
390
391
392
  if (options_act_reversible(old_options)<0) {
    global_options = old_options;
    return -1;
  }
393
  if (options_act(old_options) < 0) { /* acting on the options failed. die. */
394
395
    err(LD_CONFIG,
        "Acting on config options left us in a broken state. Dying.");
396
397
398
    exit(1);
  }
  if (old_options)
399
    config_free(&options_format, old_options);
400
401

  return 0;
402
403
}

404
405
406
void
config_free_all(void)
{
407
408
409
410
411
412
413
414
  if (global_options) {
    config_free(&options_format, global_options);
    global_options = NULL;
  }
  if (global_state) {
    config_free(&state_format, global_state);
    global_state = NULL;
  }
415
  tor_free(torrc_fname);
416
417
418
419
  if (reachable_addr_policy) {
    addr_policy_free(reachable_addr_policy);
    reachable_addr_policy = NULL;
  }
420
421
}

422
423
424
425
/** If options->SafeLogging is on, return a not very useful string,
 * else return address.
 */
const char *
426
427
safe_str(const char *address)
{
428
429
430
431
432
433
  if (get_options()->SafeLogging)
    return "[scrubbed]";
  else
    return address;
}

434
435
436
437
438
439
440
441
442
443
444
445
446
/** Add the default directory servers directly into the trusted dir list. */
static void
add_default_trusted_dirservers(void)
{
  const char *dirservers[] = {
"moria1 v1 18.244.0.188:9031 FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441",
"moria2 v1 18.244.0.114:80 719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF",
"tor26 v1 86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D" };
  parse_dir_server_line(dirservers[0], 0);
  parse_dir_server_line(dirservers[1], 0);
  parse_dir_server_line(dirservers[2], 0);
}

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
/** 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.
 *
 * Return 0 if all goes well, return -1 if things went badly.
 */
static int
options_act_reversible(or_options_t *old_options)
{
  smartlist_t *new_listeners = smartlist_create();
  smartlist_t *replaced_listeners = smartlist_create();
  static int libevent_initialized = 0;
  or_options_t *options = get_options();
  int running_tor = options->command == CMD_RUN_TOR;
  int set_conn_limit = 0;
  int r = -1;

  if (running_tor && options->RunAsDaemon) {
    /* No need to roll back, since you can't change the value. */
    start_daemon();
  }

  /* Setuid/setgid as appropriate */
  if (options->User || options->Group) {
    if (switch_id(options->User, options->Group) != 0) {
      /* No need to roll back, since you can't change the value. */
      goto done;
    }
  }

  /* Set up libevent. */
  if (running_tor && !libevent_initialized) {
    if (init_libevent())
      goto done;
    libevent_initialized = 1;
  }

  /* Ensure data directory is private; create if possible. */
  if (check_private_dir(options->DataDirectory, CPD_CREATE)<0) {
486
    err(LD_FS, "Couldn't access/create private data directory \"%s\"",
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
           options->DataDirectory);
    /* No need to roll back, since you can't change the value. */
    goto done;
  }

  /* Bail out at this point if we're not going to be a client or server:
   * we don't run  */
  if (options->command != CMD_RUN_TOR)
    goto commit;

  options->_ConnLimit =
    set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
  if (options->_ConnLimit < 0)
    goto rollback;
  set_conn_limit = 1;

  if (retry_all_listeners(0, replaced_listeners, new_listeners) < 0) {
504
    err(LD_CONFIG, "Failed to bind one of the listener ports.");
505
506
507
508
509
510
511
    goto rollback;
  }

 commit:
  r = 0;
  SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
  {
512
    notice(LD_NET, "Closing old %s on %s:%d",
513
514
515
516
517
518
519
520
521
522
523
524
525
526
           conn_type_to_string(conn->type), conn->address, conn->port);
    connection_close_immediate(conn);
    connection_mark_for_close(conn);
  });
  goto done;

 rollback:
  r = -1;

  if (set_conn_limit && old_options)
    set_max_file_descriptors((unsigned)old_options->ConnLimit,MAXCONNECTIONS);

  SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
  {
527
    notice(LD_NET, "Closing %s on %s:%d",
528
529
530
531
532
533
534
535
536
537
538
           conn_type_to_string(conn->type), conn->address, conn->port);
    connection_close_immediate(conn);
    connection_mark_for_close(conn);
  });

 done:
  smartlist_free(new_listeners);
  smartlist_free(replaced_listeners);
  return r;
}

539
540
541
/** 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.
542
 *
543
 * Return 0 if all goes well, return -1 if it's time to die.
544
545
546
 *
 * Note 2: We haven't moved all the "act on new configuration" logic
 * here yet.  Some is still in do_hup() and other places.
547
 */
548
549
static int
options_act(or_options_t *old_options)
550
{
551
  config_line_t *cl;
552
553
  char *fn;
  size_t len;
554
  or_options_t *options = get_options();
555
  int running_tor = options->command == CMD_RUN_TOR;
556
557

  clear_trusted_dir_servers();
558
559
560
561
562
563
564
  if (options->DirServers) {
    for (cl = options->DirServers; cl; cl = cl->next) {
      if (parse_dir_server_line(cl->value, 0)<0) {
        err(LD_BUG,
            "Bug: Previously validated DirServer line could not be added!");
        return -1;
      }
565
    }
566
567
  } else {
    add_default_trusted_dirservers();
568
569
  }

570
  if (running_tor && rend_config_services(options, 0)<0) {
571
572
    err(LD_BUG,
        "Bug: Previously validated hidden services line could not be added!");
573
    return -1;
574
  }
575

576
577
578
  if (options->EntryNodes && strlen(options->EntryNodes))
    options->UseHelperNodes = 0;

579
580
581
582
583
  if (running_tor) {
    len = strlen(options->DataDirectory)+32;
    fn = tor_malloc(len);
    tor_snprintf(fn, len, "%s/cached-status", options->DataDirectory);
    if (check_private_dir(fn, CPD_CREATE) != 0) {
584
585
      err(LD_CONFIG,
          "Couldn't access/create private data directory \"%s\"", fn);
586
587
588
      tor_free(fn);
      return -1;
    }
589
590
    tor_free(fn);
  }
591

592
593
  /* 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. */
594
595
596
  if (options->command != CMD_RUN_TOR)
    return 0;

597
  mark_logs_temp(); /* Close current logs once new logs are open. */
598
  if (options_init_logs(options, 0)<0) /* Configure the log(s) */
599
    return -1;
600

601
602
603
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
604
  add_callback_log(LOG_ERR, LOG_ERR, control_event_logmsg);
605
  control_adjust_event_log_severity();
606

607
608
609
610
611
  /* Load state */
  if (! global_state)
    if (or_state_load())
      return -1;

612
613
614
615
616
617
618
619
620
  {
    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);
  }

621
  /* Finish backgrounding the process */
622
  if (running_tor && options->RunAsDaemon) {
623
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
624
    finish_daemon(options->DataDirectory);
625
626
627
628
  }

  /* Write our pid to the pid file. If we do not have write permissions we
   * will log a warning */
629
  if (running_tor && options->PidFile)
630
631
    write_pidfile(options->PidFile);

632
633
634
  /* Register addressmap directives */
  config_register_addressmaps(options);

635
636
637
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();
638
  parse_authdir_policy();
639
  parse_reachable_addresses();
640

641
642
  init_cookie_authentication(options->CookieAuthentication);

643
644
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
645
    err(LD_GENERAL,"Error loading rendezvous service keys");
646
647
648
    return -1;
  }

649
  /* Set up accounting */
650
  if (accounting_parse_options(options, 0)<0) {
651
    err(LD_CONFIG,"Error in accounting options");
652
653
    return -1;
  }
654
  if (accounting_is_enabled(options))
655
656
    configure_accounting(time(NULL));

657
658
659
  if (!running_tor)
    return 0;

660
661
  /* Check for transitions that need action. */
  if (old_options) {
662
    if (options->UseHelperNodes && !old_options->UseHelperNodes) {
663
      info(LD_CIRC,"Switching to helper nodes; abandoning previous circuits");
664
665
666
667
      circuit_mark_all_unused_circs();
      circuit_expire_all_dirty_circs();
    }

668
    if (options_transition_affects_workers(old_options, options)) {
669
      info(LD_GENERAL,"Worker-related options changed. Rotating workers.");
670
671
672
673
674
      cpuworkers_rotate();
      dnsworkers_rotate();
    }
  }

675
  /* Since our options changed, we might need to regenerate and upload our
676
   * server descriptor.
677
   */
678
679
  if (!old_options || options_transition_affects_descriptor(old_options, options))
    mark_my_descriptor_dirty();
680

681
  return 0;
682
683
684
685
686
687
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
688
/** If <b>option</b> is an official abbreviation for a longer option,
689
690
 * return the longer option.  Otherwise return <b>option</b>.
 * If <b>command_line</b> is set, apply all abbreviations.  Otherwise, only
691
692
 * apply abbreviations that work for the config file and the command line.
 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
693
static const char *
694
695
expand_abbrev(config_format_t *fmt, const char *option, int command_line,
              int warn_obsolete)
696
697
{
  int i;
698
699
700
  if (! fmt->abbrevs)
    return option;
  for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
701
    /* Abbreviations are casei. */
702
703
    if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
        (command_line || !fmt->abbrevs[i].commandline_only)) {
704
      if (warn_obsolete && fmt->abbrevs[i].warn) {
705
        warn(LD_CONFIG,
706
707
708
709
            "The configuration option '%s' is deprecated; use '%s' instead.",
               fmt->abbrevs[i].abbreviated,
               fmt->abbrevs[i].full);
      }
710
      return fmt->abbrevs[i].full;
711
    }
712
713
714
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
715

716
717
718
719
720
/** Helper: Read a list of configuration options from the command line.
 * If successful, put them in *<b>result</b> and return 0, and return
 * -1 and leave *<b>result</b> alone. */
static int
config_get_commandlines(int argc, char **argv, config_line_t **result)
721
{
722
723
  config_line_t *front = NULL;
  config_line_t **new = &front;
724
725
726
  char *s;
  int i = 1;

727
  while (i < argc) {
728
729
730
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
731
      continue;
732
733
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
734
      continue;
Nick Mathewson's avatar
Nick Mathewson committed
735
736
737
    } else if (!strcmp(argv[i],"--nt-service")) {
      i += 1;
      continue;
738
    }
739
    if (i == argc-1) {
740
      warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
741
742
743
744
             argv[i]);
      config_free_lines(front);
      return -1;
    }
745

746
    *new = tor_malloc_zero(sizeof(config_line_t));
747
    s = argv[i];
748

749
    while (*s == '-')
750
      s++;
751

752
    (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
753
754
    (*new)->value = tor_strdup(argv[i+1]);
    (*new)->next = NULL;
755
    log(LOG_DEBUG, LD_CONFIG, "Commandline: parsed keyword '%s', value '%s'",
756
757
758
        (*new)->key, (*new)->value);

    new = &((*new)->next);
759
760
    i += 2;
  }
761
762
  *result = front;
  return 0;
763
764
}

Nick Mathewson's avatar
Nick Mathewson committed
765
/** Helper: allocate a new configuration option mapping 'key' to 'val',
766
767
 * append it to *<b>lst</b>. */
static void
768
config_line_append(config_line_t **lst,
769
770
                   const char *key,
                   const char *val)
771
{
772
  config_line_t *newline;
773

774
  newline = tor_malloc(sizeof(config_line_t));
775
776
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
777
778
779
780
781
  newline->next = NULL;
  while (*lst)
    lst = &((*lst)->next);

  (*lst) = newline;
782
783
}

784
785
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
786
787
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
788
int
789
config_get_lines(char *string, config_line_t **result)
790
{
791
  config_line_t *list = NULL, **next;
792
  char *k, *v;
793

794
  next = &list;
795
796
797
798
799
800
  do {
    string = parse_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      return -1;
    }
801
802
803
804
    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. */
805
      *next = tor_malloc(sizeof(config_line_t));
806
807
808
809
810
      (*next)->key = tor_strdup(k);
      (*next)->value = tor_strdup(v);
      (*next)->next = NULL;
      next = &((*next)->next);
    }
811
  } while (*string);
812

813
  *result = list;
814
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
815
816
}

Nick Mathewson's avatar
Nick Mathewson committed
817
818
819
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
820
void
821
config_free_lines(config_line_t *front)
822
{
823
  config_line_t *tmp;
824

825
  while (front) {
826
827
828
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
829
830
831
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
832
833
834
  }
}

835
836
837
838
839
840
841
842
843
844
845
846
/** 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
847
848
849
850
/** 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.
 */
851
static config_var_t *
852
config_find_option(config_format_t *fmt, const char *key)
853
854
{
  int i;
855
  size_t keylen = strlen(key);
856
  if (!keylen)
857
    return NULL; /* if they say "--" on the commandline, it's not an option */
Nick Mathewson's avatar
Nick Mathewson committed
858
  /* First, check for an exact (case-insensitive) match */
859
  for (i=0; fmt->vars[i].name; ++i) {
860
    if (!strcasecmp(key, fmt->vars[i].name)) {
861
      return &fmt->vars[i];
862
    }
Nick Mathewson's avatar
Nick Mathewson committed
863
864
  }
  /* If none, check for an abbreviated match */
865
866
  for (i=0; fmt->vars[i].name; ++i) {
    if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
867
      warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
868
          "Please use '%s' instead",
869
870
             key, fmt->vars[i].name);
      return &fmt->vars[i];
871
872
    }
  }
873
  /* Okay, unrecognized options */
874
875
876
  return NULL;
}

877
878
879
880
/*
 * Functions to assign config options.
 */

881
882
/** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
883
884
 *
 * Called from config_assign_line() and option_reset().
885
 */
886
static int
887
888
config_assign_value(config_format_t *fmt, or_options_t *options,
                    config_line_t *c)
889
{
890
  int i, ok;
891
892
  config_var_t *var;
  void *lvalue;
893

894
895
896
  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
897
  tor_assert(var);
898

Nick Mathewson's avatar
Nick Mathewson committed
899
  lvalue = ((char*)options) + var->var_offset;
900

901
  switch (var->type) {
902