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