package ftp import ( "git.loafle.net/overflow/overflow_discovery/match/packet" "git.loafle.net/overflow/overflow_discovery/model/scaninfo" log "github.com/cihub/seelog" ) // FTP Status codes, defined in RFC 959 const ( statusReadyServer = "120" statusOK = "200" statusNewConnectOK = "220" statusSystemNameOK = "215" statusCloseConnect = "221" statusUnkownCMD = "202" statusTlsUseOK = "234" statusCloseControlConnect = "421" statusSyntaxErr = "500" statusParamSyntaxErr = "501" statusNotUseCMD = "502" statusIncorrectCMD = "503" statusTlsNotUse = "534" statusNeedUserId = "332" ) type FTPMatcher struct { sendPackets []*packet.Packet isFtps bool } func (ftp *FTPMatcher) Match(index int, packet *packet.Packet, info scaninfo.ServiceScanInfo) bool { result := false if packet == nil || packet.Buffer == nil || packet.Len == 0 { log.Error("Packet nil") return result } str := string(packet.Buffer) //fmt.Println(str) code := str[:3] if index == 0 { switch code { case statusNewConnectOK, statusReadyServer: //fmt.Println(code) result = true break } } else if index == 1 { switch code { case statusSystemNameOK, statusSyntaxErr, statusParamSyntaxErr, statusNotUseCMD: //fmt.Println(code) result = true break } } else if index == 2 { switch code { case statusIncorrectCMD, statusParamSyntaxErr, statusNotUseCMD, statusNeedUserId: //fmt.Println(code) result = true break } } else if index == 3 { switch code { case statusCloseConnect, statusSyntaxErr: //fmt.Println(code) result = true break } } if index == 3 && result == true { var err error var isfs bool //fmt.Println(info.Port.Host.Ip, info.Port.Port) isfs, err = StartCheckFTPS(info.GetIP(), info.GetPort()) if isfs && err == nil { ftp.isFtps = isfs } else if err != nil { log.Warn("FTPS Check Error : ", err.Error()) } } return result } func (ftp *FTPMatcher) PacketCount() int { return len(ftp.sendPackets) } func (ftp *FTPMatcher) Packet(index int) *packet.Packet { return ftp.sendPackets[index] } func (ftp *FTPMatcher) ServiceName() string { re := "" if ftp.isFtps { re = "FTPS" } else { re = "FTP" } return re } func (ftp *FTPMatcher) IsError(index int, packet *packet.Packet, info scaninfo.ServiceScanInfo) bool { return false } func (ftp *FTPMatcher) HasResponse(index int) bool { return false } func (ftp *FTPMatcher) IsPrePacket() bool { return true } func NewFTPMatcher() *FTPMatcher { ftm := FTPMatcher{} sysStr := "SYST\r\n" systByte := make([]byte, len(sysStr)) copy(systByte[:], sysStr) ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(systByte, len(sysStr))) passStr := "PASS \r\n" passByte := make([]byte, len(passStr)) copy(passByte[:], passStr) ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(passByte, len(passStr))) quitStr := "QUIT\r\n" quitByte := make([]byte, len(quitStr)) copy(quitByte[:], quitStr) ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(quitByte, len(quitStr))) return &ftm }