config.c 114 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
typedef int (*validate_fn_t)(void*,void*);
251

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
284
static int options_validate(or_options_t *old_options,
                            or_options_t *options);
285
static int options_act_reversible(or_options_t *old_options);
286
static int options_act(or_options_t *old_options);
287
static int options_transition_allowed(or_options_t *old, or_options_t *new);
288
289
290
291
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);
292
static int check_nickname_list(const char *lst, const char *name);
293
static void config_register_addressmaps(or_options_t *options);
294

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

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

324
325
/*static*/ or_options_t *options_new(void);

326
327
#define OR_OPTIONS_MAGIC 9090909

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

350
351
352
353
354
/*
 * Functions to read and write the global options pointer.
 */

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

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

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

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

  return 0;
404
405
}

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

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

436
437
438
439
440
441
442
443
444
445
446
447
448
/** 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);
}

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
486
487
/** 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) {
488
    err(LD_FS, "Couldn't access/create private data directory \"%s\"",
489
        options->DataDirectory);
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    /* 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) {
506
    err(LD_CONFIG, "Failed to bind one of the listener ports.");
507
508
509
510
511
512
513
    goto rollback;
  }

 commit:
  r = 0;
  SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
  {
514
    notice(LD_NET, "Closing old %s on %s:%d",
515
516
517
518
519
520
521
522
523
524
525
526
527
528
           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,
  {
529
    notice(LD_NET, "Closing %s on %s:%d",
530
531
532
533
534
535
536
537
538
539
540
           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;
}

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

  clear_trusted_dir_servers();
560
561
562
563
564
565
566
  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;
      }
567
    }
568
569
  } else {
    add_default_trusted_dirservers();
570
571
  }

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

578
579
580
  if (options->EntryNodes && strlen(options->EntryNodes))
    options->UseHelperNodes = 0;

581
582
583
584
585
  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) {
586
587
      err(LD_CONFIG,
          "Couldn't access/create private data directory \"%s\"", fn);
588
589
590
      tor_free(fn);
      return -1;
    }
591
592
    tor_free(fn);
  }
593

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

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

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

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

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

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

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

634
635
636
  /* Register addressmap directives */
  config_register_addressmaps(options);

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

643
644
  init_cookie_authentication(options->CookieAuthentication);

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

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

659
660
661
  if (!running_tor)
    return 0;

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

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

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

683
  return 0;
684
685
686
687
688
689
}

/*
 * Functions to parse config options
 */

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

718
719
720
721
722
/** 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)
723
{
724
725
  config_line_t *front = NULL;
  config_line_t **new = &front;
726
727
728
  char *s;
  int i = 1;

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

748
    *new = tor_malloc_zero(sizeof(config_line_t));
749
    s = argv[i];
750

751
    while (*s == '-')
752
      s++;
753

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

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

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

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

  (*lst) = newline;
784
785
}

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

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

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

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

827
  while (front) {
828
829
830
    tmp = front;
    front = tmp->next;

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

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

879
880
881
882
/*
 * Functions to assign config options.
 */

883
884
/** <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.
885
886
 *
 * Called from config_assign_line() and option_reset().
887
 */
888
static int
889
890
config_assign_value(config_format_t *fmt, or_options_t *options,
                    config_line_t *c)
891
{
892
  int i, ok;
893
894
  config_var_t *var;
  void *lvalue;
895

896
897
898
  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
899