swid-gen: Share SWID generator between sw-collector, imc-swima and imc-swid

This commit is contained in:
Andreas Steffen 2017-08-03 09:00:59 +02:00
parent 073c179a88
commit 88501a64ca
15 changed files with 567 additions and 451 deletions

View File

@ -21,6 +21,15 @@ charon.imcv.os_info.default_password_enabled = no
charon.imcv.policy_script = ipsec _imv_policy
Script called for each TNC connection to generate IMV policies.
libimcv.swid_gen.command = /usr/local/bin/swid_generator
SWID generator command to be executed.
libimcv.swid_gen.tag_creator.name = strongSwan Project
Name of the tagCreator entity.
libimcv.swid_gen.tag_creator.regid = strongswan.org
regid of the tagCreator entity.
libimcv.debug_level = 1
Debug level for a stand-alone _libimcv_ library.

View File

@ -22,14 +22,5 @@ sw-collector.rest_api.uri =
sw-collector.rest_api.timeout = 120
Timeout of REST API HTTP POST transaction.
sw-collector.tag_creator.name = strongSwan Project
Name of the tagCreator entity.
sw-collector.tag_creator.regid = strongswan.org
regid of the tagCreator entity.
sw-collector.swid_generator = /usr/local/bin/swid_generator
SWID generator command to be executed.
sw-collector.load =
Plugins to load in sw-collector tool.

View File

@ -1,9 +1,6 @@
libimcv.plugins.imc-swid.swid_directory = ${prefix}/share
Directory where SWID tags are located.
libimcv.plugins.imc-swid.swid_generator = /usr/local/bin/swid_generator
SWID generator command to be executed.
libimcv.plugins.imc-swid.swid_pretty = FALSE
Generate XML-encoded SWID tags with pretty indentation.

View File

@ -9,9 +9,6 @@ libimcv.plugins.imc-swima.swid_epoch = 0x11223344
libimcv.plugins.imc-swima.swid_directory = ${prefix}/share
Directory where SWID tags are located.
libimcv.plugins.imc-swima.swid_generator = /usr/local/bin/swid_generator
SWID generator command to be executed.
libimcv.plugins.imc-swima.swid_pretty = FALSE
Generate XML-encoded SWID tags with pretty indentation.

View File

@ -100,6 +100,7 @@ libimcv_la_SOURCES = \
swid/swid_inventory.h swid/swid_inventory.c \
swid/swid_tag.h swid/swid_tag.c \
swid/swid_tag_id.h swid/swid_tag_id.c \
swid_gen/swid_gen.h swid_gen/swid_gen.c \
swima/swima_data_model.h swima/swima_data_model.c \
swima/swima_record.h swima/swima_record.c \
swima/swima_event.h swima/swima_event.c \
@ -214,6 +215,7 @@ imcv_tests_SOURCES = \
pa_tnc/pa_tnc_attr_manager.c \
seg/seg_env.c seg/seg_contract.c \
seg/seg_contract_manager.c \
swid_gen/swid_gen.c \
swima/swima_data_model.c \
swima/swima_event.c \
swima/swima_events.c \

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2015 Andreas Steffen
* Copyright (C) 2013-2017 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -30,8 +30,6 @@
#include <pen/pen.h>
#include <utils/debug.h>
#define SWID_GENERATOR "/usr/local/bin/swid_generator"
/* IMC definitions */
static const char imc_name[] = "SWID";
@ -165,7 +163,7 @@ static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
pa_tnc_attr_t *attr, *attr_error;
imc_swid_state_t *swid_state;
swid_inventory_t *swid_inventory;
char *swid_directory, *swid_generator;
char *swid_directory;
uint32_t eid_epoch;
bool swid_pretty, swid_full;
enumerator_t *enumerator;
@ -173,9 +171,6 @@ static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
swid_directory = lib->settings->get_str(lib->settings,
"%s.plugins.imc-swid.swid_directory",
SWID_DIRECTORY, lib->ns);
swid_generator = lib->settings->get_str(lib->settings,
"%s.plugins.imc-swid.swid_generator",
SWID_GENERATOR, lib->ns);
swid_pretty = lib->settings->get_bool(lib->settings,
"%s.plugins.imc-swid.swid_pretty",
FALSE, lib->ns);
@ -184,8 +179,8 @@ static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
FALSE, lib->ns);
swid_inventory = swid_inventory_create(full_tags);
if (!swid_inventory->collect(swid_inventory, swid_directory, swid_generator,
targets, swid_pretty, swid_full))
if (!swid_inventory->collect(swid_inventory, swid_directory, targets,
swid_pretty, swid_full))
{
swid_inventory->destroy(swid_inventory);
attr_error = swid_error_create(TCG_SWID_ERROR, request_id,

View File

@ -590,7 +590,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
DBG1(DBG_IMV, " %s", target);
/* Separate target into tag_creator and unique_sw_id */
separator = strchr(target, '_');
separator = strstr(target, "__");
if (!separator)
{
error_str = "separation of regid from "
@ -598,9 +598,9 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
break;
}
tag_creator = chunk_create(target, separator - target);
separator++;
separator += 2;
unique_sw_id = chunk_create(separator, strlen(target) -
tag_creator.len - 1);
tag_creator.len - 2);
tag_id = swid_tag_id_create(tag_creator, unique_sw_id,
chunk_empty);
cast_attr = (tcg_swid_attr_req_t*)attr;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2016 Andreas Steffen
* Copyright (C) 2013-2017 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -288,8 +288,8 @@ METHOD(imv_swid_state_t, get_request_id, uint32_t,
METHOD(imv_swid_state_t, set_swid_inventory, void,
private_imv_swid_state_t *this, swid_inventory_t *inventory)
{
chunk_t tag_creator, unique_sw_id;
char software_id[256];
chunk_t tag_creator, sw_id;
char software_id[BUF_LEN];
json_object *jstring;
swid_tag_id_t *tag_id;
enumerator_t *enumerator;
@ -299,10 +299,9 @@ METHOD(imv_swid_state_t, set_swid_inventory, void,
{
/* Construct software ID from tag creator and unique software ID */
tag_creator = tag_id->get_tag_creator(tag_id);
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
snprintf(software_id, 256, "%.*s_%.*s",
tag_creator.len, tag_creator.ptr,
unique_sw_id.len, unique_sw_id.ptr);
sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
snprintf(software_id, BUF_LEN, "%.*s__%.*s",
tag_creator.len, tag_creator.ptr, sw_id.len, sw_id.ptr);
DBG3(DBG_IMV, " %s", software_id);
/* Add software ID to JSON array */

View File

@ -16,9 +16,10 @@
#include "swid_inventory.h"
#include "swid_tag.h"
#include "swid_tag_id.h"
#include "swid_gen/swid_gen.h"
#include <collections/linked_list.h>
#include <bio/bio_writer.h>
#include <utils/lexparser.h>
#include <utils/debug.h>
#include <stdio.h>
@ -52,186 +53,92 @@ struct private_swid_inventory_t {
linked_list_t *list;
};
/**
* Read SWID tags issued by the swid_generator tool
*/
static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
{
swid_tag_t *tag;
bio_writer_t *writer;
chunk_t tag_encoding, tag_file_path = chunk_empty;
bool more_tags = TRUE, last_newline;
char line[8192];
size_t len;
while (more_tags)
{
last_newline = TRUE;
writer = bio_writer_create(512);
while (TRUE)
{
if (!fgets(line, sizeof(line), file))
{
more_tags = FALSE;
break;
}
len = strlen(line);
if (last_newline && line[0] == '\n')
{
break;
}
else
{
last_newline = (line[len-1] == '\n');
writer->write_data(writer, chunk_create(line, len));
}
}
tag_encoding = writer->get_buf(writer);
if (tag_encoding.len > 1)
{
/* remove trailing newline if present */
if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
{
tag_encoding.len--;
}
DBG3(DBG_IMC, " %.*s", tag_encoding.len, tag_encoding.ptr);
tag = swid_tag_create(tag_encoding, tag_file_path);
this->list->insert_last(this->list, tag);
}
writer->destroy(writer);
}
return SUCCESS;
}
/**
* Read SWID tag or software IDs issued by the swid_generator tool
*/
static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
{
swid_tag_id_t *tag_id;
chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
char line[BUF_LEN];
while (TRUE)
{
char *separator;
size_t len;
if (!fgets(line, sizeof(line), file))
{
return SUCCESS;
}
len = strlen(line);
/* remove trailing newline if present */
if (len > 0 && line[len - 1] == '\n')
{
len--;
}
DBG3(DBG_IMC, " %.*s", len, line);
separator = strchr(line, '_');
if (!separator)
{
DBG1(DBG_IMC, "separation of regid from unique software ID failed");
return FAILED;
}
tag_creator = chunk_create(line, separator - line);
separator++;
unique_sw_id = chunk_create(separator, len - (separator - line));
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
this->list->insert_last(this->list, tag_id);
}
}
static status_t generate_tags(private_swid_inventory_t *this, char *generator,
static status_t generate_tags(private_swid_inventory_t *this,
swid_inventory_t *targets, bool pretty, bool full)
{
FILE *file;
char command[BUF_LEN];
char doc_separator[] = "'\n\n'";
swid_gen_t *swid_gen;
swid_tag_t *tag;
swid_tag_id_t *tag_id;
enumerator_t *enumerator;
status_t status = SUCCESS;
chunk_t out;
swid_gen = swid_gen_create();
if (targets->get_count(targets) == 0)
{
/* Assemble the SWID generator command */
if (this->full_tags)
DBG2(DBG_IMC, "SWID tag%s generation by package manager",
this->full_tags ? "" : " ID");
enumerator = swid_gen->create_tag_enumerator(swid_gen, !this->full_tags,
full, pretty);
if (enumerator)
{
snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
generator, doc_separator, pretty ? " --pretty" : "",
full ? " --full" : "");
while (enumerator->enumerate(enumerator, &out))
{
if (this->full_tags)
{
chunk_t swid_tag = out;
tag = swid_tag_create(swid_tag, chunk_empty);
this->list->insert_last(this->list, tag);
}
else
{
chunk_t tag_creator, sw_id = out;
if (extract_token_str(&tag_creator, "__", &sw_id))
{
tag_id = swid_tag_id_create(tag_creator, sw_id,
chunk_empty);
this->list->insert_last(this->list, tag_id);
}
else
{
DBG1(DBG_IMC, "separation of regid from unique "
"software ID failed");
status = FAILED;
chunk_free(&out);
break;
}
}
chunk_free(&out);
}
enumerator->destroy(enumerator);
}
else
{
snprintf(command, BUF_LEN, "%s software-id", generator);
status = NOT_SUPPORTED;
}
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (!file)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NOT_SUPPORTED;
}
if (this->full_tags)
{
DBG2(DBG_IMC, "SWID tag generation by package manager");
status = read_swid_tags(this, file);
}
else
{
DBG2(DBG_IMC, "SWID tag ID generation by package manager");
status = read_swid_tag_ids(this, file);
}
pclose(file);
}
else if (this->full_tags)
{
swid_tag_id_t *tag_id;
enumerator_t *enumerator;
DBG2(DBG_IMC, "targeted SWID tag generation");
enumerator = targets->create_enumerator(targets);
while (enumerator->enumerate(enumerator, &tag_id))
{
char software_id[BUF_LEN];
chunk_t tag_creator, unique_sw_id;
char software_id[BUF_LEN], *swid_tag;
chunk_t tag_creator, sw_id;
/* Construct software ID from tag creator and unique software ID */
tag_creator = tag_id->get_tag_creator(tag_id);
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
snprintf(software_id, BUF_LEN, "%.*s_%.*s",
tag_creator.len, tag_creator.ptr,
unique_sw_id.len, unique_sw_id.ptr);
sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
snprintf(software_id, BUF_LEN, "%.*s__%.*s",
tag_creator.len, tag_creator.ptr, sw_id.len, sw_id.ptr);
/* Assemble the SWID generator command */
snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
generator, software_id, pretty ? " --pretty" : "",
full ? " --full" : "");
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (!file)
swid_tag = swid_gen->generate_tag(swid_gen, software_id, NULL, NULL,
full, pretty);
if (swid_tag)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NOT_SUPPORTED;
}
status = read_swid_tags(this, file);
pclose(file);
if (status != SUCCESS)
{
break;
tag = swid_tag_create(chunk_from_str(swid_tag), chunk_empty);
this->list->insert_last(this->list, tag);
free(swid_tag);
}
}
enumerator->destroy(enumerator);
}
swid_gen->destroy(swid_gen);
return status;
}
@ -284,16 +191,16 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
}
/* parse the swidtag filename into its components */
separator = strchr(rel_name, '_');
separator = strstr(rel_name, "__");
if (!separator)
{
DBG1(DBG_IMC, " %s", rel_name);
DBG1(DBG_IMC, " '_' separator not found");
DBG1(DBG_IMC, " '__' separator not found");
goto end;
}
tag_creator = chunk_create(rel_name, separator-rel_name);
unique_sw_id = chunk_create(separator+1, suffix-separator-1);
unique_sw_id = chunk_create(separator+2, suffix-separator-2);
tag_file_path = chunk_from_str(abs_name);
/* In case of a targeted request */
@ -364,13 +271,13 @@ end:
}
METHOD(swid_inventory_t, collect, bool,
private_swid_inventory_t *this, char *directory, char *generator,
swid_inventory_t *targets, bool pretty, bool full)
private_swid_inventory_t *this, char *directory, swid_inventory_t *targets,
bool pretty, bool full)
{
/**
* Tags are generated by a package manager
*/
generate_tags(this, generator, targets, pretty, full);
generate_tags(this, targets, pretty, full);
/**
* Collect swidtag files by iteratively entering all directories in

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2014 Andreas Steffen
* Copyright (C) 2013-2017 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -37,13 +37,12 @@ struct swid_inventory_t {
* Collect the SWID tags stored on the endpoint
*
* @param directory SWID directory path
* @param generator Path to SWID generator
* @param targets List of target tag IDs
* @param pretty Generate indented XML SWID tags
* @param full Include file information in SWID tags
* @return TRUE if successful
*/
bool (*collect)(swid_inventory_t *this, char *directory, char *generator,
bool (*collect)(swid_inventory_t *this, char *directory,
swid_inventory_t *targets, bool pretty, bool full);
/**

View File

@ -0,0 +1,291 @@
/*
* 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 "swid_gen.h"
#include <bio/bio_writer.h>
#define SWID_GENERATOR "/usr/local/bin/swid_generator"
typedef struct private_swid_gen_t private_swid_gen_t;
/**
* Private data of a swid_gen_t object.
*
*/
struct private_swid_gen_t {
/**
* Public swid_gen_t interface.
*/
swid_gen_t public;
/**
* Path of the SWID generator command
*/
char *generator;
/**
* Entity name of the tagCreator
*/
char *entity;
/**
* Regid of the tagCreator
*/
char *regid;
};
METHOD(swid_gen_t, generate_tag, char*,
private_swid_gen_t *this, char *sw_id, char *package, char *version,
bool full, bool pretty)
{
char *tag = NULL;
size_t tag_buf_len = 8192;
char tag_buf[tag_buf_len], command[BUF_LEN];
bio_writer_t *writer;
chunk_t swid_tag;
FILE *file;
/* Compose the SWID generator command */
if (full || !package || !version)
{
snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" "
"--regid %s --software-id %s%s%s",
this->generator, this->entity, this->regid, sw_id,
full ? " --full" : "", pretty ? " --pretty" : "");
}
else
{
snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" "
"--regid %s --name %s --version-string %s%s",
this->generator, this->entity, this->regid, package,
version, pretty ? " --pretty" : "");
}
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (file)
{
writer = bio_writer_create(tag_buf_len);
while (TRUE)
{
if (!fgets(tag_buf, tag_buf_len, file))
{
break;
}
writer->write_data(writer, chunk_create(tag_buf, strlen(tag_buf)));
}
pclose(file);
swid_tag = writer->extract_buf(writer);
writer->destroy(writer);
if (swid_tag.len > 0)
{
tag = swid_tag.ptr;
tag[swid_tag.len - 1] = '\0';
}
else
{
chunk_free(&swid_tag);
}
}
else
{
DBG1(DBG_IMC, "failed to run swid_generator command");
}
return tag;
}
typedef struct {
/** public enumerator interface */
enumerator_t public;
/** swid_generator output stream */
FILE *file;
/** generate software identifier only */
bool sw_id_only;
} swid_gen_enumerator_t;
METHOD(enumerator_t, enumerate, bool,
swid_gen_enumerator_t *this, va_list args)
{
chunk_t *out;
VA_ARGS_VGET(args, out);
if (this->sw_id_only)
{
char line[BUF_LEN];
size_t len;
if (!fgets(line, sizeof(line), this->file))
{
return FALSE;
}
len = strlen(line);
if (len == 0)
{
return FALSE;
}
/* remove trailing newline if present */
if (line[len - 1] == '\n')
{
len--;
}
DBG3(DBG_IMC, " %.*s", len, line);
*out = chunk_clone(chunk_create(line, len));
}
else
{
bool last_newline = TRUE;
size_t len, line_len = 8192;
char line[line_len];
bio_writer_t *writer;
chunk_t swid_tag;
writer = bio_writer_create(line_len);
while (TRUE)
{
if (!fgets(line, line_len, this->file))
{
break;
}
len = strlen(line);
if (last_newline && line[0] == '\n')
{
break;
}
else
{
last_newline = (line[len-1] == '\n');
writer->write_data(writer, chunk_create(line, len));
}
}
swid_tag = writer->extract_buf(writer);
writer->destroy(writer);
if (swid_tag.len <= 1)
{
chunk_free(&swid_tag);
return FALSE;
}
/* remove trailing newline if present */
if (swid_tag.ptr[swid_tag.len - 1] == '\n')
{
swid_tag.len--;
}
DBG3(DBG_IMC, " %.*s", swid_tag.len, swid_tag.ptr);
*out = swid_tag;
}
return TRUE;
}
METHOD(enumerator_t, enumerator_destroy, void,
swid_gen_enumerator_t *this)
{
pclose(this->file);
free(this);
}
METHOD(swid_gen_t, create_tag_enumerator, enumerator_t*,
private_swid_gen_t *this, bool sw_id_only, bool full, bool pretty)
{
swid_gen_enumerator_t *enumerator;
char command[BUF_LEN];
char doc_separator[] = "'\n\n'";
FILE *file;
/* Assemble the SWID generator command */
if (sw_id_only)
{
snprintf(command, BUF_LEN, "%s software-id --regid %s ",
this->generator, this->regid);
}
else
{
snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" --regid %s "
"--doc-separator %s%s%s", this->generator, this->entity,
this->regid, doc_separator, pretty ? " --pretty" : "",
full ? " --full" : "");
}
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (!file)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NULL;
}
INIT(enumerator,
.public = {
.enumerate = enumerator_enumerate_default,
.venumerate = _enumerate,
.destroy = _enumerator_destroy,
},
.sw_id_only = sw_id_only,
.file = file,
);
return &enumerator->public;
}
METHOD(swid_gen_t, destroy, void,
private_swid_gen_t *this)
{
free(this->generator);
free(this->entity);
free(this->regid);
free(this);
}
/**
* See header
*/
swid_gen_t *swid_gen_create(void)
{
private_swid_gen_t *this;
char *entity, *regid, *generator;
entity = lib->settings->get_str(lib->settings,
"libimcv.swid_gen.tag_creator.name", "strongSwan Project");
regid = lib->settings->get_str(lib->settings,
"libimcv.swid_gen.tag_creator.regid", "strongswan.org");
generator = lib->settings->get_str(lib->settings,
"libimcv.swid_gen.command", SWID_GENERATOR);
INIT(this,
.public = {
.generate_tag = _generate_tag,
.create_tag_enumerator = _create_tag_enumerator,
.destroy = _destroy,
},
.generator = strdup(generator),
.entity = strdup(entity),
.regid = strdup(regid),
);
return &this->public;
}

View File

@ -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 swid_gen swid_gen
* @{ @ingroup libimcv
*/
#ifndef SWID_GEN_H_
#define SWID_GEN_H_
#include <library.h>
typedef struct swid_gen_t swid_gen_t;
/**
* Class generating a either a full or a minimalistic ISO 19770-2:2015 SWID tag
*/
struct swid_gen_t {
/**
* Generate a SWID tag
*
* @param sw_id Software identifier
* @param package Package name (can be NULL)
* @param version Package version (can be NULL)
* @param full Generate full SWID tags with file information
* @param pretty Generate SWID tags with pretty formating
* @return SWID tag
*/
char* (*generate_tag)(swid_gen_t *this, char *sw_id, char *package,
char *version, bool full, bool pretty);
/**
* Generate a SWID tag
*
* @param sw_id_only Return software identifier only
* @param full Generate full SWID tags with file information
* @param pretty Generate SWID tags with pretty formating
* @return Tag enumerator (sw_id, tag)
*/
enumerator_t* (*create_tag_enumerator)(swid_gen_t *this, bool sw_id_only,
bool full, bool pretty);
/**
* Destroys a swid_gen_t object.
*/
void (*destroy)(swid_gen_t *this);
};
/**
* Creates a swid_gen_t object
*/
swid_gen_t* swid_gen_create(void);
#endif /** SWID_GEN_H_ @}*/

View File

@ -15,8 +15,9 @@
#include "swima_collector.h"
#include <swid_gen/swid_gen.h>
#include <collections/linked_list.h>
#include <bio/bio_writer.h>
#include <utils/debug.h>
#include <stdio.h>
@ -33,8 +34,6 @@
#define SWID_DIRECTORY NULL
#endif
#define SWID_GENERATOR "/usr/local/bin/swid_generator"
/**
* Directories to be skipped by collector
*/
@ -133,104 +132,6 @@ end:
return status;
}
/**
* Read SWID tags issued by the swid_generator tool
*/
static status_t read_swid_tags(private_swima_collector_t *this, FILE *file)
{
swima_record_t *sw_record;
bio_writer_t *writer;
chunk_t sw_id, swid_tag;
bool more_tags = TRUE, last_newline;
char line[8192];
size_t len;
status_t status;
while (more_tags)
{
last_newline = TRUE;
writer = bio_writer_create(512);
while (TRUE)
{
if (!fgets(line, sizeof(line), file))
{
more_tags = FALSE;
break;
}
len = strlen(line);
if (last_newline && line[0] == '\n')
{
break;
}
else
{
last_newline = (line[len-1] == '\n');
writer->write_data(writer, chunk_create(line, len));
}
}
swid_tag = writer->get_buf(writer);
if (swid_tag.len > 1)
{
/* remove trailing newline if present */
if (swid_tag.ptr[swid_tag.len - 1] == '\n')
{
swid_tag.len--;
}
DBG3(DBG_IMC, " %.*s", swid_tag.len, swid_tag.ptr);
status = extract_sw_id(swid_tag, &sw_id);
if (status != SUCCESS)
{
DBG1(DBG_IMC, "software id could not be extracted from tag");
writer->destroy(writer);
return status;
}
sw_record = swima_record_create(0, sw_id, chunk_empty);
sw_record->set_source_id(sw_record, SOURCE_ID_GENERATOR);
sw_record->set_record(sw_record, swid_tag);
this->inventory->add(this->inventory, sw_record);
chunk_free(&sw_id);
}
writer->destroy(writer);
}
return SUCCESS;
}
/**
* Read Software Identifiers issued by the swid_generator tool
*/
static status_t read_swid_tag_ids(private_swima_collector_t *this, FILE *file)
{
swima_record_t *sw_record;
chunk_t sw_id;
char line[BUF_LEN];
size_t len;
while (TRUE)
{
if (!fgets(line, sizeof(line), file))
{
return SUCCESS;
}
len = strlen(line);
/* remove trailing newline if present */
if (len > 0 && line[len - 1] == '\n')
{
len--;
}
DBG3(DBG_IMC, " %.*s", len, line);
sw_id = chunk_create(line, len);
sw_record = swima_record_create(0, sw_id, chunk_empty);
sw_record->set_source_id(sw_record, SOURCE_ID_GENERATOR);
this->inventory->add(this->inventory, sw_record);
}
}
static status_t retrieve_inventory(private_swima_collector_t *this,
swima_inventory_t *targets)
{
@ -299,82 +200,118 @@ static status_t retrieve_events(private_swima_collector_t *this,
return SUCCESS;
}
static status_t generate_tags(private_swima_collector_t *this, char *generator,
swima_inventory_t *targets, bool pretty, bool full)
static status_t generate_tags(private_swima_collector_t *this,
swima_inventory_t *targets, bool pretty, bool full)
{
FILE *file;
char command[BUF_LEN];
char doc_separator[] = "'\n\n'";
swid_gen_t *swid_gen;
swima_record_t *target, *sw_record;
enumerator_t *enumerator;
status_t status = SUCCESS;
swid_gen = swid_gen_create();
if (targets->get_count(targets) == 0)
{
/* Assemble the SWID generator command */
if (this->sw_id_only)
chunk_t out, sw_id, swid_tag = chunk_empty;
DBG2(DBG_IMC, "SWID tag%s generation by package manager",
this->sw_id_only ? " ID" : "");
enumerator = swid_gen->create_tag_enumerator(swid_gen, this->sw_id_only,
full, pretty);
if (enumerator)
{
snprintf(command, BUF_LEN, "%s software-id", generator);
while (enumerator->enumerate(enumerator, &out))
{
if (this->sw_id_only)
{
sw_id = out;
}
else
{
swid_tag = out;
status = extract_sw_id(swid_tag, &sw_id);
if (status != SUCCESS)
{
DBG1(DBG_IMC, "software id could not be extracted "
"from tag");
chunk_free(&swid_tag);
break;
}
}
sw_record = swima_record_create(0, sw_id, chunk_empty);
sw_record->set_source_id(sw_record, SOURCE_ID_GENERATOR);
if (!this->sw_id_only)
{
sw_record->set_record(sw_record, swid_tag);
chunk_free(&swid_tag);
}
this->inventory->add(this->inventory, sw_record);
chunk_free(&sw_id);
}
enumerator->destroy(enumerator);
}
else
{
snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
generator, doc_separator, pretty ? " --pretty" : "",
full ? " --full" : "");
status = NOT_SUPPORTED;
}
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (!file)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NOT_SUPPORTED;
}
if (this->sw_id_only)
{
DBG2(DBG_IMC, "SWID tag ID generation by package manager");
status = read_swid_tag_ids(this, file);
}
else
{
DBG2(DBG_IMC, "SWID tag generation by package manager");
status = read_swid_tags(this, file);
}
pclose(file);
}
else if (!this->sw_id_only)
{
swima_record_t *target;
enumerator_t *enumerator;
chunk_t sw_id;
DBG2(DBG_IMC, "targeted SWID tag generation");
enumerator = targets->create_enumerator(targets);
while (enumerator->enumerate(enumerator, &target))
{
swima_record_t *sw_record;
char *tag = NULL, *name, *package, *version;
u_int installed;
chunk_t sw_id;
enumerator_t *e;
sw_id = target->get_sw_id(target, NULL);
name = strndup(sw_id.ptr, sw_id.len);
/* Assemble the SWID generator command */
snprintf(command, BUF_LEN, "%s swid --software-id %.*s%s%s",
generator, sw_id.len, sw_id.ptr,
pretty ? " --pretty" : "", full ? " --full" : "");
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (!file)
if (this->db)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NOT_SUPPORTED;
e = this->db->query(this->db,
"SELECT package, version, installed "
"FROM sw_identifiers WHERE name = ?", DB_TEXT, name,
DB_TEXT, DB_TEXT, DB_UINT);
if (!e)
{
DBG1(DBG_IMC, "database query for sw_identifiers failed");
status = FAILED;
free(name);
break;
}
if (e->enumerate(e, &package, &version, &installed))
{
tag = swid_gen->generate_tag(swid_gen, name, package,
version, full && installed, pretty);
}
e->destroy(e);
}
status = read_swid_tags(this, file);
pclose(file);
if (status != SUCCESS)
else
{
break;
tag = swid_gen->generate_tag(swid_gen, name, NULL, NULL,
full, pretty);
}
free(name);
if (tag)
{
DBG2(DBG_IMC, " %.*s", sw_id.len, sw_id.ptr);
sw_record = swima_record_create(0, sw_id, chunk_empty);
sw_record->set_source_id(sw_record, SOURCE_ID_GENERATOR);
sw_record->set_record(sw_record, chunk_from_str(tag));
this->inventory->add(this->inventory, sw_record);
free(tag);
}
}
enumerator->destroy(enumerator);
}
swid_gen->destroy(swid_gen);
return status;
}
@ -480,6 +417,7 @@ static bool collect_tags(private_swima_collector_t *this, char *pathname,
{
if (chunk_equals(target->get_sw_id(target, NULL), sw_id))
{
DBG2(DBG_IMC, " %.*s", sw_id.len, sw_id.ptr);
match = TRUE;
break;
}
@ -518,16 +456,13 @@ end:
METHOD(swima_collector_t, collect_inventory, swima_inventory_t*,
private_swima_collector_t *this, bool sw_id_only, swima_inventory_t *targets)
{
char *directory, *generator;
bool pretty, full;
char *directory;
status_t status;
directory = lib->settings->get_str(lib->settings,
"%s.plugins.imc-swima.swid_directory",
SWID_DIRECTORY, lib->ns);
generator = lib->settings->get_str(lib->settings,
"%s.plugins.imc-swima.swid_generator",
SWID_GENERATOR, lib->ns);
pretty = lib->settings->get_bool(lib->settings,
"%s.plugins.imc-swima.swid_pretty",
FALSE, lib->ns);
@ -550,13 +485,14 @@ METHOD(swima_collector_t, collect_inventory, swima_inventory_t*,
}
else
{
status = generate_tags(this, generator, targets, pretty, full);
status = generate_tags(this, targets, pretty, full);
}
/**
* Source 2: Collect swidtag files by iteratively entering all
* directories in the tree under the "directory" path.
*/
DBG2(DBG_IMC, "SWID tag%s collection", sw_id_only ? " ID" : "");
collect_tags(this, directory, targets, FALSE);
return status == SUCCESS ? this->inventory : NULL;

View File

@ -99,9 +99,18 @@ The following parameters can be configured in strongswan.conf:
uri = https://admin-user:ietf99hackathon@tnc.strongswan.org/api/
timeout = 120
}
tag_creator {
name = strongSwan Project
regid = strongswan.org
}
.P
The parameters of the swid_generator used with the \-\-generate command can
be changed in the libimcv section of strongswan.conf:
.P
libimcv {
swid_gen {
command = /usr/local/bin/swid_generator
tag_creator {
name = strongSwan Project
regid = strongswan.org
}
}
}
.

View File

@ -30,13 +30,11 @@
#include "sw_collector_dpkg.h"
#
#include <library.h>
#include <bio/bio_writer.h>
#include <utils/debug.h>
#include <utils/lexparser.h>
#include <imv/imv_os_info.h>
#define SWID_GENERATOR "/usr/local/bin/swid_generator"
#include <swid_gen/swid_gen.h>
/**
* global debug output variables
@ -470,105 +468,21 @@ static int unregistered_identifiers(sw_collector_db_t *db,
}
/**
* Generate a either a full or a minimalistic ISO 19770-2:2015 SWID tag
*/
static char* generate_tag(char *name, char *package, char *version,
char* entity, char *regid, char *product,
bool full_tag, char *generator)
{
char *tag = NULL;
if (full_tag)
{
size_t tag_buf_len = 8192;
char tag_buf[tag_buf_len], command[BUF_LEN];
bio_writer_t *writer;
chunk_t tag_chunk;
FILE *file;
/* Compose the SWID generator command */
snprintf(command, BUF_LEN, "%s swid --full --regid %s --entity-name "
"\"%s\" --package %s", generator, regid, entity, package);
\
/* Open a pipe stream for reading the SWID generator output */
file = popen(command, "r");
if (file)
{
writer = bio_writer_create(tag_buf_len);
while (TRUE)
{
if (!fgets(tag_buf, tag_buf_len, file))
{
break;
}
writer->write_data(writer,
chunk_create(tag_buf, strlen(tag_buf)));
}
pclose(file);
tag_chunk = writer->extract_buf(writer);
writer->destroy(writer);
if (tag_chunk.len > 1)
{
tag = tag_chunk.ptr;
tag[tag_chunk.len - 1] = '\0';
}
}
else
{
DBG1(DBG_IMC, "failed to run swid_generator command");
}
}
/* Generate minimalistic SWID tag */
if (!tag)
{
char *tag_id;
tag_id = strstr(name, "__");
if (!tag_id)
{
return NULL;
}
tag_id += 2;
if (asprintf(&tag, "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<SoftwareIdentity name=\"%s\" tagId=\"%s\" version=\"%s\" "
"versionScheme=\"alphanumeric\" "
"xmlns=\"http://standards.iso.org/iso/19770/-2/2015/schema.xsd\">"
"<Entity name=\"%s\" regid=\"%s\" role=\"tagCreator\"/>"
"<Meta product=\"%s\"/>"
"</SoftwareIdentity>",
package, tag_id, version, entity, regid, product) == -1)
{
tag = NULL;
}
}
return tag;
}
/**
* Generate a minimalistic ISO 19770-2:2015 SWID tag for
* all removed SW identifiers that are not registered centrally
* Generate ISO 19770-2:2015 SWID tags for [installed|removed|all]
* SW identifiers that are not registered centrally
*/
static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
bool full_tags, sw_collector_db_query_t type)
{
swid_gen_t * swid_gen;
sw_collector_rest_api_t *rest_api;
char *name, *package, *version, *entity, *regid, *product, *generator, *tag;
char *name, *package, *version, *tag;
enumerator_t *enumerator;
uint32_t sw_id;
bool installed;
int count = 0, installed_count = 0, status = EXIT_FAILURE;
entity = lib->settings->get_str(lib->settings, "%s.tag_creator.name",
"strongSwan Project", lib->ns);
regid = lib->settings->get_str(lib->settings, "%s.tag_creator.regid",
"strongswan.org", lib->ns);
generator = lib->settings->get_str(lib->settings, "%s.swid_generator",
SWID_GENERATOR, lib->ns);
info->get_os(info, &product);
swid_gen = swid_gen_create();
rest_api = sw_collector_rest_api_create(db);
if (!rest_api)
{
@ -585,8 +499,8 @@ static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
sw_id = db->get_sw_id(db, name, &package, &version, NULL, &installed);
if (sw_id)
{
tag = generate_tag(name, package, version, entity, regid, product,
full_tags && installed, generator);
tag = swid_gen->generate_tag(swid_gen, name, package, version,
full_tags && installed, FALSE);
if (tag)
{
DBG2(DBG_IMC, " creating %s", name);
@ -623,6 +537,7 @@ static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
}
end:
swid_gen->destroy(swid_gen);
DESTROY_IF(rest_api);
return status;