[tor-commits] [vidalia/alpha] Implement SafeCookie authentication
chiiph at torproject.org
chiiph at torproject.org
Thu Jul 5 00:13:45 UTC 2012
commit 34d524b6f994d27f4df243f422eed493a5226b0c
Author: Tomás Touceda <chiiph at torproject.org>
Date: Wed Jul 4 21:10:55 2012 -0300
Implement SafeCookie authentication
---
changes/bug5855 | 3 +
src/torcontrol/TorControl.cpp | 74 +++++++++++++++++--
src/torcontrol/TorControl.h | 2 +-
src/vidalia/MainWindow.cpp | 12 ++-
src/vidalia/MainWindow.h | 2 +-
.../plugin/extensions/qtscript_TorControl.cpp | 2 +-
6 files changed, 80 insertions(+), 15 deletions(-)
diff --git a/changes/bug5855 b/changes/bug5855
new file mode 100644
index 0000000..610aae8
--- /dev/null
+++ b/changes/bug5855
@@ -0,0 +1,3 @@
+ New features:
+ o Use SafeCookie authentication method if available instead of the regular
+ cookie authentication. Resolves ticket 5855.
diff --git a/src/torcontrol/TorControl.cpp b/src/torcontrol/TorControl.cpp
index 01bfb1d..c7bf85d 100644
--- a/src/torcontrol/TorControl.cpp
+++ b/src/torcontrol/TorControl.cpp
@@ -19,10 +19,18 @@
#include "RouterStatus.h"
#include "file.h"
#include "stringutil.h"
+#include "crypto.h"
#include <QHostAddress>
#include <QVariantMap>
+#define SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT \
+ "Tor safe cookie authentication server-to-controller hash"
+#define SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT \
+ "Tor safe cookie authentication controller-to-server hash"
+#define AUTHENTICATION_COOKIE_LEN 32
+#define DIGEST256_LEN 32
+#define SAFECOOKIE_SERVER_NONCE_LEN DIGEST256_LEN
/** Default constructor */
TorControl::TorControl(ControlMethod::Method method)
@@ -333,7 +341,8 @@ TorControl::isConnected()
bool
TorControl::send(ControlCommand cmd, ControlReply &reply, QString *errmsg)
{
- if (!_authenticated and (cmd.keyword() != "AUTHENTICATE") and
+ if (!_authenticated and (cmd.keyword() != "AUTHCHALLENGE") and
+ (cmd.keyword() != "AUTHENTICATE") and
(cmd.keyword() != "PROTOCOLINFO") and
(cmd.keyword() != "QUIT")) {
if (errmsg)
@@ -366,18 +375,67 @@ TorControl::send(ControlCommand cmd, QString *errmsg)
* "AUTHENTICATE" SP 1*HEXDIG CRLF
*/
bool
-TorControl::authenticate(const QByteArray cookie, QString *errmsg)
+TorControl::authenticate(const QByteArray cookie, bool safe, QString *errmsg)
{
- ControlCommand cmd("AUTHENTICATE", base16_encode(cookie));
ControlReply reply;
QString str;
+ if (safe) {
+ QByteArray client_nonce = crypto_rand_bytes(DIGEST256_LEN);
+ ControlCommand cmdChallenge("AUTHCHALLENGE", QString("SAFECOOKIE %1").arg(base16_encode(client_nonce)));
- if (!send(cmd, reply, &str)) {
- emit authenticationFailed(str);
- _shouldContinue = false;
- _reason = str;
+ if (!send(cmdChallenge, reply, &str)) {
+ emit authenticationFailed(str);
+ _shouldContinue = false;
+ _reason = str;
- return err(errmsg, str);
+ return err(errmsg, str);
+ }
+
+ QHash<QString, QString> response = string_parse_keyvals(reply.getMessage());
+ QString tmp;
+ tmp.append(cookie);
+ tmp.append(client_nonce);
+ tmp.append(base16_decode(response.value("SERVERNONCE").toAscii()));
+
+ char *client_hash = (char*)malloc(DIGEST256_LEN);
+ char *server_hash = (char*)malloc(DIGEST256_LEN);
+
+ crypto_hmac_sha256(server_hash,
+ SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
+ strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
+ tmp.toAscii().data(),
+ tmp.size());
+
+ if (!QString(server_hash).compare(response.value("SERVERHASH"))) {
+ str = "Server hash was wrong in SAFECOOKIE auth";
+ return err(errmsg, str);
+ }
+
+ crypto_hmac_sha256(client_hash,
+ SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
+ strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
+ tmp.toAscii().data(),
+ tmp.size());
+
+ ControlCommand cmd("AUTHENTICATE", base16_encode(QByteArray(client_hash, DIGEST256_LEN)));
+
+ if (!send(cmd, reply, &str)) {
+ emit authenticationFailed(str);
+ _shouldContinue = false;
+ _reason = str;
+
+ return err(errmsg, str);
+ }
+ } else {
+ ControlCommand cmd("AUTHENTICATE", base16_encode(cookie));
+
+ if (!send(cmd, reply, &str)) {
+ emit authenticationFailed(str);
+ _shouldContinue = false;
+ _reason = str;
+
+ return err(errmsg, str);
+ }
}
onAuthenticated();
return true;
diff --git a/src/torcontrol/TorControl.h b/src/torcontrol/TorControl.h
index 3aa78d3..1158bbd 100644
--- a/src/torcontrol/TorControl.h
+++ b/src/torcontrol/TorControl.h
@@ -78,7 +78,7 @@ public:
/** Check if we're connected to Tor's control socket */
bool isConnected();
/** Sends an authentication cookie to Tor. */
- bool authenticate(const QByteArray cookie, QString *errmsg = 0);
+ bool authenticate(const QByteArray cookie, bool safe = true, QString *errmsg = 0);
/** Sends an authentication password to Tor. */
bool authenticate(const QString &password = QString(), QString *errmsg = 0);
/** Returns true if the process has passed through auth successfully */
diff --git a/src/vidalia/MainWindow.cpp b/src/vidalia/MainWindow.cpp
index 2ea816e..e3cacb0 100644
--- a/src/vidalia/MainWindow.cpp
+++ b/src/vidalia/MainWindow.cpp
@@ -1522,7 +1522,7 @@ MainWindow::authenticate()
QString errmsg;
if (authMethod == TorSettings::CookieAuth) {
- if(tryCookie(pi)) {
+ if(tryCookie(pi, authMethods.contains("SAFECOOKIE"))) {
authenticated();
return;
} else {
@@ -1556,7 +1556,7 @@ MainWindow::authenticate()
}
bool
-MainWindow::tryCookie(const ProtocolInfo &pi)
+MainWindow::tryCookie(const ProtocolInfo &pi, bool safe)
{
TorSettings settings;
/* Try to load an auth cookie and send it to Tor */
@@ -1589,8 +1589,12 @@ MainWindow::tryCookie(const ProtocolInfo &pi)
.arg(cookie.size()));
return false;
}
- vNotice("Authenticating using 'cookie' authentication.");
- return _torControl->authenticate(cookie);
+ if (safe) {
+ vNotice("Authenticating using 'safecookie' authentication.");
+ } else {
+ vNotice("Authenticating using 'cookie' authentication.");
+ }
+ return _torControl->authenticate(cookie, safe);
}
bool
diff --git a/src/vidalia/MainWindow.h b/src/vidalia/MainWindow.h
index 4bb3ef8..e5befa3 100644
--- a/src/vidalia/MainWindow.h
+++ b/src/vidalia/MainWindow.h
@@ -95,7 +95,7 @@ private slots:
/** Called when Vidalia has successfully authenticated to Tor. */
void authenticated();
/** Called when authenticated() detects that you can do auth with a cookie */
- bool tryCookie(const ProtocolInfo &pi);
+ bool tryCookie(const ProtocolInfo &pi, bool safe = false);
/** Called when cookie auth fails or when it's the only method configured */
bool tryHashed();
/** Called when Vidalia fails to authenticate to Tor. The failure reason is
diff --git a/src/vidalia/plugin/extensions/qtscript_TorControl.cpp b/src/vidalia/plugin/extensions/qtscript_TorControl.cpp
index 97cb237..67a3a7a 100644
--- a/src/vidalia/plugin/extensions/qtscript_TorControl.cpp
+++ b/src/vidalia/plugin/extensions/qtscript_TorControl.cpp
@@ -221,7 +221,7 @@ static QScriptValue qtscript_TorControl_prototype_call(QScriptContext *context,
&& qscriptvalue_cast<QString*>(context->argument(1))) {
QByteArray _q_arg0 = qscriptvalue_cast<QByteArray>(context->argument(0));
QString* _q_arg1 = qscriptvalue_cast<QString*>(context->argument(1));
- bool _q_result = _q_self->authenticate(_q_arg0, _q_arg1);
+ bool _q_result = _q_self->authenticate(_q_arg0, false, _q_arg1);
return QScriptValue(context->engine(), _q_result);
} else if (context->argument(0).isString()
&& qscriptvalue_cast<QString*>(context->argument(1))) {
More information about the tor-commits
mailing list