"unknown"
);
+ENUM(os_package_state_names, OS_PACKAGE_STATE_UPDATE, OS_PACKAGE_STATE_BLACKLIST,
+ "",
+ " [s]",
+ " [b]"
+);
+
/**
* Private data of an os_info_t object.
*
typedef struct os_info_t os_info_t;
typedef enum os_type_t os_type_t;
typedef enum os_fwd_status_t os_fwd_status_t;
+typedef enum os_package_state_t os_package_state_t;
#include <library.h>
extern enum_name_t *os_type_names;
/**
+ * Defines the security state of a package stored in the database
+ */
+enum os_package_state_t {
+ OS_PACKAGE_STATE_UPDATE = 0, /* latest update */
+ OS_PACKAGE_STATE_SECURITY = 1, /* latest security fix */
+ OS_PACKAGE_STATE_BLACKLIST = 2 /* blacklisted package */
+};
+
+extern enum_name_t *os_package_state_names;
+
+/**
* Defines the IPv4 forwarding status
*/
enum os_fwd_status_t {
chunk_t os_name = chunk_empty;
chunk_t os_version = chunk_empty;
bool fatal_error = FALSE, assessment = FALSE;
- int count, count_bad, count_ok;
os_state = (imv_os_state_t*)state;
!os_state->get_package_request(os_state) &&
!os_state->get_angel_count(os_state))
{
- os_state->get_count(os_state, &count, &count_bad, &count_ok);
- DBG1(DBG_IMV, "processed %d packages: %d bad, %d ok, %d not found",
- count, count_bad, count_ok, count - count_bad - count_ok);
+ int count, count_update, count_blacklist, count_ok;
- if (count_bad)
+ os_state->get_count(os_state, &count, &count_update, &count_blacklist,
+ &count_ok);
+ DBG1(DBG_IMV, "processed %d packages: %d not updated, %d blacklisted, "
+ "%d ok, %d not found", count, count_update, count_blacklist,
+ count_ok, count - count_update - count_blacklist - count_ok);
+
+ if (count_update || count_blacklist)
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
chunk_t os_name, os_version, name, version;
os_type_t os_type;
size_t os_version_len;
- int pid, gid, security;
- int count = 0, count_ok = 0, count_no_match = 0;
+ os_package_state_t package_state;
+ int pid, gid;
+ int count = 0, count_ok = 0, count_no_match = 0, count_blacklist = 0;
enumerator_t *e;
status_t status = SUCCESS;
bool found, match;
found = FALSE;
match = FALSE;
- while (e->enumerate(e, &cur_release, &security))
+ while (e->enumerate(e, &cur_release, &package_state))
{
found = TRUE;
- if (streq(release, cur_release))
+ if (streq(release, cur_release) || streq("*", cur_release))
{
match = TRUE;
break;
{
if (match)
{
- DBG2(DBG_IMV, "package '%s' (%s)%s is ok", package, release,
- security ? " [s]" : "");
- count_ok++;
+ if (package_state == OS_PACKAGE_STATE_BLACKLIST)
+ {
+ DBG2(DBG_IMV, "package '%s' (%s) is blacklisted",
+ package, release);
+ count_blacklist++;
+ state->add_bad_package(state, package, package_state);
+ }
+ else
+ {
+ DBG2(DBG_IMV, "package '%s' (%s)%N is ok", package, release,
+ os_package_state_names, package_state);
+ count_ok++;
+ }
}
else
{
DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
count_no_match++;
- state->add_bad_package(state, package);
+ state->add_bad_package(state, package, package_state);
}
}
else
free(release);
}
free(product);
- state->set_count(state, count, count_no_match, count_ok);
+ state->set_count(state, count, count_no_match, count_blacklist, count_ok);
return status;
}
#include <collections/linked_list.h>
typedef struct private_imv_os_state_t private_imv_os_state_t;
+typedef struct package_entry_t package_entry_t;
+typedef struct reason_entry_t reason_entry_t;
+typedef struct instruction_entry_t instruction_entry_t;
/**
* Private data of an imv_os_state_t object.
int count;
/**
- * Number of blacklisted or not updated packages
+ * Number of not updated packages
*/
- int count_bad;
+ int count_update;
+
+ /**
+ * Number of blacklisted packages
+ */
+ int count_blacklist;
/**
* Number of whitelisted packages
};
-typedef struct entry_t entry_t;
+/**
+ * Store a bad package entry
+ */
+struct package_entry_t {
+ char *name;
+ os_package_state_t state;
+};
+
+/**
+ * Free a bad package entry
+ */
+static void free_package_entry(package_entry_t *this)
+{
+ free(this->name);
+ free(this);
+}
/**
* Define an internal reason string entry
*/
-struct entry_t {
+struct reason_entry_t {
char *lang;
char *string;
};
/**
* Table of multi-lingual reason string entries
*/
-static entry_t reasons[] = {
+static reason_entry_t reasons[] = {
{ "en", "Vulnerable or blacklisted software packages were found" },
{ "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" },
};
/**
- * Table of multi-lingual remediation instruction string entries
+ * Define a remediation instruction string entry
+ */
+struct instruction_entry_t {
+ char *lang;
+ char *update_string;
+ char *removal_string;
+};
+
+/**
+ * Tables of multi-lingual remediation instruction string entries
*/
-static entry_t instructions [] = {
- { "en", "Please update the following software packages:\n" },
- { "de", "Bitte updaten Sie die folgenden Softwarepakete\n" },
- { "pl", "Proszę zaktualizować następujące pakiety:\n" }
+static instruction_entry_t instructions [] = {
+ { "en", "Please update the following software packages:\n",
+ "Please remove the following software packages:\n" },
+ { "de", "Bitte updaten Sie die folgenden Softwarepakete\n",
+ "Bitte entfernen Sie die folgenden Softwarepakete\n" },
+ { "pl", "Proszę zaktualizować następujące pakiety:\n",
+ "Proszę usunąć następujące pakiety:\n" }
};
METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
char *lang;
int i;
- if (!this->count_bad)
+ if (!this->count_update && !this->count_blacklist)
{
return FALSE;
}
bool match = FALSE;
char *lang, *package, *pos;
enumerator_t *enumerator;
- int i, len;
+ package_entry_t *entry;
+ int i, i_chosen = 0, len = 0;
- if (!this->count_bad)
+ if (!this->count_update && !this->count_blacklist)
{
return FALSE;
}
- /* set the default language */
- *lang_code = instructions[0].lang;
- *string = instructions[0].string;
-
while (language_enumerator->enumerate(language_enumerator, &lang))
{
for (i = 0; i < countof(instructions); i++)
if (streq(lang, instructions[i].lang))
{
match = TRUE;
- *lang_code = instructions[i].lang;
- *string = instructions[i].string;
+ i_chosen = i;
break;
}
}
break;
}
}
+ *lang_code = instructions[i_chosen].lang;
/* Compute the size of the remediation string */
- len = strlen(*string);
+ if (this->count_update)
+ {
+ len += strlen(instructions[i_chosen].update_string);
+ }
+ if (this->count_blacklist)
+ {
+ len += strlen(instructions[i_chosen].removal_string);
+ }
enumerator = this->bad_packages->create_enumerator(this->bad_packages);
- while (enumerator->enumerate(enumerator, &package))
+ while (enumerator->enumerate(enumerator, &entry))
{
- len += strlen(package) + 1;
+ len += strlen(entry->name) + 1;
}
enumerator->destroy(enumerator);
+ /* Allocate memory for the remediation instructions */
pos = this->instructions = malloc(len + 1);
- strcpy(pos, *string);
- pos += strlen(*string);
- enumerator = this->bad_packages->create_enumerator(this->bad_packages);
- while (enumerator->enumerate(enumerator, &package))
+ /* List of blacklisted packages, if any */
+ if (this->count_blacklist)
{
- strcpy(pos, package);
- pos += strlen(package);
- *pos++ = '\n';
+ strcpy(pos, instructions[i_chosen].removal_string);
+ pos += strlen(instructions[i_chosen].removal_string);
+
+ enumerator = this->bad_packages->create_enumerator(this->bad_packages);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->state == OS_PACKAGE_STATE_BLACKLIST)
+ {
+ strcpy(pos, entry->name);
+ pos += strlen(entry->name);
+ *pos++ = '\n';
+ }
+ }
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
- *pos = '\0';
+ /* List of packages in need of an update, if any */
+ if (this->count_update)
+ {
+ strcpy(pos, instructions[i_chosen].update_string);
+ pos += strlen(instructions[i_chosen].update_string);
+
+ enumerator = this->bad_packages->create_enumerator(this->bad_packages);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->state != OS_PACKAGE_STATE_BLACKLIST)
+ {
+ strcpy(pos, entry->name);
+ pos += strlen(entry->name);
+ *pos++ = '\n';
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ *pos = '\0';
*string = this->instructions;
*uri = lib->settings->get_str(lib->settings,
"libimcv.plugins.imv-os.remediation_uri", NULL);
METHOD(imv_state_t, destroy, void,
private_imv_os_state_t *this)
{
- this->bad_packages->destroy_function(this->bad_packages, free);
+ this->bad_packages->destroy_function(this->bad_packages,
+ (void*)free_package_entry);
free(this->instructions);
free(this->info);
free(this->name.ptr);
}
METHOD(imv_os_state_t, set_count, void,
- private_imv_os_state_t *this, int count, int count_bad, int count_ok)
+ private_imv_os_state_t *this, int count, int count_update,
+ int count_blacklist, int count_ok)
{
- this->count += count;
- this->count_bad += count_bad;
- this->count_ok += count_ok;
+ this->count += count;
+ this->count_update += count_update;
+ this->count_blacklist += count_blacklist;
+ this->count_ok += count_ok;
}
METHOD(imv_os_state_t, get_count, void,
- private_imv_os_state_t *this, int *count, int *count_bad, int *count_ok)
+ private_imv_os_state_t *this, int *count, int *count_update,
+ int *count_blacklist, int *count_ok)
{
if (count)
{
*count = this->count;
}
- if (count_bad)
+ if (count_update)
{
- *count_bad = this->count_bad;
+ *count_update = this->count_update;
+ }
+ if (count_blacklist)
+ {
+ *count_blacklist = this->count_blacklist;
}
if (count_ok)
{
}
METHOD(imv_os_state_t, add_bad_package, void,
- private_imv_os_state_t *this, char *package)
+ private_imv_os_state_t *this, char *package,
+ os_package_state_t package_state)
{
- this->bad_packages->insert_last(this->bad_packages, strdup(package));
+ package_entry_t *entry;
+
+ entry = malloc_thing(package_entry_t);
+ entry->name = strdup(package);
+ entry->state = package_state;
+ this->bad_packages->insert_last(this->bad_packages, entry);
}
/**
/**
* Set [or with multiple attributes increment] package counters
*
- * @param count Number of processed packages
- * @param count_bad Number of blacklisted or not updated packages
- * @param count_ok Number of whitelisted packages
+ * @param count Number of processed packages
+ * @param count_update Number of not updated packages
+ * @param count_blacklist Number of blacklisted packages
+ * @param count_ok Number of whitelisted packages
*/
- void (*set_count)(imv_os_state_t *this, int count, int count_bad,
- int count_ok);
+ void (*set_count)(imv_os_state_t *this, int count, int count_update,
+ int count_blacklist, int count_ok);
/**
* Set [or with multiple attributes increment] package counters
*
- * @param count Number of processed packages
- * @param count_bad Number of blacklisted or not updated packages
- * @param count_ok Number of whitelisted packages
+ * @param count Number of processed packages
+ * @param count_update Number of not updated packages
+ * @param count_blacklist Number of blacklisted packages
+ * @param count_ok Number of whitelisted packages
*/
- void (*get_count)(imv_os_state_t *this, int *count, int *count_bad,
- int *count_ok);
+ void (*get_count)(imv_os_state_t *this, int *count, int *count_update,
+ int *count_blacklist, int *count_ok);
/**
* Set/reset OS Installed Packages request status
*
* Store a bad package that has to be updated or removed
*
* @param package Name of software package
+ * @param package_state Security state of software package
*/
- void (*add_bad_package)(imv_os_state_t *this, char *package);
+ void (*add_bad_package)(imv_os_state_t *this, char *package,
+ os_package_state_t package_state);
};
#include <syslog.h>
#include <time.h>
+#include "imv_os_state.h"
+
#include <library.h>
#include <utils/debug.h>
{ "delete", no_argument, NULL, 'd' },
{ "del", no_argument, NULL, 'd' },
{ "aik", required_argument, NULL, 'A' },
- { "security", no_argument, NULL, 'B' },
+ { "blacklist", no_argument, NULL, 'B' },
{ "component", required_argument, NULL, 'C' },
{ "comp", required_argument, NULL, 'C' },
{ "directory", required_argument, NULL, 'D' },
{ "relative", no_argument, NULL, 'R' },
{ "rel", no_argument, NULL, 'R' },
{ "sequence", required_argument, NULL, 'S' },
- { "version", required_argument, NULL, 'V' },
{ "seq", required_argument, NULL, 'S' },
+ { "version", required_argument, NULL, 'V' },
+ { "security", no_argument, NULL, 'Y' },
{ "sha1", no_argument, NULL, '1' },
{ "sha256", no_argument, NULL, '2' },
{ "sha384", no_argument, NULL, '3' },
continue;
}
case 'B':
- attest->set_security(attest);
+ attest->set_security(attest, OS_PACKAGE_STATE_BLACKLIST);
continue;
case 'C':
if (!attest->set_component(attest, optarg, op == OP_ADD))
exit(EXIT_FAILURE);
}
continue;
+ case 'Y':
+ attest->set_security(attest, OS_PACKAGE_STATE_SECURITY);
+ continue;
case '1':
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
continue;
bool relative;
/**
- * TRUE if a security issue exists
+ * Package security state
*/
- bool security;
+ os_package_state_t security;
/**
* Sequence number for ordering entries
}
METHOD(attest_db_t, set_security, void,
- private_attest_db_t *this)
+ private_attest_db_t *this, os_package_state_t security)
{
- this->security = TRUE;
+ this->security = security;
}
METHOD(attest_db_t, set_sequence, void,
{
enumerator_t *e;
char *package, *version;
- int gid, gid_old = 0, security, spaces, count = 0;
+ os_package_state_t security;
+ int gid, gid_old = 0, spaces, count = 0;
time_t t;
if (this->pid)
printf(" ");
}
}
- printf(" %T (%s) %s\n", &t, TRUE, version, security ? "[s]" : "");
+ printf(" %T (%s)%N\n", &t, TRUE, version,
+ os_package_state_names, security);
count++;
}
e->destroy(e);
DB_UINT, this->gid, DB_UINT, this->pid, DB_TEXT,
this->version, DB_UINT, this->security, DB_INT, t) == 1;
- printf("'%s' package %s (%s) %s%sinserted into database\n",
+ printf("'%s' package %s (%s)%N %sinserted into database\n",
this->product, this->package, this->version,
- this->security ? "[s] " : "", success ? "" : "could not be ");
+ os_package_state_names, this->security,
+ success ? "" : "could not be ");
}
return success;
}
#define ATTEST_DB_H_
#include <pts/pts_meas_algo.h>
-
+#include <os_info/os_info.h>
#include <library.h>
typedef struct attest_db_t attest_db_t;
void (*set_relative)(attest_db_t *this);
/**
- * Set the security vulnerability flag
+ * Set the package security state
*/
- void (*set_security)(attest_db_t *this);
+ void (*set_security)(attest_db_t *this, os_package_state_t security);
/**
* Set the sequence number