285 lines
6.1 KiB
Go
285 lines
6.1 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
omd "git.loafle.net/overflow/model/discovery"
|
|
omm "git.loafle.net/overflow/model/meta"
|
|
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"
|
|
)
|
|
|
|
const (
|
|
deadline = time.Millisecond * 1000
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
var limitedMatchers []osm.Matcher
|
|
matchCtx := osm.NewMatchCtx(hostAddress, portNumber)
|
|
|
|
if omm.MetaHostTypeEnumPrinter.String() == targetPort.Host.HostType {
|
|
switch portNumber {
|
|
// case 7:
|
|
// return nil
|
|
case 515:
|
|
limitedMatchers = []osm.Matcher{
|
|
matcher.GetMatcherByKey(matchCtx, "LPD"),
|
|
}
|
|
case 8290:
|
|
discoverySession.AddServiceUnknown(
|
|
omm.ToMetaDiscovererType(omm.MetaDiscovererTypeEnumTCPMatcher),
|
|
targetPort,
|
|
)
|
|
return nil
|
|
case 9100:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
connectors := newConnectors()
|
|
stopChan := make(chan struct{})
|
|
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(deadline)); nil != err {
|
|
continue LOOP
|
|
}
|
|
n, err := conn.Read(buf)
|
|
if nil != err {
|
|
n = 0
|
|
}
|
|
|
|
if 0 < n {
|
|
discoveredMatcher = hadlePrePacket(matchCtx, _connector, conn, osm.NewPacket(buf, n), limitedMatchers, stopChan)
|
|
} else {
|
|
conn.Close()
|
|
discoveredMatcher = hadlePostPacket(matchCtx, _connector, targetPort, limitedMatchers, stopChan)
|
|
}
|
|
|
|
if nil != discoveredMatcher {
|
|
if "HTTP" == discoveredMatcher.Key(matchCtx) {
|
|
hsm := matcher.GetHTTPSubMatchers()
|
|
if _discoveredMatcher := hadlePostPacket(matchCtx, _connector, targetPort, hsm, stopChan); _discoveredMatcher != nil {
|
|
discoveredMatcher = _discoveredMatcher
|
|
}
|
|
}
|
|
discoveredConnector = _connector
|
|
|
|
break LOOP
|
|
}
|
|
|
|
select {
|
|
case <-discoverySession.StopChan():
|
|
return nil
|
|
default:
|
|
}
|
|
}
|
|
|
|
if nil != discoveredMatcher {
|
|
s := omd.NewService(
|
|
targetPort,
|
|
discoveredConnector.metaCryptoType(),
|
|
discoveredMatcher.Key(matchCtx),
|
|
)
|
|
s.Name = discoveredMatcher.Name(matchCtx)
|
|
s.ServiceType = discoveredMatcher.Type(matchCtx)
|
|
s.ServiceVendor = discoveredMatcher.Vendor(matchCtx)
|
|
s.ServiceVersion = discoveredMatcher.Version(matchCtx)
|
|
s.DiscoveredDate = omu.NowPtr()
|
|
|
|
discoverySession.AddService(
|
|
omm.ToMetaDiscovererType(omm.MetaDiscovererTypeEnumTCPMatcher),
|
|
s,
|
|
matchCtx.GetAttributes(),
|
|
)
|
|
} else {
|
|
discoverySession.AddServiceUnknown(
|
|
omm.ToMetaDiscovererType(omm.MetaDiscovererTypeEnumTCPMatcher),
|
|
targetPort,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func hadlePrePacket(matchCtx *osm.MatchCtx, _connector connector, conn net.Conn, packet *osm.Packet, limitedMatchers []osm.Matcher, stopChan <-chan struct{}) osm.Matcher {
|
|
defer func() {
|
|
conn.Close()
|
|
}()
|
|
|
|
matchers := matcher.GetTCPMatchers(true)
|
|
if nil != limitedMatchers {
|
|
matchers = limitedMatchers
|
|
}
|
|
|
|
buf := make([]byte, 1024)
|
|
var (
|
|
discoveredMatcher osm.Matcher
|
|
packetCount int
|
|
_packet *osm.Packet
|
|
err error
|
|
nRead int
|
|
)
|
|
|
|
LOOP:
|
|
for _, _matcher := range matchers {
|
|
matchCtx.InitAttribute()
|
|
err = _matcher.Match(matchCtx, 0, packet)
|
|
if nil != err {
|
|
continue LOOP
|
|
}
|
|
|
|
packetCount = _matcher.PacketCount(matchCtx)
|
|
|
|
if 0 == packetCount {
|
|
return _matcher
|
|
}
|
|
|
|
INNER_LOOP:
|
|
for j := 0; j < packetCount; j++ {
|
|
_packet = _matcher.Packet(matchCtx, j)
|
|
|
|
err = conn.SetWriteDeadline(time.Now().Add(deadline))
|
|
if nil != err {
|
|
return nil
|
|
}
|
|
_, err = conn.Write(_packet.Buffer)
|
|
if nil != err {
|
|
return nil
|
|
}
|
|
|
|
err = conn.SetReadDeadline(time.Now().Add(deadline))
|
|
if nil != err {
|
|
return nil
|
|
}
|
|
nRead, err = conn.Read(buf)
|
|
if nil != err {
|
|
return nil
|
|
}
|
|
|
|
err = _matcher.Match(matchCtx, j+1, osm.NewPacket(buf, nRead))
|
|
if nil == err {
|
|
discoveredMatcher = _matcher
|
|
} else {
|
|
discoveredMatcher = nil
|
|
break INNER_LOOP
|
|
}
|
|
}
|
|
|
|
if nil != discoveredMatcher {
|
|
return discoveredMatcher
|
|
}
|
|
|
|
select {
|
|
case <-stopChan:
|
|
return nil
|
|
default:
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func hadlePostPacket(matchCtx *osm.MatchCtx, _connector connector, targetPort *omd.Port, limitedMatchers []osm.Matcher, stopChan <-chan struct{}) osm.Matcher {
|
|
matchers := matcher.GetTCPMatchers(false)
|
|
if nil != limitedMatchers {
|
|
matchers = limitedMatchers
|
|
}
|
|
|
|
buf := make([]byte, 1024)
|
|
var (
|
|
discoveredMatcher osm.Matcher
|
|
packetCount int
|
|
_packet *osm.Packet
|
|
err error
|
|
conn net.Conn
|
|
nRead int
|
|
)
|
|
|
|
LOOP:
|
|
for _, _matcher := range matchers {
|
|
matchCtx.InitAttribute()
|
|
packetCount = _matcher.PacketCount(matchCtx)
|
|
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(matchCtx, j)
|
|
|
|
err = conn.SetWriteDeadline(time.Now().Add(deadline))
|
|
if nil != err {
|
|
break INNER_LOOP
|
|
}
|
|
_, err = conn.Write(_packet.Buffer)
|
|
if nil != err {
|
|
break INNER_LOOP
|
|
}
|
|
|
|
err = conn.SetReadDeadline(time.Now().Add(deadline))
|
|
if nil != err {
|
|
break INNER_LOOP
|
|
}
|
|
nRead, err = conn.Read(buf)
|
|
if nil != err {
|
|
// if !_matcher.HasResponse(matchCtx, j) {
|
|
// discoveredMatcher = _matcher
|
|
// }
|
|
break INNER_LOOP
|
|
}
|
|
|
|
// log.Printf("res: %s", string(buf[:n]))
|
|
|
|
err = _matcher.Match(matchCtx, j, osm.NewPacket(buf, nRead))
|
|
if err == nil {
|
|
if packetCount-1 == j {
|
|
discoveredMatcher = _matcher
|
|
|
|
break INNER_LOOP
|
|
}
|
|
} else {
|
|
break INNER_LOOP
|
|
}
|
|
}
|
|
|
|
conn.Close()
|
|
if nil != discoveredMatcher {
|
|
return discoveredMatcher
|
|
}
|
|
|
|
select {
|
|
case <-stopChan:
|
|
return nil
|
|
default:
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|