Vidalia 0.3.1
TorSettings.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file TorSettings.cpp
13** \brief Settings used for starting and running Tor
14*/
15
16#include "TorSettings.h"
17#include "Vidalia.h"
18#include "crypto.h"
19#include "file.h"
20#include "stringutil.h"
21#if defined(Q_OS_WIN32)
22#include "win32.h"
23#include <QFileInfo>
24#endif
25
26#include <QDir>
27#include <QProcess>
28
29/* Tor Settings */
30#define SETTING_TOR_EXECUTABLE "TorExecutable"
31#define SETTING_TORRC "Torrc"
32#define SETTING_CONTROL_ADDR "ControlAddr"
33#define SETTING_CONTROL_PORT "ControlPort"
34#define SETTING_SOCKET_PATH "ControlSocket"
35#define SETTING_CONTROL_METHOD "ControlMethod"
36#define SETTING_AUTH_TOKEN "AuthToken"
37#define SETTING_TOR_USER "User"
38#define SETTING_TOR_GROUP "Group"
39#define SETTING_DATA_DIRECTORY "DataDirectory"
40#define SETTING_AUTH_METHOD "AuthenticationMethod"
41#define SETTING_CONTROL_PASSWORD "ControlPassword"
42#define SETTING_USE_RANDOM_PASSWORD "UseRandomPassword"
43#define SETTING_WARN_PLAINTEXT_PORTS "WarnPlaintextPorts"
44#define SETTING_REJECT_PLAINTEXT_PORTS "RejectPlaintextPorts"
45#define SETTING_BOOTSTRAP "Bootstrap"
46#define SETTING_BOOTSTRAP_FROM "BootstrapFrom"
47#define SETTING_AUTOCONTROL "AutoControl"
48
49/** Default to using hashed password authentication */
50#define DEFAULT_AUTH_METHOD PasswordAuth
51/** Default control method */
52#define DEFAULT_CONTROL_METHOD "ControlPort"
53/** Default socket path */
54#define DEFAULT_SOCKET_PATH ""
55
56/* Arguments we can pass to Tor on the command-line */
57#define TOR_ARG_CONTROL_PORT "ControlPort"
58#define TOR_ARG_TORRC "-f"
59#define TOR_ARG_DATA_DIRECTORY "DataDirectory"
60#define TOR_ARG_HASHED_PASSWORD "HashedControlPassword"
61#define TOR_ARG_COOKIE_AUTH "CookieAuthentication"
62#define TOR_ARG_SOCKSPORT "SocksPort"
63
64/** Generate random control passwords of 16 characters */
65#define PASSWORD_LEN 16
66
67
68/** Default constructor */
70: AbstractTorSettings("Tor", torControl)
71{
72#if defined(Q_OS_WIN32)
73 QString programFiles = win32_program_files_folder();
74 if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists())
76 programFiles + "\\Vidalia Bundle\\Tor\\tor.exe");
77 else
78 setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe");
79#else
80 setDefault(SETTING_TOR_EXECUTABLE, "/usr/bin/tor");
81#endif
82
84 setDefault(SETTING_CONTROL_ADDR, "127.0.0.1");
92 setDefault(SETTING_WARN_PLAINTEXT_PORTS, QList<QVariant>() << 23 << 109
93 << 110 << 143);
98}
99
100/** Applies any changes to Tor's control port or authentication settings. */
101bool
102TorSettings::apply(QString *errmsg)
103{
104 QHash<QString, QString> conf;
105 QString hashedPassword;
106
107 conf.insert(SETTING_CONTROL_PORT,
109
110 if(localValue(SETTING_AUTOCONTROL).toBool())
111 conf.insert(TOR_ARG_SOCKSPORT, "auto");
112 else
113 conf.insert(TOR_ARG_SOCKSPORT, "9050");
114
115 AuthenticationMethod authMethod =
117 switch (authMethod) {
118 case CookieAuth:
119 conf.insert(TOR_ARG_COOKIE_AUTH, "1");
120 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
121 break;
122 case PasswordAuth:
123 hashedPassword = useRandomPassword()
126 if (hashedPassword.isEmpty()) {
127 if (errmsg)
128 *errmsg = tr("Failed to hash the control password.");
129 return false;
130 }
131 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
132 conf.insert(TOR_ARG_HASHED_PASSWORD, hashedPassword);
133 break;
134 default:
135 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
136 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
137 }
138
140 localValue(SETTING_WARN_PLAINTEXT_PORTS).toStringList().join(","));
142 localValue(SETTING_REJECT_PLAINTEXT_PORTS).toStringList().join(","));
143
144 return torControl()->setConf(conf, errmsg);
145}
146
147/** Gets the location of Tor's data directory. */
148QString
150{
151 return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString());
152}
153
154/** Sets the location to use as Tor's data directory. */
155void
156TorSettings::setDataDirectory(const QString &dataDirectory)
157{
158 setValue(SETTING_DATA_DIRECTORY, dataDirectory);
159}
160
161/** Returns a fully-qualified path to Tor's executable, including the
162 * executable name. */
163QString
165{
166 QString tor = localValue(SETTING_TOR_EXECUTABLE).toString();
167 if (tor.isEmpty()) /* Don't let the Tor executable name be empty */
168 tor = defaultValue(SETTING_TOR_EXECUTABLE).toString();
169 return QDir::convertSeparators(tor);
170}
171
172/** Sets the location and name of Tor's executable to the given string. */
173void
174TorSettings::setExecutable(const QString &torExecutable)
175{
176 setValue(SETTING_TOR_EXECUTABLE, torExecutable);
177}
178
179/** Returns the torrc that will be used when starting Tor. */
180QString
182{
183 QString torrc;
185 if (tc && tc->isConnected() && tc->getInfo("config-file", torrc))
186 return QDir::convertSeparators(torrc);
187 return QDir::convertSeparators(localValue(SETTING_TORRC).toString());
188}
189
190/** Sets the torrc that will be used when starting Tor.
191 * \param torrc The torrc to use.
192 */
193void
194TorSettings::setTorrc(const QString &torrc)
195{
196 setValue(SETTING_TORRC, torrc);
197}
198
199/** Get the address or hostname used to connect to Tor */
200QHostAddress
202{
203 QString addr = localValue(SETTING_CONTROL_ADDR).toString();
204 return QHostAddress(addr);
205}
206
207/** Set the address or hostname used to connect to Tor */
208void
209TorSettings::setControlAddress(const QHostAddress &addr)
210{
211 setValue(SETTING_CONTROL_ADDR, addr.toString());
212}
213
214/** Get the control port used to connect to Tor */
215quint16
217{
218 return (quint16)value(SETTING_CONTROL_PORT).toInt();
219}
220
221/** Set the control port used to connect to Tor */
222void
224{
226}
227
228/** Get the path for ControlSocket */
229QString
231{
232 return value(SETTING_SOCKET_PATH).toString();
233}
234
235/** Set the path for ControlSocket */
236void
237TorSettings::setSocketPath(const QString &path)
238{
240}
241
242/** Get the current control method */
245{
247}
248
249/** Set the control method */
250void
252{
254}
255
256/** Returns the plaintext (i.e., not hashed) control password used when
257 * authenticating to Tor. */
258QString
260{
261 return localValue(SETTING_CONTROL_PASSWORD).toString();
262}
263
264/** Sets the control password used when starting Tor with
265 * HashedControlPassword to <b>password</b>. */
266void
267TorSettings::setControlPassword(const QString &password)
268{
270}
271
272/** Returns true if a new, random control password is to be used each time Tor
273 * is started. */
274bool
276{
278}
279
280/** Sets whether or not to generate and use a random control password each
281 * time Tor is started. */
282void
284{
286}
287
288/** Returns the current authentication method used when connecting to Tor. */
291{
294
295 if (tc && tc->isConnected()) {
296 QHash<QString,QString> conf;
297 conf.insert(TOR_ARG_COOKIE_AUTH, "");
298 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
299 if (tc->getConf(conf)) {
300 if (conf.value(TOR_ARG_COOKIE_AUTH) == "1")
301 type = CookieAuth;
302 else if (!conf.value(TOR_ARG_HASHED_PASSWORD).isEmpty())
303 type = PasswordAuth;
304 }
305 }
306 if (type == UnknownAuth)
308 return (type == UnknownAuth ? DEFAULT_AUTH_METHOD : type);
309}
310
311/** Sets the authentication method used when starting Tor to <b>method</b>. */
312void
314{
316}
317
318/** Returns the current list of ports that will cause Tor to issue a warning
319 * when the user tries to connect to one of them. */
320QList<quint16>
322{
323 QList<quint16> out;
324 QList<QVariant> ports;
325
326 ports = value(SETTING_WARN_PLAINTEXT_PORTS).toList();
327 foreach (QVariant port, ports) {
328 out << port.toUInt();
329 }
330 return out;
331}
332
333/** Sets the list of ports that will cause Tor to issue a warning when the
334 * user tries to connect to one of them. */
335void
336TorSettings::setWarnPlaintextPorts(const QList<quint16> &ports)
337{
338 QList<QVariant> warnList;
339 foreach (quint16 port, ports) {
340 warnList << QVariant(port);
341 }
343}
344
345/** Returns the current list of ports that will cause Tor to reject the
346 * connection when the user tries to connect to one of them. */
347QList<quint16>
349{
350 QList<quint16> out;
351 QList<QVariant> ports;
352
353 ports = value(SETTING_REJECT_PLAINTEXT_PORTS).toList();
354 foreach (QVariant port, ports) {
355 out << port.toUInt();
356 }
357 return out;
358}
359
360/** Sets the list of ports that will cause Tor to reject the connection
361 * when the user tries to connect to one of them. */
362void
363TorSettings::setRejectPlaintextPorts(const QList<quint16> &ports)
364{
365 QList<QVariant> rejectList;
366 foreach (quint16 port, ports) {
367 rejectList << QVariant(port);
368 }
370}
371
372/** Returns the string description of the authentication method specified by
373 * <b>method</b>. The authentication method string is stored in Vidalia's
374 * configuration file. */
375QString
377{
378 switch (method) {
379 case NullAuth: return "none";
380 case PasswordAuth: return "password";
381 case CookieAuth: return "cookie";
382 default: break;
383 }
384 return "unknown";
385}
386
387/** Returns the AuthenticationMethod enum value for the string
388 * description of the authentication method given in <b>authMethod</b>. */
390TorSettings::toAuthenticationMethod(const QString &authMethod) const
391{
392 QString str = authMethod.toLower();
393 if (str == toString(NullAuth))
394 return NullAuth;
395 else if (str == toString(PasswordAuth))
396 return PasswordAuth;
397 else if (str == toString(CookieAuth))
398 return CookieAuth;
399 return UnknownAuth;
400}
401
402/** Generates a random control password consisting of PASSWORD_LEN characters. */
403QString
405{
407}
408
409/** Returns the hash of <b>password</b> as given by the command "tor
410 * --hash-password foo". */
411QString
412TorSettings::hashPassword(const QString &password)
413{
414 QByteArray salt;
415
416 /* Generate an 8 octet salt value. Bail if we fail to generate enough
417 * random bytes (unlikely). */
418 while (salt.size() < 8) {
419 QByteArray bytes = crypto_rand_bytes(8-salt.size());
420 if (bytes.isNull())
421 return QString();
422 salt.append(bytes);
423 }
424
425 /* Generate the salted hash of the specified password. 96 is the one-octet
426 * RFC 2440 coded count value hardcoded into Tor. Specifies that we should
427 * hash 64K worth of data. */
428 QByteArray key = crypto_secret_to_key(password, salt, 96);
429 if (key.isNull())
430 return QString();
431 salt.append(96); /* Append the coded count value to the salt */
432
433 /* Convert the result to hexadecimal and put it in the format Tor wants. */
434 return QString("16:%1%2").arg(base16_encode(salt))
435 .arg(base16_encode(key));
436}
437
438void
440{
441 setValue(SETTING_BOOTSTRAP, enabled);
442}
443
444bool
446{
447 return value(SETTING_BOOTSTRAP).toBool();
448}
449
450void
452{
454}
455
456QString
458{
459 return QDir::convertSeparators(value(SETTING_BOOTSTRAP_FROM).toString());
460}
461
462bool
464{
465 return value(SETTING_AUTOCONTROL).toBool();
466}
467
468void
469TorSettings::setAutoControlPort(const bool autoControl)
470{
471 setValue(SETTING_AUTOCONTROL, autoControl);
472}
stop errmsg QVariant
#define SETTING_USE_RANDOM_PASSWORD
Definition: TorSettings.cpp:42
#define SETTING_REJECT_PLAINTEXT_PORTS
Definition: TorSettings.cpp:44
#define PASSWORD_LEN
Definition: TorSettings.cpp:65
#define TOR_ARG_HASHED_PASSWORD
Definition: TorSettings.cpp:60
#define DEFAULT_SOCKET_PATH
Definition: TorSettings.cpp:54
#define SETTING_WARN_PLAINTEXT_PORTS
Definition: TorSettings.cpp:43
#define SETTING_CONTROL_METHOD
Definition: TorSettings.cpp:35
#define SETTING_CONTROL_PASSWORD
Definition: TorSettings.cpp:41
#define SETTING_BOOTSTRAP
Definition: TorSettings.cpp:45
#define SETTING_TORRC
Definition: TorSettings.cpp:31
#define SETTING_CONTROL_PORT
Definition: TorSettings.cpp:33
#define TOR_ARG_COOKIE_AUTH
Definition: TorSettings.cpp:61
#define SETTING_TOR_EXECUTABLE
Definition: TorSettings.cpp:30
#define SETTING_CONTROL_ADDR
Definition: TorSettings.cpp:32
#define TOR_ARG_SOCKSPORT
Definition: TorSettings.cpp:62
#define DEFAULT_CONTROL_METHOD
Definition: TorSettings.cpp:52
#define SETTING_AUTOCONTROL
Definition: TorSettings.cpp:47
#define SETTING_AUTH_METHOD
Definition: TorSettings.cpp:40
#define SETTING_DATA_DIRECTORY
Definition: TorSettings.cpp:39
#define DEFAULT_AUTH_METHOD
Definition: TorSettings.cpp:50
#define SETTING_SOCKET_PATH
Definition: TorSettings.cpp:34
#define SETTING_BOOTSTRAP_FROM
Definition: TorSettings.cpp:46
virtual void setValue(const QString &key, const QVariant &value)
TorControl * torControl() const
virtual QVariant localValue(const QString &key) const
virtual QVariant value(const QString &key) const
static Method fromString(QString method)
static QString toString(ControlMethod::Method method)
bool setConf(QHash< QString, QString > map, QString *errmsg=0)
Definition: TorControl.cpp:722
void setControlPassword(const QString &password)
void setBootstrap(bool enabled)
bool apply(QString *errmsg=0)
QString getExecutable() const
QList< quint16 > getWarnPlaintextPorts() const
bool useRandomPassword() const
void setUseRandomPassword(bool useRandomPassword)
static QString randomPassword()
QString getControlPassword() const
void setControlAddress(const QHostAddress &addr)
QString toString(AuthenticationMethod type) const
quint16 getControlPort() const
TorSettings(TorControl *torControl=0)
Definition: TorSettings.cpp:69
AuthenticationMethod toAuthenticationMethod(const QString &authMethod) const
bool bootstrap() const
QHostAddress getControlAddress() const
QList< quint16 > getRejectPlaintextPorts() const
void setTorrc(const QString &torrc)
void setAuthenticationMethod(AuthenticationMethod method)
QString getDataDirectory() const
void setControlMethod(ControlMethod::Method method)
void setSocketPath(const QString &path)
QString getTorrc() const
void setDataDirectory(const QString &dataDir)
void setBootstrapFrom(const QString &from)
QString bootstrapFrom() const
void setControlPort(quint16 port)
QString getSocketPath() const
void setRejectPlaintextPorts(const QList< quint16 > &ports)
void setWarnPlaintextPorts(const QList< quint16 > &ports)
ControlMethod::Method getControlMethod() const
void setExecutable(const QString &torExecutable)
bool autoControlPort() const
void setAutoControlPort(const bool autoControl)
AuthenticationMethod getAuthenticationMethod() const
static QString hashPassword(const QString &password)
QVariant defaultValue(const QString &key) const
Definition: VSettings.cpp:79
void setDefault(const QString &key, const QVariant &val)
Definition: VSettings.cpp:71
static QString dataDirectory()
Definition: Vidalia.cpp:355
QByteArray crypto_secret_to_key(const QString &secret, const QByteArray &salt, quint8 c)
Definition: crypto.cpp:166
QString crypto_rand_string(int len)
Definition: crypto.cpp:150
QByteArray crypto_rand_bytes(int len)
Definition: crypto.cpp:71
Definition: tcglobal.cpp:19
QString base16_encode(const QByteArray &buf)
Definition: stringutil.cpp:115
QString win32_program_files_folder()
Definition: win32.cpp:78