func (this *ChunkReader) Read() (*alloc.Buffer, error) { buffer := alloc.NewBuffer() if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil { buffer.Release() 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.BytesToUint16(buffer.Value[:2]) + AuthSize if length > alloc.BufferSize { // Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer. buffer.Release() buffer = alloc.NewLocalBuffer(int(length) + 128) } if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil { buffer.Release() return nil, err } buffer.Slice(0, int(length)) authBytes := buffer.Value[:AuthSize] payload := buffer.Value[AuthSize:] actualAuthBytes := this.auth.Authenticate(nil, payload) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.") } buffer.SliceFrom(AuthSize) return buffer, nil }
func (this *SimpleAuthenticator) Open(buffer *alloc.Buffer) bool { len := buffer.Len() xtra := 4 - len%4 if xtra != 0 { buffer.Slice(0, len+xtra) } xorbkd(buffer.Value) if xtra != 0 { buffer.Slice(0, len) } fnvHash := fnv.New32a() fnvHash.Write(buffer.Value[4:]) if serial.BytesToUint32(buffer.Value[:4]) != fnvHash.Sum32() { return false } length := serial.BytesToUint16(buffer.Value[4:6]) if buffer.Len()-6 != int(length) { return false } buffer.SliceFrom(6) return true }
func (v *AuthenticationReader) NextChunk() error { if v.buffer.Len() < 2 { return errInsufficientBuffer } size := int(serial.BytesToUint16(v.buffer.BytesTo(2))) if size > v.buffer.Len()-2 { return errInsufficientBuffer } if size > readerBufferSize-2 { return errInvalidLength } if size == v.auth.Overhead() { return io.EOF } if size < v.auth.Overhead() { return errors.New("AuthenticationReader: invalid packet size.") } cipherChunk := v.buffer.BytesRange(2, size+2) plainChunk, err := v.auth.Open(cipherChunk[:0], cipherChunk) if err != nil { return err } v.chunk = plainChunk v.buffer.SliceFrom(size + 2) return nil }
func (v *ChunkReader) Read() (*buf.Buffer, error) { buffer := buf.New() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, 2)); err != nil { buffer.Release() 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.BytesToUint16(buffer.BytesTo(2)) + AuthSize if length > buf.Size { // Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer. buffer.Release() buffer = buf.NewLocal(int(length) + 128) } buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, int(length))); err != nil { buffer.Release() return nil, err } authBytes := buffer.BytesTo(AuthSize) payload := buffer.BytesFrom(AuthSize) actualAuthBytes := make([]byte, AuthSize) v.auth.Authenticate(payload)(actualAuthBytes) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.") } buffer.SliceFrom(AuthSize) return buffer, nil }
// Open implements cipher.AEAD.Open(). func (v *SimpleAuthenticator) Open(dst, nonce, cipherText, extra []byte) ([]byte, error) { dst = append(dst, cipherText...) dstLen := len(dst) xtra := 4 - dstLen%4 if xtra != 4 { dst = append(dst, make([]byte, xtra)...) } xorbkd(dst) if xtra != 4 { dst = dst[:dstLen] } fnvHash := fnv.New32a() fnvHash.Write(dst[4:]) if serial.BytesToUint32(dst[:4]) != fnvHash.Sum32() { return nil, crypto.ErrAuthenticationFailed } length := serial.BytesToUint16(dst[4:6]) if len(dst)-6 != int(length) { return nil, crypto.ErrAuthenticationFailed } return dst[6:], nil }
func (this *ChunkReader) Read() (*alloc.Buffer, error) { buffer := alloc.NewLargeBuffer() if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil { buffer.Release() 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.BytesToUint16(buffer.Value[:2]) + AuthSize if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil { buffer.Release() return nil, err } buffer.Slice(0, int(length)) authBytes := buffer.Value[:AuthSize] payload := buffer.Value[AuthSize:] actualAuthBytes := this.auth.Authenticate(nil, payload) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() log.Debug("AuthenticationReader: Unexpected auth: ", authBytes) return nil, transport.ErrCorruptedPacket } buffer.SliceFrom(AuthSize) return buffer, nil }
func (this *Listener) OnReceive(payload *alloc.Buffer, session *proxy.SessionInfo) { defer payload.Release() src := session.Source if valid := this.authenticator.Open(payload); !valid { log.Info("KCP|Listener: discarding invalid payload from ", src) return } if !this.running { return } this.Lock() defer this.Unlock() if !this.running { return } if payload.Len() < 4 { return } conv := serial.BytesToUint16(payload.Value) cmd := Command(payload.Value[2]) sourceId := src.NetAddr() + "|" + serial.Uint16ToString(conv) conn, found := this.sessions[sourceId] if !found { if cmd == CommandTerminate { return } log.Debug("KCP|Listener: Creating session with id(", sourceId, ") from ", src) writer := &Writer{ id: sourceId, hub: this.hub, dest: src, listener: this, } srcAddr := &net.UDPAddr{ IP: src.Address.IP(), Port: int(src.Port), } auth, err := this.config.GetAuthenticator() if err != nil { log.Error("KCP|Listener: Failed to create authenticator: ", err) } conn = NewConnection(conv, writer, this.Addr().(*net.UDPAddr), srcAddr, auth, this.config) select { case this.awaitingConns <- conn: case <-time.After(time.Second * 5): conn.Close() return } this.sessions[sourceId] = conn } conn.Input(payload.Value) }
func (this *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { cmd := new(protocol.CommandSwitchAccount) if len(data) == 0 { return nil, transport.ErrCorruptedPacket } lenHost := int(data[0]) if len(data) < lenHost+1 { return nil, transport.ErrCorruptedPacket } if lenHost > 0 { cmd.Host = v2net.ParseAddress(string(data[1 : 1+lenHost])) } portStart := 1 + lenHost if len(data) < portStart+2 { return nil, transport.ErrCorruptedPacket } cmd.Port = v2net.PortFromBytes(data[portStart : portStart+2]) idStart := portStart + 2 if len(data) < idStart+16 { return nil, transport.ErrCorruptedPacket } cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) alterIdStart := idStart + 16 if len(data) < alterIdStart+2 { return nil, transport.ErrCorruptedPacket } cmd.AlterIds = serial.BytesToUint16(data[alterIdStart : alterIdStart+2]) levelStart := alterIdStart + 2 if len(data) < levelStart+1 { return nil, transport.ErrCorruptedPacket } cmd.Level = protocol.UserLevel(data[levelStart]) timeStart := levelStart + 1 if len(data) < timeStart { return nil, transport.ErrCorruptedPacket } cmd.ValidMin = data[timeStart] return cmd, nil }
func (v *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { cmd := new(protocol.CommandSwitchAccount) if len(data) == 0 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } lenHost := int(data[0]) if len(data) < lenHost+1 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } if lenHost > 0 { cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost])) } portStart := 1 + lenHost if len(data) < portStart+2 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.Port = net.PortFromBytes(data[portStart : portStart+2]) idStart := portStart + 2 if len(data) < idStart+16 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) alterIDStart := idStart + 16 if len(data) < alterIDStart+2 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.AlterIds = serial.BytesToUint16(data[alterIDStart : alterIDStart+2]) levelStart := alterIDStart + 2 if len(data) < levelStart+1 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.Level = uint32(data[levelStart]) timeStart := levelStart + 1 if len(data) < timeStart { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.ValidMin = data[timeStart] return cmd, nil }
func ReadSegment(buf []byte) (Segment, []byte) { if len(buf) <= 4 { return nil, nil } conv := serial.BytesToUint16(buf) buf = buf[2:] cmd := Command(buf[0]) opt := SegmentOption(buf[1]) buf = buf[2:] if cmd == CommandData { seg := NewDataSegment() seg.Conv = conv seg.Option = opt if len(buf) < 16 { return nil, nil } seg.Timestamp = serial.BytesToUint32(buf) buf = buf[4:] seg.Number = serial.BytesToUint32(buf) buf = buf[4:] seg.SendingNext = serial.BytesToUint32(buf) buf = buf[4:] dataLen := int(serial.BytesToUint16(buf)) buf = buf[2:] if len(buf) < dataLen { return nil, nil } seg.Data = AllocateBuffer().Clear().Append(buf[:dataLen]) buf = buf[dataLen:] return seg, buf } if cmd == CommandACK { seg := NewAckSegment() seg.Conv = conv seg.Option = opt if len(buf) < 13 { return nil, nil } seg.ReceivingWindow = serial.BytesToUint32(buf) buf = buf[4:] seg.ReceivingNext = serial.BytesToUint32(buf) buf = buf[4:] seg.Timestamp = serial.BytesToUint32(buf) buf = buf[4:] count := int(buf[0]) buf = buf[1:] if len(buf) < count*4 { return nil, nil } for i := 0; i < count; i++ { seg.PutNumber(serial.BytesToUint32(buf)) buf = buf[4:] } return seg, buf } seg := NewCmdOnlySegment() seg.Conv = conv seg.Command = cmd seg.Option = opt if len(buf) < 12 { return nil, nil } seg.SendingNext = serial.BytesToUint32(buf) buf = buf[4:] seg.ReceivinNext = serial.BytesToUint32(buf) buf = buf[4:] seg.PeerRTO = serial.BytesToUint32(buf) buf = buf[4:] return seg, buf }
// PortFromBytes converts a byte array to a Port, assuming bytes are in big endian order. // @unsafe Caller must ensure that the byte array has at least 2 elements. func PortFromBytes(port []byte) Port { return Port(serial.BytesToUint16(port)) }
func (this *AuthChunkReader) Read() (*alloc.Buffer, error) { var buffer *alloc.Buffer if this.last != nil { buffer = this.last this.last = nil } else { buffer = alloc.NewBufferWithSize(4096).Clear() } if this.chunkLength == -1 { for buffer.Len() < 6 { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } length := serial.BytesToUint16(buffer.Value[:2]) this.chunkLength = int(length) - 4 this.validator = NewValidator(serial.BytesToUint32(buffer.Value[2:6])) buffer.SliceFrom(6) if buffer.Len() < this.chunkLength && this.chunkLength <= 2048 { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } } else if buffer.Len() < this.chunkLength { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } if this.chunkLength == 0 { buffer.Release() return nil, io.EOF } if buffer.Len() < this.chunkLength { this.validator.Consume(buffer.Value) this.chunkLength -= buffer.Len() } else { this.validator.Consume(buffer.Value[:this.chunkLength]) if !this.validator.Validate() { buffer.Release() return nil, transport.ErrCorruptedPacket } leftLength := buffer.Len() - this.chunkLength if leftLength > 0 { this.last = alloc.NewBufferWithSize(leftLength + 4096).Clear() this.last.Append(buffer.Value[this.chunkLength:]) buffer.Slice(0, this.chunkLength) } this.chunkLength = -1 this.validator = nil } return buffer, nil }