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 2362 2008-02-29 04:30:11Z edmanm $
00014 ** \brief Settings used for starting and running Tor
00015 */
00016 
00017 #include <QDir>
00018 #include <QProcess>
00019 #include <crypto.h>
00020 #include <vidalia.h>
00021 
00022 #if defined(Q_OS_WIN32)
00023 #include <QFileInfo>
00024 #include <win32.h>
00025 #endif
00026 
00027 #include "torsettings.h"
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_AUTH_TOKEN          "AuthToken"
00035 #define SETTING_TOR_USER            "User"
00036 #define SETTING_TOR_GROUP           "Group"
00037 #define SETTING_DATA_DIRECTORY      "DataDirectory"
00038 #define SETTING_AUTH_METHOD         "AuthenticationMethod"
00039 #define SETTING_CONTROL_PASSWORD    "ControlPassword"
00040 #define SETTING_USE_RANDOM_PASSWORD "UseRandomPassword"
00041 
00042 /** Default to using hashed password authentication */
00043 #define DEFAULT_AUTH_METHOD     PasswordAuth
00044 
00045 /* Arguments we can pass to Tor on the command-line */
00046 #define TOR_ARG_CONTROL_PORT    "ControlPort"
00047 #define TOR_ARG_TORRC           "-f"
00048 #define TOR_ARG_USER            "User"
00049 #define TOR_ARG_GROUP           "Group"
00050 #define TOR_ARG_DATA_DIRECTORY  "DataDirectory"
00051 #define TOR_ARG_HASHED_PASSWORD "HashedControlPassword"
00052 #define TOR_ARG_COOKIE_AUTH     "CookieAuthentication"
00053 
00054 /** Generate random control passwords of 16 characters */
00055 #define PASSWORD_LEN    16
00056 
00057 
00058 /** Default constructor */
00059 TorSettings::TorSettings(TorControl *torControl)
00060 : AbstractTorSettings("Tor", torControl)
00061 {
00062 #if defined(Q_OS_WIN32)
00063   QString programFiles = win32_program_files_folder();
00064   if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists())
00065     setDefault(SETTING_TOR_EXECUTABLE,
00066                programFiles + "\\Vidalia Bundle\\Tor\\tor.exe");
00067   else
00068     setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe");
00069 #else
00070   setDefault(SETTING_TOR_EXECUTABLE, "/usr/bin/tor");
00071 #endif
00072 
00073   setDefault(SETTING_TORRC,         "/etc/tor/torrc");
00074   setDefault(SETTING_CONTROL_ADDR,  "127.0.0.1");
00075   setDefault(SETTING_CONTROL_PORT,  9051);
00076   setDefault(SETTING_AUTH_METHOD,   toString(DEFAULT_AUTH_METHOD));
00077   setDefault(SETTING_TOR_USER,      "toruser");
00078   setDefault(SETTING_TOR_GROUP,     "toruser");
00079   setDefault(SETTING_DATA_DIRECTORY, "/var/lib/tor");
00080   setDefault(SETTING_CONTROL_PASSWORD, "");
00081   setDefault(SETTING_USE_RANDOM_PASSWORD, true);
00082 }
00083 
00084 /** Applies any changes to Tor's control port or authentication settings. */
00085 bool
00086 TorSettings::apply(QString *errmsg)
00087 {
00088   QHash<QString, QString> conf;
00089   QString hashedPassword;
00090 
00091   conf.insert(SETTING_CONTROL_PORT,
00092               localValue(SETTING_CONTROL_PORT).toString());
00093   
00094   AuthenticationMethod authMethod = 
00095     toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00096   switch (authMethod) {
00097     case CookieAuth:
00098       conf.insert(TOR_ARG_COOKIE_AUTH,    "1");
00099       conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00100       break;
00101     case PasswordAuth:
00102       hashedPassword = useRandomPassword() 
00103                           ? hashPassword(randomPassword())
00104                           : hashPassword(getControlPassword());
00105       if (hashedPassword.isEmpty()) {
00106         if (errmsg)
00107           *errmsg =  tr("Failed to hash the control password.");
00108         return false;
00109       }
00110       conf.insert(TOR_ARG_COOKIE_AUTH,    "0");
00111       conf.insert(TOR_ARG_HASHED_PASSWORD, hashedPassword);
00112       break;
00113     default:
00114       conf.insert(TOR_ARG_COOKIE_AUTH,    "0");
00115       conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00116   }
00117   return torControl()->setConf(conf, errmsg);
00118 }
00119 
00120 /** Gets the location of Tor's data directory. */
00121 QString
00122 TorSettings::getDataDirectory() const
00123 {
00124   return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString());
00125 }
00126 
00127 /** Sets the location to use as Tor's data directory. */
00128 void
00129 TorSettings::setDataDirectory(const QString &dataDirectory)
00130 {
00131   setValue(SETTING_DATA_DIRECTORY, dataDirectory);
00132 }
00133 
00134 /** Returns a fully-qualified path to Tor's executable, including the
00135  * executable name. */
00136 QString
00137 TorSettings::getExecutable() const
00138 {
00139   QString tor = localValue(SETTING_TOR_EXECUTABLE).toString();
00140   if (tor.isEmpty()) /* Don't let the Tor executable name be empty */
00141     tor = defaultValue(SETTING_TOR_EXECUTABLE).toString();
00142   return QDir::convertSeparators(tor);
00143 }
00144 
00145 /** Sets the location and name of Tor's executable to the given string. */
00146 void
00147 TorSettings::setExecutable(const QString &torExecutable)
00148 {
00149   setValue(SETTING_TOR_EXECUTABLE, torExecutable);
00150 }
00151 
00152 /** Returns the torrc that will be used when starting Tor. */
00153 QString
00154 TorSettings::getTorrc() const
00155 {
00156   QString torrc;
00157   TorControl *tc = torControl();
00158   if (tc && tc->isConnected() && tc->getInfo("config-file", torrc))
00159     return QDir::convertSeparators(torrc);
00160   return QDir::convertSeparators(localValue(SETTING_TORRC).toString());
00161 }
00162 
00163 /** Sets the torrc that will be used when starting Tor.
00164  * \param torrc The torrc to use. 
00165  */
00166 void
00167 TorSettings::setTorrc(const QString &torrc)
00168 {
00169   setValue(SETTING_TORRC, torrc);
00170 }
00171 
00172 /** Returns the user used when running Tor. The user is specified as an
00173  * argument to Tor, which will setuid to this user. */
00174 QString
00175 TorSettings::getUser() const
00176 {
00177   return value(SETTING_TOR_USER).toString();
00178 }
00179 
00180 /** Sets the user used when running Tor. The user is specified as an argument
00181  * to Tor, which will setuid to this user. */
00182 void
00183 TorSettings::setUser(const QString &user)
00184 {
00185   setValue(SETTING_TOR_USER, user);
00186 }
00187 
00188 /** Returns the group used when running Tor. The group is specified as an
00189  * argument to Tor, which will setgid to this group. */
00190 QString
00191 TorSettings::getGroup() const
00192 {
00193   return value(SETTING_TOR_GROUP).toString();
00194 }
00195 
00196 /** Sets the group used when running Tor. The group is specified as an
00197  * argument to Tor, which will setgid to this group. */
00198 void
00199 TorSettings::setGroup(const QString &group)
00200 {
00201   setValue(SETTING_TOR_GROUP, group);
00202 }
00203 
00204 /** Get the address or hostname used to connect to Tor */
00205 QHostAddress
00206 TorSettings::getControlAddress() const
00207 {
00208   QString addr = localValue(SETTING_CONTROL_ADDR).toString();
00209   return QHostAddress(addr);
00210 }
00211 
00212 /** Set the address or hostname used to connect to Tor */
00213 void
00214 TorSettings::setControlAddress(const QHostAddress &addr)
00215 {
00216   setValue(SETTING_CONTROL_ADDR, addr.toString());
00217 }
00218 
00219 /** Get the control port used to connect to Tor */
00220 quint16
00221 TorSettings::getControlPort() const
00222 {
00223   return (quint16)value(SETTING_CONTROL_PORT).toInt();
00224 }
00225 
00226 /** Set the control port used to connect to Tor */
00227 void
00228 TorSettings::setControlPort(quint16 port)
00229 {
00230   setValue(SETTING_CONTROL_PORT, port);
00231 }
00232 
00233 /** Returns the plaintext (i.e., not hashed) control password used when
00234  * authenticating to Tor. */
00235 QString
00236 TorSettings::getControlPassword() const
00237 {
00238   return localValue(SETTING_CONTROL_PASSWORD).toString();
00239 }
00240 
00241 /** Sets the control password used when starting Tor with
00242  * HashedControlPassword to <b>password</b>. */
00243 void
00244 TorSettings::setControlPassword(const QString &password)
00245 {
00246   setValue(SETTING_CONTROL_PASSWORD, password);
00247 }
00248 
00249 /** Returns true if a new, random control password is to be used each time Tor
00250  * is started. */
00251 bool
00252 TorSettings::useRandomPassword() const
00253 {
00254   return localValue(SETTING_USE_RANDOM_PASSWORD).toBool();
00255 }
00256 
00257 /** Sets whether or not to generate and use a random control password each
00258  * time Tor is started. */
00259 void
00260 TorSettings::setUseRandomPassword(bool useRandomPassword)
00261 {
00262   setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword);
00263 }
00264 
00265 /** Returns the current authentication method used when connecting to Tor. */
00266 TorSettings::AuthenticationMethod
00267 TorSettings::getAuthenticationMethod() const
00268 {
00269   AuthenticationMethod type = UnknownAuth;
00270   TorControl *tc = torControl();
00271 
00272   if (tc && tc->isConnected()) {
00273     QHash<QString,QString> conf;
00274     conf.insert(TOR_ARG_COOKIE_AUTH, "");
00275     conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00276     if (tc->getConf(conf)) {
00277       if (conf.value(TOR_ARG_COOKIE_AUTH) == "1")
00278         type = CookieAuth;
00279       else if (!conf.value(TOR_ARG_HASHED_PASSWORD).isEmpty())
00280         type = PasswordAuth;
00281     }
00282   }
00283   if (type == UnknownAuth)
00284     type = toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00285   return (type == UnknownAuth ? DEFAULT_AUTH_METHOD : type);
00286 }
00287 
00288 /** Sets the authentication method used when starting Tor to <b>method</b>. */
00289 void
00290 TorSettings::setAuthenticationMethod(AuthenticationMethod method)
00291 {
00292   setValue(SETTING_AUTH_METHOD, toString(method));
00293 }
00294 
00295 /** Returns the string description of the authentication method specified by
00296  * <b>method</b>. The authentication method string is stored in Vidalia's
00297  * configuration file. */
00298 QString
00299 TorSettings::toString(AuthenticationMethod method) const
00300 {
00301   switch (method) {
00302     case NullAuth:  return "none";
00303     case PasswordAuth:  return "password";
00304     case CookieAuth:  return "cookie";
00305     default: break;
00306   }
00307   return "unknown";
00308 }
00309 
00310 /** Returns the AuthenticationMethod enum value for the string
00311  * description of the authentication method given in <b>authMethod</b>. */
00312 TorSettings::AuthenticationMethod
00313 TorSettings::toAuthenticationMethod(const QString &authMethod) const
00314 { 
00315   QString str = authMethod.toLower();
00316   if (str == toString(NullAuth))
00317     return NullAuth;
00318   else if (str == toString(PasswordAuth))
00319     return PasswordAuth;
00320   else if (str == toString(CookieAuth))
00321     return CookieAuth;
00322   return UnknownAuth;
00323 }
00324 
00325 /** Generates a random control password consisting of PASSWORD_LEN characters. */
00326 QString
00327 TorSettings::randomPassword()
00328 {
00329   return crypto_rand_string(PASSWORD_LEN);
00330 }
00331 
00332 /** Returns the hash of <b>password</b> as given by the command "tor
00333  * --hash-password foo". */
00334 QString
00335 TorSettings::hashPassword(const QString &password)
00336 {
00337   TorSettings settings;
00338   QProcess tor;
00339   QString dataDirectory, line;
00340   QStringList args;
00341 
00342   /* Tor writes its state file even if all we're doing is --hash-password. So
00343    * if the user has configured a non-default data directory, then include
00344    * that in the list of command line arguments. */
00345   dataDirectory = settings.getDataDirectory();
00346   if (!dataDirectory.isEmpty())
00347     args << "DataDirectory" << dataDirectory;
00348   args << "--hash-password" << password;
00349   
00350   /* Run Tor, tell it to hash the given password, and then wait for it to
00351    * finish. */
00352   tor.start(settings.getExecutable(), args);
00353   if (!tor.waitForStarted() || !tor.waitForFinished())
00354     return QString();
00355 
00356   /* The hashed password will (hopefully) be the line that starts with "16:" */
00357   while (tor.canReadLine()) {
00358     line = tor.readLine();
00359     if (line.startsWith("16:"))
00360       return line.trimmed();
00361   }
00362   return QString();
00363 }
00364 

Generated on Sat Aug 16 17:38:36 2008 for Vidalia by  doxygen 1.5.6