Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 17 additions & 60 deletions src/common/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@

#ifdef OS_WINDOWS
#include <stdlib.h>
#include <winsock2.h>

Check warning on line 46 in src/common/util.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

non-portable path to file '<WinSock2.h>'; specified path differs in case from file name on disk

See more on https://sonarcloud.io/project/issues?id=OpenSCAP_openscap&issues=AaFodk9jbuRPE_xln-iX&open=AaFodk9jbuRPE_xln-iX&pullRequest=2473
#include <ws2tcpip.h>

Check warning on line 47 in src/common/util.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

non-portable path to file '<WS2tcpip.h>'; specified path differs in case from file name on disk

See more on https://sonarcloud.io/project/issues?id=OpenSCAP_openscap&issues=AaFodk9jbuRPE_xln-iY&open=AaFodk9jbuRPE_xln-iY&pullRequest=2473
#include <windows.h>
#else
#include <arpa/inet.h>
#include <libgen.h>
#include <strings.h>
#include <sys/socket.h>
#endif

#define PATH_SEPARATOR '/'
Expand Down Expand Up @@ -200,67 +204,20 @@

char *oscap_expand_ipv6(const char *input)
{
// we have to do a double pass because we need to know the number of
// specified components, :: will fill up to a total of 8 if encountered

const char* input_it = input;
unsigned short component_count = 1; // fencepost, we start with 1
while (*input_it) {
if (*input_it == ':') {
// don't count ::1 as 2 components
if (input_it != input)
component_count++;

// the next character is either a part of a component or another ':'
// in any case we don't want to count it
input_it++;
}

input_it++;
}
unsigned char b[16];

// IPv6 is at most eight 4-tuples of [0-9a-f] with 7 separators, plus \0
char* ret = malloc(8 * 4 * sizeof(char) + 7 + 1);
char* output_it = ret;

input_it = input;
while (*input_it) {
// signifies that we have finished writing a component this iteration
bool closed_component = false;

if (*input_it == ':') {
const char next = *(input_it + 1 * sizeof(char));
if (next == ':') {
// skip one extra char to skip over the whole ::
input_it++;

for (unsigned short i = component_count; i < 8; ++i) {
// don't add leading separators
if (output_it != ret)
*output_it++ = ':';

*output_it++ = '0';
closed_component = true;
}
}
else {
closed_component = true;
}
}
else {
*output_it++ = *input_it;
}

input_it++;

// if this was not the last char of the input add a separator
if (closed_component && *input_it)
*output_it++ = ':';
}

*output_it = '\0';

return ret;
/*
* glibc rejects a %zone; macOS inet_pton drops it, writing the
* interface index into the second group of link-local addresses.
*/
if (strchr(input, '%') != NULL || inet_pton(AF_INET6, input, b) != 1)
return oscap_strdup(input);

return oscap_sprintf("%x:%x:%x:%x:%x:%x:%x:%x",
b[0] * 256u + b[1], b[2] * 256u + b[3],
b[4] * 256u + b[5], b[6] * 256u + b[7],
b[8] * 256u + b[9], b[10] * 256u + b[11],
b[12] * 256u + b[13], b[14] * 256u + b[15]);
}

char *oscap_realpath(const char *path, char *resolved_path)
Expand Down
3 changes: 3 additions & 0 deletions src/common/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ bool oscap_ptr_cmp(void *node1, void *node2);
* Asset Identification specification requires fully expanded IPv6 addresses.
* Despite this being greatly discouraged by RFC 5952 we have to comply and
* expand given IPv6, otherwise the resulting AI content would be invalid.
*
* @return newly allocated expanded address, or a copy of input if it is not
* an IPv6 address or has a %zone suffix
*/
char *oscap_expand_ipv6(const char *input);

Expand Down
32 changes: 32 additions & 0 deletions tests/common/test_oscap_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ int test_oscap_path_startswith(void);
int test_oscap_strrm(void);
int test_oscap_indent(void);
int test_oscap_remove_excess_whitespace(void);
int test_oscap_expand_ipv6(void);

int test_oscap_path_startswith()
{
Expand Down Expand Up @@ -168,6 +169,36 @@ int test_oscap_remove_excess_whitespace()
return 0;
}

int test_oscap_expand_ipv6()
{
const char *cases[][2] = {
{ "::1", "0:0:0:0:0:0:0:1" },
{ "::", "0:0:0:0:0:0:0:0" },
{ "2001:db8::1", "2001:db8:0:0:0:0:0:1" },
{ "2001:db8:1::", "2001:db8:1:0:0:0:0:0" },
{ "2001:DB8:1::", "2001:db8:1:0:0:0:0:0" },
{ "2001:db8::00ff", "2001:db8:0:0:0:0:0:ff" },
{ "2001:db8::ff00:42:8329", "2001:db8:0:0:0:ff00:42:8329" },
{ "2001:db8::192.0.2.1", "2001:db8:0:0:0:0:c000:201" },
{ "2001:db8:0000:0000:0000:0000:198.51.100.200",
"2001:db8:0:0:0:0:c633:64c8" },
{ "2001:db8:1:2:3:4:5:6", "2001:db8:1:2:3:4:5:6" },
{ "fe80::1%eth0", "fe80::1%eth0" },
{ "fe80::1:", "fe80::1:" },
{ "00:11:22:33:44:55", "00:11:22:33:44:55" },
};

for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
char *result = oscap_expand_ipv6(cases[i][0]);
int mismatch = strcmp(result, cases[i][1]);
free(result);
if (mismatch != 0)
return (int)i + 1;
}

return 0;
}

int main (int argc, char *argv[])
{
int retval = 0;
Expand All @@ -180,6 +211,7 @@ int main (int argc, char *argv[])
return retval;
if ((retval = test_oscap_remove_excess_whitespace()) != 0)
return retval;
retval = test_oscap_expand_ipv6();

return retval;
}