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