1package ntlmssp
2
3import (
4	"bytes"
5	"encoding/binary"
6	"fmt"
7)
8
9type challengeMessageFields struct {
10	messageHeader
11	TargetName      varField
12	NegotiateFlags  negotiateFlags
13	ServerChallenge [8]byte
14	_               [8]byte
15	TargetInfo      varField
16}
17
18func (m challengeMessageFields) IsValid() bool {
19	return m.messageHeader.IsValid() && m.MessageType == 2
20}
21
22type challengeMessage struct {
23	challengeMessageFields
24	TargetName    string
25	TargetInfo    map[avID][]byte
26	TargetInfoRaw []byte
27}
28
29func (m *challengeMessage) UnmarshalBinary(data []byte) error {
30	r := bytes.NewReader(data)
31	err := binary.Read(r, binary.LittleEndian, &m.challengeMessageFields)
32	if err != nil {
33		return err
34	}
35	if !m.challengeMessageFields.IsValid() {
36		return fmt.Errorf("Message is not a valid challenge message: %+v", m.challengeMessageFields.messageHeader)
37	}
38
39	if m.challengeMessageFields.TargetName.Len > 0 {
40		m.TargetName, err = m.challengeMessageFields.TargetName.ReadStringFrom(data, m.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEUNICODE))
41		if err != nil {
42			return err
43		}
44	}
45
46	if m.challengeMessageFields.TargetInfo.Len > 0 {
47		d, err := m.challengeMessageFields.TargetInfo.ReadFrom(data)
48		m.TargetInfoRaw = d
49		if err != nil {
50			return err
51		}
52		m.TargetInfo = make(map[avID][]byte)
53		r := bytes.NewReader(d)
54		for {
55			var id avID
56			var l uint16
57			err = binary.Read(r, binary.LittleEndian, &id)
58			if err != nil {
59				return err
60			}
61			if id == avIDMsvAvEOL {
62				break
63			}
64
65			err = binary.Read(r, binary.LittleEndian, &l)
66			if err != nil {
67				return err
68			}
69			value := make([]byte, l)
70			n, err := r.Read(value)
71			if err != nil {
72				return err
73			}
74			if n != int(l) {
75				return fmt.Errorf("Expected to read %d bytes, got only %d", l, n)
76			}
77			m.TargetInfo[id] = value
78		}
79	}
80
81	return nil
82}
83