service_matcher-go/redis/redis.go

193 lines
3.8 KiB
Go
Raw Normal View History

2018-08-13 07:48:32 +00:00
package redis
import (
"bufio"
2018-09-03 13:52:01 +00:00
"strconv"
2018-08-13 07:48:32 +00:00
"strings"
2018-08-15 07:17:18 +00:00
osm "git.loafle.net/overflow/service_matcher-go"
2018-08-13 07:48:32 +00:00
)
const REDIS_PING string = "*1\r\n$4\r\nPING\r\n"
const REDIS_INFO string = "*1\r\n$4\r\nINFO\r\n"
const REDIS_QUIT string = "*1\r\n$4\r\nQUIT\r\n"
type RedisMatcher struct {
2018-08-15 07:17:18 +00:00
osm.Matchers
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) Key() string {
2018-08-13 07:48:32 +00:00
return "REDIS"
}
2018-09-12 04:26:27 +00:00
func (m *RedisMatcher) Type() string {
return "NOSQL"
}
2018-09-12 04:52:58 +00:00
func (m *RedisMatcher) Vendor(matchCtx *osm.MatchCtx) string {
return "Redis"
}
func (m *RedisMatcher) Version(matchCtx *osm.MatchCtx) string {
return "UNKNOWN"
}
func (m *RedisMatcher) OsType(matchCtx *osm.MatchCtx) string {
return "UNKNOWN"
}
func (m *RedisMatcher) OsVersion(matchCtx *osm.MatchCtx) string {
return "UNKNOWN"
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) Name(matchCtx *osm.MatchCtx) string {
2018-08-13 07:48:32 +00:00
name := "Redis"
2018-09-03 13:36:57 +00:00
if v, ok := matchCtx.GetAttribute("protected"); ok {
2018-09-03 13:52:01 +00:00
if _v, _err := strconv.ParseBool(v); nil != _err && _v {
2018-09-03 13:36:57 +00:00
return name + " (protected)"
}
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:36:57 +00:00
if v, ok := matchCtx.GetAttribute("redis_mode"); ok {
2018-09-03 13:52:01 +00:00
name = name + " " + v
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:36:57 +00:00
if v, ok := matchCtx.GetAttribute("redis_version"); ok {
2018-09-03 13:52:01 +00:00
name = name + " (" + v + ")"
2018-08-13 07:48:32 +00:00
}
return name
}
2018-09-03 13:41:28 +00:00
func (m *RedisMatcher) IsPrePacket() bool {
2018-08-13 07:48:32 +00:00
return false
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) HasResponse(matchCtx *osm.MatchCtx, index int) bool {
2018-08-13 07:48:32 +00:00
return true
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) IsError(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) bool {
2018-08-13 07:48:32 +00:00
return false
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) Match(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) error {
2018-08-13 07:48:32 +00:00
2018-09-03 06:42:56 +00:00
if packet == nil || !packet.Valid() {
2018-08-15 07:17:18 +00:00
return osm.NoPacketReceivedError()
2018-08-13 07:48:32 +00:00
}
2018-09-03 06:42:56 +00:00
resp := strings.Split(string(packet.Bytes()), "\r\n")[0]
2018-08-13 07:48:32 +00:00
if len(resp) <= 0 {
2018-08-15 07:17:18 +00:00
return osm.NotMatchedError()
2018-08-13 07:48:32 +00:00
}
switch index {
case 0:
sign := string([]rune(resp)[0])
if len(sign) <= 0 {
2018-08-15 07:17:18 +00:00
return osm.NotMatchedError()
2018-08-13 07:48:32 +00:00
}
if sign == "+" {
if resp == "+PONG" || resp == "+OK" {
return nil
}
}
if sign == "-" {
if resp == "-NOAUTH" || resp == "-ERR" {
return nil
}
}
2018-09-03 13:36:57 +00:00
protected := m.checkProtectedMode(packet)
2018-09-03 13:52:01 +00:00
matchCtx.SetAttribute("protected", strconv.FormatBool(protected))
2018-09-03 13:36:57 +00:00
if protected {
2018-08-13 07:48:32 +00:00
return nil
}
case 1: // INFO
2018-09-03 13:36:57 +00:00
response := string(packet.Bytes())
2018-08-13 07:48:32 +00:00
2018-09-03 13:36:57 +00:00
if v, ok := matchCtx.GetAttribute("protected"); ok {
2018-09-03 13:52:01 +00:00
if _v, _err := strconv.ParseBool(v); nil != _err && _v {
2018-09-03 13:36:57 +00:00
m.parseResponse(matchCtx, response)
}
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:52:01 +00:00
2018-08-13 07:48:32 +00:00
return nil
case 2:
sign := string([]rune(resp)[0])
if sign == "+" || sign == "-" {
return nil
}
return nil
default:
2018-08-15 07:17:18 +00:00
return osm.NotMatchedError()
2018-08-13 07:48:32 +00:00
}
2018-08-15 07:17:18 +00:00
return osm.NotMatchedError()
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) checkProtectedMode(packet *osm.Packet) bool {
2018-08-13 07:48:32 +00:00
var (
compareSign = "-"
compareMsg = "DENIED"
)
2018-09-03 06:42:56 +00:00
str := string(packet.Bytes())
2018-08-13 07:48:32 +00:00
if str == "" {
return false
}
if 0 >= len(str) || len(compareMsg)+2 > len(str) {
return false
}
firstCompare := str[0:1]
seconcdCompare := str[1 : len(compareMsg)+1]
if firstCompare != compareSign {
return false
}
if seconcdCompare != compareMsg {
return false
}
return true
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) parseResponse(matchCtx *osm.MatchCtx, response string) {
scanner := bufio.NewScanner(strings.NewReader(response))
2018-08-13 07:48:32 +00:00
for scanner.Scan() {
line := scanner.Text()
if strings.Compare(line, "") == 0 {
break
}
if len(line) > 0 && strings.Contains(line, ":") {
kv := strings.Split(line, ":")
if len(kv[0]) > 0 && len(kv[1]) > 0 {
2018-09-03 13:36:57 +00:00
matchCtx.SetAttribute(kv[0], kv[1])
2018-08-13 07:48:32 +00:00
}
}
}
}
2018-09-03 13:36:57 +00:00
func (m *RedisMatcher) PacketCount(matchCtx *osm.MatchCtx) int {
if v, ok := matchCtx.GetAttribute("protected"); ok {
2018-09-03 13:52:01 +00:00
if _v, _err := strconv.ParseBool(v); nil != _err && _v {
2018-09-03 13:36:57 +00:00
return 1
}
2018-08-13 07:48:32 +00:00
}
2018-09-03 13:36:57 +00:00
2018-08-13 07:48:32 +00:00
return 3
}
2018-08-15 07:17:18 +00:00
func NewMatcher() osm.Matcher {
2018-08-13 07:48:32 +00:00
m := &RedisMatcher{}
2018-08-15 07:17:18 +00:00
m.AddPacket(osm.NewPacket([]byte(REDIS_PING), len(REDIS_PING)))
m.AddPacket(osm.NewPacket([]byte(REDIS_INFO), len(REDIS_INFO)))
m.AddPacket(osm.NewPacket([]byte(REDIS_QUIT), len(REDIS_QUIT)))
2018-08-13 07:48:32 +00:00
return m
}