Vidalia 0.2.10
|
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 ** \version $Id: TorSettings.cpp 3901 2009-06-27 01:57:05Z edmanm $ 00014 ** \brief Settings used for starting and running Tor 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 /* Tor Settings */ 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 /** Default to using hashed password authentication */ 00046 #define DEFAULT_AUTH_METHOD PasswordAuth 00047 00048 /* Arguments we can pass to Tor on the command-line */ 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 /** Generate random control passwords of 16 characters */ 00056 #define PASSWORD_LEN 16 00057 00058 00059 /** Default constructor */ 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, "/usr/bin/tor"); 00072 #endif 00073 00074 setDefault(SETTING_TORRC, "/etc/tor/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, "/var/lib/tor"); 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 /** Applies any changes to Tor's control port or authentication settings. */ 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 /** Gets the location of Tor's data directory. */ 00129 QString 00130 TorSettings::getDataDirectory() const 00131 { 00132 return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString()); 00133 } 00134 00135 /** Sets the location to use as Tor's data directory. */ 00136 void 00137 TorSettings::setDataDirectory(const QString &dataDirectory) 00138 { 00139 setValue(SETTING_DATA_DIRECTORY, dataDirectory); 00140 } 00141 00142 /** Returns a fully-qualified path to Tor's executable, including the 00143 * executable name. */ 00144 QString 00145 TorSettings::getExecutable() const 00146 { 00147 QString tor = localValue(SETTING_TOR_EXECUTABLE).toString(); 00148 if (tor.isEmpty()) /* Don't let the Tor executable name be empty */ 00149 tor = defaultValue(SETTING_TOR_EXECUTABLE).toString(); 00150 return QDir::convertSeparators(tor); 00151 } 00152 00153 /** Sets the location and name of Tor's executable to the given string. */ 00154 void 00155 TorSettings::setExecutable(const QString &torExecutable) 00156 { 00157 setValue(SETTING_TOR_EXECUTABLE, torExecutable); 00158 } 00159 00160 /** Returns the torrc that will be used when starting Tor. */ 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 /** Sets the torrc that will be used when starting Tor. 00172 * \param torrc The torrc to use. 00173 */ 00174 void 00175 TorSettings::setTorrc(const QString &torrc) 00176 { 00177 setValue(SETTING_TORRC, torrc); 00178 } 00179 00180 /** Get the address or hostname used to connect to Tor */ 00181 QHostAddress 00182 TorSettings::getControlAddress() const 00183 { 00184 QString addr = localValue(SETTING_CONTROL_ADDR).toString(); 00185 return QHostAddress(addr); 00186 } 00187 00188 /** Set the address or hostname used to connect to Tor */ 00189 void 00190 TorSettings::setControlAddress(const QHostAddress &addr) 00191 { 00192 setValue(SETTING_CONTROL_ADDR, addr.toString()); 00193 } 00194 00195 /** Get the control port used to connect to Tor */ 00196 quint16 00197 TorSettings::getControlPort() const 00198 { 00199 return (quint16)value(SETTING_CONTROL_PORT).toInt(); 00200 } 00201 00202 /** Set the control port used to connect to Tor */ 00203 void 00204 TorSettings::setControlPort(quint16 port) 00205 { 00206 setValue(SETTING_CONTROL_PORT, port); 00207 } 00208 00209 /** Returns the plaintext (i.e., not hashed) control password used when 00210 * authenticating to Tor. */ 00211 QString 00212 TorSettings::getControlPassword() const 00213 { 00214 return localValue(SETTING_CONTROL_PASSWORD).toString(); 00215 } 00216 00217 /** Sets the control password used when starting Tor with 00218 * HashedControlPassword to <b>password</b>. */ 00219 void 00220 TorSettings::setControlPassword(const QString &password) 00221 { 00222 setValue(SETTING_CONTROL_PASSWORD, password); 00223 } 00224 00225 /** Returns true if a new, random control password is to be used each time Tor 00226 * is started. */ 00227 bool 00228 TorSettings::useRandomPassword() const 00229 { 00230 return localValue(SETTING_USE_RANDOM_PASSWORD).toBool(); 00231 } 00232 00233 /** Sets whether or not to generate and use a random control password each 00234 * time Tor is started. */ 00235 void 00236 TorSettings::setUseRandomPassword(bool useRandomPassword) 00237 { 00238 setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword); 00239 } 00240 00241 /** Returns the current authentication method used when connecting to Tor. */ 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 /** Sets the authentication method used when starting Tor to <b>method</b>. */ 00265 void 00266 TorSettings::setAuthenticationMethod(AuthenticationMethod method) 00267 { 00268 setValue(SETTING_AUTH_METHOD, toString(method)); 00269 } 00270 00271 /** Returns the current list of ports that will cause Tor to issue a warning 00272 * when the user tries to connect to one of them. */ 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 /** Sets the list of ports that will cause Tor to issue a warning when the 00287 * user tries to connect to one of them. */ 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 /** Returns the current list of ports that will cause Tor to reject the 00299 * connection when the user tries to connect to one of them. */ 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 /** Sets the list of ports that will cause Tor to reject the connection 00314 * when the user tries to connect to one of them. */ 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 /** Returns the string description of the authentication method specified by 00326 * <b>method</b>. The authentication method string is stored in Vidalia's 00327 * configuration file. */ 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 /** Returns the AuthenticationMethod enum value for the string 00341 * description of the authentication method given in <b>authMethod</b>. */ 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 /** Generates a random control password consisting of PASSWORD_LEN characters. */ 00356 QString 00357 TorSettings::randomPassword() 00358 { 00359 return crypto_rand_string(PASSWORD_LEN); 00360 } 00361 00362 /** Returns the hash of <b>password</b> as given by the command "tor 00363 * --hash-password foo". */ 00364 QString 00365 TorSettings::hashPassword(const QString &password) 00366 { 00367 QByteArray salt; 00368 00369 /* Generate an 8 octet salt value. Bail if we fail to generate enough 00370 * random bytes (unlikely). */ 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 /* Generate the salted hash of the specified password. 96 is the one-octet 00379 * RFC 2440 coded count value hardcoded into Tor. Specifies that we should 00380 * hash 64K worth of data. */ 00381 QByteArray key = crypto_secret_to_key(password, salt, 96); 00382 if (key.isNull()) 00383 return QString(); 00384 salt.append(96); /* Append the coded count value to the salt */ 00385 00386 /* Convert the result to hexadecimal and put it in the format Tor wants. */ 00387 return QString("16:%1%2").arg(base16_encode(salt)) 00388 .arg(base16_encode(key)); 00389 } 00390