-
Notifications
You must be signed in to change notification settings - Fork 46
/
parser.go
103 lines (98 loc) · 2.56 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package rule
import (
"bufio"
"github.com/antlr/antlr4/runtime/Go/antlr/v4"
"github.com/yaklang/yaklang/common/log"
rule "github.com/yaklang/yaklang/common/suricata/parser"
"github.com/yaklang/yaklang/common/utils"
"reflect"
"strings"
)
var presetEnv = map[string]string{
"HOME_NET": utils.GetLocalIPAddress(),
}
func Parse(data string, envs ...string) ([]*Rule, error) {
var buf strings.Builder
var dataBuf = bufio.NewReader(strings.NewReader(data))
for {
line, err := utils.BufioReadLineString(dataBuf)
if err != nil {
break
}
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "#") || strings.HasPrefix(line, "//") || line == "" {
buf.WriteByte('\n')
continue
}
buf.WriteString(line)
buf.WriteByte('\n')
}
compileRaw := buf.String()
lexer := rule.NewSuricataRuleLexer(antlr.NewInputStream(compileRaw))
tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
parser := rule.NewSuricataRuleParser(tokenStream)
parser.RemoveErrorListeners()
//for _, t := range lexer.GetAllTokens() {
// fmt.Println(t)
//}
v := &RuleSyntaxVisitor{Raw: []byte(data), CompileRaw: compileRaw}
v.Environment = make(map[string]string)
for k, val := range presetEnv {
v.Environment[k] = val
}
for _, e := range envs {
before, after, cut := strings.Cut(e, "=")
if !cut {
log.Warnf("env input:[%v] cannot parse as key=value", e)
continue
}
v.Environment[before] = after
}
v.VisitRules(parser.Rules().(*rule.RulesContext))
for _, r := range v.Rules {
ParseRuleMetadata(r)
}
if len(v.Rules) > 0 {
return v.Rules, nil
} else {
return nil, v.MergeErrors()
}
}
func ParseRuleMetadata(rule *Rule) {
defer func() {
if err := recover(); err != nil {
log.Errorf("parse rule metadata failed: %s", err)
}
}()
if rule == nil {
return
}
for _, meta := range rule.Metadata {
for _, item := range strings.Split(meta, ",") {
info := strings.Split(strings.TrimSpace(item), " ")
if len(info) != 2 {
continue
}
t := reflect.TypeOf(rule).Elem()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("json")
if tag == info[0] {
if info[0] == "CVE" {
info[1] = strings.Replace(info[1], "_", "-", -1)
}
if info[0] == "updated_at" {
info[1] = strings.Replace(info[1], "_", "-", -1)
}
if info[0] == "created_at" {
info[1] = strings.Replace(info[1], "_", "-", -1)
}
if info[0] == "reviewed_at" {
info[1] = strings.Replace(info[1], "_", "-", -1)
}
reflect.ValueOf(rule).Elem().Field(i).SetString(info[1])
}
}
}
}
}