Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Added functions used for the matching of CPEs to rules. #828

4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ if (BUILD_TESTS AND NOT SKIP_SRC)
add_custom_target (tests
DEPENDS array-test alivedetection-test boreas_error-test boreas_io-test
cli-test cpeutils-test cvss-test ping-test sniffer-test util-test networking-test
passwordbasedauthentication-test xmlutils-test version-test osp-test
nvti-test hosts-test)
passwordbasedauthentication-test xmlutils-test version-test versionutils-test
osp-test nvti-test hosts-test)

endif (BUILD_TESTS AND NOT SKIP_SRC)

Expand Down
22 changes: 20 additions & 2 deletions util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ include_directories (${GLIB_INCLUDE_DIRS} ${GPGME_INCLUDE_DIRS} ${GCRYPT_INCLUDE
${LIBXML2_INCLUDE_DIRS})

set (FILES cpeutils.c passwordbasedauthentication.c compressutils.c fileutils.c gpgmeutils.c kb.c ldaputils.c
nvticache.c mqtt.c radiusutils.c serverutils.c sshutils.c uuidutils.c
nvticache.c mqtt.c radiusutils.c serverutils.c sshutils.c uuidutils.c versionutils.c
xmlutils.c)

set (HEADERS cpeutils.h passwordbasedauthentication.h authutils.h compressutils.h fileutils.h gpgmeutils.h kb.h
ldaputils.h nvticache.h mqtt.h radiusutils.h serverutils.h sshutils.h
uuidutils.h xmlutils.h)
uuidutils.h versionutils.h xmlutils.h)

if (BUILD_STATIC)
add_library (gvm_util_static STATIC ${FILES})
Expand Down Expand Up @@ -179,6 +179,24 @@ if (BUILD_TESTS)
add_custom_target (tests-cpeutils
DEPENDS cpeutils-test)

add_executable (versionutils-test
EXCLUDE_FROM_ALL
versionutils_tests.c)

add_test (versionutils-test versionutils-test)

target_include_directories (versionutils-test PRIVATE ${CGREEN_INCLUDE_DIRS})

target_link_libraries (versionutils-test ${CGREEN_LIBRARIES}
${GLIB_LDFLAGS} ${GIO_LDFLAGS} ${GPGME_LDFLAGS} ${ZLIB_LDFLAGS}
${RADIUS_LDFLAGS} ${LIBSSH_LDFLAGS} ${GNUTLS_LDFLAGS}
${GCRYPT_LDFLAGS} ${LDAP_LDFLAGS} ${REDIS_LDFLAGS}
${LIBXML2_LDFLAGS} ${UUID_LDFLAGS}
${LINKER_HARDENING_FLAGS})

add_custom_target (tests-versionutils
DEPENDS versionutils-test)

add_executable (xmlutils-test
EXCLUDE_FROM_ALL
xmlutils_tests.c)
Expand Down
2 changes: 2 additions & 0 deletions util/cpeutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* CPE or the CPE 2.3 formatted string binding of a CPE into a CPE struct
* that corresponds to the WFN naming of a CPE. Further functions to convert
* the CPE struct into the different bindings are provided.
* This file also contains a function that checks if one CPE (represented in a
* CPE struct) is a match for an other CPE (also represented in a CPE struct).
*/

#include "cpeutils.h"
Expand Down
333 changes: 333 additions & 0 deletions util/versionutils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
/* SPDX-FileCopyrightText: 2009-2024 Greenbone AG
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/

/**
* @file
* @brief Functions to handle version numbers / version strings.
*
* Up to now this library provides a function to compare two version numbers /
* two version strings to decide which version is the newer one.
*/

#include "versionutils.h"

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <glib.h>
#include <string.h>

#undef G_LOG_DOMAIN
/**
* @brief GLib logging domain.
*/
#define G_LOG_DOMAIN "libgvm util"

/**
* @brief Compare two version strings representing a software version
* to decide which version is newer.
*
* @param[in] version1 The first version string to compare.
* @param[in] version2 The second version string to compare.
*
* @return Returns a value > 0 if version1 is newer than version2.
* Returns 0 if version1 is the same than version2.
* Returns a value between -1 and -4 if version2 is newer
* than version1.
* Returns -5 if the result is undefined.
*/
int
cmp_versions (const char *version1, const char *version2)
{
char *ver1, *ver2;
char *part1, *part2;
int index1 = 0, index2 = 0;
int release_state1 = 0, release_state2 = 0;
int rs1, rs2;

ver1 = prepare_version_string (version1);
ver2 = prepare_version_string (version2);

if (strcmp (ver1, ver2) == 0)
a-h-abdelsalam marked this conversation as resolved.
Show resolved Hide resolved
{
g_free (ver1);
g_free (ver2);
return (0);

Check warning on line 57 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L55-L57

Added lines #L55 - L57 were not covered by tests
}

if ((release_state1 = get_release_state (ver1, index1)))
index1++;
if ((release_state2 = get_release_state (ver2, index2)))
index2++;

Check warning on line 63 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L63

Added line #L63 was not covered by tests

part1 = get_part (ver1, index1);
part2 = get_part (ver2, index2);
while (part1 && part2)
{
if (strcmp (part1, part2) == 0)
{
index1++;
index2++;
g_free (part1);
g_free (part2);
part1 = get_part (ver1, index1);
part2 = get_part (ver2, index2);
continue;
}
else
break;
}

if (part1 == NULL && part2 == NULL)
return (release_state2 - release_state1);

Check warning on line 84 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L84

Added line #L84 was not covered by tests

if (is_text (part1) || is_text (part2))
{
if (part1)
g_free (part1);
if (part2)
g_free (part2);
return (-5); // undefined
}

rs1 = get_release_state (ver1, index1);
rs2 = get_release_state (ver2, index2);

if ((rs1 && release_state1) || (rs2 && release_state2))
return (-5); // undefined

Check warning on line 99 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L99

Added line #L99 was not covered by tests

if (part1 == NULL)
{
g_free (part2);
if (rs2)
return (rs2 - release_state1);
else
return (-1);
}

if (part2 == NULL)
{
g_free (part1);
if (rs1)
return (release_state2 - rs1);
else
return (1);

Check warning on line 116 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L116

Added line #L116 was not covered by tests
}

int ret = -5;

if (rs1 && rs2)
ret = rs2 - rs1;

Check warning on line 122 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L122

Added line #L122 was not covered by tests

if (rs1)
ret = -1;

if (rs2)
ret = 1;

Check warning on line 128 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L128

Added line #L128 was not covered by tests

if (!rs1 && !rs2 && atoi (part1) < atoi (part2))
ret = -1;

Check warning on line 131 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L131

Added line #L131 was not covered by tests

if (!rs1 && !rs2 && atoi (part1) == atoi (part2))
ret = 0;

Check warning on line 134 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L134

Added line #L134 was not covered by tests

if (!rs1 && !rs2 && atoi (part1) > atoi (part2))
ret = 1;

g_free (part1);
g_free (part2);
g_free (ver1);
g_free (ver2);
return (ret);
}

/**
* @brief Prepare the version string for comparison.
*
* @param[in] version The version string to generate the prepared
* version string from.
*
* @return Returns a prepared copy of the version string version.
*/
static char *
prepare_version_string (const char *version)
{
char prep_version[1024];
char *ver;
int index_v, index_pv;
gboolean is_digit;

if (!version)
return (NULL);

Check warning on line 163 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L163

Added line #L163 was not covered by tests

ver = g_strdup (version);

/* set all characters to lowercase */
char *c = ver;
for (; *c; c++)
*c = tolower (*c);

index_v = index_pv = 0;

is_digit = g_ascii_isdigit (ver[0]);

while (index_v < (int) strlen (ver))
{
if (ver[index_v] == '_' || ver[index_v] == '-' || ver[index_v] == '+'
|| ver[index_v] == ':' || ver[index_v] == '.')
{
if (index_pv > 0 && prep_version[index_pv - 1] != '.')
a-h-abdelsalam marked this conversation as resolved.
Show resolved Hide resolved
{
prep_version[index_pv] = '.';
index_pv++;
}
index_v++;
continue;
}

if (is_digit != g_ascii_isdigit (ver[index_v]))
{
is_digit = !is_digit;
if (index_pv > 0 && prep_version[index_pv - 1] != '.')
{
prep_version[index_pv] = '.';
index_pv++;
}
}

if (ver[index_v] == 'r')
{
if (strstr (ver + index_v, "releasecandidate") == ver + index_v)
{
prep_version[index_pv] = 'r';
prep_version[index_pv + 1] = 'c';
index_pv += 2;
index_v += 16;
continue;

Check warning on line 208 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L204-L208

Added lines #L204 - L208 were not covered by tests
}
if ((strstr (ver + index_v, "release-candidate") == ver + index_v)
|| (strstr (ver + index_v, "release_candidate") == ver + index_v))
{
prep_version[index_pv] = 'r';
prep_version[index_pv + 1] = 'c';
index_pv += 2;
index_v += 17;
continue;
}
}

prep_version[index_pv] = ver[index_v];
index_v++;
index_pv++;
}

prep_version[index_pv] = '\0';
g_free (ver);
return (g_strdup (prep_version));
a-h-abdelsalam marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @brief Gets the release state of a specified part of the version string
* if any.
*
* @param[in] version The version string to get the release state from.
* @param[in] index The part of the version string to check.
*
* @return Returns 0 if there is no release state, returns 4 if the release
* state is "development" (dev), returns 3 if the state is "alpha",
* 2 if the state is beta and 1 if the state is release candidate (rc).
*/
static int
get_release_state (const char *version, int index)
{
char *part;
int rel_stat = 0;

part = get_part (version, index);

if (part == NULL)
return (0);

if (strcmp (part, "dev") == 0 || strcmp (part, "development") == 0)
rel_stat = 4;

Check warning on line 254 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L254

Added line #L254 was not covered by tests
if (strcmp (part, "alpha") == 0)
rel_stat = 3;

Check warning on line 256 in util/versionutils.c

View check run for this annotation

Codecov / codecov/patch

util/versionutils.c#L256

Added line #L256 was not covered by tests
if (strcmp (part, "beta") == 0)
rel_stat = 2;
if (strcmp (part, "rc") == 0)
rel_stat = 1;

g_free (part);
return (rel_stat);
}

/**
* @brief Gets the part of the version string that is specified by index.
*
* @param[in] version The version string to get the part from.
* @param[in] index The part of the version string to return.
*
* @return Returns a copy of the specified part of the version string.
*/
static char *
get_part (const char *version, int index)
{
int dot_count = 0;
int begin, end;

for (begin = 0; begin < (int) strlen (version) && dot_count < index; begin++)
{
if (version[begin] == '.')
dot_count++;
}

if (begin == (int) strlen (version))
return (NULL);

for (end = begin + 1; end < (int) strlen (version) && version[end] != '.';
end++)
;

return (str_cpy ((char *) (version + begin), end - begin));
a-h-abdelsalam marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @brief Checks if a given part of the version string is plain text.
*
* @param[in] part The part of the version string to check.
*
* @return Returns TRUE if part contains only plain text, FALSE otherwise.
*/
static gboolean
is_text (const char *part)
{
if (!part)
return (FALSE);
if (strcmp (part, "dev") == 0 || strcmp (part, "alpha") == 0
|| strcmp (part, "beta") == 0 || strcmp (part, "rc") == 0)
return (FALSE);
if (g_ascii_isdigit (*part))
return (FALSE);
return (TRUE);
}

/**
* @brief Copy size characters of a string to an newly allocated new string.
*
* @param[in] src The string the first size characters are to be copied
* from.
* @param[in] size The number of characters to copy.
*
* @return The copy of the first size characters of src as a new string.
*/
static char *
str_cpy (char *source, int size)
{
char *result;
result = (char *) g_malloc (size + 1);
memset (result, 0, size + 1);
strncpy (result, source, size);
return (result);
}
Loading
Loading