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