From d23ca7f34500ee126a66a054dd279a6abe571dde Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Tue, 7 Sep 2021 14:59:36 +0200 Subject: [PATCH] os_info: Parse /etc/os-release first --- scripts/.gitignore | 1 + scripts/Makefile.am | 9 ++ scripts/os_info.c | 55 ++++++++ src/libimcv/imc/imc_os_info.c | 177 ++++++++++++++---------- src/libimcv/imc/imc_os_info.h | 4 +- src/libimcv/os_info/os_info.c | 1 + src/libimcv/os_info/os_info.h | 1 + src/libimcv/plugins/imc_hcd/imc_hcd.c | 2 +- src/libimcv/plugins/imc_os/imc_os.c | 2 +- src/libimcv/swid_gen/swid_gen_info.c | 2 +- src/sw-collector/sw_collector_history.c | 17 ++- 11 files changed, 184 insertions(+), 87 deletions(-) create mode 100644 scripts/os_info.c diff --git a/scripts/.gitignore b/scripts/.gitignore index 7883d9cca..177500b46 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -16,3 +16,4 @@ settings-test thread_analysis tls_test timeattack +os_info diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 82d92ef79..b4a7863bc 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -31,6 +31,7 @@ malloc_speed_SOURCES = malloc_speed.c fetch_SOURCES = fetch.c dnssec_SOURCES = dnssec.c timeattack_SOURCES = timeattack.c + id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la @@ -46,6 +47,14 @@ aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la timeattack_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(RTLIB) +if USE_IMCV + AM_CPPFLAGS += -I$(top_srcdir)/src/libimcv + noinst_PROGRAMS += os_info + os_info_SOURCES = os_info.c + os_info_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libimcv/libimcv.la +endif + key2keyid.o : $(top_builddir)/config.status keyid2sql.o : $(top_builddir)/config.status diff --git a/scripts/os_info.c b/scripts/os_info.c new file mode 100644 index 000000000..4be6e692f --- /dev/null +++ b/scripts/os_info.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 Andreas Steffen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +#include +#include +#include + +/** + * Define debug level + */ +static level_t dbg_level = 1; + +static void dbg_os_info(debug_t group, level_t level, char *fmt, ...) +{ + if ((level <= dbg_level) || level <= 1) + { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +int main(int argc, char *argv[]) +{ + imc_os_info_t *os_info; + bool all; + + all = argc > 1; + + library_init(NULL, "os_info"); + atexit(library_deinit); + + dbg = dbg_os_info; + + os_info = imc_os_info_create(all); + os_info->destroy(os_info); + + return 0; +} diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c index 13f6d93f3..3ae220d54 100644 --- a/src/libimcv/imc/imc_os_info.c +++ b/src/libimcv/imc/imc_os_info.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -128,7 +129,7 @@ METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*, * Determine Windows release */ static bool extract_platform_info(os_type_t *type, chunk_t *name, - chunk_t *version) + chunk_t *version, bool test) { OSVERSIONINFOEX osvie; char buf[64]; @@ -363,14 +364,11 @@ METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*, return (enumerator_t*)enumerator; } -#define RELEASE_LSB 0 -#define RELEASE_DEBIAN 1 - /** * Determine Linux distribution version and hardware platform */ static bool extract_platform_info(os_type_t *type, chunk_t *name, - chunk_t *version) + chunk_t *version, bool test) { FILE *file; u_char buf[BUF_LEN], *pos = buf; @@ -379,34 +377,16 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name, os_type_t os_type = OS_TYPE_UNKNOWN; chunk_t os_name = chunk_empty; chunk_t os_version = chunk_empty; - char *os_str; + char *arch; struct utsname uninfo; int i; /* Linux/Unix distribution release info (from http://linuxmafia.com) */ const char* releases[] = { - "/etc/lsb-release", "/etc/debian_version", - "/etc/SuSE-release", "/etc/novell-release", - "/etc/sles-release", "/etc/redhat-release", - "/etc/fedora-release", "/etc/gentoo-release", - "/etc/slackware-version", "/etc/annvix-release", - "/etc/arch-release", "/etc/arklinux-release", - "/etc/aurox-release", "/etc/blackcat-release", - "/etc/cobalt-release", "/etc/conectiva-release", - "/etc/debian_release", "/etc/immunix-release", - "/etc/lfs-release", "/etc/linuxppc-release", - "/etc/mandrake-release", "/etc/mandriva-release", - "/etc/mandrakelinux-release", "/etc/mklinux-release", - "/etc/pld-release", "/etc/redhat_version", - "/etc/slackware-release", "/etc/e-smith-release", - "/etc/release", "/etc/sun-release", - "/etc/tinysofa-release", "/etc/turbolinux-release", - "/etc/ultrapenguin-release", "/etc/UnitedLinux-release", - "/etc/va-release", "/etc/yellowdog-release" + "/etc/os-release", "/usr/lib/os-release", + "/etc/lsb-release", "/etc/debian_version" }; - const char lsb_distrib_id[] = "DISTRIB_ID="; - const char lsb_distrib_release[] = "DISTRIB_RELEASE="; for (i = 0; i < countof(releases); i++) { @@ -437,11 +417,71 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name, fclose(file); DBG1(DBG_IMC, "processing \"%s\" file", releases[i]); + os_name = chunk_empty; + os_version = chunk_empty; switch (i) { - case RELEASE_LSB: + case 0: /* os-release */ + case 1: + { + const char os_id[] = "ID="; + const char os_version_id[] = "VERSION_ID="; + bool match; + + /* Determine OS ID */ + pos = buf; + do + { + pos = strstr(pos, os_id); + if (!pos) + { + DBG1(DBG_IMC, "failed to find begin of ID field"); + return FALSE; + } + match = (pos == buf || *(pos-1) == '\n'); + pos += strlen(os_id); + } while (!match); + + os_name.ptr = pos; + + /* Convert first ID character to upper case */ + *pos = toupper(*pos); + + pos = strchr(pos, '\n'); + if (!pos) + { + DBG1(DBG_IMC, "failed to find end of ID field"); + return FALSE; + } + os_name.len = pos - os_name.ptr; + + /* Determine Version ID */ + pos = strstr(buf, os_version_id); + if (!pos) + { + DBG1(DBG_IMC, "failed to find begin of VERSION_ID field"); + return FALSE; + } + pos += strlen(os_version_id) + 1; + + os_version.ptr = pos; + + pos = strchr(pos, '"'); + if (!pos) + { + DBG1(DBG_IMC, "failed to find end of VERSION_ID field"); + return FALSE; + } + os_version.len = pos - os_version.ptr; + + break; + } + case 2: /* lsb-release */ { + const char lsb_distrib_id[] = "DISTRIB_ID="; + const char lsb_distrib_release[] = "DISTRIB_RELEASE="; + /* Determine Distribution ID */ pos = strstr(buf, lsb_distrib_id); if (!pos) @@ -482,13 +522,16 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name, break; } - case RELEASE_DEBIAN: + case 3: /* debian_version */ { os_type = OS_TYPE_DEBIAN; - os_version.ptr = buf; + /* Use Debian OS type name */ + os_name = chunk_from_str(enum_to_name(os_type_names, os_type)); - /* extract major release number only */ + + /* Extract major release number only */ + os_version.ptr = buf; pos = strchr(buf, '.'); if (!pos) { @@ -499,42 +542,23 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name, DBG1(DBG_PTS, "failed to find end of release string"); return FALSE; } - os_version.len = pos - os_version.ptr; break; } default: - { - const char str_release[] = " release "; - - os_name.ptr = buf; - - pos = strstr(buf, str_release); - if (!pos) - { - DBG1(DBG_IMC, "failed to find release keyword"); - return FALSE; - } - - os_name.len = pos - os_name.ptr; - - pos += strlen(str_release); - os_version.ptr = pos; - - pos = strchr(pos, '\n'); - if (!pos) - { - DBG1(DBG_IMC, "failed to find end of release string"); - return FALSE; - } - - os_version.len = pos - os_version.ptr; - break; - } } - break; + + /* Successfully extracted the OS info - exit unless in test mode */ + if (!test) + { + break; + } + DBG1(DBG_IMC, " operating system name is '%.*s'", + os_name.len, os_name.ptr); + DBG1(DBG_IMC, " operating system version is '%.*s'", + os_version.len, os_version.ptr); } if (!os_version.ptr) @@ -543,38 +567,37 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name, return FALSE; } - if (uname(&uninfo) < 0) - { - DBG1(DBG_IMC, "could not retrieve machine architecture"); - return FALSE; - } - /* Try to find a matching OS type based on the OS name */ if (os_type == OS_TYPE_UNKNOWN) { os_type = os_type_from_name(os_name); } - /* If known use the official OS name */ - if (os_type != OS_TYPE_UNKNOWN) + if (uname(&uninfo) < 0) + { + DBG1(DBG_IMC, "could not retrieve machine architecture"); + return FALSE; + } + arch = uninfo.machine; + + if (os_type == OS_TYPE_RASPBIAN && streq(arch, "armv7l")) { - os_str = enum_to_name(os_type_names, os_type); - os_name = chunk_create(os_str, strlen(os_str)); + arch = "armhf"; } - /* copy OS type */ + /* Copy OS type */ *type = os_type; - /* copy OS name */ + /* Copy OS name */ *name = chunk_clone(os_name); - /* copy OS version and machine architecture */ - *version = chunk_alloc(os_version.len + 1 + strlen(uninfo.machine)); + /* Copy OS version and machine architecture */ + *version = chunk_alloc(os_version.len + 1 + strlen(arch)); pos = version->ptr; memcpy(pos, os_version.ptr, os_version.len); pos += os_version.len; *pos++ = ' '; - memcpy(pos, uninfo.machine, strlen(uninfo.machine)); + memcpy(pos, arch, strlen(arch)); return TRUE; } @@ -592,7 +615,7 @@ METHOD(imc_os_info_t, destroy, void, /** * See header */ -imc_os_info_t *imc_os_info_create(void) +imc_os_info_t *imc_os_info_create(bool test) { private_imc_os_info_t *this; chunk_t name, version; @@ -615,11 +638,13 @@ imc_os_info_t *imc_os_info_create(void) } else { - if (!extract_platform_info(&type, &name, &version)) + if (!extract_platform_info(&type, &name, &version, test)) { return NULL; } } + DBG1(DBG_IMC, "operating system type is '%N'", + os_type_names, type); DBG1(DBG_IMC, "operating system name is '%.*s'", name.len, name.ptr); DBG1(DBG_IMC, "operating system version is '%.*s'", diff --git a/src/libimcv/imc/imc_os_info.h b/src/libimcv/imc/imc_os_info.h index 680e2b7a3..f85b9a470 100644 --- a/src/libimcv/imc/imc_os_info.h +++ b/src/libimcv/imc/imc_os_info.h @@ -108,7 +108,9 @@ struct imc_os_info_t { /** * Create an imc_os_info_t object + * + * @param test activate test mode for os_info script */ -imc_os_info_t* imc_os_info_create(void); +imc_os_info_t* imc_os_info_create(bool test); #endif /** IMC_OS_INFO_H_ @}*/ diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 258b8b442..09c96fa1b 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -19,6 +19,7 @@ ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_WINDOWS, "Unknown", "Debian", "Ubuntu", + "Raspbian", "Fedora", "Red Hat", "CentOS", diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h index aa7b137dc..bb68ba5fb 100644 --- a/src/libimcv/os_info/os_info.h +++ b/src/libimcv/os_info/os_info.h @@ -33,6 +33,7 @@ enum os_type_t { OS_TYPE_UNKNOWN, OS_TYPE_DEBIAN, OS_TYPE_UBUNTU, + OS_TYPE_RASPBIAN, OS_TYPE_FEDORA, OS_TYPE_REDHAT, OS_TYPE_CENTOS, diff --git a/src/libimcv/plugins/imc_hcd/imc_hcd.c b/src/libimcv/plugins/imc_hcd/imc_hcd.c index 09ba8bc0b..1e5100bf6 100644 --- a/src/libimcv/plugins/imc_hcd/imc_hcd.c +++ b/src/libimcv/plugins/imc_hcd/imc_hcd.c @@ -106,7 +106,7 @@ TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } - os = imc_os_info_create(); + os = imc_os_info_create(FALSE); if (!os) { imc_hcd->destroy(imc_hcd); diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index a10492e04..0789dbba4 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -68,7 +68,7 @@ TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } - os = imc_os_info_create(); + os = imc_os_info_create(FALSE); if (!os) { imc_os->destroy(imc_os); diff --git a/src/libimcv/swid_gen/swid_gen_info.c b/src/libimcv/swid_gen/swid_gen_info.c index 463502b56..bf71967a4 100644 --- a/src/libimcv/swid_gen/swid_gen_info.c +++ b/src/libimcv/swid_gen/swid_gen_info.c @@ -135,7 +135,7 @@ swid_gen_info_t *swid_gen_info_create(void) .create_sw_id = _create_sw_id, .destroy = _destroy, }, - .os_info = imc_os_info_create(), + .os_info = imc_os_info_create(FALSE), .tag_creator = strdup(tag_creator), ); diff --git a/src/sw-collector/sw_collector_history.c b/src/sw-collector/sw_collector_history.c index f1fd9f60f..9353cdd74 100644 --- a/src/sw-collector/sw_collector_history.c +++ b/src/sw-collector/sw_collector_history.c @@ -488,19 +488,22 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db, { private_sw_collector_history_t *this; swid_gen_info_t *info; - os_type_t os_type; char *os; info = swid_gen_info_create(); + info->get_os(info, &os); /* check if OS supports apg/dpkg history logs */ - info->get_os(info, &os); - os_type = info->get_os_type(info); - if (os_type != OS_TYPE_DEBIAN && os_type != OS_TYPE_UBUNTU) + switch (info->get_os_type(info)) { - DBG1(DBG_IMC, "%.*s not supported", os); - info->destroy(info); - return NULL; + case OS_TYPE_DEBIAN: + case OS_TYPE_UBUNTU: + case OS_TYPE_RASPBIAN: + break; + default: + DBG1(DBG_IMC, "%.*s not supported", os); + info->destroy(info); + return NULL; } INIT(this, -- 2.39.2