implemented TNCCS 1.1 without libtnc

This commit is contained in:
Andreas Steffen
2011-01-07 05:29:59 +01:00
parent cfa190bb7c
commit d9e21bf180
20 changed files with 2192 additions and 188 deletions
@@ -0,0 +1,284 @@
/*
* 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 <debug.h>
#include <utils/linked_list.h>
#include <tnc/tnccs/tnccs.h>
#include <libxml/parser.h>
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;
/**
* 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((u_char*)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;
xmlNodePtr cur;
xmlNsPtr ns;
xmlChar *batchid, *recipient;
int batch_id;
status_t status;
this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len);
if (!this->doc)
{
DBG1(DBG_TNC, "failed to parse XML message");
return FAILED;
}
/* check out the XML document */
cur = xmlDocGetRootElement(this->doc);
if (!cur)
{
DBG1(DBG_TNC, "empty XML document");
return FAILED;
}
/* check TNCCS namespace */
ns = xmlSearchNsByHref(this->doc, cur, (const xmlChar*)
"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
if (!ns)
{
DBG1(DBG_TNC, "TNCCS namespace not found");
return FAILED;
}
/* check XML document type */
if (xmlStrcmp(cur->name, (const xmlChar*)"TNCCS-Batch"))
{
DBG1(DBG_TNC, "wrong XML document type '%s', expected TNCCS-Batch",
cur->name);
return FAILED;
}
/* check presence of BatchID property */
batchid = xmlGetProp(cur, (const xmlChar*)"BatchId");
if (!batchid)
{
DBG1(DBG_TNC, "BatchId is missing");
return FAILED;
}
/* check BatchID */
batch_id = atoi((char*)batchid);
xmlFree(batchid);
if (batch_id != this->batch_id)
{
DBG1(DBG_TNC, "BatchID %d expected, got %d", this->batch_id, batch_id);
return FAILED;
}
/* check presence of Recipient property */
recipient = xmlGetProp(cur, (const xmlChar*)"Recipient");
if (!recipient)
{
DBG1(DBG_TNC, "Recipient is missing");
return FAILED;
}
/* check recipient */
if (!streq((char*)recipient, this->is_server ? "TNCS" : "TNCC"))
{
DBG1(DBG_TNC, "message recipient expected '%s', got '%s'",
this->is_server ? "TNCS" : "TNCC", (char*)recipient);
xmlFree(recipient);
return FAILED;
}
xmlFree(recipient);
/* 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",
(char*)cur->name);
continue;
}
tnccs_msg = tnccs_msg_create_from_node(cur);
if (!tnccs_msg)
{
continue;
}
status = tnccs_msg->process(tnccs_msg);
if (status == FAILED)
{
tnccs_msg->destroy(tnccs_msg);
return FAILED;
}
this->messages->insert_last(this->messages, tnccs_msg);
}
return SUCCESS;
}
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, destroy, void,
private_tnccs_batch_t *this)
{
this->messages->destroy_offset(this->messages,
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;
char buf[12];
const char *recipient;
INIT(this,
.public = {
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.destroy = _destroy,
},
.is_server = is_server,
.messages = linked_list_create(),
.batch_id = batch_id,
.doc = xmlNewDoc(BAD_CAST "1.0"),
);
DBG2(DBG_TNC, "creating TNCCS Batch #%d", this->batch_id);
n = xmlNewNode(NULL, BAD_CAST "TNCCS-Batch");
snprintf(buf, sizeof(buf), "%d", batch_id);
recipient = this->is_server ? "TNCC" : "TNCS";
xmlNewProp(n, BAD_CAST "BatchId", BAD_CAST buf);
xmlNewProp(n, BAD_CAST "Recipient", BAD_CAST recipient);
xmlNewProp(n, BAD_CAST "xmlns", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
xmlNewProp(n, BAD_CAST "xmlns:xsi", BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
xmlNewProp(n, BAD_CAST "xsi:schemaLocation", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS# "
"https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.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,
.destroy = _destroy,
},
.is_server = is_server,
.batch_id = batch_id,
.messages = linked_list_create(),
.encoding = chunk_clone(data),
);
return &this->public;
}
@@ -0,0 +1,93 @@
/*
* 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);
/**
* 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_ @}*/