2 * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
3 * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "tnccs_batch.h"
17 #include "messages/tnccs_error_msg.h"
20 #include <utils/linked_list.h>
21 #include <tnc/tnccs/tnccs.h>
23 #include <libxml/parser.h>
25 typedef struct private_tnccs_batch_t private_tnccs_batch_t
;
28 * Private data of a tnccs_batch_t object.
31 struct private_tnccs_batch_t
{
33 * Public tnccs_batch_t interface.
43 * TNCC if TRUE, TNCS if FALSE
48 * linked list of TNCCS messages
50 linked_list_t
*messages
;
53 * linked list of TNCCS error messages
55 linked_list_t
*errors
;
68 METHOD(tnccs_batch_t
, get_encoding
, chunk_t
,
69 private_tnccs_batch_t
*this)
71 return this->encoding
;
74 METHOD(tnccs_batch_t
, add_msg
, void,
75 private_tnccs_batch_t
*this, tnccs_msg_t
* msg
)
79 DBG2(DBG_TNC
, "adding %N message", tnccs_msg_type_names
,
81 this->messages
->insert_last(this->messages
, msg
);
82 root
= xmlDocGetRootElement(this->doc
);
83 xmlAddChild(root
, msg
->get_node(msg
));
86 METHOD(tnccs_batch_t
, build
, void,
87 private_tnccs_batch_t
*this)
92 xmlDocDumpFormatMemory(this->doc
, &xmlbuf
, &buf_size
, 1);
93 this->encoding
= chunk_create((u_char
*)xmlbuf
, buf_size
);
94 this->encoding
= chunk_clone(this->encoding
);
98 METHOD(tnccs_batch_t
, process
, status_t
,
99 private_tnccs_batch_t
*this)
101 tnccs_msg_t
*tnccs_msg
, *msg
;
102 tnccs_error_type_t error_type
= TNCCS_ERROR_OTHER
;
103 char *error_msg
, buf
[BUF_LEN
];
106 xmlChar
*batchid
, *recipient
;
109 this->doc
= xmlParseMemory(this->encoding
.ptr
, this->encoding
.len
);
112 error_type
= TNCCS_ERROR_MALFORMED_BATCH
;
113 error_msg
= "failed to parse XML message";
117 /* check out the XML document */
118 cur
= xmlDocGetRootElement(this->doc
);
121 error_type
= TNCCS_ERROR_MALFORMED_BATCH
;
122 error_msg
= "empty XML document";
126 /* check TNCCS namespace */
127 ns
= xmlSearchNsByHref(this->doc
, cur
, (const xmlChar
*)
128 "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
131 error_type
= TNCCS_ERROR_MALFORMED_BATCH
;
132 error_msg
= "TNCCS namespace not found";
136 /* check XML document type */
137 if (xmlStrcmp(cur
->name
, (const xmlChar
*)"TNCCS-Batch"))
139 error_type
= TNCCS_ERROR_MALFORMED_BATCH
;
141 snprintf(buf
, BUF_LEN
, "wrong XML document type '%s', expected TNCCS-Batch",
146 /* check presence of BatchID property */
147 batchid
= xmlGetProp(cur
, (const xmlChar
*)"BatchId");
150 error_type
= TNCCS_ERROR_INVALID_BATCH_ID
;
151 error_msg
= "BatchId is missing";
156 batch_id
= atoi((char*)batchid
);
158 if (batch_id
!= this->batch_id
)
160 error_type
= TNCCS_ERROR_INVALID_BATCH_ID
;
162 snprintf(buf
, BUF_LEN
, "BatchId %d expected, got %d", this->batch_id
,
167 /* check presence of Recipient property */
168 recipient
= xmlGetProp(cur
, (const xmlChar
*)"Recipient");
171 error_type
= TNCCS_ERROR_INVALID_RECIPIENT_TYPE
;
172 error_msg
= "Recipient is missing";
176 /* check recipient */
177 if (!streq((char*)recipient
, this->is_server ?
"TNCS" : "TNCC"))
179 error_type
= TNCCS_ERROR_INVALID_RECIPIENT_TYPE
;
181 snprintf(buf
, BUF_LEN
, "message recipient expected '%s', got '%s'",
182 this->is_server ?
"TNCS" : "TNCC", (char*)recipient
);
188 DBG2(DBG_TNC
, "processing TNCCS Batch #%d", batch_id
);
190 /* Now walk the tree, handling message nodes as we go */
191 for (cur
= cur
->xmlChildrenNode
; cur
!= NULL
; cur
= cur
->next
)
193 /* ignore empty or blank nodes */
194 if (xmlIsBlankNode(cur
))
199 /* ignore nodes with wrong namespace */
202 DBG1(DBG_TNC
, "ignoring message node '%s' having wrong namespace",
207 tnccs_msg
= tnccs_msg_create_from_node(cur
, this->errors
);
209 /* exit if a message parsing error occurred */
210 if (this->errors
->get_count(this->errors
) > 0)
215 /* ignore unrecognized messages */
221 this->messages
->insert_last(this->messages
, tnccs_msg
);
226 msg
= tnccs_error_msg_create(error_type
, error_msg
);
227 this->errors
->insert_last(this->errors
, msg
);
231 METHOD(tnccs_batch_t
, create_msg_enumerator
, enumerator_t
*,
232 private_tnccs_batch_t
*this)
234 return this->messages
->create_enumerator(this->messages
);
237 METHOD(tnccs_batch_t
, create_error_enumerator
, enumerator_t
*,
238 private_tnccs_batch_t
*this)
240 return this->errors
->create_enumerator(this->errors
);
243 METHOD(tnccs_batch_t
, destroy
, void,
244 private_tnccs_batch_t
*this)
246 this->messages
->destroy_offset(this->messages
,
247 offsetof(tnccs_msg_t
, destroy
));
248 this->errors
->destroy_offset(this->errors
,
249 offsetof(tnccs_msg_t
, destroy
));
250 xmlFreeDoc(this->doc
);
251 free(this->encoding
.ptr
);
258 tnccs_batch_t
* tnccs_batch_create(bool is_server
, int batch_id
)
260 private_tnccs_batch_t
*this;
263 const char *recipient
;
267 .get_encoding
= _get_encoding
,
271 .create_msg_enumerator
= _create_msg_enumerator
,
272 .create_error_enumerator
= _create_error_enumerator
,
275 .is_server
= is_server
,
276 .messages
= linked_list_create(),
277 .errors
= linked_list_create(),
278 .batch_id
= batch_id
,
279 .doc
= xmlNewDoc(BAD_CAST
"1.0"),
282 DBG2(DBG_TNC
, "creating TNCCS Batch #%d", this->batch_id
);
283 n
= xmlNewNode(NULL
, BAD_CAST
"TNCCS-Batch");
284 snprintf(buf
, sizeof(buf
), "%d", batch_id
);
285 recipient
= this->is_server ?
"TNCC" : "TNCS";
286 xmlNewProp(n
, BAD_CAST
"BatchId", BAD_CAST buf
);
287 xmlNewProp(n
, BAD_CAST
"Recipient", BAD_CAST recipient
);
288 xmlNewProp(n
, BAD_CAST
"xmlns", BAD_CAST
"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
289 xmlNewProp(n
, BAD_CAST
"xmlns:xsi", BAD_CAST
"http://www.w3.org/2001/XMLSchema-instance");
290 xmlNewProp(n
, BAD_CAST
"xsi:schemaLocation", BAD_CAST
"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS# "
291 "https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd");
292 xmlDocSetRootElement(this->doc
, n
);
294 return &this->public;
300 tnccs_batch_t
* tnccs_batch_create_from_data(bool is_server
, int batch_id
, chunk_t data
)
302 private_tnccs_batch_t
*this;
306 .get_encoding
= _get_encoding
,
310 .create_msg_enumerator
= _create_msg_enumerator
,
311 .create_error_enumerator
= _create_error_enumerator
,
314 .is_server
= is_server
,
315 .batch_id
= batch_id
,
316 .messages
= linked_list_create(),
317 .errors
= linked_list_create(),
318 .encoding
= chunk_clone(data
),
321 return &this->public;