From d10933693007bae2917875ad19bd3dd4e075fd28 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Fri, 20 Mar 2015 11:21:35 +0000 Subject: [PATCH] Add support for password ("HASHEDPASSWORD") authentication. --- cmd_authenticate.go | 18 +++++++++++++++--- examples/basic/basic.go | 5 +++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cmd_authenticate.go b/cmd_authenticate.go index f48f14f..478d6f8 100644 --- a/cmd_authenticate.go +++ b/cmd_authenticate.go @@ -18,7 +18,7 @@ import ( // Authenticate authenticates with the Tor instance using the "best" possible // authentication method. -func (c *Conn) Authenticate() error { +func (c *Conn) Authenticate(passwd string) error { if c.isAuthenticated { return nil } @@ -29,11 +29,12 @@ func (c *Conn) Authenticate() error { return err } - // TODO: Add support for password authentication. "COOKIE" auth is - // superceded by "SAFECOOKIE" on all reasonable versions of Tor. + // "COOKIE" authentication exists, but anything modern supports + // "SAFECOOKIE". const ( cmdAuthenticate = "AUTHENTICATE" authMethodNull = "NULL" + authMethodPassword = "HASHEDPASSWORD" authMethodSafeCookie = "SAFECOOKIE" ) if pi.AuthMethods[authMethodNull] { @@ -118,6 +119,17 @@ func (c *Conn) Authenticate() error { _, err = c.Request("%s %s", cmdAuthenticate, clientHashStr) c.isAuthenticated = err == nil return err + } else if pi.AuthMethods[authMethodPassword] { + // Despite the name HASHEDPASSWORD, the raw password is actually sent. + // According to the code, this can either be a QuotedString, or base16 + // encoded, so go with the later since it's easier to handle. + if passwd == "" { + return newProtocolError("password auth needs a password") + } + passwdStr := hex.EncodeToString([]byte(passwd)) + _, err = c.Request("%s %s", cmdAuthenticate, passwdStr) + c.isAuthenticated = err == nil + return err } else { return newProtocolError("no supported authentication methods") } diff --git a/examples/basic/basic.go b/examples/basic/basic.go index 6488bd0..38456ec 100644 --- a/examples/basic/basic.go +++ b/examples/basic/basic.go @@ -26,8 +26,9 @@ func main() { // Do not enable in production. c.Debug(true) - // Authenticate with the control port. - if err := c.Authenticate(); err != nil { + // Authenticate with the control port. The password argument + // here can be "" if no password is set (CookieAuth, no auth). + if err := c.Authenticate("ExamplePassword"); err != nil { log.Fatalf("Authentication failed: %v", err) }