Ver código fonte

refactor shadowsocks

v2ray 9 anos atrás
pai
commit
e9c784d4bd

+ 0 - 6
common/crypto/authenticator.go

@@ -1,6 +0,0 @@
-package crypto
-
-type Authenticator interface {
-	AuthSize() int
-	Authenticate(auth []byte, data []byte) []byte
-}

+ 0 - 68
common/io/reader.go

@@ -4,9 +4,6 @@ import (
 	"io"
 
 	"github.com/v2ray/v2ray-core/common/alloc"
-	"github.com/v2ray/v2ray-core/common/crypto"
-	"github.com/v2ray/v2ray-core/common/serial"
-	"github.com/v2ray/v2ray-core/transport"
 )
 
 // ReadFrom reads from a reader and put all content to a buffer.
@@ -55,68 +52,3 @@ func (this *AdaptiveReader) Read() (*alloc.Buffer, error) {
 	}
 	return buffer, nil
 }
-
-type ChunkReader struct {
-	reader io.Reader
-}
-
-func NewChunkReader(reader io.Reader) *ChunkReader {
-	return &ChunkReader{
-		reader: reader,
-	}
-}
-
-func (this *ChunkReader) Read() (*alloc.Buffer, error) {
-	buffer := alloc.NewLargeBuffer()
-	if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil {
-		alloc.Release(buffer)
-		return nil, err
-	}
-	length := serial.BytesLiteral(buffer.Value[:2]).Uint16Value()
-	if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil {
-		alloc.Release(buffer)
-		return nil, err
-	}
-	buffer.Slice(0, int(length))
-	return buffer, nil
-}
-
-type AuthenticationReader struct {
-	reader            Reader
-	authenticator     crypto.Authenticator
-	authBeforePayload bool
-}
-
-func NewAuthenticationReader(reader Reader, auth crypto.Authenticator, authBeforePayload bool) *AuthenticationReader {
-	return &AuthenticationReader{
-		reader:            reader,
-		authenticator:     auth,
-		authBeforePayload: authBeforePayload,
-	}
-}
-
-func (this *AuthenticationReader) Read() (*alloc.Buffer, error) {
-	buffer, err := this.reader.Read()
-	if err != nil {
-		alloc.Release(buffer)
-		return nil, err
-	}
-
-	authSize := this.authenticator.AuthSize()
-	var authBytes, payloadBytes []byte
-	if this.authBeforePayload {
-		authBytes = buffer.Value[:authSize]
-		payloadBytes = buffer.Value[authSize:]
-	} else {
-		payloadBytes = buffer.Value[:authSize]
-		authBytes = buffer.Value[authSize:]
-	}
-
-	actualAuthBytes := this.authenticator.Authenticate(nil, payloadBytes)
-	if !serial.BytesLiteral(authBytes).Equals(serial.BytesLiteral(actualAuthBytes)) {
-		alloc.Release(buffer)
-		return nil, transport.CorruptedPacket
-	}
-	buffer.Value = payloadBytes
-	return buffer, nil
-}

+ 45 - 4
proxy/shadowsocks/ota.go

@@ -3,8 +3,12 @@ package shadowsocks
 import (
 	"crypto/hmac"
 	"crypto/sha1"
+	"io"
 
+	"github.com/v2ray/v2ray-core/common/alloc"
+	"github.com/v2ray/v2ray-core/common/log"
 	"github.com/v2ray/v2ray-core/common/serial"
+	"github.com/v2ray/v2ray-core/transport"
 )
 
 const (
@@ -23,10 +27,6 @@ func NewAuthenticator(keygen KeyGenerator) *Authenticator {
 	}
 }
 
-func (this *Authenticator) AuthSize() int {
-	return AuthSize
-}
-
 func (this *Authenticator) Authenticate(auth []byte, data []byte) []byte {
 	hasher := hmac.New(sha1.New, this.key())
 	hasher.Write(data)
@@ -53,3 +53,44 @@ func ChunkKeyGenerator(iv []byte) func() []byte {
 		return newKey
 	}
 }
+
+type ChunkReader struct {
+	reader io.Reader
+	auth   *Authenticator
+}
+
+func NewChunkReader(reader io.Reader, auth *Authenticator) *ChunkReader {
+	return &ChunkReader{
+		reader: reader,
+		auth:   auth,
+	}
+}
+
+func (this *ChunkReader) Read() (*alloc.Buffer, error) {
+	buffer := alloc.NewLargeBuffer()
+	if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil {
+		alloc.Release(buffer)
+		return nil, err
+	}
+	// There is a potential buffer overflow here. Large buffer is 64K bytes,
+	// while uin16 + 10 will be more than that
+	length := serial.BytesLiteral(buffer.Value[:2]).Uint16Value() + AuthSize
+	if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil {
+		alloc.Release(buffer)
+		return nil, err
+	}
+	buffer.Slice(0, int(length))
+
+	authBytes := buffer.Value[:AuthSize]
+	payload := buffer.Value[AuthSize:]
+
+	actualAuthBytes := this.auth.Authenticate(nil, payload)
+	if !serial.BytesLiteral(authBytes).Equals(serial.BytesLiteral(actualAuthBytes)) {
+		alloc.Release(buffer)
+		log.Debug("AuthenticationReader: Unexpected auth: ", authBytes)
+		return nil, transport.CorruptedPacket
+	}
+	buffer.Value = payload
+
+	return buffer, nil
+}

+ 1 - 1
proxy/shadowsocks/protocol.go

@@ -86,7 +86,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator) (*Request, error) {
 	lenBuffer += 2
 
 	if request.OTA {
-		authBytes := buffer.Value[lenBuffer : lenBuffer+auth.AuthSize()]
+		authBytes := buffer.Value[lenBuffer : lenBuffer+AuthSize]
 		_, err = io.ReadFull(reader, authBytes)
 		if err != nil {
 			log.Error("Shadowsocks: Failed to read OTA: ", err)

+ 2 - 2
proxy/shadowsocks/shadowsocks.go

@@ -155,7 +155,7 @@ func (this *Shadowsocks) handleConnection(conn *hub.TCPConn) {
 		return
 	}
 
-	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)))
+	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(iv, key)))
 	if err != nil {
 		return
 	}
@@ -188,7 +188,7 @@ func (this *Shadowsocks) handleConnection(conn *hub.TCPConn) {
 	var payloadReader v2io.Reader
 	if request.OTA {
 		payloadAuth := NewAuthenticator(ChunkKeyGenerator(iv))
-		payloadReader = v2io.NewAuthenticationReader(v2io.NewChunkReader(reader), payloadAuth, true)
+		payloadReader = NewChunkReader(reader, payloadAuth)
 	} else {
 		payloadReader = v2io.NewAdaptiveReader(reader)
 	}