aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv/plugins/imc_swima
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2017-07-09 23:17:22 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2017-07-12 19:12:22 +0200
commit5b1dbc3a8da2244e14a6a488647acbfa91ead517 (patch)
treef348bbd1e357f4b33fcd4684b11111b98031ae88 /src/libimcv/plugins/imc_swima
parenteab650d62fac17c9ea24143818aca7e9a66cceb1 (diff)
downloadstrongswan-5b1dbc3a8da2244e14a6a488647acbfa91ead517.tar.bz2
strongswan-5b1dbc3a8da2244e14a6a488647acbfa91ead517.tar.xz
sw-collector: Check for epoch-less Debian package versions
Diffstat (limited to 'src/libimcv/plugins/imc_swima')
-rw-r--r--src/libimcv/plugins/imc_swima/Makefile.am2
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw-collector.c141
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.c154
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.h30
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.c152
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.h53
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.c394
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.h16
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.c176
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.h69
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.c6
-rw-r--r--src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.h2
12 files changed, 881 insertions, 314 deletions
diff --git a/src/libimcv/plugins/imc_swima/Makefile.am b/src/libimcv/plugins/imc_swima/Makefile.am
index cde20980f..e14556c62 100644
--- a/src/libimcv/plugins/imc_swima/Makefile.am
+++ b/src/libimcv/plugins/imc_swima/Makefile.am
@@ -37,7 +37,9 @@ ipsec_PROGRAMS = sw-collector
sw_collector_SOURCES = \
sw_collector/sw-collector.c \
sw_collector/sw_collector_db.h sw_collector/sw_collector_db.c \
+ sw_collector/sw_collector_dpkg.h sw_collector/sw_collector_dpkg.c \
sw_collector/sw_collector_history.h sw_collector/sw_collector_history.c \
+ sw_collector/sw_collector_info.h sw_collector/sw_collector_info.c \
sw_collector/sw_collector_rest_api.h sw_collector/sw_collector_rest_api.c
sw_collector_LDADD = \
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw-collector.c b/src/libimcv/plugins/imc_swima/sw_collector/sw-collector.c
index bb72349c7..2f4df181a 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw-collector.c
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw-collector.c
@@ -23,14 +23,18 @@
# include <syslog.h>
#endif
+#include "sw_collector_info.h"
#include "sw_collector_db.h"
#include "sw_collector_history.h"
#include "sw_collector_rest_api.h"
-
+#include "sw_collector_dpkg.h"
+#
#include <library.h>
#include <utils/debug.h>
#include <utils/lexparser.h>
+#include <imv/imv_os_info.h>
+
/**
* global debug output variables
*/
@@ -44,7 +48,8 @@ enum collector_op_t {
COLLECTOR_OP_EXTRACT,
COLLECTOR_OP_LIST,
COLLECTOR_OP_UNREGISTERED,
- COLLECTOR_OP_GENERATE
+ COLLECTOR_OP_GENERATE,
+ COLLECTOR_OP_MIGRATE
};
/**
@@ -110,9 +115,9 @@ static void usage(void)
printf("\
Usage:\n\
sw-collector --help\n\
- sw-collector [--debug <level>] [--quiet] --list\n\
- sw-collector [--debug <level>] [--quiet] --unregistered|--generate\n\
- sw-collector [--debug <level>] [--quiet] [--count <event count>]\n");
+ sw-collector [--debug <level>] [--quiet] [--count <event count>]\n\
+ sw-collector [--debug <level>] [--quiet] --list|-unregistered\n\
+ sw-collector [--debug <level>] [--quiet] ---generate|--migrate\n");
}
/**
@@ -135,12 +140,13 @@ static collector_op_t do_args(int argc, char *argv[])
{ "debug", required_argument, NULL, 'd' },
{ "generate", no_argument, NULL, 'g' },
{ "list", no_argument, NULL, 'l' },
+ { "migrate", no_argument, NULL, 'm' },
{ "quiet", no_argument, NULL, 'q' },
{ "unregistered", no_argument, NULL, 'u' },
{ 0,0,0,0 }
};
- c = getopt_long(argc, argv, "hc:d:lqu", long_opts, NULL);
+ c = getopt_long(argc, argv, "hc:d:lmqu", long_opts, NULL);
switch (c)
{
case EOF:
@@ -161,6 +167,9 @@ static collector_op_t do_args(int argc, char *argv[])
case 'l':
op = COLLECTOR_OP_LIST;
continue;
+ case 'm':
+ op = COLLECTOR_OP_MIGRATE;
+ continue;
case 'q':
stderr_quiet = TRUE;
continue;
@@ -179,38 +188,44 @@ static collector_op_t do_args(int argc, char *argv[])
/**
* Extract software events from apt history log files
*/
-static int extract_history(sw_collector_db_t *db)
+static int extract_history(sw_collector_info_t *info, sw_collector_db_t *db)
{
sw_collector_history_t *history = NULL;
uint32_t epoch, last_eid, eid = 0;
- char *history_path, *last_time = NULL, rfc_time[21];
+ char *history_path, *os, *last_time = NULL, rfc_time[21];
chunk_t *h, history_chunk, line, cmd;
+ os_type_t os_type;
int status = EXIT_FAILURE;
bool skip = TRUE;
+ /* 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)
+ {
+ DBG1(DBG_IMC, "%.*s not supported", os);
+ return EXIT_FAILURE;
+ }
+
/* open history file for reading */
history_path= lib->settings->get_str(lib->settings, "%s.history", NULL,
lib->ns);
if (!history_path)
{
fprintf(stderr, "sw-collector.history path not set.\n");
- return FALSE;
+ return EXIT_FAILURE;
}
h = chunk_map(history_path, FALSE);
if (!h)
{
fprintf(stderr, "opening '%s' failed: %s", history, strerror(errno));
- return FALSE;
+ return EXIT_FAILURE;
}
history_chunk = *h;
/* Instantiate history extractor */
- history = sw_collector_history_create(db, 1);
- if (!history)
- {
- /* OS is not supported */
- goto end;
- }
+ history = sw_collector_history_create(info, db, 1);
/* retrieve last event in database */
if (!db->get_last_event(db, &last_eid, &epoch, &last_time) || !last_eid)
@@ -313,7 +328,7 @@ static int extract_history(sw_collector_db_t *db)
end:
free(last_time);
- DESTROY_IF(history);
+ history->destroy(history);
chunk_unmap(h);
return status;
@@ -326,14 +341,14 @@ static int list_identifiers(sw_collector_db_t *db)
{
enumerator_t *e;
char *name, *package, *version;
- uint32_t count = 0, installed_count = 0, installed;
+ uint32_t sw_id, count = 0, installed_count = 0, installed;
- e = db->create_sw_enumerator(db, SW_QUERY_ALL);
+ e = db->create_sw_enumerator(db, SW_QUERY_ALL, NULL);
if (!e)
{
return EXIT_FAILURE;
}
- while (e->enumerate(e, &name, &package, &version, &installed))
+ while (e->enumerate(e, &sw_id, &name, &package, &version, &installed))
{
printf("%s,%s,%s,%d\n", name, package, version, installed);
if (installed)
@@ -433,9 +448,12 @@ static char* generate_tag(char *name, char *package, char *version,
return (res == -1) ? NULL : tag;
}
-static int generate_tags(sw_collector_db_t *db)
+/**
+ * Generate a minimalistic ISO 19770-2:2015 SWID tag for
+ * all deleted SW identifiers that are not registered centrally
+ */
+static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db)
{
- sw_collector_history_t *os_info;
sw_collector_rest_api_t *rest_api;
char *pos, *name, *package, *version, *entity, *regid, *product, *tag;
enumerator_t *enumerator;
@@ -446,13 +464,7 @@ static int generate_tags(sw_collector_db_t *db)
"strongSwan Project", lib->ns);
regid = lib->settings->get_str(lib->settings, "%s.tag_creator.regid",
"strongswan.org", lib->ns);
-
- os_info = sw_collector_history_create(db, 0);
- if (!os_info)
- {
- return EXIT_FAILURE;
- }
- os_info->get_os(os_info, &product);
+ info->get_os(info, &product);
rest_api = sw_collector_rest_api_create(db);
if (!rest_api)
@@ -493,18 +505,69 @@ static int generate_tags(sw_collector_db_t *db)
count);
end:
- os_info->destroy(os_info);
DESTROY_IF(rest_api);
return status;
}
+/**
+ * Append missing architecture suffix to package entries in the database
+ */
+static int migrate(sw_collector_info_t *info, sw_collector_db_t *db)
+{
+ sw_collector_dpkg_t *dpkg;
+
+ char *package, *arch, *version;
+ char package_arch[BUF_LEN];
+ int res, count = 0;
+ int status = EXIT_SUCCESS;
+ enumerator_t *enumerator;
+
+ dpkg = sw_collector_dpkg_create();
+ if (!dpkg)
+ {
+ return FAILED;
+ }
+
+ enumerator = dpkg->create_sw_enumerator(dpkg);
+ while (enumerator->enumerate(enumerator, &package, &arch, &version))
+ {
+ if (streq(arch, "all"))
+ {
+ continue;
+ }
+
+ /* Concatenate package and architecture strings */
+ snprintf(package_arch, BUF_LEN, "%s:%s", package, arch);
+
+ res = db->update_package(db, package, package_arch);
+ if (res < 0)
+ {
+ status = EXIT_FAILURE;
+ break;
+ }
+ else if (res > 0)
+ {
+ count += res;
+ DBG2(DBG_IMC, "replaced '%s' by '%s'", package, package_arch);
+ }
+ }
+ enumerator->destroy(enumerator);
+ dpkg->destroy(dpkg);
+
+ DBG1(DBG_IMC, "migrated %d sw identifier records", count);
+
+ return status;
+}
+
+
int main(int argc, char *argv[])
{
sw_collector_db_t *db = NULL;
+ sw_collector_info_t *info;
collector_op_t op;
- char *uri;
- int status;
+ char *uri, *tag_creator;
+ int status = EXIT_FAILURE;
op = do_args(argc, argv);
@@ -543,10 +606,15 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ /* Attach OS info */
+ tag_creator = lib->settings->get_str(lib->settings, "%s.tag_creator.regid",
+ "strongswan.org", lib->ns);
+ info = sw_collector_info_create(tag_creator);
+
switch (op)
{
case COLLECTOR_OP_EXTRACT:
- status = extract_history(db);
+ status = extract_history(info, db);
break;
case COLLECTOR_OP_LIST:
status = list_identifiers(db);
@@ -555,11 +623,14 @@ int main(int argc, char *argv[])
status = unregistered_identifiers(db);
break;
case COLLECTOR_OP_GENERATE:
- status = generate_tags(db);
- default:
+ status = generate_tags(info, db);
+ break;
+ case COLLECTOR_OP_MIGRATE:
+ status = migrate(info, db);
break;
}
db->destroy(db);
+ info->destroy(info);
exit(status);
}
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.c b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.c
index 62a650787..206cbde2f 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.c
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.c
@@ -110,71 +110,19 @@ METHOD(sw_collector_db_t, add_sw_event, bool,
METHOD(sw_collector_db_t, set_sw_id, uint32_t,
private_sw_collector_db_t *this, char *name, char *package, char *version,
- uint8_t source, bool installed, bool check)
+ uint8_t source, bool installed)
{
- uint32_t sw_id = 0, status;
- enumerator_t *e;
+ uint32_t sw_id;
- /* Does software identifier already exist in database? */
- e = this->db->query(this->db,
- "SELECT id, installed FROM sw_identifiers WHERE name = ?",
- DB_TEXT, name, DB_UINT, DB_UINT);
- if (!e)
+ if (this->db->execute(this->db, &sw_id,
+ "INSERT INTO sw_identifiers "
+ "(name, package, version, source, installed) VALUES (?, ?, ?, ?, ?)",
+ DB_TEXT, name, DB_TEXT, package, DB_TEXT, version, DB_UINT, source,
+ DB_UINT, installed) != 1)
{
- DBG1(DBG_IMC, "database query for sw_identifier failed");
+ DBG1(DBG_IMC, "unable to insert sw_id into database");
return 0;
}
- if (!e->enumerate(e, &sw_id, &status))
- {
- sw_id = 0;
- }
- e->destroy(e);
-
- if (sw_id)
- {
- if (status == installed)
- {
- if (!check)
- {
- DBG1(DBG_IMC, " Warning: sw_id %u is already %s", sw_id,
- status ? "installed" : "deleted");
- }
- return sw_id;
- }
- if (check)
- {
- DBG1(DBG_IMC, " Warning: sw_id %u is %s", sw_id,
- status ? "installed" : "deleted");
- }
-
- /* Change installation status */
- if (this->db->execute(this->db, NULL,
- "UPDATE sw_identifiers SET installed = ? WHERE id = ?",
- DB_UINT, installed, DB_UINT, sw_id) != 1)
- {
- DBG1(DBG_IMC, "unable to update sw_id status in database");
- return 0;
- }
- }
- else
- {
- /* Create new software identifier */
- if (this->db->execute(this->db, &sw_id,
- "INSERT INTO sw_identifiers "
- "(name, package, version, source, installed) VALUES "
- "(?, ?, ?, ?, ?)",
- DB_TEXT, name, DB_TEXT, package, DB_TEXT, version,
- DB_UINT, source, DB_UINT, installed) != 1)
- {
- DBG1(DBG_IMC, "unable to insert sw_id into database");
- return 0;
- }
-
- if (check || !installed)
- {
- add_sw_event(this, 1, sw_id, SWIMA_EVENT_ACTION_CREATION);
- }
- }
return sw_id;
}
@@ -255,25 +203,91 @@ METHOD(sw_collector_db_t, get_sw_id_count, uint32_t,
return count;
}
+METHOD(sw_collector_db_t, update_sw_id, bool,
+ private_sw_collector_db_t *this, uint32_t sw_id, char *name, char *version,
+ bool installed)
+{
+ int res;
+
+ if (name && version)
+ {
+ res = this->db->execute(this->db, NULL,
+ "UPDATE sw_identifiers SET name = ?, version = ?, installed = ? "
+ "WHERE id = ?", DB_TEXT, name, DB_TEXT, version, DB_UINT, installed,
+ DB_UINT, sw_id);
+ }
+ else
+ {
+ res = this->db->execute(this->db, NULL,
+ "UPDATE sw_identifiers SET installed = ? WHERE id = ?",
+ DB_UINT, installed, DB_UINT, sw_id);
+ }
+ if (res != 1)
+ {
+ DBG1(DBG_IMC, "unable to update software identifier in database");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(sw_collector_db_t, update_package, int,
+ private_sw_collector_db_t *this, char *package, char *package_new)
+{
+ int count;
+
+ count = this->db->execute(this->db, NULL,
+ "UPDATE sw_identifiers SET package = ? "
+ "WHERE package = ?", DB_TEXT, package_new, DB_TEXT, package);
+ if (count < 0)
+ {
+ DBG1(DBG_IMC, "unable to update package name in database");
+ }
+
+ return count;
+}
+
METHOD(sw_collector_db_t, create_sw_enumerator, enumerator_t*,
- private_sw_collector_db_t *this, sw_collector_db_query_t type)
+ private_sw_collector_db_t *this, sw_collector_db_query_t type, char *package)
{
enumerator_t *e;
- uint32_t installed;
+ u_int installed;
if (type == SW_QUERY_ALL)
{
- e = this->db->query(this->db,
- "SELECT name, package, version, installed FROM sw_identifiers "
- "ORDER BY name ASC", DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+ if (package)
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name, package, version, installed "
+ "FROM sw_identifiers WHERE package = ? ORDER BY name ASC",
+ DB_TEXT, package, DB_UINT, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name, package, version, installed "
+ "FROM sw_identifiers ORDER BY name ASC",
+ DB_UINT, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+ }
}
else
{
installed = (type == SW_QUERY_INSTALLED);
- e = this->db->query(this->db,
- "SELECT name, package, version, installed FROM sw_identifiers "
- "WHERE installed = ? ORDER BY name ASC",
- DB_UINT, installed, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+
+ if (package)
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name, package, version, installed "
+ "FROM sw_identifiers WHERE package = ? AND installed = ? "
+ "ORDER BY name ASC", DB_TEXT, package, DB_UINT, installed,
+ DB_UINT, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name, package, version, installed "
+ "FROM sw_identifiers WHERE installed = ? ORDER BY name ASC",
+ DB_UINT, installed, DB_UINT, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
+ }
}
if (!e)
{
@@ -308,6 +322,8 @@ sw_collector_db_t *sw_collector_db_create(char *uri)
.set_sw_id = _set_sw_id,
.get_sw_id = _get_sw_id,
.get_sw_id_count = _get_sw_id_count,
+ .update_sw_id = _update_sw_id,
+ .update_package = _update_package,
.create_sw_enumerator = _create_sw_enumerator,
.destroy = _destroy,
},
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.h b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.h
index c4e82a990..88a13bbdb 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.h
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_db.h
@@ -78,12 +78,10 @@ struct sw_collector_db_t {
* @param version Version of software package
* @param source Source ID of the software collector
* @param installed Installation status to be set, TRUE if installed
- * @param check Check if SW ID is already installed
* @return Primary key pointing to SW ID or 0 if failed
*/
uint32_t (*set_sw_id)(sw_collector_db_t *this, char *name, char *package,
- char *version, uint8_t source, bool installed,
- bool check);
+ char *version, uint8_t source, bool installed);
/**
* Get software_identifier record
@@ -108,13 +106,37 @@ struct sw_collector_db_t {
sw_collector_db_query_t type);
/**
+ * Update the software identifier version
+ *
+ * @param sw_id Primary key of software identifier
+ * @param name Software identifier
+ * @param version Package version
+ * @param installed Installation status
+ * @return TRUE if update successful
+ */
+ bool (*update_sw_id)(sw_collector_db_t *this, uint32_t sw_id, char *name,
+ char *version, bool installed);
+
+ /**
+ * Update the package name
+ *
+ * @param package Package name to be changed
+ * @param package_new New package name
+ * @return TRUE if update successful
+ */
+ int (*update_package)(sw_collector_db_t *this, char *package,
+ char *package_new);
+
+ /**
* Enumerate over all collected [installed] software identities
*
* @param type Query type (ALL, INSTALLED, DELETED)
+ * @param package If not NULL enumerate over all package versions
* @return Enumerator
*/
enumerator_t* (*create_sw_enumerator)(sw_collector_db_t *this,
- sw_collector_db_query_t type);
+ sw_collector_db_query_t type,
+ char *package);
/**
* Destroy sw_collector_db_t object
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.c b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.c
new file mode 100644
index 000000000..b5a858297
--- /dev/null
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "sw_collector_dpkg.h"
+
+typedef struct private_sw_collector_dpkg_t private_sw_collector_dpkg_t;
+
+/**
+ * Private data of an sw_collector_dpkg_t object.
+ */
+struct private_sw_collector_dpkg_t {
+
+ /**
+ * Public members of sw_collector_dpkg_state_t
+ */
+ sw_collector_dpkg_t public;
+
+};
+
+typedef struct {
+ /** public enumerator interface */
+ enumerator_t public;
+ /** dpkg output stream */
+ FILE *file;
+ /** current dpkg output line */
+ char line[BUF_LEN];
+} dpkg_enumerator_t;
+
+METHOD(enumerator_t, enumerate, bool,
+ dpkg_enumerator_t *this, va_list args)
+{
+ char **package, **arch, **version, *state, *pos;
+
+ VA_ARGS_VGET(args, package, arch, version);
+
+ while (TRUE)
+ {
+ if (!fgets(this->line, BUF_LEN, this->file))
+ {
+ return FALSE;
+ }
+
+ *package = this->line;
+ pos = strchr(this->line, '\t');
+ if (!pos)
+ {
+ return FALSE;
+ }
+ *pos = '\0';
+
+ *arch = ++pos;
+ pos = strchr(pos, '\t');
+ if (!pos)
+ {
+ return FALSE;
+ }
+ *pos = '\0';
+
+ *version = ++pos;
+ pos = strchr(pos, '\t');
+ if (!pos)
+ {
+ return FALSE;
+ }
+ *pos = '\0';
+
+ state = ++pos;
+ pos = strchr(pos, '\n');
+ if (!pos)
+ {
+ return FALSE;
+ }
+ *pos = '\0';
+
+ if (streq(state, "install ok installed"))
+ {
+ return TRUE;
+ }
+ }
+}
+
+METHOD(enumerator_t, enumerator_destroy, void,
+ dpkg_enumerator_t *this)
+{
+ pclose(this->file);
+ free(this);
+}
+
+METHOD(sw_collector_dpkg_t, create_sw_enumerator, enumerator_t*,
+ private_sw_collector_dpkg_t *this)
+{
+ dpkg_enumerator_t *enumerator;
+ char cmd[] = "dpkg-query -W -f="
+ "\'${Package}\t${Architecture}\t${Version}\t${Status}\n\'";
+ FILE *file;
+
+ file = popen(cmd, "r");
+ if (!file)
+ {
+ DBG1(DBG_IMC, "failed to run dpgk-query command");
+ return NULL;
+ }
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate,
+ .destroy = _enumerator_destroy,
+ },
+ .file = file,
+ );
+
+ return &enumerator->public;
+}
+
+METHOD(sw_collector_dpkg_t, destroy, void,
+ private_sw_collector_dpkg_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+sw_collector_dpkg_t *sw_collector_dpkg_create(void)
+{
+ private_sw_collector_dpkg_t *this;
+
+ INIT(this,
+ .public = {
+ .create_sw_enumerator = _create_sw_enumerator,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.h b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.h
new file mode 100644
index 000000000..eab792e8a
--- /dev/null
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_dpkg.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup sw_collector_dpkg_t sw_collector_dpkg
+ * @{ @ingroup sw_collector
+ */
+
+#ifndef SW_COLLECTOR_DPKG_H_
+#define SW_COLLECTOR_DPKG_H_
+
+#include <library.h>
+
+typedef struct sw_collector_dpkg_t sw_collector_dpkg_t;
+
+/**
+ * Software collector dpkg object
+ */
+struct sw_collector_dpkg_t {
+
+ /**
+ * List of installed software identifiers managed by the
+ * Debian "dpkg" package manager
+ *
+ * @return Enumerator
+ */
+ enumerator_t* (*create_sw_enumerator)(sw_collector_dpkg_t *this);
+
+ /**
+ * Destroy sw_collector_dpkg_t object
+ */
+ void (*destroy)(sw_collector_dpkg_t *this);
+
+};
+
+/**
+ * Create an sw_collector_dpkg_t instance
+ */
+sw_collector_dpkg_t* sw_collector_dpkg_create(void);
+
+#endif /** SW_COLLECTOR_DPKG_H_ @}*/
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.c b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.c
index 9371285d4..0fc6164cd 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.c
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.c
@@ -18,8 +18,8 @@
#include <time.h>
#include "sw_collector_history.h"
+#include "sw_collector_dpkg.h"
-#include "imc/imc_os_info.h"
#include "swima/swima_event.h"
typedef struct private_sw_collector_history_t private_sw_collector_history_t;
@@ -35,29 +35,14 @@ struct private_sw_collector_history_t {
sw_collector_history_t public;
/**
- * tagCreator
- */
- char *tag_creator;
-
- /**
- * OS string 'name_version-arch'
- */
- char *os;
-
- /**
- * Product string 'name version arch'
- */
- char *product;
-
- /**
- * OS info about endpoint
+ * Software Event Source Number
*/
- imc_os_info_t *os_info;
+ uint8_t source;
/**
- * Software Event Source Number
+ * Reference to OS info object
*/
- uint8_t source;
+ sw_collector_info_t *info;
/**
* Reference to collector database
@@ -66,16 +51,6 @@ struct private_sw_collector_history_t {
};
-METHOD(sw_collector_history_t, get_os, char*,
- private_sw_collector_history_t *this, char **product)
-{
- if (product)
- {
- *product = this->product;
- }
- return this->os;
-}
-
/**
* Define auxiliary package_t list item object
*/
@@ -90,52 +65,9 @@ struct package_t {
};
/**
- * Replaces invalid character by a valid one
- */
-static void sanitize_uri(char *uri, char a, char b)
-{
- char *pos = uri;
-
- while (TRUE)
- {
- pos = strchr(pos, a);
- if (!pos)
- {
- break;
- }
- *pos = b;
- pos++;
- }
-}
-
-/**
- * Create software identifier
- */
-char* create_sw_id(char *tag_creator, char *os, char *package, char *version)
-{
- char *pos, *sw_id;
- size_t len;
-
- /* Remove architecture from package name */
- pos = strchr(package, ':');
- len = pos ? (pos - package) : strlen(package);
-
- /* Build software identifier */
- if (asprintf(&sw_id, "%s__%s-%.*s%s%s", tag_creator, os, len, package,
- strlen(version) ? "-" : "", version) == -1)
- {
- return NULL;
- }
- sanitize_uri(sw_id, ':', '~');
- sanitize_uri(sw_id, '+', '~');
-
- return sw_id;
-}
-
-/**
* Create package_t list item object
*/
-static package_t* create_package(char* tag_creator, char *os, chunk_t package,
+static package_t* create_package(sw_collector_info_t *info, chunk_t package,
chunk_t version, chunk_t old_version)
{
package_t *this;
@@ -146,11 +78,11 @@ static package_t* create_package(char* tag_creator, char *os, chunk_t package,
.old_version = strndup(old_version.ptr, old_version.len),
)
- this->sw_id = create_sw_id(tag_creator, os, this->package, this->version);
+ this->sw_id = info->create_sw_id(info, this->package, this->version);
if (old_version.len)
{
- this->old_sw_id = create_sw_id(tag_creator, os, this->package,
- this->old_version);
+ this->old_sw_id = info->create_sw_id(info, this->package,
+ this->old_version);
}
return this;
@@ -175,8 +107,8 @@ static void free_package(package_t *this)
/**
* Extract and parse a single package item
*/
-static package_t* extract_package(chunk_t item, char *tag_creator, char *os,
- sw_collector_history_op_t op)
+static package_t* extract_package(chunk_t item, sw_collector_info_t *info,
+ sw_collector_history_op_t op)
{
chunk_t package, version, old_version;
package_t *p;
@@ -208,7 +140,7 @@ static package_t* extract_package(chunk_t item, char *tag_creator, char *os,
version = item;
}
}
- p = create_package(tag_creator, os, package, version, old_version);
+ p = create_package(info, package, version, old_version);
/* generate log entry */
if (op == SW_OP_UPGRADE)
@@ -277,16 +209,22 @@ METHOD(sw_collector_history_t, extract_packages, bool,
private_sw_collector_history_t *this, chunk_t args, uint32_t eid,
sw_collector_history_op_t op)
{
+ bool success = FALSE;
package_t *p = NULL;
- uint32_t sw_id;
chunk_t item;
- bool success = FALSE;
eat_whitespace(&args);
while (extract_token(&item, ')', &args))
{
- p = extract_package(item, this->tag_creator, this->os, op);
+ char *del_sw_id = NULL, *del_version = NULL;
+ char *nx, *px, *vx, *v1;
+ bool installed;
+ u_int sw_idx, ix;
+ uint32_t sw_id, sw_id_epoch_less = 0;
+ enumerator_t *e;
+
+ p = extract_package(item, this->info, op);
if (!p)
{
goto end;
@@ -299,29 +237,115 @@ METHOD(sw_collector_history_t, extract_packages, bool,
continue;
}
- sw_id = this->db->set_sw_id(this->db, p->sw_id, p->package, p->version,
- this->source, op != SW_OP_REMOVE, FALSE);
- if (!sw_id)
+ switch (op)
{
- goto end;
- }
- if (!this->db->add_sw_event(this->db, eid, sw_id, op != SW_OP_REMOVE ?
- SWIMA_EVENT_ACTION_CREATION : SWIMA_EVENT_ACTION_DELETION))
- {
- goto end;
+ case SW_OP_REMOVE:
+ /* prepare subsequent deletion sw event */
+ del_sw_id = p->sw_id;
+ del_version = p->version;
+ break;
+ case SW_OP_UPGRADE:
+ /* prepare subsequent deletion sw event */
+ del_sw_id = p->old_sw_id;
+ del_version = p->old_version;
+ /* fall through to next case */
+ case SW_OP_INSTALL:
+ sw_id = this->db->get_sw_id(this->db, p->sw_id, NULL, NULL,
+ NULL, &installed);
+ if (sw_id)
+ {
+ /* sw identifier exists - update state to 'installed' */
+ if (installed)
+ {
+ /* this case should not occur */
+ DBG1(DBG_IMC, " warning: sw_id %d is already "
+ "installed", sw_id);
+ }
+ else if (!this->db->update_sw_id(this->db, sw_id, NULL,
+ NULL, TRUE))
+ {
+ goto end;
+ }
+ }
+ else
+ {
+ /* new sw identifier - create with state 'installed' */
+ sw_id = this->db->set_sw_id(this->db, p->sw_id, p->package,
+ p->version, this->source, TRUE);
+ if (!sw_id)
+ {
+ goto end;
+ }
+ }
+
+ /* add creation sw event with current eid */
+ if (!this->db->add_sw_event(this->db, eid, sw_id,
+ SWIMA_EVENT_ACTION_CREATION))
+ {
+ goto end;
+ }
+ break;
}
- if (op == SW_OP_UPGRADE)
+ if (op != SW_OP_INSTALL)
{
- sw_id = this->db->set_sw_id(this->db, p->old_sw_id, p->package,
- p->old_version, this->source, FALSE,
- FALSE);
- if (!sw_id)
+ sw_id = 0;
+
+ /* look for existing installed package versions */
+ e = this->db->create_sw_enumerator(this->db, SW_QUERY_INSTALLED,
+ p->package);
+ if (!e)
{
goto end;
}
+
+ while (e->enumerate(e, &sw_idx, &nx, &px, &vx, &ix))
+ {
+ if (streq(vx, del_version))
+ {
+ /* full match with epoch */
+ sw_id = sw_idx;
+ break;
+ }
+ v1 = strchr(vx, ':');
+ if (v1 && streq(++v1, del_version))
+ {
+ /* match with stripped epoch */
+ sw_id_epoch_less = sw_idx;
+ }
+ }
+ e->destroy(e);
+
+ if (!sw_id && sw_id_epoch_less)
+ {
+ /* no full match - fall back to epoch-less match */
+ sw_id = sw_id_epoch_less;
+ }
+ if (sw_id)
+ {
+ /* sw identifier exists - update state to 'deleted' */
+ if (!this->db->update_sw_id(this->db, sw_id, NULL, NULL, FALSE))
+ {
+ goto end;
+ }
+ }
+ else
+ {
+ /* new sw identifier - create with state 'deleted' */
+ sw_id = this->db->set_sw_id(this->db, del_sw_id, p->package,
+ del_version, this->source, FALSE);
+
+ /* add creation sw event with eid = 1 */
+ if (!sw_id || !this->db->add_sw_event(this->db, 1, sw_id,
+ SWIMA_EVENT_ACTION_CREATION))
+ {
+ goto end;
+ }
+ }
+
+ /* add creation sw event with current eid */
if (!this->db->add_sw_event(this->db, eid, sw_id,
- SWIMA_EVENT_ACTION_DELETION))
+ SWIMA_EVENT_ACTION_DELETION))
{
goto end;
}
@@ -346,150 +370,136 @@ end:
METHOD(sw_collector_history_t, merge_installed_packages, bool,
private_sw_collector_history_t *this)
{
- FILE *file;
uint32_t sw_id, count = 0;
- char line[BUF_LEN], *pos, *package, *version, *state, *name;
- bool success = FALSE;
- char cmd[] = "dpkg-query -W -f=\'${Package}\t${Version}\t${Status}\n\'";
+ char package_arch[BUF_LEN];
+ char *package, *arch, *version, *v1, *name, *n1;
+ bool installed, success = FALSE;
+ sw_collector_dpkg_t *dpkg;
+ enumerator_t *enumerator;
DBG1(DBG_IMC, "Merging:");
- file = popen(cmd, "r");
- if (!file)
+ dpkg = sw_collector_dpkg_create();
+ if (!dpkg)
{
- DBG1(DBG_IMC, "failed to run dpgk-query command");
return FALSE;
}
- while (TRUE)
+ enumerator = dpkg->create_sw_enumerator(dpkg);
+ while (enumerator->enumerate(enumerator, &package, &arch, &version))
{
- if (!fgets(line, sizeof(line), file))
- {
- break;
- }
+ name = this->info->create_sw_id(this->info, package, version);
+ DBG3(DBG_IMC, " %s merged", name);
- package = line;
- pos = strchr(line, '\t');
- if (!pos)
+ sw_id = this->db->get_sw_id(this->db, name, NULL, NULL, NULL,
+ &installed);
+ if (sw_id)
{
- goto end;
+ if (!installed)
+ {
+ DBG1(DBG_IMC, " warning: existing sw_id %u"
+ " is not installed", sw_id);
+
+ if (!this->db->update_sw_id(this->db, sw_id, name, version,
+ TRUE))
+ {
+ free(name);
+ goto end;
+ }
+ }
}
- *pos = '\0';
-
- version = ++pos;
- pos = strchr(pos, '\t');
- if (!pos)
+ else
{
- goto end;
+ /* check for a Debian epoch number */
+ v1 = strchr(version, ':');
+ if (v1)
+ {
+ /* check for existing and installed epoch-less version */
+ n1 = this->info->create_sw_id(this->info, package, ++v1);
+ sw_id = this->db->get_sw_id(this->db, n1, NULL, NULL, NULL,
+ &installed);
+ free(n1);
+
+ if (sw_id && installed)
+ {
+ /* add epoch to existing version */
+ if (!this->db->update_sw_id(this->db, sw_id, name, version,
+ installed))
+ {
+ free(name);
+ goto end;
+ }
+ }
+ else
+ {
+ sw_id = 0;
+ }
+ }
}
- *pos = '\0';
- state = ++pos;
- pos = strchr(pos, '\n');
- if (!pos)
+ if (!sw_id)
{
- goto end;
- }
- *pos = '\0';
+ /* Package name is stored with appended architecture */
+ if (!streq(arch, "all"))
+ {
+ snprintf(package_arch, BUF_LEN, "%s:%s", package, arch);
+ package = package_arch;
+ }
- if (!streq(state, "install ok installed"))
- {
- continue;
- }
- name = create_sw_id(this->tag_creator, this->os, package, version);
- DBG3(DBG_IMC, " %s merged", name);
+ /* new sw identifier - create with state 'installed' */
+ sw_id = this->db->set_sw_id(this->db, name, package, version,
+ this->source, TRUE);
+
+ /* add creation sw event with eid = 1 */
+ if (!sw_id || !this->db->add_sw_event(this->db, 1, sw_id,
+ SWIMA_EVENT_ACTION_CREATION))
+ {
+ free(name);
+ goto end;
+ }
- sw_id = this->db->set_sw_id(this->db, name, package, version,
- this->source, TRUE, TRUE);
- free(name);
- if (!sw_id)
- {
- goto end;
}
+ free(name);
count++;
}
success = TRUE;
- DBG1(DBG_IMC, " merged %u installed packages, %u registed in database",
+
+ DBG1(DBG_IMC, " merged %u installed packages, %u registered in database",
count, this->db->get_sw_id_count(this->db, SW_QUERY_INSTALLED));
end:
- pclose(file);
+ enumerator->destroy(enumerator);
+ dpkg->destroy(dpkg);
+
return success;
}
METHOD(sw_collector_history_t, destroy, void,
private_sw_collector_history_t *this)
{
- this->os_info->destroy(this->os_info);
- free(this->os);
- free(this->product);
free(this);
}
/**
* Described in header.
*/
-sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
+sw_collector_history_t *sw_collector_history_create(sw_collector_info_t *info,
+ sw_collector_db_t *db,
uint8_t source)
{
private_sw_collector_history_t *this;
- chunk_t os_name, os_version, os_arch;
- os_type_t os_type;
INIT(this,
.public = {
- .get_os = _get_os,
.extract_timestamp = _extract_timestamp,
.extract_packages = _extract_packages,
.merge_installed_packages = _merge_installed_packages,
.destroy = _destroy,
},
- .db = db,
.source = source,
- .os_info = imc_os_info_create(),
- .tag_creator = lib->settings->get_str(lib->settings,
- "%s.tag_creator.regid", "strongswan.org", lib->ns),
+ .info = info,
+ .db = db,
);
- os_type = this->os_info->get_type(this->os_info);
- os_name = this->os_info->get_name(this->os_info);
- os_arch = this->os_info->get_version(this->os_info);
-
- /* check if OS is supported */
- if (os_type != OS_TYPE_DEBIAN && os_type != OS_TYPE_UBUNTU)
- {
- DBG1(DBG_IMC, "%.*s OS not supported", os_name.len, os_name.ptr);
- destroy(this);
- return NULL;
- }
-
- /* get_version() returns version followed by arch */
- if (!extract_token(&os_version, ' ', &os_arch))
- {
- DBG1(DBG_IMC, "separation of OS version from arch failed");
- destroy(this);
- return NULL;
- }
-
- /* construct OS string */
- if (asprintf(&this->os, "%.*s_%.*s-%.*s", os_name.len, os_name.ptr,
- os_version.len, os_version.ptr,
- os_arch.len, os_arch.ptr) == -1)
- {
- DBG1(DBG_IMC, "constructon of OS string failed");
- destroy(this);
- return NULL;
- }
-
- /* construct product string */
- if (asprintf(&this->product, "%.*s %.*s %.*s", os_name.len, os_name.ptr,
- os_version.len, os_version.ptr,
- os_arch.len, os_arch.ptr) == -1)
- {
- DBG1(DBG_IMC, "constructon of product string failed");
- destroy(this);
- return NULL;
- }
-
return &this->public;
}
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.h b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.h
index d1a3b2130..857cc17d2 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.h
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_history.h
@@ -15,12 +15,14 @@
/**
* @defgroup sw_collector_history_t sw_collector_history
- * @{ @ingroup imc_swima
+ * @{ @ingroup sw_collector
*/
#ifndef SW_COLLECTOR_HISTORY_H_
#define SW_COLLECTOR_HISTORY_H_
+#include "sw_collector_history.h"
+#include "sw_collector_info.h"
#include "sw_collector_db.h"
#include <library.h>
@@ -45,14 +47,6 @@ enum sw_collector_history_op_t {
struct sw_collector_history_t {
/**
- * Get OS and product strings
- *
- * @param product Product string formed from OS info
- * @return OS string formed from OS info
- */
- char* (*get_os)(sw_collector_history_t *this, char **product);
-
- /**
* Extract timestamp from event in installation history
*
* @param args Arguments to be processed
@@ -90,10 +84,12 @@ struct sw_collector_history_t {
/**
* Create an sw_collector_history_t instance
*
+ * @param info Internal reference to collector info
* @param db Internal reference to collector database
* @param source Software event source number
*/
-sw_collector_history_t* sw_collector_history_create(sw_collector_db_t *db,
+sw_collector_history_t* sw_collector_history_create(sw_collector_info_t *info,
+ sw_collector_db_t *db,
uint8_t source);
#endif /** SW_COLLECTOR_HISTORY_H_ @}*/
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.c b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.c
new file mode 100644
index 000000000..0ac5f0dfb
--- /dev/null
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "sw_collector_info.h"
+
+#include <library.h>
+#include <utils/lexparser.h>
+
+typedef struct private_sw_collector_info_t private_sw_collector_info_t;
+
+/**
+ * Private data of an sw_collector_info_t object.
+ */
+struct private_sw_collector_info_t {
+
+ /**
+ * Public members of sw_collector_info_state_t
+ */
+ sw_collector_info_t public;
+
+ /**
+ * tagCreator
+ */
+ char *tag_creator;
+
+ /**
+ * OS string 'Name_Version-Arch'
+ */
+ char *os;
+
+ /**
+ * Product string 'Name Version Arch'
+ */
+ char *product;
+
+ /**
+ * OS info about endpoint
+ */
+ imc_os_info_t *os_info;
+
+};
+
+/**
+ * Replaces invalid character by a valid one
+ */
+static void sanitize_uri(char *uri, char a, char b)
+{
+ char *pos = uri;
+
+ while (TRUE)
+ {
+ pos = strchr(pos, a);
+ if (!pos)
+ {
+ break;
+ }
+ *pos = b;
+ pos++;
+ }
+}
+
+METHOD(sw_collector_info_t, get_os_type, os_type_t,
+ private_sw_collector_info_t *this)
+{
+ return this->os_info->get_type(this->os_info);
+}
+
+METHOD(sw_collector_info_t, get_os, char*,
+ private_sw_collector_info_t *this, char **product)
+{
+ if (product)
+ {
+ *product = this->product;
+ }
+ return this->os;
+}
+
+METHOD(sw_collector_info_t, create_sw_id, char*,
+ private_sw_collector_info_t *this, char *package, char *version)
+{
+ char *pos, *sw_id;
+ size_t len;
+
+ /* Remove architecture from package name */
+ pos = strchr(package, ':');
+ len = pos ? (pos - package) : strlen(package);
+
+ /* Build software identifier */
+ if (asprintf(&sw_id, "%s__%s-%.*s%s%s", this->tag_creator, this->os, len,
+ package, strlen(version) ? "-" : "", version) == -1)
+ {
+ return NULL;
+ }
+ sanitize_uri(sw_id, ':', '~');
+ sanitize_uri(sw_id, '+', '~');
+
+ return sw_id;
+}
+
+METHOD(sw_collector_info_t, destroy, void,
+ private_sw_collector_info_t *this)
+{
+ this->os_info->destroy(this->os_info);
+ free(this->os);
+ free(this->product);
+ free(this->tag_creator);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+sw_collector_info_t *sw_collector_info_create(char *tag_creator)
+{
+ private_sw_collector_info_t *this;
+ chunk_t os_name, os_version, os_arch;
+
+ INIT(this,
+ .public = {
+ .get_os_type = _get_os_type,
+ .get_os = _get_os,
+ .create_sw_id = _create_sw_id,
+ .destroy = _destroy,
+ },
+ .os_info = imc_os_info_create(),
+ .tag_creator = strdup(tag_creator),
+ );
+
+ os_name = this->os_info->get_name(this->os_info);
+ os_arch = this->os_info->get_version(this->os_info);
+
+ /* get_version() returns version followed by arch */
+ if (!extract_token(&os_version, ' ', &os_arch))
+ {
+ DBG1(DBG_IMC, "separation of OS version from arch failed");
+ destroy(this);
+ return NULL;
+ }
+
+ /* construct OS string */
+ if (asprintf(&this->os, "%.*s_%.*s-%.*s", os_name.len, os_name.ptr,
+ os_version.len, os_version.ptr,
+ os_arch.len, os_arch.ptr) == -1)
+ {
+ DBG1(DBG_IMC, "constructon of OS string failed");
+ destroy(this);
+ return NULL;
+ }
+
+ /* construct product string */
+ if (asprintf(&this->product, "%.*s %.*s %.*s", os_name.len, os_name.ptr,
+ os_version.len, os_version.ptr,
+ os_arch.len, os_arch.ptr) == -1)
+ {
+ DBG1(DBG_IMC, "constructon of product string failed");
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.h b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.h
new file mode 100644
index 000000000..a54d788f4
--- /dev/null
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_info.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup sw_collector_info_t sw_collector_info
+ * @{ @ingroup sw_collector
+ */
+
+#ifndef SW_COLLECTOR_INFO_H_
+#define SW_COLLECTOR_INFO_H_
+
+typedef struct sw_collector_info_t sw_collector_info_t;
+
+#include "imc/imc_os_info.h"
+
+struct sw_collector_info_t {
+
+ /**
+ * Get OS type
+ *
+ * @return OS type
+ */
+ os_type_t (*get_os_type)(sw_collector_info_t *this);
+
+ /**
+ * Get OS and product strings
+ *
+ * @param product Product string 'Name Version Arch'
+ * @return OS string 'Name_Version-Arch'
+ */
+ char* (*get_os)(sw_collector_info_t *this, char **product);
+
+ /**
+ * Create software identifier including tagCreator and OS
+ *
+ * @param package Package string
+ * @param version Version string
+ * @return Software Identifier string
+ */
+ char* (*create_sw_id)(sw_collector_info_t *this, char *package,
+ char *version);
+
+ /**
+ * Destroy sw_collector_info_t object
+ */
+ void (*destroy)(sw_collector_info_t *this);
+
+};
+
+/**
+ * Create an sw_collector_info_t instance
+ *
+ * @param tag_creator Regid of tagCreator
+ */
+sw_collector_info_t* sw_collector_info_create(char *tag_creator);
+
+#endif /** SW_COLLECTOR_INFO_H_ @}*/
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.c b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.c
index 15108a01c..6b9b7b96a 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.c
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.c
@@ -50,19 +50,19 @@ static json_object* create_rest_request(private_sw_collector_rest_api_t *this,
{
json_object *jrequest, *jarray, *jstring;
char *name, *package, *version;
- uint32_t i;
+ uint32_t sw_id, i;
enumerator_t *e;
jrequest = json_object_new_object();
jarray = json_object_new_array();
json_object_object_add(jrequest, "data", jarray);
- e = this->db->create_sw_enumerator(this->db, type);
+ e = this->db->create_sw_enumerator(this->db, type, NULL);
if (!e)
{
return NULL;
}
- while (e->enumerate(e, &name, &package, &version, &i))
+ while (e->enumerate(e, &sw_id, &name, &package, &version, &i))
{
jstring = json_object_new_string(name);
json_object_array_add(jarray, jstring);
diff --git a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.h b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.h
index e44ab6d06..ca45230e6 100644
--- a/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.h
+++ b/src/libimcv/plugins/imc_swima/sw_collector/sw_collector_rest_api.h
@@ -26,7 +26,7 @@
typedef struct sw_collector_rest_api_t sw_collector_rest_api_t;
/**
- * Software collector database object
+ * Software collector REST API object
*/
struct sw_collector_rest_api_t {