Moved tnc-tnccs, tnc-imc, tnccs-11, tnccs-20 and tnccs-dynamic libcharon plugins to libtnccs

This commit is contained in:
Andreas Steffen
2013-08-15 23:34:22 +02:00
parent 180a2f2642
commit e8f65c5cde
73 changed files with 92 additions and 63 deletions
-25
View File
@@ -1,25 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs \
-I$(top_srcdir)/src/libtls
AM_CFLAGS = \
-rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
else
plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
libstrongswan_tnc_imc_la_LIBADD = \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libtnccs/libtnccs.la
endif
libstrongswan_tnc_imc_la_SOURCES = \
tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \
tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c
libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version
-428
View File
@@ -1,428 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley
* Copyright (C) 2010-2011 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 "tnc_imc.h"
#include <dlfcn.h>
#include <tncif_pa_subtypes.h>
#include <utils/debug.h>
#include <library.h>
#include <collections/linked_list.h>
#include <threading/mutex.h>
typedef struct private_tnc_imc_t private_tnc_imc_t;
/**
* Private data of an imc_t object.
*/
struct private_tnc_imc_t {
/**
* Public members of imc_t.
*/
imc_t public;
/**
* Name of loaded IMC
*/
char *name;
/**
* Handle of loaded IMC
*/
void *handle;
/**
* ID of loaded IMC
*/
TNC_IMCID id;
/**
* list of additional IMC IDs
*/
linked_list_t *additional_ids;
/**
* List of message types supported by IMC - Vendor ID part
*/
TNC_VendorIDList supported_vids;
/**
* List of message types supported by IMC - Subtype part
*/
TNC_MessageSubtypeList supported_subtypes;
/**
* Number of supported message types
*/
TNC_UInt32 type_count;
/**
* mutex to lock the imc_t object
*/
mutex_t *mutex;
};
METHOD(imc_t, set_id, void,
private_tnc_imc_t *this, TNC_IMCID id)
{
this->id = id;
}
METHOD(imc_t, get_id, TNC_IMCID,
private_tnc_imc_t *this)
{
return this->id;
}
METHOD(imc_t, add_id, void,
private_tnc_imc_t *this, TNC_IMCID id)
{
void *pointer;
/* store the scalar value in the pointer */
pointer = (void*)id;
this->additional_ids->insert_last(this->additional_ids, pointer);
}
METHOD(imc_t, has_id, bool,
private_tnc_imc_t *this, TNC_IMCID id)
{
enumerator_t *enumerator;
TNC_IMCID additional_id;
void *pointer;
bool found = FALSE;
/* check primary IMC ID */
if (id == this->id)
{
return TRUE;
}
/* return if there are no additional IMC IDs */
if (this->additional_ids->get_count(this->additional_ids) == 0)
{
return FALSE;
}
/* check additional IMC IDs */
enumerator = this->additional_ids->create_enumerator(this->additional_ids);
while (enumerator->enumerate(enumerator, &pointer))
{
/* interpret pointer as scalar value */
additional_id = (TNC_UInt32)pointer;
if (id == additional_id)
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
METHOD(imc_t, get_name, char*,
private_tnc_imc_t *this)
{
return this->name;
}
METHOD(imc_t, set_message_types, void,
private_tnc_imc_t *this, TNC_MessageTypeList supported_types,
TNC_UInt32 type_count)
{
char buf[BUF_LEN];
char *pos = buf;
int len = sizeof(buf);
int i, written;
size_t size;
TNC_VendorID vid;
TNC_MessageSubtype subtype;
enum_name_t *pa_subtype_names;
/* lock the imc_t instance */
this->mutex->lock(this->mutex);
/* Free existing VendorID and MessageSubtype lists */
free(this->supported_vids);
this->supported_vids = NULL;
free(this->supported_subtypes);
this->supported_subtypes = NULL;
/* Store the new MessageType list */
this->type_count = type_count;
if (type_count && supported_types)
{
size = type_count * sizeof(TNC_VendorID);
this->supported_vids = malloc(size);
size = type_count * sizeof(TNC_MessageSubtype);
this->supported_subtypes = malloc(size);
for (i = 0; i < type_count; i++)
{
vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY;
subtype = supported_types[i] & TNC_SUBTYPE_ANY;
pa_subtype_names = get_pa_subtype_names(vid);
if (pa_subtype_names)
{
written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x",
pen_names, vid, pa_subtype_names, subtype,
vid, subtype);
}
else
{
written = snprintf(pos, len," '%N' 0x%06x/0x%02x",
pen_names, vid, vid, subtype);
}
if (written >= len)
{
break;
}
pos += written;
len -= written;
this->supported_vids[i] = vid;
this->supported_subtypes[i] = subtype;
}
}
*pos = '\0';
DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
this->id, type_count, (type_count == 1) ? "":"s", buf);
/* unlock the imc_t instance */
this->mutex->unlock(this->mutex);
}
METHOD(imc_t, set_message_types_long, void,
private_tnc_imc_t *this, TNC_VendorIDList supported_vids,
TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count)
{
char buf[BUF_LEN];
char *pos = buf;
int len = sizeof(buf);
int i, written;
size_t size;
TNC_VendorID vid;
TNC_MessageSubtype subtype;
enum_name_t *pa_subtype_names;
/* lock the imc_t instance */
this->mutex->lock(this->mutex);
/* Free existing VendorID and MessageSubtype lists */
free(this->supported_vids);
this->supported_vids = NULL;
free(this->supported_subtypes);
this->supported_subtypes = NULL;
/* Store the new MessageType list */
this->type_count = type_count;
if (type_count && supported_vids && supported_subtypes)
{
size = type_count * sizeof(TNC_VendorID);
this->supported_vids = malloc(size);
memcpy(this->supported_vids, supported_vids, size);
size = type_count * sizeof(TNC_MessageSubtype);
this->supported_subtypes = malloc(size);
memcpy(this->supported_subtypes, supported_subtypes, size);
for (i = 0; i < type_count; i++)
{
vid = supported_vids[i];
subtype = supported_subtypes[i];
pa_subtype_names = get_pa_subtype_names(vid);
if (pa_subtype_names)
{
written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x",
pen_names, vid, pa_subtype_names, subtype,
vid, subtype);
}
else
{
written = snprintf(pos, len," '%N' 0x%06x/0x%08x",
pen_names, vid, vid, subtype);
}
if (written >= len)
{
break;
}
pos += written;
len -= written;
}
}
*pos = '\0';
DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
this->id, type_count, (type_count == 1) ? "":"s", buf);
/* unlock the imc_t instance */
this->mutex->unlock(this->mutex);
}
METHOD(imc_t, type_supported, bool,
private_tnc_imc_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype)
{
TNC_VendorID vid;
TNC_MessageSubtype subtype;
int i;
for (i = 0; i < this->type_count; i++)
{
vid = this->supported_vids[i];
subtype = this->supported_subtypes[i];
if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) ||
(vid == msg_vid && (subtype == TNC_SUBTYPE_ANY ||
subtype == msg_subtype)))
{
return TRUE;
}
}
return FALSE;
}
METHOD(imc_t, destroy, void,
private_tnc_imc_t *this)
{
if (this->handle && lib->settings->get_bool(lib->settings,
"%s.plugins.tnc-imc.dlclose", TRUE, "charon"))
{
dlclose(this->handle);
}
this->mutex->destroy(this->mutex);
this->additional_ids->destroy(this->additional_ids);
free(this->supported_vids);
free(this->supported_subtypes);
free(this->name);
free(this);
}
/**
* Generic constructor
*/
static private_tnc_imc_t* tnc_imc_create_empty(char *name)
{
private_tnc_imc_t *this;
INIT(this,
.public = {
.set_id = _set_id,
.get_id = _get_id,
.add_id = _add_id,
.has_id = _has_id,
.get_name = _get_name,
.set_message_types = _set_message_types,
.set_message_types_long = _set_message_types_long,
.type_supported = _type_supported,
.destroy = _destroy,
},
.name = strdup(name),
.additional_ids = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
return this;
}
/**
* See header
*/
imc_t* tnc_imc_create(char *name, char *path)
{
private_tnc_imc_t *this;
this = tnc_imc_create_empty(name);
this->handle = dlopen(path, RTLD_LAZY);
if (!this->handle)
{
DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
destroy(this);
return NULL;
}
this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
if (!this->public.initialize)
{
DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
path, dlerror());
destroy(this);
return NULL;
}
this->public.notify_connection_change =
dlsym(this->handle, "TNC_IMC_NotifyConnectionChange");
this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake");
if (!this->public.begin_handshake)
{
DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
path, dlerror());
destroy(this);
return NULL;
}
this->public.receive_message =
dlsym(this->handle, "TNC_IMC_ReceiveMessage");
this->public.receive_message_long =
dlsym(this->handle, "TNC_IMC_ReceiveMessageLong");
this->public.batch_ending =
dlsym(this->handle, "TNC_IMC_BatchEnding");
this->public.terminate =
dlsym(this->handle, "TNC_IMC_Terminate");
this->public.provide_bind_function =
dlsym(this->handle, "TNC_IMC_ProvideBindFunction");
if (!this->public.provide_bind_function)
{
DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
path, dlerror());
destroy(this);
return NULL;
}
return &this->public;
}
/**
* See header
*/
imc_t* tnc_imc_create_from_functions(char *name,
TNC_IMC_InitializePointer initialize,
TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
TNC_IMC_BeginHandshakePointer begin_handshake,
TNC_IMC_ReceiveMessagePointer receive_message,
TNC_IMC_ReceiveMessageLongPointer receive_message_long,
TNC_IMC_BatchEndingPointer batch_ending,
TNC_IMC_TerminatePointer terminate,
TNC_IMC_ProvideBindFunctionPointer provide_bind_function)
{
private_tnc_imc_t *this;
this = tnc_imc_create_empty(name);
this->public.initialize = initialize;
this->public.notify_connection_change = notify_connection_change;
this->public.begin_handshake = begin_handshake;
this->public.receive_message = receive_message;
this->public.receive_message_long = receive_message_long;
this->public.batch_ending = batch_ending;
this->public.terminate = terminate;
this->public.provide_bind_function = provide_bind_function;
return &this->public;
}
-60
View File
@@ -1,60 +0,0 @@
/*
* Copyright (C) 2010 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 tnc_imc_t tnc_imc
* @{ @ingroup tnc_imc
*/
#ifndef TNC_IMC_H_
#define TNC_IMC_H_
#include <tnc/imc/imc.h>
/**
* Create an Integrity Measurement Collector loaded from a library.
*
* @param name name of the IMC
* @param filename path to the dynamic IMC library
* @return instance of the imc_t interface
*/
imc_t* tnc_imc_create(char *name, char *filename);
/**
* Create an Integrity Measurement Collector from a set of IMC functions.
*
* @param name name of the IMC
* @param initialize TNC_IMC_InitializePointer
* @param notify_connection_change TNC_IMC_NotifyConnectionChangePointer
* @param begin_handshake TNC_IMC_BeginHandshakePointer
* @param receive_message TNC_IMC_ReceiveMessagePointer
* @param receive_message_long TNC_IMC_ReceiveMessageLongPointer
* @param batch_ending TNC_IMC_BatchEndingPointer
* @param terminate TNC_IMC_TerminatePointer
* @param provide_bind_function TNC_IMC_ProvideBindFunctionPointer
* @return instance of the imc_t interface
*/
imc_t* tnc_imc_create_from_functions(char *name,
TNC_IMC_InitializePointer initialize,
TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
TNC_IMC_BeginHandshakePointer begin_handshake,
TNC_IMC_ReceiveMessagePointer receive_message,
TNC_IMC_ReceiveMessageLongPointer receive_message_long,
TNC_IMC_BatchEndingPointer batch_ending,
TNC_IMC_TerminatePointer terminate,
TNC_IMC_ProvideBindFunctionPointer provide_bind_function);
#endif /** TNC_IMC_H_ @}*/
@@ -1,222 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley
* Copyright (C) 2010 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 <tnc/tnc.h>
#include <tnc/imc/imc_manager.h>
#include <tnc/tnccs/tnccs_manager.h>
#include <utils/debug.h>
/**
* Called by the IMC to inform a TNCC about the set of message types the IMC
* is able to receive
*/
TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id,
TNC_MessageTypeList supported_types,
TNC_UInt32 type_count)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->imcs->set_message_types(tnc->imcs, imc_id, supported_types,
type_count);
}
/**
* Called by the IMC to inform a TNCC about the set of message types the IMC
* is able to receive. This function supports long message types.
*/
TNC_Result TNC_TNCC_ReportMessageTypesLong(TNC_IMCID imc_id,
TNC_VendorIDList supported_vids,
TNC_MessageSubtypeList supported_subtypes,
TNC_UInt32 type_count)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring ReportMessageTypesLong() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->imcs->set_message_types_long(tnc->imcs, imc_id, supported_vids,
supported_subtypes, type_count);
}
/**
* Called by the IMC to ask a TNCC to retry an Integrity Check Handshake
*/
TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id,
TNC_ConnectionID connection_id,
TNC_RetryReason reason)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->tnccs->request_handshake_retry(tnc->tnccs, TRUE, imc_id,
connection_id, reason);
}
/**
* Called by the IMC when an IMC-IMV message is to be sent
*/
TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id,
TNC_ConnectionID connection_id,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
TNC_MessageType msg_type)
{
TNC_VendorID msg_vid;
TNC_MessageSubtype msg_subtype;
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY;
msg_subtype = msg_type & TNC_SUBTYPE_ANY;
return tnc->tnccs->send_message(tnc->tnccs, imc_id, TNC_IMVID_ANY,
connection_id, 0, msg, msg_len, msg_vid, msg_subtype);
}
/**
* Called by the IMC when an IMC-IMV message is to be sent over IF-TNCCS 2.0
*/
TNC_Result TNC_TNCC_SendMessageLong(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 imv_id)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->tnccs->send_message(tnc->tnccs, imc_id, imv_id, connection_id,
msg_flags, msg, msg_len, msg_vid, msg_subtype);
}
/**
* Called by the IMC to get the value of an attribute associated with a
* connection or with the TNCC as a whole.
*/
TNC_Result TNC_TNCC_GetAttribute(TNC_IMCID imc_id,
TNC_ConnectionID connection_id,
TNC_AttributeID attribute_id,
TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *out_value_len)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->tnccs->get_attribute(tnc->tnccs, TRUE, imc_id, connection_id,
attribute_id, buffer_len, buffer, out_value_len);
}
/**
* Called by the IMC to set the value of an attribute associated with a
* connection or with the TNCC as a whole.
*/
TNC_Result TNC_TNCC_SetAttribute(TNC_IMCID imc_id,
TNC_ConnectionID connection_id,
TNC_AttributeID attribute_id,
TNC_UInt32 buffer_len,
TNC_BufferReference buffer)
{
if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
{
DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
return tnc->tnccs->set_attribute(tnc->tnccs, TRUE, imc_id, connection_id,
attribute_id, buffer_len, buffer);
}
/**
* Called by the IMC when it wants to reserve an additional IMC ID for itself
*/
TNC_Result TNC_TNCC_ReserveAdditionalIMCID(TNC_IMCID imc_id, TNC_UInt32 *new_id)
{
if (tnc->imcs->reserve_id(tnc->imcs, imc_id, new_id))
{
return TNC_RESULT_SUCCESS;
}
DBG1(DBG_TNC, "ignoring ReserveAdditionalIMCID() from unregistered IMC %u",
imc_id);
return TNC_RESULT_INVALID_PARAMETER;
}
/**
* Called by the IMC when it needs a function pointer
*/
TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id,
char *function_name,
void **function_pointer)
{
if (streq(function_name, "TNC_TNCC_ReportMessageTypes"))
{
*function_pointer = (void*)TNC_TNCC_ReportMessageTypes;
}
else if (streq(function_name, "TNC_TNCC_ReportMessageTypesLong"))
{
*function_pointer = (void*)TNC_TNCC_ReportMessageTypesLong;
}
else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry"))
{
*function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry;
}
else if (streq(function_name, "TNC_TNCC_SendMessage"))
{
*function_pointer = (void*)TNC_TNCC_SendMessage;
}
else if (streq(function_name, "TNC_TNCC_SendMessageLong"))
{
*function_pointer = (void*)TNC_TNCC_SendMessageLong;
}
else if (streq(function_name, "TNC_TNCC_GetAttribute"))
{
*function_pointer = (void*)TNC_TNCC_GetAttribute;
}
else if (streq(function_name, "TNC_TNCC_SetAttribute"))
{
*function_pointer = (void*)TNC_TNCC_SetAttribute;
}
else if (streq(function_name, "TNC_TNCC_ReserveAdditionalIMCID"))
{
*function_pointer = (void*)TNC_TNCC_ReserveAdditionalIMCID;
}
else
{
return TNC_RESULT_INVALID_PARAMETER;
}
return TNC_RESULT_SUCCESS;
}
@@ -1,441 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley
* Copyright (C) 2010-2011 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 "tnc_imc_manager.h"
#include "tnc_imc.h"
#include <tncifimc.h>
#include <utils/debug.h>
#include <threading/rwlock.h>
#include <threading/mutex.h>
#include <collections/linked_list.h>
typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t;
/**
* Private data of an imc_manager_t object.
*/
struct private_tnc_imc_manager_t {
/**
* Public members of imc_manager_t.
*/
imc_manager_t public;
/**
* Linked list of IMCs
*/
linked_list_t *imcs;
/**
* Lock to access IMC list
*/
rwlock_t *lock;
/**
* Next IMC ID to be assigned
*/
TNC_IMCID next_imc_id;
/**
* Mutex to access next IMC ID
*/
mutex_t *id_mutex;
};
METHOD(imc_manager_t, add, bool,
private_tnc_imc_manager_t *this, imc_t *imc)
{
TNC_Version version;
TNC_IMCID imc_id;
this->id_mutex->lock(this->id_mutex);
imc_id = this->next_imc_id++;
this->id_mutex->unlock(this->id_mutex);
imc->set_id(imc, imc_id);
if (imc->initialize(imc_id, TNC_IFIMC_VERSION_1,
TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS)
{
DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc));
return FALSE;
}
this->lock->write_lock(this->lock);
this->imcs->insert_last(this->imcs, imc);
this->lock->unlock(this->lock);
if (imc->provide_bind_function(imc->get_id(imc),
TNC_TNCC_BindFunction) != TNC_RESULT_SUCCESS)
{
if (imc->terminate)
{
imc->terminate(imc->get_id(imc));
}
DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function",
imc->get_name(imc));
this->lock->write_lock(this->lock);
this->imcs->remove_last(this->imcs, (void**)&imc);
this->lock->unlock(this->lock);
return FALSE;
}
return TRUE;
}
METHOD(imc_manager_t, remove_, imc_t*,
private_tnc_imc_manager_t *this, TNC_IMCID id)
{
enumerator_t *enumerator;
imc_t *imc, *removed_imc = NULL;
this->lock->write_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (id == imc->get_id(imc))
{
this->imcs->remove_at(this->imcs, enumerator);
removed_imc = imc;
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return removed_imc;
}
METHOD(imc_manager_t, load, bool,
private_tnc_imc_manager_t *this, char *name, char *path)
{
imc_t *imc;
imc = tnc_imc_create(name, path);
if (!imc)
{
return FALSE;
}
if (!add(this, imc))
{
imc->destroy(imc);
return FALSE;
}
DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), name, path);
return TRUE;
}
METHOD(imc_manager_t, load_from_functions, bool,
private_tnc_imc_manager_t *this, char *name,
TNC_IMC_InitializePointer initialize,
TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
TNC_IMC_BeginHandshakePointer begin_handshake,
TNC_IMC_ReceiveMessagePointer receive_message,
TNC_IMC_ReceiveMessageLongPointer receive_message_long,
TNC_IMC_BatchEndingPointer batch_ending,
TNC_IMC_TerminatePointer terminate,
TNC_IMC_ProvideBindFunctionPointer provide_bind_function)
{
imc_t *imc;
imc = tnc_imc_create_from_functions(name,
initialize, notify_connection_change,
begin_handshake, receive_message,
receive_message_long, batch_ending,
terminate, provide_bind_function);
if (!imc)
{
return FALSE;
}
if (!add(this, imc))
{
imc->destroy(imc);
return FALSE;
}
DBG1(DBG_TNC, "IMC %u \"%s\" loaded", imc->get_id(imc), name);
return TRUE;
}
METHOD(imc_manager_t, is_registered, bool,
private_tnc_imc_manager_t *this, TNC_IMCID id)
{
enumerator_t *enumerator;
imc_t *imc;
bool found = FALSE;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (imc->has_id(imc, id))
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return found;
}
METHOD(imc_manager_t, reserve_id, bool,
private_tnc_imc_manager_t *this, TNC_IMCID id, TNC_UInt32 *new_id)
{
enumerator_t *enumerator;
imc_t *imc;
bool found = FALSE;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (id == imc->get_id(imc))
{
found = TRUE;
this->id_mutex->lock(this->id_mutex);
*new_id = this->next_imc_id++;
this->id_mutex->unlock(this->id_mutex);
imc->add_id(imc, *new_id);
DBG2(DBG_TNC, "additional ID %u reserved for IMC with primary ID %u",
*new_id, id);
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return found;
}
METHOD(imc_manager_t, get_preferred_language, char*,
private_tnc_imc_manager_t *this)
{
return lib->settings->get_str(lib->settings,
"%s.plugins.tnc-imc.preferred_language", "en", "charon");
}
METHOD(imc_manager_t, notify_connection_change, void,
private_tnc_imc_manager_t *this, TNC_ConnectionID id,
TNC_ConnectionState state)
{
enumerator_t *enumerator;
imc_t *imc;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (imc->notify_connection_change)
{
imc->notify_connection_change(imc->get_id(imc), id, state);
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
METHOD(imc_manager_t, begin_handshake, void,
private_tnc_imc_manager_t *this, TNC_ConnectionID id)
{
enumerator_t *enumerator;
imc_t *imc;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
imc->begin_handshake(imc->get_id(imc), id);
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
METHOD(imc_manager_t, set_message_types, TNC_Result,
private_tnc_imc_manager_t *this, TNC_IMCID id,
TNC_MessageTypeList supported_types,
TNC_UInt32 type_count)
{
enumerator_t *enumerator;
imc_t *imc;
TNC_Result result = TNC_RESULT_FATAL;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (id == imc->get_id(imc))
{
imc->set_message_types(imc, supported_types, type_count);
result = TNC_RESULT_SUCCESS;
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return result;
}
METHOD(imc_manager_t, set_message_types_long, TNC_Result,
private_tnc_imc_manager_t *this, TNC_IMCID id,
TNC_VendorIDList supported_vids,
TNC_MessageSubtypeList supported_subtypes,
TNC_UInt32 type_count)
{
enumerator_t *enumerator;
imc_t *imc;
TNC_Result result = TNC_RESULT_FATAL;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (id == imc->get_id(imc))
{
imc->set_message_types_long(imc, supported_vids, supported_subtypes,
type_count);
result = TNC_RESULT_SUCCESS;
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return result;
}
METHOD(imc_manager_t, receive_message, void,
private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id,
bool excl,
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)
{
bool type_supported = FALSE;
TNC_MessageType msg_type;
TNC_UInt32 msg_flags;
enumerator_t *enumerator;
imc_t *imc;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (imc->type_supported(imc, msg_vid, msg_subtype) &&
(!excl || (excl && imc->has_id(imc, dst_imc_id))))
{
if (imc->receive_message_long && src_imv_id)
{
type_supported = TRUE;
msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
imc->receive_message_long(imc->get_id(imc), connection_id,
msg_flags, msg, msg_len, msg_vid, msg_subtype,
src_imv_id, dst_imc_id);
}
else if (imc->receive_message && msg_vid <= TNC_VENDORID_ANY &&
msg_subtype <= TNC_SUBTYPE_ANY)
{
type_supported = TRUE;
msg_type = (msg_vid << 8) | msg_subtype;
imc->receive_message(imc->get_id(imc), connection_id,
msg, msg_len, msg_type);
}
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
if (!type_supported)
{
DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMC",
msg_vid, msg_subtype);
}
}
METHOD(imc_manager_t, batch_ending, void,
private_tnc_imc_manager_t *this, TNC_ConnectionID id)
{
enumerator_t *enumerator;
imc_t *imc;
this->lock->read_lock(this->lock);
enumerator = this->imcs->create_enumerator(this->imcs);
while (enumerator->enumerate(enumerator, &imc))
{
if (imc->batch_ending)
{
imc->batch_ending(imc->get_id(imc), id);
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
METHOD(imc_manager_t, destroy, void,
private_tnc_imc_manager_t *this)
{
imc_t *imc;
while (this->imcs->remove_last(this->imcs, (void**)&imc) == SUCCESS)
{
if (imc->terminate &&
imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
{
DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
imc->get_name(imc));
}
imc->destroy(imc);
}
this->imcs->destroy(this->imcs);
this->lock->destroy(this->lock);
this->id_mutex->destroy(this->id_mutex);
free(this);
}
/**
* Described in header.
*/
imc_manager_t* tnc_imc_manager_create(void)
{
private_tnc_imc_manager_t *this;
INIT(this,
.public = {
.add = _add,
.remove = _remove_, /* avoid name conflict with stdio.h */
.load = _load,
.load_from_functions = _load_from_functions,
.is_registered = _is_registered,
.reserve_id = _reserve_id,
.get_preferred_language = _get_preferred_language,
.notify_connection_change = _notify_connection_change,
.begin_handshake = _begin_handshake,
.set_message_types = _set_message_types,
.set_message_types_long = _set_message_types_long,
.receive_message = _receive_message,
.batch_ending = _batch_ending,
.destroy = _destroy,
},
.imcs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.id_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.next_imc_id = 1,
);
return &this->public;
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2010 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 tnc_imc_manager tnc_imc_manager
* @{ @ingroup tnc_imc
*/
#ifndef TNC_IMC_MANAGER_H_
#define TNC_IMC_MANAGER_H_
#include <tnc/imc/imc_manager.h>
/**
* Create an IMC manager instance.
*/
imc_manager_t *tnc_imc_manager_create();
#endif /** TNC_IMC_MANAGER_H_ @}*/
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2010-2011 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 "tnc_imc_plugin.h"
#include "tnc_imc_manager.h"
#include <tnc/tnc.h>
typedef struct private_tnc_imc_plugin_t private_tnc_imc_plugin_t;
/**
* Private data of a tnc_imc_plugin_t object.
*/
struct private_tnc_imc_plugin_t {
/**
* Public interface.
*/
tnc_imc_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
private_tnc_imc_plugin_t *this)
{
return "tnc-imc";
}
METHOD(plugin_t, get_features, int,
private_tnc_imc_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
private_tnc_imc_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *tnc_imc_plugin_create(void)
{
private_tnc_imc_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
);
return &this->public.plugin;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010 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 tnc_imc tnc_imc
* @ingroup cplugins
*
* @defgroup tnc_imc_plugin tnc_imc_plugin
* @{ @ingroup tnc_imc
*/
#ifndef TNC_IMC_PLUGIN_H_
#define TNC_IMC_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct tnc_imc_plugin_t tnc_imc_plugin_t;
/**
* TNC IMC plugin
*/
struct tnc_imc_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** TNC_IMC_PLUGIN_H_ @}*/
@@ -1,23 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
-rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la
else
plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la
libstrongswan_tnc_tnccs_la_LIBADD = \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libtnccs/libtnccs.la
endif
libstrongswan_tnc_tnccs_la_SOURCES = \
tnc_tnccs_plugin.h tnc_tnccs_plugin.c \
tnc_tnccs_manager.h tnc_tnccs_manager.c
libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version
@@ -1,866 +0,0 @@
/*
* Copyright (C) 2010-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.
*/
#define _GNU_SOURCE /* for asprintf() */
#include "tnc_tnccs_manager.h"
#include <tnc/tnc.h>
#include <tnc/imv/imv_manager.h>
#include <tnc/imc/imc_manager.h>
#include <tnc/imv/imv_manager.h>
#include <tncif_identity.h>
#include <tls.h>
#include <utils/debug.h>
#include <pen/pen.h>
#include <bio/bio_writer.h>
#include <collections/linked_list.h>
#include <threading/rwlock.h>
#include <stdio.h>
typedef struct private_tnc_tnccs_manager_t private_tnc_tnccs_manager_t;
typedef struct tnccs_entry_t tnccs_entry_t;
typedef struct tnccs_connection_entry_t tnccs_connection_entry_t;
/**
* TNCCS constructor entry
*/
struct tnccs_entry_t {
/**
* TNCCS protocol type
*/
tnccs_type_t type;
/**
* constructor function to create instance
*/
tnccs_constructor_t constructor;
};
/**
* TNCCS connection entry
*/
struct tnccs_connection_entry_t {
/**
* TNCCS connection ID
*/
TNC_ConnectionID id;
/**
* TNCCS protocol type
*/
tnccs_type_t type;
/**
* TNCCS instance
*/
tnccs_t *tnccs;
/**
* TNCCS send message function
*/
tnccs_send_message_t send_message;
/**
* TNCCS request handshake retry flag
*/
bool *request_handshake_retry;
/**
* Maximum size of a PA-TNC message
*/
u_int32_t max_msg_len;
/**
* collection of IMV recommendations
*/
recommendations_t *recs;
};
/**
* private data of tnc_tnccs_manager
*/
struct private_tnc_tnccs_manager_t {
/**
* public functions
*/
tnccs_manager_t public;
/**
* list of TNCCS protocol entries
*/
linked_list_t *protocols;
/**
* rwlock to lock the TNCCS protocol entries
*/
rwlock_t *protocol_lock;
/**
* connection ID counter
*/
TNC_ConnectionID connection_id;
/**
* list of TNCCS connection entries
*/
linked_list_t *connections;
/**
* rwlock to lock TNCCS connection entries
*/
rwlock_t *connection_lock;
};
METHOD(tnccs_manager_t, add_method, void,
private_tnc_tnccs_manager_t *this, tnccs_type_t type,
tnccs_constructor_t constructor)
{
tnccs_entry_t *entry;
entry = malloc_thing(tnccs_entry_t);
entry->type = type;
entry->constructor = constructor;
this->protocol_lock->write_lock(this->protocol_lock);
this->protocols->insert_last(this->protocols, entry);
this->protocol_lock->unlock(this->protocol_lock);
}
METHOD(tnccs_manager_t, remove_method, void,
private_tnc_tnccs_manager_t *this, tnccs_constructor_t constructor)
{
enumerator_t *enumerator;
tnccs_entry_t *entry;
this->protocol_lock->write_lock(this->protocol_lock);
enumerator = this->protocols->create_enumerator(this->protocols);
while (enumerator->enumerate(enumerator, &entry))
{
if (constructor == entry->constructor)
{
this->protocols->remove_at(this->protocols, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->protocol_lock->unlock(this->protocol_lock);
}
METHOD(tnccs_manager_t, create_instance, tnccs_t*,
private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server,
identification_t *server, identification_t *peer,
tnc_ift_type_t transport)
{
enumerator_t *enumerator;
tnccs_entry_t *entry;
tnccs_t *protocol = NULL;
this->protocol_lock->read_lock(this->protocol_lock);
enumerator = this->protocols->create_enumerator(this->protocols);
while (enumerator->enumerate(enumerator, &entry))
{
if (type == entry->type)
{
protocol = entry->constructor(is_server, server, peer, transport);
if (protocol)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->protocol_lock->unlock(this->protocol_lock);
return protocol;
}
METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
private_tnc_tnccs_manager_t *this, tnccs_type_t type, tnccs_t *tnccs,
tnccs_send_message_t send_message, bool* request_handshake_retry,
u_int32_t max_msg_len, recommendations_t **recs)
{
tnccs_connection_entry_t *entry;
entry = malloc_thing(tnccs_connection_entry_t);
entry->type = type;
entry->tnccs = tnccs;
entry->send_message = send_message;
entry->request_handshake_retry = request_handshake_retry;
entry->max_msg_len = max_msg_len;
if (recs)
{
/* we assume a TNC Server needing recommendations from IMVs */
if (!tnc->imvs)
{
DBG1(DBG_TNC, "no IMV manager available!");
free(entry);
return 0;
}
entry->recs = tnc->imvs->create_recommendations(tnc->imvs);
*recs = entry->recs;
}
else
{
/* we assume a TNC Client */
if (!tnc->imcs)
{
DBG1(DBG_TNC, "no IMC manager available!");
free(entry);
return 0;
}
entry->recs = NULL;
}
this->connection_lock->write_lock(this->connection_lock);
entry->id = ++this->connection_id;
this->connections->insert_last(this->connections, entry);
this->connection_lock->unlock(this->connection_lock);
DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
return entry->id;
}
METHOD(tnccs_manager_t, remove_connection, void,
private_tnc_tnccs_manager_t *this, TNC_ConnectionID id, bool is_server)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
if (is_server)
{
if (tnc->imvs)
{
tnc->imvs->notify_connection_change(tnc->imvs, id,
TNC_CONNECTION_STATE_DELETE);
}
}
else
{
if (tnc->imcs)
{
tnc->imcs->notify_connection_change(tnc->imcs, id,
TNC_CONNECTION_STATE_DELETE);
}
}
this->connection_lock->write_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == entry->id)
{
this->connections->remove_at(this->connections, enumerator);
if (entry->recs)
{
entry->recs->destroy(entry->recs);
}
free(entry);
DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
}
METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result,
private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id,
TNC_ConnectionID id,
TNC_RetryReason reason)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
if (id == TNC_CONNECTIONID_ANY)
{
DBG2(DBG_TNC, "%s %u requests handshake retry for all connections "
"(reason: %u)", is_imc ? "IMC":"IMV", reason);
}
else
{
DBG2(DBG_TNC, "%s %u requests handshake retry for Connection ID %u "
"(reason: %u)", is_imc ? "IMC":"IMV", imcv_id, id, reason);
}
this->connection_lock->read_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == TNC_CONNECTIONID_ANY || id == entry->id)
{
*entry->request_handshake_retry = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
return TNC_RESULT_SUCCESS;
}
METHOD(tnccs_manager_t, send_message, TNC_Result,
private_tnc_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_ConnectionID id,
TNC_UInt32 msg_flags,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
TNC_VendorID msg_vid,
TNC_MessageSubtype msg_subtype)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
tnccs_send_message_t send_message = NULL;
tnccs_t *tnccs = NULL;
if (msg_vid == TNC_VENDORID_ANY || msg_subtype == TNC_SUBTYPE_ANY)
{
DBG1(DBG_TNC, "not sending message of invalid type 0x%02x/0x%08x",
msg_vid, msg_subtype);
return TNC_RESULT_INVALID_PARAMETER;
}
this->connection_lock->read_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == entry->id)
{
tnccs = entry->tnccs;
send_message = entry->send_message;
break;
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
if (tnccs && send_message)
{
return send_message(tnccs, imc_id, imv_id, msg_flags, msg, msg_len,
msg_vid, msg_subtype);
}
return TNC_RESULT_FATAL;
}
METHOD(tnccs_manager_t, provide_recommendation, TNC_Result,
private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id,
TNC_ConnectionID id,
TNC_IMV_Action_Recommendation rec,
TNC_IMV_Evaluation_Result eval)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
recommendations_t *recs = NULL;
this->connection_lock->read_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == entry->id)
{
recs = entry->recs;
break;
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
if (recs)
{
recs->provide_recommendation(recs, imv_id, rec, eval);
return TNC_RESULT_SUCCESS;
}
return TNC_RESULT_FATAL;
}
/**
* Write the value of a boolean attribute into the buffer
*/
static TNC_Result bool_attribute(TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *value_len,
bool value)
{
*value_len = 1;
if (buffer && buffer_len > 0)
{
*buffer = value ? 0x01 : 0x00;
return TNC_RESULT_SUCCESS;
}
else
{
return TNC_RESULT_INVALID_PARAMETER;
}
}
/**
* Write the value of an u_int32_t attribute into the buffer
*/
static TNC_Result uint_attribute(TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *value_len,
u_int32_t value)
{
*value_len = sizeof(u_int32_t);
if (buffer && buffer_len >= *value_len)
{
htoun32(buffer, value);
return TNC_RESULT_SUCCESS;
}
else
{
return TNC_RESULT_INVALID_PARAMETER;
}
}
/**
* Write the value of string attribute into the buffer
*/
static TNC_Result str_attribute(TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *value_len,
char *value)
{
*value_len = 1 + strlen(value);
if (buffer && buffer_len >= *value_len)
{
snprintf(buffer, buffer_len, "%s", value);
return TNC_RESULT_SUCCESS;
}
else
{
return TNC_RESULT_INVALID_PARAMETER;
}
}
/**
* Write the value of a TNC identity list into the buffer
*/
static TNC_Result identity_attribute(TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *value_len,
linked_list_t *list)
{
bio_writer_t *writer;
enumerator_t *enumerator;
u_int32_t count;
chunk_t value;
tncif_identity_t *tnc_id;
TNC_Result result = TNC_RESULT_INVALID_PARAMETER;
count = list->get_count(list);
writer = bio_writer_create(4 + TNCIF_IDENTITY_MIN_SIZE * count);
writer->write_uint32(writer, count);
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &tnc_id))
{
tnc_id->build(tnc_id, writer);
}
enumerator->destroy(enumerator);
value = writer->get_buf(writer);
*value_len = value.len;
if (buffer && buffer_len >= value.len)
{
memcpy(buffer, value.ptr, value.len);
result = TNC_RESULT_SUCCESS;
}
writer->destroy(writer);
return result;
}
METHOD(tnccs_manager_t, get_attribute, TNC_Result,
private_tnc_tnccs_manager_t *this, bool is_imc,
TNC_UInt32 imcv_id,
TNC_ConnectionID id,
TNC_AttributeID attribute_id,
TNC_UInt32 buffer_len,
TNC_BufferReference buffer,
TNC_UInt32 *value_len)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
bool attribute_match = FALSE, entry_found = FALSE;
if (is_imc)
{
switch (attribute_id)
{
/* these attributes are unsupported */
case TNC_ATTRIBUTEID_SOHR:
case TNC_ATTRIBUTEID_SSOHR:
return TNC_RESULT_INVALID_PARAMETER;
/* these attributes are supported */
case TNC_ATTRIBUTEID_PRIMARY_IMC_ID:
attribute_match = TRUE;
break;
/* these attributes are yet to be matched */
default:
break;
}
}
else
{
switch (attribute_id)
{
/* these attributes are unsupported or invalid */
case TNC_ATTRIBUTEID_REASON_STRING:
case TNC_ATTRIBUTEID_REASON_LANGUAGE:
case TNC_ATTRIBUTEID_SOH:
case TNC_ATTRIBUTEID_SSOH:
return TNC_RESULT_INVALID_PARAMETER;
/* these attributes are supported */
case TNC_ATTRIBUTEID_PRIMARY_IMV_ID:
case TNC_ATTRIBUTEID_AR_IDENTITIES:
attribute_match = TRUE;
break;
/* these attributes are yet to be matched */
default:
break;
}
}
if (!attribute_match)
{
switch (attribute_id)
{
/* these attributes are supported */
case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE:
case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS:
case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE:
case TNC_ATTRIBUTEID_HAS_LONG_TYPES:
case TNC_ATTRIBUTEID_HAS_EXCLUSIVE:
case TNC_ATTRIBUTEID_HAS_SOH:
case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL:
case TNC_ATTRIBUTEID_IFTNCCS_VERSION:
case TNC_ATTRIBUTEID_IFT_PROTOCOL:
case TNC_ATTRIBUTEID_IFT_VERSION:
break;
/* these attributes are unsupported or unknown */
case TNC_ATTRIBUTEID_DHPN:
case TNC_ATTRIBUTEID_TLS_UNIQUE:
default:
return TNC_RESULT_INVALID_PARAMETER;
}
}
/* attributes specific to the TNCC or TNCS are unsupported */
if (id == TNC_CONNECTIONID_ANY)
{
return TNC_RESULT_INVALID_PARAMETER;
}
this->connection_lock->read_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == entry->id)
{
entry_found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
if (!entry_found)
{
return TNC_RESULT_INVALID_PARAMETER;
}
switch (attribute_id)
{
case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE:
{
recommendations_t *recs;
chunk_t pref_lang;
recs = entry->recs;
if (!recs)
{
return TNC_RESULT_INVALID_PARAMETER;
}
pref_lang = recs->get_preferred_language(recs);
if (pref_lang.len == 0)
{
return TNC_RESULT_INVALID_PARAMETER;
}
*value_len = pref_lang.len;
if (buffer && buffer_len >= pref_lang.len)
{
memcpy(buffer, pref_lang.ptr, pref_lang.len);
}
return TNC_RESULT_SUCCESS;
}
case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS:
return uint_attribute(buffer_len, buffer, value_len,
0xffffffff);
case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE:
return uint_attribute(buffer_len, buffer, value_len,
entry->max_msg_len);
case TNC_ATTRIBUTEID_HAS_LONG_TYPES:
case TNC_ATTRIBUTEID_HAS_EXCLUSIVE:
return bool_attribute(buffer_len, buffer, value_len,
entry->type == TNCCS_2_0);
case TNC_ATTRIBUTEID_HAS_SOH:
return bool_attribute(buffer_len, buffer, value_len,
entry->type == TNCCS_SOH);
case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL:
{
char *protocol;
switch (entry->type)
{
case TNCCS_1_1:
case TNCCS_2_0:
protocol = "IF-TNCCS";
break;
case TNCCS_SOH:
protocol = "IF-TNCCS-SOH";
break;
default:
return TNC_RESULT_INVALID_PARAMETER;
}
return str_attribute(buffer_len, buffer, value_len, protocol);
}
case TNC_ATTRIBUTEID_IFTNCCS_VERSION:
{
char *version;
switch (entry->type)
{
case TNCCS_1_1:
version = "1.1";
break;
case TNCCS_2_0:
version = "2.0";
break;
case TNCCS_SOH:
version = "1.0";
break;
default:
return TNC_RESULT_INVALID_PARAMETER;
}
return str_attribute(buffer_len, buffer, value_len, version);
}
case TNC_ATTRIBUTEID_IFT_PROTOCOL:
{
char *protocol;
switch (entry->tnccs->get_transport(entry->tnccs))
{
case TNC_IFT_EAP_1_0:
case TNC_IFT_EAP_1_1:
case TNC_IFT_EAP_2_0:
protocol = "IF-T for Tunneled EAP";
break;
case TNC_IFT_TLS_1_0:
case TNC_IFT_TLS_2_0:
protocol = "IF-T for TLS";
break;
default:
return TNC_RESULT_INVALID_PARAMETER;
}
return str_attribute(buffer_len, buffer, value_len, protocol);
}
case TNC_ATTRIBUTEID_IFT_VERSION:
{
char *version;
switch (entry->tnccs->get_transport(entry->tnccs))
{
case TNC_IFT_EAP_1_0:
case TNC_IFT_TLS_1_0:
version = "1.0";
break;
case TNC_IFT_EAP_1_1:
version = "1.1";
break;
case TNC_IFT_EAP_2_0:
case TNC_IFT_TLS_2_0:
version = "2.0";
break;
default:
return TNC_RESULT_INVALID_PARAMETER;
}
return str_attribute(buffer_len, buffer, value_len, version);
}
case TNC_ATTRIBUTEID_AR_IDENTITIES:
{
linked_list_t *list;
identification_t *peer;
tnccs_t *tnccs;
tncif_identity_t *tnc_id;
u_int32_t id_type, subject_type;
chunk_t id_value;
char *id_str;
TNC_Result result;
list = linked_list_create();
tnccs = entry->tnccs;
peer = tnccs->tls.get_peer_id(&tnccs->tls);
if (peer)
{
switch (peer->get_type(peer))
{
case ID_IPV4_ADDR:
id_type = TNC_ID_IPV4_ADDR;
subject_type = TNC_SUBJECT_MACHINE;
break;
case ID_IPV6_ADDR:
id_type = TNC_ID_IPV6_ADDR;
subject_type = TNC_SUBJECT_MACHINE;
break;
case ID_FQDN:
id_type = TNC_ID_USERNAME;
subject_type = TNC_SUBJECT_USER;
break;
case ID_RFC822_ADDR:
id_type = TNC_ID_EMAIL_ADDR;
subject_type = TNC_SUBJECT_USER;
break;
case ID_DER_ASN1_DN:
id_type = TNC_ID_X500_DN;
subject_type = TNC_SUBJECT_USER;
break;
default:
id_type = TNC_ID_UNKNOWN;
subject_type = TNC_SUBJECT_UNKNOWN;
}
if (id_type != TNC_ID_UNKNOWN &&
asprintf(&id_str, "%Y", peer) >= 0)
{
id_value = chunk_from_str(id_str);
tnc_id = tncif_identity_create(
pen_type_create(PEN_TCG, id_type), id_value,
pen_type_create(PEN_TCG, subject_type),
pen_type_create(PEN_TCG,
tnccs->get_auth_type(tnccs)));
list->insert_last(list, tnc_id);
}
}
result = identity_attribute(buffer_len, buffer, value_len, list);
list->destroy_offset(list, offsetof(tncif_identity_t, destroy));
return result;
}
default:
return TNC_RESULT_INVALID_PARAMETER;
}
}
METHOD(tnccs_manager_t, set_attribute, TNC_Result,
private_tnc_tnccs_manager_t *this, bool is_imc,
TNC_UInt32 imcv_id,
TNC_ConnectionID id,
TNC_AttributeID attribute_id,
TNC_UInt32 buffer_len,
TNC_BufferReference buffer)
{
enumerator_t *enumerator;
tnccs_connection_entry_t *entry;
recommendations_t *recs = NULL;
if (is_imc || id == TNC_CONNECTIONID_ANY ||
(attribute_id != TNC_ATTRIBUTEID_REASON_STRING &&
attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE))
{
return TNC_RESULT_INVALID_PARAMETER;
}
this->connection_lock->read_lock(this->connection_lock);
enumerator = this->connections->create_enumerator(this->connections);
while (enumerator->enumerate(enumerator, &entry))
{
if (id == entry->id)
{
recs = entry->recs;
break;
}
}
enumerator->destroy(enumerator);
this->connection_lock->unlock(this->connection_lock);
if (recs)
{
chunk_t attribute = { buffer, buffer_len };
if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING)
{
return recs->set_reason_string(recs, imcv_id, attribute);
}
else
{
return recs->set_reason_language(recs, imcv_id, attribute);
}
}
return TNC_RESULT_INVALID_PARAMETER;
}
METHOD(tnccs_manager_t, destroy, void,
private_tnc_tnccs_manager_t *this)
{
this->protocols->destroy_function(this->protocols, free);
this->protocol_lock->destroy(this->protocol_lock);
this->connections->destroy_function(this->connections, free);
this->connection_lock->destroy(this->connection_lock);
free(this);
}
/*
* See header
*/
tnccs_manager_t *tnc_tnccs_manager_create()
{
private_tnc_tnccs_manager_t *this;
INIT(this,
.public = {
.add_method = _add_method,
.remove_method = _remove_method,
.create_instance = _create_instance,
.create_connection = _create_connection,
.remove_connection = _remove_connection,
.request_handshake_retry = _request_handshake_retry,
.send_message = _send_message,
.provide_recommendation = _provide_recommendation,
.get_attribute = _get_attribute,
.set_attribute = _set_attribute,
.destroy = _destroy,
},
.protocols = linked_list_create(),
.connections = linked_list_create(),
.protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
return &this->public;
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2010 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 tnc_tnccs_manager tnc_tnccs_manager
* @{ @ingroup tnc_tnccs
*/
#ifndef TNC_TNCCS_MANAGER_H_
#define TNC_TNCCS_MANAGER_H_
#include <tnc/tnccs/tnccs_manager.h>
/**
* Create a TNCCS manager instance.
*/
tnccs_manager_t *tnc_tnccs_manager_create();
#endif /** TNC_TNCCS_MANAGER_H_ @}*/
@@ -1,98 +0,0 @@
/*
* Copyright (C) 2010 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 "tnc_tnccs_plugin.h"
#include "tnc_tnccs_manager.h"
#include <tnc/tnc.h>
#include <utils/debug.h>
typedef struct private_tnc_tnccs_plugin_t private_tnc_tnccs_plugin_t;
/**
* Private data of a tnc_tnccs_plugin_t object.
*/
struct private_tnc_tnccs_plugin_t {
/**
* Public interface.
*/
tnc_tnccs_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
private_tnc_tnccs_plugin_t *this)
{
return "tnc-tnccs";
}
METHOD(plugin_t, get_features, int,
private_tnc_tnccs_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnc_manager_register, tnc_tnccs_manager_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-manager"),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
private_tnc_tnccs_plugin_t *this)
{
libtnccs_deinit();
free(this);
}
/*
* see header file
*/
plugin_t *tnc_tnccs_plugin_create(void)
{
private_tnc_tnccs_plugin_t *this;
if (lib->integrity)
{
if (lib->integrity->check(lib->integrity, "libtnccs", libtnccs_init))
{
DBG1(DBG_LIB,
"lib 'libtnccs': passed file and segment integrity tests");
}
else
{
DBG1(DBG_LIB,
"lib 'libtnccs': failed integrity tests");
return NULL;
}
}
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
);
libtnccs_init();
return &this->public.plugin;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010 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 tnc_tnccs tnc_tnccs
* @ingroup cplugins
*
* @defgroup tnc_tnccs_plugin tnc_tnccs_plugin
* @{ @ingroup tnc_tnccs
*/
#ifndef TNC_TNCCS_PLUGIN_H_
#define TNC_TNCCS_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct tnc_tnccs_plugin_t tnc_tnccs_plugin_t;
/**
* TNCCS manager plugin
*/
struct tnc_tnccs_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** TNC_TNCCS_PLUGIN_H_ @}*/
@@ -1,35 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
${xml_CFLAGS} \
-rdynamic
libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS}
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
else
plugin_LTLIBRARIES = libstrongswan-tnccs-11.la
libstrongswan_tnccs_11_la_LIBADD += \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libtnccs/libtnccs.la
endif
libstrongswan_tnccs_11_la_SOURCES = \
tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \
batch/tnccs_batch.h batch/tnccs_batch.c \
messages/tnccs_msg.h messages/tnccs_msg.c \
messages/imc_imv_msg.h messages/imc_imv_msg.c \
messages/tnccs_error_msg.h messages/tnccs_error_msg.c \
messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \
messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \
messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \
messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c
libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version
@@ -1,325 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_batch.h"
#include "messages/tnccs_error_msg.h"
#include <tnc/tnccs/tnccs.h>
#include <collections/linked_list.h>
#include <utils/debug.h>
#include <libxml/parser.h>
#define TNCCS_NS "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#"
#define SCHEMA_NS "http://www.w3.org/2001/XMLSchema-instance"
#define TNCCS_XSD "https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd"
typedef struct private_tnccs_batch_t private_tnccs_batch_t;
/**
* Private data of a tnccs_batch_t object.
*
*/
struct private_tnccs_batch_t {
/**
* Public tnccs_batch_t interface.
*/
tnccs_batch_t public;
/**
* Batch ID
*/
int batch_id;
/**
* TNCC if TRUE, TNCS if FALSE
*/
bool is_server;
/**
* linked list of TNCCS messages
*/
linked_list_t *messages;
/**
* linked list of TNCCS error messages
*/
linked_list_t *errors;
/**
* XML document
*/
xmlDocPtr doc;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(tnccs_batch_t, get_encoding, chunk_t,
private_tnccs_batch_t *this)
{
return this->encoding;
}
METHOD(tnccs_batch_t, add_msg, void,
private_tnccs_batch_t *this, tnccs_msg_t* msg)
{
xmlNodePtr root;
DBG2(DBG_TNC, "adding %N message", tnccs_msg_type_names,
msg->get_type(msg));
this->messages->insert_last(this->messages, msg);
root = xmlDocGetRootElement(this->doc);
xmlAddChild(root, msg->get_node(msg));
}
METHOD(tnccs_batch_t, build, void,
private_tnccs_batch_t *this)
{
xmlChar *xmlbuf;
int buf_size;
xmlDocDumpFormatMemory(this->doc, &xmlbuf, &buf_size, 1);
this->encoding = chunk_create(xmlbuf, buf_size);
this->encoding = chunk_clone(this->encoding);
xmlFree(xmlbuf);
}
METHOD(tnccs_batch_t, process, status_t,
private_tnccs_batch_t *this)
{
tnccs_msg_t *tnccs_msg, *msg;
tnccs_error_type_t error_type = TNCCS_ERROR_OTHER;
char *error_msg, buf[BUF_LEN];
xmlNodePtr cur;
xmlNsPtr ns;
xmlChar *batchid, *recipient;
int batch_id;
this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len);
if (!this->doc)
{
error_type = TNCCS_ERROR_MALFORMED_BATCH;
error_msg = "failed to parse XML message";
goto fatal;
}
/* check out the XML document */
cur = xmlDocGetRootElement(this->doc);
if (!cur)
{
error_type = TNCCS_ERROR_MALFORMED_BATCH;
error_msg = "empty XML document";
goto fatal;
}
/* check TNCCS namespace */
ns = xmlSearchNsByHref(this->doc, cur, TNCCS_NS);
if (!ns)
{
error_type = TNCCS_ERROR_MALFORMED_BATCH;
error_msg = "TNCCS namespace not found";
goto fatal;
}
/* check XML document type */
if (xmlStrcmp(cur->name, "TNCCS-Batch"))
{
error_type = TNCCS_ERROR_MALFORMED_BATCH;
error_msg = buf;
snprintf(buf, BUF_LEN, "wrong XML document type '%s', expected TNCCS-Batch",
cur->name);
goto fatal;
}
/* check presence of BatchID property */
batchid = xmlGetProp(cur, "BatchId");
if (!batchid)
{
error_type = TNCCS_ERROR_INVALID_BATCH_ID;
error_msg = "BatchId is missing";
goto fatal;
}
/* check BatchID */
batch_id = atoi((char*)batchid);
xmlFree(batchid);
if (batch_id != this->batch_id)
{
error_type = TNCCS_ERROR_INVALID_BATCH_ID;
error_msg = buf;
snprintf(buf, BUF_LEN, "BatchId %d expected, got %d", this->batch_id,
batch_id);
goto fatal;
}
/* check presence of Recipient property */
recipient = xmlGetProp(cur, "Recipient");
if (!recipient)
{
error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
error_msg = "Recipient is missing";
goto fatal;
}
/* check recipient */
if (!streq(recipient, this->is_server ? "TNCS" : "TNCC"))
{
error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
error_msg = buf;
snprintf(buf, BUF_LEN, "message recipient expected '%s', got '%s'",
this->is_server ? "TNCS" : "TNCC", recipient);
xmlFree(recipient);
goto fatal;
}
xmlFree(recipient);
DBG2(DBG_TNC, "processing TNCCS Batch #%d", batch_id);
/* Now walk the tree, handling message nodes as we go */
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
{
/* ignore empty or blank nodes */
if (xmlIsBlankNode(cur))
{
continue;
}
/* ignore nodes with wrong namespace */
if (cur->ns != ns)
{
DBG1(DBG_TNC, "ignoring message node '%s' having wrong namespace",
cur->name);
continue;
}
tnccs_msg = tnccs_msg_create_from_node(cur, this->errors);
/* exit if a message parsing error occurred */
if (this->errors->get_count(this->errors) > 0)
{
return FAILED;
}
/* ignore unrecognized messages */
if (!tnccs_msg)
{
continue;
}
this->messages->insert_last(this->messages, tnccs_msg);
}
return SUCCESS;
fatal:
msg = tnccs_error_msg_create(error_type, error_msg);
this->errors->insert_last(this->errors, msg);
return FAILED;
}
METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*,
private_tnccs_batch_t *this)
{
return this->messages->create_enumerator(this->messages);
}
METHOD(tnccs_batch_t, create_error_enumerator, enumerator_t*,
private_tnccs_batch_t *this)
{
return this->errors->create_enumerator(this->errors);
}
METHOD(tnccs_batch_t, destroy, void,
private_tnccs_batch_t *this)
{
this->messages->destroy_offset(this->messages,
offsetof(tnccs_msg_t, destroy));
this->errors->destroy_offset(this->errors,
offsetof(tnccs_msg_t, destroy));
xmlFreeDoc(this->doc);
free(this->encoding.ptr);
free(this);
}
/**
* See header
*/
tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id)
{
private_tnccs_batch_t *this;
xmlNodePtr n;
xmlNsPtr ns_xsi;
char buf[12];
INIT(this,
.public = {
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
.is_server = is_server,
.messages = linked_list_create(),
.errors = linked_list_create(),
.batch_id = batch_id,
.doc = xmlNewDoc("1.0"),
);
DBG2(DBG_TNC, "creating TNCCS Batch #%d", this->batch_id);
n = xmlNewNode(NULL, "TNCCS-Batch");
xmlNewNs(n, TNCCS_NS, NULL);
ns_xsi = xmlNewNs(n, SCHEMA_NS, "xsi");
snprintf(buf, sizeof(buf), "%d", batch_id);
xmlNewProp(n, "BatchId", buf);
xmlNewProp(n, "Recipient", this->is_server ? "TNCC" : "TNCS");
xmlNewNsProp(n, ns_xsi, "schemaLocation", TNCCS_NS " " TNCCS_XSD);
xmlDocSetRootElement(this->doc, n);
return &this->public;
}
/**
* See header
*/
tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, chunk_t data)
{
private_tnccs_batch_t *this;
INIT(this,
.public = {
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
.is_server = is_server,
.batch_id = batch_id,
.messages = linked_list_create(),
.errors = linked_list_create(),
.encoding = chunk_clone(data),
);
return &this->public;
}
@@ -1,100 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_batch tnccs_batch
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_BATCH_H_
#define TNCCS_BATCH_H_
typedef enum tnccs_batch_type_t tnccs_batch_type_t;
typedef struct tnccs_batch_t tnccs_batch_t;
#include "messages/tnccs_msg.h"
#include <library.h>
/**
* Interface for a TNCCS 1.x Batch.
*/
struct tnccs_batch_t {
/**
* Get the encoding of the TNCCS 1.x Batch
*
* @return encoded TNCCS 1.x batch
*/
chunk_t (*get_encoding)(tnccs_batch_t *this);
/**
* Add TNCCS message
*
* @param msg TNCCS message to be addedd
*/
void (*add_msg)(tnccs_batch_t *this, tnccs_msg_t* msg);
/**
* Build the TNCCS 1.x Batch
*/
void (*build)(tnccs_batch_t *this);
/**
* Process the TNCCS 1.x Batch
*
* @return return processing status
*/
status_t (*process)(tnccs_batch_t *this);
/**
* Enumerates over all TNCCS Messages
*
* @return return message enumerator
*/
enumerator_t* (*create_msg_enumerator)(tnccs_batch_t *this);
/**
* Enumerates over all parsing errors
*
* @return return error enumerator
*/
enumerator_t* (*create_error_enumerator)(tnccs_batch_t *this);
/**
* Destroys a tnccs_batch_t object.
*/
void (*destroy)(tnccs_batch_t *this);
};
/**
* Create an empty TNCCS 1.x Batch
*
* @param is_server TRUE if server, FALSE if client
* @param batch_id number of the batch to be sent
*/
tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id);
/**
* Create an unprocessed TNCCS 1.x Batch from data
*
* @param is_server TRUE if server, FALSE if client
* @param batch_id current Batch ID
* @param data encoded PB-TNC batch
*/
tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id,
chunk_t data);
#endif /** TNCCS_BATCH_H_ @}*/
@@ -1,243 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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_imv_msg.h"
#include <tnc/tnccs/tnccs.h>
#include <utils/lexparser.h>
#include <utils/debug.h>
typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
#define BYTES_PER_LINE 57
/**
* Private data of a imc_imv_msg_t object.
*
*/
struct private_imc_imv_msg_t {
/**
* Public imc_imv_msg_t interface.
*/
imc_imv_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
/**
* IMC-IMV message type
*/
TNC_MessageType msg_type;
/**
* IMC-IMV message body
*/
chunk_t msg_body;
};
/**
* Encodes message data into multiple base64-encoded lines
*/
static chunk_t encode_base64(chunk_t data)
{
chunk_t encoding;
u_char *pos;
size_t b64_chars, b64_lines;
/* handle empty message data object */
if (data.len == 0)
{
encoding = chunk_alloc(1);
*encoding.ptr = '\0';
return encoding;
}
/* compute and allocate maximum size of base64 object */
b64_chars = 4 * ((data.len + 2) / 3);
b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
encoding = chunk_alloc(b64_chars + b64_lines);
pos = encoding.ptr;
/* encode lines */
while (b64_lines--)
{
chunk_t data_line, b64_line;
data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE));
data.ptr += data_line.len;
data.len -= data_line.len;
b64_line = chunk_to_base64(data_line, pos);
pos += b64_line.len;
*pos = '\n';
pos++;
}
/* terminate last line with NULL character instead of newline */
*(pos-1) = '\0';
return encoding;
}
/**
* Decodes message data from multiple base64-encoded lines
*/
static chunk_t decode_base64(chunk_t data)
{
chunk_t decoding, data_line, b64_line;
u_char *pos;
/* compute and allocate maximum size of decoded message data */
decoding = chunk_alloc(3 * ((data.len + 3) / 4));
pos = decoding.ptr;
decoding.len = 0;
while (fetchline(&data, &b64_line))
{
data_line = chunk_from_base64(b64_line, pos);
pos += data_line.len;
decoding.len += data_line.len;
}
return decoding;
}
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_imc_imv_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_imc_imv_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, destroy, void,
private_imc_imv_msg_t *this)
{
free(this->msg_body.ptr);
free(this);
}
METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType,
private_imc_imv_msg_t *this)
{
return this->msg_type;
}
METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
private_imc_imv_msg_t *this)
{
return this->msg_body;
}
/**
* See header
*/
tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
{
private_imc_imv_msg_t *this;
xmlNsPtr ns;
xmlNodePtr cur;
xmlChar *content;
chunk_t b64_body;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_msg_type = _get_msg_type,
.get_msg_body = _get_msg_body,
},
.type = IMC_IMV_MSG,
.node = node,
);
ns = node->ns;
cur = node->xmlChildrenNode;
while (cur)
{
if (streq(cur->name, "Type") && cur->ns == ns)
{
content = xmlNodeGetContent(cur);
this->msg_type = strtoul(content, NULL, 16);
xmlFree(content);
}
else if (streq(cur->name, "Base64") && cur->ns == ns)
{
content = xmlNodeGetContent(cur);
b64_body = chunk_create(content, strlen(content));
this->msg_body = decode_base64(b64_body);
xmlFree(content);
}
cur = cur->next;
}
return &this->public.tnccs_msg_interface;
}
/**
* See header
*/
tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
{
private_imc_imv_msg_t *this;
chunk_t b64_body;
char buf[10]; /* big enough for hex-encoded message type */
xmlNodePtr n;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_msg_type = _get_msg_type,
.get_msg_body = _get_msg_body,
},
.type = IMC_IMV_MSG,
.node = xmlNewNode(NULL, "IMC-IMV-Message"),
.msg_type = msg_type,
.msg_body = chunk_clone(msg_body),
);
/* add the message type number in hex */
n = xmlNewNode(NULL, "Type");
snprintf(buf, 10, "%08x", this->msg_type);
xmlNodeSetContent(n, buf);
xmlAddChild(this->node, n);
/* encode the message as a Base64 node */
n = xmlNewNode(NULL, "Base64");
b64_body = encode_base64(this->msg_body);
xmlNodeSetContent(n, b64_body.ptr);
xmlAddChild(this->node, n);
free(b64_body.ptr);
return &this->public.tnccs_msg_interface;
}
@@ -1,71 +0,0 @@
/*
* Copyright (C) 2010 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_imv_msg imc_imv_msg
* @{ @ingroup tnccs_11
*/
#ifndef IMC_IMV_MSG_H_
#define IMC_IMV_MSG_H_
typedef struct imc_imv_msg_t imc_imv_msg_t;
#include "tnccs_msg.h"
#include <tncif.h>
/**
* Classs representing the PB-PA message type.
*/
struct imc_imv_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
/**
* Get IMC-IMV message type
*
* @return IMC-IMV message type
*/
TNC_MessageType (*get_msg_type)(imc_imv_msg_t *this);
/**
* Get IMC-IMV message body
*
* @return IMC-IMV message body
*/
chunk_t (*get_msg_body)(imc_imv_msg_t *this);
};
/**
* Create an IMC-IMV message from XML-encoded message node
*
* @param node XML-encoded message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
/**
* Create an IMC-IMV message from parameters
*
* @param msg_type IMC-IMV message type
* @param msg_body IMC-IMV message body
*/
tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body);
#endif /** IMC_IMV_MSG_H_ @}*/
@@ -1,190 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_error_msg.h"
#include <utils/debug.h>
ENUM(tnccs_error_type_names, TNCCS_ERROR_BATCH_TOO_LONG, TNCCS_ERROR_OTHER,
"batch-too-long",
"malformed-batch",
"invalid-batch-id",
"invalid-recipient-type",
"internal-error",
"other"
);
typedef struct private_tnccs_error_msg_t private_tnccs_error_msg_t;
/**
* Private data of a tnccs_error_msg_t object.
*
*/
struct private_tnccs_error_msg_t {
/**
* Public tnccs_error_msg_t interface.
*/
tnccs_error_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
/**
* Error type
*/
tnccs_error_type_t error_type;
/**
* Error message
*/
char *error_msg;
/**
* reference count
*/
refcount_t ref;
};
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_tnccs_error_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_tnccs_error_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, get_ref, tnccs_msg_t*,
private_tnccs_error_msg_t *this)
{
ref_get(&this->ref);
return &this->public.tnccs_msg_interface;
}
METHOD(tnccs_msg_t, destroy, void,
private_tnccs_error_msg_t *this)
{
if (ref_put(&this->ref))
{
free(this->error_msg);
free(this);
}
}
METHOD(tnccs_error_msg_t, get_message, char*,
private_tnccs_error_msg_t *this, tnccs_error_type_t *type)
{
*type = this->error_type;
return this->error_msg;
}
/**
* See header
*/
tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
{
private_tnccs_error_msg_t *this;
xmlChar *error_type_name, *error_msg;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_message = _get_message,
},
.type = TNCCS_MSG_ERROR,
.ref = 1,
.node = node,
.error_type = TNCCS_ERROR_OTHER,
);
error_type_name = xmlGetProp(node, "type");
if (error_type_name)
{
this->error_type = enum_from_name(tnccs_error_type_names,
error_type_name);
if (this->error_type == -1)
{
this->error_type = TNCCS_ERROR_OTHER;
}
xmlFree(error_type_name);
}
error_msg = xmlNodeGetContent(node);
if (error_msg)
{
this->error_msg = strdup(error_msg);
xmlFree(error_msg);
}
return &this->public.tnccs_msg_interface;
}
/**
* See header
*/
tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg)
{
private_tnccs_error_msg_t *this;
xmlNodePtr n, n2;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_message = _get_message,
},
.type = TNCCS_MSG_ERROR,
.ref = 1,
.node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
.error_type = type,
.error_msg = strdup(msg),
);
DBG1(DBG_TNC, "%s", msg);
n = xmlNewNode(NULL, "Type");
xmlNodeSetContent(n, "00000002");
xmlAddChild(this->node, n);
n = xmlNewNode(NULL, "XML");
xmlAddChild(this->node, n);
n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
xmlNewProp(n2, "type", enum_to_name(tnccs_error_type_names, type));
xmlNodeSetContent(n2, msg);
xmlAddChild(n, n2);
return &this->public.tnccs_msg_interface;
}
@@ -1,80 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_error_msg tnccs_error_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_ERROR_MSG_H_
#define TNCCS_ERROR_MSG_H_
typedef enum tnccs_error_type_t tnccs_error_type_t;
typedef struct tnccs_error_msg_t tnccs_error_msg_t;
#include "tnccs_msg.h"
/**
* TNCCS error types as defined in section 8.1.4 of TCG TNC IF-TNCCS v1.2
*/
enum tnccs_error_type_t {
TNCCS_ERROR_BATCH_TOO_LONG,
TNCCS_ERROR_MALFORMED_BATCH,
TNCCS_ERROR_INVALID_BATCH_ID,
TNCCS_ERROR_INVALID_RECIPIENT_TYPE,
TNCCS_ERROR_INTERNAL_ERROR,
TNCCS_ERROR_OTHER
};
/**
* enum name for tnccs_error_type_t.
*/
extern enum_name_t *tnccs_error_type_names;
/**
* Class representing the TNCCS-Error message type
*/
struct tnccs_error_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
/**
* Get error message and type
*
* @param type TNCCS error type
* @return arbitrary error message
*/
char* (*get_message)(tnccs_error_msg_t *this, tnccs_error_type_t *type);
};
/**
* Create a TNCCS-Error message from XML-encoded message node
*
* @param node XML-encoded message node
*/
tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node);
/**
* Create a TNCCS-Error message from parameters
*
* @param type TNCCS error type
* @param msg arbitrary error message
*/
tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg);
#endif /** TNCCS_ERROR_MSG_H_ @}*/
@@ -1,140 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_msg.h"
#include "imc_imv_msg.h"
#include "tnccs_error_msg.h"
#include "tnccs_preferred_language_msg.h"
#include "tnccs_reason_strings_msg.h"
#include "tnccs_recommendation_msg.h"
#include "tnccs_tncs_contact_info_msg.h"
#include <library.h>
#include <utils/debug.h>
ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF,
"IMC-IMV",
"TNCCS-Recommendation",
"TNCCS-Error",
"TNCCS-PreferredLanguage",
"TNCCS-ReasonStrings",
"TNCCS-TNCSContactInfo"
);
/**
* See header
*/
tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
{
char *error_msg, buf[BUF_LEN];
tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
tnccs_msg_t *msg;
tnccs_msg_type_t type = IMC_IMV_MSG;
if (streq((char*)node->name, "IMC-IMV-Message"))
{
DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
return imc_imv_msg_create_from_node(node, errors);
}
else if (streq((char*)node->name, "TNCC-TNCS-Message"))
{
bool found = FALSE;
xmlNsPtr ns = node->ns;
xmlNodePtr cur = node->xmlChildrenNode;
xmlNodePtr xml_msg_node = NULL;
while (cur)
{
if (streq(cur->name, "Type") && cur->ns == ns)
{
xmlChar *content = xmlNodeGetContent(cur);
type = strtol(content, NULL, 16);
xmlFree(content);
found = TRUE;
}
else if (streq(cur->name, "XML") && cur->ns == ns)
{
xml_msg_node = cur->xmlChildrenNode;
}
cur = cur->next;
}
if (!found)
{
error_msg = "Type is missing in TNCC-TNCS-Message";
goto fatal;
}
if (!xml_msg_node)
{
error_msg = "XML node is missing in TNCC-TNCS-Message";
goto fatal;
}
cur = xml_msg_node;
/* skip empty and blank nodes */
while (cur && xmlIsBlankNode(cur))
{
cur = cur->next;
}
if (!cur)
{
error_msg = "XML node is empty";
goto fatal;
}
/* check if TNCCS message type and node name agree */
if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF)
{
DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
if (cur->ns != ns)
{
error_msg = "node is not in the TNCCS message namespace";
goto fatal;
}
if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
{
error_msg = buf;
snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
tnccs_msg_type_names, type, (char*)cur->name);
goto fatal;
}
}
switch (type)
{
case TNCCS_MSG_RECOMMENDATION:
return tnccs_recommendation_msg_create_from_node(cur, errors);
case TNCCS_MSG_ERROR:
return tnccs_error_msg_create_from_node(cur);
case TNCCS_MSG_PREFERRED_LANGUAGE:
return tnccs_preferred_language_msg_create_from_node(cur, errors);
case TNCCS_MSG_REASON_STRINGS:
return tnccs_reason_strings_msg_create_from_node(cur, errors);
case TNCCS_MSG_TNCS_CONTACT_INFO:
return tnccs_tncs_contact_info_msg_create_from_node(cur, errors);
default:
DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type);
return NULL;
}
}
DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name);
return NULL;
fatal:
msg = tnccs_error_msg_create(error_type, error_msg);
errors->insert_last(errors, msg);
return NULL;
}
@@ -1,102 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_msg tnccs_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_MSG_H_
#define TNCCS_MSG_H_
typedef enum tnccs_msg_type_t tnccs_msg_type_t;
typedef struct tnccs_msg_t tnccs_msg_t;
#include <library.h>
#include <collections/linked_list.h>
#include <libxml/parser.h>
/**
* TNCC-TNCS messages as defined in section 2.8.5 of TCG TNC IF-TNCCS v1.2
*/
enum tnccs_msg_type_t {
IMC_IMV_MSG = 0,
TNCCS_MSG_RECOMMENDATION = 1,
TNCCS_MSG_ERROR = 2,
TNCCS_MSG_PREFERRED_LANGUAGE = 3,
TNCCS_MSG_REASON_STRINGS = 4,
TNCCS_MSG_TNCS_CONTACT_INFO = 5,
TNCCS_MSG_ROOF = 5
};
/**
* enum name for tnccs_msg_type_t.
*/
extern enum_name_t *tnccs_msg_type_names;
/**
* Generic interface for all TNCCS message types.
*
* To handle all messages in a generic way, this interface
* must be implemented by each message type.
*/
struct tnccs_msg_t {
/**
* Get the TNCCS Message Type
*
* @return TNCCS Message Type
*/
tnccs_msg_type_t (*get_type)(tnccs_msg_t *this);
/**
* Get the XML-encoded Message Node
*
* @return Message Node
*/
xmlNodePtr (*get_node)(tnccs_msg_t *this);
/**
* Process the TNCCS Message
*
* @return return processing status
*/
status_t (*process)(tnccs_msg_t *this);
/**
* Get a new reference to the message.
*
* @return this, with an increased refcount
*/
tnccs_msg_t* (*get_ref)(tnccs_msg_t *this);
/**
* Destroys a tnccs_msg_t object.
*/
void (*destroy)(tnccs_msg_t *this);
};
/**
* Create a pre-processed TNCCS message
*
* Useful for the parser which wants a generic constructor for all
* tnccs_msg_t types.
*
* @param node TNCCS message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
#endif /** TNCCS_MSG_H_ @}*/
@@ -1,137 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_preferred_language_msg.h"
#include <utils/debug.h>
typedef struct private_tnccs_preferred_language_msg_t private_tnccs_preferred_language_msg_t;
/**
* Private data of a tnccs_preferred_language_msg_t object.
*
*/
struct private_tnccs_preferred_language_msg_t {
/**
* Public tnccs_preferred_language_msg_t interface.
*/
tnccs_preferred_language_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
/**
* Preferred language
*/
char *preferred_language;
};
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_tnccs_preferred_language_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_tnccs_preferred_language_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, destroy, void,
private_tnccs_preferred_language_msg_t *this)
{
free(this->preferred_language);
free(this);
}
METHOD(tnccs_preferred_language_msg_t, get_preferred_language, char*,
private_tnccs_preferred_language_msg_t *this)
{
return this->preferred_language;
}
/**
* See header
*/
tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors)
{
private_tnccs_preferred_language_msg_t *this;
xmlChar *language;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_preferred_language = _get_preferred_language,
},
.type = TNCCS_MSG_PREFERRED_LANGUAGE,
.node = node,
);
language = xmlNodeGetContent(node);
this->preferred_language = strdup(language);
xmlFree(language);
return &this->public.tnccs_msg_interface;
}
/**
* See header
*/
tnccs_msg_t *tnccs_preferred_language_msg_create(char *language)
{
private_tnccs_preferred_language_msg_t *this;
xmlNodePtr n, n2;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_preferred_language = _get_preferred_language,
},
.type = TNCCS_MSG_PREFERRED_LANGUAGE,
.node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
.preferred_language = strdup(language),
);
/* add the message type number in hex */
n = xmlNewNode(NULL, "Type");
xmlNodeSetContent(n, "00000003");
xmlAddChild(this->node, n);
n = xmlNewNode(NULL, "XML");
xmlAddChild(this->node, n);
n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
xmlNodeSetContent(n2, language);
xmlAddChild(n, n2);
return &this->public.tnccs_msg_interface;
}
@@ -1,64 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_preferred_language_msg tnccs_preferred_language_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_PREFERRED_LANGUAGE_MSG_H_
#define TNCCS_PREFERRED_LANGUAGE_MSG_H_
typedef struct tnccs_preferred_language_msg_t tnccs_preferred_language_msg_t;
#include "tnccs_msg.h"
#include <tncif.h>
/**
* Class representing the TNCCS-PreferredLanguage message type
*/
struct tnccs_preferred_language_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
/**
* Get preferred language string
*
* @return preferred language string
*/
char* (*get_preferred_language)(tnccs_preferred_language_msg_t *this);
};
/**
* Create a TNCCS-PreferredLanguage message from XML-encoded message node
*
* @param node XML-encoded message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors);
/**
* Create a TNCCS-PreferredLanguage message from parameters
*
* @param language preferred language string
*/
tnccs_msg_t *tnccs_preferred_language_msg_create(char *language);
#endif /** TNCCS_PREFERRED_LANGUAGE_MSG_H_ @}*/
@@ -1,196 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_reason_strings_msg.h"
#include "tnccs_error_msg.h"
#include <utils/debug.h>
typedef struct private_tnccs_reason_strings_msg_t private_tnccs_reason_strings_msg_t;
/**
* Private data of a tnccs_reason_strings_msg_t object.
*
*/
struct private_tnccs_reason_strings_msg_t {
/**
* Public tnccs_reason_strings_msg_t interface.
*/
tnccs_reason_strings_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
/**
* Reason String
*/
chunk_t reason;
/**
* Reason Language
*/
chunk_t language;
};
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_tnccs_reason_strings_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_tnccs_reason_strings_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, destroy, void,
private_tnccs_reason_strings_msg_t *this)
{
free(this->reason.ptr);
free(this->language.ptr);
free(this);
}
METHOD(tnccs_reason_strings_msg_t, get_reason, chunk_t,
private_tnccs_reason_strings_msg_t *this, chunk_t *language)
{
*language = this->language;
return this->reason;
}
/**
* See header
*/
tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors)
{
private_tnccs_reason_strings_msg_t *this;
char *error_msg, *lang_string, *reason_string;
tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
tnccs_msg_t *msg;
xmlNodePtr child;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_reason = _get_reason,
},
.type = TNCCS_MSG_REASON_STRINGS,
.node = node,
);
if (xmlStrcmp(node->name, "TNCCS-ReasonStrings"))
{
error_msg = "TNCCS-ReasonStrings tag expected";
goto fatal;
}
child = node->xmlChildrenNode;
while (child)
{
if (xmlIsBlankNode(child))
{
child = child->next;
continue;
}
if (xmlStrcmp(child->name, "ReasonString"))
{
error_msg = "ReasonString tag expected";
goto fatal;
}
break;
}
lang_string = xmlGetProp(child, "lang");
if (!lang_string)
{
lang_string = strdup("");
}
this->language = chunk_clone(chunk_from_str(lang_string));
xmlFree(lang_string);
reason_string = xmlNodeGetContent(child);
this->reason = chunk_clone(chunk_from_str(reason_string));
xmlFree(reason_string);
return &this->public.tnccs_msg_interface;
fatal:
msg = tnccs_error_msg_create(error_type, error_msg);
errors->insert_last(errors, msg);
destroy(this);
return NULL;
}
/**
* See header
*/
tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language)
{
private_tnccs_reason_strings_msg_t *this;
xmlNodePtr n, n2, n3;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_reason = _get_reason,
},
.type = TNCCS_MSG_REASON_STRINGS,
.node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
.reason = chunk_create_clone(malloc(reason.len + 1), reason),
.language = chunk_create_clone(malloc(language.len + 1), language),
);
/* add NULL termination for XML string representation */
this->reason.ptr[this->reason.len] = '\0';
this->language.ptr[this->language.len] = '\0';
/* add the message type number in hex */
n = xmlNewNode(NULL, "Type");
xmlNodeSetContent(n, "00000004");
xmlAddChild(this->node, n);
n = xmlNewNode(NULL, "XML");
xmlAddChild(this->node, n);
n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
/* could add multiple reasons here, if we had them */
n3 = xmlNewNode(NULL, "ReasonString");
xmlNewProp(n3, "xml:lang", this->language.ptr);
xmlNodeSetContent(n3, this->reason.ptr);
xmlAddChild(n2, n3);
xmlAddChild(n, n2);
return &this->public.tnccs_msg_interface;
}
@@ -1,64 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_reason_strings_msg tnccs_reason_strings_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_REASON_STRINGS_MSG_H_
#define TNCCS_REASON_STRINGS_MSG_H_
typedef struct tnccs_reason_strings_msg_t tnccs_reason_strings_msg_t;
#include "tnccs_msg.h"
/**
* Class representing the TNCCS-ReasonStrings message type
*/
struct tnccs_reason_strings_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
/**
* Get reason string and language
*
* @param language reason language
* @return reason string
*/
chunk_t (*get_reason)(tnccs_reason_strings_msg_t *this, chunk_t *language);
};
/**
* Create a TNCCS-ReasonStrings message from XML-encoded message node
*
* @param node XML-encoded message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors);
/**
* Create a TNCCS-ReasonStrings message from parameters
*
* @param reason reason string
* @param language reason language
*/
tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language);
#endif /** TNCCS_REASON_STRINGS_MSG_H_ @}*/
@@ -1,186 +0,0 @@
/*
* Copyright (C) 2006 Mike McCauley ([email protected])
* Copyright (C) 2010 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 "tnccs_recommendation_msg.h"
#include "tnccs_error_msg.h"
#include <utils/debug.h>
typedef struct private_tnccs_recommendation_msg_t private_tnccs_recommendation_msg_t;
/**
* Private data of a tnccs_recommendation_msg_t object.
*
*/
struct private_tnccs_recommendation_msg_t {
/**
* Public tnccs_recommendation_msg_t interface.
*/
tnccs_recommendation_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
/**
* Action Recommendation
*/
TNC_IMV_Action_Recommendation rec;
};
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_tnccs_recommendation_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_tnccs_recommendation_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, destroy, void,
private_tnccs_recommendation_msg_t *this)
{
free(this);
}
METHOD(tnccs_recommendation_msg_t, get_recommendation, TNC_IMV_Action_Recommendation,
private_tnccs_recommendation_msg_t *this)
{
return this->rec;
}
/**
* See header
*/
tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors)
{
private_tnccs_recommendation_msg_t *this;
xmlChar *rec_string;
char *error_msg, buf[BUF_LEN];
tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
tnccs_msg_t *msg;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_recommendation = _get_recommendation,
},
.type = TNCCS_MSG_RECOMMENDATION,
.node = node,
);
rec_string = xmlGetProp(node, "type");
if (!rec_string)
{
error_msg = "type property in TNCCS-Recommendation is missing";
goto fatal;
}
else if (streq(rec_string, "allow"))
{
this->rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
}
else if (streq(rec_string, "isolate"))
{
this->rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
}
else if (streq(rec_string, "none"))
{
this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
}
else
{
error_msg = buf;
snprintf(buf, BUF_LEN, "unsupported type property value '%s' "
"in TNCCS-Recommendation", rec_string);
xmlFree(rec_string);
goto fatal;
}
xmlFree(rec_string);
return &this->public.tnccs_msg_interface;
fatal:
msg = tnccs_error_msg_create(error_type, error_msg);
errors->insert_last(errors, msg);
destroy(this);
return NULL;
}
/**
* See header
*/
tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec)
{
private_tnccs_recommendation_msg_t *this;
xmlNodePtr n, n2;
char *rec_string;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
.get_recommendation = _get_recommendation,
},
.type = TNCCS_MSG_RECOMMENDATION,
.node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
.rec = rec,
);
/* add the message type number in hex */
n = xmlNewNode(NULL, "Type");
xmlNodeSetContent(n, "00000001");
xmlAddChild(this->node, n);
n = xmlNewNode(NULL, "XML");
xmlAddChild(this->node, n);
switch (rec)
{
case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
rec_string = "allow";
break;
case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
rec_string = "isolate";
break;
case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
default:
rec_string = "none";
}
n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
xmlNewProp(n2, BAD_CAST "type", rec_string);
xmlNodeSetContent(n2, "");
xmlAddChild(n, n2);
return &this->public.tnccs_msg_interface;
}
@@ -1,64 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_recommendation_msg tnccs_recommendation_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_RECOMMENDATION_MSG_H_
#define TNCCS_RECOMMENDATION_MSG_H_
typedef struct tnccs_recommendation_msg_t tnccs_recommendation_msg_t;
#include "tnccs_msg.h"
#include <tncifimv.h>
/**
* Class representing the TNCCS-Recommendation message type
*/
struct tnccs_recommendation_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
/**
* Get Action Recommendation
*
* @return Action Recommendation
*/
TNC_IMV_Action_Recommendation (*get_recommendation)(tnccs_recommendation_msg_t *this);
};
/**
* Create a TNCCS-Recommendation message from XML-encoded message node
*
* @param node XML-encoded message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors);
/**
* Create a TNCCS-Recommendation message from parameters
*
* @param rec Action Recommendation
*/
tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec);
#endif /** TNCCS_RECOMMENDATION_MSG_H_ @}*/
@@ -1,118 +0,0 @@
/*
* Copyright (C) 2010 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 "tnccs_tncs_contact_info_msg.h"
#include <utils/debug.h>
typedef struct private_tnccs_tncs_contact_info_msg_t private_tnccs_tncs_contact_info_msg_t;
/**
* Private data of a tnccs_tncs_contact_info_msg_t object.
*
*/
struct private_tnccs_tncs_contact_info_msg_t {
/**
* Public tnccs_tncs_contact_info_msg_t interface.
*/
tnccs_tncs_contact_info_msg_t public;
/**
* TNCCS message type
*/
tnccs_msg_type_t type;
/**
* XML-encoded message node
*/
xmlNodePtr node;
};
METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
private_tnccs_tncs_contact_info_msg_t *this)
{
return this->type;
}
METHOD(tnccs_msg_t, get_node, xmlNodePtr,
private_tnccs_tncs_contact_info_msg_t *this)
{
return this->node;
}
METHOD(tnccs_msg_t, destroy, void,
private_tnccs_tncs_contact_info_msg_t *this)
{
free(this);
}
/**
* See header
*/
tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors)
{
private_tnccs_tncs_contact_info_msg_t *this;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
},
.type = TNCCS_MSG_TNCS_CONTACT_INFO,
.node = node,
);
return &this->public.tnccs_msg_interface;
}
/**
* See header
*/
tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void)
{
private_tnccs_tncs_contact_info_msg_t *this;
xmlNodePtr n /*, n2 */;
INIT(this,
.public = {
.tnccs_msg_interface = {
.get_type = _get_type,
.get_node = _get_node,
.destroy = _destroy,
},
},
.type = TNCCS_MSG_TNCS_CONTACT_INFO,
.node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
);
/* add the message type number in hex */
n = xmlNewNode(NULL, "Type");
xmlNodeSetContent(n, "00000005");
xmlAddChild(this->node, n);
n = xmlNewNode(NULL, "XML");
xmlAddChild(this->node, n);
/* TODO
n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
xmlNodeSetContent(n2, language);
xmlAddChild(n, n2);
*/
return &this->public.tnccs_msg_interface;
}
@@ -1,54 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_tncs_contact_info_msg tnccs_tncs_contact_info_msg
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_TNCS_CONTACT_INFO_MSG_H_
#define TNCCS_TNCS_CONTACT_INFO_MSG_H_
typedef struct tnccs_tncs_contact_info_msg_t tnccs_tncs_contact_info_msg_t;
#include "tnccs_msg.h"
/**
* Class representing the TNCCS-TNCSContactInfo message type
*/
struct tnccs_tncs_contact_info_msg_t {
/**
* TNCCS Message interface
*/
tnccs_msg_t tnccs_msg_interface;
};
/**
* Create a TNCCS-TNCSContactInfo message from XML-encoded message node
*
* @param node XML-encoded message node
* @param errors linked list of TNCCS error messages
*/
tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
linked_list_t *errors);
/**
* Create a TNCCS-TNCSContactInfo message from parameters
*
*/
tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void);
#endif /** TNCCS_TNCS_CONTACT_INFO_MSG_H_ @}*/
-633
View File
@@ -1,633 +0,0 @@
/*
* Copyright (C) 2010-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 "tnccs_11.h"
#include "batch/tnccs_batch.h"
#include "messages/tnccs_msg.h"
#include "messages/imc_imv_msg.h"
#include "messages/tnccs_error_msg.h"
#include "messages/tnccs_preferred_language_msg.h"
#include "messages/tnccs_reason_strings_msg.h"
#include "messages/tnccs_recommendation_msg.h"
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
#include <tnc/tnc.h>
#include <tnc/imc/imc_manager.h>
#include <tnc/imv/imv_manager.h>
#include <tnc/tnccs/tnccs.h>
#include <tnc/tnccs/tnccs_manager.h>
#include <utils/debug.h>
#include <daemon.h>
#include <threading/mutex.h>
typedef struct private_tnccs_11_t private_tnccs_11_t;
/**
* Private data of a tnccs_11_t object.
*/
struct private_tnccs_11_t {
/**
* Public tnccs_t interface.
*/
tnccs_t public;
/**
* TNCC if TRUE, TNCS if FALSE
*/
bool is_server;
/**
* Server identity
*/
identification_t *server;
/**
* Client identity
*/
identification_t *peer;
/**
* Underlying TNC IF-T transport protocol
*/
tnc_ift_type_t transport;
/**
* Type of TNC client authentication
*/
u_int32_t auth_type;
/**
* Connection ID assigned to this TNCCS connection
*/
TNC_ConnectionID connection_id;
/**
* Last TNCCS batch ID
*/
int batch_id;
/**
* TNCCS batch being constructed
*/
tnccs_batch_t *batch;
/**
* Maximum PA-TNC message size
*/
size_t max_msg_len;
/**
* Mutex locking the batch in construction
*/
mutex_t *mutex;
/**
* Flag set while processing
*/
bool fatal_error;
/**
* Flag set by TNCCS-Recommendation message
*/
bool delete_state;
/**
* SendMessage() by IMC/IMV only allowed if flag is set
*/
bool send_msg;
/**
* Flag set by IMC/IMV RequestHandshakeRetry() function
*/
bool request_handshake_retry;
/**
* Set of IMV recommendations (TNC Server only)
*/
recommendations_t *recs;
};
METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_UInt32 msg_flags,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
TNC_VendorID msg_vid,
TNC_MessageSubtype msg_subtype)
{
tnccs_msg_t *tnccs_msg;
TNC_MessageType msg_type;
enum_name_t *pa_subtype_names;
if (!this->send_msg)
{
DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
this->is_server ? "IMV" : "IMC",
this->is_server ? imv_id : imc_id);
return TNC_RESULT_ILLEGAL_OPERATION;
}
if (msg_vid > TNC_VENDORID_ANY || msg_subtype > TNC_SUBTYPE_ANY)
{
return TNC_RESULT_NO_LONG_MESSAGE_TYPES;
}
msg_type = (msg_vid << 8) | msg_subtype;
pa_subtype_names = get_pa_subtype_names(msg_vid);
if (pa_subtype_names)
{
DBG2(DBG_TNC, "creating IMC-IMV message type '%N/%N' 0x%06x/0x%02x",
pen_names, msg_vid, pa_subtype_names, msg_subtype,
msg_vid, msg_subtype);
}
else
{
DBG2(DBG_TNC, "creating IMC-IMV message type '%N' 0x%06x/0x%02x",
pen_names, msg_vid, msg_vid, msg_subtype);
}
tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len));
/* adding an IMC-IMV Message to TNCCS batch */
this->mutex->lock(this->mutex);
if (!this->batch)
{
this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
}
this->batch->add_msg(this->batch, tnccs_msg);
this->mutex->unlock(this->mutex);
return TNC_RESULT_SUCCESS;
}
/**
* Handle a single TNCCS message according to its type
*/
static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg)
{
switch (msg->get_type(msg))
{
case IMC_IMV_MSG:
{
imc_imv_msg_t *imc_imv_msg;
TNC_MessageType msg_type;
chunk_t msg_body;
u_int32_t msg_vid, msg_subtype;
enum_name_t *pa_subtype_names;
imc_imv_msg = (imc_imv_msg_t*)msg;
msg_type = imc_imv_msg->get_msg_type(imc_imv_msg);
msg_body = imc_imv_msg->get_msg_body(imc_imv_msg);
msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY;
msg_subtype = msg_type & TNC_SUBTYPE_ANY;
pa_subtype_names = get_pa_subtype_names(msg_vid);
if (pa_subtype_names)
{
DBG2(DBG_TNC, "handling IMC-IMV message type '%N/%N' 0x%06x/0x%02x",
pen_names, msg_vid, pa_subtype_names, msg_subtype,
msg_vid, msg_subtype);
}
else
{
DBG2(DBG_TNC, "handling IMC-IMV message type '%N' 0x%06x/0x%02x",
pen_names, msg_vid, msg_vid, msg_subtype);
}
this->send_msg = TRUE;
if (this->is_server)
{
tnc->imvs->receive_message(tnc->imvs, this->connection_id,
FALSE, msg_body.ptr, msg_body.len,
msg_vid, msg_subtype, 0, TNC_IMVID_ANY);
}
else
{
tnc->imcs->receive_message(tnc->imcs, this->connection_id,
FALSE, msg_body.ptr, msg_body.len,
msg_vid, msg_subtype, 0, TNC_IMCID_ANY);
}
this->send_msg = FALSE;
break;
}
case TNCCS_MSG_RECOMMENDATION:
{
tnccs_recommendation_msg_t *rec_msg;
TNC_IMV_Action_Recommendation rec;
TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
rec_msg = (tnccs_recommendation_msg_t*)msg;
rec = rec_msg->get_recommendation(rec_msg);
if (this->is_server)
{
DBG1(DBG_TNC, "ignoring NCCS-Recommendation message from "
" TNC client");
break;
}
DBG1(DBG_TNC, "TNC recommendation is '%N'",
TNC_IMV_Action_Recommendation_names, rec);
switch (rec)
{
case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
break;
case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
break;
case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
default:
state = TNC_CONNECTION_STATE_ACCESS_NONE;
}
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
state);
this->delete_state = TRUE;
break;
}
case TNCCS_MSG_ERROR:
{
tnccs_error_msg_t *err_msg;
tnccs_error_type_t error_type;
char *error_msg;
err_msg = (tnccs_error_msg_t*)msg;
error_msg = err_msg->get_message(err_msg, &error_type);
DBG1(DBG_TNC, "received '%N' TNCCS-Error: %s",
tnccs_error_type_names, error_type, error_msg);
/* we assume that all errors are fatal */
this->fatal_error = TRUE;
break;
}
case TNCCS_MSG_PREFERRED_LANGUAGE:
{
tnccs_preferred_language_msg_t *lang_msg;
char *lang;
lang_msg = (tnccs_preferred_language_msg_t*)msg;
lang = lang_msg->get_preferred_language(lang_msg);
DBG2(DBG_TNC, "setting preferred language to '%s'", lang);
this->recs->set_preferred_language(this->recs,
chunk_create(lang, strlen(lang)));
break;
}
case TNCCS_MSG_REASON_STRINGS:
{
tnccs_reason_strings_msg_t *reason_msg;
chunk_t reason_string, reason_lang;
reason_msg = (tnccs_reason_strings_msg_t*)msg;
reason_string = reason_msg->get_reason(reason_msg, &reason_lang);
DBG2(DBG_TNC, "reason string is '%.*s'", (int)reason_string.len,
reason_string.ptr);
DBG2(DBG_TNC, "language code is '%.*s'", (int)reason_lang.len,
reason_lang.ptr);
break;
}
default:
break;
}
}
METHOD(tls_t, process, status_t,
private_tnccs_11_t *this, void *buf, size_t buflen)
{
chunk_t data;
tnccs_batch_t *batch;
tnccs_msg_t *msg;
enumerator_t *enumerator;
status_t status;
if (this->is_server && !this->connection_id)
{
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_1_1, (tnccs_t*)this, _send_msg,
&this->request_handshake_retry,
this->max_msg_len, &this->recs);
if (!this->connection_id)
{
return FAILED;
}
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_CREATE);
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
}
data = chunk_create(buf, buflen);
DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
data.len, this->connection_id);
DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data);
status = batch->process(batch);
if (status == FAILED)
{
this->fatal_error = TRUE;
this->mutex->lock(this->mutex);
if (this->batch)
{
DBG1(DBG_TNC, "cancelling TNCCS batch");
this->batch->destroy(this->batch);
this->batch_id--;
}
this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
/* add error messages to outbound batch */
enumerator = batch->create_error_enumerator(batch);
while (enumerator->enumerate(enumerator, &msg))
{
this->batch->add_msg(this->batch, msg->get_ref(msg));
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
else
{
enumerator = batch->create_msg_enumerator(batch);
while (enumerator->enumerate(enumerator, &msg))
{
handle_message(this, msg);
}
enumerator->destroy(enumerator);
/* received any TNCCS-Error messages */
if (this->fatal_error)
{
DBG1(DBG_TNC, "a fatal TNCCS-Error occurred, terminating connection");
batch->destroy(batch);
return FAILED;
}
this->send_msg = TRUE;
if (this->is_server)
{
tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
}
else
{
tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
}
this->send_msg = FALSE;
}
batch->destroy(batch);
return NEED_MORE;
}
/**
* Add a recommendation message if a final recommendation is available
*/
static void check_and_build_recommendation(private_tnccs_11_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
TNC_IMVID id;
chunk_t reason, language;
enumerator_t *enumerator;
tnccs_msg_t *msg;
if (!this->recs->have_recommendation(this->recs, &rec, &eval))
{
tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
}
if (this->recs->have_recommendation(this->recs, &rec, &eval))
{
if (!this->batch)
{
this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
}
msg = tnccs_recommendation_msg_create(rec);
this->batch->add_msg(this->batch, msg);
/* currently we just send the first Reason String */
enumerator = this->recs->create_reason_enumerator(this->recs);
if (enumerator->enumerate(enumerator, &id, &reason, &language))
{
msg = tnccs_reason_strings_msg_create(reason, language);
this->batch->add_msg(this->batch, msg);
}
enumerator->destroy(enumerator);
/* we have reache the final state */
this->delete_state = TRUE;
}
}
METHOD(tls_t, build, status_t,
private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen)
{
status_t status;
/* Initialize the connection */
if (!this->is_server && !this->connection_id)
{
tnccs_msg_t *msg;
char *pref_lang;
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_1_1, (tnccs_t*)this, _send_msg,
&this->request_handshake_retry,
this->max_msg_len, NULL);
if (!this->connection_id)
{
return FAILED;
}
/* Create TNCCS-PreferredLanguage message */
pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
msg = tnccs_preferred_language_msg_create(pref_lang);
this->mutex->lock(this->mutex);
this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
this->batch->add_msg(this->batch, msg);
this->mutex->unlock(this->mutex);
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
TNC_CONNECTION_STATE_CREATE);
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
this->send_msg = TRUE;
tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
this->send_msg = FALSE;
}
/* Do not allow any asynchronous IMCs or IMVs to add additional messages */
this->mutex->lock(this->mutex);
if (this->recs && !this->delete_state &&
(!this->batch || this->fatal_error))
{
check_and_build_recommendation(this);
}
if (this->batch)
{
chunk_t data;
this->batch->build(this->batch);
data = this->batch->get_encoding(this->batch);
DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
data.len, this->connection_id);
DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
*msglen = 0;
if (data.len > *buflen)
{
DBG1(DBG_TNC, "fragmentation of TNCCS batch not supported yet");
}
else
{
*buflen = data.len;
}
memcpy(buf, data.ptr, *buflen);
this->batch->destroy(this->batch);
this->batch = NULL;
status = ALREADY_DONE;
}
else
{
DBG1(DBG_TNC, "no TNCCS Batch to send");
status = INVALID_STATE;
}
this->mutex->unlock(this->mutex);
return status;
}
METHOD(tls_t, is_server, bool,
private_tnccs_11_t *this)
{
return this->is_server;
}
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_11_t *this)
{
return this->server;
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_11_t *this)
{
return this->peer;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
private_tnccs_11_t *this)
{
return TLS_PURPOSE_EAP_TNC;
}
METHOD(tls_t, is_complete, bool,
private_tnccs_11_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
{
return tnc->imvs->enforce_recommendation(tnc->imvs, rec, eval);
}
else
{
return FALSE;
}
}
METHOD(tls_t, get_eap_msk, chunk_t,
private_tnccs_11_t *this)
{
return chunk_empty;
}
METHOD(tls_t, destroy, void,
private_tnccs_11_t *this)
{
tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
this->is_server);
this->server->destroy(this->server);
this->peer->destroy(this->peer);
this->mutex->destroy(this->mutex);
DESTROY_IF(this->batch);
free(this);
}
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_11_t *this)
{
return this->transport;
}
METHOD(tnccs_t, set_transport, void,
private_tnccs_11_t *this, tnc_ift_type_t transport)
{
this->transport = transport;
}
METHOD(tnccs_t, get_auth_type, u_int32_t,
private_tnccs_11_t *this)
{
return this->auth_type;
}
METHOD(tnccs_t, set_auth_type, void,
private_tnccs_11_t *this, u_int32_t auth_type)
{
this->auth_type = auth_type;
}
/**
* See header
*/
tnccs_t* tnccs_11_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport)
{
private_tnccs_11_t *this;
INIT(this,
.public = {
.tls = {
.process = _process,
.build = _build,
.is_server = _is_server,
.get_server_id = _get_server_id,
.get_peer_id = _get_peer_id,
.get_purpose = _get_purpose,
.is_complete = _is_complete,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
.set_auth_type = _set_auth_type,
},
.is_server = is_server,
.server = server->clone(server),
.peer = peer->clone(peer),
.transport = transport,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.max_msg_len = lib->settings->get_int(lib->settings,
"%s.plugins.tnccs-11.max_message_size", 45000,
charon->name),
);
return &this->public;
}
-42
View File
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010-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 tnccs_11_h tnccs_11
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_11_H_
#define TNCCS_11_H_
#include <library.h>
#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of the TNC IF-TNCCS 1.1 protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
* @param server Server identity
* @param peer Client identity
* @param transport Underlying IF-T transport protocol
* @return TNC_IF_TNCCS 1.1 protocol stack
*/
tnccs_t* tnccs_11_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport);
#endif /** TNCCS_11_H_ @}*/
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2010 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 "tnccs_11_plugin.h"
#include "tnccs_11.h"
#include <tnc/tnccs/tnccs_manager.h>
METHOD(plugin_t, get_name, char*,
tnccs_11_plugin_t *this)
{
return "tnccs-11";
}
METHOD(plugin_t, get_features, int,
tnccs_11_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnccs_method_register, tnccs_11_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-1.1"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
tnccs_11_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *tnccs_11_plugin_create()
{
tnccs_11_plugin_t *this;
INIT(this,
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
);
return &this->plugin;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_11 tnccs_11
* @ingroup cplugins
*
* @defgroup tnccs_11_plugin tnccs_11_plugin
* @{ @ingroup tnccs_11
*/
#ifndef TNCCS_11_PLUGIN_H_
#define TNCCS_11_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct tnccs_11_plugin_t tnccs_11_plugin_t;
/**
* EAP-TNC plugin
*/
struct tnccs_11_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** TNCCS_11_PLUGIN_H_ @}*/
@@ -1,35 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
-rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
else
plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
libstrongswan_tnccs_20_la_LIBADD = \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libtnccs/libtnccs.la
endif
libstrongswan_tnccs_20_la_SOURCES = \
tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
messages/pb_experimental_msg.h messages/pb_experimental_msg.c \
messages/pb_pa_msg.h messages/pb_pa_msg.c \
messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \
messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \
messages/pb_error_msg.h messages/pb_error_msg.c \
messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \
messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \
messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \
state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version
@@ -1,577 +0,0 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
* Copyright (C) 2010-2012 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 "pb_tnc_batch.h"
#include "messages/pb_error_msg.h"
#include "state_machine/pb_tnc_state_machine.h"
#include <tnc/tnccs/tnccs.h>
#include <collections/linked_list.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <pen/pen.h>
#include <utils/debug.h>
ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE,
"CDATA",
"SDATA",
"RESULT",
"CRETRY",
"SRETRY",
"CLOSE"
);
typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
/**
* PB-Batch Header (see section 4.1 of RFC 5793)
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version |D| Reserved | B-Type|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Batch Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define PB_TNC_BATCH_FLAG_NONE 0x00
#define PB_TNC_BATCH_FLAG_D (1<<7)
#define PB_TNC_BATCH_HEADER_SIZE 8
/**
* PB-TNC Message (see section 4.2 of RFC 5793)
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Flags | PB-TNC Vendor ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PB-TNC Message Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PB-TNC Message Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PB-TNC Message Value (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define PB_TNC_FLAG_NONE 0x00
#define PB_TNC_FLAG_NOSKIP (1<<7)
#define PB_TNC_HEADER_SIZE 12
#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff
/**
* Private data of a pb_tnc_batch_t object.
*
*/
struct private_pb_tnc_batch_t {
/**
* Public pb_pa_msg_t interface.
*/
pb_tnc_batch_t public;
/**
* TNCC if TRUE, TNCS if FALSE
*/
bool is_server;
/**
* PB-TNC Batch type
*/
pb_tnc_batch_type_t type;
/**
* Current PB-TNC Batch size
*/
size_t batch_len;
/**
* Maximum PB-TNC Batch size
*/
size_t max_batch_len;
/**
* linked list of PB-TNC messages
*/
linked_list_t *messages;
/**
* linked list of PB-TNC error messages
*/
linked_list_t *errors;
/**
* Encoded message
*/
chunk_t encoding;
/**
* Offset into encoding (used for error reporting)
*/
u_int32_t offset;
};
METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t,
private_pb_tnc_batch_t *this)
{
return this->type;
}
METHOD(pb_tnc_batch_t, get_encoding, chunk_t,
private_pb_tnc_batch_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_batch_t, add_msg, bool,
private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg)
{
chunk_t msg_value;
size_t msg_len;
msg->build(msg);
msg_value = msg->get_encoding(msg);
msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
if (this->batch_len + msg_len > this->max_batch_len)
{
/* message just does not fit into this batch */
return FALSE;
}
this->batch_len += msg_len;
DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names,
msg->get_type(msg));
this->messages->insert_last(this->messages, msg);
return TRUE;
}
METHOD(pb_tnc_batch_t, build, void,
private_pb_tnc_batch_t *this)
{
u_int32_t msg_len;
chunk_t msg_value;
enumerator_t *enumerator;
pb_tnc_msg_type_t msg_type;
pb_tnc_msg_t *msg;
bio_writer_t *writer;
/* build PB-TNC batch header */
writer = bio_writer_create(this->batch_len);
writer->write_uint8 (writer, PB_TNC_VERSION);
writer->write_uint8 (writer, this->is_server ?
PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
writer->write_uint16(writer, this->type);
writer->write_uint32(writer, this->batch_len);
/* build PB-TNC messages */
enumerator = this->messages->create_enumerator(this->messages);
while (enumerator->enumerate(enumerator, &msg))
{
u_int8_t flags = PB_TNC_FLAG_NONE;
/* build PB-TNC message */
msg_value = msg->get_encoding(msg);
msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
msg_type = msg->get_type(msg);
if (pb_tnc_msg_infos[msg_type].has_noskip_flag)
{
flags |= PB_TNC_FLAG_NOSKIP;
}
writer->write_uint8 (writer, flags);
writer->write_uint24(writer, PEN_IETF);
writer->write_uint32(writer, msg_type);
writer->write_uint32(writer, msg_len);
writer->write_data (writer, msg_value);
}
enumerator->destroy(enumerator);
this->encoding = writer->extract_buf(writer);
writer->destroy(writer);
}
static status_t process_batch_header(private_pb_tnc_batch_t *this,
pb_tnc_state_machine_t *state_machine)
{
bio_reader_t *reader;
pb_tnc_msg_t *msg;
pb_error_msg_t *err_msg;
u_int8_t version, flags, reserved, type;
u_int32_t batch_len;
bool directionality;
if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE)
{
DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header",
this->encoding.len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, 0);
goto fatal;
}
reader = bio_reader_create(this->encoding);
reader->read_uint8 (reader, &version);
reader->read_uint8 (reader, &flags);
reader->read_uint8 (reader, &reserved);
reader->read_uint8 (reader, &type);
reader->read_uint32(reader, &batch_len);
reader->destroy(reader);
/* Version */
if (version != PB_TNC_VERSION)
{
DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%02x", version);
msg = pb_error_msg_create(TRUE, PEN_IETF,
PB_ERROR_VERSION_NOT_SUPPORTED);
err_msg = (pb_error_msg_t*)msg;
err_msg->set_bad_version(err_msg, version);
goto fatal;
}
/* Directionality */
directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
if (directionality == this->is_server)
{
DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
directionality ? "server" : "client");
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, 1);
goto fatal;
}
/* Batch Type */
this->type = type & 0x0F;
if (this->type > PB_BATCH_ROOF)
{
DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, 3);
goto fatal;
}
if (!state_machine->receive_batch(state_machine, this->type))
{
DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
pb_tnc_batch_type_names, this->type);
msg = pb_error_msg_create(TRUE, PEN_IETF,
PB_ERROR_UNEXPECTED_BATCH_TYPE);
goto fatal;
}
DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
this->type);
/* Batch Length */
if (this->encoding.len != batch_len)
{
DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes",
this->encoding.len, batch_len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, 4);
goto fatal;
}
this->offset = PB_TNC_BATCH_HEADER_SIZE;
/* Register an empty CDATA batch with the state machine */
if (this->type == PB_BATCH_CDATA)
{
state_machine->set_empty_cdata(state_machine,
this->offset == this->encoding.len);
}
return SUCCESS;
fatal:
this->errors->insert_last(this->errors, msg);
return FAILED;
}
static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
{
bio_reader_t *reader;
pb_tnc_msg_t *pb_tnc_msg, *msg;
u_int8_t flags;
u_int32_t vendor_id, msg_type, msg_len, offset;
chunk_t data, msg_value;
bool noskip_flag;
status_t status;
data = chunk_skip(this->encoding, this->offset);
if (data.len < PB_TNC_HEADER_SIZE)
{
DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header",
data.len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset);
goto fatal;
}
reader = bio_reader_create(data);
reader->read_uint8 (reader, &flags);
reader->read_uint24(reader, &vendor_id);
reader->read_uint32(reader, &msg_type);
reader->read_uint32(reader, &msg_len);
reader->destroy(reader);
noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE;
if (msg_len > data.len)
{
DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset + 8);
goto fatal;
}
if (vendor_id == PEN_RESERVED)
{
DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset + 1);
goto fatal;
}
if (msg_type == PB_TNC_RESERVED_MSG_TYPE)
{
DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved",
PB_TNC_RESERVED_MSG_TYPE);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset + 4);
goto fatal;
}
if (vendor_id != PEN_IETF || msg_type > PB_MSG_ROOF)
{
if (msg_len < PB_TNC_HEADER_SIZE)
{
DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length",
msg_len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset + 8);
goto fatal;
}
if (noskip_flag)
{
DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / "
"Type 0x%08x)", vendor_id, msg_type);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
goto fatal;
}
else
{
DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / "
"Type 0x%08x)", vendor_id, msg_type);
this->offset += msg_len;
return SUCCESS;
}
}
else
{
if (msg_type == PB_MSG_EXPERIMENTAL && noskip_flag)
{
DBG1(DBG_TNC, "reject PB-Experimental message with NOSKIP flag set");
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
goto fatal;
}
if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE &&
pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag)
{
DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set",
pb_tnc_msg_type_names, msg_type,
pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not");
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset);
goto fatal;
}
if (msg_len < pb_tnc_msg_infos[msg_type].min_size ||
(pb_tnc_msg_infos[msg_type].exact_size &&
msg_len != pb_tnc_msg_infos[msg_type].min_size))
{
DBG1(DBG_TNC, "%N message length must be %s %u bytes but is %u bytes",
pb_tnc_msg_type_names, msg_type,
pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least",
pb_tnc_msg_infos[msg_type].min_size, msg_len);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset);
goto fatal;
}
}
if (pb_tnc_msg_infos[msg_type].in_result_batch &&
this->type != PB_BATCH_RESULT)
{
if (this->is_server)
{
DBG1(DBG_TNC,"reject %N message received from a PB-TNC client",
pb_tnc_msg_type_names, msg_type);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset);
goto fatal;
}
else
{
DBG1(DBG_TNC,"ignore %N message not received within RESULT batch",
pb_tnc_msg_type_names, msg_type);
this->offset += msg_len;
return SUCCESS;
}
}
DBG2(DBG_TNC, "processing %N message (%u bytes)", pb_tnc_msg_type_names,
msg_type, msg_len);
data.len = msg_len;
msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE);
pb_tnc_msg = pb_tnc_msg_create_from_data(msg_type, msg_value);
status = pb_tnc_msg->process(pb_tnc_msg, &offset);
if (status == FAILED || status == VERIFY_ERROR)
{
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_INVALID_PARAMETER, this->offset + offset);
this->errors->insert_last(this->errors, msg);
}
if (status == FAILED)
{
pb_tnc_msg->destroy(pb_tnc_msg);
return FAILED;
}
this->messages->insert_last(this->messages, pb_tnc_msg);
this->offset += msg_len;
return status;
fatal:
this->errors->insert_last(this->errors, msg);
return FAILED;
}
METHOD(pb_tnc_batch_t, process, status_t,
private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine)
{
status_t status;
status = process_batch_header(this, state_machine);
if (status != SUCCESS)
{
return FAILED;
}
while (this->offset < this->encoding.len)
{
switch (process_tnc_msg(this))
{
case FAILED:
return FAILED;
case VERIFY_ERROR:
status = VERIFY_ERROR;
break;
case SUCCESS:
default:
break;
}
}
return status;
}
METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*,
private_pb_tnc_batch_t *this)
{
return this->messages->create_enumerator(this->messages);
}
METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*,
private_pb_tnc_batch_t *this)
{
return this->errors->create_enumerator(this->errors);
}
METHOD(pb_tnc_batch_t, destroy, void,
private_pb_tnc_batch_t *this)
{
this->messages->destroy_offset(this->messages,
offsetof(pb_tnc_msg_t, destroy));
this->errors->destroy_offset(this->errors,
offsetof(pb_tnc_msg_t, destroy));
free(this->encoding.ptr);
free(this);
}
/**
* See header
*/
pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
size_t max_batch_len)
{
private_pb_tnc_batch_t *this;
INIT(this,
.public = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
.is_server = is_server,
.type = type,
.max_batch_len = max_batch_len,
.batch_len = PB_TNC_BATCH_HEADER_SIZE,
.messages = linked_list_create(),
.errors = linked_list_create(),
);
DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type);
return &this->public;
}
/**
* See header
*/
pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
{
private_pb_tnc_batch_t *this;
INIT(this,
.public = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
.is_server = is_server,
.messages = linked_list_create(),
.errors = linked_list_create(),
.encoding = chunk_clone(data),
);
return &this->public;
}
@@ -1,130 +0,0 @@
/*
* Copyright (C) 2010-2012 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 pb_tnc_batch pb_tnc_batch
* @{ @ingroup tnccs_20
*/
#ifndef PB_TNC_BATCH_H_
#define PB_TNC_BATCH_H_
typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t;
typedef struct pb_tnc_batch_t pb_tnc_batch_t;
#include "messages/pb_tnc_msg.h"
#include "state_machine/pb_tnc_state_machine.h"
#include <library.h>
/**
* PB-TNC Batch Types as defined in section 4.1 of RFC 5793
*/
enum pb_tnc_batch_type_t {
PB_BATCH_NONE = 0, /* for internal use only */
PB_BATCH_CDATA = 1,
PB_BATCH_SDATA = 2,
PB_BATCH_RESULT = 3,
PB_BATCH_CRETRY = 4,
PB_BATCH_SRETRY = 5,
PB_BATCH_CLOSE = 6,
PB_BATCH_ROOF = 6
};
/**
* enum name for pb_tnc_batch_type_t.
*/
extern enum_name_t *pb_tnc_batch_type_names;
/**
* Interface for all PB-TNC Batch Types.
*/
struct pb_tnc_batch_t {
/**
* Get the PB-TNC Message Type
*
* @return PB-TNC batch type
*/
pb_tnc_batch_type_t (*get_type)(pb_tnc_batch_t *this);
/**
* Get the encoding of the PB-TNC Batch
*
* @return encoded PB-TNC batch
*/
chunk_t (*get_encoding)(pb_tnc_batch_t *this);
/**
* Add a PB-TNC Message
*
* @param msg PB-TNC message to be addedd
* @return TRUE if message fit into batch and was added
*/
bool (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg);
/**
* Build the PB-TNC Batch
*/
void (*build)(pb_tnc_batch_t *this);
/**
* Process the PB-TNC Batch
*
* @param PB-TNC state machine
* @return return processing status
*/
status_t (*process)(pb_tnc_batch_t *this,
pb_tnc_state_machine_t *state_machine);
/**
* Enumerates over all PB-TNC Messages
*
* @return return message enumerator
*/
enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this);
/**
* Enumerates over all parsing errors
*
* @return return error enumerator
*/
enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this);
/**
* Destroys a pb_tnc_batch_t object.
*/
void (*destroy)(pb_tnc_batch_t *this);
};
/**
* Create an empty PB-TNC Batch of a given type
*
* @param is_server TRUE if server, FALSE if client
* @param type PB-TNC batch type
* @param max_batch_len maximum size the PB-TNC batch
*/
pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
size_t max_batch_len);
/**
* Create an unprocessed PB-TNC Batch from data
*
* @param is_server TRUE if server, FALSE if client
* @param data encoded PB-TNC batch
*/
pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data);
#endif /** PB_TNC_BATCH_H_ @}*/
@@ -1,181 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_access_recommendation_msg.h"
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED,
"Access Allowed",
"Access Denied",
"Quarantined"
);
typedef struct private_pb_access_recommendation_msg_t private_pb_access_recommendation_msg_t;
/**
* PB-Access-Recommendation message (see section 4.7 of RFC 5793)
*
* 0 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 | Access Recommendation Code |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define ACCESS_RECOMMENDATION_RESERVED 0x0000
#define ACCESS_RECOMMENDATION_MSG_SIZE 4
/**
* Private data of a pb_access_recommendation_msg_t object.
*
*/
struct private_pb_access_recommendation_msg_t {
/**
* Public pb_access_recommendation_msg_t interface.
*/
pb_access_recommendation_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Access recommendation code
*/
u_int16_t recommendation;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_access_recommendation_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_access_recommendation_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_access_recommendation_msg_t *this)
{
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
writer = bio_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE);
writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED);
writer->write_uint16(writer, this->recommendation);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_access_recommendation_msg_t *this, u_int32_t *offset)
{
bio_reader_t *reader;
u_int16_t reserved;
reader = bio_reader_create(this->encoding);
reader->read_uint16(reader, &reserved);
reader->read_uint16(reader, &this->recommendation);
reader->destroy(reader);
if (this->recommendation < PB_REC_ACCESS_ALLOWED ||
this->recommendation > PB_REC_QUARANTINED)
{
DBG1(DBG_TNC, "invalid access recommendation code (%u)",
this->recommendation);
*offset = 2;
return FAILED;
}
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_access_recommendation_msg_t *this)
{
free(this->encoding.ptr);
free(this);
}
METHOD(pb_access_recommendation_msg_t, get_access_recommendation, u_int16_t,
private_pb_access_recommendation_msg_t *this)
{
return this->recommendation;
}
/**
* See header
*/
pb_tnc_msg_t *pb_access_recommendation_msg_create_from_data(chunk_t data)
{
private_pb_access_recommendation_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_access_recommendation = _get_access_recommendation,
},
.type = PB_MSG_ACCESS_RECOMMENDATION,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_access_recommendation_msg_create(u_int16_t recommendation)
{
private_pb_access_recommendation_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_access_recommendation = _get_access_recommendation,
},
.type = PB_MSG_ACCESS_RECOMMENDATION,
.recommendation = recommendation,
);
return &this->public.pb_interface;
}
@@ -1,76 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_access_recommendation_msg pb_access_recommendation_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_ACCESS_RECOMMENDATION_MSG_H_
#define PB_ACCESS_RECOMMENDATION_MSG_H_
typedef enum pb_access_recommendation_code_t pb_access_recommendation_code_t;
typedef struct pb_access_recommendation_msg_t pb_access_recommendation_msg_t;
#include "pb_tnc_msg.h"
/**
* PB Access Recommendation Codes as defined in section 4.7 of RFC 5793
*/
enum pb_access_recommendation_code_t {
PB_REC_ACCESS_ALLOWED = 1,
PB_REC_ACCESS_DENIED = 2,
PB_REC_QUARANTINED = 3,
};
/**
* enum name for pb_access_recommendation_code_t.
*/
extern enum_name_t *pb_access_recommendation_code_names;
/**
* Class representing the PB-Access-Recommendation message type.
*/
struct pb_access_recommendation_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get PB Access Recommendation
*
* @return PB Access Recommendation
*/
u_int16_t (*get_access_recommendation)(pb_access_recommendation_msg_t *this);
};
/**
* Create a PB-Access-Recommendation message from parameters
*
* @param recommendation Access Recommendation code
*/
pb_tnc_msg_t* pb_access_recommendation_msg_create(u_int16_t recommendation);
/**
* Create an unprocessed PB-Access-Recommendation message from raw data
*
* @param data PB-Access-Recommendation message data
*/
pb_tnc_msg_t* pb_access_recommendation_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,174 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_assessment_result_msg.h"
#include <tncifimv.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t;
/**
* PB-Assessment-Result message (see section 4.6 of RFC 5793)
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Assessment Result |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define ASSESSMENT_RESULT_MSG_SIZE 4
/**
* Private data of a pb_assessment_result_msg_t object.
*
*/
struct private_pb_assessment_result_msg_t {
/**
* Public pb_assessment_result_msg_t interface.
*/
pb_assessment_result_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Assessment result code
*/
u_int32_t assessment_result;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_assessment_result_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_assessment_result_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_assessment_result_msg_t *this)
{
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
writer = bio_writer_create(ASSESSMENT_RESULT_MSG_SIZE);
writer->write_uint32(writer, this->assessment_result);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_assessment_result_msg_t *this, u_int32_t *offset)
{
bio_reader_t *reader;
reader = bio_reader_create(this->encoding);
reader->read_uint32(reader, &this->assessment_result);
reader->destroy(reader);
if (this->assessment_result < TNC_IMV_EVALUATION_RESULT_COMPLIANT ||
this->assessment_result > TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
{
DBG1(DBG_TNC, "invalid assessment result (%u)",
this->assessment_result);
*offset = 0;
return FAILED;
}
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_assessment_result_msg_t *this)
{
free(this->encoding.ptr);
free(this);
}
METHOD(pb_assessment_result_msg_t, get_assessment_result, u_int32_t,
private_pb_assessment_result_msg_t *this)
{
return this->assessment_result;
}
/**
* See header
*/
pb_tnc_msg_t *pb_assessment_result_msg_create_from_data(chunk_t data)
{
private_pb_assessment_result_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_assessment_result = _get_assessment_result,
},
.type = PB_MSG_ASSESSMENT_RESULT,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_assessment_result_msg_create(u_int32_t assessment_result)
{
private_pb_assessment_result_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_assessment_result = _get_assessment_result,
},
.type = PB_MSG_ASSESSMENT_RESULT,
.assessment_result = assessment_result,
);
return &this->public.pb_interface;
}
@@ -1,60 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_assessment_result_msg pb_assessment_result_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_ASSESSMENT_RESULT_MSG_H_
#define PB_ASSESSMENT_RESULT_MSG_H_
typedef struct pb_assessment_result_msg_t pb_assessment_result_msg_t;
#include "pb_tnc_msg.h"
/**
* Class representing the PB-Assessment-Result message type.
*/
struct pb_assessment_result_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get PB Assessment result
*
* @return PB Assessment result
*/
u_int32_t (*get_assessment_result)(pb_assessment_result_msg_t *this);
};
/**
* Create a PB-Assessment-Result message from parameters
*
* @param assessment_result Assessment result code
*/
pb_tnc_msg_t* pb_assessment_result_msg_create(u_int32_t assessment_result);
/**
* Create an unprocessed PB-Assessment-Result message from raw data
*
* @param data PB-Assessment-Result message data
*/
pb_tnc_msg_t* pb_assessment_result_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,352 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_error_msg.h"
#include <tnc/tnccs/tnccs.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <pen/pen.h>
#include <utils/debug.h>
ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE,
PB_ERROR_VERSION_NOT_SUPPORTED,
"Unexpected Batch Type",
"Invalid Parameter",
"Local Error",
"Unsupported Mandatory Message",
"Version Not Supported"
);
typedef struct private_pb_error_msg_t private_pb_error_msg_t;
/**
* PB-Error message (see section 4.9 of RFC 5793)
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Flags | Error Code Vendor ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Error Code | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Error Parameters (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define ERROR_FLAG_NONE 0x00
#define ERROR_FLAG_FATAL (1<<7)
#define ERROR_RESERVED 0x0000
#define ERROR_HEADER_SIZE 8
/**
* Private data of a pb_error_msg_t object.
*
*/
struct private_pb_error_msg_t {
/**
* Public pb_error_msg_t interface.
*/
pb_error_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Fatal flag
*/
bool fatal;
/**
* PB Error Code Vendor ID
*/
u_int32_t vendor_id;
/**
* PB Error Code
*/
u_int16_t error_code;
/**
* PB Error Offset
*/
u_int32_t error_offset;
/**
* Bad PB-TNC version received
*/
u_int8_t bad_version;
/**
* Encoded message
*/
chunk_t encoding;
/**
* reference count
*/
refcount_t ref;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_error_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_error_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_error_msg_t *this)
{
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
/* build message header */
writer = bio_writer_create(ERROR_HEADER_SIZE);
writer->write_uint8 (writer, this->fatal ?
ERROR_FLAG_FATAL : ERROR_FLAG_NONE);
writer->write_uint24(writer, this->vendor_id);
writer->write_uint16(writer, this->error_code);
writer->write_uint16(writer, ERROR_RESERVED);
/* build message body */
if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
{
/* Bad version */
writer->write_uint8(writer, this->bad_version);
writer->write_uint8(writer, PB_TNC_VERSION); /* Max version */
writer->write_uint8(writer, PB_TNC_VERSION); /* Min version */
writer->write_uint8(writer, 0x00); /* Reserved */
}
else
{
/* Error Offset */
writer->write_uint32(writer, this->error_offset);
}
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_error_msg_t *this, u_int32_t *offset)
{
u_int8_t flags, max_version, min_version;
u_int16_t reserved;
bio_reader_t *reader;
if (this->encoding.len < ERROR_HEADER_SIZE)
{
DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes",
pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE);
*offset = 0;
return FAILED;
}
/* process message header */
reader = bio_reader_create(this->encoding);
reader->read_uint8 (reader, &flags);
reader->read_uint24(reader, &this->vendor_id);
reader->read_uint16(reader, &this->error_code);
reader->read_uint16(reader, &reserved);
this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE;
if (this->vendor_id == PEN_IETF && reader->remaining(reader) == 4)
{
if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
{
reader->read_uint8(reader, &this->bad_version);
reader->read_uint8(reader, &max_version);
reader->read_uint8(reader, &min_version);
}
else
{
reader->read_uint32(reader, &this->error_offset);
}
}
reader->destroy(reader);
return SUCCESS;
}
METHOD(pb_tnc_msg_t, get_ref, pb_tnc_msg_t*,
private_pb_error_msg_t *this)
{
ref_get(&this->ref);
return &this->public.pb_interface;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_error_msg_t *this)
{
if (ref_put(&this->ref))
{
free(this->encoding.ptr);
free(this);
}
}
METHOD(pb_error_msg_t, get_fatal_flag, bool,
private_pb_error_msg_t *this)
{
return this->fatal;
}
METHOD(pb_error_msg_t, get_vendor_id, u_int32_t,
private_pb_error_msg_t *this)
{
return this->vendor_id;
}
METHOD(pb_error_msg_t, get_error_code, u_int16_t,
private_pb_error_msg_t *this)
{
return this->error_code;
}
METHOD(pb_error_msg_t, get_offset, u_int32_t,
private_pb_error_msg_t *this)
{
return this->error_offset;
}
METHOD(pb_error_msg_t, get_bad_version, u_int8_t,
private_pb_error_msg_t *this)
{
return this->bad_version;
}
METHOD(pb_error_msg_t, set_bad_version, void,
private_pb_error_msg_t *this, u_int8_t version)
{
this->bad_version = version;
}
/**
* See header
*/
pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
pb_tnc_error_code_t error_code)
{
private_pb_error_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_fatal_flag = _get_fatal_flag,
.get_vendor_id = _get_vendor_id,
.get_error_code = _get_error_code,
.get_offset = _get_offset,
.get_bad_version = _get_bad_version,
.set_bad_version = _set_bad_version,
},
.type = PB_MSG_ERROR,
.ref = 1,
.fatal = fatal,
.vendor_id = vendor_id,
.error_code = error_code,
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
pb_tnc_error_code_t error_code,
u_int32_t error_offset)
{
private_pb_error_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_fatal_flag = _get_fatal_flag,
.get_vendor_id = _get_vendor_id,
.get_error_code = _get_error_code,
.get_offset = _get_offset,
.get_bad_version = _get_bad_version,
.set_bad_version = _set_bad_version,
},
.type = PB_MSG_ERROR,
.ref = 1,
.fatal = fatal,
.vendor_id = vendor_id,
.error_code = error_code,
.error_offset = error_offset,
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_error_msg_create_from_data(chunk_t data)
{
private_pb_error_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_fatal_flag = _get_fatal_flag,
.get_vendor_id = _get_vendor_id,
.get_error_code = _get_error_code,
.get_offset = _get_offset,
.get_bad_version = _get_bad_version,
.set_bad_version = _set_bad_version,
},
.type = PB_MSG_ERROR,
.ref = 1,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
@@ -1,127 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_error_msg pb_error_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_ERROR_MSG_H_
#define PB_ERROR_MSG_H_
typedef enum pb_tnc_error_code_t pb_tnc_error_code_t;
typedef struct pb_error_msg_t pb_error_msg_t;
#include "pb_tnc_msg.h"
/**
* PB-TNC Error Codes as defined in section 4.9.1 of RFC 5793
*/
enum pb_tnc_error_code_t {
PB_ERROR_UNEXPECTED_BATCH_TYPE = 0,
PB_ERROR_INVALID_PARAMETER = 1,
PB_ERROR_LOCAL_ERROR = 2,
PB_ERROR_UNSUPPORTED_MANDATORY_MSG = 3,
PB_ERROR_VERSION_NOT_SUPPORTED = 4
};
/**
* enum name for pb_tnc_error_code_t.
*/
extern enum_name_t *pb_tnc_error_code_names;
/**
* Class representing the PB-Error message type.
*/
struct pb_error_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get the fatal flag
*
* @return fatal flag
*/
bool (*get_fatal_flag)(pb_error_msg_t *this);
/**
* Get PB Error code Vendor ID
*
* @return PB Error Code Vendor ID
*/
u_int32_t (*get_vendor_id)(pb_error_msg_t *this);
/**
* Get PB Error Code
*
* @return PB Error Code
*/
u_int16_t (*get_error_code)(pb_error_msg_t *this);
/**
* Get the PB Error Offset
*
* @return PB Error Offset
*/
u_int32_t (*get_offset)(pb_error_msg_t *this);
/**
* Get the PB Bad Version
*
* @return PB Bad Version
*/
u_int8_t (*get_bad_version)(pb_error_msg_t *this);
/**
* Set the PB Bad Version
*
* @param version PB Bad Version
*/
void (*set_bad_version)(pb_error_msg_t *this, u_int8_t version);
};
/**
* Create a PB-Error message from parameters
*
* @param fatal fatal flag
* @param vendor_id Error Code Vendor ID
* @param error_code Error Code
*/
pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
pb_tnc_error_code_t error_code);
/**
* Create a PB-Error message from parameters with offset field
*
* @param fatal fatal flag
* @param vendor_id Error Code Vendor ID
* @param error_code Error Code
* @param error_offset Error Offset
*/
pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
pb_tnc_error_code_t error_code,
u_int32_t error_offset);
/**
* Create an unprocessed PB-Error message from raw data
*
* @param data PB-Error message data
*/
pb_tnc_msg_t* pb_error_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,102 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_experimental_msg.h"
typedef struct private_pb_experimental_msg_t private_pb_experimental_msg_t;
/**
* Private data of a pb_experimental_msg_t object.
*
*/
struct private_pb_experimental_msg_t {
/**
* Public pb_experimental_msg_t interface.
*/
pb_experimental_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_experimental_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_experimental_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_experimental_msg_t *this)
{
/* nothing to do since message contents equal encoding */
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_experimental_msg_t *this, u_int32_t *offset)
{
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_experimental_msg_t *this)
{
free(this->encoding.ptr);
free(this);
}
/**
* See header
*/
pb_tnc_msg_t *pb_experimental_msg_create_from_data(chunk_t data)
{
private_pb_experimental_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
},
.type = PB_MSG_EXPERIMENTAL,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_experimental_msg_create(chunk_t body)
{
return pb_experimental_msg_create_from_data(body);
}
@@ -1,53 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_experimental_msg pb_experimental_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_EXPERIMENTAL_MSG_H_
#define PB_EXPERIMENTAL_MSG_H_
typedef struct pb_experimental_msg_t pb_experimental_msg_t;
#include "pb_tnc_msg.h"
/**
* Class representing the PB-Experimental message type.
*/
struct pb_experimental_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
};
/**
* Create a PB-Experimental message from parameters
*
* @param body message body
*/
pb_tnc_msg_t* pb_experimental_msg_create(chunk_t body);
/**
* Create an unprocessed PB-Experimental message from raw data
*
* @param data PB-Experimental message data
*/
pb_tnc_msg_t* pb_experimental_msg_create_from_data(chunk_t data);
#endif /** PB_EXPERIMENTAL_MSG_H_ @}*/
@@ -1,179 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_language_preference_msg.h"
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t;
/**
* PB-Language-Preference message (see section 4.10 of RFC 5793)
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Language Preference (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define PB_LANG_PREFIX "Accept-Language: "
#define PB_LANG_PREFIX_LEN strlen(PB_LANG_PREFIX)
/**
* Private data of a pb_language_preference_msg_t object.
*
*/
struct private_pb_language_preference_msg_t {
/**
* Public pb_access_recommendation_msg_t interface.
*/
pb_language_preference_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Language preference
*/
chunk_t language_preference;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_language_preference_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_language_preference_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_language_preference_msg_t *this)
{
if (this->encoding.ptr)
{
return;
}
this->encoding = chunk_cat("cc",
chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN),
this->language_preference);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_language_preference_msg_t *this, u_int32_t *offset)
{
chunk_t lang;
if (this->encoding.len >= PB_LANG_PREFIX_LEN &&
memeq(this->encoding.ptr, PB_LANG_PREFIX, PB_LANG_PREFIX_LEN))
{
lang = chunk_skip(this->encoding, PB_LANG_PREFIX_LEN);
this->language_preference = lang.len ? chunk_clone(lang) : chunk_empty;
}
else
{
DBG1(DBG_TNC, "language preference must be preceded by '%s'",
PB_LANG_PREFIX);
*offset = 0;
return FAILED;
}
if (this->language_preference.len &&
this->language_preference.ptr[this->language_preference.len-1] == '\0')
{
DBG1(DBG_TNC, "language preference must not be null terminated");
*offset = PB_LANG_PREFIX_LEN + this->language_preference.len - 1;
return FAILED;
}
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_language_preference_msg_t *this)
{
free(this->encoding.ptr);
free(this->language_preference.ptr);
free(this);
}
METHOD(pb_language_preference_msg_t, get_language_preference, chunk_t,
private_pb_language_preference_msg_t *this)
{
return this->language_preference;
}
/**
* See header
*/
pb_tnc_msg_t *pb_language_preference_msg_create_from_data(chunk_t data)
{
private_pb_language_preference_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_language_preference = _get_language_preference,
},
.type = PB_MSG_LANGUAGE_PREFERENCE,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_language_preference_msg_create(chunk_t language_preference)
{
private_pb_language_preference_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_language_preference = _get_language_preference,
},
.type = PB_MSG_LANGUAGE_PREFERENCE,
.language_preference = chunk_clone(language_preference),
);
return &this->public.pb_interface;
}
@@ -1,60 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_language_preference_msg pb_language_preference_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_LANGUAGE_PREFERENCE_MSG_H_
#define PB_LANGUAGE_PREFERENCE_MSG_H_
typedef struct pb_language_preference_msg_t pb_language_preference_msg_t;
#include "pb_tnc_msg.h"
/**
* Class representing the PB-Language-Preference message type.
*/
struct pb_language_preference_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get PB Language Preference
*
* @return Language preference
*/
chunk_t (*get_language_preference)(pb_language_preference_msg_t *this);
};
/**
* Create a PB-Language-Preference message from parameters
*
* @param language_preference Preferred language(s)
*/
pb_tnc_msg_t* pb_language_preference_msg_create(chunk_t language_preference);
/**
* Create an unprocessed PB-Language-Preference message from raw data
*
* @param data PB-Language-Preference message data
*/
pb_tnc_msg_t* pb_language_preference_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,274 +0,0 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
* Copyright (C) 2010 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 "pb_pa_msg.h"
#include <tnc/tnccs/tnccs.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <pen/pen.h>
#include <utils/debug.h>
typedef struct private_pb_pa_msg_t private_pb_pa_msg_t;
/**
* PB-PA message
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Flags | PA Message Vendor ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PA Subtype |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Posture Collector Identifier | Posture Validator Identifier |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PA Message Body (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define PA_FLAG_NONE 0x00
#define PA_FLAG_EXCL (1<<7)
#define PA_RESERVED_SUBTYPE 0xffffffff
/**
* Private data of a pb_pa_msg_t object.
*
*/
struct private_pb_pa_msg_t {
/**
* Public pb_pa_msg_t interface.
*/
pb_pa_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Exclusive flag
*/
bool excl;
/**
* Vendor-specific PA Subtype
*/
pen_type_t subtype;
/**
* Posture Validator Identifier
*/
u_int16_t collector_id;
/**
* Posture Validator Identifier
*/
u_int16_t validator_id;
/**
* PA Message Body
*/
chunk_t msg_body;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_pa_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_pa_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_pa_msg_t *this)
{
chunk_t msg_header;
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
/* build message header */
writer = bio_writer_create(64);
writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE);
writer->write_uint24(writer, this->subtype.vendor_id);
writer->write_uint32(writer, this->subtype.type);
writer->write_uint16(writer, this->collector_id);
writer->write_uint16(writer, this->validator_id);
msg_header = writer->get_buf(writer);
/* create encoding by concatenating message header and message body */
this->encoding = chunk_cat("cc", msg_header, this->msg_body);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_pa_msg_t *this, u_int32_t *offset)
{
u_int8_t flags;
size_t msg_body_len;
bio_reader_t *reader;
/* process message header */
reader = bio_reader_create(this->encoding);
reader->read_uint8 (reader, &flags);
reader->read_uint24(reader, &this->subtype.vendor_id);
reader->read_uint32(reader, &this->subtype.type);
reader->read_uint16(reader, &this->collector_id);
reader->read_uint16(reader, &this->validator_id);
this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
/* process message body */
msg_body_len = reader->remaining(reader);
if (msg_body_len)
{
reader->read_data(reader, msg_body_len, &this->msg_body);
this->msg_body = chunk_clone(this->msg_body);
}
reader->destroy(reader);
if (this->subtype.vendor_id == PEN_RESERVED)
{
DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
*offset = 1;
return FAILED;
}
if (this->subtype.type == PA_RESERVED_SUBTYPE)
{
DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
*offset = 4;
return FAILED;
}
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_pa_msg_t *this)
{
free(this->encoding.ptr);
free(this->msg_body.ptr);
free(this);
}
METHOD(pb_pa_msg_t, get_subtype, pen_type_t,
private_pb_pa_msg_t *this)
{
return this->subtype;
}
METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
private_pb_pa_msg_t *this)
{
return this->collector_id;
}
METHOD(pb_pa_msg_t, get_validator_id, u_int16_t,
private_pb_pa_msg_t *this)
{
return this->validator_id;
}
METHOD(pb_pa_msg_t, get_body, chunk_t,
private_pb_pa_msg_t *this)
{
return this->msg_body;
}
METHOD(pb_pa_msg_t, get_exclusive_flag, bool,
private_pb_pa_msg_t *this)
{
return this->excl;
}
/**
* See header
*/
pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
{
private_pb_pa_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.process = _process,
.destroy = _destroy,
},
.get_subtype = _get_subtype,
.get_collector_id = _get_collector_id,
.get_validator_id = _get_validator_id,
.get_body = _get_body,
.get_exclusive_flag = _get_exclusive_flag,
},
.type = PB_MSG_PA,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
u_int16_t collector_id, u_int16_t validator_id,
bool excl, chunk_t msg_body)
{
private_pb_pa_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_subtype= _get_subtype,
.get_collector_id = _get_collector_id,
.get_validator_id = _get_validator_id,
.get_body = _get_body,
.get_exclusive_flag = _get_exclusive_flag,
},
.type = PB_MSG_PA,
.subtype = { vendor_id, subtype },
.collector_id = collector_id,
.validator_id = validator_id,
.excl = excl,
.msg_body = chunk_clone(msg_body),
);
return &this->public.pb_interface;
}
@@ -1,98 +0,0 @@
/*
* Copyright (C) 2010 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 pb_pa_msg pb_pa_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_PA_MSG_H_
#define PB_PA_MSG_H_
typedef struct pb_pa_msg_t pb_pa_msg_t;
#include "pb_tnc_msg.h"
#include <pen/pen.h>
/**
* Class representing the PB-PA message type.
*/
struct pb_pa_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get PA Message Vendor ID and Subtype
*
* @return Vendor-specific PA Subtype
*/
pen_type_t (*get_subtype)(pb_pa_msg_t *this);
/**
* Get Posture Collector ID
*
* @return Posture Collector ID
*/
u_int16_t (*get_collector_id)(pb_pa_msg_t *this);
/**
* Get Posture Validator ID
*
* @return Posture Validator ID
*/
u_int16_t (*get_validator_id)(pb_pa_msg_t *this);
/**
* Get the PA Message Body
*
* @return PA Message Body
*/
chunk_t (*get_body)(pb_pa_msg_t *this);
/**
* Get the exclusive flag
*
* @return exclusive flag
*/
bool (*get_exclusive_flag)(pb_pa_msg_t *this);
};
/**
* Create a PB-PA message from parameters
*
* @param vendor_id PA Message Vendor ID
* @param subtype PA Subtype
* @param collector_id Posture Collector ID
* @param validator_id Posture Validator ID
* @param excl Exclusive Flag
* @param msg_body PA Message Body
*/
pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
u_int16_t collector_id, u_int16_t validator_id,
bool excl, chunk_t msg_body);
/**
* Create an unprocessed PB-PA message from raw data
*
* @param data PB-PA message data
*/
pb_tnc_msg_t* pb_pa_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,217 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_reason_string_msg.h"
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t;
/**
* PB-Language-Preference message (see section 4.11 of RFC 5793)
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reason String Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reason String (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Lang Code Len | Reason String Language Code (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Private data of a pb_reason_string_msg_t object.
*
*/
struct private_pb_reason_string_msg_t {
/**
* Public pb_reason_string_msg_t interface.
*/
pb_reason_string_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Reason string
*/
chunk_t reason_string;
/**
* Language code
*/
chunk_t language_code;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_reason_string_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_reason_string_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_reason_string_msg_t *this)
{
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
writer = bio_writer_create(64);
writer->write_data32(writer, this->reason_string);
writer->write_data8 (writer, this->language_code);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_reason_string_msg_t *this, u_int32_t *offset)
{
bio_reader_t *reader;
reader = bio_reader_create(this->encoding);
if (!reader->read_data32(reader, &this->reason_string))
{
DBG1(DBG_TNC, "could not parse reason string");
reader->destroy(reader);
*offset = 0;
return FAILED;
};
this->reason_string = chunk_clone(this->reason_string);
if (this->reason_string.len &&
this->reason_string.ptr[this->reason_string.len-1] == '\0')
{
DBG1(DBG_TNC, "reason string must not be null terminated");
reader->destroy(reader);
*offset = 3 + this->reason_string.len;
return FAILED;
}
if (!reader->read_data8(reader, &this->language_code))
{
DBG1(DBG_TNC, "could not parse language code");
reader->destroy(reader);
*offset = 4 + this->reason_string.len;
return FAILED;
};
this->language_code = chunk_clone(this->language_code);
reader->destroy(reader);
if (this->language_code.len &&
this->language_code.ptr[this->language_code.len-1] == '\0')
{
DBG1(DBG_TNC, "language code must not be null terminated");
*offset = 4 + this->reason_string.len + this->language_code.len;
return FAILED;
}
return SUCCESS;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_reason_string_msg_t *this)
{
free(this->encoding.ptr);
free(this->reason_string.ptr);
free(this->language_code.ptr);
free(this);
}
METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t,
private_pb_reason_string_msg_t *this)
{
return this->reason_string;
}
METHOD(pb_reason_string_msg_t, get_language_code, chunk_t,
private_pb_reason_string_msg_t *this)
{
return this->language_code;
}
/**
* See header
*/
pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data)
{
private_pb_reason_string_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_reason_string = _get_reason_string,
.get_language_code = _get_language_code,
},
.type = PB_MSG_REASON_STRING,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
/**
* See header
*/
pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string,
chunk_t language_code)
{
private_pb_reason_string_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_reason_string = _get_reason_string,
.get_language_code = _get_language_code,
},
.type = PB_MSG_REASON_STRING,
.reason_string = chunk_clone(reason_string),
.language_code = chunk_clone(language_code),
);
return &this->public.pb_interface;
}
@@ -1,69 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
/**
* @defgroup pb_reason_string_msg pb_reason_string_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_REASON_STRING_MSG_H_
#define PB_REASON_STRING_MSG_H_
typedef struct pb_reason_string_msg_t pb_reason_string_msg_t;
#include "pb_tnc_msg.h"
/**
* Class representing the PB-Reason-String message type.
*/
struct pb_reason_string_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get Reason String
*
* @return Reason string
*/
chunk_t (*get_reason_string)(pb_reason_string_msg_t *this);
/**
* Get Reason String Language Code
*
* @return Language code
*/
chunk_t (*get_language_code)(pb_reason_string_msg_t *this);
};
/**
* Create a PB-Reason-String message from parameters
*
* @param reason_string Reason string
* @param language_code Language code
*/
pb_tnc_msg_t* pb_reason_string_msg_create(chunk_t reason_string,
chunk_t language_code);
/**
* Create an unprocessed PB-Reason-String message from raw data
*
* @param data PB-Reason-String message data
*/
pb_tnc_msg_t* pb_reason_string_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,311 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_remediation_parameters_msg.h"
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING,
"Remediation-URI",
"Remediation-String"
);
typedef struct private_pb_remediation_parameters_msg_t private_pb_remediation_parameters_msg_t;
/**
* PB-Remediation-Parameters message (see section 4.8 of RFC 5793)
*
* 0 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 | Remediation Parameters Vendor ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remediation Parameters Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remediation Parameters (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* 0 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remediation String Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remediation String (Variable Length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Lang Code Len | Remediation String Lang Code (Variable Len) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Private data of a pb_remediation_parameters_msg_t object.
*
*/
struct private_pb_remediation_parameters_msg_t {
/**
* Public pb_remediation_parameters_msg_t interface.
*/
pb_remediation_parameters_msg_t public;
/**
* PB-TNC message type
*/
pb_tnc_msg_type_t type;
/**
* Remediation Parameters Type
*/
pen_type_t parameters_type;
/**
* Remediation Parameters
*/
chunk_t parameters;
/**
* Remediation String
*/
chunk_t string;
/**
* Remediation Language Code
*/
chunk_t lang_code;
/**
* Encoded message
*/
chunk_t encoding;
};
METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
private_pb_remediation_parameters_msg_t *this)
{
return this->type;
}
METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
private_pb_remediation_parameters_msg_t *this)
{
return this->encoding;
}
METHOD(pb_tnc_msg_t, build, void,
private_pb_remediation_parameters_msg_t *this)
{
bio_writer_t *writer;
if (this->encoding.ptr)
{
return;
}
writer = bio_writer_create(64);
writer->write_uint32(writer, this->parameters_type.vendor_id);
writer->write_uint32(writer, this->parameters_type.type);
writer->write_data32(writer, this->parameters);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
}
METHOD(pb_tnc_msg_t, process, status_t,
private_pb_remediation_parameters_msg_t *this, u_int32_t *offset)
{
bio_reader_t *reader;
u_int8_t reserved;
status_t status = SUCCESS;
u_char *pos;
*offset = 0;
/* process message */
reader = bio_reader_create(this->encoding);
reader->read_uint8 (reader, &reserved);
reader->read_uint24(reader, &this->parameters_type.vendor_id);
reader->read_uint32(reader, &this->parameters_type.type);
reader->read_data (reader, reader->remaining(reader), &this->parameters);
this->parameters = chunk_clone(this->parameters);
reader->destroy(reader);
if (this->parameters_type.vendor_id == PEN_IETF &&
this->parameters_type.type == PB_REMEDIATION_STRING)
{
reader = bio_reader_create(this->parameters);
status = FAILED;
*offset = 8;
if (!reader->read_data32(reader, &this->string))
{
DBG1(DBG_TNC, "insufficient data for remediation string");
goto end;
};
*offset += 4;
pos = memchr(this->string.ptr, '\0', this->string.len);
if (pos)
{
DBG1(DBG_TNC, "nul termination in remediation string");
*offset += (pos - this->string.ptr);
goto end;
}
*offset += this->string.len;
if (!reader->read_data8(reader, &this->lang_code))
{
DBG1(DBG_TNC, "insufficient data for remediation string lang code");
goto end;
};
*offset += 1;
pos = memchr(this->lang_code.ptr, '\0', this->lang_code.len);
if (pos)
{
DBG1(DBG_TNC, "nul termination in remediation string lang code");
*offset += (pos - this->lang_code.ptr);
goto end;
}
status = SUCCESS;
end:
reader->destroy(reader);
}
return status;
}
METHOD(pb_tnc_msg_t, destroy, void,
private_pb_remediation_parameters_msg_t *this)
{
free(this->encoding.ptr);
free(this->parameters.ptr);
free(this);
}
METHOD(pb_remediation_parameters_msg_t, get_parameters_type, pen_type_t,
private_pb_remediation_parameters_msg_t *this)
{
return this->parameters_type;
}
METHOD(pb_remediation_parameters_msg_t, get_parameters, chunk_t,
private_pb_remediation_parameters_msg_t *this)
{
return this->parameters;
}
METHOD(pb_remediation_parameters_msg_t, get_string, chunk_t,
private_pb_remediation_parameters_msg_t *this, chunk_t *lang_code)
{
if (lang_code)
{
*lang_code = this->lang_code;
}
return this->string;
}
/**
* See header
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
chunk_t parameters)
{
private_pb_remediation_parameters_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_parameters_type = _get_parameters_type,
.get_parameters = _get_parameters,
.get_uri = _get_parameters,
.get_string = _get_string,
},
.type = PB_MSG_REMEDIATION_PARAMETERS,
.parameters_type = parameters_type,
.parameters = chunk_clone(parameters),
);
return &this->public.pb_interface;
}
/**
* Described in header.
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri)
{
pen_type_t type = { PEN_IETF, PB_REMEDIATION_URI };
return pb_remediation_parameters_msg_create(type, uri);
}
/**
* Described in header.
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
chunk_t lang_code)
{
pb_tnc_msg_t *msg;
bio_writer_t *writer;
pen_type_t type = { PEN_IETF, PB_REMEDIATION_STRING };
/* limit language code to 255 octets */
lang_code.len = min(255, lang_code.len);
writer = bio_writer_create(4 + string.len + 1 + lang_code.len);
writer->write_data32(writer, string);
writer->write_data8 (writer, lang_code);
msg = pb_remediation_parameters_msg_create(type, writer->get_buf(writer));
writer->destroy(writer);
return msg;
}
/**
* See header
*/
pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
{
private_pb_remediation_parameters_msg_t *this;
INIT(this,
.public = {
.pb_interface = {
.get_type = _get_type,
.get_encoding = _get_encoding,
.build = _build,
.process = _process,
.destroy = _destroy,
},
.get_parameters_type = _get_parameters_type,
.get_parameters = _get_parameters,
.get_uri = _get_parameters,
.get_string = _get_string,
},
.type = PB_MSG_REMEDIATION_PARAMETERS,
.encoding = chunk_clone(data),
);
return &this->public.pb_interface;
}
@@ -1,118 +0,0 @@
/*
* Copyright (C) 2011-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 pb_remediation_parameters_msg pb_remediation_parameters_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_REMEDIATION_PARAMETERS_MSG_H_
#define PB_REMEDIATION_PARAMETERS_MSG_H_
typedef enum pb_tnc_remed_param_type_t pb_tnc_remed_param_type_t;
typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t;
#include "pb_tnc_msg.h"
#include <pen/pen.h>
/**
* PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793
*/
enum pb_tnc_remed_param_type_t {
PB_REMEDIATION_URI = 1,
PB_REMEDIATION_STRING = 2,
};
/**
* enum name for pb_tnc_remed_param_type_t.
*/
extern enum_name_t *pb_tnc_remed_param_type_names;
/**
* Class representing the PB-Remediation-Parameters message type.
*/
struct pb_remediation_parameters_msg_t {
/**
* PB-TNC Message interface
*/
pb_tnc_msg_t pb_interface;
/**
* Get the Remediation Parameters Type (Vendor ID and Type)
*
* @return Remediation Parameters Type
*/
pen_type_t (*get_parameters_type)(pb_remediation_parameters_msg_t *this);
/**
* Get the Remediation Parameters
*
* @return Remediation Parameters
*/
chunk_t (*get_parameters)(pb_remediation_parameters_msg_t *this);
/**
* Get the Remediation URI
*
* @return Remediation URI
*/
chunk_t (*get_uri)(pb_remediation_parameters_msg_t *this);
/**
* Get the Remediation String
*
* @param lang_code Optional Language Code
* @return Remediation String
*/
chunk_t (*get_string)(pb_remediation_parameters_msg_t *this,
chunk_t *lang_code);
};
/**
* Create a general PB-Remediation-Parameters message
*
* @param parameters_type Remediation Parameters Type
* @param parameters Remediation Parameters
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
chunk_t parameters);
/**
* Create a PB-Remediation-Parameters message of IETF Type Remediation URI
*
* @param uri Remediation URI
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri);
/**
* Create a PB-Remediation-Parameters message of IETF Type Remediation String
*
* @param string Remediation String
* @param lang_code Remediation String Language Code
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
chunk_t lang_code);
/**
* Create an unprocessed PB-Remediation-Parameters message from raw data
*
* @param data PB-Remediation-Parameters message data
*/
pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_data(chunk_t data);
#endif /** PB_PA_MSG_H_ @}*/
@@ -1,75 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_tnc_msg.h"
#include "pb_experimental_msg.h"
#include "pb_pa_msg.h"
#include "pb_error_msg.h"
#include "pb_language_preference_msg.h"
#include "pb_assessment_result_msg.h"
#include "pb_access_recommendation_msg.h"
#include "pb_remediation_parameters_msg.h"
#include "pb_reason_string_msg.h"
#include <library.h>
ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING,
"PB-Experimental",
"PB-PA",
"PB-Assessment-Result",
"PB-Access-Recommendation",
"PB-Remediation-Parameters",
"PB-Error",
"PB-Language-Preference",
"PB-Reason-String"
);
pb_tnc_msg_info_t pb_tnc_msg_infos[] = {
{ 12, FALSE, FALSE, TRUE_OR_FALSE },
{ 24, FALSE, FALSE, TRUE },
{ 16, TRUE, TRUE, TRUE },
{ 16, TRUE, TRUE, FALSE },
{ 20, FALSE, TRUE, FALSE },
{ 20, FALSE, FALSE, TRUE },
{ 12, FALSE, FALSE, FALSE },
{ 17, FALSE, TRUE, FALSE },
};
/**
* See header
*/
pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value)
{
switch (type)
{
case PB_MSG_PA:
return pb_pa_msg_create_from_data(value);
case PB_MSG_ERROR:
return pb_error_msg_create_from_data(value);
case PB_MSG_EXPERIMENTAL:
return pb_experimental_msg_create_from_data(value);
case PB_MSG_LANGUAGE_PREFERENCE:
return pb_language_preference_msg_create_from_data(value);
case PB_MSG_ASSESSMENT_RESULT:
return pb_assessment_result_msg_create_from_data(value);
case PB_MSG_ACCESS_RECOMMENDATION:
return pb_access_recommendation_msg_create_from_data(value);
case PB_MSG_REMEDIATION_PARAMETERS:
return pb_remediation_parameters_msg_create_from_data(value);
case PB_MSG_REASON_STRING:
return pb_reason_string_msg_create_from_data(value);
}
return NULL;
}
@@ -1,128 +0,0 @@
/*
* Copyright (C) 2010 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 pb_tnc_msg pb_tnc_msg
* @{ @ingroup tnccs_20
*/
#ifndef PB_TNC_MSG_H_
#define PB_TNC_MSG_H_
typedef enum pb_tnc_msg_type_t pb_tnc_msg_type_t;
typedef struct pb_tnc_msg_info_t pb_tnc_msg_info_t;
typedef struct pb_tnc_msg_t pb_tnc_msg_t;
#include <library.h>
#define PB_TNC_VERSION 2
/**
* PB-TNC Message Types as defined in section 4.3 of RFC 5793
*/
enum pb_tnc_msg_type_t {
PB_MSG_EXPERIMENTAL = 0,
PB_MSG_PA = 1,
PB_MSG_ASSESSMENT_RESULT = 2,
PB_MSG_ACCESS_RECOMMENDATION = 3,
PB_MSG_REMEDIATION_PARAMETERS = 4,
PB_MSG_ERROR = 5,
PB_MSG_LANGUAGE_PREFERENCE = 6,
PB_MSG_REASON_STRING = 7,
PB_MSG_ROOF = 7
};
/**
* enum name for pb_tnc_msg_type_t.
*/
extern enum_name_t *pb_tnc_msg_type_names;
/**
* Information entry describing a PB-TNC Message Type
*/
struct pb_tnc_msg_info_t {
u_int32_t min_size;
bool exact_size;
bool in_result_batch;
signed char has_noskip_flag;
};
#define TRUE_OR_FALSE 2
/**
* Information on PB-TNC Message Types
*/
extern pb_tnc_msg_info_t pb_tnc_msg_infos[];
/**
* Generic interface for all PB-TNC message types.
*
* To handle all messages in a generic way, this interface
* must be implemented by each message type.
*/
struct pb_tnc_msg_t {
/**
* Get the PB-TNC Message Type
*
* @return PB-TNC Message Type
*/
pb_tnc_msg_type_t (*get_type)(pb_tnc_msg_t *this);
/**
* Get the encoding of the PB-TNC Message Value
*
* @return encoded PB-TNC Message Value
*/
chunk_t (*get_encoding)(pb_tnc_msg_t *this);
/**
* Build the PB-TNC Message Value
*/
void (*build)(pb_tnc_msg_t *this);
/**
* Process the PB-TNC Message Value
*
* @param relative offset where an error occurred
* @return return processing status
*/
status_t (*process)(pb_tnc_msg_t *this, u_int32_t *offset);
/**
* Get a new reference to the message.
*
* @return this, with an increased refcount
*/
pb_tnc_msg_t* (*get_ref)(pb_tnc_msg_t *this);
/**
* Destroys a pb_tnc_msg_t object.
*/
void (*destroy)(pb_tnc_msg_t *this);
};
/**
* Create an unprocessed PB-TNC message
*
* Useful for the parser which wants a generic constructor for all
* pb_tnc_message_t types.
*
* @param type PB-TNC message type
* @param value PB-TNC message value
*/
pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value);
#endif /** PB_TNC_MSG_H_ @}*/
@@ -1,316 +0,0 @@
/*
* Copyright (C) 2010 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 "pb_tnc_state_machine.h"
#include <utils/debug.h>
ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END,
"Init",
"Server Working",
"Client Working",
"Decided",
"End"
);
/**
* PB-TNC State Machine (see section 3.2 of RFC 5793)
*
* Receive CRETRY SRETRY
* or SRETRY +----------------+
* +--+ | |
* v | v |
* +---------+ CRETRY +---------+
* CDATA | Server |<---------| Decided | CLOSE
* +----------->| Working |--------->| |-------+
* | +---------+ RESULT +---------+ |
* | ^ | | v
* | | | +---------------------->=======
* ======== | | CLOSE " End "
* " Init " CDATA| |SDATA =======
* ======== | | ^ ^
* | | | v | |
* | | SDATA +---------+ CLOSE | |
* | +-------->| Client |----------------------+ |
* | | Working | |
* | +---------+ |
* | | ^ |
* | +--+ |
* | Receive CRETRY |
* | CLOSE |
* +--------------------------------------------------+
*/
typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t;
/**
* Private data of a pb_tnc_state_machine_t object.
*
*/
struct private_pb_tnc_state_machine_t {
/**
* Public pb_pa_message_t interface.
*/
pb_tnc_state_machine_t public;
/**
* PB-TNC Server if TRUE, PB-TNC Client if FALSE
*/
bool is_server;
/**
* Informs whether last received PB-TNC CDATA Batch was empty
*/
bool empty_cdata;
/**
* Current PB-TNC state
*/
pb_tnc_state_t state;
};
METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t,
private_pb_tnc_state_machine_t *this)
{
return this->state;
}
METHOD(pb_tnc_state_machine_t, receive_batch, bool,
private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
{
pb_tnc_state_t old_state = this->state;
switch (this->state)
{
case PB_STATE_INIT:
if (this->is_server && type == PB_BATCH_CDATA)
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (!this->is_server && type == PB_BATCH_SDATA)
{
this->state = PB_STATE_CLIENT_WORKING;
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_SERVER_WORKING:
if (!this->is_server && (type == PB_BATCH_SDATA ||
type == PB_BATCH_SRETRY))
{
this->state = PB_STATE_CLIENT_WORKING;
break;
}
if (!this->is_server && type == PB_BATCH_RESULT)
{
this->state = PB_STATE_DECIDED;
break;
}
if (this->is_server && type == PB_BATCH_CRETRY)
{
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_CLIENT_WORKING:
if (this->is_server && type == PB_BATCH_CDATA)
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (this->is_server && type == PB_BATCH_CRETRY)
{
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_DECIDED:
if ((this->is_server && type == PB_BATCH_CRETRY) ||
(!this->is_server && type == PB_BATCH_SRETRY))
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_END:
if (type == PB_BATCH_CLOSE)
{
break;
}
return FALSE;
}
if (this->state != old_state)
{
DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
}
return TRUE;
}
METHOD(pb_tnc_state_machine_t, send_batch, bool,
private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
{
pb_tnc_state_t old_state = this->state;
switch (this->state)
{
case PB_STATE_INIT:
if (!this->is_server && type == PB_BATCH_CDATA)
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (this->is_server && type == PB_BATCH_SDATA)
{
this->state = PB_STATE_CLIENT_WORKING;
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_SERVER_WORKING:
if (this->is_server && (type == PB_BATCH_SDATA ||
type == PB_BATCH_SRETRY))
{
this->state = PB_STATE_CLIENT_WORKING;
break;
}
if (this->is_server && type == PB_BATCH_RESULT)
{
this->state = PB_STATE_DECIDED;
break;
}
if (!this->is_server && type == PB_BATCH_CRETRY)
{
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_CLIENT_WORKING:
if (!this->is_server && (type == PB_BATCH_CDATA ||
type == PB_BATCH_CRETRY))
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (this->is_server && type == PB_BATCH_SRETRY)
{
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_DECIDED:
if ((this->is_server && type == PB_BATCH_SRETRY) ||
(!this->is_server && type == PB_BATCH_CRETRY))
{
this->state = PB_STATE_SERVER_WORKING;
break;
}
if (type == PB_BATCH_CLOSE)
{
this->state = PB_STATE_END;
break;
}
return FALSE;
case PB_STATE_END:
if (type == PB_BATCH_CLOSE)
{
break;
}
return FALSE;
}
if (this->state != old_state)
{
DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
}
return TRUE;
}
METHOD(pb_tnc_state_machine_t, get_empty_cdata, bool,
private_pb_tnc_state_machine_t *this)
{
return this->empty_cdata;
}
METHOD(pb_tnc_state_machine_t, set_empty_cdata, void,
private_pb_tnc_state_machine_t *this, bool empty)
{
if (empty)
{
DBG2(DBG_TNC, "received empty PB-TNC CDATA batch");
}
this->empty_cdata = empty;
}
METHOD(pb_tnc_state_machine_t, destroy, void,
private_pb_tnc_state_machine_t *this)
{
free(this);
}
/**
* See header
*/
pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server)
{
private_pb_tnc_state_machine_t *this;
INIT(this,
.public = {
.get_state = _get_state,
.receive_batch = _receive_batch,
.send_batch = _send_batch,
.get_empty_cdata = _get_empty_cdata,
.set_empty_cdata = _set_empty_cdata,
.destroy = _destroy,
},
.is_server = is_server,
.state = PB_STATE_INIT,
);
return &this->public;
}
@@ -1,102 +0,0 @@
/*
* Copyright (C) 2010 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 pb_tnc_state_machine pb_tnc_state_machine
* @{ @ingroup tnccs_20
*/
#ifndef PB_TNC_STATE_MACHINE_H_
#define PB_TNC_STATE_MACHINE_H_
typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t;
typedef enum pb_tnc_state_t pb_tnc_state_t;
#include "batch/pb_tnc_batch.h"
#include <library.h>
/**
* PB-TNC States (state machine) as defined in section 3.2 of RFC 5793
*/
enum pb_tnc_state_t {
PB_STATE_INIT,
PB_STATE_SERVER_WORKING,
PB_STATE_CLIENT_WORKING,
PB_STATE_DECIDED,
PB_STATE_END,
};
/**
* enum name for pb_tnc_state_t.
*/
extern enum_name_t *pb_tnc_state_names;
/**
* Interface for the PB-TNC state machine.
*/
struct pb_tnc_state_machine_t {
/**
* Get the current PB-TNC STATE
*
* @return current state
*/
pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this);
/**
* Compute state transition due to received PB-TNC Batch
*
* @param type type of received batch
* @result TRUE if a valid transition was found, FALSE otherwise
*/
bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
/**
* Compute state transition due to sent PB-TNC Batch
*
* @param type type of sent batch
* @result TRUE if a valid transition was found, FALSE otherwise
*/
bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
/**
* Informs whether the last received PB-TNC CDATA Batch was empty
*
* @result TRUE if last received PB-TNC CDATA Batch was empty
*/
bool (*get_empty_cdata)(pb_tnc_state_machine_t *this);
/**
* Store information whether the received PB-TNC CDATA Batch was empty
*
* @param empty set to TRUE if received PB-TNC CDATA Batch was empty
*/
void (*set_empty_cdata)(pb_tnc_state_machine_t *this, bool empty);
/**
* Destroys a pb_tnc_state_machine_t object.
*/
void (*destroy)(pb_tnc_state_machine_t *this);
};
/**
* Create and initialize a PB-TNC state machine
*
* @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client
*/
pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server);
#endif /** PB_TNC_STATE_MACHINE_H_ @}*/
-943
View File
@@ -1,943 +0,0 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
* Copyright (C) 2010-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 "tnccs_20.h"
#include "batch/pb_tnc_batch.h"
#include "messages/pb_tnc_msg.h"
#include "messages/pb_pa_msg.h"
#include "messages/pb_error_msg.h"
#include "messages/pb_assessment_result_msg.h"
#include "messages/pb_access_recommendation_msg.h"
#include "messages/pb_remediation_parameters_msg.h"
#include "messages/pb_reason_string_msg.h"
#include "messages/pb_language_preference_msg.h"
#include "state_machine/pb_tnc_state_machine.h"
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
#include <tnc/tnc.h>
#include <tnc/tnccs/tnccs_manager.h>
#include <tnc/imc/imc_manager.h>
#include <tnc/imv/imv_manager.h>
#include <threading/mutex.h>
#include <utils/debug.h>
#include <collections/linked_list.h>
#include <pen/pen.h>
typedef struct private_tnccs_20_t private_tnccs_20_t;
/**
* Private data of a tnccs_20_t object.
*/
struct private_tnccs_20_t {
/**
* Public tnccs_t interface.
*/
tnccs_t public;
/**
* TNCC if TRUE, TNCS if FALSE
*/
bool is_server;
/**
* Server identity
*/
identification_t *server;
/**
* Client identity
*/
identification_t *peer;
/**
* Underlying TNC IF-T transport protocol
*/
tnc_ift_type_t transport;
/**
* Type of TNC client authentication
*/
u_int32_t auth_type;
/**
* PB-TNC State Machine
*/
pb_tnc_state_machine_t *state_machine;
/**
* Connection ID assigned to this TNCCS connection
*/
TNC_ConnectionID connection_id;
/**
* PB-TNC messages to be sent
*/
linked_list_t *messages;
/**
* Type of PB-TNC batch being constructed
*/
pb_tnc_batch_type_t batch_type;
/**
* Maximum PB-TNC batch size
*/
size_t max_batch_len;
/**
* Maximum PA-TNC message size
*/
size_t max_msg_len;
/**
* Mutex locking the batch in construction
*/
mutex_t *mutex;
/**
* Flag set while processing
*/
bool fatal_error;
/**
* Flag set by IMC/IMV RequestHandshakeRetry() function
*/
bool request_handshake_retry;
/**
* SendMessage() by IMC/IMV only allowed if flag is set
*/
bool send_msg;
/**
* Set of IMV recommendations (TNC Server only)
*/
recommendations_t *recs;
};
/**
* If the batch type changes then delete all accumulated PB-TNC messages
*/
void change_batch_type(private_tnccs_20_t *this, pb_tnc_batch_type_t batch_type)
{
pb_tnc_msg_t *msg;
if (batch_type != this->batch_type)
{
if (this->batch_type != PB_BATCH_NONE)
{
DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
pb_tnc_batch_type_names, this->batch_type);
while (this->messages->remove_last(this->messages,
(void**)&msg) == SUCCESS)
{
msg->destroy(msg);
}
}
this->batch_type = batch_type;
}
}
METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_UInt32 msg_flags,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
TNC_VendorID msg_vid,
TNC_MessageSubtype msg_subtype)
{
pb_tnc_msg_t *pb_tnc_msg;
pb_tnc_batch_type_t batch_type;
enum_name_t *pa_subtype_names;
bool excl;
if (!this->send_msg)
{
DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
this->is_server ? "IMV" : "IMC",
this->is_server ? imv_id : imc_id);
return TNC_RESULT_ILLEGAL_OPERATION;
}
excl = (msg_flags & TNC_MESSAGE_FLAGS_EXCLUSIVE) != 0;
pb_tnc_msg = pb_pa_msg_create(msg_vid, msg_subtype, imc_id, imv_id,
excl, chunk_create(msg, msg_len));
pa_subtype_names = get_pa_subtype_names(msg_vid);
if (pa_subtype_names)
{
DBG2(DBG_TNC, "creating PB-PA message type '%N/%N' 0x%06x/0x%08x",
pen_names, msg_vid, pa_subtype_names, msg_subtype,
msg_vid, msg_subtype);
}
else
{
DBG2(DBG_TNC, "creating PB-PA message type '%N' 0x%06x/0x%08x",
pen_names, msg_vid, msg_vid, msg_subtype);
}
/* adding PA message to SDATA or CDATA batch only */
batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA;
this->mutex->lock(this->mutex);
if (this->batch_type == PB_BATCH_NONE)
{
this->batch_type = batch_type;
}
if (this->batch_type == batch_type)
{
this->messages->insert_last(this->messages, pb_tnc_msg);
}
else
{
pb_tnc_msg->destroy(pb_tnc_msg);
}
this->mutex->unlock(this->mutex);
return TNC_RESULT_SUCCESS;
}
/**
* Handle a single PB-TNC message according to its type
*/
static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
{
switch (msg->get_type(msg))
{
case PB_MSG_EXPERIMENTAL:
/* nothing to do */
break;
case PB_MSG_PA:
{
pb_pa_msg_t *pa_msg;
pen_type_t msg_subtype;
u_int16_t imc_id, imv_id;
chunk_t msg_body;
bool excl;
enum_name_t *pa_subtype_names;
pa_msg = (pb_pa_msg_t*)msg;
msg_subtype = pa_msg->get_subtype(pa_msg);
msg_body = pa_msg->get_body(pa_msg);
imc_id = pa_msg->get_collector_id(pa_msg);
imv_id = pa_msg->get_validator_id(pa_msg);
excl = pa_msg->get_exclusive_flag(pa_msg);
pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
if (pa_subtype_names)
{
DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
pen_names, msg_subtype.vendor_id, pa_subtype_names,
msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
}
else
{
DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
msg_subtype.type);
}
this->send_msg = TRUE;
if (this->is_server)
{
tnc->imvs->receive_message(tnc->imvs, this->connection_id,
excl, msg_body.ptr, msg_body.len,
msg_subtype.vendor_id,
msg_subtype.type, imc_id, imv_id);
}
else
{
tnc->imcs->receive_message(tnc->imcs, this->connection_id,
excl, msg_body.ptr, msg_body.len,
msg_subtype.vendor_id,
msg_subtype.type, imv_id, imc_id);
}
this->send_msg = FALSE;
break;
}
case PB_MSG_ASSESSMENT_RESULT:
{
pb_assessment_result_msg_t *assess_msg;
u_int32_t result;
assess_msg = (pb_assessment_result_msg_t*)msg;
result = assess_msg->get_assessment_result(assess_msg);
DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
TNC_IMV_Evaluation_Result_names, result);
break;
}
case PB_MSG_ACCESS_RECOMMENDATION:
{
pb_access_recommendation_msg_t *rec_msg;
pb_access_recommendation_code_t rec;
TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
rec_msg = (pb_access_recommendation_msg_t*)msg;
rec = rec_msg->get_access_recommendation(rec_msg);
DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
pb_access_recommendation_code_names, rec);
switch (rec)
{
case PB_REC_ACCESS_ALLOWED:
state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
break;
case PB_REC_ACCESS_DENIED:
state = TNC_CONNECTION_STATE_ACCESS_NONE;
break;
case PB_REC_QUARANTINED:
state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
}
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
state);
break;
}
case PB_MSG_REMEDIATION_PARAMETERS:
{
pb_remediation_parameters_msg_t *rem_msg;
pen_type_t parameters_type;
chunk_t parameters, string, lang_code;
rem_msg = (pb_remediation_parameters_msg_t*)msg;
parameters_type = rem_msg->get_parameters_type(rem_msg);
parameters = rem_msg->get_parameters(rem_msg);
if (parameters_type.vendor_id == PEN_IETF)
{
switch (parameters_type.type)
{
case PB_REMEDIATION_URI:
DBG1(DBG_TNC, "remediation uri: %.*s",
parameters.len, parameters.ptr);
break;
case PB_REMEDIATION_STRING:
string = rem_msg->get_string(rem_msg, &lang_code);
DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s",
lang_code.len, lang_code.ptr,
string.len, string.ptr);
break;
default:
DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
}
}
else
{
DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
}
break;
}
case PB_MSG_ERROR:
{
pb_error_msg_t *err_msg;
bool fatal;
u_int32_t vendor_id;
u_int16_t error_code;
err_msg = (pb_error_msg_t*)msg;
fatal = err_msg->get_fatal_flag(err_msg);
vendor_id = err_msg->get_vendor_id(err_msg);
error_code = err_msg->get_error_code(err_msg);
if (fatal)
{
this->fatal_error = TRUE;
}
if (vendor_id == PEN_IETF)
{
switch (error_code)
{
case PB_ERROR_INVALID_PARAMETER:
case PB_ERROR_UNSUPPORTED_MANDATORY_MSG:
DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
"(offset %u bytes)",
fatal ? "fatal" : "non-fatal",
pb_tnc_error_code_names, error_code,
err_msg->get_offset(err_msg));
break;
case PB_ERROR_VERSION_NOT_SUPPORTED:
DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
"caused by bad version 0x%02x",
fatal ? "fatal" : "non-fatal",
pb_tnc_error_code_names, error_code,
err_msg->get_bad_version(err_msg));
break;
case PB_ERROR_UNEXPECTED_BATCH_TYPE:
case PB_ERROR_LOCAL_ERROR:
default:
DBG1(DBG_TNC, "received %s PB-TNC error '%N'",
fatal ? "fatal" : "non-fatal",
pb_tnc_error_code_names, error_code);
break;
}
}
else
{
DBG1(DBG_TNC, "received %s PB-TNC error (%u) "
"with Vendor ID 0x%06x",
fatal ? "fatal" : "non-fatal",
error_code, vendor_id);
}
break;
}
case PB_MSG_LANGUAGE_PREFERENCE:
{
pb_language_preference_msg_t *lang_msg;
chunk_t lang;
lang_msg = (pb_language_preference_msg_t*)msg;
lang = lang_msg->get_language_preference(lang_msg);
if (this->recs)
{
DBG2(DBG_TNC, "setting language preference to '%.*s'",
(int)lang.len, lang.ptr);
this->recs->set_preferred_language(this->recs, lang);
}
break;
}
case PB_MSG_REASON_STRING:
{
pb_reason_string_msg_t *reason_msg;
chunk_t reason_string, language_code;
reason_msg = (pb_reason_string_msg_t*)msg;
reason_string = reason_msg->get_reason_string(reason_msg);
language_code = reason_msg->get_language_code(reason_msg);
DBG1(DBG_TNC, "reason string is '%.*s' [%.*s]",
(int)reason_string.len, reason_string.ptr,
(int)language_code.len, language_code.ptr);
break;
}
default:
break;
}
}
/**
* Build a CRETRY or SRETRY batch
*/
static void build_retry_batch(private_tnccs_20_t *this)
{
pb_tnc_batch_type_t batch_retry_type;
batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
if (this->batch_type == batch_retry_type)
{
/* retry batch has already been selected */
return;
}
change_batch_type(this, batch_retry_type);
if (this->is_server)
{
this->recs->clear_recommendation(this->recs);
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
}
}
METHOD(tls_t, process, status_t,
private_tnccs_20_t *this, void *buf, size_t buflen)
{
chunk_t data;
pb_tnc_batch_t *batch;
pb_tnc_msg_t *msg;
enumerator_t *enumerator;
status_t status;
if (this->is_server && !this->connection_id)
{
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_2_0, (tnccs_t*)this, _send_msg,
&this->request_handshake_retry,
this->max_msg_len, &this->recs);
if (!this->connection_id)
{
return FAILED;
}
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_CREATE);
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
}
data = chunk_create(buf, buflen);
DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u",
data.len, this->connection_id);
DBG3(DBG_TNC, "%B", &data);
batch = pb_tnc_batch_create_from_data(this->is_server, data);
status = batch->process(batch, this->state_machine);
if (status != FAILED)
{
enumerator_t *enumerator;
pb_tnc_msg_t *msg;
pb_tnc_batch_type_t batch_type;
bool empty = TRUE;
batch_type = batch->get_type(batch);
if (batch_type == PB_BATCH_CRETRY)
{
/* Send an SRETRY batch in response */
this->mutex->lock(this->mutex);
build_retry_batch(this);
this->mutex->unlock(this->mutex);
}
else if (batch_type == PB_BATCH_SRETRY)
{
/* Restart the measurements */
tnc->imcs->notify_connection_change(tnc->imcs,
this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
this->send_msg = TRUE;
tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
this->send_msg = FALSE;
}
enumerator = batch->create_msg_enumerator(batch);
while (enumerator->enumerate(enumerator, &msg))
{
handle_message(this, msg);
empty = FALSE;
}
enumerator->destroy(enumerator);
/* received an empty CLOSE batch from PB-TNC client */
if (this->is_server && batch_type == PB_BATCH_CLOSE && empty)
{
batch->destroy(batch);
if (this->fatal_error)
{
DBG1(DBG_TNC, "a fatal PB-TNC error occurred, "
"terminating connection");
return FAILED;
}
else
{
return SUCCESS;
}
}
this->send_msg = TRUE;
if (this->is_server)
{
tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
}
else
{
tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
}
this->send_msg = FALSE;
}
switch (status)
{
case FAILED:
this->fatal_error = TRUE;
this->mutex->lock(this->mutex);
change_batch_type(this, PB_BATCH_CLOSE);
this->mutex->unlock(this->mutex);
/* fall through to add error messages to outbound batch */
case VERIFY_ERROR:
enumerator = batch->create_error_enumerator(batch);
while (enumerator->enumerate(enumerator, &msg))
{
this->mutex->lock(this->mutex);
this->messages->insert_last(this->messages, msg->get_ref(msg));
this->mutex->unlock(this->mutex);
}
enumerator->destroy(enumerator);
break;
case SUCCESS:
default:
break;
}
batch->destroy(batch);
return NEED_MORE;
}
/**
* Build a RESULT batch if a final recommendation is available
*/
static void check_and_build_recommendation(private_tnccs_20_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
TNC_ConnectionState state;
TNC_IMVID id;
chunk_t reason, language;
enumerator_t *enumerator;
pb_tnc_msg_t *msg;
pb_access_recommendation_code_t pb_rec;
if (!this->recs->have_recommendation(this->recs, &rec, &eval))
{
tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
}
if (this->recs->have_recommendation(this->recs, &rec, &eval))
{
this->batch_type = PB_BATCH_RESULT;
msg = pb_assessment_result_msg_create(eval);
this->messages->insert_last(this->messages, msg);
/**
* Map IMV Action Recommendation codes to PB Access Recommendation codes
* and communicate Access Recommendation to IMVs
*/
switch (rec)
{
case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
pb_rec = PB_REC_ACCESS_ALLOWED;
break;
case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
pb_rec = PB_REC_QUARANTINED;
break;
case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
default:
state = TNC_CONNECTION_STATE_ACCESS_NONE;
pb_rec = PB_REC_ACCESS_DENIED;
}
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
state);
msg = pb_access_recommendation_msg_create(pb_rec);
this->messages->insert_last(this->messages, msg);
enumerator = this->recs->create_reason_enumerator(this->recs);
while (enumerator->enumerate(enumerator, &id, &reason, &language))
{
msg = pb_reason_string_msg_create(reason, language);
this->messages->insert_last(this->messages, msg);
}
enumerator->destroy(enumerator);
}
}
METHOD(tls_t, build, status_t,
private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
{
status_t status;
pb_tnc_state_t state;
/* Initialize the connection */
if (!this->is_server && !this->connection_id)
{
pb_tnc_msg_t *msg;
char *pref_lang;
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_2_0, (tnccs_t*)this, _send_msg,
&this->request_handshake_retry,
this->max_msg_len, NULL);
if (!this->connection_id)
{
return FAILED;
}
/* Create PB-TNC Language Preference message */
pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
msg = pb_language_preference_msg_create(chunk_create(pref_lang,
strlen(pref_lang)));
this->mutex->lock(this->mutex);
this->batch_type = PB_BATCH_CDATA;
this->messages->insert_last(this->messages, msg);
this->mutex->unlock(this->mutex);
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
TNC_CONNECTION_STATE_CREATE);
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
this->send_msg = TRUE;
tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
this->send_msg = FALSE;
}
state = this->state_machine->get_state(this->state_machine);
if (this->fatal_error && state == PB_STATE_END)
{
DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
return FAILED;
}
/* Do not allow any asynchronous IMCs or IMVs to add additional messages */
this->mutex->lock(this->mutex);
if (this->request_handshake_retry)
{
if (state != PB_STATE_INIT)
{
build_retry_batch(this);
}
/* Reset the flag for the next handshake retry request */
this->request_handshake_retry = FALSE;
}
if (this->is_server && state == PB_STATE_SERVER_WORKING &&
this->recs->have_recommendation(this->recs, NULL, NULL))
{
check_and_build_recommendation(this);
}
if (this->batch_type == PB_BATCH_NONE)
{
if (this->is_server)
{
if (state == PB_STATE_SERVER_WORKING)
{
if (this->state_machine->get_empty_cdata(this->state_machine))
{
check_and_build_recommendation(this);
}
else
{
DBG2(DBG_TNC, "no recommendation available yet, "
"sending empty PB-TNC SDATA batch");
this->batch_type = PB_BATCH_SDATA;
}
}
}
else
{
switch (state)
{
case PB_STATE_CLIENT_WORKING:
DBG2(DBG_TNC, "no client data to send, "
"sending empty PB-TNC CDATA batch");
this->batch_type = PB_BATCH_CDATA;
break;
case PB_STATE_DECIDED:
/**
* In the DECIDED state and if no CRETRY is under way,
* a PB-TNC client replies with an empty CLOSE batch.
*/
this->batch_type = PB_BATCH_CLOSE;
break;
default:
break;
}
}
}
if (this->batch_type != PB_BATCH_NONE)
{
pb_tnc_batch_t *batch;
pb_tnc_msg_t *msg;
chunk_t data;
int msg_count;
enumerator_t *enumerator;
if (this->state_machine->send_batch(this->state_machine, this->batch_type))
{
batch = pb_tnc_batch_create(this->is_server, this->batch_type,
min(this->max_batch_len, *buflen));
enumerator = this->messages->create_enumerator(this->messages);
while (enumerator->enumerate(enumerator, &msg))
{
if (batch->add_msg(batch, msg))
{
this->messages->remove_at(this->messages, enumerator);
}
else
{
break;
}
}
enumerator->destroy(enumerator);
batch->build(batch);
data = batch->get_encoding(batch);
DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
pb_tnc_batch_type_names, this->batch_type, data.len,
this->connection_id);
DBG3(DBG_TNC, "%B", &data);
*buflen = data.len;
*msglen = 0;
memcpy(buf, data.ptr, *buflen);
batch->destroy(batch);
msg_count = this->messages->get_count(this->messages);
if (msg_count)
{
DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
msg_count, (msg_count == 1) ? "" : "s",
pb_tnc_batch_type_names, this->batch_type);
}
else
{
this->batch_type = PB_BATCH_NONE;
}
status = ALREADY_DONE;
}
else
{
change_batch_type(this, PB_BATCH_NONE);
status = INVALID_STATE;
}
}
else
{
DBG1(DBG_TNC, "no PB-TNC batch to send");
status = INVALID_STATE;
}
this->mutex->unlock(this->mutex);
return status;
}
METHOD(tls_t, is_server, bool,
private_tnccs_20_t *this)
{
return this->is_server;
}
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_20_t *this)
{
return this->server;
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_20_t *this)
{
return this->peer;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
private_tnccs_20_t *this)
{
return TLS_PURPOSE_EAP_TNC;
}
METHOD(tls_t, is_complete, bool,
private_tnccs_20_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
{
return tnc->imvs->enforce_recommendation(tnc->imvs, rec, eval);
}
else
{
return FALSE;
}
}
METHOD(tls_t, get_eap_msk, chunk_t,
private_tnccs_20_t *this)
{
return chunk_empty;
}
METHOD(tls_t, destroy, void,
private_tnccs_20_t *this)
{
tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
this->is_server);
this->server->destroy(this->server);
this->peer->destroy(this->peer);
this->state_machine->destroy(this->state_machine);
this->mutex->destroy(this->mutex);
this->messages->destroy_offset(this->messages,
offsetof(pb_tnc_msg_t, destroy));
free(this);
}
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_20_t *this)
{
return this->transport;
}
METHOD(tnccs_t, set_transport, void,
private_tnccs_20_t *this, tnc_ift_type_t transport)
{
this->transport = transport;
}
METHOD(tnccs_t, get_auth_type, u_int32_t,
private_tnccs_20_t *this)
{
return this->auth_type;
}
METHOD(tnccs_t, set_auth_type, void,
private_tnccs_20_t *this, u_int32_t auth_type)
{
this->auth_type = auth_type;
}
/**
* See header
*/
tnccs_t* tnccs_20_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport)
{
private_tnccs_20_t *this;
INIT(this,
.public = {
.tls = {
.process = _process,
.build = _build,
.is_server = _is_server,
.get_server_id = _get_server_id,
.get_peer_id = _get_peer_id,
.get_purpose = _get_purpose,
.is_complete = _is_complete,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
.set_auth_type = _set_auth_type,
},
.is_server = is_server,
.server = server->clone(server),
.peer = peer->clone(peer),
.transport = transport,
.state_machine = pb_tnc_state_machine_create(is_server),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.messages = linked_list_create(),
.max_batch_len = lib->settings->get_int(lib->settings,
"%s.plugins.tnccs-20.max_batch_size", 65522,
"charon"),
.max_msg_len = lib->settings->get_int(lib->settings,
"%s.plugins.tnccs-20.max_message_size", 65490,
"charon"),
);
return &this->public;
}
-42
View File
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010-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 tnccs_20_h tnccs_20
* @{ @ingroup tnccs_20
*/
#ifndef TNCCS_20_H_
#define TNCCS_20_H_
#include <library.h>
#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of the TNC IF-TNCCS 2.0 protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
* @param server Server identity
* @param peer Client identity
* @param transport Underlying IF-T transport protocol
* @return TNC_IF_TNCCS 2.0 protocol stack
*/
tnccs_t* tnccs_20_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport);
#endif /** TNCCS_20_H_ @}*/
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2010 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 "tnccs_20_plugin.h"
#include "tnccs_20.h"
#include <tnc/tnccs/tnccs_manager.h>
METHOD(plugin_t, get_name, char*,
tnccs_20_plugin_t *this)
{
return "tnccs-20";
}
METHOD(plugin_t, get_features, int,
tnccs_20_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnccs_method_register, tnccs_20_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-2.0"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
tnccs_20_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *tnccs_20_plugin_create()
{
tnccs_20_plugin_t *this;
INIT(this,
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
);
return &this->plugin;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2010 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 tnccs_20 tnccs_20
* @ingroup cplugins
*
* @defgroup tnccs_20_plugin tnccs_20_plugin
* @{ @ingroup tnccs_20
*/
#ifndef TNCCS_20_PLUGIN_H_
#define TNCCS_20_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct tnccs_20_plugin_t tnccs_20_plugin_t;
/**
* EAP-TNC plugin
*/
struct tnccs_20_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** TNCCS_20_PLUGIN_H_ @}*/
@@ -1,22 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
-rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
else
plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
libstrongswan_tnccs_dynamic_la_LIBADD = \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libtnccs/libtnccs.la
endif
libstrongswan_tnccs_dynamic_la_SOURCES = \
tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c
libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version
@@ -1,223 +0,0 @@
/*
* Copyright (C) 2011-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 "tnccs_dynamic.h"
#include <tnc/tnc.h>
#include <utils/debug.h>
typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t;
/**
* Private data of a tnccs_dynamic_t object.
*/
struct private_tnccs_dynamic_t {
/**
* Public tnccs_t interface.
*/
tnccs_t public;
/**
* Server identity
*/
identification_t *server;
/**
* Client identity
*/
identification_t *peer;
/**
* Detected TNC IF-TNCCS stack
*/
tls_t *tls;
/**
* Underlying TNC IF-T transport protocol
*/
tnc_ift_type_t transport;
/**
* Type of TNC client authentication
*/
u_int32_t auth_type;
};
/**
* Determine the version of the IF-TNCCS protocol used by analyzing the first
* byte of the TNCCS batch received from a TNC Client according to the rules
* defined by section 3.5 "Interoperability with older IF-TNCCS versions" of
* the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard.
*/
tnccs_type_t determine_tnccs_protocol(char version)
{
switch (version)
{
case '\t':
case '\n':
case '\r':
case ' ':
case '<':
return TNCCS_1_1;
case 0x00:
return TNCCS_SOH;
case 0x02:
return TNCCS_2_0;
default:
return TNCCS_UNKNOWN;
}
}
METHOD(tls_t, process, status_t,
private_tnccs_dynamic_t *this, void *buf, size_t buflen)
{
tnccs_type_t type;
tnccs_t *tnccs;
if (!this->tls)
{
if (buflen == 0)
{
return FAILED;
}
type = determine_tnccs_protocol(*(char*)buf);
DBG1(DBG_TNC, "%N protocol detected dynamically",
tnccs_type_names, type);
tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE,
this->server, this->peer, this->transport);
if (!tnccs)
{
DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type);
return FAILED;
}
tnccs->set_auth_type(tnccs, this->auth_type);
this->tls = &tnccs->tls;
}
return this->tls->process(this->tls, buf, buflen);
}
METHOD(tls_t, build, status_t,
private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen)
{
return this->tls->build(this->tls, buf, buflen, msglen);
}
METHOD(tls_t, is_server, bool,
private_tnccs_dynamic_t *this)
{
return TRUE;
}
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_dynamic_t *this)
{
return this->server;
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_dynamic_t *this)
{
return this->peer;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
private_tnccs_dynamic_t *this)
{
return TLS_PURPOSE_EAP_TNC;
}
METHOD(tls_t, is_complete, bool,
private_tnccs_dynamic_t *this)
{
return this->tls ? this->tls->is_complete(this->tls) : FALSE;
}
METHOD(tls_t, get_eap_msk, chunk_t,
private_tnccs_dynamic_t *this)
{
return chunk_empty;
}
METHOD(tls_t, destroy, void,
private_tnccs_dynamic_t *this)
{
DESTROY_IF(this->tls);
this->server->destroy(this->server);
this->peer->destroy(this->peer);
free(this);
}
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_dynamic_t *this)
{
return this->transport;
}
METHOD(tnccs_t, set_transport, void,
private_tnccs_dynamic_t *this, tnc_ift_type_t transport)
{
this->transport = transport;
}
METHOD(tnccs_t, get_auth_type, u_int32_t,
private_tnccs_dynamic_t *this)
{
return this->auth_type;
}
METHOD(tnccs_t, set_auth_type, void,
private_tnccs_dynamic_t *this, u_int32_t auth_type)
{
this->auth_type = auth_type;
}
/**
* See header
*/
tnccs_t* tnccs_dynamic_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport)
{
private_tnccs_dynamic_t *this;
INIT(this,
.public = {
.tls = {
.process = _process,
.build = _build,
.is_server = _is_server,
.get_server_id = _get_server_id,
.get_peer_id = _get_peer_id,
.get_purpose = _get_purpose,
.is_complete = _is_complete,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
.set_auth_type = _set_auth_type,
},
.server = server->clone(server),
.peer = peer->clone(peer),
.transport = transport,
);
return &this->public;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2011-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 tnccs_dynamic_h tnccs_dynamic
* @{ @ingroup tnccs_dynamic
*/
#ifndef TNCCS_DYNAMIC_H_
#define TNCCS_DYNAMIC_H_
#include <library.h>
#include <tnc/tnccs/tnccs.h>
/**
* Create an instance of a dynamic TNC IF-TNCCS protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
* @param server Server identity
* @param peer Client identity
* @param transport Underlying IF-T transport protocol
* @return dynamic TNC IF-TNCCS protocol stack
*/
tnccs_t* tnccs_dynamic_create(bool is_server,
identification_t *server,
identification_t *peer,
tnc_ift_type_t transport);
#endif /** TNCCS_DYNAMIC_H_ @}*/
@@ -1,62 +0,0 @@
/*
* Copyright (C) 2011 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 "tnccs_dynamic_plugin.h"
#include "tnccs_dynamic.h"
#include <tnc/tnccs/tnccs_manager.h>
METHOD(plugin_t, get_name, char*,
tnccs_dynamic_plugin_t *this)
{
return "tnccs-dynamic";
}
METHOD(plugin_t, get_features, int,
tnccs_dynamic_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK(tnccs_method_register, tnccs_dynamic_create),
PLUGIN_PROVIDE(CUSTOM, "tnccs-dynamic"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-1.1"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-2.0"),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
tnccs_dynamic_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *tnccs_dynamic_plugin_create()
{
tnccs_dynamic_plugin_t *this;
INIT(this,
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
);
return &this->plugin;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2011 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 tnccs_dynamic tnccs_dynamic
* @ingroup cplugins
*
* @defgroup tnccs_dynamic_plugin tnccs_dynamic_plugin
* @{ @ingroup tnccs_dynamic
*/
#ifndef TNCCS_DYNAMIC_PLUGIN_H_
#define TNCCS_DYNAMIC_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct tnccs_dynamic_plugin_t tnccs_dynamic_plugin_t;
/**
* EAP-TNC plugin
*/
struct tnccs_dynamic_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** TNCCS_DYNAMIC_PLUGIN_H_ @}*/