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.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 
Generated on Mon Aug 30 22:58:55 2010 for Vidalia by  doxygen 1.6.3