예제 #1
0
func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, auth4 Socks4AuthenticationRequest, err error) {
	buffer := alloc.NewSmallBuffer()
	defer buffer.Release()

	nBytes, err := reader.Read(buffer.Value)
	if err != nil {
		return
	}
	if nBytes < 2 {
		log.Info("Socks expected 2 bytes read, but only %d bytes read", nBytes)
		err = errors.NewCorruptedPacketError()
		return
	}

	if buffer.Value[0] == socks4Version {
		auth4.Version = buffer.Value[0]
		auth4.Command = buffer.Value[1]
		auth4.Port = binary.BigEndian.Uint16(buffer.Value[2:4])
		copy(auth4.IP[:], buffer.Value[4:8])
		err = NewSocksVersion4Error()
		return
	}

	auth.version = buffer.Value[0]
	if auth.version != socksVersion {
		err = errors.NewProtocolVersionError(int(auth.version))
		return
	}

	auth.nMethods = buffer.Value[1]
	if auth.nMethods <= 0 {
		log.Info("Zero length of authentication methods")
		err = errors.NewCorruptedPacketError()
		return
	}

	if nBytes-2 != int(auth.nMethods) {
		log.Info("Unmatching number of auth methods, expecting %d, but got %d", auth.nMethods, nBytes)
		err = errors.NewCorruptedPacketError()
		return
	}
	copy(auth.authMethods[:], buffer.Value[2:nBytes])
	return
}
예제 #2
0
파일: vmess.go 프로젝트: nenew/v2ray-core
// Read reads a VMessRequest from a byte stream.
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
	buffer := make([]byte, 256)

	nBytes, err := reader.Read(buffer[:user.IDBytesLen])
	if err != nil {
		return nil, err
	}

	log.Debug("Read user hash: %v", buffer[:nBytes])

	userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes])
	if !valid {
		return nil, errors.NewAuthenticationError(buffer[:nBytes])
	}

	aesCipher, err := aes.NewCipher(userId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
	decryptor := v2io.NewCryptionReader(aesStream, reader)

	if err != nil {
		return nil, err
	}

	nBytes, err = decryptor.Read(buffer[:41])
	if err != nil {
		return nil, err
	}
	bufferLen := nBytes

	request := &VMessRequest{
		UserId:  *userId,
		Version: buffer[0],
	}

	if request.Version != Version {
		return nil, errors.NewProtocolVersionError(int(request.Version))
	}

	copy(request.RequestIV[:], buffer[1:17])       // 16 bytes
	copy(request.RequestKey[:], buffer[17:33])     // 16 bytes
	copy(request.ResponseHeader[:], buffer[33:37]) // 4 bytes
	request.Command = buffer[37]

	port := binary.BigEndian.Uint16(buffer[38:40])

	switch buffer[40] {
	case addrTypeIPv4:
		_, err = decryptor.Read(buffer[41:45]) // 4 bytes
		bufferLen += 4
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[41:45], port)
	case addrTypeIPv6:
		_, err = decryptor.Read(buffer[41:57]) // 16 bytes
		bufferLen += 16
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[41:57], port)
	case addrTypeDomain:
		_, err = decryptor.Read(buffer[41:42])
		if err != nil {
			return nil, err
		}
		domainLength := int(buffer[41])
		_, err = decryptor.Read(buffer[42 : 42+domainLength])
		if err != nil {
			return nil, err
		}
		bufferLen += 1 + domainLength
		request.Address = v2net.DomainAddress(string(buffer[42:42+domainLength]), port)
	}

	_, err = decryptor.Read(buffer[bufferLen : bufferLen+4])
	if err != nil {
		return nil, err
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer[:bufferLen])
	actualHash := fnv1a.Sum32()
	expectedHash := binary.BigEndian.Uint32(buffer[bufferLen : bufferLen+4])

	if actualHash != expectedHash {
		return nil, errors.NewCorruptedPacketError()
	}

	return request, nil
}