193 lines
5.5 KiB
Go
193 lines
5.5 KiB
Go
package ruleset_v2
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"ladder/proxychain"
|
|
"reflect"
|
|
"runtime"
|
|
"strings"
|
|
|
|
_ "gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Rule struct {
|
|
Domains []string
|
|
RequestModifications []proxychain.RequestModification
|
|
ResponseModifications []proxychain.ResponseModification
|
|
}
|
|
|
|
// implement type encoding/json/Marshaler
|
|
func (rule *Rule) UnmarshalJSON(data []byte) error {
|
|
type Aux struct {
|
|
Domains []string `json:"domains"`
|
|
RequestModifications []string `json:"request_modifications"`
|
|
ResponseModifications []string `json:"response_modifications"`
|
|
}
|
|
|
|
aux := &Aux{}
|
|
if err := json.Unmarshal(data, aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
//fmt.Println(aux.Domains)
|
|
rule.Domains = aux.Domains
|
|
|
|
// convert requestModification function call string into actual functional option
|
|
for _, rqmModStr := range aux.RequestModifications {
|
|
name, params, err := parseFuncCall(rqmModStr)
|
|
if err != nil {
|
|
return fmt.Errorf("Rule::UnmarshalJSON invalid function call syntax => '%s'", err)
|
|
}
|
|
f, exists := rqmModMap[name]
|
|
if !exists {
|
|
return fmt.Errorf("Rule::UnmarshalJSON => requestModifier '%s' does not exist, please check spelling", name)
|
|
}
|
|
rule.RequestModifications = append(rule.RequestModifications, f(params...))
|
|
}
|
|
|
|
// convert responseModification function call string into actual functional option
|
|
for _, rsmModStr := range aux.ResponseModifications {
|
|
name, params, err := parseFuncCall(rsmModStr)
|
|
if err != nil {
|
|
return fmt.Errorf("Rule::UnmarshalJSON invalid function call syntax => '%s'", err)
|
|
}
|
|
f, exists := rsmModMap[name]
|
|
if !exists {
|
|
return fmt.Errorf("Rule::UnmarshalJSON => responseModifier '%s' does not exist, please check spelling", name)
|
|
}
|
|
rule.ResponseModifications = append(rule.ResponseModifications, f(params...))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// not fully possible to go from rule to JSON rule because
|
|
// reflection cannot get the parameters of the functional options
|
|
// of requestmodifiers and responsemodifiers
|
|
func (r *Rule) MarshalJSON() ([]byte, error) {
|
|
type Aux struct {
|
|
Domains []string `json:"domains"`
|
|
RequestModifications []string `json:"request_modifications"`
|
|
ResponseModifications []string `json:"response_modifications"`
|
|
}
|
|
aux := &Aux{}
|
|
aux.Domains = r.Domains
|
|
|
|
for _, rqmMod := range r.RequestModifications {
|
|
fnName := getFunctionName(rqmMod)
|
|
aux.RequestModifications = append(aux.RequestModifications, fnName)
|
|
}
|
|
|
|
for _, rsmMod := range r.ResponseModifications {
|
|
fnName := getFunctionName(rsmMod)
|
|
aux.ResponseModifications = append(aux.ResponseModifications, fnName)
|
|
}
|
|
|
|
return json.Marshal(aux)
|
|
}
|
|
|
|
// getFunctionName returns the name of the function
|
|
func getFunctionName(i interface{}) string {
|
|
// Get the value of the interface
|
|
val := reflect.ValueOf(i)
|
|
|
|
// Ensure it's a function
|
|
if val.Kind() != reflect.Func {
|
|
return "Not a function"
|
|
}
|
|
|
|
// Get the pointer to the function
|
|
ptr := val.Pointer()
|
|
|
|
// Get the function details from runtime
|
|
funcForPc := runtime.FuncForPC(ptr)
|
|
|
|
if funcForPc == nil {
|
|
return "Unknown"
|
|
}
|
|
|
|
// Return the name of the function
|
|
return extractShortName(funcForPc.Name())
|
|
}
|
|
|
|
// extractShortName extracts the short function name from the full name
|
|
func extractShortName(fullName string) string {
|
|
parts := strings.Split(fullName, ".")
|
|
if len(parts) > 0 {
|
|
// Assuming the function name is always the second last part
|
|
return parts[len(parts)-2]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// == YAML
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface for Rule
|
|
func (rule *Rule) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
type Aux struct {
|
|
Domains []string `yaml:"domains"`
|
|
RequestModifications []string `yaml:"request_modifications"`
|
|
ResponseModifications []string `yaml:"response_modifications"`
|
|
}
|
|
|
|
aux := &Aux{}
|
|
if err := unmarshal(aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
rule.Domains = aux.Domains
|
|
|
|
// Process requestModifications
|
|
for _, rqmModStr := range aux.RequestModifications {
|
|
name, params, err := parseFuncCall(rqmModStr)
|
|
if err != nil {
|
|
return fmt.Errorf("Rule::UnmarshalYAML invalid function call syntax => '%s'", err)
|
|
}
|
|
f, exists := rqmModMap[name]
|
|
if !exists {
|
|
return fmt.Errorf("Rule::UnmarshalYAML => requestModifier '%s' does not exist, please check spelling", name)
|
|
}
|
|
rule.RequestModifications = append(rule.RequestModifications, f(params...))
|
|
}
|
|
|
|
// Process responseModifications
|
|
for _, rsmModStr := range aux.ResponseModifications {
|
|
name, params, err := parseFuncCall(rsmModStr)
|
|
if err != nil {
|
|
return fmt.Errorf("Rule::UnmarshalYAML invalid function call syntax => '%s'", err)
|
|
}
|
|
f, exists := rsmModMap[name]
|
|
if !exists {
|
|
return fmt.Errorf("Rule::UnmarshalYAML => responseModifier '%s' does not exist, please check spelling", name)
|
|
}
|
|
rule.ResponseModifications = append(rule.ResponseModifications, f(params...))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Rule) MarshalYAML() (interface{}, error) {
|
|
type Aux struct {
|
|
Domains []string `yaml:"domains"`
|
|
RequestModifications []string `yaml:"request_modifications"`
|
|
ResponseModifications []string `yaml:"response_modifications"`
|
|
}
|
|
|
|
aux := &Aux{
|
|
Domains: r.Domains,
|
|
}
|
|
|
|
for _, rqmMod := range r.RequestModifications {
|
|
// Assuming getFunctionName returns a string representation of the function
|
|
fnName := getFunctionName(rqmMod)
|
|
aux.RequestModifications = append(aux.RequestModifications, fnName)
|
|
}
|
|
|
|
for _, rsmMod := range r.ResponseModifications {
|
|
fnName := getFunctionName(rsmMod)
|
|
aux.ResponseModifications = append(aux.ResponseModifications, fnName)
|
|
}
|
|
|
|
return aux, nil
|
|
}
|