]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libtnccs / plugins / tnccs_11 / messages / imc_imv_msg.c
CommitLineData
d9e21bf1 1/*
1b671669 2 * Copyright (C) 2010 Andreas Steffen
1b671669 3 *
d9e21bf1 4 * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
d9e21bf1
AS
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17#include "imc_imv_msg.h"
18
19#include <tnc/tnccs/tnccs.h>
f0a8bf47 20
5fee822a 21#include <utils/lexparser.h>
f05b4272 22#include <utils/debug.h>
d9e21bf1
AS
23
24typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
25
26#define BYTES_PER_LINE 57
27
28/**
29 * Private data of a imc_imv_msg_t object.
30 *
31 */
32struct private_imc_imv_msg_t {
33 /**
34 * Public imc_imv_msg_t interface.
35 */
36 imc_imv_msg_t public;
37
38 /**
39 * TNCCS message type
40 */
41 tnccs_msg_type_t type;
42
43 /**
44 * XML-encoded message node
45 */
46 xmlNodePtr node;
47
48 /**
49 * IMC-IMV message type
50 */
51 TNC_MessageType msg_type;
52
53 /**
54 * IMC-IMV message body
55 */
56 chunk_t msg_body;
57
58};
59
d9e21bf1 60/**
6ccb23e8 61 * Encodes message data into multiple base64-encoded lines
d9e21bf1
AS
62 */
63static chunk_t encode_base64(chunk_t data)
64{
65 chunk_t encoding;
66 u_char *pos;
67 size_t b64_chars, b64_lines;
68
f33966fe
AS
69 /* handle empty message data object */
70 if (data.len == 0)
71 {
72 encoding = chunk_alloc(1);
73 *encoding.ptr = '\0';
74 return encoding;
75 }
76
d9e21bf1
AS
77 /* compute and allocate maximum size of base64 object */
78 b64_chars = 4 * ((data.len + 2) / 3);
79 b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
80 encoding = chunk_alloc(b64_chars + b64_lines);
81 pos = encoding.ptr;
82
83 /* encode lines */
84 while (b64_lines--)
85 {
86 chunk_t data_line, b64_line;
87
88 data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE));
89 data.ptr += data_line.len;
90 data.len -= data_line.len;
91 b64_line = chunk_to_base64(data_line, pos);
92 pos += b64_line.len;
93 *pos = '\n';
94 pos++;
95 }
96 /* terminate last line with NULL character instead of newline */
97 *(pos-1) = '\0';
98
99 return encoding;
100}
101
5fee822a 102/**
6ccb23e8 103 * Decodes message data from multiple base64-encoded lines
5fee822a
AS
104 */
105static chunk_t decode_base64(chunk_t data)
106{
107 chunk_t decoding, data_line, b64_line;
108 u_char *pos;
109
110 /* compute and allocate maximum size of decoded message data */
111 decoding = chunk_alloc(3 * ((data.len + 3) / 4));
112 pos = decoding.ptr;
113 decoding.len = 0;
114
115 while (fetchline(&data, &b64_line))
116 {
117 data_line = chunk_from_base64(b64_line, pos);
118 pos += data_line.len;
119 decoding.len += data_line.len;
120 }
121
122 return decoding;
123}
124
125METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
126 private_imc_imv_msg_t *this)
127{
128 return this->type;
129}
130
131METHOD(tnccs_msg_t, get_node, xmlNodePtr,
132 private_imc_imv_msg_t *this)
133{
134 return this->node;
135}
136
d9e21bf1
AS
137METHOD(tnccs_msg_t, destroy, void,
138 private_imc_imv_msg_t *this)
139{
140 free(this->msg_body.ptr);
141 free(this);
142}
143
144METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType,
145 private_imc_imv_msg_t *this)
146{
147 return this->msg_type;
148}
149
150METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
151 private_imc_imv_msg_t *this)
152{
153 return this->msg_body;
154}
155
156/**
157 * See header
158 */
5fee822a 159tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
d9e21bf1
AS
160{
161 private_imc_imv_msg_t *this;
5fee822a
AS
162 xmlNsPtr ns;
163 xmlNodePtr cur;
164 xmlChar *content;
165 chunk_t b64_body;
d9e21bf1
AS
166
167 INIT(this,
168 .public = {
169 .tnccs_msg_interface = {
170 .get_type = _get_type,
171 .get_node = _get_node,
172 .destroy = _destroy,
173 },
174 .get_msg_type = _get_msg_type,
175 .get_msg_body = _get_msg_body,
176 },
177 .type = IMC_IMV_MSG,
178 .node = node,
179 );
180
5fee822a
AS
181 ns = node->ns;
182 cur = node->xmlChildrenNode;
183 while (cur)
184 {
2a4915e8 185 if (streq(cur->name, "Type") && cur->ns == ns)
5fee822a
AS
186 {
187 content = xmlNodeGetContent(cur);
2a4915e8 188 this->msg_type = strtoul(content, NULL, 16);
6ccb23e8 189 xmlFree(content);
5fee822a 190 }
2a4915e8 191 else if (streq(cur->name, "Base64") && cur->ns == ns)
5fee822a
AS
192 {
193 content = xmlNodeGetContent(cur);
2a4915e8 194 b64_body = chunk_create(content, strlen(content));
5fee822a 195 this->msg_body = decode_base64(b64_body);
6ccb23e8 196 xmlFree(content);
5fee822a
AS
197 }
198 cur = cur->next;
199 }
200
d9e21bf1
AS
201 return &this->public.tnccs_msg_interface;
202}
203
204/**
205 * See header
206 */
207tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
208{
209 private_imc_imv_msg_t *this;
210 chunk_t b64_body;
211 char buf[10]; /* big enough for hex-encoded message type */
212 xmlNodePtr n;
213
214 INIT(this,
215 .public = {
216 .tnccs_msg_interface = {
217 .get_type = _get_type,
218 .get_node = _get_node,
219 .destroy = _destroy,
220 },
221 .get_msg_type = _get_msg_type,
222 .get_msg_body = _get_msg_body,
223 },
224 .type = IMC_IMV_MSG,
2a4915e8 225 .node = xmlNewNode(NULL, "IMC-IMV-Message"),
d9e21bf1
AS
226 .msg_type = msg_type,
227 .msg_body = chunk_clone(msg_body),
228 );
229
230 /* add the message type number in hex */
2a4915e8 231 n = xmlNewNode(NULL, "Type");
d9e21bf1 232 snprintf(buf, 10, "%08x", this->msg_type);
2a4915e8 233 xmlNodeSetContent(n, buf);
d9e21bf1
AS
234 xmlAddChild(this->node, n);
235
236 /* encode the message as a Base64 node */
2a4915e8 237 n = xmlNewNode(NULL, "Base64");
d9e21bf1 238 b64_body = encode_base64(this->msg_body);
2a4915e8 239 xmlNodeSetContent(n, b64_body.ptr);
d9e21bf1
AS
240 xmlAddChild(this->node, n);
241 free(b64_body.ptr);
242
243 return &this->public.tnccs_msg_interface;
244}