commit 34d524b6f994d27f4df243f422eed493a5226b0c Author: Tomás Touceda chiiph@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))) {
tor-commits@lists.torproject.org