Improve rule parsing, fix bugs (#28)

This commit is contained in:
Tad Glines 2019-05-09 13:34:17 -07:00 коммит произвёл GitHub
Родитель 7b8b09d5d4
Коммит dbe2bd2c78
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 626 добавлений и 109 удалений

Просмотреть файл

@ -20,6 +20,7 @@
#include "StringUtils.h" #include "StringUtils.h"
#include "KernelInfo.h" #include "KernelInfo.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "UserDB.h"
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
@ -28,6 +29,8 @@
#include <climits> #include <climits>
#include <system_error> #include <system_error>
#include <pwd.h>
#include <fcntl.h>
// Character that seperates key in AUDIT_FILTERKEY field in rules // Character that seperates key in AUDIT_FILTERKEY field in rules
#define KEY_SEP 0x01 #define KEY_SEP 0x01
@ -216,11 +219,13 @@ bool AuditRule::Parse(const std::string& text, std::string& error) {
if (!parse_add_p_arg(args[idx+1], error)) { if (!parse_add_p_arg(args[idx+1], error)) {
return false; return false;
} }
idx += 2;
break; break;
case 'k': case 'k':
if (!parse_add_k_arg(args[idx+1], error)) { if (!parse_add_k_arg(args[idx+1], error)) {
return false; return false;
} }
idx += 2;
break; break;
case 'S': case 'S':
if (watch) { if (watch) {
@ -236,6 +241,7 @@ bool AuditRule::Parse(const std::string& text, std::string& error) {
if (!parse_add_S_arg(args[idx+1], error)) { if (!parse_add_S_arg(args[idx+1], error)) {
return false; return false;
} }
idx += 2;
break; break;
case 'F': case 'F':
if (watch) { if (watch) {
@ -244,8 +250,16 @@ bool AuditRule::Parse(const std::string& text, std::string& error) {
error.append("' option"); error.append("' option");
return false; return false;
} }
if (!parse_add_F_arg(args[idx+1], error)) { if (args[idx].size() > 2) {
return false; if (!parse_add_F_arg(args[idx].substr(2), error)) {
return false;
}
idx += 1;
} else {
if (!parse_add_F_arg(args[idx+1], error)) {
return false;
}
idx += 2;
} }
break; break;
case 'C': case 'C':
@ -258,6 +272,7 @@ bool AuditRule::Parse(const std::string& text, std::string& error) {
if (!parse_add_C_arg(args[idx+1], error)) { if (!parse_add_C_arg(args[idx+1], error)) {
return false; return false;
} }
idx += 2;
break; break;
default: default:
error.append("Unsupported option '"); error.append("Unsupported option '");
@ -265,7 +280,6 @@ bool AuditRule::Parse(const std::string& text, std::string& error) {
error.append("'"); error.append("'");
return false; return false;
} }
idx += 2;
} }
return true; return true;
@ -302,28 +316,32 @@ bool AuditRule::parse_add_a_arg(const std::string& val, std::string& error) {
return false; return false;
} }
bool action_found = false;
for (auto& part: parts) { for (auto& part: parts) {
auto itr = s_a_actions.find(part); auto itr = s_a_actions.find(part);
if (itr != s_a_actions.end()) { if (itr != s_a_actions.end()) {
ruleptr()->action = itr->second; ruleptr()->action = itr->second;
action_found = true;
} }
} }
if (ruleptr()->action == 0) { if (!action_found) {
error.append("Invalid or missing action value for option '-a': '"); error.append("Invalid or missing action value for option '-a': '");
error.append(val); error.append(val);
error.append("'"); error.append("'");
return false; return false;
} }
bool flags_found = false;
for (auto& part: parts) { for (auto& part: parts) {
auto itr = s_a_flags.find(part); auto itr = s_a_flags.find(part);
if (itr != s_a_flags.end()) { if (itr != s_a_flags.end()) {
ruleptr()->flags |= itr->second; ruleptr()->flags |= itr->second;
flags_found = true;
} }
} }
if (ruleptr()->flags == 0) { if (!flags_found) {
error.append("Invalid or missing flags value for option '-a': '"); error.append("Invalid or missing flags value for option '-a': '");
error.append(val); error.append(val);
error.append("'"); error.append("'");
@ -422,6 +440,18 @@ std::unordered_map<std::string, uint32_t> s_F_ops(
} }
); );
std::unordered_map<std::string, uint32_t> s_F_ftypes(
{
{"socket", S_IFSOCK},
{"link", S_IFLNK},
{"file", S_IFREG},
{"block", S_IFBLK},
{"dir", S_IFDIR},
{"character", S_IFCHR},
{"fifo", S_IFIFO},
}
);
bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) { bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) {
auto idx = val.find_first_of("=!<>&"); auto idx = val.find_first_of("=!<>&");
if (idx == 0) { if (idx == 0) {
@ -474,6 +504,128 @@ bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) {
} }
switch (field) { switch (field) {
case AUDIT_UID:
case AUDIT_EUID:
case AUDIT_SUID:
case AUDIT_FSUID:
case AUDIT_LOGINUID:
case AUDIT_OBJ_UID:
try {
if (std::isdigit(value[0])) {
uint32_t v = static_cast<uint32_t>(stoul(value, 0, 0));
add_field(field, op, v);
} else if (value.size() > 1 && value[0] == '-' && std::isdigit(value[1])) {
uint32_t v = static_cast<uint32_t>(stol(value, 0, 0));
add_field(field, op, v);
} else {
if (value == "unset") {
add_field(field, op, 4294967295);
} else {
auto uid = UserDB::UserNameToUid(value);
if (uid < 0) {
error.append("Invalid value for option '-F': Unknown username: '");
error.append(val);
error.append("'");
return false;
}
add_field(field, op, uid);
}
}
} catch (std::exception &) {
error.append("Invalid value for option '-F': Invalid numeric value: '");
error.append(val);
error.append("'");
return false;
}
break;
case AUDIT_GID:
case AUDIT_EGID:
case AUDIT_SGID:
case AUDIT_FSGID:
case AUDIT_OBJ_GID:
try {
if (std::isdigit(value[0])) {
uint32_t v = static_cast<uint32_t>(stoul(value, 0, 0));
add_field(field, op, v);
} else if (value.size() > 1 && value[0] == '-' && std::isdigit(value[1])) {
uint32_t v = static_cast<uint32_t>(stol(value, 0, 0));
add_field(field, op, v);
} else {
if (value == "unset") {
add_field(field, op, 4294967295);
} else {
auto gid = UserDB::GroupNameToGid(value);
if (gid < 0) {
error.append("Invalid value for option '-F': Unknown group name: '");
error.append(val);
error.append("'");
return false;
}
add_field(field, op, gid);
}
}
} catch (std::exception &) {
error.append("Invalid value for option '-F': Invalid numeric value: '");
error.append(val);
error.append("'");
return false;
}
break;
case AUDIT_EXIT:
if ((ruleptr()->flags & FILTER_MASK) != AUDIT_FILTER_EXIT) {
error.append("Invalid value for option '-F': Cannot filter on exit field unless flags (-a option) == 'exit'");
return false;
}
try {
if (std::isdigit(value[0])) {
uint32_t v = static_cast<uint32_t>(stoul(value, 0, 0));
add_field(field, op, v);
} else if (value.size() > 1 && value[0] == '-' && std::isdigit(value[1])) {
uint32_t v = static_cast<uint32_t>(stol(value, 0, 0));
add_field(field, op, v);
} else {
auto v = NameToErrno(value);
if (v == 0) {
error.append("Invalid value for option '-F': Invalid errno name: '");
error.append(val);
error.append("'");
return false;
}
add_field(field, op, v);
}
} catch (std::exception &) {
error.append("Invalid value for option '-F': Invalid numeric value: '");
error.append(val);
error.append("'");
return false;
}
break;
case AUDIT_MSGTYPE:
if ((ruleptr()->flags & FILTER_MASK) != AUDIT_FILTER_TYPE) {
error.append("Invalid value for option '-F': Cannot filter on msg type unless flags (-a option) == 'exclude'");
return false;
}
if (std::isdigit(value[0])) {
try {
uint32_t v = static_cast<uint32_t>(stoul(value, 0, 0));
add_field(field, op, v);
} catch (std::exception &) {
error.append("Invalid value for option '-F': Invalid numeric value: '");
error.append(val);
error.append("'");
return false;
}
} else {
auto rt = RecordNameToType(value);
if (rt == RecordType::UNKNOWN) {
error.append("Invalid value for option '-F': Invalid record type name: '");
error.append(val);
error.append("'");
return false;
}
add_field(field, op, static_cast<uint32_t>(rt));
}
break;
case AUDIT_ARCH: { case AUDIT_ARCH: {
auto arch = ArchNameToArch(value); auto arch = ArchNameToArch(value);
if (arch == 0) { if (arch == 0) {
@ -489,12 +641,6 @@ bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) {
add_field(field, op, arch); add_field(field, op, arch);
break; break;
} }
case AUDIT_MSGTYPE:
if ((ruleptr()->flags & FILTER_MASK) != AUDIT_FILTER_TYPE) {
error.append("Invalid value for option '-F': Cannot filter on msg type unless flags (-a option) == 'exclude'");
return false;
}
break;
case AUDIT_PERM: { case AUDIT_PERM: {
uint32_t perms = 0; uint32_t perms = 0;
for (auto c: value) { for (auto c: value) {
@ -521,11 +667,29 @@ bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) {
add_field(AUDIT_PERM, op, perms); add_field(AUDIT_PERM, op, perms);
break; break;
} }
case AUDIT_OBJ_USER:
/* fallthrough */
case AUDIT_OBJ_ROLE:
/* fallthrough */
case AUDIT_OBJ_TYPE:
/* fallthrough */
case AUDIT_OBJ_LEV_LOW:
/* fallthrough */
case AUDIT_OBJ_LEV_HIGH:
if (ruleptr()->flags != AUDIT_FILTER_EXIT) {
error = "Field '" + field_name + "' can only be used with 'exit' filter";
return false;
}
add_str_field(field, op, value);
break;
case AUDIT_WATCH: case AUDIT_WATCH:
/* fallthrough */ /* fallthrough */
case AUDIT_DIR: { case AUDIT_DIR: {
/* fallthrough */ if (ruleptr()->flags != AUDIT_FILTER_EXIT) {
auto path = clean_path(val); error = "Field '" + field_name + "' can only be used with 'exit' filter";
return false;
}
auto path = clean_path(value);
if (!check_path(path, error)) { if (!check_path(path, error)) {
error = "Invalid path option: " + error; error = "Invalid path option: " + error;
return false; return false;
@ -533,12 +697,38 @@ bool AuditRule::parse_add_F_arg(const std::string& val, std::string& error) {
add_str_field(field, op, path); add_str_field(field, op, path);
break; break;
} }
case AUDIT_SUBJ_USER:
/* fallthrough */
case AUDIT_SUBJ_ROLE:
/* fallthrough */
case AUDIT_SUBJ_TYPE:
/* fallthrough */
case AUDIT_SUBJ_SEN:
/* fallthrough */
case AUDIT_SUBJ_CLR:
/* fallthrough */
case AUDIT_EXE: case AUDIT_EXE:
add_str_field(field, op, value); add_str_field(field, op, value);
break; break;
case AUDIT_FILTERKEY: case AUDIT_FILTERKEY:
AddKey(value); AddKey(value);
break; break;
case AUDIT_FILETYPE: {
if (ruleptr()->flags != AUDIT_FILTER_EXIT) {
error = "Field '" + field_name + "' can only be used with 'exit' filter";
return false;
}
auto ft = s_F_ftypes.find(value);
if (ft != s_F_ftypes.end()) {
add_field(field, op, ft->second);
} else {
error.append("Invalid value for option '-F': Invalid filetype name: '");
error.append(val);
error.append("'");
return false;
}
break;
}
default: default:
try { try {
uint32_t v = static_cast<uint32_t>(stol(value, 0, 0)); uint32_t v = static_cast<uint32_t>(stol(value, 0, 0));
@ -1689,7 +1879,7 @@ void RemoveSection(std::vector<std::string>& lines, const std::string& start_mar
lines.erase(start, end); lines.erase(start, end);
} }
std::vector<AuditRule> ParseRules(const std::vector<std::string>& lines) { std::vector<AuditRule> ParseRules(const std::vector<std::string>& lines, std::vector<std::string>* errors) {
std::vector<AuditRule> rules; std::vector<AuditRule> rules;
for (int i = 0; i < lines.size(); ++i) { for (int i = 0; i < lines.size(); ++i) {
AuditRule rule; AuditRule rule;
@ -1697,7 +1887,11 @@ std::vector<AuditRule> ParseRules(const std::vector<std::string>& lines) {
if (rule.Parse(lines[i], error)) { if (rule.Parse(lines[i], error)) {
rules.emplace_back(rule); rules.emplace_back(rule);
} else if (!error.empty()) { } else if (!error.empty()) {
throw std::runtime_error("Failed to parse line " + std::to_string(i+1) + ": " + error); if (errors != nullptr) {
errors->emplace_back("Failed to parse line " + std::to_string(i + 1) + ": " + error);
} else {
throw std::runtime_error("Failed to parse line " + std::to_string(i + 1) + ": " + error);
}
} }
} }
return rules; return rules;
@ -1827,7 +2021,7 @@ std::vector<AuditRule> DiffRules(const std::vector<AuditRule>& actual, const std
return rules; return rules;
} }
std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir) { std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir, std::vector<std::string>* errors) {
std::vector<std::string> files; std::vector<std::string> files;
std::vector<AuditRule> rules; std::vector<AuditRule> rules;
@ -1836,7 +2030,7 @@ std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir) {
for(auto& file: files) { for(auto& file: files) {
if (ends_with(file, ".rules")) { if (ends_with(file, ".rules")) {
auto lines = ReadFile(dir + "/" + file); auto lines = ReadFile(dir + "/" + file);
rules = MergeRules(rules, ParseRules(lines)); rules = MergeRules(rules, ParseRules(lines, errors));
} }
} }
@ -1844,7 +2038,7 @@ std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir) {
} }
// Read rules from auditd rules.d dir // Read rules from auditd rules.d dir
std::vector<AuditRule> ReadAuditdRulesDir(bool exclude_auoms) { std::vector<AuditRule> ReadAuditdRulesDir(bool exclude_auoms, std::vector<std::string>* errors) {
std::vector<std::string> files; std::vector<std::string> files;
std::vector<AuditRule> rules; std::vector<AuditRule> rules;
@ -1853,8 +2047,9 @@ std::vector<AuditRule> ReadAuditdRulesDir(bool exclude_auoms) {
for(auto& file: files) { for(auto& file: files) {
if (ends_with(file, ".rules")) { if (ends_with(file, ".rules")) {
auto lines = ReadFile(std::string(AUDITD_RULES_DIR) + "/" + file); auto lines = ReadFile(std::string(AUDITD_RULES_DIR) + "/" + file);
std::vector<std::string> file_errors;
if (exclude_auoms) { if (exclude_auoms) {
auto in_rules = ParseRules(lines); auto in_rules = ParseRules(lines, &file_errors);
std::vector<AuditRule> out_rules; std::vector<AuditRule> out_rules;
out_rules.reserve(in_rules.size()); out_rules.reserve(in_rules.size());
// Only include non-auoms rules // Only include non-auoms rules
@ -1866,7 +2061,19 @@ std::vector<AuditRule> ReadAuditdRulesDir(bool exclude_auoms) {
} }
rules = MergeRules(rules, out_rules); rules = MergeRules(rules, out_rules);
} else { } else {
rules = MergeRules(rules, ParseRules(lines)); rules = MergeRules(rules, ParseRules(lines, &file_errors));
}
if (errors != nullptr) {
for (auto &err : file_errors) {
errors->emplace_back("Encountered parse error in '" + std::string(AUDITD_RULES_DIR) + "/" + file + "': " + err);
}
} else {
std::stringstream ss;
ss << "Encountered parse errors in '" << std::string(AUDITD_RULES_DIR) << "/" << file << "': " << std::endl;
for (auto &err : file_errors) {
ss << " " << err << std::endl;
}
throw std::runtime_error(ss.str());
} }
} }
} }
@ -1908,7 +2115,7 @@ bool HasAuditdRulesFiles() {
return PathExists(AUDITD_RULES_FILE); return PathExists(AUDITD_RULES_FILE);
} }
std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms) { std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms, std::vector<std::string>* errors) {
if (!PathExists(AUDITD_RULES_FILE)) { if (!PathExists(AUDITD_RULES_FILE)) {
return std::vector<AuditRule>(); return std::vector<AuditRule>();
} }
@ -1918,13 +2125,15 @@ std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms) {
// If the audit.rules file was at any time in the past generated with augenrules // If the audit.rules file was at any time in the past generated with augenrules
// assume it is still in use // assume it is still in use
if (PathExists(AUGENRULES_BIN) && lines.size() > 0 && starts_with(lines[0], AUGENRULES_HEADER)) { if (PathExists(AUGENRULES_BIN) && lines.size() > 0 && starts_with(lines[0], AUGENRULES_HEADER)) {
return ReadAuditdRulesDir(exclude_auoms); return ReadAuditdRulesDir(exclude_auoms, errors);
} else { } else {
std::vector<AuditRule> rules;
std::vector<std::string> file_errors;
if (exclude_auoms) { if (exclude_auoms) {
// Remove the auoms rules section if present. // Remove the auoms rules section if present.
RemoveSection(lines, AUOMS_AUDITD_RULES_FILE_START_MARKER, AUOMS_AUDITD_RULES_FILE_END_MARKER); RemoveSection(lines, AUOMS_AUDITD_RULES_FILE_START_MARKER, AUOMS_AUDITD_RULES_FILE_END_MARKER);
auto in_rules = ParseRules(lines); auto in_rules = ParseRules(lines, &file_errors);
std::vector<AuditRule> out_rules; std::vector<AuditRule> out_rules;
out_rules.reserve(in_rules.size()); out_rules.reserve(in_rules.size());
// Only include non-auoms rules // Only include non-auoms rules
@ -1934,17 +2143,30 @@ std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms) {
out_rules.emplace_back(rule); out_rules.emplace_back(rule);
} }
} }
return MergeRules({}, out_rules); rules = MergeRules({}, out_rules);
} else { } else {
return MergeRules({}, ParseRules(lines)); rules = MergeRules({}, ParseRules(lines, &file_errors));
} }
if (errors != nullptr) {
for (auto &err : file_errors) {
errors->emplace_back("Encountered parse error in '" + std::string(AUDITD_RULES_FILE) + "': " + err);
}
} else {
std::stringstream ss;
ss << "Encountered parse errors in '" << std::string(AUDITD_RULES_FILE) << "': " << std::endl;
for (auto &err : file_errors) {
ss << " " << err << std::endl;
}
throw std::runtime_error(ss.str());
}
return rules;
} }
} }
bool WriteAuditdRules(const std::vector<AuditRule>& rules) { bool WriteAuditdRules(const std::vector<AuditRule>& rules) {
auto lines = ReadFile(AUDITD_RULES_FILE); auto lines = ReadFile(AUDITD_RULES_FILE);
if (PathExists(AUGENRULES_BIN) && lines.size() > 0 && starts_with(lines[0], AUGENRULES_HEADER)) { if (PathExists(AUGENRULES_BIN) && !lines.empty() && starts_with(lines[0], AUGENRULES_HEADER)) {
WriteAuomsRuleToAuditDir(rules); WriteAuomsRuleToAuditDir(rules);
return true; return true;
} else { } else {
@ -1960,8 +2182,9 @@ bool WriteAuditdRules(const std::vector<AuditRule>& rules) {
// Remove auoms's desired rules to auditd config // Remove auoms's desired rules to auditd config
// Returns true if augenrules needs to be run // Returns true if augenrules needs to be run
bool RemoveAuomsRulesAuditdFiles() { bool RemoveAuomsRulesAuditdFiles() {
std::vector<std::string> errors;
bool has_auoms_rules = false; bool has_auoms_rules = false;
auto rules = ReadActualAuditdRules(false); auto rules = ReadActualAuditdRules(false, &errors);
for (auto &rule: rules) { for (auto &rule: rules) {
auto keys = rule.GetKeys(); auto keys = rule.GetKeys();
if (keys.count(AUOMS_RULE_KEY) > 0) { if (keys.count(AUOMS_RULE_KEY) > 0) {

Просмотреть файл

@ -141,6 +141,9 @@ public:
AuditRule(const void* data, size_t len): _data(), _value_offsets(), is_delete_rule(false) { AuditRule(const void* data, size_t len): _data(), _value_offsets(), is_delete_rule(false) {
_data.fill(0); _data.fill(0);
if (len > _data.size()) {
throw std::out_of_range("len too large");
}
::memcpy(_data.data(), data, len); ::memcpy(_data.data(), data, len);
fill_value_offsets(); fill_value_offsets();
} }
@ -240,7 +243,10 @@ private:
void ReplaceSection(std::vector<std::string>& lines, const std::vector<std::string>& replacement, const std::string& start_marker, const std::string& end_marker); void ReplaceSection(std::vector<std::string>& lines, const std::vector<std::string>& replacement, const std::string& start_marker, const std::string& end_marker);
void RemoveSection(std::vector<std::string>& lines, const std::string& start_marker, const std::string& end_marker); void RemoveSection(std::vector<std::string>& lines, const std::string& start_marker, const std::string& end_marker);
std::vector<AuditRule> ParseRules(const std::vector<std::string>& lines);
// If errors is null, then ParseRules will throiw an exception if there is a parse error
// If errors is not null, then ParseRules willa append each parse error to errors and return only the parsed rules.
std::vector<AuditRule> ParseRules(const std::vector<std::string>& lines, std::vector<std::string>* errors);
std::vector<AuditRule> MergeRules(const std::vector<AuditRule>& rules1); std::vector<AuditRule> MergeRules(const std::vector<AuditRule>& rules1);
std::vector<AuditRule> MergeRules(const std::vector<AuditRule>& rules1, const std::vector<AuditRule>& rules2); std::vector<AuditRule> MergeRules(const std::vector<AuditRule>& rules1, const std::vector<AuditRule>& rules2);
@ -253,10 +259,10 @@ std::vector<AuditRule> DiffRules(const std::vector<AuditRule>& actual, const std
bool HasAuditdRulesFiles(); bool HasAuditdRulesFiles();
// Read all *.rules files from dir, parse, merge then return them. // Read all *.rules files from dir, parse, merge then return them.
std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir); std::vector<AuditRule> ReadAuditRulesFromDir(const std::string& dir, std::vector<std::string>* errors);
// Read rules from auditd rules (excluding auoms rules) // Read rules from auditd rules (excluding auoms rules)
std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms); std::vector<AuditRule> ReadActualAuditdRules(bool exclude_auoms, std::vector<std::string>* errors);
// Adds auoms's desired rules to auditd config // Adds auoms's desired rules to auditd config
// Returns true if augenrules needs to be run // Returns true if augenrules needs to be run

Просмотреть файл

@ -2,13 +2,20 @@
// Created by tad on 3/18/19. // Created by tad on 3/18/19.
// //
#include <sstream>
#include "AuditRulesMonitor.h" #include "AuditRulesMonitor.h"
#include "Logger.h" #include "Logger.h"
#include "ExecUtil.h" #include "ExecUtil.h"
#define PREFERRED_BACKLOG_LIMIT 8192
void AuditRulesMonitor::run() { void AuditRulesMonitor::run() {
Logger::Info("AuditRulesMonitor: Starting"); Logger::Info("AuditRulesMonitor: Starting");
check_audit_status();
while(!_sleep(1000)) { while(!_sleep(1000)) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
@ -35,7 +42,8 @@ void AuditRulesMonitor::on_stop() {
void AuditRulesMonitor::get_desired_rules() { void AuditRulesMonitor::get_desired_rules() {
try { try {
auto rules = ReadAuditRulesFromDir(_audit_rules_dir); std::vector<std::string> errors;
auto rules = ReadAuditRulesFromDir(_audit_rules_dir, &errors);
_desired_rules.resize(0); _desired_rules.resize(0);
for (auto& rule: rules) { for (auto& rule: rules) {
// Only include the rule in the desired rules if it is supported on the host system // Only include the rule in the desired rules if it is supported on the host system
@ -44,7 +52,16 @@ void AuditRulesMonitor::get_desired_rules() {
_desired_rules.emplace_back(rule); _desired_rules.emplace_back(rule);
} }
} }
_op_status->ClearErrorCondition(ErrorCategory::DESIRED_RULES); if (errors.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::DESIRED_RULES);
} else {
std::stringstream ss;
ss << " Encountered parse errors: " << std::endl;
for (auto& err : errors) {
ss << " " << err << std::endl;
}
_op_status->SetErrorCondition(ErrorCategory::DESIRED_RULES, ss.str());
}
} catch(std::exception& ex) { } catch(std::exception& ex) {
Logger::Error("AuditRulesMonitor: Failed to read desired rules from %s: %s", _audit_rules_dir.c_str(), ex.what()); Logger::Error("AuditRulesMonitor: Failed to read desired rules from %s: %s", _audit_rules_dir.c_str(), ex.what());
_op_status->SetErrorCondition(ErrorCategory::DESIRED_RULES, "Failed to read desired rules from " + _audit_rules_dir + ": " + ex.what()); _op_status->SetErrorCondition(ErrorCategory::DESIRED_RULES, "Failed to read desired rules from " + _audit_rules_dir + ": " + ex.what());
@ -57,16 +74,27 @@ void AuditRulesMonitor::check_file_rules() {
return; return;
} }
try { try {
auto rules = ReadActualAuditdRules(false); std::vector<std::string> errors;
auto rules = ReadActualAuditdRules(false, &errors);
auto merged_rules = MergeRules(rules); auto merged_rules = MergeRules(rules);
auto diff = DiffRules(merged_rules, _desired_rules, ""); auto diff = DiffRules(merged_rules, _desired_rules, "");
if (diff.empty()) { if (diff.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_FILE); if (errors.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_FILE);
} else {
std::stringstream ss;
ss << " Encountered parse errors: " << std::endl;
for (auto& err : errors) {
ss << " " << err << std::endl;
}
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, ss.str());
}
return; return;
} }
Logger::Info("AuditRulesMonitor: Found desired audit rules not currently present in auditd rules files(s), adding new rules"); Logger::Info("AuditRulesMonitor: Found desired audit rules not currently present in auditd rules files(s), adding new rules");
// Re-read rules but exclude auoms rules // Re-read rules but exclude auoms rules
rules = ReadActualAuditdRules(true); errors.clear();
rules = ReadActualAuditdRules(true, &errors);
merged_rules = MergeRules(rules); merged_rules = MergeRules(rules);
// Re-calculate diff // Re-calculate diff
diff = DiffRules(merged_rules, _desired_rules, ""); diff = DiffRules(merged_rules, _desired_rules, "");
@ -78,12 +106,32 @@ void AuditRulesMonitor::check_file_rules() {
if (ret != 0) { if (ret != 0) {
Logger::Warn("AuditRulesMonitor: augenrules failed: %s", cmd.FailMsg().c_str()); Logger::Warn("AuditRulesMonitor: augenrules failed: %s", cmd.FailMsg().c_str());
Logger::Warn("AuditRulesMonitor: augenrules output: %s", output.c_str()); Logger::Warn("AuditRulesMonitor: augenrules output: %s", output.c_str());
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, std::string("augenrules failed: ") + cmd.FailMsg()); if (errors.empty()) {
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, std::string("augenrules failed: ") + cmd.FailMsg());
} else {
std::stringstream ss;
ss << " Encountered parse errors and augenrules failed: " << std::endl;
ss << " augenrules error:" << cmd.FailMsg() << std::endl;
for (auto& err : errors) {
ss << " " << err << std::endl;
}
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, ss.str());
}
return;
} else { } else {
Logger::Warn("AuditRulesMonitor: augenrules succeeded"); Logger::Warn("AuditRulesMonitor: augenrules succeeded");
} }
} }
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_FILE); if (errors.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_FILE);
} else {
std::stringstream ss;
ss << " Encountered parse errors: " << std::endl;
for (auto& err : errors) {
ss << " " << err << std::endl;
}
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, ss.str());
}
} catch (std::exception& ex) { } catch (std::exception& ex) {
Logger::Error("AuditRulesMonitor: Failed to check/update auditd rules: %s", ex.what()); Logger::Error("AuditRulesMonitor: Failed to check/update auditd rules: %s", ex.what());
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, std::string("Failed to check/update auditd rules: ") + ex.what()); _op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_FILE, std::string("Failed to check/update auditd rules: ") + ex.what());
@ -226,3 +274,26 @@ bool AuditRulesMonitor::check_kernel_rules() {
return true; return true;
} }
void AuditRulesMonitor::check_audit_status() {
audit_status status;
auto ret = NetlinkRetry([this,&status]() { return _netlink.AuditGet(status); } );
if (ret != 0) {
Logger::Error("Failed to get audit status: %s", std::strerror(-ret));
return;
}
if (status.backlog_limit < PREFERRED_BACKLOG_LIMIT) {
Logger::Error("Increasing audit backlog limit from %u to %u", status.backlog_limit, PREFERRED_BACKLOG_LIMIT);
ret = NetlinkRetry([this]() {
audit_status status;
::memset(&status, 0, sizeof(status));
status.mask = AUDIT_STATUS_BACKLOG_LIMIT;
status.backlog_limit = PREFERRED_BACKLOG_LIMIT;
return _netlink.AuditSet(status);
});
if (ret != 0) {
Logger::Error("Failed to set audit backlog limit to %d: %s", PREFERRED_BACKLOG_LIMIT, std::strerror(-ret));
return;
}
}
}

Просмотреть файл

@ -36,6 +36,7 @@ private:
void get_desired_rules(); void get_desired_rules();
void check_file_rules(); void check_file_rules();
bool check_kernel_rules(); bool check_kernel_rules();
void check_audit_status();
Netlink& _netlink; Netlink& _netlink;
std::string _audit_rules_dir; std::string _audit_rules_dir;

Просмотреть файл

@ -113,6 +113,7 @@ add_executable(auoms
TranslateRecordType.cpp TranslateRecordType.cpp
TranslateFieldType.cpp TranslateFieldType.cpp
TranslateField.cpp TranslateField.cpp
TranslateErrno.cpp
AuditRules.cpp AuditRules.cpp
AuditRulesMonitor.cpp AuditRulesMonitor.cpp
KernelInfo.cpp KernelInfo.cpp
@ -155,6 +156,7 @@ add_executable(auomsctl
TranslateRecordType.cpp TranslateRecordType.cpp
TranslateFieldType.cpp TranslateFieldType.cpp
TranslateField.cpp TranslateField.cpp
TranslateErrno.cpp
AuditRules.cpp AuditRules.cpp
StringUtils.cpp StringUtils.cpp
KernelInfo.cpp KernelInfo.cpp
@ -165,6 +167,7 @@ add_executable(auomsctl
FileUtils.cpp FileUtils.cpp
UnixDomainListener.cpp UnixDomainListener.cpp
Event.cpp Event.cpp
UserDB.cpp
) )
# See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html # See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html

Просмотреть файл

@ -180,8 +180,6 @@ bool CollectionMonitor::is_collector_alive() {
} }
void CollectionMonitor::send_audit_pid_report(int pid) { void CollectionMonitor::send_audit_pid_report(int pid) {
Logger::Info("CollectionMonitor: Audit Pid: %d", pid);
auto pinfo = ProcessInfo::Open(pid); auto pinfo = ProcessInfo::Open(pid);
std::string exe; std::string exe;
int ppid = -1; int ppid = -1;

Просмотреть файл

@ -107,7 +107,7 @@ bool CursorWriter::Read() {
Logger::Error("Output(%s): Failed to open cursor file (%s): %s", _name.c_str(), _path.c_str(), std::strerror(errno)); Logger::Error("Output(%s): Failed to open cursor file (%s): %s", _name.c_str(), _path.c_str(), std::strerror(errno));
return false; return false;
} else { } else {
_cursor = QueueCursor::TAIL; _cursor = QueueCursor::HEAD;
return true; return true;
} }
} }

Просмотреть файл

@ -114,7 +114,7 @@ bool ProcessInfo::parse_stat() {
if (*ptr != '(') { if (*ptr != '(') {
return false; return false;
} }
f_end = strchr(ptr, ')'); f_end = strstr(ptr, ") ");
if (f_end != nullptr && f_end+1 < end && f_end[1] == ')') { if (f_end != nullptr && f_end+1 < end && f_end[1] == ')') {
f_end += 1; f_end += 1;
} }

Просмотреть файл

@ -294,8 +294,13 @@ void Queue::Close(bool save)
save_locked(lock); save_locked(lock);
} }
// Wait for any active save to complete
_cond.wait(lock, [this]() { return !_save_active; });
close(_fd); close(_fd);
_fd = -1; _fd = -1;
_cond.notify_all();
} }
void Queue::Save() { void Queue::Save() {
@ -329,8 +334,6 @@ void Queue::save_locked(std::unique_lock<std::mutex>& lock)
return; return;
} }
auto fd = _fd;
_save_active = true; _save_active = true;
FileHeader before; FileHeader before;
@ -393,20 +396,22 @@ void Queue::save_locked(std::unique_lock<std::mutex>& lock)
int64_t save_size = 0; int64_t save_size = 0;
if (nregions > 0) { if (nregions > 0) {
_pwrite(fd, &before, sizeof(FileHeader), 0); _pwrite(_fd, &before, sizeof(FileHeader), 0);
for (int i = 0; i < nregions; i++) { for (int i = 0; i < nregions; i++) {
_pwrite(fd, regions[i].data, regions[i].size, regions[i].index); _pwrite(_fd, regions[i].data, regions[i].size, regions[i].index);
save_size += regions[i].size; save_size += regions[i].size;
} }
} }
_pwrite(fd, &after, sizeof(FileHeader), 0); _pwrite(_fd, &after, sizeof(FileHeader), 0);
lock.lock(); lock.lock();
_saved_size += save_size; _saved_size += save_size;
_save_active = false; _save_active = false;
_cond.notify_all();
} }
// Assumes queue is locked // Assumes queue is locked

Просмотреть файл

@ -21,6 +21,7 @@
#include <signal.h> #include <signal.h>
std::atomic<bool> Signals::_exit(false); std::atomic<bool> Signals::_exit(false);
std::mutex Signals::_mutex;
std::function<void()> Signals::_hup_fn; std::function<void()> Signals::_hup_fn;
std::function<void()> Signals::_exit_fn; std::function<void()> Signals::_exit_fn;
pthread_t Signals::_main_id; pthread_t Signals::_main_id;
@ -106,13 +107,17 @@ void Signals::run() {
return; return;
} }
if (sig == SIGHUP) { if (sig == SIGHUP) {
std::lock_guard<std::mutex> _lock(_mutex);
if (_hup_fn) { if (_hup_fn) {
_hup_fn(); _hup_fn();
} }
} else { } else {
_exit.store(true); _exit.store(true);
if (_exit_fn) { {
_exit_fn(); std::lock_guard<std::mutex> _lock(_mutex);
if (_exit_fn) {
_exit_fn();
}
} }
// Break main thread out of blocking syscall // Break main thread out of blocking syscall
pthread_kill(_main_id, SIGQUIT); pthread_kill(_main_id, SIGQUIT);

Просмотреть файл

@ -18,6 +18,7 @@
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <mutex>
#include <pthread.h> #include <pthread.h>
@ -29,13 +30,20 @@ public:
static bool IsExit(); static bool IsExit();
static void Terminate(); static void Terminate();
static void SetHupHandler(std::function<void()> fn) { _hup_fn = fn; } static void SetHupHandler(std::function<void()> fn) {
static void SetExitHandler(std::function<void()> fn) { _exit_fn = fn; } std::lock_guard<std::mutex> _lock(_mutex);
_hup_fn = fn;
}
static void SetExitHandler(std::function<void()> fn) {
std::lock_guard<std::mutex> _lock(_mutex);
_exit_fn = fn;
}
private: private:
static void run(); static void run();
static std::atomic<bool> _exit; static std::atomic<bool> _exit;
static std::mutex _mutex;
static std::function<void()> _hup_fn; static std::function<void()> _hup_fn;
static std::function<void()> _exit_fn; static std::function<void()> _exit_fn;
static pthread_t _main_id; static pthread_t _main_id;

Просмотреть файл

@ -45,4 +45,7 @@ field_type_t FieldNameToType(RecordType rtype, const std::string_view& name, con
std::string FieldIdToName(int field); std::string FieldIdToName(int field);
int FieldNameToId(const std::string_view& name); int FieldNameToId(const std::string_view& name);
std::string ErrnoToName(int field);
int NameToErrno(const std::string_view& name);
#endif //AUOMS_TRANSLATE_H #endif //AUOMS_TRANSLATE_H

182
TranslateErrno.cpp Normal file
Просмотреть файл

@ -0,0 +1,182 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <linux/audit.h>
#include "Translate.h"
#include "StringTable.h"
#include <errno.h>
static StringTable<int> s_errno_table(0, {
{"EPERM", EPERM},
{"ENOENT", ENOENT},
{"ESRCH", ESRCH},
{"EINTR", EINTR},
{"EIO", EIO},
{"ENXIO", ENXIO},
{"E2BIG", E2BIG},
{"ENOEXEC", ENOEXEC},
{"EBADF", EBADF},
{"ECHILD", ECHILD},
{"EAGAIN", EAGAIN},
{"ENOMEM", ENOMEM},
{"EACCES", EACCES},
{"EFAULT", EFAULT},
{"ENOTBLK", ENOTBLK},
{"EBUSY", EBUSY},
{"EEXIST", EEXIST},
{"EXDEV", EXDEV},
{"ENODEV", ENODEV},
{"ENOTDIR", ENOTDIR},
{"EISDIR", EISDIR},
{"EINVAL", EINVAL},
{"ENFILE", ENFILE},
{"EMFILE", EMFILE},
{"ENOTTY", ENOTTY},
{"ETXTBSY", ETXTBSY},
{"EFBIG", EFBIG},
{"ENOSPC", ENOSPC},
{"ESPIPE", ESPIPE},
{"EROFS", EROFS},
{"EMLINK", EMLINK},
{"EPIPE", EPIPE},
{"EDOM", EDOM},
{"ERANGE", ERANGE},
{"EDEADLK", EDEADLK},
{"ENAMETOOLONG", ENAMETOOLONG},
{"ENOLCK", ENOLCK},
{"ENOSYS", ENOSYS},
{"ENOTEMPTY", ENOTEMPTY},
{"ELOOP", ELOOP},
{"EWOULDBLOCK", EWOULDBLOCK},
{"ENOMSG", ENOMSG},
{"EIDRM", EIDRM},
{"ECHRNG", ECHRNG},
{"EL2NSYNC", EL2NSYNC},
{"EL3HLT", EL3HLT},
{"EL3RST", EL3RST},
{"ELNRNG", ELNRNG},
{"EUNATCH", EUNATCH},
{"ENOCSI", ENOCSI},
{"EL2HLT", EL2HLT},
{"EBADE", EBADE},
{"EBADR", EBADR},
{"EXFULL", EXFULL},
{"ENOANO", ENOANO},
{"EBADRQC", EBADRQC},
{"EBADSLT", EBADSLT},
{"EDEADLOCK", EDEADLOCK},
{"EBFONT", EBFONT},
{"ENOSTR", ENOSTR},
{"ENODATA", ENODATA},
{"ETIME", ETIME},
{"ENOSR", ENOSR},
{"ENONET", ENONET},
{"ENOPKG", ENOPKG},
{"EREMOTE", EREMOTE},
{"ENOLINK", ENOLINK},
{"EADV", EADV},
{"ESRMNT", ESRMNT},
{"ECOMM", ECOMM},
{"EPROTO", EPROTO},
{"EMULTIHOP", EMULTIHOP},
{"EDOTDOT", EDOTDOT},
{"EBADMSG", EBADMSG},
{"EOVERFLOW", EOVERFLOW},
{"ENOTUNIQ", ENOTUNIQ},
{"EBADFD", EBADFD},
{"EREMCHG", EREMCHG},
{"ELIBACC", ELIBACC},
{"ELIBBAD", ELIBBAD},
{"ELIBSCN", ELIBSCN},
{"ELIBMAX", ELIBMAX},
{"ELIBEXEC", ELIBEXEC},
{"EILSEQ", EILSEQ},
{"ERESTART", ERESTART},
{"ESTRPIPE", ESTRPIPE},
{"EUSERS", EUSERS},
{"ENOTSOCK", ENOTSOCK},
{"EDESTADDRREQ", EDESTADDRREQ},
{"EMSGSIZE", EMSGSIZE},
{"EPROTOTYPE", EPROTOTYPE},
{"ENOPROTOOPT", ENOPROTOOPT},
{"EPROTONOSUPPORT", EPROTONOSUPPORT},
{"ESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
{"EOPNOTSUPP", EOPNOTSUPP},
{"EPFNOSUPPORT", EPFNOSUPPORT},
{"EAFNOSUPPORT", EAFNOSUPPORT},
{"EADDRINUSE", EADDRINUSE},
{"EADDRNOTAVAIL", EADDRNOTAVAIL},
{"ENETDOWN", ENETDOWN},
{"ENETUNREACH", ENETUNREACH},
{"ENETRESET", ENETRESET},
{"ECONNABORTED", ECONNABORTED},
{"ECONNRESET", ECONNRESET},
{"ENOBUFS", ENOBUFS},
{"EISCONN", EISCONN},
{"ENOTCONN", ENOTCONN},
{"ESHUTDOWN", ESHUTDOWN},
{"ETOOMANYREFS", ETOOMANYREFS},
{"ETIMEDOUT", ETIMEDOUT},
{"ECONNREFUSED", ECONNREFUSED},
{"EHOSTDOWN", EHOSTDOWN},
{"EHOSTUNREACH", EHOSTUNREACH},
{"EALREADY", EALREADY},
{"EINPROGRESS", EINPROGRESS},
{"ESTALE", ESTALE},
{"EUCLEAN", EUCLEAN},
{"ENOTNAM", ENOTNAM},
{"ENAVAIL", ENAVAIL},
{"EISNAM", EISNAM},
{"EREMOTEIO", EREMOTEIO},
{"EDQUOT", EDQUOT},
{"ENOMEDIUM", ENOMEDIUM},
{"EMEDIUMTYPE", EMEDIUMTYPE},
{"ECANCELED", ECANCELED},
{"ENOKEY", ENOKEY},
{"EKEYEXPIRED", EKEYEXPIRED},
{"EKEYREVOKED", EKEYREVOKED},
{"EKEYREJECTED", EKEYREJECTED},
{"EOWNERDEAD", EOWNERDEAD},
{"ENOTRECOVERABLE", ENOTRECOVERABLE},
{"ERFKILL", ERFKILL},
{"EHWPOISON", EHWPOISON},
});
std::string ErrnoToName(int n) {
int err = n;
if (err < 0) {
err = -err;
}
auto str = std::string(s_errno_table.ToString(n));
if (str.empty()) {
str = std::to_string(n);
}
if (n < 0) {
return "-" + str;
} else {
return str;
}
}
int NameToErrno(const std::string_view& name) {
if (!name.empty() && name[0] == '-') {
return -(s_errno_table.ToInt(name.substr(1)));
} else {
return s_errno_table.ToInt(name);
}
}

Просмотреть файл

@ -204,8 +204,9 @@ void UserDB::update_task()
} }
} }
void parse_file(const std::string& path, std::unordered_map<int, std::string>& db) std::vector<std::pair<int, std::string>> parse_file(const std::string& path)
{ {
std::vector<std::pair<int, std::string>> entries;
std::ifstream fs(path); std::ifstream fs(path);
int line_num = 1; int line_num = 1;
@ -232,11 +233,9 @@ void parse_file(const std::string& path, std::unordered_map<int, std::string>& d
} catch (...) { } catch (...) {
continue; continue;
} }
// Just in case there are multiple entries, only the first id->name is used entries.emplace_back(id, name);
if (db.count(id) == 0) {
db.emplace(std::make_pair(id, name));
}
} }
return entries;
} }
void UserDB::update() void UserDB::update()
@ -245,8 +244,18 @@ void UserDB::update()
std::unordered_map<int, std::string> groups; std::unordered_map<int, std::string> groups;
try { try {
parse_file(_dir + "/passwd", users); for (auto& e : parse_file(_dir + "/passwd")) {
parse_file(_dir + "/group", groups); // Just in case there are multiple entries, only the first id->name is used
if (users.count(e.first) == 0) {
users.emplace(e);
}
}
for (auto& e : parse_file(_dir + "/group")) {
// Just in case there are multiple entries, only the first id->name is used
if (groups.count(e.first) == 0) {
groups.emplace(e);
}
}
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
Logger::Warn("UserDB: Update failed: %s", ex.what()); Logger::Warn("UserDB: Update failed: %s", ex.what());
return; return;
@ -256,3 +265,29 @@ void UserDB::update()
_users = users; _users = users;
_groups = groups; _groups = groups;
} }
int UserDB::UserNameToUid(const std::string& name) {
try {
for (auto& e : parse_file("/etc/passwd")) {
if (e.second == name) {
return e.first;
}
}
} catch (const std::exception& ex) {
return -1;
}
return -1;
}
int UserDB::GroupNameToGid(const std::string& name) {
try {
for (auto& e : parse_file("/etc/group")) {
if (e.second == name) {
return e.first;
}
}
} catch (const std::exception& ex) {
return -1;
}
return -1;
}

Просмотреть файл

@ -37,6 +37,9 @@ public:
void update(); // Exposed only to simplify tests void update(); // Exposed only to simplify tests
static int UserNameToUid(const std::string& name);
static int GroupNameToGid(const std::string& name);
private: private:
void inotify_task(); void inotify_task();

Просмотреть файл

@ -8,6 +8,6 @@
AUOMS_BUILDVERSION_MAJOR=2 AUOMS_BUILDVERSION_MAJOR=2
AUOMS_BUILDVERSION_MINOR=0 AUOMS_BUILDVERSION_MINOR=0
AUOMS_BUILDVERSION_PATCH=0 AUOMS_BUILDVERSION_PATCH=0
AUOMS_BUILDVERSION_BUILDNR=10 AUOMS_BUILDVERSION_BUILDNR=12
AUOMS_BUILDVERSION_DATE=20190421 AUOMS_BUILDVERSION_DATE=20190501
AUOMS_BUILDVERSION_STATUS=Developer_Build AUOMS_BUILDVERSION_STATUS=Developer_Build

Просмотреть файл

@ -77,9 +77,6 @@ int show_audit_status() {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Netlink netlink; Netlink netlink;
netlink.SetQuite(); netlink.SetQuite();
@ -116,9 +113,6 @@ int list_rules(bool raw_fmt, const std::string& key) {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Netlink netlink; Netlink netlink;
netlink.SetQuite(); netlink.SetQuite();
@ -163,9 +157,6 @@ int delete_rules(const std::string& key) {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Netlink netlink; Netlink netlink;
netlink.SetQuite(); netlink.SetQuite();
@ -222,10 +213,7 @@ int load_rules(const std::string& path) {
int exit_code = 0; int exit_code = 0;
try { try {
auto lines = ReadFile(path); auto lines = ReadFile(path);
auto rules = ParseRules(lines); auto rules = ParseRules(lines, nullptr);
Signals::Init();
Signals::Start();
Netlink netlink; Netlink netlink;
netlink.SetQuite(); netlink.SetQuite();
@ -268,9 +256,16 @@ int load_rules(const std::string& path) {
int print_rules(const std::string& path) { int print_rules(const std::string& path) {
try { try {
auto lines = ReadFile(path); auto lines = ReadFile(path);
auto rules = ParseRules(lines); std::vector<AuditRule> rules;
for (auto& rule: rules) { for (int i = 0; i < lines.size(); ++i) {
std::cout << rule.CanonicalText() << std::endl; AuditRule rule;
std::string error;
if (rule.Parse(lines[i], error)) {
std::cout << rule.CanonicalText() << std::endl;
} else if (!error.empty()) {
std::cout << "Failed to parse line " << i+1 << ": " << error << std::endl;
std::cout << " " << lines[i] << std::endl;
}
} }
} catch (std::exception& ex) { } catch (std::exception& ex) {
std::cerr << ex.what() << std::endl; std::cerr << ex.what() << std::endl;
@ -282,8 +277,8 @@ int print_rules(const std::string& path) {
int merge_rules(const std::string& file1, const std::string& file2) { int merge_rules(const std::string& file1, const std::string& file2) {
try { try {
auto rules1 = ParseRules(ReadFile(file1)); auto rules1 = ParseRules(ReadFile(file1), nullptr);
auto rules2 = ParseRules(ReadFile(file2)); auto rules2 = ParseRules(ReadFile(file2), nullptr);
auto merged_rules = MergeRules(rules1, rules2); auto merged_rules = MergeRules(rules1, rules2);
for (auto& rule: merged_rules) { for (auto& rule: merged_rules) {
std::cout << rule.CanonicalText() << std::endl; std::cout << rule.CanonicalText() << std::endl;
@ -298,8 +293,8 @@ int merge_rules(const std::string& file1, const std::string& file2) {
int diff_rules(const std::string& file1, const std::string& file2) { int diff_rules(const std::string& file1, const std::string& file2) {
try { try {
auto rules1 = MergeRules(ParseRules(ReadFile(file1))); auto rules1 = MergeRules(ParseRules(ReadFile(file1), nullptr));
auto rules2 = MergeRules(ParseRules(ReadFile(file2))); auto rules2 = MergeRules(ParseRules(ReadFile(file2), nullptr));
auto diffed_rules = DiffRules(rules1, rules2, ""); auto diffed_rules = DiffRules(rules1, rules2, "");
for (auto& rule: diffed_rules) { for (auto& rule: diffed_rules) {
std::cout << rule.CanonicalText() << std::endl; std::cout << rule.CanonicalText() << std::endl;
@ -318,9 +313,6 @@ int show_auoms_status() {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
UnixDomainWriter io("/var/run/auoms/status.socket"); UnixDomainWriter io("/var/run/auoms/status.socket");
if (!io.Open()) { if (!io.Open()) {
std::cout << "auoms is not running" << std::endl; std::cout << "auoms is not running" << std::endl;
@ -676,10 +668,6 @@ int enable_auoms() {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Signals::SetExitHandler([](){ exit(1); });
// Return // Return
// 0 on success // 0 on success
// 1 if service could not be enabled // 1 if service could not be enabled
@ -739,10 +727,6 @@ int disable_auoms() {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Signals::SetExitHandler([](){ exit(1); });
// Return // Return
// 0 on success // 0 on success
// 1 if service could not be disabled // 1 if service could not be disabled
@ -884,9 +868,6 @@ int tap_audit() {
return false; return false;
}; };
Signals::Init();
Signals::Start();
Logger::Info("Connecting to AUDIT NETLINK socket"); Logger::Info("Connecting to AUDIT NETLINK socket");
auto ret = netlink.Open(handler); auto ret = netlink.Open(handler);
if (ret != 0) { if (ret != 0) {
@ -1068,9 +1049,6 @@ int monitor_auoms_events() {
std::string sock_path = "/var/run/auoms/auomsctl.socket"; std::string sock_path = "/var/run/auoms/auomsctl.socket";
std::string config_path = "/etc/opt/microsoft/auoms/outconf.d/auomsctl.conf"; std::string config_path = "/etc/opt/microsoft/auoms/outconf.d/auomsctl.conf";
Signals::Init();
Signals::Start();
UnixDomainListener listener(sock_path, 0666); UnixDomainListener listener(sock_path, 0666);
if (!listener.Open()) { if (!listener.Open()) {
return -1; return -1;
@ -1106,7 +1084,7 @@ int monitor_auoms_events() {
} }
int set_rules() { int set_rules() {
auto rules = ReadAuditRulesFromDir("/etc/opt/microsoft/auoms/rules.d"); auto rules = ReadAuditRulesFromDir("/etc/opt/microsoft/auoms/rules.d", nullptr);
std::vector<AuditRule> desired_rules; std::vector<AuditRule> desired_rules;
for (auto& rule: rules) { for (auto& rule: rules) {
// Only include the rule in the desired rules if it is supported on the host system // Only include the rule in the desired rules if it is supported on the host system
@ -1117,14 +1095,14 @@ int set_rules() {
} }
try { try {
auto rules = ReadActualAuditdRules(false); auto rules = ReadActualAuditdRules(false, nullptr);
auto diff = DiffRules(rules, desired_rules, ""); auto diff = DiffRules(rules, desired_rules, "");
if (diff.empty()) { if (diff.empty()) {
return 0; return 0;
} }
Logger::Info("AuditRulesMonitor: Found desired audit rules not currently present in auditd rules files(s), adding new rules"); Logger::Info("AuditRulesMonitor: Found desired audit rules not currently present in auditd rules files(s), adding new rules");
// Re-read rules but exclude auoms rules // Re-read rules but exclude auoms rules
rules = ReadActualAuditdRules(true); rules = ReadActualAuditdRules(true, nullptr);
// Re-calculate diff // Re-calculate diff
diff = DiffRules(rules, desired_rules, ""); diff = DiffRules(rules, desired_rules, "");
if (WriteAuditdRules(diff)) { if (WriteAuditdRules(diff)) {
@ -1156,7 +1134,7 @@ bool is_set_intersect(T a, T b) {
} }
int load_rules() { int load_rules() {
auto rules = ReadAuditRulesFromDir("/etc/opt/microsoft/auoms/rules.d"); auto rules = ReadAuditRulesFromDir("/etc/opt/microsoft/auoms/rules.d", nullptr);
std::vector<AuditRule> desired_rules; std::vector<AuditRule> desired_rules;
for (auto& rule: rules) { for (auto& rule: rules) {
// Only include the rule in the desired rules if it is supported on the host system // Only include the rule in the desired rules if it is supported on the host system
@ -1168,9 +1146,6 @@ int load_rules() {
Netlink netlink; Netlink netlink;
Signals::Init();
Signals::Start();
Logger::Info("Connecting to AUDIT NETLINK socket"); Logger::Info("Connecting to AUDIT NETLINK socket");
auto ret = netlink.Open(nullptr); auto ret = netlink.Open(nullptr);
if (ret != 0) { if (ret != 0) {
@ -1285,10 +1260,6 @@ int upgrade() {
return 1; return 1;
} }
Signals::Init();
Signals::Start();
Signals::SetExitHandler([](){ exit(1); });
try { try {
// Use auditd plugin file to determine if auoms should be enabled // Use auditd plugin file to determine if auoms should be enabled
if (is_auditd_plugin_enabled()) { if (is_auditd_plugin_enabled()) {
@ -1354,6 +1325,10 @@ int main(int argc, char**argv) {
exit(1); exit(1);
} }
Signals::Init();
Signals::Start();
Signals::SetExitHandler([](){ exit(1); });
if (strcmp(argv[1], "-v") == 0) { if (strcmp(argv[1], "-v") == 0) {
std::cout << std::string(AUOMS_VERSION) << std::endl; std::cout << std::string(AUOMS_VERSION) << std::endl;
return 0; return 0;

Просмотреть файл

@ -15,7 +15,7 @@
# Default is ${run_dir}/input.socket # Default is ${run_dir}/input.socket
#socket_path = /var/run/auoms/input.socket #socket_path = /var/run/auoms/input.socket
# The path to the file where auomscollect will keep trask of which events have been sent to auoms # The path to the file where auomscollect will keep track of which events have been sent to auoms
# #
# Default is ${data_dir}/collect.cursor # Default is ${data_dir}/collect.cursor
#cursor_path = /var/opt/microsoft/auoms/data/collect.cursor #cursor_path = /var/opt/microsoft/auoms/data/collect.cursor

Просмотреть файл

@ -28,7 +28,6 @@ if [ "$1" = "upgrade" ]; then
fi fi
%Postinstall_100 %Postinstall_100
echo "Postinstall_100 $1"
if [ "$1" = "configure" ]; then if [ "$1" = "configure" ]; then
if [ -e ${{AUOMS_AUDISP_CONF}}.auomssave ]; then if [ -e ${{AUOMS_AUDISP_CONF}}.auomssave ]; then
if [ -e ${{AUOMS_AUDISP_CONF}} ]; then if [ -e ${{AUOMS_AUDISP_CONF}} ]; then