package ftp import ( "strings" osm "git.loafle.net/overflow/service_matcher-go" ) // 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" statusNotLoggedIn = "530" statusTlsNotUse = "534" statusNeedUserId = "332" ) type FTPMatcher struct { osm.Matchers } func (m *FTPMatcher) Key() string { return "FTP" } func (m *FTPMatcher) Name(matchCtx *osm.MatchCtx) string { return "FTP" } func (m *FTPMatcher) IsPrePacket() bool { return true } func (m *FTPMatcher) HasResponse(matchCtx *osm.MatchCtx, index int) bool { return true } func (m *FTPMatcher) IsError(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) bool { return false } func (m *FTPMatcher) Match(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) error { if packet == nil || !packet.Valid() { return osm.NoPacketReceivedError() } str := strings.Split(string(packet.Bytes()), "\r\n")[0] if len(str) < 4 { return osm.NotMatchedError() } code := str[:3] if index == 0 { switch code { case statusNewConnectOK, statusReadyServer: matchCtx.SetAttribute("comment", str[4:]) return nil } } else if index == 1 { switch code { case statusCloseConnect, statusSyntaxErr: return nil } } return osm.NotMatchedError() } func NewMatcher() osm.Matcher { m := &FTPMatcher{} quitStr := "QUIT\r\n" quitByte := make([]byte, len(quitStr)) copy(quitByte[:], quitStr) m.AddPacket(osm.NewPacket(quitByte, len(quitStr))) return m }