Skip to content

Commit

Permalink
Add support for offline mode in XCCDF result (Evaluation Characterist…
Browse files Browse the repository at this point in the history
…ics)

Also OSCAP_EVALUATION_TARGET is collected as xccdf:facts:identifier
and target is always a hostname.
  • Loading branch information
evgenyz committed Apr 27, 2020
1 parent 3dd51c7 commit 243cb6a
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 67 deletions.
5 changes: 5 additions & 0 deletions src/DS/rds.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,11 @@ static xmlNodePtr ds_rds_add_ai_from_xccdf_results(xmlDocPtr doc, xmlNodePtr ass
}
}

if (xmlGetLastChild(connections) == NULL) {
xmlUnlinkNode(connections);
xmlFreeNode(connections);
}

return asset;
}

Expand Down
172 changes: 105 additions & 67 deletions src/XCCDF/result.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,29 +209,56 @@ static inline void _xccdf_result_clear_metadata(struct xccdf_item *result)
NULL);
}

#ifdef OSCAP_UNIX
static char *_get_etc_hostname(const char *oscap_probe_root)
{
FILE *fp;
char hname[HOST_NAME_MAX+1] = { '\0' };
char *ret = NULL;
int rc;

fp = oscap_fopen_with_prefix(oscap_probe_root, "/etc/hostname");

if (fp == NULL)
goto fail;

rc = fread(hname, 1, HOST_NAME_MAX, fp);
/* If file is empty, we don't want to allocate an empty string for it */
if (ferror(fp) || rc == 0 )
goto finish;

hname[strcspn(hname, "\n")] = '\0';
ret = strdup(hname);

finish:
fclose(fp);
fail:
return ret;
}
#endif

void xccdf_result_fill_sysinfo(struct xccdf_result *result)
{
#if defined(OS_LINUX)
struct ifaddrs *ifaddr, *ifa;
int fd;
#endif
struct xccdf_target_fact *fact = NULL;
const char *probe_root = getenv("OSCAP_PROBE_ROOT");

#ifdef OSCAP_UNIX
struct utsname sname;

if (uname(&sname) == -1)
return;

_xccdf_result_clear_metadata(XITEM(result));

/* override target name by environment variable */
const char *target_hostname = getenv("OSCAP_EVALUATION_TARGET");
if (target_hostname == NULL) {
target_hostname = sname.nodename;
char *hostname = NULL;
if (probe_root) {
hostname = _get_etc_hostname(probe_root);
} else {
struct utsname sname;
if (uname(&sname) != -1)
hostname = strdup(sname.nodename);
}

/* store target name */
xccdf_result_add_target(result, target_hostname);
xccdf_result_add_target(result, hostname ? hostname : "Unknown");
free(hostname);
#elif defined(OS_WINDOWS)
TCHAR computer_name[MAX_COMPUTERNAME_LENGTH + 1];
DWORD computer_name_size = MAX_COMPUTERNAME_LENGTH + 1;
Expand All @@ -240,68 +267,79 @@ void xccdf_result_fill_sysinfo(struct xccdf_result *result)
xccdf_result_add_target(result, computer_name);
#endif

const char *ev_target = getenv("OSCAP_EVALUATION_TARGET");
if (ev_target) {
fact = xccdf_target_fact_new();
xccdf_target_fact_set_name(fact, "urn:xccdf:fact:identifier");
xccdf_target_fact_set_string(fact, ev_target);
xccdf_result_add_target_fact(result, fact);
}

_xccdf_result_fill_scanner(result);
_xccdf_result_fill_identity(result);

if (!probe_root)
_xccdf_result_fill_identity(result);

#if defined(OS_LINUX)

/* get network interfaces */
if (getifaddrs(&ifaddr) == -1)
return;
if (!probe_root) {
/* get network interfaces */
if (getifaddrs(&ifaddr) == -1)
return;

fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd == -1)
goto out1;

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
int family;
char hostip[NI_MAXHOST];
struct ifreq ifr;

if (!ifa->ifa_addr)
continue;
family = ifa->ifa_addr->sa_family;
if (family != AF_INET && family != AF_INET6)
continue;

if (family == AF_INET) {
if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in),
hostip, sizeof(hostip), NULL, 0, NI_NUMERICHOST))
goto out2;
} else {
struct sockaddr_in6 *sin6;

sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
if (!inet_ntop(family, (const void *) &sin6->sin6_addr,
hostip, sizeof(hostip)))
goto out2;
}
/* store ip address */
xccdf_result_add_target_address(result, hostip);

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0;
if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) {
struct xccdf_target_fact *fact;
unsigned char mac[6];
char macbuf[20];

memcpy(mac, ifr.ifr_hwaddr.sa_data, sizeof(mac));
snprintf(macbuf, sizeof(macbuf), "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
fact = xccdf_target_fact_new();
xccdf_target_fact_set_name(fact, "urn:xccdf:fact:ethernet:MAC");
xccdf_target_fact_set_string(fact, macbuf);
/* store mac address */
xccdf_result_add_target_fact(result, fact);
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd == -1)
goto out1;

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
int family;
char hostip[NI_MAXHOST];
struct ifreq ifr;

if (!ifa->ifa_addr)
continue;
family = ifa->ifa_addr->sa_family;
if (family != AF_INET && family != AF_INET6)
continue;

if (family == AF_INET) {
if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in),
hostip, sizeof(hostip), NULL, 0, NI_NUMERICHOST))
goto out2;
} else {
struct sockaddr_in6 *sin6;

sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
if (!inet_ntop(family, (const void *) &sin6->sin6_addr,
hostip, sizeof(hostip)))
goto out2;
}
/* store ip address */
xccdf_result_add_target_address(result, hostip);

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0;
if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) {
unsigned char mac[6];
char macbuf[20];

memcpy(mac, ifr.ifr_hwaddr.sa_data, sizeof(mac));
snprintf(macbuf, sizeof(macbuf), "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
fact = xccdf_target_fact_new();
xccdf_target_fact_set_name(fact, "urn:xccdf:fact:ethernet:MAC");
xccdf_target_fact_set_string(fact, macbuf);
/* store mac address */
xccdf_result_add_target_fact(result, fact);
}
}
}

out2:
close(fd);
out1:
freeifaddrs(ifaddr);
out2:
close(fd);
out1:
freeifaddrs(ifaddr);
}

#elif defined(OS_WINDOWS)

Expand Down
6 changes: 6 additions & 0 deletions xsl/xccdf-report-impl.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ Authors:
<xsl:value-of select="$testresult/cdf:target/text()"/>
</td>
</tr>
<xsl:if test="$testresult/cdf:target-facts/cdf:fact[@name = 'urn:xccdf:fact:identifier']">
<tr>
<th>Target ID</th>
<td><xsl:value-of select="$testresult/cdf:target-facts/cdf:fact[@name = 'urn:xccdf:fact:identifier']/text()"/></td>
</tr>
</xsl:if>
<xsl:if test="$testresult/cdf:benchmark">
<tr>
<th>Benchmark URL</th>
Expand Down

0 comments on commit 243cb6a

Please sign in to comment.