func ReadUserPassRequest(reader io.Reader) (request Socks5UserPassRequest, err error) { buffer := buf.NewLocal(512) defer buffer.Release() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return } request.version = buffer.Byte(0) nUsername := int(buffer.Byte(1)) buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, nUsername)) if err != nil { return } request.username = buffer.String() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return } nPassword := int(buffer.Byte(0)) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, nPassword)) if err != nil { return } request.password = buffer.String() return }
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 }
func readUsernamePassword(reader io.Reader) (string, string, error) { buffer := buf.NewLocal(512) defer buffer.Release() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return "", "", err } nUsername := int(buffer.Byte(1)) buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nUsername)); err != nil { return "", "", err } username := buffer.String() buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil { return "", "", err } nPassword := int(buffer.Byte(0)) buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nPassword)); err != nil { return "", "", err } password := buffer.String() return username, password, nil }
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { buffer := buf.NewLocal(512) defer buffer.Release() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)) if err != nil { return } request = &Socks5Request{ Version: buffer.Byte(0), Command: buffer.Byte(1), // buffer[2] is a reserved field AddrType: buffer.Byte(3), } switch request.AddrType { case AddrTypeIPv4: _, err = io.ReadFull(reader, request.IPv4[:]) if err != nil { return } case AddrTypeDomain: buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return } domainLength := int(buffer.Byte(0)) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)) if err != nil { return } request.Domain = string(buffer.BytesFrom(-domainLength)) case AddrTypeIPv6: _, err = io.ReadFull(reader, request.IPv6[:]) if err != nil { return } default: err = errors.Format("Socks: Unexpected address type %d", request.AddrType) return } err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return } request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2)) return }
func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf.Buffer, error) { user := request.User rawAccount, err := user.GetTypedAccount() if err != nil { return nil, errors.Base(err).Message("Shadowsocks|UDP: Failed to parse account.") } account := rawAccount.(*ShadowsocksAccount) buffer := buf.NewSmall() ivLen := account.Cipher.IVSize() buffer.AppendSupplier(buf.ReadFullFrom(rand.Reader, ivLen)) iv := buffer.Bytes() switch request.Address.Family() { case v2net.AddressFamilyIPv4: buffer.AppendBytes(AddrTypeIPv4) buffer.Append([]byte(request.Address.IP())) case v2net.AddressFamilyIPv6: buffer.AppendBytes(AddrTypeIPv6) buffer.Append([]byte(request.Address.IP())) case v2net.AddressFamilyDomain: buffer.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain()))) buffer.Append([]byte(request.Address.Domain())) default: return nil, errors.New("Shadowsocks|UDP: Unsupported address type: ", request.Address.Family()) } buffer.AppendSupplier(serial.WriteUint16(uint16(request.Port))) buffer.Append(payload.Bytes()) if request.Option.Has(RequestOptionOneTimeAuth) { authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) buffer.SetByte(ivLen, buffer.Byte(ivLen)|0x10) buffer.AppendSupplier(authenticator.Authenticate(buffer.BytesFrom(ivLen))) } stream, err := account.Cipher.NewEncodingStream(account.Key, iv) if err != nil { return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.") } stream.XORKeyStream(buffer.BytesFrom(ivLen), buffer.BytesFrom(ivLen)) return buffer, nil }
func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) { rawAccount, err := user.GetTypedAccount() if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.") } account := rawAccount.(*ShadowsocksAccount) buffer := buf.NewLocal(512) defer buffer.Release() ivLen := account.Cipher.IVSize() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, ivLen)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IV.") } iv := append([]byte(nil), buffer.BytesTo(ivLen)...) stream, err := account.Cipher.NewDecodingStream(account.Key, iv) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.") } reader = crypto.NewCryptionReader(stream, reader) authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) request := &protocol.RequestHeader{ Version: Version, User: user, Command: protocol.RequestCommandTCP, } buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read address type.") } addrType := (buffer.Byte(0) & 0x0F) if (buffer.Byte(0) & 0x10) == 0x10 { request.Option |= RequestOptionOneTimeAuth } if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA enabled, while server disables OTA.") } if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA disabled, while server enables OTA.") } switch addrType { case AddrTypeIPv4: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv4 address.") } request.Address = v2net.IPAddress(buffer.BytesFrom(-4)) case AddrTypeIPv6: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 16)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv6 address.") } request.Address = v2net.IPAddress(buffer.BytesFrom(-16)) case AddrTypeDomain: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain lenth.") } domainLength := int(buffer.BytesFrom(-1)[0]) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain.") } request.Address = v2net.DomainAddress(string(buffer.BytesFrom(-domainLength))) default: // Check address validity after OTA verification. } err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read port.") } request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2)) if request.Option.Has(RequestOptionOneTimeAuth) { actualAuth := make([]byte, AuthSize) authenticator.Authenticate(buffer.Bytes())(actualAuth) err := buffer.AppendSupplier(buf.ReadFullFrom(reader, AuthSize)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read OTA.") } if !bytes.Equal(actualAuth, buffer.BytesFrom(-AuthSize)) { return nil, nil, errors.New("Shadowsocks|TCP: Invalid OTA") } } if request.Address == nil { return nil, nil, errors.New("Shadowsocks|TCP: Invalid remote address.") } var chunkReader buf.Reader if request.Option.Has(RequestOptionOneTimeAuth) { chunkReader = NewChunkReader(reader, NewAuthenticator(ChunkKeyGenerator(iv))) } else { chunkReader = buf.NewReader(reader) } return request, chunkReader, nil }
func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) { buffer := buf.NewLocal(512) request := new(protocol.RequestHeader) if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return nil, errors.Base(err).Message("Socks|Server: Insufficient header.") } version := buffer.Byte(0) if version == socks4Version { if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 6)); err != nil { return nil, errors.Base(err).Message("Socks|Server: Insufficient header.") } port := v2net.PortFromBytes(buffer.BytesRange(2, 4)) address := v2net.IPAddress(buffer.BytesRange(4, 8)) _, err := readUntilNull(reader) // user id if err != nil { return nil, err } if address.IP()[0] == 0x00 { domain, err := readUntilNull(reader) if err != nil { return nil, errors.Base(err).Message("Socks|Server: Failed to read domain for socks 4a.") } address = v2net.DomainAddress(domain) } switch buffer.Byte(1) { case cmdTCPConnect: request.Command = protocol.RequestCommandTCP request.Address = address request.Port = port request.Version = socks4Version if err := writeSocks4Response(writer, socks4RequestGranted, v2net.AnyIP, v2net.Port(0)); err != nil { return nil, err } return request, nil default: writeSocks4Response(writer, socks4RequestRejected, v2net.AnyIP, v2net.Port(0)) return nil, errors.New("Socks|Server: Unsupported command: ", buffer.Byte(1)) } } if version == socks5Version { nMethod := int(buffer.Byte(1)) if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nMethod)); err != nil { return nil, err } var expectedAuth byte = authNotRequired if s.config.AuthType == AuthType_PASSWORD { expectedAuth = authPassword } if !hasAuthMethod(expectedAuth, buffer.BytesRange(2, 2+nMethod)) { writeSocks5AuthenticationResponse(writer, authNoMatchingMethod) return nil, errors.New("Socks|Server: No matching auth method.") } if err := writeSocks5AuthenticationResponse(writer, expectedAuth); err != nil { return nil, err } if expectedAuth == authPassword { username, password, err := readUsernamePassword(reader) if err != nil { return nil, errors.Base(err).Message("Socks|Server: Failed to read username and password for authentication.") } if !s.config.HasAccount(username, password) { writeSocks5AuthenticationResponse(writer, 0xFF) return nil, errors.New("Socks|Server: Invalid username or password.") } if err := writeSocks5AuthenticationResponse(writer, 0x00); err != nil { return nil, err } } buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil { return nil, err } cmd := buffer.Byte(1) if cmd == cmdTCPBind || (cmd == cmdUDPPort && !s.config.UdpEnabled) { writeSocks5Response(writer, statusCmdNotSupport, v2net.AnyIP, v2net.Port(0)) return nil, errors.New("Socks|Server: Unsupported command: ", cmd) } switch cmd { case cmdTCPConnect: request.Command = protocol.RequestCommandTCP case cmdUDPPort: request.Command = protocol.RequestCommandUDP } addrType := buffer.Byte(3) buffer.Clear() request.Version = socks5Version switch addrType { case addrTypeIPv4: if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil { return nil, err } request.Address = v2net.IPAddress(buffer.Bytes()) case addrTypeIPv6: if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 16)); err != nil { return nil, err } request.Address = v2net.IPAddress(buffer.Bytes()) case addrTypeDomain: if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil { return nil, err } domainLength := int(buffer.Byte(0)) if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)); err != nil { return nil, err } request.Address = v2net.DomainAddress(string(buffer.BytesFrom(-domainLength))) default: return nil, errors.New("Socks|Server: Unknown address type: ", addrType) } if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return nil, err } request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2)) responseAddress := v2net.AnyIP responsePort := v2net.Port(1717) if request.Command == protocol.RequestCommandUDP { addr := s.config.Address.AsAddress() if addr == nil { addr = v2net.LocalHostIP } responseAddress = addr responsePort = s.port } if err := writeSocks5Response(writer, statusSuccess, responseAddress, responsePort); err != nil { return nil, err } return request, nil } return nil, errors.New("Socks|Server: Unknown Socks version: ", version) }
func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) { authByte := byte(authNotRequired) if request.User != nil { authByte = byte(authPassword) } authRequest := []byte{socks5Version, 0x01, authByte} if _, err := writer.Write(authRequest); err != nil { return nil, err } b := buf.NewLocal(64) if err := b.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return nil, err } if b.Byte(0) != socks5Version { return nil, errors.New("Socks|Client: Unexpected server version: ", b.Byte(0)) } if b.Byte(1) != authByte { return nil, errors.New("Socks|Client: auth method not supported.") } if authByte == authPassword { rawAccount, err := request.User.GetTypedAccount() if err != nil { return nil, err } account := rawAccount.(*Account) b.Clear() b.AppendBytes(socks5Version, byte(len(account.Username))) b.Append([]byte(account.Username)) b.AppendBytes(byte(len(account.Password))) b.Append([]byte(account.Password)) if _, err := writer.Write(b.Bytes()); err != nil { return nil, err } b.Clear() if err := b.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return nil, err } if b.Byte(1) != 0x00 { return nil, errors.New("Socks|Client: Server rejects account: ", b.Byte(1)) } } b.Clear() command := byte(cmdTCPConnect) if request.Command == protocol.RequestCommandUDP { command = byte(cmdUDPPort) } b.AppendBytes(socks5Version, command, 0x00 /* reserved */) appendAddress(b, request.Address, request.Port) if _, err := writer.Write(b.Bytes()); err != nil { return nil, err } b.Clear() if err := b.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil { return nil, err } resp := b.Byte(1) if resp != 0x00 { return nil, errors.New("Socks|Client: Server rejects request: ", resp) } addrType := b.Byte(3) b.Clear() var address v2net.Address switch addrType { case addrTypeIPv4: if err := b.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil { return nil, err } address = v2net.IPAddress(b.Bytes()) case addrTypeIPv6: if err := b.AppendSupplier(buf.ReadFullFrom(reader, 16)); err != nil { return nil, err } address = v2net.IPAddress(b.Bytes()) case addrTypeDomain: if err := b.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil { return nil, err } domainLength := int(b.Byte(0)) if err := b.AppendSupplier(buf.ReadFullFrom(reader, domainLength)); err != nil { return nil, err } address = v2net.DomainAddress(string(b.BytesFrom(-domainLength))) default: return nil, errors.New("Socks|Server: Unknown address type: ", addrType) } if err := b.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return nil, err } port := v2net.PortFromBytes(b.BytesFrom(-2)) if request.Command == protocol.RequestCommandUDP { udpRequest := &protocol.RequestHeader{ Version: socks5Version, Command: protocol.RequestCommandUDP, Address: address, Port: port, } return udpRequest, nil } return nil, nil }