aa0f69effd18e60fec86fdbe9e06e3befc5d7982
[strongswan.git] / src / libpts / plugins / imc_swid / imc_swid.c
1 /*
2 * Copyright (C) 2013 Andreas Steffen
3 * 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_swid_state.h"
17
18 #include "libpts.h"
19 #include "swid/swid_tag.h"
20 #include "swid/swid_tag_id.h"
21 #include "tcg/swid/tcg_swid_attr_req.h"
22 #include "tcg/swid/tcg_swid_attr_tag_inv.h"
23 #include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
24
25 #include <imc/imc_agent.h>
26 #include <imc/imc_msg.h>
27
28 #include <tncif_pa_subtypes.h>
29
30 #include <pen/pen.h>
31 #include <utils/debug.h>
32
33 static char strongswan_tag[] =
34 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
35 "<software_identification_tag "
36 "xmlns=\"http://standards.iso.org/iso/19770/-2/2009/schema.xsd\">\n"
37 "<entitlement_required_indicator>true</entitlement_required_indicator>\n"
38 "<product_title>strongSwan</product_title>\n"
39 "<product_version>\n"
40 " <name>5.1.1dr1</name>\n"
41 " <numeric>\n"
42 " <major>5</major>\n"
43 " <minor>1</minor>\n"
44 " <build>0</build>\n"
45 " <review></review>\n"
46 " </numeric>\n"
47 "</product_version>\n"
48 "<software_creator>\n"
49 " <name>strongSwan Project</name>\n"
50 " <regid>regid.2004-03.org.strongswan</regid>\n"
51 "</software_creator>\n"
52 "<software_licensor>\n"
53 " <name>strongSwan Project</name>\n"
54 " <regid>regid.2004-03.org.strongswan</regid>\n"
55 "</software_licensor>\n"
56 "<software_id>\n"
57 " <unique_id>strongSwan-5-1-0</unique_id>\n"
58 " <tag_creator_regid>regid.2004-03.org.strongswan</tag_creator_regid>\n"
59 "</software_id>\n"
60 "<tag_creator>\n"
61 " <name>strongSwan</name>\n"
62 " <regid>regid.2004-03.org.strongswan</regid>\n"
63 "</tag_creator>\n"
64 "</software_identification_tag>\n";
65
66 /* IMC definitions */
67
68 static const char imc_name[] = "SWID";
69
70 static pen_type_t msg_types[] = {
71 { PEN_TCG, PA_SUBTYPE_TCG_SWID }
72 };
73
74 static imc_agent_t *imc_swid;
75
76 /**
77 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
78 */
79 TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
80 TNC_Version min_version,
81 TNC_Version max_version,
82 TNC_Version *actual_version)
83 {
84 if (imc_swid)
85 {
86 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
87 return TNC_RESULT_ALREADY_INITIALIZED;
88 }
89 imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
90 imc_id, actual_version);
91 if (!imc_swid)
92 {
93 return TNC_RESULT_FATAL;
94 }
95
96 libpts_init();
97
98 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
99 {
100 DBG1(DBG_IMC, "no common IF-IMC version");
101 return TNC_RESULT_NO_COMMON_VERSION;
102 }
103 return TNC_RESULT_SUCCESS;
104 }
105
106 /**
107 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
108 */
109 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
110 TNC_ConnectionID connection_id,
111 TNC_ConnectionState new_state)
112 {
113 imc_state_t *state;
114
115 if (!imc_swid)
116 {
117 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
118 return TNC_RESULT_NOT_INITIALIZED;
119 }
120 switch (new_state)
121 {
122 case TNC_CONNECTION_STATE_CREATE:
123 state = imc_swid_state_create(connection_id);
124 return imc_swid->create_state(imc_swid, state);
125 case TNC_CONNECTION_STATE_HANDSHAKE:
126 if (imc_swid->change_state(imc_swid, connection_id, new_state,
127 &state) != TNC_RESULT_SUCCESS)
128 {
129 return TNC_RESULT_FATAL;
130 }
131 state->set_result(state, imc_id,
132 TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
133 return TNC_RESULT_SUCCESS;
134 case TNC_CONNECTION_STATE_DELETE:
135 return imc_swid->delete_state(imc_swid, connection_id);
136 default:
137 return imc_swid->change_state(imc_swid, connection_id,
138 new_state, NULL);
139 }
140 }
141
142 /**
143 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
144 */
145 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
146 TNC_ConnectionID connection_id)
147 {
148 imc_state_t *state;
149
150 if (!imc_swid)
151 {
152 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
153 return TNC_RESULT_NOT_INITIALIZED;
154 }
155 if (!imc_swid->get_state(imc_swid, connection_id, &state))
156 {
157 return TNC_RESULT_FATAL;
158 }
159
160 return TNC_RESULT_SUCCESS;
161 }
162
163 static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
164 {
165 imc_msg_t *out_msg;
166 imc_swid_state_t *swid_state;
167 enumerator_t *enumerator;
168 pa_tnc_attr_t *attr;
169 pen_type_t type;
170 TNC_Result result;
171 bool fatal_error = FALSE;
172
173 /* parse received PA-TNC message and handle local and remote errors */
174 result = in_msg->receive(in_msg, &fatal_error);
175 if (result != TNC_RESULT_SUCCESS)
176 {
177 return result;
178 }
179 out_msg = imc_msg_create_as_reply(in_msg);
180 swid_state = (imc_swid_state_t*)state;
181
182 /* analyze PA-TNC attributes */
183 enumerator = in_msg->create_attribute_enumerator(in_msg);
184 while (enumerator->enumerate(enumerator, &attr))
185 {
186 tcg_swid_attr_req_t *attr_req;
187 u_int8_t flags;
188 u_int32_t request_id, eid_epoch;
189
190 type = attr->get_type(attr);
191
192 if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
193 {
194 continue;
195 }
196
197 attr_req = (tcg_swid_attr_req_t*)attr;
198 flags = attr_req->get_flags(attr_req);
199 request_id = attr_req->get_request_id(attr_req);
200 eid_epoch = swid_state->get_eid_epoch(swid_state);
201
202 if (flags & TCG_SWID_ATTR_REQ_FLAG_R)
203 {
204 swid_tag_id_t *tag_id;
205 tcg_swid_attr_tag_id_inv_t *attr_cast;
206
207 attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
208 attr_cast = (tcg_swid_attr_tag_id_inv_t*)attr;
209 tag_id = swid_tag_id_create(
210 chunk_from_str("regid.2004-03.org.strongswan"),
211 chunk_from_str("strongSwan-5-1-0"),
212 chunk_empty);
213 attr_cast->add_tag_id(attr_cast, tag_id);
214 }
215 else
216 {
217 swid_tag_t *tag;
218 tcg_swid_attr_tag_inv_t *attr_cast;
219
220 attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
221 attr_cast = (tcg_swid_attr_tag_inv_t*)attr;
222 tag = swid_tag_create(chunk_from_str(strongswan_tag), chunk_empty);
223 attr_cast->add_tag(attr_cast, tag);
224 }
225 out_msg->add_attribute(out_msg, attr);
226 }
227 enumerator->destroy(enumerator);
228
229 if (fatal_error)
230 {
231 result = TNC_RESULT_FATAL;
232 }
233 else
234 {
235 result = out_msg->send(out_msg, TRUE);
236 }
237 out_msg->destroy(out_msg);
238
239 return result;
240 }
241
242 /**
243 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
244
245 */
246 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
247 TNC_ConnectionID connection_id,
248 TNC_BufferReference msg,
249 TNC_UInt32 msg_len,
250 TNC_MessageType msg_type)
251 {
252 imc_state_t *state;
253 imc_msg_t *in_msg;
254 TNC_Result result;
255
256 if (!imc_swid)
257 {
258 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
259 return TNC_RESULT_NOT_INITIALIZED;
260 }
261 if (!imc_swid->get_state(imc_swid, connection_id, &state))
262 {
263 return TNC_RESULT_FATAL;
264 }
265 in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
266 chunk_create(msg, msg_len));
267 result = receive_message(state, in_msg);
268 in_msg->destroy(in_msg);
269
270 return result;
271 }
272
273 /**
274 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
275 */
276 TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
277 TNC_ConnectionID connection_id,
278 TNC_UInt32 msg_flags,
279 TNC_BufferReference msg,
280 TNC_UInt32 msg_len,
281 TNC_VendorID msg_vid,
282 TNC_MessageSubtype msg_subtype,
283 TNC_UInt32 src_imv_id,
284 TNC_UInt32 dst_imc_id)
285 {
286 imc_state_t *state;
287 imc_msg_t *in_msg;
288 TNC_Result result;
289
290 if (!imc_swid)
291 {
292 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
293 return TNC_RESULT_NOT_INITIALIZED;
294 }
295 if (!imc_swid->get_state(imc_swid, connection_id, &state))
296 {
297 return TNC_RESULT_FATAL;
298 }
299 in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
300 src_imv_id, dst_imc_id,msg_vid, msg_subtype,
301 chunk_create(msg, msg_len));
302 result =receive_message(state, in_msg);
303 in_msg->destroy(in_msg);
304
305 return result;
306 }
307
308 /**
309 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
310 */
311 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
312 TNC_ConnectionID connection_id)
313 {
314 if (!imc_swid)
315 {
316 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
317 return TNC_RESULT_NOT_INITIALIZED;
318 }
319 return TNC_RESULT_SUCCESS;
320 }
321
322 /**
323 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
324 */
325 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
326 {
327 if (!imc_swid)
328 {
329 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
330 return TNC_RESULT_NOT_INITIALIZED;
331 }
332
333 libpts_deinit();
334
335 imc_swid->destroy(imc_swid);
336 imc_swid = NULL;
337
338 return TNC_RESULT_SUCCESS;
339 }
340
341 /**
342 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
343 */
344 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
345 TNC_TNCC_BindFunctionPointer bind_function)
346 {
347 if (!imc_swid)
348 {
349 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
350 return TNC_RESULT_NOT_INITIALIZED;
351 }
352 return imc_swid->bind_functions(imc_swid, bind_function);
353 }