[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r1846: Authenticate based on whatever method is currently configure (in trunk: . src/gui)
Author: edmanm
Date: 2007-08-21 00:34:14 -0400 (Tue, 21 Aug 2007)
New Revision: 1846
Modified:
trunk/
trunk/src/gui/mainwindow.cpp
trunk/src/gui/mainwindow.h
Log:
r2007@adrastea: edmanm | 2007-08-21 00:32:46 -0400
Authenticate based on whatever method is currently configured in vidalia.conf.
This seems to work for me in my common case. I'm sure it explodes gloriously
for you and in many not-so-common cases.
Property changes on: trunk
___________________________________________________________________
svk:merge ticket from /vidalia/local/trunk [r2007] on 54b3572a-7227-0410-958f-53ecd705b71a
Modified: trunk/src/gui/mainwindow.cpp
===================================================================
--- trunk/src/gui/mainwindow.cpp 2007-08-21 04:34:06 UTC (rev 1845)
+++ trunk/src/gui/mainwindow.cpp 2007-08-21 04:34:14 UTC (rev 1846)
@@ -32,7 +32,9 @@
#include <QtGui>
#include <QTimer>
#include <vidalia.h>
+#include <util/file.h>
#include <util/html.h>
+#include <util/string.h>
#include <QSysInfo>
#include "common/vmessagebox.h"
@@ -122,6 +124,7 @@
* notification area. */
createTrayIcon();
/* Start with Tor initially stopped */
+ _status = Unset;
updateTorStatus(Stopped);
/* Create a new TorControl object, used to communicate with and manipulate Tor */
@@ -135,7 +138,10 @@
connect(_torControl, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(_torControl, SIGNAL(connectFailed(QString)),
this, SLOT(connectFailed(QString)));
-
+ connect(_torControl, SIGNAL(authenticated()), this, SLOT(authenticated()));
+ connect(_torControl, SIGNAL(authenticationFailed(QString)),
+ this, SLOT(authenticationFailed(QString)));
+
/* Make sure we shut down when the operating system is restarting */
connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
@@ -204,7 +210,7 @@
}
/* Disconnect all of the TorControl object's signals */
- disconnect(_torControl, 0, 0, 0);
+ QObject::disconnect(_torControl, 0, 0, 0);
/* And then quit for real */
QCoreApplication::quit();
@@ -224,7 +230,7 @@
if (_torControl->isConnected() && settings.isServerEnabled()) {
connect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
if (!stop())
- disconnect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
+ QObject::disconnect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
return;
}
}
@@ -384,6 +390,10 @@
QString statusText, actionText;
QString trayIconFile, statusIconFile;
+ vNotice("Tor status changed from '%1' to '%2'.")
+ .arg(toString(_status)).arg(toString(status));
+ _status = status;
+
if (status == Stopped) {
statusText = tr("Tor is not running");
actionText = tr("Start Tor");
@@ -399,8 +409,8 @@
/* XXX: This might need to be smarter if we ever start connecting other
* slots to these triggered() and clicked() signals. */
- disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
- disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
+ QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
+ QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
connect(_startStopAct, SIGNAL(triggered()), this, SLOT(start()));
connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(start()));
} else if (status == Stopping) {
@@ -412,13 +422,11 @@
}
trayIconFile = IMG_TOR_STOPPING;
statusIconFile = IMG_TOR_STOPPING_48;
- ui.lblNewIdentity->setEnabled(false);
+
ui.lblStartStopTor->setStatusTip(tr("Stop Tor Now"));
- } else if (status == Running) {
+ } else if (status == Started) {
statusText = tr("Tor is running");
actionText = tr("Stop Tor");
- trayIconFile = IMG_TOR_RUNNING;
- statusIconFile = IMG_TOR_RUNNING_48;
_startStopAct->setEnabled(true);
_startStopAct->setText(actionText);
_startStopAct->setIcon(QIcon(IMG_STOP_TOR_16));
@@ -426,16 +434,14 @@
ui.lblStartStopTor->setText(actionText);
ui.lblStartStopTor->setPixmap(QPixmap(IMG_STOP_TOR_48));
ui.lblStartStopTor->setStatusTip(actionText);
- _newIdentityAct->setEnabled(true);
- ui.lblNewIdentity->setEnabled(true);
/* XXX: This might need to be smarter if we ever start connecting other
* slots to these triggered() and clicked() signals. */
- disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
- disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
+ QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
+ QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
connect(_startStopAct, SIGNAL(triggered()), this, SLOT(stop()));
connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(stop()));
- } else { /* status == Starting */
+ } else if (status == Starting) {
statusText = tr("Tor is starting up");
trayIconFile = IMG_TOR_STARTING;
statusIconFile = IMG_TOR_STARTING_48;
@@ -444,19 +450,31 @@
ui.lblStartStopTor->setEnabled(false);
ui.lblStartStopTor->setStatusTip(statusText);
ui.lblStartStopTor->setAnimation(QPixmap(ANIM_PROCESS_WORKING));
+ } else if (status == Connecting) {
+ statusText = tr("Vidalia is connecting to Tor.");
+ } else if (status == Authenticating) {
+ statusText = tr("Vidalia is authenticating to Tor.");
+ } else if (status == Authenticated) {
+ statusText = tr("Tor is running.");
+ trayIconFile = IMG_TOR_RUNNING;
+ statusIconFile = IMG_TOR_RUNNING_48;
}
/* Update the tray icon */
+ if (!trayIconFile.isEmpty()) {
#if defined(USE_QSYSTEMTRAYICON)
- _trayIcon.setIcon(QIcon(trayIconFile));
+ _trayIcon.setIcon(QIcon(trayIconFile));
#else
- _trayIcon.setIcon(trayIconFile);
+ _trayIcon.setIcon(trayIconFile);
#endif
- _trayIcon.setToolTip(statusText);
-
- /* Update the status banner */
- ui.lblTorStatus->setText(statusText);
- ui.lblTorStatusImg->setPixmap(QPixmap(statusIconFile));
+ }
+ /* Update the status banner on the control panel */
+ if (!statusIconFile.isEmpty())
+ ui.lblTorStatusImg->setPixmap(QPixmap(statusIconFile));
+ if (!statusText.isEmpty()) {
+ _trayIcon.setToolTip(statusText);
+ ui.lblTorStatus->setText(statusText);
+ }
}
#if defined(USE_QSYSTEMTRAYICON)
@@ -526,6 +544,8 @@
void
MainWindow::started()
{
+ updateTorStatus(Started);
+
/* Now that Tor is running, we want to know if it dies when we didn't want
* it to. */
_isIntentionalExit = false;
@@ -567,6 +587,13 @@
QString errmsg;
bool rc, delayShutdown = false;
+ /* If Vidalia is not running Tor and we were never authenticated, then
+ * all we can do is simply disconnect the control socket. */
+ if (!_torControl->isVidaliaRunningTor() && _status != Authenticated) {
+ disconnect();
+ return true;
+ }
+
/* If we're running a server, give users the option of terminating
* gracefully so clients have time to find new servers. */
if (server.isServerEnabled() && !_delayedShutdownStarted) {
@@ -647,12 +674,100 @@
void
MainWindow::connected()
{
+ updateTorStatus(Connected);
+ if (!authenticate())
+ stop();
+}
+
+/** Called when Vidalia wants to disconnect from a Tor it did not start. */
+void
+MainWindow::disconnect()
+{
+ updateTorStatus(Disconnecting);
+ _torControl->disconnect();
+}
+
+/** Called when the control socket has been disconnected. */
+void
+MainWindow::disconnected()
+{
+ /*XXX We should warn here if we get disconnected when we didn't intend to */
+ if (_torControl->isVidaliaRunningTor())
+ updateTorStatus(Disconnected);
+ else
+ updateTorStatus(Stopped);
+ _newIdentityAct->setEnabled(false);
+ ui.lblNewIdentity->setEnabled(false);
+}
+
+/** Attempts to authenticate to Tor's control port, depending on the
+ * authentication method specified in TorSettings::getAuthenticationMethod().
+ */
+bool
+MainWindow::authenticate()
+{
+ TorSettings::AuthenticationMethod authMethod;
+ TorSettings settings;
+
+ updateTorStatus(Authenticating);
+
+ authMethod = settings.getAuthenticationMethod();
+ if (authMethod == TorSettings::CookieAuth) {
+ /* Try to load an auth cookie and send it to Tor */
+ QByteArray cookie = loadControlCookie();
+ while (cookie.isEmpty()) {
+ /* Prompt the user to find their control_auth_cookie */
+ int ret = VMessageBox::question(this,
+ tr("Cookie Authentication Required"),
+ p(tr("Tor requires Vidalia to send the contents of an "
+ "authentication cookie, but Vidalia was unable to "
+ "find one."))
+ + p(tr("Would you like to browse for the file "
+ "'control_auth_cookie' yourself?")),
+ VMessageBox::Browse, VMessageBox::Cancel);
+
+ if (ret == VMessageBox::Cancel)
+ return false;
+ QString cookieDir = QFileDialog::getOpenFileName(this,
+ tr("Tor Data Directory"),
+ settings.getDataDirectory(),
+ tr("Tor Control Cookie (control_auth_cookie)"));
+ if (cookieDir.isEmpty())
+ return false;
+ cookieDir = QFileInfo(cookieDir).absolutePath();
+ cookie = loadControlCookie(cookieDir);
+ }
+ return _torControl->authenticate(cookie);
+ } else if (authMethod == TorSettings::PasswordAuth) {
+ /* Get the control password and send it to Tor */
+ QString password = settings.getControlPassword();
+ return _torControl->authenticate(password);
+ }
+ /* No authentication. Send an empty password. */
+ return _torControl->authenticate(QString(""));
+}
+
+/** Called when Vidalia has successfully authenticated to Tor. */
+void
+MainWindow::authenticated()
+{
ServerSettings serverSettings(_torControl);
QString errmsg;
- /* Update our tray status icon */
- updateTorStatus(Running);
+ updateTorStatus(Authenticated);
+ /* Let people click on their beloved "New Identity" button */
+ _newIdentityAct->setEnabled(true);
+ ui.lblNewIdentity->setEnabled(true);
+
+ /* Register for any pertinent asynchronous events. */
+ if (!_torControl->setEvents(&errmsg))
+ VMessageBox::warning(this, tr("Error Registering for Events"),
+ p(tr("Vidalia was unable to register for Tor events. "
+ "Many of Vidalia's features may be unavailable."))
+ + p(errmsg),
+ VMessageBox::Ok);
+
/* If the user changed some of the server's settings while Tor wasn't
* running, then we better let Tor know about the changes now. */
if (serverSettings.changedSinceLastApply()) {
@@ -674,14 +789,57 @@
}
}
-/** Called when the control socket has been disconnected. */
+/** Called when Vidalia fails to authenticate to Tor. The failure reason is
+ * specified in <b>errmsg</b>. */
void
-MainWindow::disconnected()
+MainWindow::authenticationFailed(QString errmsg)
{
- _newIdentityAct->setEnabled(false);
- ui.lblNewIdentity->setEnabled(false);
+ /*XXX This should be smarter. We should parse the error message and give a
+ * more helpful hint about what went wrong. */
+ VMessageBox::warning(this,
+ tr("Error Authenticating to Tor"),
+ p(tr("Vidalia was unable to authenticate to Tor.")) + p(errmsg),
+ VMessageBox::Ok);
+ stop();
}
+/** Searches for and attempts to load the control authentication cookie. This
+ * assumes the cookie is named 'control_auth_cookie'. If <b>cookieDir</b> is
+ * empty, this method will search some default locations depending on the
+ * current platform. */
+QByteArray
+MainWindow::loadControlCookie(QString cookieDir)
+{
+ QFile authCookie;
+ QStringList dirList;
+
+ if (!cookieDir.isEmpty()) {
+ dirList << cookieDir;
+ } else {
+ /* Try some default locations */
+ TorSettings settings;
+ QString dataDir = settings.getDataDirectory();
+ if (!dataDir.isEmpty())
+ dirList << dataDir;
+
+#if defined(Q_WS_WIN)
+ dirList << expand_filename("%APPDATA%\\Tor");
+#else
+ dirList << expand_filename("~/.tor");
+#endif
+ }
+
+ /* Search for the cookie file */
+ foreach (QString dir, dirList) {
+ if (!QFileInfo(dir + "/control_auth_cookie").exists())
+ continue;
+ authCookie.setFileName(dir + "/control_auth_cookie");
+ if (authCookie.open(QIODevice::ReadOnly))
+ return authCookie.readAll();
+ }
+ return QByteArray();
+}
+
/** Creates and displays Vidalia's About dialog. */
void
MainWindow::showAboutDialog()
@@ -767,3 +925,26 @@
}
}
+/** Converts a TorStatus enum value to a string for debug logging purposes. */
+QString
+MainWindow::toString(TorStatus status)
+{
+ switch (status) {
+ /* These strings only appear in debug logs, so they should not be
+ * translated. */
+ case Unset: return "Unset";
+ case Stopping: return "Stopping";
+ case Stopped: return "Stopped";
+ case Starting: return "Starting";
+ case Started: return "Started";
+ case Connecting: return "Connecting";
+ case Connected: return "Connected";
+ case Disconnecting: return "Disconnecting";
+ case Disconnected: return "Disconnected";
+ case Authenticating: return "Authenticating";
+ case Authenticated: return "Authenticated";
+ default: break;
+ }
+ return "Unknown";
+}
+
Modified: trunk/src/gui/mainwindow.h
===================================================================
--- trunk/src/gui/mainwindow.h 2007-08-21 04:34:06 UTC (rev 1845)
+++ trunk/src/gui/mainwindow.h 2007-08-21 04:34:14 UTC (rev 1846)
@@ -77,8 +77,15 @@
void connected();
/** Called when the control connection fails. */
void connectFailed(QString errmsg);
+ /** Called when Vidalia wants to disconnect from a Tor it did not start. */
+ void disconnect();
/** Called when the control socket has been disconnected. */
void disconnected();
+ /** Called when Vidalia has successfully authenticated to Tor. */
+ void authenticated();
+ /** Called when Vidalia fails to authenticate to Tor. The failure reason is
+ * specified in <b>errmsg</b>. */
+ void authenticationFailed(QString errmsg);
/** Re-enables the 'New Identity' button after a delay from the previous time
* 'New Identity' was used. */
void enableNewIdentity();
@@ -106,10 +113,17 @@
private:
enum TorStatus {
- Stopped, /**< Tor is not running. */
- Starting, /**< Tor is in the process of starting. */
- Running, /**< Tor is currently running. */
- Stopping /**< Tor is in the process of shutting down. */
+ Unset, /**< Tor's status has not yet been set. */
+ Stopping, /**< Tor is in the process of shutting down. */
+ Stopped, /**< Tor is not running. */
+ Starting, /**< Tor is in the process of starting. */
+ Started, /**< Tor is currently running. */
+ Connecting, /**< Vidalia is connecting to Tor. */
+ Connected, /**< Vidalia is connected to Tor. */
+ Disconnecting, /**< Vidalia is disconnecting from Tor. */
+ Disconnected, /**< Vidalia is disconnected from Tor. */
+ Authenticating, /**< Vidalia is authenticating to Tor. */
+ Authenticated /**< Vidalia has authenticated to Tor. */
};
/** Create the actions on the tray menu or menubar */
void createActions();
@@ -124,8 +138,19 @@
bool isTrayIconSupported();
/** Updates the UI to reflect Tor's current <b>status</b>. */
void updateTorStatus(TorStatus status);
+ /** Converts a TorStatus enum value to a string for debug logging purposes. */
+ QString toString(TorStatus status);
+ /** Authenticates Vidalia to Tor's control port. */
+ bool authenticate();
+ /** Searches for and attempts to load the control authentication cookie.
+ * This assumes the cookie is named 'control_auth_cookie'. If
+ * <b>cookieDir</b> is empty, this method will search some default locations
+ * depending on the current platform. */
+ QByteArray loadControlCookie(QString cookieDir = QString());
- /* Used to determine if the Tor process exiting was intentional or not */
+ /** The current status of Tor. */
+ TorStatus _status;
+ /** Used to determine if the Tor process exiting was intentional or not */
bool _isIntentionalExit;
/** Tracks whether we started a delayed server shutdown. */
bool _delayedShutdownStarted;