torsettings.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00043 #define DEFAULT_AUTH_METHOD PasswordAuth
00044
00045
00046 #define TOR_ARG_CONTROL_PORT "ControlPort"
00047 #define TOR_ARG_TORRC "-f"
00048 #define TOR_ARG_DATA_DIRECTORY "DataDirectory"
00049 #define TOR_ARG_HASHED_PASSWORD "HashedControlPassword"
00050 #define TOR_ARG_COOKIE_AUTH "CookieAuthentication"
00051
00052
00053 #define PASSWORD_LEN 16
00054
00055
00056
00057 TorSettings::TorSettings(TorControl *torControl)
00058 : AbstractTorSettings("Tor", torControl)
00059 {
00060 #if defined(Q_OS_WIN32)
00061 QString programFiles = win32_program_files_folder();
00062 if (QFileInfo(programFiles + "\\Vidalia Bundle\\Tor\\tor.exe").exists())
00063 setDefault(SETTING_TOR_EXECUTABLE,
00064 programFiles + "\\Vidalia Bundle\\Tor\\tor.exe");
00065 else
00066 setDefault(SETTING_TOR_EXECUTABLE, programFiles + "\\Tor\\tor.exe");
00067 #else
00068 setDefault(SETTING_TOR_EXECUTABLE, "/usr/bin/tor");
00069 #endif
00070
00071 setDefault(SETTING_TORRC, "/etc/tor/torrc");
00072 setDefault(SETTING_CONTROL_ADDR, "127.0.0.1");
00073 setDefault(SETTING_CONTROL_PORT, 9051);
00074 setDefault(SETTING_AUTH_METHOD, toString(DEFAULT_AUTH_METHOD));
00075 setDefault(SETTING_DATA_DIRECTORY, "/var/lib/tor");
00076 setDefault(SETTING_CONTROL_PASSWORD, "");
00077 setDefault(SETTING_USE_RANDOM_PASSWORD, true);
00078 }
00079
00080
00081 bool
00082 TorSettings::apply(QString *errmsg)
00083 {
00084 QHash<QString, QString> conf;
00085 QString hashedPassword;
00086
00087 conf.insert(SETTING_CONTROL_PORT,
00088 localValue(SETTING_CONTROL_PORT).toString());
00089
00090 AuthenticationMethod authMethod =
00091 toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00092 switch (authMethod) {
00093 case CookieAuth:
00094 conf.insert(TOR_ARG_COOKIE_AUTH, "1");
00095 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00096 break;
00097 case PasswordAuth:
00098 hashedPassword = useRandomPassword()
00099 ? hashPassword(randomPassword())
00100 : hashPassword(getControlPassword());
00101 if (hashedPassword.isEmpty()) {
00102 if (errmsg)
00103 *errmsg = tr("Failed to hash the control password.");
00104 return false;
00105 }
00106 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
00107 conf.insert(TOR_ARG_HASHED_PASSWORD, hashedPassword);
00108 break;
00109 default:
00110 conf.insert(TOR_ARG_COOKIE_AUTH, "0");
00111 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00112 }
00113 return torControl()->setConf(conf, errmsg);
00114 }
00115
00116
00117 QString
00118 TorSettings::getDataDirectory() const
00119 {
00120 return QDir::convertSeparators(value(SETTING_DATA_DIRECTORY).toString());
00121 }
00122
00123
00124 void
00125 TorSettings::setDataDirectory(const QString &dataDirectory)
00126 {
00127 setValue(SETTING_DATA_DIRECTORY, dataDirectory);
00128 }
00129
00130
00131
00132 QString
00133 TorSettings::getExecutable() const
00134 {
00135 QString tor = localValue(SETTING_TOR_EXECUTABLE).toString();
00136 if (tor.isEmpty())
00137 tor = defaultValue(SETTING_TOR_EXECUTABLE).toString();
00138 return QDir::convertSeparators(tor);
00139 }
00140
00141
00142 void
00143 TorSettings::setExecutable(const QString &torExecutable)
00144 {
00145 setValue(SETTING_TOR_EXECUTABLE, torExecutable);
00146 }
00147
00148
00149 QString
00150 TorSettings::getTorrc() const
00151 {
00152 QString torrc;
00153 TorControl *tc = torControl();
00154 if (tc && tc->isConnected() && tc->getInfo("config-file", torrc))
00155 return QDir::convertSeparators(torrc);
00156 return QDir::convertSeparators(localValue(SETTING_TORRC).toString());
00157 }
00158
00159
00160
00161
00162 void
00163 TorSettings::setTorrc(const QString &torrc)
00164 {
00165 setValue(SETTING_TORRC, torrc);
00166 }
00167
00168
00169 QHostAddress
00170 TorSettings::getControlAddress() const
00171 {
00172 QString addr = localValue(SETTING_CONTROL_ADDR).toString();
00173 return QHostAddress(addr);
00174 }
00175
00176
00177 void
00178 TorSettings::setControlAddress(const QHostAddress &addr)
00179 {
00180 setValue(SETTING_CONTROL_ADDR, addr.toString());
00181 }
00182
00183
00184 quint16
00185 TorSettings::getControlPort() const
00186 {
00187 return (quint16)value(SETTING_CONTROL_PORT).toInt();
00188 }
00189
00190
00191 void
00192 TorSettings::setControlPort(quint16 port)
00193 {
00194 setValue(SETTING_CONTROL_PORT, port);
00195 }
00196
00197
00198
00199 QString
00200 TorSettings::getControlPassword() const
00201 {
00202 return localValue(SETTING_CONTROL_PASSWORD).toString();
00203 }
00204
00205
00206
00207 void
00208 TorSettings::setControlPassword(const QString &password)
00209 {
00210 setValue(SETTING_CONTROL_PASSWORD, password);
00211 }
00212
00213
00214
00215 bool
00216 TorSettings::useRandomPassword() const
00217 {
00218 return localValue(SETTING_USE_RANDOM_PASSWORD).toBool();
00219 }
00220
00221
00222
00223 void
00224 TorSettings::setUseRandomPassword(bool useRandomPassword)
00225 {
00226 setValue(SETTING_USE_RANDOM_PASSWORD, useRandomPassword);
00227 }
00228
00229
00230 TorSettings::AuthenticationMethod
00231 TorSettings::getAuthenticationMethod() const
00232 {
00233 AuthenticationMethod type = UnknownAuth;
00234 TorControl *tc = torControl();
00235
00236 if (tc && tc->isConnected()) {
00237 QHash<QString,QString> conf;
00238 conf.insert(TOR_ARG_COOKIE_AUTH, "");
00239 conf.insert(TOR_ARG_HASHED_PASSWORD, "");
00240 if (tc->getConf(conf)) {
00241 if (conf.value(TOR_ARG_COOKIE_AUTH) == "1")
00242 type = CookieAuth;
00243 else if (!conf.value(TOR_ARG_HASHED_PASSWORD).isEmpty())
00244 type = PasswordAuth;
00245 }
00246 }
00247 if (type == UnknownAuth)
00248 type = toAuthenticationMethod(localValue(SETTING_AUTH_METHOD).toString());
00249 return (type == UnknownAuth ? DEFAULT_AUTH_METHOD : type);
00250 }
00251
00252
00253 void
00254 TorSettings::setAuthenticationMethod(AuthenticationMethod method)
00255 {
00256 setValue(SETTING_AUTH_METHOD, toString(method));
00257 }
00258
00259
00260
00261
00262 QString
00263 TorSettings::toString(AuthenticationMethod method) const
00264 {
00265 switch (method) {
00266 case NullAuth: return "none";
00267 case PasswordAuth: return "password";
00268 case CookieAuth: return "cookie";
00269 default: break;
00270 }
00271 return "unknown";
00272 }
00273
00274
00275
00276 TorSettings::AuthenticationMethod
00277 TorSettings::toAuthenticationMethod(const QString &authMethod) const
00278 {
00279 QString str = authMethod.toLower();
00280 if (str == toString(NullAuth))
00281 return NullAuth;
00282 else if (str == toString(PasswordAuth))
00283 return PasswordAuth;
00284 else if (str == toString(CookieAuth))
00285 return CookieAuth;
00286 return UnknownAuth;
00287 }
00288
00289
00290 QString
00291 TorSettings::randomPassword()
00292 {
00293 return crypto_rand_string(PASSWORD_LEN);
00294 }
00295
00296
00297
00298 QString
00299 TorSettings::hashPassword(const QString &password)
00300 {
00301 TorSettings settings;
00302 QProcess tor;
00303 QString dataDirectory, line;
00304 QStringList args;
00305
00306 QStringList env = QProcess::systemEnvironment();
00307 #if !defined(Q_OS_WIN32)
00308
00309 for (int i = 0; i < env.size(); i++) {
00310 QString envVar = env.at(i);
00311 if (envVar.startsWith("PATH="))
00312 env.replace(i, envVar += ":/usr/sbin");
00313 }
00314 #endif
00315 tor.setEnvironment(env);
00316
00317
00318
00319
00320 dataDirectory = settings.getDataDirectory();
00321 if (!dataDirectory.isEmpty())
00322 args << "DataDirectory" << dataDirectory;
00323 args << "--hash-password" << password;
00324
00325
00326
00327 tor.start(settings.getExecutable(), args);
00328 if (!tor.waitForStarted() || !tor.waitForFinished())
00329 return QString();
00330
00331
00332 while (tor.canReadLine()) {
00333 line = tor.readLine();
00334 if (line.startsWith("16:"))
00335 return line.trimmed();
00336 }
00337 return QString();
00338 }
00339