00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "TorSettings.h"
00018 #include "Vidalia.h"
00019 #include "crypto.h"
00020 #include "file.h"
00021 #include "stringutil.h"
00022 #if defined(Q_OS_WIN32)
00023 #include "win32.h"
00024 #include <QFileInfo>
00025 #endif
00026
00027 #include <QDir>
00028 #include <QProcess>
00029
00030
00031 #define SETTING_TOR_EXECUTABLE "TorExecutable"
00032 #define SETTING_TORRC "Torrc"
00033 #define SETTING_CONTROL_ADDR "ControlAddr"
00034 #define SETTING_CONTROL_PORT "ControlPort"
00035 #define SETTING_AUTH_TOKEN "AuthToken"
00036 #define SETTING_TOR_USER "User"
00037 #define SETTING_TOR_GROUP "Group"
00038 #define SETTING_DATA_DIRECTORY "DataDirectory"
00039 #define SETTING_AUTH_METHOD "AuthenticationMethod"
00040 #define SETTING_CONTROL_PASSWORD "ControlPassword"
00041 #define SETTING_USE_RANDOM_PASSWORD "UseRandomPassword"
00042 #define SETTING_WARN_PLAINTEXT_PORTS "WarnPlaintextPorts"
00043 #define SETTING_REJECT_PLAINTEXT_PORTS "RejectPlaintextPorts"
00044
00045
00046 #define DEFAULT_AUTH_METHOD PasswordAuth
00047
00048
00049 #define TOR_ARG_CONTROL_PORT "ControlPort"
00050 #define TOR_ARG_TORRC "-f"
00051 #define TOR_ARG_DATA_DIRECTORY "DataDirectory"
00052 #define TOR_ARG_HASHED_PASSWORD "HashedControlPassword"
00053 #define TOR_ARG_COOKIE_AUTH "CookieAuthentication"
00054
00055
00056 #define PASSWORD_LEN 16
00057
00058
00059
00060 TorSettings::TorSettings(TorControl *torControl)
00061 : AbstractTorSettings("Tor", torControl)
00062 {
00063 #if defined(Q_OS_WIN32)
00064 QString programFiles = win32_program_files_folder();
00065 if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists())
00066 setDefault(SETTING_TOR_EXECUTABLE,
00067 programFiles + "\\Vidalia Bundle\\Tor\\tor.exe");
00068 else
00069 setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe");
00070 #else
00071 setDefault(SETTING_TOR_EXECUTABLE, "tor");
00072 #endif
00073
00074 setDefault(SETTING_TORRC, Vidalia::dataDirectory() + "/torrc");
00075 setDefault(SETTING_CONTROL_ADDR, "127.0.0.1");
00076 setDefault(SETTING_CONTROL_PORT, 9051);
00077 setDefault(SETTING_AUTH_METHOD, toString(DEFAULT_AUTH_METHOD));
00078 setDefault(SETTING_DATA_DIRECTORY, "");
00079 setDefault(SETTING_CONTROL_PASSWORD, "");
00080 setDefault(SETTING_USE_RANDOM_PASSWORD, true);
00081 setDefault(SETTING_WARN_PLAINTEXT_PORTS, QList<QVariant>() << 23 << 109
00082 << 110 << 143);
00083 setDefault(SETTING_REJECT_PLAINTEXT_PORTS, QList<QVariant>());
00084 }
00085
00086
00087 bool
00088 TorSettings::apply(QString *errmsg)
00089 {
00090 QHash<QString, QString> conf;
00091 QString hashedPassword;
00092
00093 conf.insert(SETTING_CONTROL_PORT,
00094 localValue(SETTING_CONTROL_PORT).toString());
00095
00096 AuthenticationMethod authMethod =
00097 toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00098 switch (authMethod) {
00099 case CookieAuth:
00100 conf.insert(TOR_ARG_COOKIE_AUTH, "1");
00101 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00102 break;
00103 case PasswordAuth:
00104 hashedPassword = useRandomPassword()
00105 ? hashPassword(randomPassword())
00106 : hashPassword(getControlPassword());
00107 if (hashedPassword.isEmpty()) {
00108 if (errmsg)
00109 *errmsg = tr("Failed to hash the control password.");
00110 return false;
00111 }
00112 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
00113 conf.insert(TOR_ARG_HASHED_PASSWORD, hashedPassword);
00114 break;
00115 default:
00116 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
00117 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00118 }
00119
00120 conf.insert(SETTING_WARN_PLAINTEXT_PORTS,
00121 localValue(SETTING_WARN_PLAINTEXT_PORTS).toStringList().join(","));
00122 conf.insert(SETTING_REJECT_PLAINTEXT_PORTS,
00123 localValue(SETTING_REJECT_PLAINTEXT_PORTS).toStringList().join(","));
00124
00125 return torControl()->setConf(conf, errmsg);
00126 }
00127
00128
00129 QString
00130 TorSettings::getDataDirectory() const
00131 {
00132 return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString());
00133 }
00134
00135
00136 void
00137 TorSettings::setDataDirectory(const QString &dataDirectory)
00138 {
00139 setValue(SETTING_DATA_DIRECTORY, dataDirectory);
00140 }
00141
00142
00143
00144 QString
00145 TorSettings::getExecutable() const
00146 {
00147 QString tor = localValue(SETTING_TOR_EXECUTABLE).toString();
00148 if (tor.isEmpty())
00149 tor = defaultValue(SETTING_TOR_EXECUTABLE).toString();
00150 return QDir::convertSeparators(tor);
00151 }
00152
00153
00154 void
00155 TorSettings::setExecutable(const QString &torExecutable)
00156 {
00157 setValue(SETTING_TOR_EXECUTABLE, torExecutable);
00158 }
00159
00160
00161 QString
00162 TorSettings::getTorrc() const
00163 {
00164 QString torrc;
00165 TorControl *tc = torControl();
00166 if (tc && tc->isConnected() && tc->getInfo("config-file", torrc))
00167 return QDir::convertSeparators(torrc);
00168 return QDir::convertSeparators(localValue(SETTING_TORRC).toString());
00169 }
00170
00171
00172
00173
00174 void
00175 TorSettings::setTorrc(const QString &torrc)
00176 {
00177 setValue(SETTING_TORRC, torrc);
00178 }
00179
00180
00181 QHostAddress
00182 TorSettings::getControlAddress() const
00183 {
00184 QString addr = localValue(SETTING_CONTROL_ADDR).toString();
00185 return QHostAddress(addr);
00186 }
00187
00188
00189 void
00190 TorSettings::setControlAddress(const QHostAddress &addr)
00191 {
00192 setValue(SETTING_CONTROL_ADDR, addr.toString());
00193 }
00194
00195
00196 quint16
00197 TorSettings::getControlPort() const
00198 {
00199 return (quint16)value(SETTING_CONTROL_PORT).toInt();
00200 }
00201
00202
00203 void
00204 TorSettings::setControlPort(quint16 port)
00205 {
00206 setValue(SETTING_CONTROL_PORT, port);
00207 }
00208
00209
00210
00211 QString
00212 TorSettings::getControlPassword() const
00213 {
00214 return localValue(SETTING_CONTROL_PASSWORD).toString();
00215 }
00216
00217
00218
00219 void
00220 TorSettings::setControlPassword(const QString &password)
00221 {
00222 setValue(SETTING_CONTROL_PASSWORD, password);
00223 }
00224
00225
00226
00227 bool
00228 TorSettings::useRandomPassword() const
00229 {
00230 return localValue(SETTING_USE_RANDOM_PASSWORD).toBool();
00231 }
00232
00233
00234
00235 void
00236 TorSettings::setUseRandomPassword(bool useRandomPassword)
00237 {
00238 setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword);
00239 }
00240
00241
00242 TorSettings::AuthenticationMethod
00243 TorSettings::getAuthenticationMethod() const
00244 {
00245 AuthenticationMethod type = UnknownAuth;
00246 TorControl *tc = torControl();
00247
00248 if (tc && tc->isConnected()) {
00249 QHash<QString,QString> conf;
00250 conf.insert(TOR_ARG_COOKIE_AUTH, "");
00251 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00252 if (tc->getConf(conf)) {
00253 if (conf.value(TOR_ARG_COOKIE_AUTH) == "1")
00254 type = CookieAuth;
00255 else if (!conf.value(TOR_ARG_HASHED_PASSWORD).isEmpty())
00256 type = PasswordAuth;
00257 }
00258 }
00259 if (type == UnknownAuth)
00260 type = toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00261 return (type == UnknownAuth ? DEFAULT_AUTH_METHOD : type);
00262 }
00263
00264
00265 void
00266 TorSettings::setAuthenticationMethod(AuthenticationMethod method)
00267 {
00268 setValue(SETTING_AUTH_METHOD, toString(method));
00269 }
00270
00271
00272
00273 QList<quint16>
00274 TorSettings::getWarnPlaintextPorts() const
00275 {
00276 QList<quint16> out;
00277 QList<QVariant> ports;
00278
00279 ports = value(SETTING_WARN_PLAINTEXT_PORTS).toList();
00280 foreach (QVariant port, ports) {
00281 out << port.toUInt();
00282 }
00283 return out;
00284 }
00285
00286
00287
00288 void
00289 TorSettings::setWarnPlaintextPorts(const QList<quint16> &ports)
00290 {
00291 QList<QVariant> warnList;
00292 foreach (quint16 port, ports) {
00293 warnList << QVariant(port);
00294 }
00295 setValue(SETTING_WARN_PLAINTEXT_PORTS, warnList);
00296 }
00297
00298
00299
00300 QList<quint16>
00301 TorSettings::getRejectPlaintextPorts() const
00302 {
00303 QList<quint16> out;
00304 QList<QVariant> ports;
00305
00306 ports = value(SETTING_REJECT_PLAINTEXT_PORTS).toList();
00307 foreach (QVariant port, ports) {
00308 out << port.toUInt();
00309 }
00310 return out;
00311 }
00312
00313
00314
00315 void
00316 TorSettings::setRejectPlaintextPorts(const QList<quint16> &ports)
00317 {
00318 QList<QVariant> rejectList;
00319 foreach (quint16 port, ports) {
00320 rejectList << QVariant(port);
00321 }
00322 setValue(SETTING_REJECT_PLAINTEXT_PORTS, rejectList);
00323 }
00324
00325
00326
00327
00328 QString
00329 TorSettings::toString(AuthenticationMethod method) const
00330 {
00331 switch (method) {
00332 case NullAuth: return "none";
00333 case PasswordAuth: return "password";
00334 case CookieAuth: return "cookie";
00335 default: break;
00336 }
00337 return "unknown";
00338 }
00339
00340
00341
00342 TorSettings::AuthenticationMethod
00343 TorSettings::toAuthenticationMethod(const QString &authMethod) const
00344 {
00345 QString str = authMethod.toLower();
00346 if (str == toString(NullAuth))
00347 return NullAuth;
00348 else if (str == toString(PasswordAuth))
00349 return PasswordAuth;
00350 else if (str == toString(CookieAuth))
00351 return CookieAuth;
00352 return UnknownAuth;
00353 }
00354
00355
00356 QString
00357 TorSettings::randomPassword()
00358 {
00359 return crypto_rand_string(PASSWORD_LEN);
00360 }
00361
00362
00363
00364 QString
00365 TorSettings::hashPassword(const QString &password)
00366 {
00367 QByteArray salt;
00368
00369
00370
00371 while (salt.size() < 8) {
00372 QByteArray bytes = crypto_rand_bytes(8-salt.size());
00373 if (bytes.isNull())
00374 return QString();
00375 salt.append(bytes);
00376 }
00377
00378
00379
00380
00381 QByteArray key = crypto_secret_to_key(password, salt, 96);
00382 if (key.isNull())
00383 return QString();
00384 salt.append(96);
00385
00386
00387 return QString("16:%1%2").arg(base16_encode(salt))
00388 .arg(base16_encode(key));
00389 }
00390