-
Notifications
You must be signed in to change notification settings - Fork 0
/
nns_ntlm_dialer.go
136 lines (124 loc) · 3.14 KB
/
nns_ntlm_dialer.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 nns
import (
"bytes"
"errors"
"github.com/LeakIX/ntlmssp"
"net"
"time"
)
// NNSConn implements net.Conn interface and is an authenticated/"encrypted" NNS wrapped connection
type Conn struct {
tcpConn net.Conn
secSession *ntlmssp.SecuritySession
buffer *bytes.Buffer
}
func (conn *Conn) Read(b []byte) (n int, err error) {
if conn.buffer.Len() != 0 {
//decrypted buffer not empty, keep sending bytes
return conn.buffer.Read(b)
}
// empty, reset the buffer
conn.buffer.Reset()
// get nns encrypted packet
nnsPacket, err := UnmarshalNNSPacket(conn.tcpConn)
if err != nil {
return 0, err
}
// get sig from first 16 bytes
sig := nnsPacket.Payload[0:16]
// get the payload
encryptedPayload := nnsPacket.Payload[16:nnsPacket.Size]
// decrypt the ntlmssp packet
decrypted, err := conn.secSession.Unwrap(encryptedPayload, sig)
if err != nil {
return 0, err
}
// store in our buffer
_, err = conn.buffer.Write(decrypted)
// read into b buffer
return conn.buffer.Read(b)
}
func (conn *Conn) Write(b []byte) (n int, err error) {
encryptedPayload, sig, err := conn.secSession.Wrap(b)
if err != nil {
return 0, err
}
nnsPacket := DataPacket{
Payload: append(sig, encryptedPayload...),
}
err = nnsPacket.WriteTo(conn.tcpConn)
if err != nil {
return 0, err
}
return len(b), nil
}
func (conn *Conn) Close() error {
return conn.tcpConn.Close()
}
func (conn *Conn) LocalAddr() net.Addr {
return conn.tcpConn.LocalAddr()
}
func (conn *Conn) RemoteAddr() net.Addr {
return conn.tcpConn.RemoteAddr()
}
func (conn *Conn) SetDeadline(t time.Time) error {
return conn.tcpConn.SetDeadline(t)
}
func (conn *Conn) SetReadDeadline(t time.Time) error {
return conn.tcpConn.SetReadDeadline(t)
}
func (conn *Conn) SetWriteDeadline(t time.Time) error {
return conn.tcpConn.SetWriteDeadline(t)
}
func DialNTLMSSP(address string, ntlmsspClient *ntlmssp.Client, timeout time.Duration) (conn net.Conn, err error) {
if timeout > 0 {
conn, err = net.DialTimeout("tcp", address, timeout)
} else {
conn, err = net.Dial("tcp", address)
}
if err != nil {
return nil, err
}
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
nego, err := ntlmsspClient.Authenticate(nil, nil)
nnsAuthPacket := AuthPacket{
MessageType: HandshakeInProgress,
Payload: nego,
}
if err != nil {
return nil, err
}
err = nnsAuthPacket.WriteTo(conn)
if err != nil {
return nil, err
}
nnsAuthPacket, err = UnmarshalAuthPacket(conn)
if err != nil {
return nil, err
}
ntlmSSPAuthPacket, err := ntlmsspClient.Authenticate(nnsAuthPacket.Payload, nil)
nnsAuthPacket = AuthPacket{
MessageType: HandshakeInProgress,
Payload: ntlmSSPAuthPacket,
}
err = nnsAuthPacket.WriteTo(conn)
if err != nil {
return nil, err
}
nnsAuthPacket, err = UnmarshalAuthPacket(conn)
if err != nil {
return nil, err
}
if nnsAuthPacket.MessageType != HandshakeDone {
return nil, AuthFailed
}
nnsConn := &Conn{
tcpConn: conn,
secSession: ntlmsspClient.SecuritySession(),
buffer: bytes.NewBuffer([]byte{}),
}
//We're auth !
return nnsConn, nil
}
var AuthFailed = errors.New("authentication failed")