probe/discovery/target/service/service-tcp.go
crusader 266ffdd674 ing
2018-09-01 22:09:33 +09:00

203 lines
4.6 KiB
Go

package service
import (
"fmt"
"net"
"time"
omd "git.loafle.net/overflow/model/discovery"
omu "git.loafle.net/overflow/model/util"
osm "git.loafle.net/overflow/service_matcher-go"
ouej "git.loafle.net/overflow/util-go/encoding/json"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/internal/matcher"
)
func scanTCP(discoverySession session.DiscoverySession, targetPort *omd.Port) error {
hostAddress := targetPort.Host.Address
portNumber, err := ouej.NumberToInt(targetPort.PortNumber)
if err != nil {
return fmt.Errorf("Service scan on %s:%s error has occurred %v ", hostAddress, targetPort.PortNumber, err)
}
info := osm.NewMatchInfo(hostAddress, portNumber)
connectors := newConnectors()
buf := make([]byte, 1024)
var discoveredMatcher osm.Matcher
var discoveredConnector connector
LOOP:
for _, _connector := range connectors {
conn, err := _connector.dial(targetPort)
if nil != err {
continue LOOP
}
if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err {
continue LOOP
}
n, err := conn.Read(buf)
if nil != err {
n = 0
}
if 0 < n {
discoveredMatcher = hadlePrePacket(info, _connector, conn, osm.NewPacket(buf, n))
} else {
conn.Close()
discoveredMatcher = hadlePostPacket(info, _connector, targetPort, nil)
}
if nil != discoveredMatcher {
if "HTTP" == discoveredMatcher.Key() {
hsm := matcher.GetHTTPSubMatchers()
if _discoveredMatcher := hadlePostPacket(info, _connector, targetPort, hsm); _discoveredMatcher != nil {
discoveredMatcher = _discoveredMatcher
}
}
discoveredConnector = _connector
break LOOP
}
}
if nil != discoveredMatcher {
// log.Printf("discovered matcher: %s(%s) %v", discoveredMatcher.Name(), discoveredMatcher.Key(), discoveredMatcher)
discoverySession.AddService(&omd.Service{
MetaCryptoType: discoveredConnector.metaCryptoType(),
Key: discoveredMatcher.Key(),
Name: discoveredMatcher.Name(),
Meta: discoveredMatcher.Meta(),
DiscoveredDate: omu.NowPtr(),
Port: targetPort,
})
}
return nil
}
func hadlePrePacket(info osm.MatchInfo, _connector connector, conn net.Conn, packet *osm.Packet) osm.Matcher {
defer func() {
conn.Close()
}()
matchers := matcher.GetTCPMatchers(true)
buf := make([]byte, 1024)
var discoveredMatcher osm.Matcher
LOOP:
for _, matcher := range matchers {
if err := matcher.Match(info, 0, packet); err != nil {
continue LOOP
}
packetCount := matcher.PacketCount()
if 0 == packetCount {
return matcher
}
INNER_LOOP:
for j := 0; j < packetCount; j++ {
_packet := matcher.Packet(j)
if err := conn.SetWriteDeadline(time.Now().Add(1 * time.Second)); nil != err {
return nil
}
_, err := conn.Write(_packet.Buffer)
if nil != err {
return nil
}
if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err {
return nil
}
n, err := conn.Read(buf)
if nil != err {
return nil
}
if err := matcher.Match(info, j+1, osm.NewPacket(buf, n)); nil == err {
discoveredMatcher = matcher
} else {
discoveredMatcher = nil
break INNER_LOOP
}
}
if nil != discoveredMatcher {
return discoveredMatcher
}
}
return nil
}
func hadlePostPacket(info osm.MatchInfo, _connector connector, targetPort *omd.Port, limitedMatchers []osm.Matcher) osm.Matcher {
matchers := matcher.GetTCPMatchers(false)
if nil != limitedMatchers {
matchers = limitedMatchers
}
buf := make([]byte, 1024)
var discoveredMatcher osm.Matcher
LOOP:
for _, matcher := range matchers {
packetCount := matcher.PacketCount()
if 0 == packetCount {
continue LOOP
}
conn, err := _connector.dial(targetPort)
if nil != err {
return nil
}
INNER_LOOP:
for j := 0; j < packetCount; j++ {
_packet := matcher.Packet(j)
if err := conn.SetWriteDeadline(time.Now().Add(1 * time.Second)); nil != err {
break INNER_LOOP
}
_, err := conn.Write(_packet.Buffer)
if nil != err {
break INNER_LOOP
}
if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err {
break INNER_LOOP
}
n, err := conn.Read(buf)
if nil != err {
if !matcher.HasResponse(j) {
discoveredMatcher = matcher
}
break INNER_LOOP
}
// log.Printf("res: %s", string(buf[:n]))
if err := matcher.Match(info, j+1, osm.NewPacket(buf, n)); err == nil {
if packetCount-1 == j {
discoveredMatcher = matcher
break INNER_LOOP
}
} else {
break INNER_LOOP
}
}
conn.Close()
if nil != discoveredMatcher {
return discoveredMatcher
}
}
return nil
}