Fix auditd message parsing

This commit is contained in:
Teddy Reed 2015-10-27 15:10:58 -07:00
parent 689ec53a71
commit a3067fcbb5
3 changed files with 49 additions and 16 deletions

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include <memory>
#include <vector>

View File

@ -169,22 +169,51 @@ inline bool handleAuditReply(const struct audit_reply& reply,
// Tokenize the message.
auto message = std::string(reply.message, reply.len);
std::vector<std::string> fields;
boost::split(fields, message, boost::is_any_of(" ="));
std::string().swap(message);
auto preamble_end = message.find("): ");
if (preamble_end == std::string::npos) {
return false;
} else {
ec->preamble = message.substr(0, preamble_end + 1);
message = message.substr(preamble_end + 3);
}
// Iterate over each field=value pair.
auto field_it = fields.begin();
ec->preamble = std::move(*field_it);
for (++field_it; field_it != fields.end(); field_it++) {
const auto& key = *field_it;
if (++field_it == fields.end()) {
// A malformed message will have had an odd number of fields=value
// pairs, discard the event.
return false;
// The linear search will construct series of key value pairs.
std::string key, value;
// There are several ways of representing value data (enclosed strings, etc).
bool found_assignment{false}, found_enclose{false};
for (const auto& c : message) {
// Iterate over each character in the audit message.
if ((found_enclose && c == '"') || (!found_enclose && c == ' ')) {
if (c == '"') {
value += c;
}
// This is a terminating sequence, the end of an enclosure or space tok.
if (!key.empty()) {
// Multiple space tokens are supported.
ec->fields[key] = value;
}
found_enclose = false;
found_assignment = false;
key.clear();
value.clear();
} else if (!found_assignment && c == ' ') {
// A field tokenizer.
} else if (found_assignment) {
// Enclosure sequences appear immediately following assignment.
if (c == '"') {
found_enclose = true;
}
value += c;
} else if (c == '=') {
found_assignment = true;
} else {
key += c;
}
// Assign the key/value pair.
ec->fields[key] = std::move(*field_it);
}
// Last step, if there was no trailing tokenizer.
if (!key.empty()) {
ec->fields[key] = value;
}
// There is a special field for syscalls.

View File

@ -43,7 +43,7 @@ TEST_F(AuditTests, test_handle_reply) {
// A 'fake' audit message.
std::string message =
"audit(1440542781.644:403030): argc=3 a0=\"/bin/sh\" a1=\"-c\" a2=\"h\"";
"audit(1440542781.644:403030): argc=3 a0=\"H=1 \" a1=\"/bin/sh\" a2=c";
reply.type = 1;
reply.len = message.size();
@ -56,10 +56,13 @@ TEST_F(AuditTests, test_handle_reply) {
free((char*)reply.message);
EXPECT_EQ(reply.type, ec->type);
EXPECT_EQ(ec->preamble, "audit(1440542781.644:403030)");
EXPECT_EQ(ec->fields.size(), 4U);
EXPECT_EQ(ec->fields.count("argc"), 1U);
EXPECT_EQ(ec->fields["argc"], "3");
EXPECT_EQ(ec->fields["a0"], "\"/bin/sh\"");
EXPECT_EQ(ec->fields["a0"], "\"H=1 \"");
EXPECT_EQ(ec->fields["a1"], "\"/bin/sh\"");
EXPECT_EQ(ec->fields["a2"], "c");
}
TEST_F(AuditTests, test_audit_value_decode) {