libimcv: Removed TCG SWID IMC/IMV support
This commit is contained in:
@@ -61,13 +61,11 @@ plugins = \
|
||||
plugins/imc-hcd.opt \
|
||||
plugins/imc-os.opt \
|
||||
plugins/imc-scanner.opt \
|
||||
plugins/imc-swid.opt \
|
||||
plugins/imc-swima.opt \
|
||||
plugins/imc-test.opt \
|
||||
plugins/imv-attestation.opt \
|
||||
plugins/imv-os.opt \
|
||||
plugins/imv-scanner.opt \
|
||||
plugins/imv-swid.opt \
|
||||
plugins/imv-swima.opt \
|
||||
plugins/imv-test.opt \
|
||||
plugins/ipseckey.opt \
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
libimcv.plugins.imc-swid.swid_directory = ${prefix}/share
|
||||
Directory where SWID tags are located.
|
||||
|
||||
libimcv.plugins.imc-swid.swid_pretty = no
|
||||
Generate XML-encoded SWID tags with pretty indentation.
|
||||
|
||||
libimcv.plugins.imc-swid.swid_full = no
|
||||
Include file information in the XML-encoded SWID tags.
|
||||
@@ -1,5 +0,0 @@
|
||||
libimcv.plugins.imv-swid.rest_api_uri =
|
||||
HTTP URI of the SWID REST API.
|
||||
|
||||
libimcv.plugins.imv-swid.rest_api_timeout = 120
|
||||
Timeout of SWID REST API HTTP POST transaction.
|
||||
+3
-9
@@ -245,8 +245,6 @@ ARG_ENABL_SET([imc-os], [enable IMC operating system module.])
|
||||
ARG_ENABL_SET([imv-os], [enable IMV operating system module.])
|
||||
ARG_ENABL_SET([imc-attestation],[enable IMC attestation module.])
|
||||
ARG_ENABL_SET([imv-attestation],[enable IMV attestation module.])
|
||||
ARG_ENABL_SET([imc-swid], [enable IMC swid module.])
|
||||
ARG_ENABL_SET([imv-swid], [enable IMV swid module.])
|
||||
ARG_ENABL_SET([imc-swima], [enable IMC swima module.])
|
||||
ARG_ENABL_SET([imv-swima], [enable IMV swima module.])
|
||||
ARG_ENABL_SET([imc-hcd], [enable IMC hcd module.])
|
||||
@@ -441,7 +439,7 @@ if test x$eap_tls = xtrue -o x$eap_ttls = xtrue -o x$eap_peap = xtrue -o x$tnc_t
|
||||
tls=true;
|
||||
fi
|
||||
|
||||
if test x$imc_test = xtrue -o x$imv_test = xtrue -o x$imc_scanner = xtrue -o x$imv_scanner = xtrue -o x$imc_os = xtrue -o x$imv_os = xtrue -o x$imc_attestation = xtrue -o x$imv_attestation = xtrue -o x$imc_swid = xtrue -o x$imv_swid = xtrue -o x$imc_swima = xtrue -o x$imv_swima = xtrue -o x$imc_hcd = xtrue -o x$imv_hcd = xtrue; then
|
||||
if test x$imc_test = xtrue -o x$imv_test = xtrue -o x$imc_scanner = xtrue -o x$imv_scanner = xtrue -o x$imc_os = xtrue -o x$imv_os = xtrue -o x$imc_attestation = xtrue -o x$imv_attestation = xtrue -o x$imc_swima = xtrue -o x$imv_swima = xtrue -o x$imc_hcd = xtrue -o x$imv_hcd = xtrue; then
|
||||
imcv=true;
|
||||
fi
|
||||
|
||||
@@ -1036,7 +1034,7 @@ if test x$tss_tss2 = xtrue; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$imc_swima = xtrue -o $imv_swima = xtrue -o x$imv_swid = xtrue; then
|
||||
if test x$imc_swima = xtrue -o $imv_swima = xtrue; then
|
||||
PKG_CHECK_MODULES(json, [json-c], [],
|
||||
[PKG_CHECK_MODULES(json, [json])])
|
||||
AC_SUBST(json_CFLAGS)
|
||||
@@ -1660,8 +1658,6 @@ AM_CONDITIONAL(USE_IMC_OS, test x$imc_os = xtrue)
|
||||
AM_CONDITIONAL(USE_IMV_OS, test x$imv_os = xtrue)
|
||||
AM_CONDITIONAL(USE_IMC_ATTESTATION, test x$imc_attestation = xtrue)
|
||||
AM_CONDITIONAL(USE_IMV_ATTESTATION, test x$imv_attestation = xtrue)
|
||||
AM_CONDITIONAL(USE_IMC_SWID, test x$imc_swid = xtrue)
|
||||
AM_CONDITIONAL(USE_IMV_SWID, test x$imv_swid = xtrue)
|
||||
AM_CONDITIONAL(USE_IMC_SWIMA, test x$imc_swima = xtrue)
|
||||
AM_CONDITIONAL(USE_IMV_SWIMA, test x$imv_swima = xtrue)
|
||||
AM_CONDITIONAL(USE_IMC_HCD, test x$imc_hcd = xtrue)
|
||||
@@ -1766,7 +1762,7 @@ fi
|
||||
if test x$fuzzing = xtrue; then
|
||||
AC_DEFINE([USE_FUZZING], [], [build code for fuzzing])
|
||||
fi
|
||||
if test x$imc_swima = xtrue -o x$imv_swima = xtrue -o x$imv_swid = xtrue ; then
|
||||
if test x$imc_swima = xtrue -o x$imv_swima = xtrue; then
|
||||
AC_DEFINE([USE_JSON], [], [build code for JSON])
|
||||
fi
|
||||
|
||||
@@ -1893,8 +1889,6 @@ AC_CONFIG_FILES([
|
||||
src/libimcv/plugins/imv_os/Makefile
|
||||
src/libimcv/plugins/imc_attestation/Makefile
|
||||
src/libimcv/plugins/imv_attestation/Makefile
|
||||
src/libimcv/plugins/imc_swid/Makefile
|
||||
src/libimcv/plugins/imv_swid/Makefile
|
||||
src/libimcv/plugins/imc_swima/Makefile
|
||||
src/libimcv/plugins/imv_swima/Makefile
|
||||
src/libimcv/plugins/imc_hcd/Makefile
|
||||
|
||||
@@ -75,10 +75,6 @@ libimcv_la_SOURCES := \
|
||||
seg/seg_contract.h seg/seg_contract.c \
|
||||
seg/seg_contract_manager.h seg/seg_contract_manager.c \
|
||||
seg/seg_env.h seg/seg_env.c \
|
||||
swid/swid_error.h swid/swid_error.c \
|
||||
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 \
|
||||
swid_gen/swid_gen_info.h swid_gen/swid_gen_info.c \
|
||||
swima/swima_data_model.h swima/swima_data_model.c \
|
||||
@@ -109,9 +105,6 @@ libimcv_la_SOURCES := \
|
||||
tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
|
||||
tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
|
||||
tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
|
||||
tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
|
||||
tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
|
||||
tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
|
||||
|
||||
LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES))
|
||||
|
||||
|
||||
+1
-16
@@ -96,10 +96,6 @@ libimcv_la_SOURCES = \
|
||||
seg/seg_contract.h seg/seg_contract.c \
|
||||
seg/seg_contract_manager.h seg/seg_contract_manager.c \
|
||||
seg/seg_env.h seg/seg_env.c \
|
||||
swid/swid_error.h swid/swid_error.c \
|
||||
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 \
|
||||
swid_gen/swid_gen_info.h swid_gen/swid_gen_info.c \
|
||||
swima/swima_data_model.h swima/swima_data_model.c \
|
||||
@@ -129,10 +125,7 @@ libimcv_la_SOURCES = \
|
||||
tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
|
||||
tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
|
||||
tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
|
||||
tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
|
||||
tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
|
||||
tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
|
||||
tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
|
||||
tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c
|
||||
|
||||
ipsec_SCRIPTS = imv/_imv_policy
|
||||
EXTRA_DIST = imv/_imv_policy Android.mk
|
||||
@@ -183,14 +176,6 @@ if USE_IMV_ATTESTATION
|
||||
SUBDIRS += plugins/imv_attestation
|
||||
endif
|
||||
|
||||
if USE_IMC_SWID
|
||||
SUBDIRS += plugins/imc_swid
|
||||
endif
|
||||
|
||||
if USE_IMV_SWID
|
||||
SUBDIRS += plugins/imv_swid
|
||||
endif
|
||||
|
||||
if USE_IMC_SWIMA
|
||||
SUBDIRS += plugins/imc_swima
|
||||
endif
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
strongswan.org_*.swidtag
|
||||
@@ -1,36 +0,0 @@
|
||||
regid = strongswan.org
|
||||
unique_sw_id = strongSwan-$(PACKAGE_VERSION_MAJOR)-$(PACKAGE_VERSION_MINOR)-$(PACKAGE_VERSION_BUILD)$(PACKAGE_VERSION_REVIEW)
|
||||
swid_tag = $(regid)__$(unique_sw_id).swidtag
|
||||
|
||||
swiddir = $(pkgdatadir)/swidtag
|
||||
dist_swid_DATA = $(swid_tag)
|
||||
EXTRA_DIST = $(regid)__strongSwan.swidtag.in
|
||||
CLEANFILES = $(regid)__strongSwan*.swidtag
|
||||
|
||||
$(swid_tag) : $(regid)__strongSwan.swidtag.in
|
||||
$(AM_V_GEN) \
|
||||
sed \
|
||||
-e "s:@VERSION_MAJOR@:$(PACKAGE_VERSION_MAJOR):" \
|
||||
-e "s:@VERSION_MINOR@:$(PACKAGE_VERSION_MINOR):" \
|
||||
-e "s:@VERSION_BUILD@:$(PACKAGE_VERSION_BUILD):" \
|
||||
-e "s:@VERSION_REVIEW@:$(PACKAGE_VERSION_REVIEW):" \
|
||||
$(srcdir)/$(regid)__strongSwan.swidtag.in > $@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libimcv \
|
||||
-DSWID_DIRECTORY=\"${prefix}/share\"
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imc-swid.la
|
||||
|
||||
imc_swid_la_LIBADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
|
||||
imc_swid_la_SOURCES = imc_swid.c imc_swid_state.h imc_swid_state.c
|
||||
|
||||
imc_swid_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
@@ -1,417 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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.
|
||||
*/
|
||||
|
||||
#include "imc_swid_state.h"
|
||||
|
||||
#include <imc/imc_agent.h>
|
||||
#include <imc/imc_msg.h>
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/swid/tcg_swid_attr_req.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
#include "swid/swid_error.h"
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
/* IMC definitions */
|
||||
|
||||
static const char imc_name[] = "SWID";
|
||||
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_SWID }
|
||||
};
|
||||
|
||||
static imc_agent_t *imc_swid;
|
||||
|
||||
/**
|
||||
* see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
|
||||
TNC_Version min_version,
|
||||
TNC_Version max_version,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
if (imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
|
||||
return TNC_RESULT_ALREADY_INITIALIZED;
|
||||
}
|
||||
imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
|
||||
imc_id, actual_version);
|
||||
if (!imc_swid)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
|
||||
{
|
||||
DBG1(DBG_IMC, "no common IF-IMC version");
|
||||
return TNC_RESULT_NO_COMMON_VERSION;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
imc_state_t *state;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imc_swid_state_create(connection_id);
|
||||
return imc_swid->create_state(imc_swid, state);
|
||||
case TNC_CONNECTION_STATE_HANDSHAKE:
|
||||
if (imc_swid->change_state(imc_swid, connection_id, new_state,
|
||||
&state) != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
state->set_result(state, imc_id,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
return TNC_RESULT_SUCCESS;
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return imc_swid->delete_state(imc_swid, connection_id);
|
||||
default:
|
||||
return imc_swid->change_state(imc_swid, connection_id,
|
||||
new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *out_msg;
|
||||
pa_tnc_attr_t *attr;
|
||||
seg_contract_t *contract;
|
||||
seg_contract_manager_t *contracts;
|
||||
size_t max_attr_size = SWID_MAX_ATTR_SIZE;
|
||||
size_t max_seg_size;
|
||||
char buf[BUF_LEN];
|
||||
TNC_Result result = TNC_RESULT_SUCCESS;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
|
||||
/* Determine maximum PA-TNC attribute segment size */
|
||||
max_seg_size = state->get_max_msg_len(state) - PA_TNC_HEADER_SIZE
|
||||
- PA_TNC_ATTR_HEADER_SIZE
|
||||
- TCG_SEG_ATTR_SEG_ENV_HEADER;
|
||||
|
||||
/* Announce support of PA-TNC segmentation to IMV */
|
||||
contract = seg_contract_create(msg_types[0], max_attr_size, max_seg_size,
|
||||
TRUE, imc_id, TRUE);
|
||||
contract->get_info_string(contract, buf, BUF_LEN, TRUE);
|
||||
DBG2(DBG_IMC, "%s", buf);
|
||||
contracts = state->get_contracts(state);
|
||||
contracts->add_contract(contracts, contract);
|
||||
attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
|
||||
|
||||
/* send PA-TNC message with the excl flag not set */
|
||||
out_msg = imc_msg_create(imc_swid, state, connection_id, imc_id,
|
||||
TNC_IMVID_ANY, msg_types[0]);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
result = out_msg->send(out_msg, FALSE);
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or multiple SWID Inventory attributes to the send queue
|
||||
*/
|
||||
static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
|
||||
uint32_t request_id, bool full_tags,
|
||||
swid_inventory_t *targets)
|
||||
{
|
||||
pa_tnc_attr_t *attr, *attr_error;
|
||||
imc_swid_state_t *swid_state;
|
||||
swid_inventory_t *swid_inventory;
|
||||
char *swid_directory;
|
||||
uint32_t eid_epoch;
|
||||
bool swid_pretty, swid_full;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
swid_directory = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_directory",
|
||||
SWID_DIRECTORY, lib->ns);
|
||||
swid_pretty = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_pretty",
|
||||
FALSE, lib->ns);
|
||||
swid_full = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_full",
|
||||
FALSE, lib->ns);
|
||||
|
||||
swid_inventory = swid_inventory_create(full_tags);
|
||||
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,
|
||||
0, "error in SWID tag collection");
|
||||
msg->add_attribute(msg, attr_error);
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_IMC, "collected %d SWID tag%s%s",
|
||||
swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID",
|
||||
swid_inventory->get_count(swid_inventory) == 1 ? "" : "s");
|
||||
|
||||
swid_state = (imc_swid_state_t*)state;
|
||||
eid_epoch = swid_state->get_eid_epoch(swid_state);
|
||||
|
||||
if (full_tags)
|
||||
{
|
||||
tcg_swid_attr_tag_inv_t *swid_attr;
|
||||
swid_tag_t *tag;
|
||||
|
||||
/* Send a TCG SWID Tag Inventory attribute */
|
||||
attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
|
||||
swid_attr = (tcg_swid_attr_tag_inv_t*)attr;
|
||||
|
||||
enumerator = swid_inventory->create_enumerator(swid_inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag))
|
||||
{
|
||||
swid_attr->add(swid_attr, tag->get_ref(tag));
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcg_swid_attr_tag_id_inv_t *swid_id_attr;
|
||||
swid_tag_id_t *tag_id;
|
||||
|
||||
/* Send a TCG SWID Tag ID Inventory attribute */
|
||||
attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
|
||||
swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
|
||||
|
||||
enumerator = swid_inventory->create_enumerator(swid_inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
msg->add_attribute(msg, attr);
|
||||
swid_inventory->destroy(swid_inventory);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
|
||||
{
|
||||
imc_msg_t *out_msg;
|
||||
pa_tnc_attr_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
pen_type_t type;
|
||||
TNC_Result result;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imc_msg_create_as_reply(in_msg);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
tcg_swid_attr_req_t *attr_req;
|
||||
uint8_t flags;
|
||||
uint32_t request_id;
|
||||
bool full_tags;
|
||||
swid_inventory_t *targets;
|
||||
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
attr_req = (tcg_swid_attr_req_t*)attr;
|
||||
flags = attr_req->get_flags(attr_req);
|
||||
request_id = attr_req->get_request_id(attr_req);
|
||||
targets = attr_req->get_targets(attr_req);
|
||||
|
||||
if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
|
||||
{
|
||||
attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id,
|
||||
0, "no subscription available yet");
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
}
|
||||
full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
|
||||
|
||||
if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (fatal_error)
|
||||
{
|
||||
result = TNC_RESULT_FATAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
|
||||
|
||||
*/
|
||||
TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_BufferReference msg,
|
||||
TNC_UInt32 msg_len,
|
||||
TNC_MessageType msg_type)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
|
||||
chunk_create(msg, msg_len));
|
||||
result = receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_UInt32 msg_flags,
|
||||
TNC_BufferReference msg,
|
||||
TNC_UInt32 msg_len,
|
||||
TNC_VendorID msg_vid,
|
||||
TNC_MessageSubtype msg_subtype,
|
||||
TNC_UInt32 src_imv_id,
|
||||
TNC_UInt32 dst_imc_id)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
|
||||
src_imv_id, dst_imc_id,msg_vid, msg_subtype,
|
||||
chunk_create(msg, msg_len));
|
||||
result =receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
imc_swid->destroy(imc_swid);
|
||||
imc_swid = NULL;
|
||||
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
|
||||
TNC_TNCC_BindFunctionPointer bind_function)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return imc_swid->bind_functions(imc_swid, bind_function);
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "imc_swid_state.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imc_swid_state_t private_imc_swid_state_t;
|
||||
|
||||
/**
|
||||
* Private data of an imc_swid_state_t object.
|
||||
*/
|
||||
struct private_imc_swid_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imc_swid_state_t
|
||||
*/
|
||||
imc_swid_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Assessment/Evaluation Result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result result;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
uint32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* Event ID Epoch
|
||||
*/
|
||||
uint32_t eid_epoch;
|
||||
};
|
||||
|
||||
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_long, bool,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_excl, bool,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_flags, void,
|
||||
private_imc_swid_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_max_msg_len, void,
|
||||
private_imc_swid_state_t *this, uint32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_max_msg_len, uint32_t,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, change_state, void,
|
||||
private_imc_swid_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_result, void,
|
||||
private_imc_swid_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result result)
|
||||
{
|
||||
this->result = result;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_result, bool,
|
||||
private_imc_swid_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result *result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
*result = this->result;
|
||||
}
|
||||
return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, destroy, void,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imc_swid_state_t, get_eid_epoch, uint32_t,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->eid_epoch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imc_state_t *imc_swid_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imc_swid_state_t *this;
|
||||
uint32_t eid_epoch;
|
||||
nonce_gen_t *ng;
|
||||
|
||||
ng = lib->crypto->create_nonce_gen(lib->crypto);
|
||||
if (!ng || !ng->get_nonce(ng, 4, (uint8_t*)&eid_epoch))
|
||||
{
|
||||
DBG1(DBG_TNC, "failed to generate random EID epoch value");
|
||||
DESTROY_IF(ng);
|
||||
return NULL;
|
||||
}
|
||||
ng->destroy(ng);
|
||||
|
||||
DBG1(DBG_IMC, "creating random EID epoch 0x%08x", eid_epoch);
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.set_result = _set_result,
|
||||
.get_result = _get_result,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_eid_epoch = _get_eid_epoch,
|
||||
},
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.connection_id = connection_id,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.eid_epoch = eid_epoch,
|
||||
);
|
||||
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 imc_swid imc_swid
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imc_swid_state_t imc_swid_state
|
||||
* @{ @ingroup imc_swid
|
||||
*/
|
||||
|
||||
#ifndef IMC_SWID_STATE_H_
|
||||
#define IMC_SWID_STATE_H_
|
||||
|
||||
#include <imc/imc_state.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct imc_swid_state_t imc_swid_state_t;
|
||||
|
||||
/**
|
||||
* Internal state of an imc_swid_t connection instance
|
||||
*/
|
||||
struct imc_swid_state_t {
|
||||
|
||||
/**
|
||||
* imc_state_t interface
|
||||
*/
|
||||
imc_state_t interface;
|
||||
|
||||
/**
|
||||
* Get Event ID Epoch
|
||||
*
|
||||
* @return Event ID Epoch
|
||||
*/
|
||||
uint32_t (*get_eid_epoch)(imc_swid_state_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imc_swid_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imc_state_t* imc_swid_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMC_SWID_STATE_H_ @}*/
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<SoftwareIdentity
|
||||
name="strongSwan"
|
||||
tagId="strongSwan-@VERSION_MAJOR@-@VERSION_MINOR@-@VERSION_BUILD@@VERSION_REVIEW@"
|
||||
version="@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_BUILD@@VERSION_REVIEW@" versionScheme="alphanumeric"
|
||||
xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd">
|
||||
<Entity
|
||||
name="strongSwan Project"
|
||||
regid="strongswan.org"
|
||||
role="softwareCreator licensor tagCreator"/>
|
||||
</SoftwareIdentity>
|
||||
@@ -1,21 +0,0 @@
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libtpmtss \
|
||||
-I$(top_srcdir)/src/libimcv
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS) $(json_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imv-swid.la
|
||||
|
||||
imv_swid_la_LIBADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(json_LIBS)
|
||||
|
||||
imv_swid_la_SOURCES = \
|
||||
imv_swid.c imv_swid_state.h imv_swid_state.c \
|
||||
imv_swid_agent.h imv_swid_agent.c
|
||||
|
||||
imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#include "imv_swid_agent.h"
|
||||
|
||||
static const char imv_name[] = "SWID";
|
||||
static const imv_agent_create_t imv_agent_create = imv_swid_agent_create;
|
||||
|
||||
/* include generic TGC TNC IF-IMV API code below */
|
||||
|
||||
#include <imv/imv_if.h>
|
||||
|
||||
@@ -1,727 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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 "imv_swid_agent.h"
|
||||
#include "imv_swid_state.h"
|
||||
|
||||
#include <imcv.h>
|
||||
#include <imv/imv_agent.h>
|
||||
#include <imv/imv_msg.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
#include "rest/rest.h"
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/swid/tcg_swid_attr_req.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
|
||||
#include "swid/swid_error.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
#include <bio/bio_reader.h>
|
||||
|
||||
typedef struct private_imv_swid_agent_t private_imv_swid_agent_t;
|
||||
|
||||
/* Subscribed PA-TNC message subtypes */
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_SWID }
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag set when corresponding attribute has been received
|
||||
*/
|
||||
enum imv_swid_attr_t {
|
||||
IMV_SWID_ATTR_TAG_INV = (1<<0),
|
||||
IMV_SWID_ATTR_TAG_ID_INV = (1<<1)
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of an imv_swid_agent_t object.
|
||||
*/
|
||||
struct private_imv_swid_agent_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_swid_agent_t
|
||||
*/
|
||||
imv_agent_if_t public;
|
||||
|
||||
/**
|
||||
* IMV agent responsible for generic functions
|
||||
*/
|
||||
imv_agent_t *agent;
|
||||
|
||||
/**
|
||||
* REST API to strongTNC manager
|
||||
*/
|
||||
rest_t *rest_api;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imv_agent_if_t, bind_functions, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
|
||||
{
|
||||
return this->agent->bind_functions(this->agent, bind_function);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
imv_state_t *state;
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imv_swid_state_create(id);
|
||||
return this->agent->create_state(this->agent, state);
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return this->agent->delete_state(this->agent, id);
|
||||
default:
|
||||
return this->agent->change_state(this->agent, id, new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a received message
|
||||
*/
|
||||
static TNC_Result receive_msg(private_imv_swid_agent_t *this,
|
||||
imv_state_t *state, imv_msg_t *in_msg)
|
||||
{
|
||||
imv_swid_state_t *swid_state;
|
||||
imv_msg_t *out_msg;
|
||||
enumerator_t *enumerator;
|
||||
pa_tnc_attr_t *attr;
|
||||
TNC_Result result;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imv_msg_create_as_reply(in_msg);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
swid_state = (imv_swid_state_t*)state;
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
uint32_t request_id = 0, last_eid, eid_epoch;
|
||||
swid_inventory_t *inventory;
|
||||
pen_type_t type;
|
||||
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
|
||||
{
|
||||
ietf_attr_pa_tnc_error_t *error_attr;
|
||||
pen_type_t error_code;
|
||||
chunk_t msg_info, description;
|
||||
bio_reader_t *reader;
|
||||
uint32_t max_attr_size;
|
||||
bool success;
|
||||
|
||||
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
|
||||
error_code = error_attr->get_error_code(error_attr);
|
||||
|
||||
if (error_code.vendor_id == PEN_TCG)
|
||||
{
|
||||
fatal_error = TRUE;
|
||||
msg_info = error_attr->get_msg_info(error_attr);
|
||||
reader = bio_reader_create(msg_info);
|
||||
success = reader->read_uint32(reader, &request_id);
|
||||
|
||||
DBG1(DBG_IMV, "received TCG error '%N' for request %d",
|
||||
swid_error_code_names, error_code.type, request_id);
|
||||
if (!success)
|
||||
{
|
||||
reader->destroy(reader);
|
||||
continue;
|
||||
}
|
||||
if (error_code.type == TCG_SWID_RESPONSE_TOO_LARGE)
|
||||
{
|
||||
if (!reader->read_uint32(reader, &max_attr_size))
|
||||
{
|
||||
reader->destroy(reader);
|
||||
continue;
|
||||
}
|
||||
DBG1(DBG_IMV, " maximum PA-TNC attribute size is %u bytes",
|
||||
max_attr_size);
|
||||
}
|
||||
description = reader->peek(reader);
|
||||
if (description.len)
|
||||
{
|
||||
DBG1(DBG_IMV, " description: %.*s", description.len,
|
||||
description.ptr);
|
||||
}
|
||||
reader->destroy(reader);
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id != PEN_TCG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type.type)
|
||||
{
|
||||
case TCG_SWID_TAG_ID_INVENTORY:
|
||||
{
|
||||
tcg_swid_attr_tag_id_inv_t *attr_cast;
|
||||
uint32_t missing;
|
||||
int tag_id_count;
|
||||
|
||||
state->set_action_flags(state, IMV_SWID_ATTR_TAG_ID_INV);
|
||||
|
||||
attr_cast = (tcg_swid_attr_tag_id_inv_t*)attr;
|
||||
request_id = attr_cast->get_request_id(attr_cast);
|
||||
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
|
||||
inventory = attr_cast->get_inventory(attr_cast);
|
||||
tag_id_count = inventory->get_count(inventory);
|
||||
missing = attr_cast->get_tag_id_count(attr_cast);
|
||||
swid_state->set_missing(swid_state, missing);
|
||||
|
||||
DBG2(DBG_IMV, "received SWID tag ID inventory with %d item%s "
|
||||
"for request %d at eid %d of epoch 0x%08x, %d item%s to "
|
||||
"follow", tag_id_count, (tag_id_count == 1) ? "" : "s",
|
||||
request_id, last_eid, eid_epoch, missing,
|
||||
(missing == 1) ? "" : "s");
|
||||
|
||||
if (request_id == swid_state->get_request_id(swid_state))
|
||||
{
|
||||
swid_state->set_swid_inventory(swid_state, inventory);
|
||||
swid_state->set_count(swid_state, tag_id_count, 0,
|
||||
in_msg->get_src_id(in_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
|
||||
"with request ID %d", request_id);
|
||||
}
|
||||
attr_cast->clear_inventory(attr_cast);
|
||||
break;
|
||||
}
|
||||
case TCG_SWID_TAG_INVENTORY:
|
||||
{
|
||||
tcg_swid_attr_tag_inv_t *attr_cast;
|
||||
swid_tag_t *tag;
|
||||
chunk_t tag_encoding;
|
||||
json_object *jobj, *jarray, *jstring;
|
||||
char *tag_str;
|
||||
uint32_t missing;
|
||||
int tag_count;
|
||||
enumerator_t *e;
|
||||
|
||||
state->set_action_flags(state, IMV_SWID_ATTR_TAG_INV);
|
||||
|
||||
attr_cast = (tcg_swid_attr_tag_inv_t*)attr;
|
||||
request_id = attr_cast->get_request_id(attr_cast);
|
||||
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
|
||||
inventory = attr_cast->get_inventory(attr_cast);
|
||||
tag_count = inventory->get_count(inventory);
|
||||
missing = attr_cast->get_tag_count(attr_cast);
|
||||
swid_state->set_missing(swid_state, missing);
|
||||
|
||||
DBG2(DBG_IMV, "received SWID tag inventory with %d item%s for "
|
||||
"request %d at eid %d of epoch 0x%08x, %d item%s to follow",
|
||||
tag_count, (tag_count == 1) ? "" : "s", request_id,
|
||||
last_eid, eid_epoch, missing, (missing == 1) ? "" : "s");
|
||||
|
||||
if (request_id == swid_state->get_request_id(swid_state))
|
||||
{
|
||||
swid_state->set_count(swid_state, 0, tag_count,
|
||||
in_msg->get_src_id(in_msg));
|
||||
|
||||
if (this->rest_api)
|
||||
{
|
||||
jobj = json_object_new_object();
|
||||
jarray = json_object_new_array();
|
||||
json_object_object_add(jobj, "data", jarray);
|
||||
|
||||
e = inventory->create_enumerator(inventory);
|
||||
while (e->enumerate(e, &tag))
|
||||
{
|
||||
tag_encoding = tag->get_encoding(tag);
|
||||
tag_str = strndup(tag_encoding.ptr, tag_encoding.len);
|
||||
DBG3(DBG_IMV, "%s", tag_str);
|
||||
jstring = json_object_new_string(tag_str);
|
||||
json_object_array_add(jarray, jstring);
|
||||
free(tag_str);
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
if (this->rest_api->post(this->rest_api,
|
||||
"swid/add-tags/", jobj, NULL) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IMV, "error in REST API add-tags request");
|
||||
}
|
||||
json_object_put(jobj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
|
||||
"with request ID %d", request_id);
|
||||
}
|
||||
attr_cast->clear_inventory(attr_cast);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (fatal_error)
|
||||
{
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
TNC_IMV_EVALUATION_RESULT_ERROR);
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
if (result == TNC_RESULT_SUCCESS)
|
||||
{
|
||||
result = this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_MessageType msg_type, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
|
||||
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_long_data(this->agent, state, id,
|
||||
src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, batch_ending, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
imv_msg_t *out_msg;
|
||||
imv_state_t *state;
|
||||
imv_session_t *session;
|
||||
imv_workitem_t *workitem;
|
||||
imv_swid_state_t *swid_state;
|
||||
imv_swid_handshake_state_t handshake_state;
|
||||
pa_tnc_attr_t *attr;
|
||||
TNC_IMVID imv_id;
|
||||
TNC_Result result = TNC_RESULT_SUCCESS;
|
||||
bool no_workitems = TRUE;
|
||||
uint32_t request_id, received;
|
||||
uint8_t flags;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
swid_state = (imv_swid_state_t*)state;
|
||||
handshake_state = swid_state->get_handshake_state(swid_state);
|
||||
session = state->get_session(state);
|
||||
imv_id = this->agent->get_id(this->agent);
|
||||
|
||||
if (handshake_state == IMV_SWID_STATE_END)
|
||||
{
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Create an empty out message - we might need it */
|
||||
out_msg = imv_msg_create(this->agent, state, id, imv_id,
|
||||
swid_state->get_imc_id(swid_state),
|
||||
msg_types[0]);
|
||||
|
||||
if (!imcv_db)
|
||||
{
|
||||
DBG2(DBG_IMV, "no workitems available - no evaluation possible");
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
out_msg->destroy(out_msg);
|
||||
swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
/* Look for SWID tag workitem and create SWID tag request */
|
||||
if (handshake_state == IMV_SWID_STATE_INIT &&
|
||||
session->get_policy_started(session))
|
||||
{
|
||||
size_t max_attr_size = SWID_MAX_ATTR_SIZE;
|
||||
size_t max_seg_size;
|
||||
seg_contract_t *contract;
|
||||
seg_contract_manager_t *contracts;
|
||||
char buf[BUF_LEN];
|
||||
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
if (enumerator)
|
||||
{
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY ||
|
||||
workitem->get_type(workitem) != IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = TCG_SWID_ATTR_REQ_FLAG_NONE;
|
||||
if (strchr(workitem->get_arg_str(workitem), 'R'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_R;
|
||||
}
|
||||
if (strchr(workitem->get_arg_str(workitem), 'S'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_S;
|
||||
}
|
||||
if (strchr(workitem->get_arg_str(workitem), 'C'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_C;
|
||||
}
|
||||
|
||||
/* Determine maximum PA-TNC attribute segment size */
|
||||
max_seg_size = state->get_max_msg_len(state)
|
||||
- PA_TNC_HEADER_SIZE
|
||||
- PA_TNC_ATTR_HEADER_SIZE
|
||||
- TCG_SEG_ATTR_SEG_ENV_HEADER;
|
||||
|
||||
/* Announce support of PA-TNC segmentation to IMC */
|
||||
contract = seg_contract_create(msg_types[0], max_attr_size,
|
||||
max_seg_size, TRUE, imv_id, FALSE);
|
||||
contract->get_info_string(contract, buf, BUF_LEN, TRUE);
|
||||
DBG2(DBG_IMV, "%s", buf);
|
||||
contracts = state->get_contracts(state);
|
||||
contracts->add_contract(contracts, contract);
|
||||
attr = tcg_seg_attr_max_size_create(max_attr_size,
|
||||
max_seg_size, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Issue a SWID request */
|
||||
request_id = workitem->get_id(workitem);
|
||||
swid_state->set_request_id(swid_state, request_id);
|
||||
attr = tcg_swid_attr_req_create(flags, request_id, 0);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
workitem->set_imv_id(workitem, imv_id);
|
||||
no_workitems = FALSE;
|
||||
DBG2(DBG_IMV, "IMV %d issues SWID request %d",
|
||||
imv_id, request_id);
|
||||
break;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (no_workitems)
|
||||
{
|
||||
DBG2(DBG_IMV, "IMV %d has no workitems - "
|
||||
"no evaluation requested", imv_id);
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
}
|
||||
handshake_state = IMV_SWID_STATE_WORKITEMS;
|
||||
swid_state->set_handshake_state(swid_state, handshake_state);
|
||||
}
|
||||
}
|
||||
|
||||
received = state->get_action_flags(state);
|
||||
|
||||
if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
|
||||
(received & (IMV_SWID_ATTR_TAG_INV|IMV_SWID_ATTR_TAG_ID_INV)) &&
|
||||
swid_state->get_missing(swid_state) == 0)
|
||||
{
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
char result_str[BUF_LEN], *error_str = "", *command;
|
||||
char *target, *separator;
|
||||
int tag_id_count, tag_count, i;
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
json_object *jrequest, *jresponse, *jvalue;
|
||||
tcg_swid_attr_req_t *cast_attr;
|
||||
swid_tag_id_t *tag_id;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
if (this->rest_api && (received & IMV_SWID_ATTR_TAG_ID_INV))
|
||||
{
|
||||
if (asprintf(&command, "sessions/%d/swid-measurement/",
|
||||
session->get_session_id(session, NULL, NULL)) < 0)
|
||||
{
|
||||
error_str = "allocation of command string failed";
|
||||
status = FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
jrequest = swid_state->get_swid_inventory(swid_state);
|
||||
status = this->rest_api->post(this->rest_api, command,
|
||||
jrequest, &jresponse);
|
||||
if (status == FAILED)
|
||||
{
|
||||
error_str = "error in REST API swid-measurement request";
|
||||
}
|
||||
free(command);
|
||||
}
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
swid_state->get_count(swid_state, &tag_id_count,
|
||||
&tag_count);
|
||||
snprintf(result_str, BUF_LEN, "received inventory of "
|
||||
"%d SWID tag ID%s and %d SWID tag%s",
|
||||
tag_id_count, (tag_id_count == 1) ? "" : "s",
|
||||
tag_count, (tag_count == 1) ? "" : "s");
|
||||
session->remove_workitem(session, enumerator);
|
||||
|
||||
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
if (received & IMV_SWID_ATTR_TAG_INV)
|
||||
{
|
||||
error_str = "not all requested SWID tags were received";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
if (json_object_get_type(jresponse) != json_type_array)
|
||||
{
|
||||
error_str = "response was not a json_array";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create a TCG SWID Request attribute */
|
||||
attr = tcg_swid_attr_req_create(TCG_SWID_ATTR_REQ_FLAG_NONE,
|
||||
swid_state->get_request_id(swid_state), 0);
|
||||
tag_id_count = json_object_array_length(jresponse);
|
||||
DBG1(DBG_IMV, "%d SWID tag target%s", tag_id_count,
|
||||
(tag_id_count == 1) ? "" : "s");
|
||||
swid_state->set_missing(swid_state, tag_id_count);
|
||||
|
||||
for (i = 0; i < tag_id_count; i++)
|
||||
{
|
||||
jvalue = json_object_array_get_idx(jresponse, i);
|
||||
if (json_object_get_type(jvalue) != json_type_string)
|
||||
{
|
||||
error_str = "json_string element expected in json_array";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
target = (char*)json_object_get_string(jvalue);
|
||||
DBG1(DBG_IMV, " %s", target);
|
||||
|
||||
/* Separate target into tag_creator and unique_sw_id */
|
||||
separator = strstr(target, "__");
|
||||
if (!separator)
|
||||
{
|
||||
error_str = "separation of regid from "
|
||||
"unique software ID failed";
|
||||
break;
|
||||
}
|
||||
tag_creator = chunk_create(target, separator - target);
|
||||
separator += 2;
|
||||
unique_sw_id = chunk_create(separator, strlen(target) -
|
||||
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;
|
||||
cast_attr->add_target(cast_attr, tag_id);
|
||||
}
|
||||
json_object_put(jresponse);
|
||||
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == FAILED)
|
||||
{
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
session->remove_workitem(session, enumerator);
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
rec = workitem->set_result(workitem, error_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
/* finalized all workitems ? */
|
||||
if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
|
||||
session->get_workitem_count(session, imv_id) == 0)
|
||||
{
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
out_msg->destroy(out_msg);
|
||||
swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
/* send non-empty PA-TNC message with excl flag not set */
|
||||
if (out_msg->get_attribute_count(out_msg))
|
||||
{
|
||||
result = out_msg->send(out_msg, FALSE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
imv_state_t *state;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, destroy, void,
|
||||
private_imv_swid_agent_t *this)
|
||||
{
|
||||
DESTROY_IF(this->rest_api);
|
||||
this->agent->destroy(this->agent);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
private_imv_swid_agent_t *this;
|
||||
imv_agent_t *agent;
|
||||
char *rest_api_uri;
|
||||
u_int rest_api_timeout;
|
||||
|
||||
agent = imv_agent_create(name, msg_types, countof(msg_types), id,
|
||||
actual_version);
|
||||
if (!agent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
agent->add_non_fatal_attr_type(agent,
|
||||
pen_type_create(PEN_TCG, TCG_SEG_MAX_ATTR_SIZE_REQ));
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.bind_functions = _bind_functions,
|
||||
.notify_connection_change = _notify_connection_change,
|
||||
.receive_message = _receive_message,
|
||||
.receive_message_long = _receive_message_long,
|
||||
.batch_ending = _batch_ending,
|
||||
.solicit_recommendation = _solicit_recommendation,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.agent = agent,
|
||||
);
|
||||
|
||||
rest_api_uri = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imv-swid.rest_api_uri", NULL, lib->ns);
|
||||
rest_api_timeout = lib->settings->get_int(lib->settings,
|
||||
"%s.plugins.imv-swid.rest_api_timeout", 120, lib->ns);
|
||||
if (rest_api_uri)
|
||||
{
|
||||
this->rest_api = rest_create(rest_api_uri, rest_api_timeout);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 imv_swid_agent_t imv_swid_agent
|
||||
* @{ @ingroup imv_swid
|
||||
*/
|
||||
|
||||
#ifndef IMV_SWID_AGENT_H_
|
||||
#define IMV_SWID_AGENT_H_
|
||||
|
||||
#include <imv/imv_agent_if.h>
|
||||
|
||||
/**
|
||||
* Creates an SWID IMV agent
|
||||
*
|
||||
* @param name Name of the IMV
|
||||
* @param id ID of the IMV
|
||||
* @param actual_version TNC IF-IMV version
|
||||
*/
|
||||
imv_agent_if_t* imv_swid_agent_create(const char* name, TNC_IMVID id,
|
||||
TNC_Version *actual_version);
|
||||
|
||||
#endif /** IMV_SWID_AGENT_H_ @}*/
|
||||
@@ -1,417 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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.
|
||||
*/
|
||||
|
||||
#include "imv_swid_state.h"
|
||||
|
||||
#include <imv/imv_lang_string.h>
|
||||
#include <imv/imv_reason_string.h>
|
||||
#include <imv/imv_remediation_string.h>
|
||||
#include <swid/swid_tag_id.h>
|
||||
|
||||
#include <tncif_policy.h>
|
||||
|
||||
#include <utils/lexparser.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imv_swid_state_t private_imv_swid_state_t;
|
||||
|
||||
/**
|
||||
* Private data of an imv_swid_state_t object.
|
||||
*/
|
||||
struct private_imv_swid_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_swid_state_t
|
||||
*/
|
||||
imv_swid_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
uint32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* Flags set for completed actions
|
||||
*/
|
||||
uint32_t action_flags;
|
||||
|
||||
/**
|
||||
* IMV database session associated with TNCCS connection
|
||||
*/
|
||||
imv_session_t *session;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* IMV action recommendation
|
||||
*/
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
|
||||
/**
|
||||
* IMV evaluation result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
|
||||
/**
|
||||
* IMV Scanner handshake state
|
||||
*/
|
||||
imv_swid_handshake_state_t handshake_state;
|
||||
|
||||
/**
|
||||
* TNC Reason String
|
||||
*/
|
||||
imv_reason_string_t *reason_string;
|
||||
|
||||
/**
|
||||
* IETF Remediation Instructions String
|
||||
*/
|
||||
imv_remediation_string_t *remediation_string;
|
||||
|
||||
/**
|
||||
* SWID Tag Request ID
|
||||
*/
|
||||
uint32_t request_id;
|
||||
|
||||
/**
|
||||
* Number of processed SWID Tag IDs
|
||||
*/
|
||||
int tag_id_count;
|
||||
|
||||
/**
|
||||
* Number of processed SWID Tags
|
||||
*/
|
||||
int tag_count;
|
||||
|
||||
/**
|
||||
* Number of missing SWID Tags or Tag IDs
|
||||
*/
|
||||
uint32_t missing;
|
||||
|
||||
/**
|
||||
* SWID IMC ID
|
||||
*/
|
||||
TNC_UInt32 imc_id;
|
||||
|
||||
/**
|
||||
* Top level JSON object
|
||||
*/
|
||||
json_object *jobj;
|
||||
|
||||
/**
|
||||
* JSON array containing an inventory of SWID Tag IDs
|
||||
*/
|
||||
json_object *jarray;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_long, bool,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_excl, bool,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_flags, void,
|
||||
private_imv_swid_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_max_msg_len, void,
|
||||
private_imv_swid_state_t *this, uint32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_max_msg_len, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_action_flags, void,
|
||||
private_imv_swid_state_t *this, uint32_t flags)
|
||||
{
|
||||
this->action_flags |= flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_action_flags, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->action_flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_session, void,
|
||||
private_imv_swid_state_t *this, imv_session_t *session)
|
||||
{
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_session, imv_session_t*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, change_state, void,
|
||||
private_imv_swid_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation *rec,
|
||||
TNC_IMV_Evaluation_Result *eval)
|
||||
{
|
||||
*rec = this->rec;
|
||||
*eval = this->eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = rec;
|
||||
this->eval = eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, update_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = tncif_policy_update_recommendation(this->rec, rec);
|
||||
this->eval = tncif_policy_update_evaluation(this->eval, eval);
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_reason_string, bool,
|
||||
private_imv_swid_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *reason_string, char **reason_language)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_remediation_instructions, bool,
|
||||
private_imv_swid_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *string, char **lang_code, char **uri)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, destroy, void,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
json_object_put(this->jobj);
|
||||
DESTROY_IF(this->session);
|
||||
DESTROY_IF(this->reason_string);
|
||||
DESTROY_IF(this->remediation_string);
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_handshake_state, void,
|
||||
private_imv_swid_state_t *this, imv_swid_handshake_state_t new_state)
|
||||
{
|
||||
this->handshake_state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->handshake_state;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_request_id, void,
|
||||
private_imv_swid_state_t *this, uint32_t request_id)
|
||||
{
|
||||
this->request_id = request_id;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_request_id, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_swid_inventory, void,
|
||||
private_imv_swid_state_t *this, swid_inventory_t *inventory)
|
||||
{
|
||||
chunk_t tag_creator, sw_id;
|
||||
char software_id[BUF_LEN];
|
||||
json_object *jstring;
|
||||
swid_tag_id_t *tag_id;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = inventory->create_enumerator(inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
/* Construct software ID from tag creator and unique software ID */
|
||||
tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
snprintf(software_id, BUF_LEN, "%.*s__%.*s",
|
||||
(int)tag_creator.len, tag_creator.ptr,
|
||||
(int)sw_id.len, sw_id.ptr);
|
||||
DBG3(DBG_IMV, " %s", software_id);
|
||||
|
||||
/* Add software ID to JSON array */
|
||||
jstring = json_object_new_string(software_id);
|
||||
json_object_array_add(this->jarray, jstring);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_swid_inventory, json_object*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->jobj;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_missing, void,
|
||||
private_imv_swid_state_t *this, uint32_t count)
|
||||
{
|
||||
this->missing = count;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_missing, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->missing;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_count, void,
|
||||
private_imv_swid_state_t *this, int tag_id_count, int tag_count,
|
||||
TNC_UInt32 imc_id)
|
||||
{
|
||||
this->tag_id_count += tag_id_count;
|
||||
this->tag_count += tag_count;
|
||||
this->imc_id = imc_id;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_count, void,
|
||||
private_imv_swid_state_t *this, int *tag_id_count, int *tag_count)
|
||||
{
|
||||
if (tag_id_count)
|
||||
{
|
||||
*tag_id_count = this->tag_id_count;
|
||||
}
|
||||
if (tag_count)
|
||||
{
|
||||
*tag_count = this->tag_count;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_imc_id, TNC_UInt32,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->imc_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imv_swid_state_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.set_action_flags = _set_action_flags,
|
||||
.get_action_flags = _get_action_flags,
|
||||
.set_session = _set_session,
|
||||
.get_session= _get_session,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.get_recommendation = _get_recommendation,
|
||||
.set_recommendation = _set_recommendation,
|
||||
.update_recommendation = _update_recommendation,
|
||||
.get_reason_string = _get_reason_string,
|
||||
.get_remediation_instructions = _get_remediation_instructions,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.set_handshake_state = _set_handshake_state,
|
||||
.get_handshake_state = _get_handshake_state,
|
||||
.set_request_id = _set_request_id,
|
||||
.get_request_id = _get_request_id,
|
||||
.set_swid_inventory = _set_swid_inventory,
|
||||
.get_swid_inventory = _get_swid_inventory,
|
||||
.set_missing = _set_missing,
|
||||
.get_missing = _get_missing,
|
||||
.set_count = _set_count,
|
||||
.get_count = _get_count,
|
||||
.get_imc_id = _get_imc_id,
|
||||
},
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.connection_id = connection_id,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.imc_id = TNC_IMCID_ANY,
|
||||
.jobj = json_object_new_object(),
|
||||
.jarray = json_object_new_array(),
|
||||
);
|
||||
|
||||
json_object_object_add(this->jobj, "data", this->jarray);
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2016 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 imv_swid imv_swid
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imv_swid_state_t imv_swid_state
|
||||
* @{ @ingroup imv_swid
|
||||
*/
|
||||
|
||||
#ifndef IMV_SWID_STATE_H_
|
||||
#define IMV_SWID_STATE_H_
|
||||
|
||||
#include <imv/imv_state.h>
|
||||
#include <swid/swid_inventory.h>
|
||||
#include <library.h>
|
||||
|
||||
#include <json.h>
|
||||
|
||||
typedef struct imv_swid_state_t imv_swid_state_t;
|
||||
typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
|
||||
|
||||
/**
|
||||
* IMV OS Handshake States (state machine)
|
||||
*/
|
||||
enum imv_swid_handshake_state_t {
|
||||
IMV_SWID_STATE_INIT,
|
||||
IMV_SWID_STATE_WORKITEMS,
|
||||
IMV_SWID_STATE_END
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal state of an imv_swid_t connection instance
|
||||
*/
|
||||
struct imv_swid_state_t {
|
||||
|
||||
/**
|
||||
* imv_state_t interface
|
||||
*/
|
||||
imv_state_t interface;
|
||||
|
||||
/**
|
||||
* Set state of the handshake
|
||||
*
|
||||
* @param new_state the handshake state of IMV
|
||||
*/
|
||||
void (*set_handshake_state)(imv_swid_state_t *this,
|
||||
imv_swid_handshake_state_t new_state);
|
||||
|
||||
/**
|
||||
* Get state of the handshake
|
||||
*
|
||||
* @return the handshake state of IMV
|
||||
*/
|
||||
imv_swid_handshake_state_t (*get_handshake_state)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set the SWID request ID
|
||||
*
|
||||
* @param request_id SWID request ID to be set
|
||||
*/
|
||||
void (*set_request_id)(imv_swid_state_t *this, uint32_t request_id);
|
||||
|
||||
/**
|
||||
* Get the SWID request ID
|
||||
*
|
||||
* @return SWID request ID
|
||||
*/
|
||||
uint32_t (*get_request_id)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set or extend the SWID Tag ID inventory in the state
|
||||
*
|
||||
* @param inventory SWID Tags ID inventory to be added
|
||||
*/
|
||||
void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
|
||||
|
||||
/**
|
||||
* Get the encoding of the complete SWID Tag ID inventory
|
||||
*
|
||||
* @return SWID Tags ID inventory as a JSON array
|
||||
*/
|
||||
json_object* (*get_swid_inventory)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set the number of still missing SWID Tags or Tag IDs
|
||||
*
|
||||
* @param count Number of missing SWID Tags or Tag IDs
|
||||
*/
|
||||
void (*set_missing)(imv_swid_state_t *this, uint32_t count);
|
||||
|
||||
/**
|
||||
* Get the number of still missing SWID Tags or Tag IDs
|
||||
*
|
||||
* @result Number of missing SWID Tags or Tag IDs
|
||||
*/
|
||||
uint32_t (*get_missing)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set [or with multiple attributes increment] SWID Tag [ID] counters
|
||||
*
|
||||
* @param tag_id_count Number of received SWID Tag IDs
|
||||
* @param tag_count Number of received SWID Tags
|
||||
* @param imc_id SWID IMC ID
|
||||
*/
|
||||
void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count,
|
||||
TNC_UInt32 imc_id);
|
||||
|
||||
/**
|
||||
* Set [or with multiple attributes increment] SWID Tag [ID] counters
|
||||
*
|
||||
* @param tag_id_count Number of received SWID Tag IDs
|
||||
* @param tag_count Number of received SWID Tags
|
||||
*/
|
||||
void (*get_count)(imv_swid_state_t *this, int *tag_id_count, int *tag_count);
|
||||
|
||||
/**
|
||||
* Get SWID IMC ID
|
||||
*
|
||||
* @return SWID IMC ID
|
||||
*/
|
||||
TNC_UInt32 (*get_imc_id)(imv_swid_state_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imv_swid_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imv_state_t* imv_swid_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMV_SWID_STATE_H_ @}*/
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "swid_error.h"
|
||||
|
||||
#include <bio/bio_writer.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
|
||||
ENUM(swid_error_code_names, TCG_SWID_ERROR, TCG_SWID_RESPONSE_TOO_LARGE,
|
||||
"SWID Error",
|
||||
"SWID Subscription Denied",
|
||||
"SWID Response Too Large"
|
||||
);
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t* swid_error_create(swid_error_code_t code, uint32_t request_id,
|
||||
uint32_t max_attr_size, char *description)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t msg_info;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t error_code;
|
||||
|
||||
error_code = pen_type_create( PEN_TCG, code);
|
||||
writer = bio_writer_create(4);
|
||||
writer->write_uint32(writer, request_id);
|
||||
if (code == TCG_SWID_RESPONSE_TOO_LARGE)
|
||||
{
|
||||
writer->write_uint32(writer, max_attr_size);
|
||||
}
|
||||
if (description)
|
||||
{
|
||||
writer->write_data(writer, chunk_from_str(description));
|
||||
}
|
||||
msg_info = writer->get_buf(writer);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
|
||||
writer->destroy(writer);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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_error swid_error
|
||||
* @{ @ingroup libimcv_swid
|
||||
*/
|
||||
|
||||
#ifndef SWID_ERROR_H_
|
||||
#define SWID_ERROR_H_
|
||||
|
||||
typedef enum swid_error_code_t swid_error_code_t;
|
||||
|
||||
#include "pa_tnc/pa_tnc_attr.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
|
||||
/**
|
||||
* SWID Error Codes
|
||||
* see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum swid_error_code_t {
|
||||
TCG_SWID_ERROR = 0x20,
|
||||
TCG_SWID_SUBSCRIPTION_DENIED = 0x21,
|
||||
TCG_SWID_RESPONSE_TOO_LARGE = 0x22
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for swid_error_code_t.
|
||||
*/
|
||||
extern enum_name_t *swid_error_code_names;
|
||||
|
||||
/**
|
||||
* Creates a SWID Error Attribute
|
||||
* see section 4.12 of TNC SWID Message and Attributes for IF-M
|
||||
*
|
||||
* @param code SWID error code
|
||||
* @param request SWID request ID
|
||||
* @param max_attr_size Maximum IF-M attribute size (if applicable)
|
||||
* @param description Optional description string or NULL
|
||||
*/
|
||||
pa_tnc_attr_t* swid_error_create(swid_error_code_t code, uint32_t request,
|
||||
uint32_t max_attr_size, char *description);
|
||||
|
||||
#endif /** SWID_ERROR_H_ @}*/
|
||||
@@ -1,342 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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.
|
||||
*/
|
||||
|
||||
#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 <utils/lexparser.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct private_swid_inventory_t private_swid_inventory_t;
|
||||
|
||||
/**
|
||||
* Private data of a swid_inventory_t object.
|
||||
*
|
||||
*/
|
||||
struct private_swid_inventory_t {
|
||||
|
||||
/**
|
||||
* Public swid_inventory_t interface.
|
||||
*/
|
||||
swid_inventory_t public;
|
||||
|
||||
/**
|
||||
* Full SWID tags or just SWID tag IDs
|
||||
*/
|
||||
bool full_tags;
|
||||
|
||||
/**
|
||||
* List of SWID tags or tag IDs
|
||||
*/
|
||||
linked_list_t *list;
|
||||
};
|
||||
|
||||
static status_t generate_tags(private_swid_inventory_t *this,
|
||||
swid_inventory_t *targets, bool pretty, bool full)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
status = NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
else if (this->full_tags)
|
||||
{
|
||||
DBG2(DBG_IMC, "targeted SWID tag generation");
|
||||
|
||||
enumerator = targets->create_enumerator(targets);
|
||||
while (enumerator->enumerate(enumerator, &tag_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);
|
||||
sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
snprintf(software_id, BUF_LEN, "%.*s__%.*s",
|
||||
(int)tag_creator.len, tag_creator.ptr,
|
||||
(int)sw_id.len, sw_id.ptr);
|
||||
|
||||
swid_tag = swid_gen->generate_tag(swid_gen, software_id, NULL, NULL,
|
||||
full, pretty);
|
||||
if (swid_tag)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static bool collect_tags(private_swid_inventory_t *this, char *pathname,
|
||||
swid_inventory_t *targets, bool is_swidtag_dir)
|
||||
{
|
||||
char *rel_name, *abs_name;
|
||||
struct stat st;
|
||||
bool success = FALSE;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = enumerator_create_directory(pathname);
|
||||
if (!enumerator)
|
||||
{
|
||||
DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
|
||||
pathname, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
if (is_swidtag_dir)
|
||||
{
|
||||
DBG2(DBG_IMC, "entering %s", pathname);
|
||||
}
|
||||
|
||||
while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
|
||||
{
|
||||
char *separator, *suffix;
|
||||
chunk_t tag_creator;
|
||||
chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
if (!collect_tags(this, abs_name, targets, is_swidtag_dir ||
|
||||
streq(rel_name, "swidtag")))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!is_swidtag_dir)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* found a swidtag file? */
|
||||
suffix = strstr(rel_name, ".swidtag");
|
||||
if (!suffix)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse the swidtag filename into its components */
|
||||
separator = strstr(rel_name, "__");
|
||||
if (!separator)
|
||||
{
|
||||
DBG1(DBG_IMC, " %s", rel_name);
|
||||
DBG1(DBG_IMC, " '__' separator not found");
|
||||
goto end;
|
||||
}
|
||||
tag_creator = chunk_create(rel_name, separator-rel_name);
|
||||
|
||||
unique_sw_id = chunk_create(separator+2, suffix-separator-2);
|
||||
tag_file_path = chunk_from_str(abs_name);
|
||||
|
||||
/* In case of a targeted request */
|
||||
if (targets->get_count(targets))
|
||||
{
|
||||
chunk_t target_unique_sw_id, target_tag_creator;
|
||||
enumerator_t *target_enumerator;
|
||||
swid_tag_id_t *tag_id;
|
||||
bool match = FALSE;
|
||||
|
||||
target_enumerator = targets->create_enumerator(targets);
|
||||
while (target_enumerator->enumerate(target_enumerator, &tag_id))
|
||||
{
|
||||
target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
target_tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
|
||||
if (chunk_equals(target_unique_sw_id, unique_sw_id) &&
|
||||
chunk_equals(target_tag_creator, tag_creator))
|
||||
{
|
||||
match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
target_enumerator->destroy(target_enumerator);
|
||||
|
||||
if (!match)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
DBG2(DBG_IMC, " %s", rel_name);
|
||||
|
||||
if (this->full_tags)
|
||||
{
|
||||
swid_tag_t *tag;
|
||||
chunk_t *xml_tag;
|
||||
|
||||
xml_tag = chunk_map(abs_name, FALSE);
|
||||
if (!xml_tag)
|
||||
{
|
||||
DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
|
||||
strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
tag = swid_tag_create(*xml_tag, tag_file_path);
|
||||
this->list->insert_last(this->list, tag);
|
||||
chunk_unmap(xml_tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
swid_tag_id_t *tag_id;
|
||||
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
|
||||
this->list->insert_last(this->list, tag_id);
|
||||
}
|
||||
}
|
||||
success = TRUE;
|
||||
|
||||
end:
|
||||
enumerator->destroy(enumerator);
|
||||
if (is_swidtag_dir)
|
||||
{
|
||||
DBG2(DBG_IMC, "leaving %s", pathname);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, collect, bool,
|
||||
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, targets, pretty, full);
|
||||
|
||||
/**
|
||||
* Collect swidtag files by iteratively entering all directories in
|
||||
* the tree under the "directory" path.
|
||||
*/
|
||||
return collect_tags(this, directory, targets, FALSE);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, add, void,
|
||||
private_swid_inventory_t *this, void *item)
|
||||
{
|
||||
this->list->insert_last(this->list, item);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, get_count, int,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
return this->list->create_enumerator(this->list);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, destroy, void,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
if (this->full_tags)
|
||||
{
|
||||
this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
swid_inventory_t *swid_inventory_create(bool full_tags)
|
||||
{
|
||||
private_swid_inventory_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.collect = _collect,
|
||||
.add = _add,
|
||||
.get_count = _get_count,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.full_tags = full_tags,
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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_inventory swid_inventory
|
||||
* @{ @ingroup libimcv_swid
|
||||
*/
|
||||
|
||||
#ifndef SWID_INVENTORY_H_
|
||||
#define SWID_INVENTORY_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/* Maximum size of a SWID Tag Inventory: 100 MB */
|
||||
#define SWID_MAX_ATTR_SIZE 100000000
|
||||
|
||||
typedef struct swid_inventory_t swid_inventory_t;
|
||||
|
||||
/**
|
||||
* Class managing SWID tag inventory
|
||||
*/
|
||||
struct swid_inventory_t {
|
||||
|
||||
/**
|
||||
* Collect the SWID tags stored on the endpoint
|
||||
*
|
||||
* @param directory SWID directory path
|
||||
* @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,
|
||||
swid_inventory_t *targets, bool pretty, bool full);
|
||||
|
||||
/**
|
||||
* Collect the SWID tags stored on the endpoint
|
||||
*
|
||||
* @param item SWID tag or tag ID to be added
|
||||
*/
|
||||
void (*add)(swid_inventory_t *this, void *item);
|
||||
|
||||
/**
|
||||
* Get the number of collected SWID tags
|
||||
*
|
||||
* @return Number of collected SWID tags
|
||||
*/
|
||||
int (*get_count)(swid_inventory_t *this);
|
||||
|
||||
/**
|
||||
* Create a SWID tag inventory enumerator
|
||||
*
|
||||
* @return Enumerator returning either tag ID or full tag
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(swid_inventory_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a swid_inventory_t object.
|
||||
*/
|
||||
void (*destroy)(swid_inventory_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a swid_inventory_t object
|
||||
*
|
||||
* @param full_tags TRUE if full tags, FALSE if tag IDs only
|
||||
*/
|
||||
swid_inventory_t* swid_inventory_create(bool full_tags);
|
||||
|
||||
#endif /** SWID_INVENTORY_H_ @}*/
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "swid_tag.h"
|
||||
|
||||
typedef struct private_swid_tag_t private_swid_tag_t;
|
||||
|
||||
/**
|
||||
* Private data of a swid_tag_t object.
|
||||
*
|
||||
*/
|
||||
struct private_swid_tag_t {
|
||||
|
||||
/**
|
||||
* Public swid_tag_t interface.
|
||||
*/
|
||||
swid_tag_t public;
|
||||
|
||||
/**
|
||||
* UTF-8 XML encoding of SWID tag
|
||||
*/
|
||||
chunk_t encoding;
|
||||
|
||||
/**
|
||||
* Optional Tag Identifier Instance ID
|
||||
*/
|
||||
chunk_t instance_id;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(swid_tag_t, get_encoding, chunk_t,
|
||||
private_swid_tag_t *this)
|
||||
{
|
||||
return this->encoding;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_t, get_instance_id, chunk_t,
|
||||
private_swid_tag_t *this)
|
||||
{
|
||||
return this->instance_id;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_t, get_ref, swid_tag_t*,
|
||||
private_swid_tag_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_t, destroy, void,
|
||||
private_swid_tag_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
free(this->encoding.ptr);
|
||||
free(this->instance_id.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t instance_id)
|
||||
{
|
||||
private_swid_tag_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_encoding = _get_encoding,
|
||||
.get_instance_id = _get_instance_id,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.encoding = chunk_clone(encoding),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
if (instance_id.len > 0)
|
||||
{
|
||||
this->instance_id = chunk_clone(instance_id);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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_tag swid_tag
|
||||
* @{ @ingroup libimcv_swid
|
||||
*/
|
||||
|
||||
#ifndef SWID_TAG_H_
|
||||
#define SWID_TAG_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct swid_tag_t swid_tag_t;
|
||||
|
||||
|
||||
/**
|
||||
* Class storing a SWID Tag
|
||||
*/
|
||||
struct swid_tag_t {
|
||||
|
||||
/**
|
||||
* Get UTF-8 XML encoding of SWID tag
|
||||
*
|
||||
* @return XML encoding of SWID tag
|
||||
*/
|
||||
chunk_t (*get_encoding)(swid_tag_t *this);
|
||||
|
||||
/**
|
||||
* Get the optional Tag Identifier Instance ID
|
||||
*
|
||||
* @return Optional Tag Identifier Instance ID
|
||||
*/
|
||||
chunk_t (*get_instance_id)(swid_tag_t *this);
|
||||
|
||||
/**
|
||||
* Get a new reference to the swid_tag object
|
||||
*
|
||||
* @return this, with an increased refcount
|
||||
*/
|
||||
swid_tag_t* (*get_ref)(swid_tag_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a swid_tag_t object.
|
||||
*/
|
||||
void (*destroy)(swid_tag_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a swid_tag_t object
|
||||
*
|
||||
* @param encoding XML encoding of SWID tag
|
||||
* @param instance_id Tag Identifier Instance ID or empty chunk
|
||||
*/
|
||||
swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t instance_id);
|
||||
|
||||
#endif /** SWID_TAG_H_ @}*/
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "swid_tag_id.h"
|
||||
|
||||
typedef struct private_swid_tag_id_t private_swid_tag_id_t;
|
||||
|
||||
/**
|
||||
* Private data of a swid_tag_id_t object.
|
||||
*
|
||||
*/
|
||||
struct private_swid_tag_id_t {
|
||||
|
||||
/**
|
||||
* Public swid_tag_id_t interface.
|
||||
*/
|
||||
swid_tag_id_t public;
|
||||
|
||||
/**
|
||||
* Tag Creator
|
||||
*/
|
||||
chunk_t tag_creator;
|
||||
|
||||
/**
|
||||
* Unique Software ID
|
||||
*/
|
||||
chunk_t unique_sw_id;
|
||||
|
||||
/**
|
||||
* Optional Tag Identifier Instance ID
|
||||
*/
|
||||
chunk_t instance_id;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
|
||||
private_swid_tag_id_t *this)
|
||||
{
|
||||
return this->tag_creator;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_id_t, get_unique_sw_id, chunk_t,
|
||||
private_swid_tag_id_t *this, chunk_t *instance_id)
|
||||
{
|
||||
if (instance_id)
|
||||
{
|
||||
*instance_id = this->instance_id;
|
||||
}
|
||||
return this->unique_sw_id;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_id_t, get_ref, swid_tag_id_t*,
|
||||
private_swid_tag_id_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(swid_tag_id_t, destroy, void,
|
||||
private_swid_tag_id_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
free(this->tag_creator.ptr);
|
||||
free(this->unique_sw_id.ptr);
|
||||
free(this->instance_id.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
|
||||
chunk_t instance_id)
|
||||
{
|
||||
private_swid_tag_id_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_tag_creator = _get_tag_creator,
|
||||
.get_unique_sw_id = _get_unique_sw_id,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.tag_creator = chunk_clone(tag_creator),
|
||||
.unique_sw_id = chunk_clone(unique_sw_id),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
if (instance_id.len > 0)
|
||||
{
|
||||
this->instance_id = chunk_clone(instance_id);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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_tag_id swid_tag_id
|
||||
* @{ @ingroup libimcv_swid
|
||||
*/
|
||||
|
||||
#ifndef SWID_TAG_ID_H_
|
||||
#define SWID_TAG_ID_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct swid_tag_id_t swid_tag_id_t;
|
||||
|
||||
|
||||
/**
|
||||
* Class storing a SWID Tag ID
|
||||
*/
|
||||
struct swid_tag_id_t {
|
||||
|
||||
/**
|
||||
* Get the Tag Creator
|
||||
*
|
||||
* @return Tag Creator
|
||||
*/
|
||||
chunk_t (*get_tag_creator)(swid_tag_id_t *this);
|
||||
|
||||
/**
|
||||
* Get the Unique Software ID and optional Tag File Path
|
||||
*
|
||||
* @param instance_id Optional Tag Identifier Instance ID
|
||||
* @return Unique Software ID
|
||||
*/
|
||||
chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *instance_id);
|
||||
|
||||
/**
|
||||
* Get a new reference to the swid_tag_id object
|
||||
*
|
||||
* @return this, with an increased refcount
|
||||
*/
|
||||
swid_tag_id_t* (*get_ref)(swid_tag_id_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a swid_tag_id_t object.
|
||||
*/
|
||||
void (*destroy)(swid_tag_id_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a swid_tag_id_t object
|
||||
*
|
||||
* @param tag_creator Tag Creator
|
||||
* @param unique_sw_id Unique Software ID
|
||||
* @param instance_id Tag Identifier Instance ID or empty chunk
|
||||
*/
|
||||
swid_tag_id_t* swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
|
||||
chunk_t instance_id);
|
||||
|
||||
#endif /** SWID_TAG_ID_H_ @}*/
|
||||
@@ -1,351 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "tcg_swid_attr_req.h"
|
||||
|
||||
#include "swid/swid_tag_id.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_msg.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <utils/debug.h>
|
||||
#include <collections/linked_list.h>
|
||||
|
||||
typedef struct private_tcg_swid_attr_req_t private_tcg_swid_attr_req_t;
|
||||
|
||||
/**
|
||||
* SWID Request
|
||||
* see section 4.7 of TCG TNC SWID Message and Attributes for IF-M
|
||||
*
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |C|S|R| Reserved| Tag ID Count |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Request ID |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Earliest EID |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Tag Creator Length | Tag Creator (variable length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Unique Software ID Length |Unique Software ID (var length)|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
#define SWID_REQ_RESERVED_MASK 0xE0
|
||||
|
||||
/**
|
||||
* Private data of an tcg_swid_attr_req_t object.
|
||||
*/
|
||||
struct private_tcg_swid_attr_req_t {
|
||||
|
||||
/**
|
||||
* Public members of tcg_swid_attr_req_t
|
||||
*/
|
||||
tcg_swid_attr_req_t public;
|
||||
|
||||
/**
|
||||
* Vendor-specific attribute type
|
||||
*/
|
||||
pen_type_t type;
|
||||
|
||||
/**
|
||||
* Length of attribute value
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
|
||||
/**
|
||||
* Attribute value or segment
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Noskip flag
|
||||
*/
|
||||
bool noskip_flag;
|
||||
|
||||
/**
|
||||
* SWID request flags
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/**
|
||||
* Request ID
|
||||
*/
|
||||
uint32_t request_id;
|
||||
|
||||
/**
|
||||
* Earliest EID
|
||||
*/
|
||||
uint32_t earliest_eid;
|
||||
|
||||
/**
|
||||
* List of Target Tag Identifiers
|
||||
*/
|
||||
swid_inventory_t *targets;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_value, chunk_t,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->noskip_flag;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
|
||||
private_tcg_swid_attr_req_t *this, bool noskip)
|
||||
{
|
||||
this->noskip_flag = noskip;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, build, void,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
swid_tag_id_t *tag_id;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (this->value.ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
writer = bio_writer_create(TCG_SWID_REQ_MIN_SIZE);
|
||||
writer->write_uint8 (writer, this->flags);
|
||||
writer->write_uint24(writer, this->targets->get_count(this->targets));
|
||||
writer->write_uint32(writer, this->request_id);
|
||||
writer->write_uint32(writer, this->earliest_eid);
|
||||
|
||||
enumerator = this->targets->create_enumerator(this->targets);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
writer->write_data16(writer, tag_creator);
|
||||
writer->write_data16(writer, unique_sw_id);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->value = writer->extract_buf(writer);
|
||||
this->length = this->value.len;
|
||||
writer->destroy(writer);
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, process, status_t,
|
||||
private_tcg_swid_attr_req_t *this, uint32_t *offset)
|
||||
{
|
||||
bio_reader_t *reader;
|
||||
uint32_t tag_id_count;
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
swid_tag_id_t *tag_id;
|
||||
|
||||
*offset = 0;
|
||||
|
||||
if (this->value.len < this->length)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
if (this->value.len < TCG_SWID_REQ_MIN_SIZE)
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for SWID Request");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
reader = bio_reader_create(this->value);
|
||||
reader->read_uint8 (reader, &this->flags);
|
||||
reader->read_uint24(reader, &tag_id_count);
|
||||
reader->read_uint32(reader, &this->request_id);
|
||||
reader->read_uint32(reader, &this->earliest_eid);
|
||||
|
||||
if (this->request_id == 0)
|
||||
{
|
||||
*offset = 4;
|
||||
return FAILED;
|
||||
}
|
||||
*offset = TCG_SWID_REQ_MIN_SIZE;
|
||||
|
||||
this->flags &= SWID_REQ_RESERVED_MASK;
|
||||
|
||||
while (tag_id_count--)
|
||||
{
|
||||
if (!reader->read_data16(reader, &tag_creator))
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for Tag Creator field");
|
||||
reader->destroy(reader);
|
||||
return FAILED;
|
||||
}
|
||||
*offset += 2 + tag_creator.len;
|
||||
|
||||
if (!reader->read_data16(reader, &unique_sw_id))
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for Unique Software ID");
|
||||
reader->destroy(reader);
|
||||
return FAILED;
|
||||
}
|
||||
*offset += 2 + unique_sw_id.len;
|
||||
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, chunk_empty);
|
||||
this->targets->add(this->targets, tag_id);
|
||||
}
|
||||
reader->destroy(reader);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, add_segment, void,
|
||||
private_tcg_swid_attr_req_t *this, chunk_t segment)
|
||||
{
|
||||
this->value = chunk_cat("mc", this->value, segment);
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, destroy, void,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->targets->destroy(this->targets);
|
||||
free(this->value.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_req_t, get_flags, uint8_t,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->flags;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_req_t, get_request_id, uint32_t,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_req_t, get_earliest_eid, uint32_t,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->earliest_eid;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_req_t, add_target, void,
|
||||
private_tcg_swid_attr_req_t *this, swid_tag_id_t *tag_id)
|
||||
{
|
||||
this->targets->add(this->targets, tag_id);
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_req_t, get_targets, swid_inventory_t*,
|
||||
private_tcg_swid_attr_req_t *this)
|
||||
{
|
||||
return this->targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_req_create(uint8_t flags, uint32_t request_id,
|
||||
uint32_t eid)
|
||||
{
|
||||
private_tcg_swid_attr_req_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_flags = _get_flags,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_earliest_eid = _get_earliest_eid,
|
||||
.add_target = _add_target,
|
||||
.get_targets = _get_targets,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_REQUEST },
|
||||
.flags = flags & SWID_REQ_RESERVED_MASK,
|
||||
.request_id = request_id,
|
||||
.earliest_eid = eid,
|
||||
.targets = swid_inventory_create(FALSE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_req_create_from_data(size_t length, chunk_t data)
|
||||
{
|
||||
private_tcg_swid_attr_req_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_flags = _get_flags,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_earliest_eid = _get_earliest_eid,
|
||||
.add_target = _add_target,
|
||||
.get_targets = _get_targets,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_REQUEST },
|
||||
.length = length,
|
||||
.value = chunk_clone(data),
|
||||
.targets = swid_inventory_create(FALSE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-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 tcg_swid_attr_req tcg_swid_attr_req
|
||||
* @{ @ingroup tcg_attr
|
||||
*/
|
||||
|
||||
#ifndef TCG_SWID_ATTR_REQ_H_
|
||||
#define TCG_SWID_ATTR_REQ_H_
|
||||
|
||||
#define TCG_SWID_REQ_MIN_SIZE 12
|
||||
|
||||
typedef struct tcg_swid_attr_req_t tcg_swid_attr_req_t;
|
||||
typedef enum tcg_swid_attr_req_flag_t tcg_swid_attr_req_flag_t;
|
||||
|
||||
enum tcg_swid_attr_req_flag_t {
|
||||
TCG_SWID_ATTR_REQ_FLAG_NONE = 0,
|
||||
TCG_SWID_ATTR_REQ_FLAG_C = (1 << 7),
|
||||
TCG_SWID_ATTR_REQ_FLAG_S = (1 << 6),
|
||||
TCG_SWID_ATTR_REQ_FLAG_R = (1 << 5)
|
||||
};
|
||||
|
||||
#include "tcg/tcg_attr.h"
|
||||
#include "swid/swid_tag_id.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
#include "pa_tnc/pa_tnc_attr.h"
|
||||
|
||||
/**
|
||||
* Class implementing the TCG SWID Request attribute
|
||||
*/
|
||||
struct tcg_swid_attr_req_t {
|
||||
|
||||
/**
|
||||
* Public PA-TNC attribute interface
|
||||
*/
|
||||
pa_tnc_attr_t pa_tnc_attribute;
|
||||
|
||||
/**
|
||||
* Get SWID request flags
|
||||
*
|
||||
* @return Flags
|
||||
*/
|
||||
uint8_t (*get_flags)(tcg_swid_attr_req_t *this);
|
||||
|
||||
/**
|
||||
* Get Request ID
|
||||
*
|
||||
* @return Request ID
|
||||
*/
|
||||
uint32_t (*get_request_id)(tcg_swid_attr_req_t *this);
|
||||
|
||||
/**
|
||||
* Get Earliest EID
|
||||
*
|
||||
* @return Event ID
|
||||
*/
|
||||
uint32_t (*get_earliest_eid)(tcg_swid_attr_req_t *this);
|
||||
|
||||
/**
|
||||
* Add Tag ID
|
||||
*
|
||||
* @param tag_id SWID Tag ID (is not cloned by constructor!)
|
||||
*/
|
||||
void (*add_target)(tcg_swid_attr_req_t *this, swid_tag_id_t *tag_id);
|
||||
|
||||
/**
|
||||
* Create Tag ID enumerator
|
||||
*
|
||||
* @return Get a list of target tag IDs
|
||||
*/
|
||||
swid_inventory_t* (*get_targets)(tcg_swid_attr_req_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_req_t object
|
||||
*
|
||||
* @param flags Sets the C|S|R flags
|
||||
* @param request_id Request ID
|
||||
* @param eid Earliest Event ID
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_req_create(uint8_t flags, uint32_t request_id,
|
||||
uint32_t eid);
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_req_t object from received data
|
||||
*
|
||||
* @param length Total length of attribute value
|
||||
* @param value Unparsed attribute value (might be a segment)
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_req_create_from_data(size_t length, chunk_t value);
|
||||
|
||||
#endif /** TCG_SWID_ATTR_REQ_H_ @}*/
|
||||
@@ -1,396 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "tcg_swid_attr_tag_id_inv.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_msg.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
|
||||
typedef struct private_tcg_swid_attr_tag_id_inv_t private_tcg_swid_attr_tag_id_inv_t;
|
||||
|
||||
/**
|
||||
* SWID Tag Identifier Inventory
|
||||
* see section 4.8 of TCG TNC SWID Message and Attributes for IF-M
|
||||
*
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Reserved | Tag ID Count |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Request ID Copy |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | EID Epoch |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Last EID |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Tag Creator Length | Tag Creator (variable length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Unique Software ID Length |Unique Software ID (var length)|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Instance ID Length | Instance ID (variable length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
#define TCG_SWID_TAG_ID_INV_RESERVED 0x00
|
||||
|
||||
/**
|
||||
* Private data of an tcg_swid_attr_tag_id_inv_t object.
|
||||
*/
|
||||
struct private_tcg_swid_attr_tag_id_inv_t {
|
||||
|
||||
/**
|
||||
* Public members of tcg_swid_attr_tag_id_inv_t
|
||||
*/
|
||||
tcg_swid_attr_tag_id_inv_t public;
|
||||
|
||||
/**
|
||||
* Vendor-specific attribute type
|
||||
*/
|
||||
pen_type_t type;
|
||||
|
||||
/**
|
||||
* Length of attribute value
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
/**
|
||||
* Offset up to which attribute value has been processed
|
||||
*/
|
||||
size_t offset;
|
||||
|
||||
/**
|
||||
* Current position of attribute value pointer
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Contains complete attribute or current segment
|
||||
*/
|
||||
chunk_t segment;
|
||||
|
||||
/**
|
||||
* Noskip flag
|
||||
*/
|
||||
bool noskip_flag;
|
||||
|
||||
/**
|
||||
* Request ID
|
||||
*/
|
||||
uint32_t request_id;
|
||||
|
||||
/**
|
||||
* Event ID Epoch
|
||||
*/
|
||||
uint32_t eid_epoch;
|
||||
|
||||
/**
|
||||
* Last Event ID
|
||||
*/
|
||||
uint32_t last_eid;
|
||||
|
||||
/**
|
||||
* Number of SWID Tag IDs in attribute
|
||||
*/
|
||||
uint32_t tag_id_count;
|
||||
|
||||
/**
|
||||
* SWID Tag ID Inventory
|
||||
*/
|
||||
swid_inventory_t *inventory;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_value, chunk_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->noskip_flag;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this, bool noskip)
|
||||
{
|
||||
this->noskip_flag = noskip;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, build, void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
swid_tag_id_t *tag_id;
|
||||
chunk_t tag_creator, unique_sw_id, instance_id;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (this->value.ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
writer = bio_writer_create(TCG_SWID_TAG_ID_INV_MIN_SIZE);
|
||||
writer->write_uint8 (writer, TCG_SWID_TAG_ID_INV_RESERVED);
|
||||
writer->write_uint24(writer, this->inventory->get_count(this->inventory));
|
||||
writer->write_uint32(writer, this->request_id);
|
||||
writer->write_uint32(writer, this->eid_epoch);
|
||||
writer->write_uint32(writer, this->last_eid);
|
||||
|
||||
enumerator = this->inventory->create_enumerator(this->inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
unique_sw_id = tag_id->get_unique_sw_id(tag_id, &instance_id);
|
||||
writer->write_data16(writer, tag_creator);
|
||||
writer->write_data16(writer, unique_sw_id);
|
||||
writer->write_data16(writer, instance_id);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->value = writer->extract_buf(writer);
|
||||
this->segment = this->value;
|
||||
this->length = this->value.len;
|
||||
writer->destroy(writer);
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, process, status_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *offset)
|
||||
{
|
||||
bio_reader_t *reader;
|
||||
uint8_t reserved;
|
||||
chunk_t tag_creator, unique_sw_id, instance_id;
|
||||
swid_tag_id_t *tag_id;
|
||||
status_t status = NEED_MORE;
|
||||
|
||||
if (this->offset == 0)
|
||||
{
|
||||
if (this->length < TCG_SWID_TAG_ID_INV_MIN_SIZE)
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
|
||||
tcg_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
return FAILED;
|
||||
}
|
||||
if (this->value.len < TCG_SWID_TAG_ID_INV_MIN_SIZE)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
reader = bio_reader_create(this->value);
|
||||
reader->read_uint8 (reader, &reserved);
|
||||
reader->read_uint24(reader, &this->tag_id_count);
|
||||
reader->read_uint32(reader, &this->request_id);
|
||||
reader->read_uint32(reader, &this->eid_epoch);
|
||||
reader->read_uint32(reader, &this->last_eid);
|
||||
this->offset = TCG_SWID_TAG_ID_INV_MIN_SIZE;
|
||||
this->value = reader->peek(reader);
|
||||
reader->destroy(reader);
|
||||
}
|
||||
|
||||
reader = bio_reader_create(this->value);
|
||||
|
||||
while (this->tag_id_count)
|
||||
{
|
||||
if (!reader->read_data16(reader, &tag_creator) ||
|
||||
!reader->read_data16(reader, &unique_sw_id) ||
|
||||
!reader->read_data16(reader, &instance_id))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, instance_id);
|
||||
this->inventory->add(this->inventory, tag_id);
|
||||
this->offset += this->value.len - reader->remaining(reader);
|
||||
this->value = reader->peek(reader);
|
||||
|
||||
/* at least one tag ID was processed */
|
||||
status = SUCCESS;
|
||||
this->tag_id_count--;
|
||||
}
|
||||
|
||||
if (this->length != this->offset)
|
||||
{
|
||||
DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
|
||||
tcg_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
end:
|
||||
reader->destroy(reader);
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, add_segment, void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this, chunk_t segment)
|
||||
{
|
||||
this->value = chunk_cat("cc", this->value, segment);
|
||||
chunk_free(&this->segment);
|
||||
this->segment = this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, destroy, void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->inventory->destroy(this->inventory);
|
||||
free(this->segment.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, add, void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id)
|
||||
{
|
||||
this->inventory->add(this->inventory, tag_id);
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, uint32_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, uint32_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *eid_epoch)
|
||||
{
|
||||
if (eid_epoch)
|
||||
{
|
||||
*eid_epoch = this->eid_epoch;
|
||||
}
|
||||
return this->last_eid;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, get_tag_id_count, uint32_t,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->tag_id_count;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, get_inventory, swid_inventory_t*,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
return this->inventory;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_id_inv_t, clear_inventory, void,
|
||||
private_tcg_swid_attr_tag_id_inv_t *this)
|
||||
{
|
||||
this->inventory->destroy(this->inventory);
|
||||
this->inventory = swid_inventory_create(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
|
||||
uint32_t eid_epoch,
|
||||
uint32_t eid)
|
||||
{
|
||||
private_tcg_swid_attr_tag_id_inv_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add = _add,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_last_eid = _get_last_eid,
|
||||
.get_tag_id_count = _get_tag_id_count,
|
||||
.get_inventory = _get_inventory,
|
||||
.clear_inventory = _clear_inventory,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
|
||||
.request_id = request_id,
|
||||
.eid_epoch = eid_epoch,
|
||||
.last_eid = eid,
|
||||
.inventory = swid_inventory_create(FALSE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create_from_data(size_t length,
|
||||
chunk_t data)
|
||||
{
|
||||
private_tcg_swid_attr_tag_id_inv_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add = _add,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_last_eid = _get_last_eid,
|
||||
.get_tag_id_count = _get_tag_id_count,
|
||||
.get_inventory = _get_inventory,
|
||||
.clear_inventory = _clear_inventory,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
|
||||
.length = length,
|
||||
.segment = chunk_clone(data),
|
||||
.inventory = swid_inventory_create(FALSE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
/* received either complete attribute value or first segment */
|
||||
this->value = this->segment;
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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 tcg_swid_attr_tag_id_inv tcg_swid_attr_tag_id_inv
|
||||
* @{ @ingroup tcg_attr
|
||||
*/
|
||||
|
||||
#ifndef TCG_SWID_ATTR_TAG_ID_INV_H_
|
||||
#define TCG_SWID_ATTR_TAG_ID_INV_H_
|
||||
|
||||
typedef struct tcg_swid_attr_tag_id_inv_t tcg_swid_attr_tag_id_inv_t;
|
||||
|
||||
#include "tcg/tcg_attr.h"
|
||||
#include "swid/swid_tag_id.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_attr.h>
|
||||
|
||||
#define TCG_SWID_TAG_ID_INV_MIN_SIZE 16
|
||||
|
||||
/**
|
||||
* Class implementing the TCG SWID Tag Identifier Inventory attribute
|
||||
*
|
||||
*/
|
||||
struct tcg_swid_attr_tag_id_inv_t {
|
||||
|
||||
/**
|
||||
* Public PA-TNC attribute interface
|
||||
*/
|
||||
pa_tnc_attr_t pa_tnc_attribute;
|
||||
|
||||
/**
|
||||
* Add a Tag ID to the attribute
|
||||
*
|
||||
* @param tag_id SWID Tag ID to be added
|
||||
*/
|
||||
void (*add)(tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id);
|
||||
|
||||
/**
|
||||
* Get Request ID
|
||||
*
|
||||
* @return Request ID
|
||||
*/
|
||||
uint32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
|
||||
|
||||
/**
|
||||
* Get Last Event ID
|
||||
*
|
||||
* @param eid_epoch Event ID Epoch
|
||||
* @return Last Event ID
|
||||
*/
|
||||
uint32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
|
||||
uint32_t *eid_epoch);
|
||||
|
||||
/**
|
||||
* Get count of remaining SWID tag IDs
|
||||
*
|
||||
* @return SWID Tag ID count
|
||||
*/
|
||||
uint32_t (*get_tag_id_count)(tcg_swid_attr_tag_id_inv_t *this);
|
||||
|
||||
/**
|
||||
* Get Inventory of SWID tag IDs
|
||||
*
|
||||
* @result SWID Tag ID Inventory
|
||||
*/
|
||||
swid_inventory_t* (*get_inventory)(tcg_swid_attr_tag_id_inv_t *this);
|
||||
|
||||
/**
|
||||
* Remove all SWID Tag IDs from the Inventory
|
||||
*/
|
||||
void (*clear_inventory)(tcg_swid_attr_tag_id_inv_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_tag_id_inv_t object
|
||||
*
|
||||
* @param request_id Copy of the Request ID
|
||||
* @param eid_epoch Event ID Epoch
|
||||
* @param eid Last Event ID
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
|
||||
uint32_t eid_epoch,
|
||||
uint32_t eid);
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_tag_id_inv_t object from received data
|
||||
*
|
||||
* @param length Total length of attribute value
|
||||
* @param value Unparsed attribute value (might be a segment)
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create_from_data(size_t length,
|
||||
chunk_t value);
|
||||
|
||||
#endif /** TCG_SWID_ATTR_TAG_ID_INV_H_ @}*/
|
||||
@@ -1,389 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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.
|
||||
*/
|
||||
|
||||
#include "tcg_swid_attr_tag_inv.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_msg.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
|
||||
typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
|
||||
|
||||
/**
|
||||
* SWID Tag Inventory
|
||||
* see section 4.10 of TCG TNC SWID Message and Attributes for IF-M
|
||||
*
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Reserved | Tag ID Count |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Request ID Copy |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | EID Epoch |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Last EID |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Instance ID Length | Instance ID (var. length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Tag Length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Tag (Variable) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
#define TCG_SWID_TAG_INV_RESERVED 0x00
|
||||
|
||||
/**
|
||||
* Private data of an tcg_swid_attr_tag_inv_t object.
|
||||
*/
|
||||
struct private_tcg_swid_attr_tag_inv_t {
|
||||
|
||||
/**
|
||||
* Public members of tcg_swid_attr_tag_inv_t
|
||||
*/
|
||||
tcg_swid_attr_tag_inv_t public;
|
||||
|
||||
/**
|
||||
* Vendor-specific attribute type
|
||||
*/
|
||||
pen_type_t type;
|
||||
|
||||
/**
|
||||
* Length of attribute value
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
/**
|
||||
* Offset up to which attribute value has been processed
|
||||
*/
|
||||
size_t offset;
|
||||
|
||||
/**
|
||||
* Current position of attribute value pointer
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Contains complete attribute or current segment
|
||||
*/
|
||||
chunk_t segment;
|
||||
|
||||
/**
|
||||
* Noskip flag
|
||||
*/
|
||||
bool noskip_flag;
|
||||
|
||||
/**
|
||||
* Request ID
|
||||
*/
|
||||
uint32_t request_id;
|
||||
|
||||
/**
|
||||
* Event ID Epoch
|
||||
*/
|
||||
uint32_t eid_epoch;
|
||||
|
||||
/**
|
||||
* Last Event ID
|
||||
*/
|
||||
uint32_t last_eid;
|
||||
|
||||
/**
|
||||
* Number of SWID Tags in attribute
|
||||
*/
|
||||
uint32_t tag_count;
|
||||
|
||||
/**
|
||||
* SWID Tag Inventory
|
||||
*/
|
||||
swid_inventory_t *inventory;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_value, chunk_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->noskip_flag;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
|
||||
private_tcg_swid_attr_tag_inv_t *this, bool noskip)
|
||||
{
|
||||
this->noskip_flag = noskip;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, build, void,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
swid_tag_t *tag;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (this->value.ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
writer = bio_writer_create(TCG_SWID_TAG_INV_MIN_SIZE);
|
||||
writer->write_uint8 (writer, TCG_SWID_TAG_INV_RESERVED);
|
||||
writer->write_uint24(writer, this->inventory->get_count(this->inventory));
|
||||
writer->write_uint32(writer, this->request_id);
|
||||
writer->write_uint32(writer, this->eid_epoch);
|
||||
writer->write_uint32(writer, this->last_eid);
|
||||
|
||||
enumerator = this->inventory->create_enumerator(this->inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag))
|
||||
{
|
||||
writer->write_data16(writer, tag->get_instance_id(tag));
|
||||
writer->write_data32(writer, tag->get_encoding(tag));
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->value = writer->extract_buf(writer);
|
||||
this->segment = this->value;
|
||||
this->length = this->value.len;
|
||||
writer->destroy(writer);
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, process, status_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this, uint32_t *offset)
|
||||
{
|
||||
bio_reader_t *reader;
|
||||
uint8_t reserved;
|
||||
chunk_t tag_encoding, instance_id;
|
||||
swid_tag_t *tag;
|
||||
status_t status = NEED_MORE;
|
||||
|
||||
if (this->offset == 0)
|
||||
{
|
||||
if (this->length < TCG_SWID_TAG_INV_MIN_SIZE)
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
|
||||
tcg_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
return FAILED;
|
||||
}
|
||||
if (this->value.len < TCG_SWID_TAG_INV_MIN_SIZE)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
reader = bio_reader_create(this->value);
|
||||
reader->read_uint8 (reader, &reserved);
|
||||
reader->read_uint24(reader, &this->tag_count);
|
||||
reader->read_uint32(reader, &this->request_id);
|
||||
reader->read_uint32(reader, &this->eid_epoch);
|
||||
reader->read_uint32(reader, &this->last_eid);
|
||||
this->offset = TCG_SWID_TAG_INV_MIN_SIZE;
|
||||
this->value = reader->peek(reader);
|
||||
reader->destroy(reader);
|
||||
}
|
||||
|
||||
reader = bio_reader_create(this->value);
|
||||
|
||||
while (this->tag_count)
|
||||
{
|
||||
if (!reader->read_data16(reader, &instance_id) ||
|
||||
!reader->read_data32(reader, &tag_encoding))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
tag = swid_tag_create(tag_encoding, instance_id);
|
||||
this->inventory->add(this->inventory, tag);
|
||||
this->offset += this->value.len - reader->remaining(reader);
|
||||
this->value = reader->peek(reader);
|
||||
|
||||
/* at least one tag was processed */
|
||||
status = SUCCESS;
|
||||
this->tag_count--;
|
||||
}
|
||||
|
||||
if (this->length != this->offset)
|
||||
{
|
||||
DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
|
||||
tcg_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
end:
|
||||
reader->destroy(reader);
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, add_segment, void,
|
||||
private_tcg_swid_attr_tag_inv_t *this, chunk_t segment)
|
||||
{
|
||||
this->value = chunk_cat("cc", this->value, segment);
|
||||
chunk_free(&this->segment);
|
||||
this->segment = this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, destroy, void,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->inventory->destroy(this->inventory);
|
||||
free(this->segment.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, add, void,
|
||||
private_tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag)
|
||||
{
|
||||
this->inventory->add(this->inventory, tag);
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, get_request_id, uint32_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, uint32_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this, uint32_t *eid_epoch)
|
||||
{
|
||||
if (eid_epoch)
|
||||
{
|
||||
*eid_epoch = this->eid_epoch;
|
||||
}
|
||||
return this->last_eid;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, get_tag_count, uint32_t,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->tag_count;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, get_inventory, swid_inventory_t*,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
return this->inventory;
|
||||
}
|
||||
|
||||
METHOD(tcg_swid_attr_tag_inv_t, clear_inventory, void,
|
||||
private_tcg_swid_attr_tag_inv_t *this)
|
||||
{
|
||||
this->inventory->destroy(this->inventory);
|
||||
this->inventory = swid_inventory_create(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(uint32_t request_id,
|
||||
uint32_t eid_epoch, uint32_t eid)
|
||||
{
|
||||
private_tcg_swid_attr_tag_inv_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add = _add,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_last_eid = _get_last_eid,
|
||||
.get_tag_count = _get_tag_count,
|
||||
.get_inventory = _get_inventory,
|
||||
.clear_inventory = _clear_inventory,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
|
||||
.request_id = request_id,
|
||||
.eid_epoch = eid_epoch,
|
||||
.last_eid = eid,
|
||||
.inventory = swid_inventory_create(TRUE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(size_t length,
|
||||
chunk_t data)
|
||||
{
|
||||
private_tcg_swid_attr_tag_inv_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add = _add,
|
||||
.get_request_id = _get_request_id,
|
||||
.get_last_eid = _get_last_eid,
|
||||
.get_tag_count = _get_tag_count,
|
||||
.get_inventory = _get_inventory,
|
||||
.clear_inventory = _clear_inventory,
|
||||
},
|
||||
.type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
|
||||
.length = length,
|
||||
.segment = chunk_clone(data),
|
||||
.inventory = swid_inventory_create(TRUE),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
/* received either complete attribute value or first segment */
|
||||
this->value = this->segment;
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 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 tcg_swid_attr_tag_inv tcg_swid_attr_tag_inv
|
||||
* @{ @ingroup tcg_attr
|
||||
*/
|
||||
|
||||
#ifndef TCG_SWID_ATTR_TAG_INV_H_
|
||||
#define TCG_SWID_ATTR_TAG_INV_H_
|
||||
|
||||
typedef struct tcg_swid_attr_tag_inv_t tcg_swid_attr_tag_inv_t;
|
||||
|
||||
#include "tcg/tcg_attr.h"
|
||||
#include "swid/swid_tag.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_attr.h>
|
||||
|
||||
#define TCG_SWID_TAG_INV_MIN_SIZE 16
|
||||
|
||||
/**
|
||||
* Class implementing the TCG SWID Tag Inventory attribute
|
||||
*
|
||||
*/
|
||||
struct tcg_swid_attr_tag_inv_t {
|
||||
|
||||
/**
|
||||
* Public PA-TNC attribute interface
|
||||
*/
|
||||
pa_tnc_attr_t pa_tnc_attribute;
|
||||
|
||||
/**
|
||||
* Add a Tag ID to the attribute
|
||||
*
|
||||
* @param tag SWID Tag to be added
|
||||
*/
|
||||
void (*add)(tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag);
|
||||
/**
|
||||
* Get Request ID
|
||||
*
|
||||
* @return Request ID
|
||||
*/
|
||||
uint32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
|
||||
|
||||
/**
|
||||
* Get Last Event ID
|
||||
*
|
||||
* @param eid_epoch Event ID Epoch
|
||||
* @return Last Event ID
|
||||
*/
|
||||
uint32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
|
||||
uint32_t *eid_epoch);
|
||||
|
||||
/**
|
||||
* Get count of remaining SWID tags
|
||||
*
|
||||
* @return SWID Tag count
|
||||
*/
|
||||
uint32_t (*get_tag_count)(tcg_swid_attr_tag_inv_t *this);
|
||||
|
||||
/**
|
||||
* Get Inventory of SWID tags
|
||||
*
|
||||
* @result SWID Tag Inventory
|
||||
*/
|
||||
swid_inventory_t* (*get_inventory)(tcg_swid_attr_tag_inv_t *this);
|
||||
|
||||
/**
|
||||
* Remove all SWID Tags from the Inventory
|
||||
*/
|
||||
void (*clear_inventory)(tcg_swid_attr_tag_inv_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_tag_inv_t object
|
||||
*
|
||||
* @param request_id Copy of the Request ID
|
||||
* @param eid_epoch Event ID Epoch
|
||||
* @param eid Last Event ID
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_tag_inv_create(uint32_t request_id,
|
||||
uint32_t eid_epoch,
|
||||
uint32_t eid);
|
||||
|
||||
/**
|
||||
* Creates an tcg_swid_attr_tag_inv_t object from received data
|
||||
*
|
||||
* @param length Total length of attribute value
|
||||
* @param value Unparsed attribute value (might be a segment)
|
||||
*/
|
||||
pa_tnc_attr_t* tcg_swid_attr_tag_inv_create_from_data(size_t length,
|
||||
chunk_t value);
|
||||
|
||||
#endif /** TCG_SWID_ATTR_TAG_INV_H_ @}*/
|
||||
@@ -31,9 +31,6 @@
|
||||
#include "tcg/pts/tcg_pts_attr_file_meas.h"
|
||||
#include "tcg/pts/tcg_pts_attr_req_file_meta.h"
|
||||
#include "tcg/pts/tcg_pts_attr_unix_file_meta.h"
|
||||
#include "tcg/swid/tcg_swid_attr_req.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/seg/tcg_seg_attr_next_seg.h"
|
||||
@@ -189,12 +186,6 @@ pa_tnc_attr_t* tcg_attr_create_from_data(uint32_t type, size_t length, chunk_t v
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TCG_SWID_REQUEST:
|
||||
return tcg_swid_attr_req_create_from_data(length, value);
|
||||
case TCG_SWID_TAG_ID_INVENTORY:
|
||||
return tcg_swid_attr_tag_id_inv_create_from_data(length, value);
|
||||
case TCG_SWID_TAG_INVENTORY:
|
||||
return tcg_swid_attr_tag_inv_create_from_data(length, value);
|
||||
case TCG_SEG_MAX_ATTR_SIZE_REQ:
|
||||
return tcg_seg_attr_max_size_create_from_data(length, value, TRUE);
|
||||
case TCG_SEG_MAX_ATTR_SIZE_RESP:
|
||||
@@ -253,6 +244,9 @@ pa_tnc_attr_t* tcg_attr_create_from_data(uint32_t type, size_t length, chunk_t v
|
||||
case TCG_PTS_UNIX_FILE_META:
|
||||
return tcg_pts_attr_unix_file_meta_create_from_data(length, value);
|
||||
/* unsupported TCG/SWID attributes */
|
||||
case TCG_SWID_REQUEST:
|
||||
case TCG_SWID_TAG_ID_INVENTORY:
|
||||
case TCG_SWID_TAG_INVENTORY:
|
||||
case TCG_SWID_TAG_ID_EVENTS:
|
||||
case TCG_SWID_TAG_EVENTS:
|
||||
case TCG_SWID_SUBSCRIPTION_STATUS_REQ:
|
||||
|
||||
@@ -54,8 +54,6 @@ CONFIG_OPTS = \
|
||||
--enable-imv-os \
|
||||
--enable-imc-attestation \
|
||||
--enable-imv-attestation \
|
||||
--enable-imc-swid \
|
||||
--enable-imv-swid \
|
||||
--enable-imc-swima \
|
||||
--enable-imv-swima \
|
||||
--enable-imc-hcd \
|
||||
|
||||
Reference in New Issue
Block a user