AuditRuleManager tests added
[platform/core/security/suspicious-activity-monitor.git] / device-agent / daemon / audit / rule.h
1 /**
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.
5  */
6 /**
7  * @file   rule.h
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>
11  */
12
13 #ifndef RULE_H
14 #define RULE_H
15
16 #include <iostream>
17 #include <string>
18 #include <list>
19 #include <set>
20
21 #include <linux/audit.h>
22
23 #include <audit-trail/audit-trail.h>
24 #include <audit-trail/rule.h>
25
26 #include <boost/variant.hpp>
27 #include <jsoncpp/json/value.h>
28 #include <jsoncpp/json/reader.h>
29 #include <jsoncpp/json/writer.h>
30
31 namespace audit
32 {
33
34 /**
35  * @class SyscallArray
36  * @brief Array of syscall indexes
37  */
38 class SyscallArray : public std::set<int>
39 {
40 public:
41     Json::Value asJson() const {
42         Json::Value res(Json::arrayValue);
43         for (auto i : *this) {
44             res.append(i);
45         }
46         return res;
47     }
48 };
49
50 /**
51  * @enum FieldType
52  * @brief Supported audit rule field types
53  */
54 enum class FieldType
55 {
56     t_int,
57     t_str,
58 };
59
60 /**
61  * @class Field
62  * @brief Audit rule condition field
63  */
64 class Field
65 {
66     struct FieldData
67     {
68         std::string name;
69         FieldType type;
70     };
71
72     static const std::map<int,FieldData> s_fields;
73
74 public:
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!");
78         }
79     }
80     Field(const std::string& field) : m_field(-1) {
81         for (const auto& i : s_fields) {
82             if (i.second.name == field) {
83                 m_field = i.first;
84                 break;
85             }
86         }
87         if (m_field == -1) {
88             throw std::logic_error("Unsupported audit rule condition field!");
89         }
90     }
91
92     FieldType type() const {
93         return s_fields.find(m_field)->second.type;
94     }
95
96     operator int() const {
97         return m_field;
98     }
99
100     operator std::string() const {
101         return s_fields.find(m_field)->second.name;
102     }
103
104     friend bool operator ==(const Field& lv, const Field& rv) {
105         return lv.m_field == rv.m_field;
106     }
107
108 private:
109     int m_field;
110 };
111
112 /**
113  * @class Operation
114  * @brief Audit rule condition operation
115  */
116 class Operation
117 {
118     static const std::map<int,std::string> s_operations;
119
120 public:
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!");
124         }
125     }
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;
130                 break;
131             }
132         }
133         if (m_operation == -1) {
134             throw std::logic_error("Unsupported audit rule condition operation!");
135         }
136     }
137
138     operator int() const {
139         return m_operation;
140     }
141
142     operator std::string() const {
143         return s_operations.find(m_operation)->second;
144     }
145
146     friend bool operator ==(const Operation& lv, const Operation& rv) {
147         return lv.m_operation == rv.m_operation;
148     }
149
150 private:
151     int m_operation;
152 };
153
154 /**
155  * @class Value
156  * @brief Audit rule condition value
157  */
158 class Value
159 {
160     class visitor : public boost::static_visitor<>
161     {
162     public:
163         visitor(Json::Value& value) : m_value(value) {
164         }
165
166         template <typename T>
167         void operator()(T v) const {
168             m_value = v;
169         }
170
171     private:
172         Json::Value& m_value;
173     };
174
175 public:
176     Value(boost::variant<int,std::string> value) : m_value(value) {
177     }
178
179     Json::Value asJson() const {
180         Json::Value res;
181         boost::apply_visitor(visitor{res}, m_value);
182         return res;
183     }
184
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();
189     }
190
191     friend bool operator ==(const Value& lv, const Value& rv) {
192         return lv.m_value == rv.m_value;
193     }
194
195 private:
196     boost::variant<int,std::string> m_value;
197 };
198
199 /**
200  * @class Condition
201  * @brief Audit rule condition
202  */
203 struct Condition
204 {
205     Condition(int field, int operation, boost::variant<int,std::string> value)
206         : m_field(field), m_operation(operation), m_value(value) {
207     }
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) {
210     }
211
212     Json::Value asJson() const {
213         Json::Value res;
214         res["field"] = (std::string)m_field;
215         res["operator"] = (std::string)m_operation;
216         res["value"] = m_value.asJson();
217         return res;
218     }
219
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);
222     }
223
224     Field m_field;
225     Operation m_operation;
226     Value m_value;
227 };
228
229 /**
230  * @class ConditionList
231  * @brief List of audit rule conditions
232  */
233 class ConditionList : public std::list<Condition>
234 {
235 public:
236     Json::Value asJson() const {
237         Json::Value res(Json::arrayValue);
238         for (const auto& i : *this) {
239             res.append(i.asJson());
240         }
241         return res;
242     }
243 };
244
245 /**
246  * @class RuleData
247  * @brief Audit rule data
248  */
249 struct RuleData
250 {
251     RuleData() : m_key(), m_syscall{}, m_condition{} {
252     }
253     RuleData(const Json::Value& data) : m_key(), m_syscall{}, m_condition{} {
254         if (data.empty()) {
255             throw std::logic_error("Empty rule!");
256         }
257
258         m_key = data.get("key", "").asString();
259         if (m_key == "") {
260             throw std::logic_error("Field \"key\" is undefined!");
261         }
262
263         const Json::Value& syscall = data["syscall"];
264         for (const Json::Value& v : syscall) {
265             m_syscall.insert(v.asInt());
266         }
267
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!");
272             }
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);
276             if (v.isInt()) {
277                 m_condition.emplace_back(Condition(f,o,v.asInt()));
278             } else {
279                 m_condition.emplace_back(Condition(f,o,v.asString()));
280             }
281         }
282     }
283
284     Json::Value asJson() const {
285         Json::Value res;
286         res["key"] = m_key;
287         res["syscall"] = m_syscall.asJson();
288         res["condition"] = m_condition.asJson();
289         return res;
290     }
291
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);
294     }
295
296     std::string m_key;
297     SyscallArray m_syscall;
298     ConditionList m_condition;
299 };
300
301 /**
302  * @class Rule
303  * @brief Audit rule representation
304  */
305 class Rule
306 {
307     /**
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
312      */
313     friend void syscallCallback(unsigned int syscall, void* user_data);
314
315     /**
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
322      */
323     friend void conditionCallback(unsigned int field, unsigned int operation, const void* value, void* user_data);
324
325 public:
326     /**
327      * @brief Constructor
328      */
329     Rule(const std::string& key);
330     Rule(audit_rule_h handle);
331     Rule(const RuleData& data);
332
333     /**
334      * @brief Destructor
335      */
336     virtual ~Rule();
337
338     /**
339      * @brief Add system call number to the rule
340      * @param syscall [in] system call number
341      * @return 0 on success, otherwise negative value
342      */
343     int addSyscall(int syscall);
344
345     /**
346      * @brief Remove system call number from the rule
347      * @param syscall [in] system call number
348      * @return 0 on success, otherwise negative value
349      */
350     int removeSyscall(int syscall);
351
352     /**
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
358      */
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);
361
362     /**
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
368      */
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);
371
372     /**
373      * @brief Get rule data
374      * @return data associated with the rule
375      */
376     const RuleData& data() const {
377         return m_data;
378     }
379
380     operator audit_rule_h () const {
381         return m_handle;
382     }
383
384     friend bool operator ==(const Rule& lv, const Rule& rv) {
385         return (lv.m_handle == rv.m_handle && lv.m_data == rv.m_data);
386     }
387
388 private:
389     audit_rule_h m_handle;
390     RuleData m_data;
391 };
392
393 } //namespace audit
394
395 #endif // RULE_H