mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-06 09:35:20 +00:00
Refactor Windows interface_addresses table to use win32 API and report accurate netmasks. (#3297)
This commit is contained in:
parent
e9dc7b0aa5
commit
05b7b80891
@ -10,6 +10,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
// clang-format off
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
// clang-format on
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
||||
#include <osquery/core.h>
|
||||
@ -21,6 +27,9 @@
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
auto kMaxBufferAllocRetries = 3;
|
||||
auto kWorkingBufferSize = 15000;
|
||||
|
||||
QueryData genInterfaceDetails(QueryContext& context) {
|
||||
QueryData results_data;
|
||||
WmiRequest request("SELECT * FROM Win32_NetworkAdapter");
|
||||
@ -80,32 +89,98 @@ QueryData genInterfaceDetails(QueryContext& context) {
|
||||
}
|
||||
|
||||
QueryData genInterfaceAddresses(QueryContext& context) {
|
||||
QueryData results_data;
|
||||
WmiRequest request(
|
||||
"SELECT * FROM win32_networkadapterconfiguration where IPEnabled=TRUE");
|
||||
if (request.getStatus().ok()) {
|
||||
std::vector<WmiResultItem>& results = request.results();
|
||||
for (const auto& result : results) {
|
||||
Row r;
|
||||
long lPlaceHolder;
|
||||
std::vector<std::string> vPlaceHolderIps;
|
||||
std::vector<std::string> vPlaceHolderSubnets;
|
||||
QueryData results;
|
||||
DWORD buffSize = kWorkingBufferSize;
|
||||
auto alloc_attempts = 0;
|
||||
size_t alloc_result;
|
||||
const auto addrFamily = AF_UNSPEC;
|
||||
const auto addrFlags =
|
||||
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
|
||||
const auto freeMem = [](auto ptr) { free(ptr); };
|
||||
std::unique_ptr<IP_ADAPTER_ADDRESSES, decltype(freeMem)> adapters(nullptr,
|
||||
freeMem);
|
||||
|
||||
result.GetLong("InterfaceIndex", lPlaceHolder);
|
||||
r["interface"] = SQL_TEXT(lPlaceHolder);
|
||||
result.GetVectorOfStrings("IPAddress", vPlaceHolderIps);
|
||||
result.GetVectorOfStrings("IPSubnet", vPlaceHolderSubnets);
|
||||
for (size_t i = 0; i < vPlaceHolderIps.size(); i++) {
|
||||
r["address"] = SQL_TEXT(vPlaceHolderIps.at(i));
|
||||
if (vPlaceHolderSubnets.size() > i) {
|
||||
r["mask"] = SQL_TEXT(vPlaceHolderSubnets.at(i));
|
||||
}
|
||||
results_data.push_back(r);
|
||||
}
|
||||
// Buffer size can change between the query and malloc (if adapters are
|
||||
// added/removed), so shenanigans are required
|
||||
do {
|
||||
adapters.reset(static_cast<PIP_ADAPTER_ADDRESSES>(malloc(buffSize)));
|
||||
if (adapters == nullptr) {
|
||||
return results;
|
||||
}
|
||||
alloc_result = GetAdaptersAddresses(
|
||||
addrFamily, addrFlags, nullptr, adapters.get(), &buffSize);
|
||||
alloc_attempts++;
|
||||
} while (alloc_result == ERROR_BUFFER_OVERFLOW &&
|
||||
alloc_attempts < kMaxBufferAllocRetries);
|
||||
if (alloc_result != NO_ERROR) {
|
||||
return results;
|
||||
}
|
||||
|
||||
return results_data;
|
||||
const IP_ADAPTER_ADDRESSES* currAdapter = adapters.get();
|
||||
while (currAdapter != nullptr) {
|
||||
std::wstring wsAdapterName = std::wstring(currAdapter->FriendlyName);
|
||||
std::string adapterName =
|
||||
std::string(wsAdapterName.begin(), wsAdapterName.end());
|
||||
|
||||
const IP_ADAPTER_UNICAST_ADDRESS* ipaddr = currAdapter->FirstUnicastAddress;
|
||||
while (ipaddr != nullptr) {
|
||||
Row r;
|
||||
r["interface"] = adapterName;
|
||||
|
||||
switch (ipaddr->SuffixOrigin) {
|
||||
case IpSuffixOriginManual:
|
||||
r["type"] = "manual";
|
||||
break;
|
||||
case IpSuffixOriginDhcp:
|
||||
r["type"] = "dhcp";
|
||||
break;
|
||||
case IpSuffixOriginLinkLayerAddress:
|
||||
case IpSuffixOriginRandom:
|
||||
r["type"] = "auto";
|
||||
break;
|
||||
default:
|
||||
r["type"] = "unknown";
|
||||
}
|
||||
|
||||
if (ipaddr->Address.lpSockaddr->sa_family == AF_INET) {
|
||||
ULONG mask;
|
||||
ConvertLengthToIpv4Mask(ipaddr->OnLinkPrefixLength, &mask);
|
||||
in_addr maskAddr;
|
||||
maskAddr.s_addr = mask;
|
||||
|
||||
char addrBuff[INET_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET, &maskAddr, addrBuff, INET_ADDRSTRLEN);
|
||||
r["mask"] = addrBuff;
|
||||
|
||||
inet_ntop(AF_INET,
|
||||
&reinterpret_cast<sockaddr_in*>(ipaddr->Address.lpSockaddr)
|
||||
->sin_addr,
|
||||
addrBuff,
|
||||
INET_ADDRSTRLEN);
|
||||
r["address"] = addrBuff;
|
||||
} else if (ipaddr->Address.lpSockaddr->sa_family == AF_INET6) {
|
||||
in6_addr netmask;
|
||||
memset(&netmask, 0x0, sizeof(netmask));
|
||||
for (long i = ipaddr->OnLinkPrefixLength, j = 0; i > 0; i -= 8, ++j)
|
||||
netmask.s6_addr[j] = i >= 8 ? 0xff : (ULONG)((0xffU << (8 - i)));
|
||||
|
||||
char addrBuff[INET6_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET6, &netmask, addrBuff, INET6_ADDRSTRLEN);
|
||||
r["mask"] = addrBuff;
|
||||
|
||||
inet_ntop(AF_INET6,
|
||||
&reinterpret_cast<sockaddr_in6*>(ipaddr->Address.lpSockaddr)
|
||||
->sin6_addr,
|
||||
addrBuff,
|
||||
INET6_ADDRSTRLEN);
|
||||
r["address"] = addrBuff;
|
||||
}
|
||||
results.emplace_back(r);
|
||||
ipaddr = ipaddr->Next;
|
||||
}
|
||||
currAdapter = currAdapter->Next;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace tables
|
||||
} // namespace osquery
|
||||
|
@ -45,15 +45,13 @@ const std::map<int, std::string> kServiceType = {
|
||||
auto closeServiceHandle = [](SC_HANDLE sch) { CloseServiceHandle(sch); };
|
||||
using svc_handle_t = std::unique_ptr<SC_HANDLE__, decltype(closeServiceHandle)>;
|
||||
|
||||
auto freeMem = [](auto ptr) { free(ptr); };
|
||||
using svc_descr_t = std::unique_ptr<SERVICE_DESCRIPTION, decltype(freeMem)>;
|
||||
using svc_query_t = std::unique_ptr<QUERY_SERVICE_CONFIG, decltype(freeMem)>;
|
||||
using enum_svc_status_t =
|
||||
std::unique_ptr<ENUM_SERVICE_STATUS_PROCESS[], decltype(freeMem)>;
|
||||
|
||||
static inline Status getService(const SC_HANDLE& scmHandle,
|
||||
const ENUM_SERVICE_STATUS_PROCESS& svc,
|
||||
QueryData& results) {
|
||||
auto freeMem = [](auto ptr) { free(ptr); };
|
||||
using svc_descr_t = std::unique_ptr<SERVICE_DESCRIPTION, decltype(freeMem)>;
|
||||
using svc_query_t = std::unique_ptr<QUERY_SERVICE_CONFIG, decltype(freeMem)>;
|
||||
|
||||
Row r;
|
||||
svc_handle_t svcHandle(
|
||||
OpenService(scmHandle, svc.lpServiceName, SERVICE_QUERY_CONFIG),
|
||||
@ -139,6 +137,11 @@ static inline Status getService(const SC_HANDLE& scmHandle,
|
||||
}
|
||||
|
||||
static inline Status getServices(QueryData& results) {
|
||||
auto freeMem = [](auto ptr) { free(ptr); };
|
||||
using svc_descr_t = std::unique_ptr<SERVICE_DESCRIPTION, decltype(freeMem)>;
|
||||
using enum_svc_status_t =
|
||||
std::unique_ptr<ENUM_SERVICE_STATUS_PROCESS[], decltype(freeMem)>;
|
||||
|
||||
svc_handle_t scmHandle(OpenSCManager(nullptr, nullptr, GENERIC_READ),
|
||||
closeServiceHandle);
|
||||
if (scmHandle == nullptr) {
|
||||
|
@ -6,6 +6,7 @@ schema([
|
||||
Column("mask", TEXT, "Interface netmask"),
|
||||
Column("broadcast", TEXT, "Broadcast address for the interface"),
|
||||
Column("point_to_point", TEXT, "PtP address for the interface"),
|
||||
Column("type", TEXT, "Type of address. One of dhcp, manual, auto, other")
|
||||
])
|
||||
attributes(cacheable=True)
|
||||
implementation("interfaces@genInterfaceAddresses")
|
||||
|
Loading…
Reference in New Issue
Block a user