2 * Samsung Ukraine R&D Center (SRK under a contract between)
3 * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
4 * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
8 * @brief Audit rule representation
9 * @date Created Apr 04, 2018
10 * @author Mail to: <A HREF="mailto:i.metelytsia@samsung.com">Iurii Metelytsia, i.metelytsia@samsung.com</A>
21 #include <linux/audit.h>
23 #include <audit-trail/audit-trail.h>
24 #include <audit-trail/rule.h>
26 #include <boost/variant.hpp>
27 #include <jsoncpp/json/value.h>
28 #include <jsoncpp/json/reader.h>
29 #include <jsoncpp/json/writer.h>
36 * @brief Array of syscall indexes
38 class SyscallArray : public std::set<int>
41 Json::Value asJson() const {
42 Json::Value res(Json::arrayValue);
43 for (auto i : *this) {
52 * @brief Supported audit rule field types
62 * @brief Audit rule condition field
72 static const std::map<int,FieldData> s_fields;
75 Field(int field) : m_field(field) {
76 if (s_fields.find(m_field) == s_fields.end()) {
77 throw std::logic_error("Unsupported audit rule condition field!");
80 Field(const std::string& field) : m_field(-1) {
81 for (const auto& i : s_fields) {
82 if (i.second.name == field) {
88 throw std::logic_error("Unsupported audit rule condition field!");
92 FieldType type() const {
93 return s_fields.find(m_field)->second.type;
96 operator int() const {
100 operator std::string() const {
101 return s_fields.find(m_field)->second.name;
104 friend bool operator ==(const Field& lv, const Field& rv) {
105 return lv.m_field == rv.m_field;
114 * @brief Audit rule condition operation
118 static const std::map<int,std::string> s_operations;
121 Operation(int operation) : m_operation(operation) {
122 if (s_operations.find(m_operation) == s_operations.end()) {
123 throw std::logic_error("Unsupported audit rule condition operation!");
126 Operation(const std::string& operation) : m_operation(-1) {
127 for (const auto& i : s_operations) {
128 if (i.second == operation) {
129 m_operation = i.first;
133 if (m_operation == -1) {
134 throw std::logic_error("Unsupported audit rule condition operation!");
138 operator int() const {
142 operator std::string() const {
143 return s_operations.find(m_operation)->second;
146 friend bool operator ==(const Operation& lv, const Operation& rv) {
147 return lv.m_operation == rv.m_operation;
156 * @brief Audit rule condition value
160 class visitor : public boost::static_visitor<>
163 visitor(Json::Value& value) : m_value(value) {
166 template <typename T>
167 void operator()(T v) const {
172 Json::Value& m_value;
176 Value(boost::variant<int,std::string> value) : m_value(value) {
179 Json::Value asJson() const {
181 boost::apply_visitor(visitor{res}, m_value);
185 operator const void*() const {
186 if (m_value.type() == typeid(int))
187 return (const void*)boost::get<int>(m_value);
188 return (const void*)boost::get<std::string>(m_value).c_str();
191 friend bool operator ==(const Value& lv, const Value& rv) {
192 return lv.m_value == rv.m_value;
196 boost::variant<int,std::string> m_value;
201 * @brief Audit rule condition
205 Condition(int field, int operation, boost::variant<int,std::string> value)
206 : m_field(field), m_operation(operation), m_value(value) {
208 Condition(const std::string& field, const std::string& operation, boost::variant<int,std::string> value)
209 : m_field(field), m_operation(operation), m_value(value) {
212 Json::Value asJson() const {
214 res["field"] = (std::string)m_field;
215 res["operator"] = (std::string)m_operation;
216 res["value"] = m_value.asJson();
220 friend bool operator ==(const Condition& lv, const Condition& rv) {
221 return (lv.m_field == rv.m_field && lv.m_operation == rv.m_operation && lv.m_value == rv.m_value);
225 Operation m_operation;
230 * @class ConditionList
231 * @brief List of audit rule conditions
233 class ConditionList : public std::list<Condition>
236 Json::Value asJson() const {
237 Json::Value res(Json::arrayValue);
238 for (const auto& i : *this) {
239 res.append(i.asJson());
247 * @brief Audit rule data
251 RuleData() : m_key(), m_syscall{}, m_condition{} {
253 RuleData(const Json::Value& data) : m_key(), m_syscall{}, m_condition{} {
255 throw std::logic_error("Empty rule!");
258 m_key = data.get("key", "").asString();
260 throw std::logic_error("Field \"key\" is undefined!");
263 const Json::Value& syscall = data["syscall"];
264 for (const Json::Value& v : syscall) {
265 m_syscall.insert(v.asInt());
268 const Json::Value& condition = data["condition"];
269 for (const Json::Value& node : condition) {
270 if (!node.isMember("field") || !node.isMember("operator") || !node.isMember("value")) {
271 throw std::logic_error("Invalid condition format!");
273 std::string f = node.get("field", "").asString();
274 std::string o = node.get("operator", "").asString();
275 Json::Value v = node.get("value", Json::Value::null);
277 m_condition.emplace_back(Condition(f,o,v.asInt()));
279 m_condition.emplace_back(Condition(f,o,v.asString()));
284 Json::Value asJson() const {
287 res["syscall"] = m_syscall.asJson();
288 res["condition"] = m_condition.asJson();
292 friend bool operator ==(const RuleData& lv, const RuleData& rv) {
293 return (lv.m_key == rv.m_key && lv.m_syscall == rv.m_syscall && lv.m_condition == rv.m_condition);
297 SyscallArray m_syscall;
298 ConditionList m_condition;
303 * @brief Audit rule representation
308 * @brief Audit rule syscall iteration callback
309 * @details Called from audit_rule_foreach_systemcall for each syscall
310 * @param syscall [in] system call number
311 * @param user_data [in] pointer to user defined data
313 friend void syscallCallback(unsigned int syscall, void* user_data);
316 * @brief Audit rule condition iteration callback
317 * @details Called from audit_rule_foreach_condition for each condition
318 * @param field [in] condition field name
319 * @param operation [in] condition operation
320 * @param value [in] condition value
321 * @param user_data [in] pointer to user defined data
323 friend void conditionCallback(unsigned int field, unsigned int operation, const void* value, void* user_data);
329 Rule(const std::string& key);
330 Rule(audit_rule_h handle);
331 Rule(const RuleData& data);
339 * @brief Add system call number to the rule
340 * @param syscall [in] system call number
341 * @return 0 on success, otherwise negative value
343 int addSyscall(int syscall);
346 * @brief Remove system call number from the rule
347 * @param syscall [in] system call number
348 * @return 0 on success, otherwise negative value
350 int removeSyscall(int syscall);
353 * @brief Add condition to the rule
354 * @param field [in] condition field name
355 * @param operstion [in] condition operation
356 * @param value [in] condition value
357 * @return 0 on success, otherwise negative value
359 int addCondition(const std::string& field, const std::string& operation, int value);
360 int addCondition(const std::string& field, const std::string& operation, const std::string& value);
363 * @brief Remove condition from the rule
364 * @param field [in] condition field name
365 * @param operstion [in] condition operation
366 * @param value [in] condition value
367 * @return 0 on success, otherwise negative value
369 int removeCondition(const std::string& field, const std::string& operation, int value);
370 int removeCondition(const std::string& field, const std::string& operation, const std::string& value);
373 * @brief Get rule data
374 * @return data associated with the rule
376 const RuleData& data() const {
380 operator audit_rule_h () const {
384 friend bool operator ==(const Rule& lv, const Rule& rv) {
385 return (lv.m_handle == rv.m_handle && lv.m_data == rv.m_data);
389 audit_rule_h m_handle;