github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/go-ntlm/ntlm/payload.go (about)

     1  //Copyright 2013 Thomson Reuters Global Resources. BSD License please see License file for more information
     2  
     3  package ntlm
     4  
     5  import (
     6  	"bytes"
     7  	"encoding/binary"
     8  	"encoding/hex"
     9  	"errors"
    10  )
    11  
    12  const (
    13  	UnicodeStringPayload = iota
    14  	OemStringPayload
    15  	BytesPayload
    16  )
    17  
    18  type PayloadStruct struct {
    19  	Type    int
    20  	Len     uint16
    21  	MaxLen  uint16
    22  	Offset  uint32
    23  	Payload []byte
    24  }
    25  
    26  func (p *PayloadStruct) Bytes() []byte {
    27  	dest := make([]byte, 0, 8)
    28  	buffer := bytes.NewBuffer(dest)
    29  
    30  	binary.Write(buffer, binary.LittleEndian, p.Len)
    31  	binary.Write(buffer, binary.LittleEndian, p.MaxLen)
    32  	binary.Write(buffer, binary.LittleEndian, p.Offset)
    33  
    34  	return buffer.Bytes()
    35  }
    36  
    37  func (p *PayloadStruct) String() string {
    38  	var returnString string
    39  
    40  	switch p.Type {
    41  	case UnicodeStringPayload:
    42  		returnString = utf16ToString(p.Payload)
    43  	case OemStringPayload:
    44  		returnString = string(p.Payload)
    45  	case BytesPayload:
    46  		returnString = hex.EncodeToString(p.Payload)
    47  	default:
    48  		returnString = "unknown type"
    49  	}
    50  	return returnString
    51  }
    52  
    53  func CreateBytePayload(bytes []byte) (*PayloadStruct, error) {
    54  	p := new(PayloadStruct)
    55  	p.Type = BytesPayload
    56  	p.Len = uint16(len(bytes))
    57  	p.MaxLen = uint16(len(bytes))
    58  	p.Payload = bytes // TODO: Copy these bytes instead of keeping a reference
    59  	return p, nil
    60  }
    61  
    62  func CreateStringPayload(value string) (*PayloadStruct, error) {
    63  	// Create UTF16 unicode bytes from string
    64  	bytes := utf16FromString(value)
    65  	p := new(PayloadStruct)
    66  	p.Type = UnicodeStringPayload
    67  	p.Len = uint16(len(bytes))
    68  	p.MaxLen = uint16(len(bytes))
    69  	p.Payload = bytes // TODO: Copy these bytes instead of keeping a reference
    70  	return p, nil
    71  }
    72  
    73  func ReadStringPayload(startByte int, bytes []byte) (*PayloadStruct, error) {
    74  	return ReadPayloadStruct(startByte, bytes, UnicodeStringPayload)
    75  }
    76  
    77  func ReadBytePayload(startByte int, bytes []byte) (*PayloadStruct, error) {
    78  	return ReadPayloadStruct(startByte, bytes, BytesPayload)
    79  }
    80  
    81  func ReadPayloadStruct(startByte int, bytes []byte, PayloadType int) (*PayloadStruct, error) {
    82  	p := new(PayloadStruct)
    83  
    84  	// [Psiphon]
    85  	// Don't panic on malformed remote input.
    86  	if len(bytes) < startByte+8 {
    87  		return nil, errors.New("invalid payload")
    88  	}
    89  
    90  	p.Type = PayloadType
    91  	p.Len = binary.LittleEndian.Uint16(bytes[startByte : startByte+2])
    92  	p.MaxLen = binary.LittleEndian.Uint16(bytes[startByte+2 : startByte+4])
    93  	p.Offset = binary.LittleEndian.Uint32(bytes[startByte+4 : startByte+8])
    94  
    95  	if p.Len > 0 {
    96  		endOffset := p.Offset + uint32(p.Len)
    97  
    98  		// [Psiphon]
    99  		// Don't panic on malformed remote input.
   100  		if len(bytes) < int(endOffset) {
   101  			return nil, errors.New("invalid payload")
   102  		}
   103  
   104  		p.Payload = bytes[p.Offset:endOffset]
   105  	}
   106  
   107  	return p, nil
   108  }