class FieldBase {
public:
+ enum {
+ RelSeparate = -1,
+ RelKeep,
+ RelSwap,
+ RelRemove,
+ };
+
virtual void emit(std::vector<char> &rule) const = 0;
+ virtual bool compare(std::shared_ptr<FieldBase> field) = 0;
+ virtual int getRelation(std::shared_ptr<FieldBase> field) = 0;
+
virtual FieldType type() const = 0;
virtual Operator op() const = 0;
emitValue(rule, _value);
}
+ bool compare(std::shared_ptr<FieldBase> field)
+ {
+ auto f = reinterpret_cast<Field<T>*>(field.get());
+ if (f == nullptr)
+ return false;
+
+ return (_type == field->type()) &&
+ (_op == field->op()) &&
+ (_value == f->value());
+ }
+
+ inline int getRelation(std::shared_ptr<FieldBase> field);
+
private:
Field create(T value, Operator op) {
_op = op;
r->buflen += r->values[r->field_count++];
}
-protected:
FieldType _type;
Operator _op;
T _value;
};
+template <typename T>
+int Field<T>::getRelation(std::shared_ptr<FieldBase> field)
+{
+ int ret = FieldBase::RelSeparate;
+ auto f = reinterpret_cast<Field<T>*>(field.get());
+
+ if (f == nullptr)
+ return FieldBase::RelKeep;
+
+ if (_op == f->op()) {
+ if (_op == Operator::Equal && _value != f->value())
+ return FieldBase::RelSeparate;
+ else if (_op == Operator::NotEqual && _value != f->value())
+ return FieldBase::RelRemove;
+ }
+
+ if (_op == Operator::Equal && f->op() == Operator::NotEqual) {
+ if (_value != f->value())
+ return FieldBase::RelSwap;
+ else
+ return FieldBase::RelRemove;
+ }
+
+ if (_op == Operator::NotEqual && f->op() == Operator::Equal) {
+ if (_value != f->value())
+ return FieldBase::RelSwap;
+ else
+ return FieldBase::RelRemove;
+ }
+ return ret;
+}
+
INT_FIELD(Pid)
INT_FIELD(Uid)
INT_FIELD(EUid)
*/
#include "rule.h"
+bool Rule::combine(Rule &r1, Rule &r2)
+{
+ int result = 0;
+ if (!r1.compareFieldType(r2) && !r2.compareFieldType(r1))
+ return false;
+
+ for (auto &c : r1.condition) {
+ if (r2.condition.find(c.first) != r2.condition.end()) {
+ int ret = c.second->getRelation(r2.condition[c.first]);
+ if (ret == FieldBase::RelSeparate)
+ return false;
+ if (ret != FieldBase::RelKeep)
+ result = 1;
+ if (ret == FieldBase::RelRemove)
+ r2.unsetCondition(c.first);
+ } else {
+ result = 1;
+ }
+ }
+
+ if (result == 0) {
+ for (auto m : r1.getMask()) {
+ r2.unsetMask(m);
+ }
+ } else if (result == 1) {
+ for (auto m : r2.getMask()) {
+ r1.unsetMask(m);
+ }
+ }
+ return true;
+}
+
Rule::Rule(Action action, Filter filter)
: buf(sizeof(RuleData))
{
}
Rule::Rule(const Rule &rule)
- : buf(sizeof(RuleData))
+ : condition(rule.condition), buf(sizeof(RuleData))
{
- conditions.insert(rule.conditions.begin(), rule.conditions.end());
setComponents(rule.buf);
}
{
std::vector<char> ret(buf);
- for (auto &c : conditions) {
+ for (auto &c : condition) {
if (c.second)
c.second->emit(ret);
}
return ret;
}
+bool Rule::compareFieldType(const Rule &rule)
+{
+ int ret = true;
+ for (auto c : rule.condition) {
+ if (condition.find(c.first) == condition.end())
+ return false;
+ }
+ return ret;
+}
+
+bool Rule::compareCondition(Rule &rule)
+{
+ for (auto c : condition) {
+ if (rule.condition.find(c.first) == rule.condition.end()
+ || !c.second->compare(rule.condition[c.first])) {
+ return false;
+ }
+ }
+ return true;
+}
+
void Rule::set(Action action)
{
ruleData()->action = static_cast<unsigned int>(action);
for (unsigned int i = 0; i < r->field_count; i++) {
if (FieldBase::isString(FieldType(r->fields[i]))) {
std::string value(ruleBuf, ruleBuf + r->values[i]);
- conditions[FieldType(r->fields[i])].reset(
+ condition[FieldType(r->fields[i])].reset(
new(std::nothrow) Field<std::string>(
FieldType(r->fields[i]), Operator(r->fieldflags[i]), value));
ruleBuf += r->values[i];
} else {
- conditions[FieldType(r->fields[i])].reset(
+ condition[FieldType(r->fields[i])].reset(
new(std::nothrow) Field<int>(
FieldType(r->fields[i]), Operator(r->fieldflags[i]), r->values[i]));
}
x = AUDIT_PERM_EXEC,
a = AUDIT_PERM_ATTR,
};
+
using RuleData = struct audit_rule_data;
+ using Condition = std::map<FieldType, std::shared_ptr<FieldBase>>;
Rule(Action action = Action::Always, Filter filter = Filter::Exit);
virtual ~Rule();
Rule(Rule &&) = delete;
Rule(const std::vector<char> &rule);
Rule(const Rule &rule);
-
+ Rule &operator = (const Rule &rule) = default;
template <typename T>
Rule &operator << (const Field<T> &field)
{
return (data() == rule.data());
}
+ static bool combine(Rule &r1, Rule &r2);
std::vector<char> data() const;
template <typename T>
void setCondition(const Field<T> &field);
- template <typename T>
- void unsetCondition(const Field<T> &field);
+ inline void unsetCondition(FieldType type);
template <typename T>
void getConditionValue(FieldType type, T &ret);
+ bool compareCondition(Rule &rule);
void setMask();
void setMask(unsigned int syscall);
void set(Action action);
void set(Filter filter);
-protected:
- std::map<FieldType, std::shared_ptr<FieldBase>> conditions;
-
private:
RuleData *ruleData()
{
return reinterpret_cast<RuleData*>(buf.data());
}
void setComponents(const std::vector<char> &rule);
+ bool compareFieldType(const Rule &rule);
+
private:
+ Condition condition;
std::vector<char> buf;
};
template <typename T>
void Rule::setCondition(const Field<T> &field)
{
- conditions[field.type()].reset(new(std::nothrow) Field<T>(field));
+ condition[field.type()].reset(new(std::nothrow) Field<T>(field));
}
-template <typename T>
-void Rule::unsetCondition(const Field<T> &field)
+void Rule::unsetCondition(FieldType type)
{
- if (conditions.find(field.type()) != conditions.end())
- conditions.erase(field.type());
+ auto c = condition.find(type);
+ if (c != condition.end()) {
+ c->second.reset();
+ condition.erase(c);
+ }
}
template <typename T>
void Rule::getConditionValue(FieldType type, T &ret)
{
- auto condition = conditions[type].get();
- if (condition == nullptr) {
- //INFO("Condition isn't exist");
+ auto c = condition[type];
+ if (c == nullptr)
return;
- }
if (!FieldBase::isString(type)
- && std::is_same<std::string, T>::value) {
- //INFO("Invalid field value type");
+ && std::is_same<std::string, T>::value)
return;
- }
- Field<T> *field = reinterpret_cast<Field<T>*>(condition);
+
+ auto field = reinterpret_cast<Field<T>*>(c.get());
ret = field->value();
}
RET_ON_FAILURE(handle, AUDIT_TRAIL_ERROR_INVALID_PARAMETER);
try {
- GetAuditRule(handle).unsetCondition(
- Field<int>{FieldType(field), Operator(op), (int)(intptr_t)value});
+ GetAuditRule(handle).unsetCondition(FieldType(field));
return AUDIT_TRAIL_ERROR_NONE;
} catch (std::exception &e) {}
try {
- GetAuditRule(handle).unsetCondition(
- Field<std::string>{FieldType(field), Operator(op), (char *)value});
+ GetAuditRule(handle).unsetCondition(FieldType(field));
return AUDIT_TRAIL_ERROR_NONE;
} catch (std::exception &e) {}