1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-27 09:55:22 +00:00

refactor shadowsocks

This commit is contained in:
v2ray 2016-01-29 20:54:06 +01:00
parent c9554546db
commit e9c784d4bd
5 changed files with 48 additions and 81 deletions

View File

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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}