os_info: Parse /etc/os-release first

This commit is contained in:
Andreas Steffen
2021-09-09 22:54:38 +02:00
parent bf91b71f1a
commit d23ca7f345
11 changed files with 184 additions and 87 deletions
+1
View File
@@ -16,3 +16,4 @@ settings-test
thread_analysis thread_analysis
tls_test tls_test
timeattack timeattack
os_info
+9
View File
@@ -31,6 +31,7 @@ malloc_speed_SOURCES = malloc_speed.c
fetch_SOURCES = fetch.c fetch_SOURCES = fetch.c
dnssec_SOURCES = dnssec.c dnssec_SOURCES = dnssec.c
timeattack_SOURCES = timeattack.c timeattack_SOURCES = timeattack.c
id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
keyid2sql_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 settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
timeattack_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(RTLIB) 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 key2keyid.o : $(top_builddir)/config.status
keyid2sql.o : $(top_builddir)/config.status keyid2sql.o : $(top_builddir)/config.status
+55
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <stdio.h>
#include <library.h>
#include <utils/debug.h>
#include <imc/imc_os_info.h>
/**
* 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;
}
+101 -76
View File
@@ -22,6 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h>
#include <collections/linked_list.h> #include <collections/linked_list.h>
#include <utils/debug.h> #include <utils/debug.h>
@@ -128,7 +129,7 @@ METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*,
* Determine Windows release * Determine Windows release
*/ */
static bool extract_platform_info(os_type_t *type, chunk_t *name, static bool extract_platform_info(os_type_t *type, chunk_t *name,
chunk_t *version) chunk_t *version, bool test)
{ {
OSVERSIONINFOEX osvie; OSVERSIONINFOEX osvie;
char buf[64]; char buf[64];
@@ -363,14 +364,11 @@ METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*,
return (enumerator_t*)enumerator; return (enumerator_t*)enumerator;
} }
#define RELEASE_LSB 0
#define RELEASE_DEBIAN 1
/** /**
* Determine Linux distribution version and hardware platform * Determine Linux distribution version and hardware platform
*/ */
static bool extract_platform_info(os_type_t *type, chunk_t *name, static bool extract_platform_info(os_type_t *type, chunk_t *name,
chunk_t *version) chunk_t *version, bool test)
{ {
FILE *file; FILE *file;
u_char buf[BUF_LEN], *pos = buf; 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; os_type_t os_type = OS_TYPE_UNKNOWN;
chunk_t os_name = chunk_empty; chunk_t os_name = chunk_empty;
chunk_t os_version = chunk_empty; chunk_t os_version = chunk_empty;
char *os_str; char *arch;
struct utsname uninfo; struct utsname uninfo;
int i; int i;
/* Linux/Unix distribution release info (from http://linuxmafia.com) */ /* Linux/Unix distribution release info (from http://linuxmafia.com) */
const char* releases[] = { const char* releases[] = {
"/etc/lsb-release", "/etc/debian_version", "/etc/os-release", "/usr/lib/os-release",
"/etc/SuSE-release", "/etc/novell-release", "/etc/lsb-release", "/etc/debian_version"
"/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"
}; };
const char lsb_distrib_id[] = "DISTRIB_ID=";
const char lsb_distrib_release[] = "DISTRIB_RELEASE=";
for (i = 0; i < countof(releases); i++) 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); fclose(file);
DBG1(DBG_IMC, "processing \"%s\" file", releases[i]); DBG1(DBG_IMC, "processing \"%s\" file", releases[i]);
os_name = chunk_empty;
os_version = chunk_empty;
switch (i) 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 */ /* Determine Distribution ID */
pos = strstr(buf, lsb_distrib_id); pos = strstr(buf, lsb_distrib_id);
if (!pos) if (!pos)
@@ -482,13 +522,16 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name,
break; break;
} }
case RELEASE_DEBIAN: case 3: /* debian_version */
{ {
os_type = OS_TYPE_DEBIAN; 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, '.'); pos = strchr(buf, '.');
if (!pos) 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"); DBG1(DBG_PTS, "failed to find end of release string");
return FALSE; return FALSE;
} }
os_version.len = pos - os_version.ptr; os_version.len = pos - os_version.ptr;
break; break;
} }
default: 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;
}
} }
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) if (!os_version.ptr)
@@ -543,38 +567,37 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name,
return FALSE; 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 */ /* Try to find a matching OS type based on the OS name */
if (os_type == OS_TYPE_UNKNOWN) if (os_type == OS_TYPE_UNKNOWN)
{ {
os_type = os_type_from_name(os_name); os_type = os_type_from_name(os_name);
} }
/* If known use the official OS name */ if (uname(&uninfo) < 0)
if (os_type != OS_TYPE_UNKNOWN)
{ {
os_str = enum_to_name(os_type_names, os_type); DBG1(DBG_IMC, "could not retrieve machine architecture");
os_name = chunk_create(os_str, strlen(os_str)); return FALSE;
}
arch = uninfo.machine;
if (os_type == OS_TYPE_RASPBIAN && streq(arch, "armv7l"))
{
arch = "armhf";
} }
/* copy OS type */ /* Copy OS type */
*type = os_type; *type = os_type;
/* copy OS name */ /* Copy OS name */
*name = chunk_clone(os_name); *name = chunk_clone(os_name);
/* copy OS version and machine architecture */ /* Copy OS version and machine architecture */
*version = chunk_alloc(os_version.len + 1 + strlen(uninfo.machine)); *version = chunk_alloc(os_version.len + 1 + strlen(arch));
pos = version->ptr; pos = version->ptr;
memcpy(pos, os_version.ptr, os_version.len); memcpy(pos, os_version.ptr, os_version.len);
pos += os_version.len; pos += os_version.len;
*pos++ = ' '; *pos++ = ' ';
memcpy(pos, uninfo.machine, strlen(uninfo.machine)); memcpy(pos, arch, strlen(arch));
return TRUE; return TRUE;
} }
@@ -592,7 +615,7 @@ METHOD(imc_os_info_t, destroy, void,
/** /**
* See header * 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; private_imc_os_info_t *this;
chunk_t name, version; chunk_t name, version;
@@ -615,11 +638,13 @@ imc_os_info_t *imc_os_info_create(void)
} }
else else
{ {
if (!extract_platform_info(&type, &name, &version)) if (!extract_platform_info(&type, &name, &version, test))
{ {
return NULL; return NULL;
} }
} }
DBG1(DBG_IMC, "operating system type is '%N'",
os_type_names, type);
DBG1(DBG_IMC, "operating system name is '%.*s'", DBG1(DBG_IMC, "operating system name is '%.*s'",
name.len, name.ptr); name.len, name.ptr);
DBG1(DBG_IMC, "operating system version is '%.*s'", DBG1(DBG_IMC, "operating system version is '%.*s'",
+3 -1
View File
@@ -108,7 +108,9 @@ struct imc_os_info_t {
/** /**
* Create an imc_os_info_t object * 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_ @}*/ #endif /** IMC_OS_INFO_H_ @}*/
+1
View File
@@ -19,6 +19,7 @@ ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_WINDOWS,
"Unknown", "Unknown",
"Debian", "Debian",
"Ubuntu", "Ubuntu",
"Raspbian",
"Fedora", "Fedora",
"Red Hat", "Red Hat",
"CentOS", "CentOS",
+1
View File
@@ -33,6 +33,7 @@ enum os_type_t {
OS_TYPE_UNKNOWN, OS_TYPE_UNKNOWN,
OS_TYPE_DEBIAN, OS_TYPE_DEBIAN,
OS_TYPE_UBUNTU, OS_TYPE_UBUNTU,
OS_TYPE_RASPBIAN,
OS_TYPE_FEDORA, OS_TYPE_FEDORA,
OS_TYPE_REDHAT, OS_TYPE_REDHAT,
OS_TYPE_CENTOS, OS_TYPE_CENTOS,
+1 -1
View File
@@ -106,7 +106,7 @@ TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
return TNC_RESULT_FATAL; return TNC_RESULT_FATAL;
} }
os = imc_os_info_create(); os = imc_os_info_create(FALSE);
if (!os) if (!os)
{ {
imc_hcd->destroy(imc_hcd); imc_hcd->destroy(imc_hcd);
+1 -1
View File
@@ -68,7 +68,7 @@ TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
return TNC_RESULT_FATAL; return TNC_RESULT_FATAL;
} }
os = imc_os_info_create(); os = imc_os_info_create(FALSE);
if (!os) if (!os)
{ {
imc_os->destroy(imc_os); imc_os->destroy(imc_os);
+1 -1
View File
@@ -135,7 +135,7 @@ swid_gen_info_t *swid_gen_info_create(void)
.create_sw_id = _create_sw_id, .create_sw_id = _create_sw_id,
.destroy = _destroy, .destroy = _destroy,
}, },
.os_info = imc_os_info_create(), .os_info = imc_os_info_create(FALSE),
.tag_creator = strdup(tag_creator), .tag_creator = strdup(tag_creator),
); );
+10 -7
View File
@@ -488,19 +488,22 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
{ {
private_sw_collector_history_t *this; private_sw_collector_history_t *this;
swid_gen_info_t *info; swid_gen_info_t *info;
os_type_t os_type;
char *os; char *os;
info = swid_gen_info_create(); info = swid_gen_info_create();
info->get_os(info, &os);
/* check if OS supports apg/dpkg history logs */ /* check if OS supports apg/dpkg history logs */
info->get_os(info, &os); switch (info->get_os_type(info))
os_type = info->get_os_type(info);
if (os_type != OS_TYPE_DEBIAN && os_type != OS_TYPE_UBUNTU)
{ {
DBG1(DBG_IMC, "%.*s not supported", os); case OS_TYPE_DEBIAN:
info->destroy(info); case OS_TYPE_UBUNTU:
return NULL; case OS_TYPE_RASPBIAN:
break;
default:
DBG1(DBG_IMC, "%.*s not supported", os);
info->destroy(info);
return NULL;
} }
INIT(this, INIT(this,