Vidalia
0.2.15
|
00001 /* 00002 ** This file is part of Vidalia, and is subject to the license terms in the 00003 ** LICENSE file, found in the top level directory of this distribution. If you 00004 ** did not receive the LICENSE file with this file, you may obtain it from the 00005 ** Vidalia source package distributed by the Vidalia Project at 00006 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 00007 ** including this file, may be copied, modified, propagated, or distributed 00008 ** except according to the terms described in the LICENSE file. 00009 */ 00010 00011 /* 00012 ** \file TorSettings.cpp 00013 ** \brief Settings used for starting and running Tor 00014 */ 00015 00016 #include "TorSettings.h" 00017 #include "Vidalia.h" 00018 #include "crypto.h" 00019 #include "file.h" 00020 #include "stringutil.h" 00021 #if defined(Q_OS_WIN32) 00022 #include "win32.h" 00023 #include <QFileInfo> 00024 #endif 00025 00026 #include <QDir> 00027 #include <QProcess> 00028 00029 /* Tor Settings */ 00030 #define SETTING_TOR_EXECUTABLE "TorExecutable" 00031 #define SETTING_TORRC "Torrc" 00032 #define SETTING_CONTROL_ADDR "ControlAddr" 00033 #define SETTING_CONTROL_PORT "ControlPort" 00034 #define SETTING_SOCKET_PATH "ControlSocket" 00035 #define SETTING_CONTROL_METHOD "ControlMethod" 00036 #define SETTING_AUTH_TOKEN "AuthToken" 00037 #define SETTING_TOR_USER "User" 00038 #define SETTING_TOR_GROUP "Group" 00039 #define SETTING_DATA_DIRECTORY "DataDirectory" 00040 #define SETTING_AUTH_METHOD "AuthenticationMethod" 00041 #define SETTING_CONTROL_PASSWORD "ControlPassword" 00042 #define SETTING_USE_RANDOM_PASSWORD "UseRandomPassword" 00043 #define SETTING_WARN_PLAINTEXT_PORTS "WarnPlaintextPorts" 00044 #define SETTING_REJECT_PLAINTEXT_PORTS "RejectPlaintextPorts" 00045 #define SETTING_BOOTSTRAP "Bootstrap" 00046 #define SETTING_BOOTSTRAP_FROM "BootstrapFrom" 00047 #define SETTING_AUTOCONTROL "AutoControl" 00048 00049 /** Default to using hashed password authentication */ 00050 #define DEFAULT_AUTH_METHOD PasswordAuth 00051 /** Default control method */ 00052 #define DEFAULT_CONTROL_METHOD "ControlPort" 00053 /** Default socket path */ 00054 #define DEFAULT_SOCKET_PATH "" 00055 00056 /* Arguments we can pass to Tor on the command-line */ 00057 #define TOR_ARG_CONTROL_PORT "ControlPort" 00058 #define TOR_ARG_TORRC "-f" 00059 #define TOR_ARG_DATA_DIRECTORY "DataDirectory" 00060 #define TOR_ARG_HASHED_PASSWORD "HashedControlPassword" 00061 #define TOR_ARG_COOKIE_AUTH "CookieAuthentication" 00062 00063 /** Generate random control passwords of 16 characters */ 00064 #define PASSWORD_LEN 16 00065 00066 00067 /** Default constructor */ 00068 TorSettings::TorSettings(TorControl *torControl) 00069 : AbstractTorSettings("Tor", torControl) 00070 { 00071 #if defined(Q_OS_WIN32) 00072 QString programFiles = win32_program_files_folder(); 00073 if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists()) 00074 setDefault(SETTING_TOR_EXECUTABLE, 00075 programFiles + "\\Vidalia Bundle\\Tor\\tor.exe"); 00076 else 00077 setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe"); 00078 #else 00079 setDefault(SETTING_TOR_EXECUTABLE, "tor"); 00080 #endif 00081 00082 setDefault(SETTING_TORRC, Vidalia::dataDirectory() + "/torrc"); 00083 setDefault(SETTING_CONTROL_ADDR, "127.0.0.1"); 00084 setDefault(SETTING_CONTROL_PORT, 9051); 00085 setDefault(SETTING_AUTH_METHOD, toString(DEFAULT_AUTH_METHOD)); 00086 setDefault(SETTING_CONTROL_METHOD, DEFAULT_CONTROL_METHOD); 00087 setDefault(SETTING_SOCKET_PATH, DEFAULT_SOCKET_PATH); 00088 setDefault(SETTING_DATA_DIRECTORY, ""); 00089 setDefault(SETTING_CONTROL_PASSWORD, ""); 00090 setDefault(SETTING_USE_RANDOM_PASSWORD, true); 00091 setDefault(SETTING_WARN_PLAINTEXT_PORTS, QList<QVariant>() << 23 << 109 00092 << 110 << 143); 00093 setDefault(SETTING_REJECT_PLAINTEXT_PORTS, QList<QVariant>()); 00094 setDefault(SETTING_BOOTSTRAP, false); 00095 setDefault(SETTING_BOOTSTRAP_FROM, ""); 00096 setDefault(SETTING_AUTOCONTROL, false); 00097 } 00098 00099 /** Applies any changes to Tor's control port or authentication settings. */ 00100 bool 00101 TorSettings::apply(QString *errmsg) 00102 { 00103 QHash<QString, QString> conf; 00104 QString hashedPassword; 00105 00106 conf.insert(SETTING_CONTROL_PORT, 00107 localValue(SETTING_CONTROL_PORT).toString()); 00108 00109 AuthenticationMethod authMethod = 00110 toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString()); 00111 switch (authMethod) { 00112 case CookieAuth: 00113 conf.insert(TOR_ARG_COOKIE_AUTH, "1"); 00114 conf.insert(TOR_ARG_HASHED_PASSWORD, ""); 00115 break; 00116 case PasswordAuth: 00117 hashedPassword = useRandomPassword() 00118 ? hashPassword(randomPassword()) 00119 : hashPassword(getControlPassword()); 00120 if (hashedPassword.isEmpty()) { 00121 if (errmsg) 00122 *errmsg = tr("Failed to hash the control password."); 00123 return false; 00124 } 00125 conf.insert(TOR_ARG_COOKIE_AUTH, "0"); 00126 conf.insert(TOR_ARG_HASHED_PASSWORD, hashedPassword); 00127 break; 00128 default: 00129 conf.insert(TOR_ARG_COOKIE_AUTH, "0"); 00130 conf.insert(TOR_ARG_HASHED_PASSWORD, ""); 00131 } 00132 00133 conf.insert(SETTING_WARN_PLAINTEXT_PORTS, 00134 localValue(SETTING_WARN_PLAINTEXT_PORTS).toStringList().join(",")); 00135 conf.insert(SETTING_REJECT_PLAINTEXT_PORTS, 00136 localValue(SETTING_REJECT_PLAINTEXT_PORTS).toStringList().join(",")); 00137 00138 return torControl()->setConf(conf, errmsg); 00139 } 00140 00141 /** Gets the location of Tor's data directory. */ 00142 QString 00143 TorSettings::getDataDirectory() const 00144 { 00145 return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString()); 00146 } 00147 00148 /** Sets the location to use as Tor's data directory. */ 00149 void 00150 TorSettings::setDataDirectory(const QString &dataDirectory) 00151 { 00152 setValue(SETTING_DATA_DIRECTORY, dataDirectory); 00153 } 00154 00155 /** Returns a fully-qualified path to Tor's executable, including the 00156 * executable name. */ 00157 QString 00158 TorSettings::getExecutable() const 00159 { 00160 QString tor = localValue(SETTING_TOR_EXECUTABLE).toString(); 00161 if (tor.isEmpty()) /* Don't let the Tor executable name be empty */ 00162 tor = defaultValue(SETTING_TOR_EXECUTABLE).toString(); 00163 return QDir::convertSeparators(tor); 00164 } 00165 00166 /** Sets the location and name of Tor's executable to the given string. */ 00167 void 00168 TorSettings::setExecutable(const QString &torExecutable) 00169 { 00170 setValue(SETTING_TOR_EXECUTABLE, torExecutable); 00171 } 00172 00173 /** Returns the torrc that will be used when starting Tor. */ 00174 QString 00175 TorSettings::getTorrc() const 00176 { 00177 QString torrc; 00178 TorControl *tc = torControl(); 00179 if (tc && tc->isConnected() && tc->getInfo("config-file", torrc)) 00180 return QDir::convertSeparators(torrc); 00181 return QDir::convertSeparators(localValue(SETTING_TORRC).toString()); 00182 } 00183 00184 /** Sets the torrc that will be used when starting Tor. 00185 * \param torrc The torrc to use. 00186 */ 00187 void 00188 TorSettings::setTorrc(const QString &torrc) 00189 { 00190 setValue(SETTING_TORRC, torrc); 00191 } 00192 00193 /** Get the address or hostname used to connect to Tor */ 00194 QHostAddress 00195 TorSettings::getControlAddress() const 00196 { 00197 QString addr = localValue(SETTING_CONTROL_ADDR).toString(); 00198 return QHostAddress(addr); 00199 } 00200 00201 /** Set the address or hostname used to connect to Tor */ 00202 void 00203 TorSettings::setControlAddress(const QHostAddress &addr) 00204 { 00205 setValue(SETTING_CONTROL_ADDR, addr.toString()); 00206 } 00207 00208 /** Get the control port used to connect to Tor */ 00209 quint16 00210 TorSettings::getControlPort() const 00211 { 00212 return (quint16)value(SETTING_CONTROL_PORT).toInt(); 00213 } 00214 00215 /** Set the control port used to connect to Tor */ 00216 void 00217 TorSettings::setControlPort(quint16 port) 00218 { 00219 setValue(SETTING_CONTROL_PORT, port); 00220 } 00221 00222 /** Get the path for ControlSocket */ 00223 QString 00224 TorSettings::getSocketPath() const 00225 { 00226 return value(SETTING_SOCKET_PATH).toString(); 00227 } 00228 00229 /** Set the path for ControlSocket */ 00230 void 00231 TorSettings::setSocketPath(const QString &path) 00232 { 00233 setValue(SETTING_SOCKET_PATH, path); 00234 } 00235 00236 /** Get the current control method */ 00237 ControlMethod::Method 00238 TorSettings::getControlMethod() const 00239 { 00240 return ControlMethod::fromString(localValue(SETTING_CONTROL_METHOD).toString()); 00241 } 00242 00243 /** Set the control method */ 00244 void 00245 TorSettings::setControlMethod(ControlMethod::Method method) 00246 { 00247 setValue(SETTING_CONTROL_METHOD, ControlMethod::toString(method)); 00248 } 00249 00250 /** Returns the plaintext (i.e., not hashed) control password used when 00251 * authenticating to Tor. */ 00252 QString 00253 TorSettings::getControlPassword() const 00254 { 00255 return localValue(SETTING_CONTROL_PASSWORD).toString(); 00256 } 00257 00258 /** Sets the control password used when starting Tor with 00259 * HashedControlPassword to <b>password</b>. */ 00260 void 00261 TorSettings::setControlPassword(const QString &password) 00262 { 00263 setValue(SETTING_CONTROL_PASSWORD, password); 00264 } 00265 00266 /** Returns true if a new, random control password is to be used each time Tor 00267 * is started. */ 00268 bool 00269 TorSettings::useRandomPassword() const 00270 { 00271 return localValue(SETTING_USE_RANDOM_PASSWORD).toBool(); 00272 } 00273 00274 /** Sets whether or not to generate and use a random control password each 00275 * time Tor is started. */ 00276 void 00277 TorSettings::setUseRandomPassword(bool useRandomPassword) 00278 { 00279 setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword); 00280 } 00281 00282 /** Returns the current authentication method used when connecting to Tor. */ 00283 TorSettings::AuthenticationMethod 00284 TorSettings::getAuthenticationMethod() const 00285 { 00286 AuthenticationMethod type = UnknownAuth; 00287 TorControl *tc = torControl(); 00288 00289 if (tc && tc->isConnected()) { 00290 QHash<QString,QString> conf; 00291 conf.insert(TOR_ARG_COOKIE_AUTH, ""); 00292 conf.insert(TOR_ARG_HASHED_PASSWORD, ""); 00293 if (tc->getConf(conf)) { 00294 if (conf.value(TOR_ARG_COOKIE_AUTH) == "1") 00295 type = CookieAuth; 00296 else if (!conf.value(TOR_ARG_HASHED_PASSWORD).isEmpty()) 00297 type = PasswordAuth; 00298 } 00299 } 00300 if (type == UnknownAuth) 00301 type = toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString()); 00302 return (type == UnknownAuth ? DEFAULT_AUTH_METHOD : type); 00303 } 00304 00305 /** Sets the authentication method used when starting Tor to <b>method</b>. */ 00306 void 00307 TorSettings::setAuthenticationMethod(AuthenticationMethod method) 00308 { 00309 setValue(SETTING_AUTH_METHOD, toString(method)); 00310 } 00311 00312 /** Returns the current list of ports that will cause Tor to issue a warning 00313 * when the user tries to connect to one of them. */ 00314 QList<quint16> 00315 TorSettings::getWarnPlaintextPorts() const 00316 { 00317 QList<quint16> out; 00318 QList<QVariant> ports; 00319 00320 ports = value(SETTING_WARN_PLAINTEXT_PORTS).toList(); 00321 foreach (QVariant port, ports) { 00322 out << port.toUInt(); 00323 } 00324 return out; 00325 } 00326 00327 /** Sets the list of ports that will cause Tor to issue a warning when the 00328 * user tries to connect to one of them. */ 00329 void 00330 TorSettings::setWarnPlaintextPorts(const QList<quint16> &ports) 00331 { 00332 QList<QVariant> warnList; 00333 foreach (quint16 port, ports) { 00334 warnList << QVariant(port); 00335 } 00336 setValue(SETTING_WARN_PLAINTEXT_PORTS, warnList); 00337 } 00338 00339 /** Returns the current list of ports that will cause Tor to reject the 00340 * connection when the user tries to connect to one of them. */ 00341 QList<quint16> 00342 TorSettings::getRejectPlaintextPorts() const 00343 { 00344 QList<quint16> out; 00345 QList<QVariant> ports; 00346 00347 ports = value(SETTING_REJECT_PLAINTEXT_PORTS).toList(); 00348 foreach (QVariant port, ports) { 00349 out << port.toUInt(); 00350 } 00351 return out; 00352 } 00353 00354 /** Sets the list of ports that will cause Tor to reject the connection 00355 * when the user tries to connect to one of them. */ 00356 void 00357 TorSettings::setRejectPlaintextPorts(const QList<quint16> &ports) 00358 { 00359 QList<QVariant> rejectList; 00360 foreach (quint16 port, ports) { 00361 rejectList << QVariant(port); 00362 } 00363 setValue(SETTING_REJECT_PLAINTEXT_PORTS, rejectList); 00364 } 00365 00366 /** Returns the string description of the authentication method specified by 00367 * <b>method</b>. The authentication method string is stored in Vidalia's 00368 * configuration file. */ 00369 QString 00370 TorSettings::toString(AuthenticationMethod method) const 00371 { 00372 switch (method) { 00373 case NullAuth: return "none"; 00374 case PasswordAuth: return "password"; 00375 case CookieAuth: return "cookie"; 00376 default: break; 00377 } 00378 return "unknown"; 00379 } 00380 00381 /** Returns the AuthenticationMethod enum value for the string 00382 * description of the authentication method given in <b>authMethod</b>. */ 00383 TorSettings::AuthenticationMethod 00384 TorSettings::toAuthenticationMethod(const QString &authMethod) const 00385 { 00386 QString str = authMethod.toLower(); 00387 if (str == toString(NullAuth)) 00388 return NullAuth; 00389 else if (str == toString(PasswordAuth)) 00390 return PasswordAuth; 00391 else if (str == toString(CookieAuth)) 00392 return CookieAuth; 00393 return UnknownAuth; 00394 } 00395 00396 /** Generates a random control password consisting of PASSWORD_LEN characters. */ 00397 QString 00398 TorSettings::randomPassword() 00399 { 00400 return crypto_rand_string(PASSWORD_LEN); 00401 } 00402 00403 /** Returns the hash of <b>password</b> as given by the command "tor 00404 * --hash-password foo". */ 00405 QString 00406 TorSettings::hashPassword(const QString &password) 00407 { 00408 QByteArray salt; 00409 00410 /* Generate an 8 octet salt value. Bail if we fail to generate enough 00411 * random bytes (unlikely). */ 00412 while (salt.size() < 8) { 00413 QByteArray bytes = crypto_rand_bytes(8-salt.size()); 00414 if (bytes.isNull()) 00415 return QString(); 00416 salt.append(bytes); 00417 } 00418 00419 /* Generate the salted hash of the specified password. 96 is the one-octet 00420 * RFC 2440 coded count value hardcoded into Tor. Specifies that we should 00421 * hash 64K worth of data. */ 00422 QByteArray key = crypto_secret_to_key(password, salt, 96); 00423 if (key.isNull()) 00424 return QString(); 00425 salt.append(96); /* Append the coded count value to the salt */ 00426 00427 /* Convert the result to hexadecimal and put it in the format Tor wants. */ 00428 return QString("16:%1%2").arg(base16_encode(salt)) 00429 .arg(base16_encode(key)); 00430 } 00431 00432 void 00433 TorSettings::setBootstrap(bool enabled) 00434 { 00435 setValue(SETTING_BOOTSTRAP, enabled); 00436 } 00437 00438 bool 00439 TorSettings::bootstrap() const 00440 { 00441 return value(SETTING_BOOTSTRAP).toBool(); 00442 } 00443 00444 void 00445 TorSettings::setBootstrapFrom(const QString &from) 00446 { 00447 setValue(SETTING_BOOTSTRAP_FROM, from); 00448 } 00449 00450 QString 00451 TorSettings::bootstrapFrom() const 00452 { 00453 return QDir::convertSeparators(value(SETTING_BOOTSTRAP_FROM).toString()); 00454 } 00455 00456 bool 00457 TorSettings::autoControlPort() const 00458 { 00459 return value(SETTING_AUTOCONTROL).toBool(); 00460 } 00461 00462 void 00463 TorSettings::setAutoControlPort(const bool autoControl) 00464 { 00465 setValue(SETTING_AUTOCONTROL, autoControl); 00466 }