torsettings.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file torsettings.cpp
00024  * \version $Id: torsettings.cpp 1880 2007-08-26 04:14:26Z edmanm $
00025  * \brief Settings used for starting and running Tor
00026  */
00027 
00028 #include <QDir>
00029 #include <QProcess>
00030 #include <util/file.h>
00031 #include <util/crypto.h>
00032 #include <vidalia.h>
00033 
00034 #include "torsettings.h"
00035 
00036 /* Tor Settings */
00037 #define SETTING_TOR_EXECUTABLE  "Tor/TorExecutable"
00038 #define SETTING_TORRC           "Tor/Torrc"
00039 #define SETTING_CONTROL_ADDR    "Tor/ControlAddr"
00040 #define SETTING_CONTROL_PORT    "Tor/ControlPort"
00041 #define SETTING_AUTH_TOKEN      "Tor/AuthToken"
00042 #define SETTING_TOR_USER        "Tor/User"
00043 #define SETTING_TOR_GROUP       "Tor/Group"
00044 #define SETTING_DATA_DIRECTORY  "Tor/DataDirectory"
00045 #define SETTING_AUTH_METHOD     "Tor/AuthenticationMethod"
00046 #define SETTING_CONTROL_PASSWORD    "Tor/ControlPassword"
00047 #define SETTING_USE_RANDOM_PASSWORD "Tor/UseRandomPassword"
00048 
00049 /* On win32, we need to add the .exe onto Tor's filename */
00050 #if defined(Q_OS_WIN32)
00051 #include <QFileInfo>
00052 #include <util/win32.h>
00053 #endif
00054 
00055 /** Default to using hashed password authentication */
00056 #define DEFAULT_AUTH_METHOD     PasswordAuth
00057 
00058 /* Arguments we can pass to Tor on the command-line */
00059 #define TOR_ARG_CONTROL_PORT    "ControlPort"
00060 #define TOR_ARG_TORRC           "-f"
00061 #define TOR_ARG_USER            "User"
00062 #define TOR_ARG_GROUP           "Group"
00063 #define TOR_ARG_DATA_DIRECTORY  "DataDirectory"
00064 #define TOR_ARG_HASHED_PASSWORD "HashedControlPassword"
00065 #define TOR_ARG_COOKIE_AUTH     "CookieAuthentication"
00066 
00067 /** Generate random control passwords of 16 characters */
00068 #define PASSWORD_LEN    16
00069 
00070 
00071 /** Default constructor */
00072 TorSettings::TorSettings()
00073 {
00074 #if defined(Q_OS_WIN32)
00075   QString programFiles = win32_program_files_folder();
00076   if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists())
00077     setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Vidalia Bundle\\Tor\\tor.exe");
00078   else
00079     setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe");
00080 #else
00081   setDefault(SETTING_TOR_EXECUTABLE, "/usr/bin/tor");
00082 #endif
00083 
00084   setDefault(SETTING_TORRC,         "/etc/tor/torrc");
00085   setDefault(SETTING_CONTROL_ADDR,  "127.0.0.1");
00086   setDefault(SETTING_CONTROL_PORT,  9051);
00087   setDefault(SETTING_AUTH_METHOD,   toString(DEFAULT_AUTH_METHOD));
00088   setDefault(SETTING_TOR_USER,      "toruser");
00089   setDefault(SETTING_TOR_GROUP,     "toruser");
00090   setDefault(SETTING_DATA_DIRECTORY, "/var/lib/tor");
00091   setDefault(SETTING_CONTROL_PASSWORD, "");
00092   setDefault(SETTING_USE_RANDOM_PASSWORD, true);
00093 }
00094 
00095 /** Gets the location of Tor's data directory. */
00096 QString
00097 TorSettings::getDataDirectory()
00098 {
00099   return value(SETTING_DATA_DIRECTORY).toString();  
00100 }
00101 
00102 /** Sets the location to use as Tor's data directory. */
00103 void
00104 TorSettings::setDataDirectory(QString dataDirectory)
00105 {
00106   setValue(SETTING_DATA_DIRECTORY, dataDirectory);
00107 }
00108 
00109 /** Returns a fully-qualified path to Tor's executable, including the
00110  * executable name. */
00111 QString
00112 TorSettings::getExecutable()
00113 {
00114   return QDir::convertSeparators(value(SETTING_TOR_EXECUTABLE).toString());
00115 }
00116 
00117 /** Sets the location and name of Tor's executable to the given string. */
00118 void
00119 TorSettings::setExecutable(QString torExecutable)
00120 {
00121   setValue(SETTING_TOR_EXECUTABLE, torExecutable);
00122 }
00123 
00124 /** Returns a formatted QString of all currently set command-line arguments.
00125  * If an argument's value contains a space, then it will be wrapped in quotes.
00126  * */
00127 QStringList
00128 TorSettings::getArguments()
00129 {
00130   QStringList args;
00131 
00132   /* Add the torrc argument (if specified) */
00133   QString torrc = getTorrc();
00134   if (!torrc.isEmpty())
00135     args << TOR_ARG_TORRC << expand_filename(torrc);
00136   
00137   /* Specify the location to use for Tor's data directory, if different from
00138    * the default. */
00139   QString dataDirectory = getDataDirectory();
00140   if (!dataDirectory.isEmpty())
00141     args << TOR_ARG_DATA_DIRECTORY << expand_filename(dataDirectory);
00142   
00143   /* Add the ControlPort value */
00144   quint16 controlPort = getControlPort();
00145   if (controlPort)
00146     args << TOR_ARG_CONTROL_PORT << QString::number(controlPort);
00147 
00148   /* Add the control port authentication argument */
00149   AuthenticationMethod authMethod = getAuthenticationMethod();
00150   if (authMethod == PasswordAuth) {
00151     if (useRandomPassword())
00152       setControlPassword(generateRandomPassword());
00153     
00154     QString password = getControlPassword();
00155     args << TOR_ARG_HASHED_PASSWORD << hashPassword(password);
00156     args << TOR_ARG_COOKIE_AUTH << "0";
00157   } else if (authMethod == CookieAuth) {
00158     args << TOR_ARG_COOKIE_AUTH << "1";
00159     args << TOR_ARG_HASHED_PASSWORD << "";
00160   } else {
00161     args << TOR_ARG_COOKIE_AUTH << "0";
00162     args << TOR_ARG_HASHED_PASSWORD << "";
00163   }
00164   
00165   /* Add the User argument (if specified) */
00166   QString user = getUser();
00167   if (!user.isEmpty())
00168     args << TOR_ARG_USER << user;
00169     
00170   /* Add the Group argument (if specified) */
00171   QString group = getGroup();
00172   if (!group.isEmpty())
00173     args << TOR_ARG_GROUP << group;
00174   
00175   return args;
00176 }
00177 
00178 /** Returns the torrc that will be used when starting Tor. */
00179 QString
00180 TorSettings::getTorrc()
00181 {
00182   return QDir::convertSeparators(value(SETTING_TORRC).toString());
00183 }
00184 
00185 /** Sets the torrc that will be used when starting Tor.
00186  * \param torrc The torrc to use. 
00187  */
00188 void
00189 TorSettings::setTorrc(QString torrc)
00190 {
00191   setValue(SETTING_TORRC, torrc);
00192 }
00193 
00194 /** Returns the user used when running Tor. The user is specified as an
00195  * argument to Tor, which will setuid to this user. */
00196 QString
00197 TorSettings::getUser()
00198 {
00199   return value(SETTING_TOR_USER).toString();
00200 }
00201 
00202 /** Sets the user used when running Tor. The user is specified as an argument
00203  * to Tor, which will setuid to this user. */
00204 void
00205 TorSettings::setUser(QString user)
00206 {
00207   setValue(SETTING_TOR_USER, user);
00208 }
00209 
00210 /** Returns the group used when running Tor. The group is specified as an
00211  * argument to Tor, which will setgid to this group. */
00212 QString
00213 TorSettings::getGroup()
00214 {
00215   return value(SETTING_TOR_GROUP).toString();
00216 }
00217 
00218 /** Sets the group used when running Tor. The group is specified as an
00219  * argument to Tor, which will setgid to this group. */
00220 void
00221 TorSettings::setGroup(QString group)
00222 {
00223   setValue(SETTING_TOR_GROUP, group);
00224 }
00225 
00226 /** Get the address or hostname used to connect to Tor */
00227 QHostAddress
00228 TorSettings::getControlAddress()
00229 {
00230   QString addr = value(SETTING_CONTROL_ADDR).toString();
00231   return QHostAddress(addr);
00232 }
00233 
00234 /** Set the address or hostname used to connect to Tor */
00235 void
00236 TorSettings::setControlAddress(QHostAddress addr)
00237 {
00238   setValue(SETTING_CONTROL_ADDR, addr.toString());
00239 }
00240 
00241 /** Get the control port used to connect to Tor */
00242 quint16
00243 TorSettings::getControlPort()
00244 {
00245   return (quint16)value(SETTING_CONTROL_PORT).toInt();
00246 }
00247 
00248 /** Set the control port used to connect to Tor */
00249 void
00250 TorSettings::setControlPort(quint16 port)
00251 {
00252   setValue(SETTING_CONTROL_PORT, port);
00253 }
00254 
00255 /** Returns the plaintext (i.e., not hashed) control password used when
00256  * authenticating to Tor. */
00257 QString
00258 TorSettings::getControlPassword()
00259 {
00260   return value(SETTING_CONTROL_PASSWORD).toString();
00261 }
00262 
00263 /** Sets the control password used when starting Tor with
00264  * HashedControlPassword to <b>password</b>. */
00265 void
00266 TorSettings::setControlPassword(QString password)
00267 {
00268   setValue(SETTING_CONTROL_PASSWORD, password);
00269 }
00270 
00271 /** Returns true if a new, random control password is to be used each time Tor
00272  * is started. */
00273 bool
00274 TorSettings::useRandomPassword()
00275 {
00276   return value(SETTING_USE_RANDOM_PASSWORD).toBool();
00277 }
00278 
00279 /** Sets whether or not to generate and use a random control password each
00280  * time Tor is started. */
00281 void
00282 TorSettings::setUseRandomPassword(bool useRandomPassword)
00283 {
00284   setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword);
00285 }
00286 
00287 /** Returns the current authentication method used when connecting to Tor. */
00288 TorSettings::AuthenticationMethod
00289 TorSettings::getAuthenticationMethod()
00290 {
00291   AuthenticationMethod type;
00292   QString str = value(SETTING_AUTH_METHOD).toString();
00293   if (str == toString(NullAuth))
00294     type = NullAuth;
00295   else if (str == toString(PasswordAuth))
00296     type = PasswordAuth;
00297   else if (str == toString(CookieAuth))
00298     type = CookieAuth;
00299   else
00300     type = UnknownAuth;
00301   return type;
00302 }
00303 
00304 /** Sets the authentication method used when starting Tor to <b>method</b>. */
00305 void
00306 TorSettings::setAuthenticationMethod(AuthenticationMethod method)
00307 {
00308   setValue(SETTING_AUTH_METHOD, toString(method));
00309 }
00310 
00311 /** Returns the string description of the authentication method specified by
00312  * <b>method</b>. The authentication method string is stored in Vidalia's
00313  * configuration file. */
00314 QString
00315 TorSettings::toString(AuthenticationMethod method)
00316 {
00317   switch (method) {
00318     case NullAuth:  return "none";
00319     case PasswordAuth:  return "password";
00320     case CookieAuth:  return "cookie";
00321     default: break;
00322   }
00323   return "unknown";
00324 }
00325 
00326 /** Generates a random control password consisting of PASSWORD_LEN characters. */
00327 QString
00328 TorSettings::generateRandomPassword()
00329 {
00330   return crypto_rand_string(PASSWORD_LEN);
00331 }
00332 
00333 /** Returns the hash of <b>password</b> as given by the command "tor
00334  * --hash-password foo". */
00335 QString
00336 TorSettings::hashPassword(QString password)
00337 {
00338   QProcess tor;
00339   QString line;
00340  
00341   /* Run Tor, tell it to hash the given password, and then wait for it to
00342    * finish. */
00343   tor.start(getExecutable(),
00344             QStringList() << "--hash-password" << password);
00345   if (!tor.waitForStarted() || !tor.waitForFinished())
00346     return QString();
00347 
00348   /* The hashed password will (hopefully) be the line that starts with "16:" */
00349   while (tor.canReadLine()) {
00350     line = tor.readLine();
00351     if (line.startsWith("16:"))
00352       return line.trimmed();
00353   }
00354   return QString();
00355 }
00356 

Generated on Wed Sep 5 15:49:28 2007 for Vidalia by  doxygen 1.5.3