forked from go-ldap/ldap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathntlmbind.go
136 lines (98 loc) · 3.88 KB
/
ntlmbind.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package ldap
import (
"fmt"
"bytes"
"io/ioutil"
"encoding/binary"
"encoding/base64"
"github.com/softlandia/cpd"
ber "github.com/go-asn1-ber/asn1-ber"
)
type NtlmBindResult struct {
DomainName string
UserName string
Workstation string
Authenticated bool
}
func (l *Conn) buildNtlmPacket(message []byte) *ber.Packet {
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, 0, nil, "Bind Request")
request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "Name"))
auth := ber.Encode(ber.ClassContext, ber.TypeConstructed, 3, nil, "Authentication")
auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "GSS-SPNEGO", "Mechanism"))
auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(message), "Credentials"))
request.AppendChild(auth)
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(request)
return packet
}
func (l *Conn) NtlmType1MsgReq(message []byte) (string, error) {
packet := l.buildNtlmPacket(message)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return "", err
}
respPacket, err := l.readPacket(msgCtx)
if err != nil {
return "", err
}
if len(respPacket.Children) >= 2 {
if len(respPacket.Children[1].Children) >= 4 {
child := respPacket.Children[1].Children[3]
if child.Tag != ber.TagObjectDescriptor {
return "", GetLDAPError(respPacket)
}
if child.Data == nil {
return "", GetLDAPError(respPacket)
}
data, err := ioutil.ReadAll(child.Data)
return base64.StdEncoding.EncodeToString(data), err
}
}
return "", fmt.Errorf("Ldap ntlm auth get type 2 Message error.")
}
func (l *Conn) NtlmType3MsgReq(message []byte) (*NtlmBindResult, error) {
bindResult := &NtlmBindResult{
Authenticated: false,
}
msgLen := uint16(len(message))
if msgLen <= 52 {
return bindResult, fmt.Errorf("Ldap ntlm auth request type 3 Message error: Invalid message format.")
}
var userLen, hostLen, domainLen, userOffset, hostOffset, domainOffset uint16
binary.Read(bytes.NewBuffer(message[28:30]), binary.LittleEndian, &domainLen)
binary.Read(bytes.NewBuffer(message[32:34]), binary.LittleEndian, &domainOffset)
binary.Read(bytes.NewBuffer(message[36:38]), binary.LittleEndian, &userLen)
binary.Read(bytes.NewBuffer(message[40:42]), binary.LittleEndian, &userOffset)
binary.Read(bytes.NewBuffer(message[44:46]), binary.LittleEndian, &hostLen)
binary.Read(bytes.NewBuffer(message[48:50]), binary.LittleEndian, &hostOffset)
domainEnd := domainOffset + domainLen
userEnd := userOffset + userLen
hostEnd := hostOffset + hostLen
if msgLen < domainEnd || msgLen < userEnd || msgLen < hostEnd {
return bindResult, fmt.Errorf("Ldap ntlm auth request type 3 Message error: Invalid message format.")
}
bindResult.DomainName = cpd.DecodeUTF16le(string(message[domainOffset:domainEnd]))
bindResult.UserName = cpd.DecodeUTF16le(string(message[userOffset:userEnd]))
bindResult.Workstation = cpd.DecodeUTF16le(string(message[hostOffset:hostEnd]))
packet := l.buildNtlmPacket(message)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return bindResult, err
}
respPacket, err := l.readPacket(msgCtx)
if err != nil {
return bindResult, err
}
if len(respPacket.Children) >= 2 {
if len(respPacket.Children[1].Children) >= 1 {
resultCode := uint16(respPacket.Children[1].Children[0].Value.(int64))
if resultCode == 0 {
bindResult.Authenticated = true
}
return bindResult, err
}
}
return bindResult, fmt.Errorf("Ldap ntlm auth request type 3 Message error: Invalid packet format.")
}