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 meta osm.Metadata } func (ftp *FTPMatcher) Key() string { return "FTP" } func (ftp *FTPMatcher) Name() string { return "FTP" } func (ftp *FTPMatcher) Meta() osm.Metadata { return ftp.meta } func (ftp *FTPMatcher) IsPrePacket() bool { return true } func (ftp *FTPMatcher) HasResponse(index int) bool { return true } func (ftp *FTPMatcher) IsError(info osm.MatchInfo, index int, packet *osm.Packet) bool { return false } func (ftp *FTPMatcher) Match(info osm.MatchInfo, index int, packet *osm.Packet) error { if packet == nil || packet.Buffer == nil || packet.Len == 0 { return osm.NoPacketReceivedError() } str := strings.Split(string(packet.Buffer), "\r\n")[0] if len(str) < 4 { return osm.NotMatchedError() } code := str[:3] if index == 0 { switch code { case statusNewConnectOK, statusReadyServer: ftp.meta["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{} m.meta = osm.NewMetadata() quitStr := "QUIT\r\n" quitByte := make([]byte, len(quitStr)) copy(quitByte[:], quitStr) m.AddPacket(osm.NewPacket(quitByte, len(quitStr))) return m }