feat(tls): add support for RDP negotiation before TLS handshake
This commit is contained in:
+29
-16
@@ -51,9 +51,10 @@ type tlsHello struct {
|
||||
msg utils.ByteBuffer // handshake layer bytes collected so far
|
||||
lsm *utils.LinearStateMachine
|
||||
|
||||
msgType byte
|
||||
minLen int // smallest valid message body
|
||||
parse func(*utils.ByteBuffer) analyzer.PropMap // parses the message body
|
||||
msgType byte
|
||||
x224Code byte // X.224 connection PDU that may precede the hello on RDP
|
||||
minLen int // smallest valid message body
|
||||
parse func(*utils.ByteBuffer) analyzer.PropMap // parses the message body
|
||||
|
||||
recLeft int // body bytes of the current record not consumed yet
|
||||
msgLen int // message body length, -1 until the handshake header is read
|
||||
@@ -63,6 +64,9 @@ type tlsHello struct {
|
||||
m analyzer.PropMap
|
||||
updated bool
|
||||
done bool
|
||||
|
||||
rdp analyzer.PropMap // RDP negotiation, nil if there was none
|
||||
rdpUpdated bool
|
||||
}
|
||||
|
||||
func newTLSStream(logger analyzer.Logger) *tlsStream {
|
||||
@@ -70,18 +74,18 @@ func newTLSStream(logger analyzer.Logger) *tlsStream {
|
||||
// minimal ClientHello body: protocol version (2 bytes) + random (32 bytes) +
|
||||
// + session ID (1 byte) + cipher suites (4 bytes) +
|
||||
// + compression methods (2 bytes) + no extensions
|
||||
s.req.init(internal.TypeClientHello, 41, internal.ParseTLSClientHelloMsgData)
|
||||
s.req.init(internal.TypeClientHello, x224CodeConnectionRequest, 41, internal.ParseTLSClientHelloMsgData)
|
||||
// minimal ServerHello body: server version (2 bytes) + random (32 bytes) +
|
||||
// + session ID (>=1 byte) + cipher suite (2 bytes) +
|
||||
// + compression method (1 byte) + no extensions
|
||||
s.resp.init(internal.TypeServerHello, 38, internal.ParseTLSServerHelloMsgData)
|
||||
s.resp.init(internal.TypeServerHello, x224CodeConnectionConfirm, 38, internal.ParseTLSServerHelloMsgData)
|
||||
return s
|
||||
}
|
||||
|
||||
func (h *tlsHello) init(msgType byte, minLen int, parse func(*utils.ByteBuffer) analyzer.PropMap) {
|
||||
h.msgType, h.minLen, h.parse = msgType, minLen, parse
|
||||
func (h *tlsHello) init(msgType, x224Code byte, minLen int, parse func(*utils.ByteBuffer) analyzer.PropMap) {
|
||||
h.msgType, h.x224Code, h.minLen, h.parse = msgType, x224Code, minLen, parse
|
||||
h.msgLen = -1
|
||||
h.lsm = utils.NewLinearStateMachine(h.readMessage, h.parseMessage)
|
||||
h.lsm = utils.NewLinearStateMachine(h.readPrelude, h.readMessage, h.parseMessage)
|
||||
}
|
||||
|
||||
func (s *tlsStream) Feed(rev, start, end bool, skip int, data []byte) (u *analyzer.PropUpdate, done bool) {
|
||||
@@ -114,17 +118,26 @@ func (s *tlsStream) Feed(rev, start, end bool, skip int, data []byte) (u *analyz
|
||||
// update returns the properties to publish for this direction, or nil if
|
||||
// there is nothing to publish. The parsed message goes under key, the record
|
||||
// count under key + "_records". The record count is kept out of the message
|
||||
// map so that a non-nil message map still means a fully parsed hello.
|
||||
// map so that a non-nil message map still means a fully parsed hello. An RDP
|
||||
// negotiation goes under "rdp_" + key as soon as it is parsed, whatever
|
||||
// publish says.
|
||||
func (h *tlsHello) update(key string, publish bool) analyzer.PropMap {
|
||||
if !publish || h.records == 0 {
|
||||
m := analyzer.PropMap{}
|
||||
if h.rdpUpdated {
|
||||
m["rdp_"+key] = h.rdp
|
||||
h.rdpUpdated = false
|
||||
}
|
||||
if publish && h.records > 0 {
|
||||
m[key+"_records"] = h.records
|
||||
if h.updated {
|
||||
m[key] = h.m
|
||||
h.updated = false
|
||||
}
|
||||
h.reported = h.records
|
||||
}
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
m := analyzer.PropMap{key + "_records": h.records}
|
||||
if h.updated {
|
||||
m[key] = h.m
|
||||
h.updated = false
|
||||
}
|
||||
h.reported = h.records
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user