[tor-commits] [flashproxy/master] extended OR port authentication.

dcf at torproject.org dcf at torproject.org
Sun Feb 3 03:40:13 UTC 2013


commit e45fc2c2a82135c0f588d4ace19a3a090dc91a41
Author: David Fifield <david at bamsoftware.com>
Date:   Tue Jan 29 14:51:26 2013 -0800

    extended OR port authentication.
---
 websocket-transport/pt.go |  118 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/websocket-transport/pt.go b/websocket-transport/pt.go
index a7459a8..bb7866a 100644
--- a/websocket-transport/pt.go
+++ b/websocket-transport/pt.go
@@ -25,7 +25,12 @@
 package main
 
 import (
+	"bufio"
 	"bytes"
+	"crypto/hmac"
+	"crypto/rand"
+	"crypto/sha256"
+	"crypto/subtle"
 	"errors"
 	"fmt"
 	"io"
@@ -352,10 +357,121 @@ func PtServerSetup(methodNames []string) PtServerInfo {
 	return info
 }
 
+// See 217-ext-orport-auth.txt section 4.2.1.3.
+func computeServerHash(info *PtServerInfo, clientNonce, serverNonce []byte) []byte {
+	h := hmac.New(sha256.New, info.AuthCookie)
+	io.WriteString(h, "ExtORPort authentication server-to-client hash")
+	h.Write(clientNonce)
+	h.Write(serverNonce)
+	return h.Sum([]byte{})
+}
+
+// See 217-ext-orport-auth.txt section 4.2.1.3.
+func computeClientHash(info *PtServerInfo, clientNonce, serverNonce []byte) []byte {
+	h := hmac.New(sha256.New, info.AuthCookie)
+	io.WriteString(h, "ExtORPort authentication client-to-server hash")
+	h.Write(clientNonce)
+	h.Write(serverNonce)
+	return h.Sum([]byte{})
+}
+
+func extOrPortAuthenticate(s *net.TCPConn, info *PtServerInfo) error {
+	r := bufio.NewReader(s)
+
+	// Read auth types. 217-ext-orport-auth.txt section 4.1.
+	var authTypes [256]bool
+	var count int
+	for count = 0; count < 256; count++ {
+		b, err := r.ReadByte()
+		if err != nil {
+			return err
+		}
+		if b == 0 {
+			break
+		}
+		authTypes[b] = true
+	}
+	if count >= 256 {
+		return errors.New(fmt.Sprintf("read 256 auth types without seeing \\x00"))
+	}
+
+	// We support only type 1, SAFE_COOKIE.
+	if !authTypes[1] {
+		return errors.New(fmt.Sprintf("server didn't offer auth type 1"))
+	}
+	_, err := s.Write([]byte{1})
+	if err != nil {
+		return err
+	}
+
+	clientNonce := make([]byte, 32)
+	clientHash := make([]byte, 32)
+	serverNonce := make([]byte, 32)
+	serverHash := make([]byte, 32)
+
+	_, err = io.ReadFull(rand.Reader, clientNonce)
+	if err != nil {
+		return err
+	}
+	_, err = s.Write(clientNonce)
+	if err != nil {
+		return err
+	}
+
+	_, err = io.ReadFull(r, serverHash)
+	if err != nil {
+		return err
+	}
+	_, err = io.ReadFull(r, serverNonce)
+	if err != nil {
+		return err
+	}
+
+	expectedServerHash := computeServerHash(info, clientNonce, serverNonce)
+	if subtle.ConstantTimeCompare(serverHash, expectedServerHash) != 1 {
+		return errors.New(fmt.Sprintf("mismatch in server hash"))
+	}
+
+	clientHash = computeClientHash(info, clientNonce, serverNonce)
+	_, err = s.Write(clientHash)
+	if err != nil {
+		return err
+	}
+
+	status := make([]byte, 1)
+	_, err = io.ReadFull(r, status)
+	if err != nil {
+		return err
+	}
+	if status[0] != 1 {
+		return errors.New(fmt.Sprintf("server rejected authentication"))
+	}
+
+	if r.Buffered() != 0 {
+		return errors.New(fmt.Sprintf("%d bytes left after extended OR port authentication", r.Buffered()))
+	}
+
+	return nil
+}
+
 // Connect to info.ExtendedOrAddr if defined, or else info.OrAddr, and return an
 // open *net.TCPConn. If connecting to the extended OR port, extended OR port
 // authentication à la 217-ext-orport-auth.txt is done before returning; an
 // error is returned if authentication fails.
 func PtConnectOr(info *PtServerInfo, conn net.Conn) (*net.TCPConn, error) {
-	return net.DialTCP("tcp", nil, ptInfo.OrAddr)
+	if info.ExtendedOrAddr == nil {
+		return net.DialTCP("tcp", nil, info.OrAddr)
+	}
+
+	s, err := net.DialTCP("tcp", nil, info.ExtendedOrAddr)
+	if err != nil {
+		return nil, err
+	}
+	err = extOrPortAuthenticate(s, info)
+	if err != nil {
+		s.Close()
+		return nil, err
+	}
+
+	return s, nil
 }





More information about the tor-commits mailing list