2018-04-02 05:25:32 +02:00
|
|
|
package rule
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2020-12-09 18:18:42 +01:00
|
|
|
"github.com/evilsocket/opensnitch/daemon/conman"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/ui/protocol"
|
2018-04-02 05:25:32 +02:00
|
|
|
)
|
|
|
|
|
2024-05-29 23:43:46 +02:00
|
|
|
// DefaultPath directory
|
|
|
|
const (
|
|
|
|
DefaultPath = "/etc/opensnitchd/rules"
|
|
|
|
)
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Action of a rule
|
2018-04-02 05:25:32 +02:00
|
|
|
type Action string
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Actions of rules
|
2018-04-02 05:25:32 +02:00
|
|
|
const (
|
2021-09-12 10:54:24 +02:00
|
|
|
Allow = Action("allow")
|
|
|
|
Deny = Action("deny")
|
|
|
|
Reject = Action("reject")
|
2018-04-02 05:25:32 +02:00
|
|
|
)
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Duration of a rule
|
2018-04-02 05:25:32 +02:00
|
|
|
type Duration string
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// daemon possible durations
|
2018-04-02 05:25:32 +02:00
|
|
|
const (
|
|
|
|
Once = Duration("once")
|
|
|
|
Restart = Duration("until restart")
|
|
|
|
Always = Duration("always")
|
|
|
|
)
|
|
|
|
|
2020-05-10 17:17:05 +02:00
|
|
|
// Rule represents an action on a connection.
|
|
|
|
// The fields match the ones saved as json to disk.
|
|
|
|
// If a .json rule file is modified on disk, it's reloaded automatically.
|
2018-04-02 05:25:32 +02:00
|
|
|
type Rule struct {
|
2024-06-10 23:54:54 +02:00
|
|
|
// Save date fields as string, to avoid issues marshalling Time (#1140).
|
|
|
|
Created string `json:"created"`
|
|
|
|
Updated string `json:"updated"`
|
|
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
Description string `json:"description"`
|
|
|
|
Action Action `json:"action"`
|
|
|
|
Duration Duration `json:"duration"`
|
|
|
|
Operator Operator `json:"operator"`
|
|
|
|
Enabled bool `json:"enabled"`
|
|
|
|
Precedence bool `json:"precedence"`
|
|
|
|
Nolog bool `json:"nolog"`
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
|
2020-05-10 17:17:05 +02:00
|
|
|
// Create creates a new rule object with the specified parameters.
|
2022-07-04 11:14:26 +02:00
|
|
|
func Create(name, description string, enabled, precedence, nolog bool, action Action, duration Duration, op *Operator) *Rule {
|
2018-04-02 05:25:32 +02:00
|
|
|
return &Rule{
|
2024-06-10 23:54:54 +02:00
|
|
|
Created: time.Now().Format(time.RFC3339),
|
2022-05-12 13:38:23 +02:00
|
|
|
Enabled: enabled,
|
|
|
|
Precedence: precedence,
|
2022-07-04 11:14:26 +02:00
|
|
|
Nolog: nolog,
|
2022-05-12 13:38:23 +02:00
|
|
|
Name: name,
|
|
|
|
Description: description,
|
|
|
|
Action: action,
|
|
|
|
Duration: duration,
|
|
|
|
Operator: *op,
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Rule) String() string {
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
enabled := "Disabled"
|
|
|
|
if r.Enabled {
|
|
|
|
enabled = "Enabled"
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("[%s] %s: if(%s){ %s %s }", enabled, r.Name, r.Operator.String(), r.Action, r.Duration)
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Match performs on a connection the checks a Rule has, to determine if it
|
|
|
|
// must be allowed or denied.
|
2023-09-22 00:36:26 +02:00
|
|
|
func (r *Rule) Match(con *conman.Connection, hasChecksums bool) bool {
|
|
|
|
return r.Operator.Match(con, hasChecksums)
|
2018-04-02 05:25:32 +02:00
|
|
|
}
|
2018-04-08 15:32:20 +02:00
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Deserialize translates back the rule received to a Rule object
|
2020-06-19 18:02:09 +02:00
|
|
|
func Deserialize(reply *protocol.Rule) (*Rule, error) {
|
2020-05-10 17:17:05 +02:00
|
|
|
if reply.Operator == nil {
|
2020-06-19 18:02:09 +02:00
|
|
|
log.Warning("Deserialize rule, Operator nil")
|
|
|
|
return nil, fmt.Errorf("invalid operator")
|
2020-05-10 17:17:05 +02:00
|
|
|
}
|
2020-06-19 18:02:09 +02:00
|
|
|
operator, err := NewOperator(
|
2018-04-08 15:32:20 +02:00
|
|
|
Type(reply.Operator.Type),
|
2020-10-23 00:02:16 +02:00
|
|
|
Sensitive(reply.Operator.Sensitive),
|
2018-04-08 15:32:20 +02:00
|
|
|
Operand(reply.Operator.Operand),
|
2018-11-20 21:21:36 +01:00
|
|
|
reply.Operator.Data,
|
|
|
|
make([]Operator, 0),
|
|
|
|
)
|
2020-06-19 18:02:09 +02:00
|
|
|
if err != nil {
|
2020-12-19 19:31:09 +01:00
|
|
|
log.Warning("Deserialize rule, NewOperator() error: %s", err)
|
2020-06-19 18:02:09 +02:00
|
|
|
return nil, err
|
2020-02-14 23:15:14 +01:00
|
|
|
}
|
2018-04-08 15:32:20 +02:00
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
newRule := Create(
|
2018-04-08 15:32:20 +02:00
|
|
|
reply.Name,
|
2022-05-12 13:38:23 +02:00
|
|
|
reply.Description,
|
2020-05-10 17:17:05 +02:00
|
|
|
reply.Enabled,
|
2020-10-23 00:02:16 +02:00
|
|
|
reply.Precedence,
|
2022-07-04 11:14:26 +02:00
|
|
|
reply.Nolog,
|
2018-04-08 15:32:20 +02:00
|
|
|
Action(reply.Action),
|
|
|
|
Duration(reply.Duration),
|
|
|
|
operator,
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
if Type(reply.Operator.Type) == List {
|
2023-11-11 02:16:08 +01:00
|
|
|
newRule.Operator.Data = ""
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
reply.Operator.Data = ""
|
|
|
|
for i := 0; i < len(reply.Operator.List); i++ {
|
|
|
|
newRule.Operator.List = append(
|
|
|
|
newRule.Operator.List,
|
|
|
|
Operator{
|
|
|
|
Type: Type(reply.Operator.List[i].Type),
|
|
|
|
Sensitive: Sensitive(reply.Operator.List[i].Sensitive),
|
|
|
|
Operand: Operand(reply.Operator.List[i].Operand),
|
|
|
|
Data: string(reply.Operator.List[i].Data),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newRule, nil
|
2018-04-08 15:32:20 +02:00
|
|
|
}
|
|
|
|
|
2020-10-23 00:02:16 +02:00
|
|
|
// Serialize translates a Rule to the protocol object
|
2018-04-08 15:32:20 +02:00
|
|
|
func (r *Rule) Serialize() *protocol.Rule {
|
2020-06-04 00:38:11 +02:00
|
|
|
if r == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2023-12-09 19:06:40 +01:00
|
|
|
r.Operator.Lock()
|
|
|
|
defer r.Operator.Unlock()
|
|
|
|
|
2024-06-10 23:54:54 +02:00
|
|
|
created, err := time.Parse(time.RFC3339, r.Created)
|
|
|
|
if err != nil {
|
|
|
|
log.Warning("Error parsing rule Created date (it should be in RFC3339 format): %s (%s)", err, string(r.Name))
|
|
|
|
log.Warning("using current time instead: %s", created)
|
|
|
|
created = time.Now()
|
|
|
|
}
|
|
|
|
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
protoRule := &protocol.Rule{
|
2024-06-10 23:54:54 +02:00
|
|
|
Created: created.Unix(),
|
2022-05-12 13:38:23 +02:00
|
|
|
Name: string(r.Name),
|
|
|
|
Description: string(r.Description),
|
|
|
|
Enabled: bool(r.Enabled),
|
|
|
|
Precedence: bool(r.Precedence),
|
2022-07-04 11:14:26 +02:00
|
|
|
Nolog: bool(r.Nolog),
|
2022-05-12 13:38:23 +02:00
|
|
|
Action: string(r.Action),
|
|
|
|
Duration: string(r.Duration),
|
2018-04-08 15:32:20 +02:00
|
|
|
Operator: &protocol.Operator{
|
2020-10-23 00:02:16 +02:00
|
|
|
Type: string(r.Operator.Type),
|
|
|
|
Sensitive: bool(r.Operator.Sensitive),
|
|
|
|
Operand: string(r.Operator.Operand),
|
|
|
|
Data: string(r.Operator.Data),
|
2018-04-08 15:32:20 +02:00
|
|
|
},
|
|
|
|
}
|
rules: improved operator list parsing and conversion
Previously when creating a new rule we followed these steps:
- Create a new protobuf Rule object from the ruleseditor or the
pop-ups.
- If the rule contained more than one operator, we converted the
list of operators to a JSON string.
- This JSON string was sent back to the daemon, and saved to the
DB.
- The list of operators were never expanded on the GUI, i.e., they
were not saved as a list of protobuf Operator objects.
- Once received in the daemon, the JSON string was parsed and
converted to a protobuf Operator list of objects.
Both, the JSON string and the list of protobuf Operator objects were
saved to disk, but the JSON string was ignored when loading the
rules.
Saving the list of operators as a JSON string was a problem if you
wanted to create or modify rules without the GUI.
Now when creating or modifying rules from the GUI, the list of operators
is no longer converted to JSON string. Instead the list is sent to the
daemon as a list of protobuf Operators, and saved as JSON objects.
Notes:
- The JSON string is no longer saved to disk as part of the rules.
- The list of operators is still saved as JSON string to the DB.
- About not enabled rules:
Previously, not enabled rules only had the list of operators as JSON
string, with the field list:[] empty.
Now the list of operators is saved as JSON objects, but if the rule
is not enabled, it won't be parsed/loaded.
Closes #1047
2023-10-09 14:55:15 +02:00
|
|
|
if r.Operator.Type == List {
|
|
|
|
r.Operator.Data = ""
|
|
|
|
for i := 0; i < len(r.Operator.List); i++ {
|
|
|
|
protoRule.Operator.List = append(protoRule.Operator.List,
|
|
|
|
&protocol.Operator{
|
|
|
|
Type: string(r.Operator.List[i].Type),
|
|
|
|
Sensitive: bool(r.Operator.List[i].Sensitive),
|
|
|
|
Operand: string(r.Operator.List[i].Operand),
|
|
|
|
Data: string(r.Operator.List[i].Data),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return protoRule
|
2018-04-08 15:32:20 +02:00
|
|
|
}
|