2c3bc59be777529b9440c1bea5648f52aeb954fd
[strongswan.git] / src / libcharon / plugins / tnccs_11 / messages / imc_imv_msg.c
1 /*
2 * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
3 * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "imc_imv_msg.h"
17
18 #include <tnc/tnccs/tnccs.h>
19 #include <debug.h>
20
21 typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
22
23 #define BYTES_PER_LINE 57
24
25 /**
26 * Private data of a imc_imv_msg_t object.
27 *
28 */
29 struct private_imc_imv_msg_t {
30 /**
31 * Public imc_imv_msg_t interface.
32 */
33 imc_imv_msg_t public;
34
35 /**
36 * TNCCS message type
37 */
38 tnccs_msg_type_t type;
39
40 /**
41 * XML-encoded message node
42 */
43 xmlNodePtr node;
44
45 /**
46 * IMC-IMV message type
47 */
48 TNC_MessageType msg_type;
49
50 /**
51 * IMC-IMV message body
52 */
53 chunk_t msg_body;
54
55 };
56
57 METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
58 private_imc_imv_msg_t *this)
59 {
60 return this->type;
61 }
62
63 METHOD(tnccs_msg_t, get_node, xmlNodePtr,
64 private_imc_imv_msg_t *this)
65 {
66 return this->node;
67 }
68
69 METHOD(tnccs_msg_t, process, status_t,
70 private_imc_imv_msg_t *this)
71 {
72 return SUCCESS;
73 }
74
75 /**
76 * Converts message data into multiple base64-encoded lines
77 */
78 static chunk_t encode_base64(chunk_t data)
79 {
80 chunk_t encoding;
81 u_char *pos;
82 size_t b64_chars, b64_lines;
83
84 /* compute and allocate maximum size of base64 object */
85 b64_chars = 4 * ((data.len + 2) / 3);
86 b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
87 encoding = chunk_alloc(b64_chars + b64_lines);
88 pos = encoding.ptr;
89
90 /* encode lines */
91 while (b64_lines--)
92 {
93 chunk_t data_line, b64_line;
94
95 data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE));
96 data.ptr += data_line.len;
97 data.len -= data_line.len;
98 b64_line = chunk_to_base64(data_line, pos);
99 pos += b64_line.len;
100 *pos = '\n';
101 pos++;
102 }
103 /* terminate last line with NULL character instead of newline */
104 *(pos-1) = '\0';
105
106 return encoding;
107 }
108
109 METHOD(tnccs_msg_t, destroy, void,
110 private_imc_imv_msg_t *this)
111 {
112 free(this->msg_body.ptr);
113 free(this);
114 }
115
116 METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType,
117 private_imc_imv_msg_t *this)
118 {
119 return this->msg_type;
120 }
121
122 METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
123 private_imc_imv_msg_t *this)
124 {
125 return this->msg_body;
126 }
127
128 /**
129 * See header
130 */
131 tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node)
132 {
133 private_imc_imv_msg_t *this;
134
135 INIT(this,
136 .public = {
137 .tnccs_msg_interface = {
138 .get_type = _get_type,
139 .get_node = _get_node,
140 .process = _process,
141 .destroy = _destroy,
142 },
143 .get_msg_type = _get_msg_type,
144 .get_msg_body = _get_msg_body,
145 },
146 .type = IMC_IMV_MSG,
147 .node = node,
148 );
149
150 return &this->public.tnccs_msg_interface;
151 }
152
153 /**
154 * See header
155 */
156 tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
157 {
158 private_imc_imv_msg_t *this;
159 chunk_t b64_body;
160 char buf[10]; /* big enough for hex-encoded message type */
161 xmlNodePtr n;
162
163 INIT(this,
164 .public = {
165 .tnccs_msg_interface = {
166 .get_type = _get_type,
167 .get_node = _get_node,
168 .process = _process,
169 .destroy = _destroy,
170 },
171 .get_msg_type = _get_msg_type,
172 .get_msg_body = _get_msg_body,
173 },
174 .type = IMC_IMV_MSG,
175 .node = xmlNewNode(NULL, BAD_CAST "IMC-IMV-Message"),
176 .msg_type = msg_type,
177 .msg_body = chunk_clone(msg_body),
178 );
179
180 /* add the message type number in hex */
181 n = xmlNewNode(NULL, BAD_CAST "Type");
182 snprintf(buf, 10, "%08x", this->msg_type);
183 xmlNodeSetContent(n, BAD_CAST buf);
184 xmlAddChild(this->node, n);
185
186 /* encode the message as a Base64 node */
187 n = xmlNewNode(NULL, BAD_CAST "Base64");
188 b64_body = encode_base64(this->msg_body);
189 xmlNodeSetContent(n, BAD_CAST b64_body.ptr);
190 xmlAddChild(this->node, n);
191 free(b64_body.ptr);
192
193 return &this->public.tnccs_msg_interface;
194 }