diff --git a/osquery/config/tests/config_tests.cpp b/osquery/config/tests/config_tests.cpp index e75da6ba..34c9865a 100644 --- a/osquery/config/tests/config_tests.cpp +++ b/osquery/config/tests/config_tests.cpp @@ -7,6 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. * */ + #include #include diff --git a/osquery/events/linux/audit.cpp b/osquery/events/linux/audit.cpp index 571e2248..5b781dbd 100644 --- a/osquery/events/linux/audit.cpp +++ b/osquery/events/linux/audit.cpp @@ -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 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. diff --git a/osquery/events/linux/tests/audit_tests.cpp b/osquery/events/linux/tests/audit_tests.cpp index 775ab425..14dbcf53 100644 --- a/osquery/events/linux/tests/audit_tests.cpp +++ b/osquery/events/linux/tests/audit_tests.cpp @@ -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) {