]>
Commit | Line | Data |
---|---|---|
b38d9d5a | 1 | /* |
88501a64 | 2 | * Copyright (C) 2013-2017 Andreas Steffen |
b38d9d5a AS |
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 | ||
b38d9d5a AS |
18 | #include <imc/imc_agent.h> |
19 | #include <imc/imc_msg.h> | |
fc472117 AS |
20 | #include "tcg/seg/tcg_seg_attr_max_size.h" |
21 | #include "tcg/seg/tcg_seg_attr_seg_env.h" | |
d6fb2cc6 AS |
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 | #include "swid/swid_inventory.h" | |
26 | #include "swid/swid_error.h" | |
b38d9d5a AS |
27 | |
28 | #include <tncif_pa_subtypes.h> | |
29 | ||
30 | #include <pen/pen.h> | |
31 | #include <utils/debug.h> | |
32 | ||
33 | /* IMC definitions */ | |
34 | ||
35 | static const char imc_name[] = "SWID"; | |
36 | ||
37 | static pen_type_t msg_types[] = { | |
38 | { PEN_TCG, PA_SUBTYPE_TCG_SWID } | |
39 | }; | |
40 | ||
41 | static imc_agent_t *imc_swid; | |
42 | ||
43 | /** | |
44 | * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 | |
45 | */ | |
46 | TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, | |
47 | TNC_Version min_version, | |
48 | TNC_Version max_version, | |
49 | TNC_Version *actual_version) | |
50 | { | |
51 | if (imc_swid) | |
52 | { | |
53 | DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name); | |
54 | return TNC_RESULT_ALREADY_INITIALIZED; | |
55 | } | |
56 | imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types), | |
57 | imc_id, actual_version); | |
58 | if (!imc_swid) | |
59 | { | |
60 | return TNC_RESULT_FATAL; | |
61 | } | |
b38d9d5a AS |
62 | if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) |
63 | { | |
64 | DBG1(DBG_IMC, "no common IF-IMC version"); | |
65 | return TNC_RESULT_NO_COMMON_VERSION; | |
66 | } | |
67 | return TNC_RESULT_SUCCESS; | |
68 | } | |
69 | ||
70 | /** | |
71 | * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3 | |
72 | */ | |
73 | TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, | |
74 | TNC_ConnectionID connection_id, | |
75 | TNC_ConnectionState new_state) | |
76 | { | |
77 | imc_state_t *state; | |
78 | ||
79 | if (!imc_swid) | |
80 | { | |
81 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
82 | return TNC_RESULT_NOT_INITIALIZED; | |
83 | } | |
84 | switch (new_state) | |
85 | { | |
86 | case TNC_CONNECTION_STATE_CREATE: | |
87 | state = imc_swid_state_create(connection_id); | |
88 | return imc_swid->create_state(imc_swid, state); | |
89 | case TNC_CONNECTION_STATE_HANDSHAKE: | |
90 | if (imc_swid->change_state(imc_swid, connection_id, new_state, | |
91 | &state) != TNC_RESULT_SUCCESS) | |
92 | { | |
93 | return TNC_RESULT_FATAL; | |
94 | } | |
95 | state->set_result(state, imc_id, | |
96 | TNC_IMV_EVALUATION_RESULT_DONT_KNOW); | |
97 | return TNC_RESULT_SUCCESS; | |
98 | case TNC_CONNECTION_STATE_DELETE: | |
99 | return imc_swid->delete_state(imc_swid, connection_id); | |
100 | default: | |
101 | return imc_swid->change_state(imc_swid, connection_id, | |
102 | new_state, NULL); | |
103 | } | |
104 | } | |
105 | ||
106 | /** | |
107 | * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 | |
108 | */ | |
109 | TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, | |
110 | TNC_ConnectionID connection_id) | |
111 | { | |
112 | imc_state_t *state; | |
fc472117 AS |
113 | imc_msg_t *out_msg; |
114 | pa_tnc_attr_t *attr; | |
115 | seg_contract_t *contract; | |
116 | seg_contract_manager_t *contracts; | |
117 | size_t max_attr_size = SWID_MAX_ATTR_SIZE; | |
118 | size_t max_seg_size; | |
119 | char buf[BUF_LEN]; | |
120 | TNC_Result result = TNC_RESULT_SUCCESS; | |
b38d9d5a AS |
121 | |
122 | if (!imc_swid) | |
123 | { | |
124 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
125 | return TNC_RESULT_NOT_INITIALIZED; | |
126 | } | |
127 | if (!imc_swid->get_state(imc_swid, connection_id, &state)) | |
128 | { | |
129 | return TNC_RESULT_FATAL; | |
130 | } | |
131 | ||
fc472117 AS |
132 | /* Determine maximum PA-TNC attribute segment size */ |
133 | max_seg_size = state->get_max_msg_len(state) - PA_TNC_HEADER_SIZE | |
134 | - PA_TNC_ATTR_HEADER_SIZE | |
10f25a3d | 135 | - TCG_SEG_ATTR_SEG_ENV_HEADER; |
fc472117 AS |
136 | |
137 | /* Announce support of PA-TNC segmentation to IMV */ | |
138 | contract = seg_contract_create(msg_types[0], max_attr_size, max_seg_size, | |
139 | TRUE, imc_id, TRUE); | |
140 | contract->get_info_string(contract, buf, BUF_LEN, TRUE); | |
141 | DBG2(DBG_IMC, "%s", buf); | |
142 | contracts = state->get_contracts(state); | |
143 | contracts->add_contract(contracts, contract); | |
144 | attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE); | |
145 | ||
146 | /* send PA-TNC message with the excl flag not set */ | |
147 | out_msg = imc_msg_create(imc_swid, state, connection_id, imc_id, | |
148 | TNC_IMVID_ANY, msg_types[0]); | |
149 | out_msg->add_attribute(out_msg, attr); | |
150 | result = out_msg->send(out_msg, FALSE); | |
151 | out_msg->destroy(out_msg); | |
152 | ||
153 | return result; | |
b38d9d5a AS |
154 | } |
155 | ||
8c40609f AS |
156 | /** |
157 | * Add one or multiple SWID Inventory attributes to the send queue | |
158 | */ | |
159 | static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg, | |
160 | uint32_t request_id, bool full_tags, | |
161 | swid_inventory_t *targets) | |
b38d9d5a | 162 | { |
903a4270 | 163 | pa_tnc_attr_t *attr, *attr_error; |
b38d9d5a | 164 | imc_swid_state_t *swid_state; |
8c40609f | 165 | swid_inventory_t *swid_inventory; |
88501a64 | 166 | char *swid_directory; |
8c40609f | 167 | uint32_t eid_epoch; |
903a4270 | 168 | bool swid_pretty, swid_full; |
b38d9d5a | 169 | enumerator_t *enumerator; |
8c40609f AS |
170 | |
171 | swid_directory = lib->settings->get_str(lib->settings, | |
172 | "%s.plugins.imc-swid.swid_directory", | |
173 | SWID_DIRECTORY, lib->ns); | |
8c40609f AS |
174 | swid_pretty = lib->settings->get_bool(lib->settings, |
175 | "%s.plugins.imc-swid.swid_pretty", | |
176 | FALSE, lib->ns); | |
177 | swid_full = lib->settings->get_bool(lib->settings, | |
178 | "%s.plugins.imc-swid.swid_full", | |
179 | FALSE, lib->ns); | |
180 | ||
181 | swid_inventory = swid_inventory_create(full_tags); | |
88501a64 AS |
182 | if (!swid_inventory->collect(swid_inventory, swid_directory, targets, |
183 | swid_pretty, swid_full)) | |
8c40609f AS |
184 | { |
185 | swid_inventory->destroy(swid_inventory); | |
a5ce2f0b | 186 | attr_error = swid_error_create(TCG_SWID_ERROR, request_id, |
8c40609f | 187 | 0, "error in SWID tag collection"); |
a5ce2f0b | 188 | msg->add_attribute(msg, attr_error); |
8c40609f AS |
189 | return FALSE; |
190 | } | |
191 | DBG1(DBG_IMC, "collected %d SWID tag%s%s", | |
192 | swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID", | |
193 | swid_inventory->get_count(swid_inventory) == 1 ? "" : "s"); | |
194 | ||
195 | swid_state = (imc_swid_state_t*)state; | |
196 | eid_epoch = swid_state->get_eid_epoch(swid_state); | |
197 | ||
8c40609f AS |
198 | if (full_tags) |
199 | { | |
200 | tcg_swid_attr_tag_inv_t *swid_attr; | |
201 | swid_tag_t *tag; | |
8c40609f | 202 | |
903a4270 | 203 | /* Send a TCG SWID Tag Inventory attribute */ |
8c40609f | 204 | attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1); |
903a4270 | 205 | swid_attr = (tcg_swid_attr_tag_inv_t*)attr; |
8c40609f AS |
206 | |
207 | enumerator = swid_inventory->create_enumerator(swid_inventory); | |
208 | while (enumerator->enumerate(enumerator, &tag)) | |
209 | { | |
8c40609f | 210 | swid_attr->add(swid_attr, tag->get_ref(tag)); |
8c40609f AS |
211 | } |
212 | enumerator->destroy(enumerator); | |
213 | } | |
214 | else | |
215 | { | |
216 | tcg_swid_attr_tag_id_inv_t *swid_id_attr; | |
217 | swid_tag_id_t *tag_id; | |
8c40609f | 218 | |
903a4270 | 219 | /* Send a TCG SWID Tag ID Inventory attribute */ |
8c40609f AS |
220 | attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1); |
221 | swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr; | |
222 | ||
223 | enumerator = swid_inventory->create_enumerator(swid_inventory); | |
224 | while (enumerator->enumerate(enumerator, &tag_id)) | |
225 | { | |
8c40609f | 226 | swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id)); |
8c40609f AS |
227 | } |
228 | enumerator->destroy(enumerator); | |
229 | } | |
903a4270 | 230 | |
8c40609f AS |
231 | msg->add_attribute(msg, attr); |
232 | swid_inventory->destroy(swid_inventory); | |
233 | ||
234 | return TRUE; | |
235 | } | |
236 | ||
237 | static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg) | |
238 | { | |
239 | imc_msg_t *out_msg; | |
b38d9d5a | 240 | pa_tnc_attr_t *attr; |
8c40609f | 241 | enumerator_t *enumerator; |
b38d9d5a AS |
242 | pen_type_t type; |
243 | TNC_Result result; | |
244 | bool fatal_error = FALSE; | |
245 | ||
f5096897 AS |
246 | /* generate an outgoing PA-TNC message - we might need it */ |
247 | out_msg = imc_msg_create_as_reply(in_msg); | |
248 | ||
b38d9d5a | 249 | /* parse received PA-TNC message and handle local and remote errors */ |
f5096897 | 250 | result = in_msg->receive(in_msg, out_msg, &fatal_error); |
b38d9d5a AS |
251 | if (result != TNC_RESULT_SUCCESS) |
252 | { | |
f5096897 | 253 | out_msg->destroy(out_msg); |
b38d9d5a AS |
254 | return result; |
255 | } | |
b38d9d5a AS |
256 | |
257 | /* analyze PA-TNC attributes */ | |
258 | enumerator = in_msg->create_attribute_enumerator(in_msg); | |
259 | while (enumerator->enumerate(enumerator, &attr)) | |
260 | { | |
261 | tcg_swid_attr_req_t *attr_req; | |
8c40609f AS |
262 | uint8_t flags; |
263 | uint32_t request_id; | |
4e2a1762 | 264 | bool full_tags; |
8c40609f | 265 | swid_inventory_t *targets; |
b38d9d5a AS |
266 | |
267 | type = attr->get_type(attr); | |
268 | ||
269 | if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST) | |
270 | { | |
271 | continue; | |
272 | } | |
273 | ||
274 | attr_req = (tcg_swid_attr_req_t*)attr; | |
275 | flags = attr_req->get_flags(attr_req); | |
276 | request_id = attr_req->get_request_id(attr_req); | |
3adffcd9 | 277 | targets = attr_req->get_targets(attr_req); |
4d2bac37 | 278 | |
1e82e27a AS |
279 | if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C)) |
280 | { | |
281 | attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id, | |
282 | 0, "no subscription available yet"); | |
283 | out_msg->add_attribute(out_msg, attr); | |
284 | break; | |
285 | } | |
4e2a1762 | 286 | full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0; |
1e82e27a | 287 | |
8c40609f | 288 | if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets)) |
b38d9d5a | 289 | { |
4e2a1762 AS |
290 | break; |
291 | } | |
b38d9d5a AS |
292 | } |
293 | enumerator->destroy(enumerator); | |
294 | ||
295 | if (fatal_error) | |
296 | { | |
297 | result = TNC_RESULT_FATAL; | |
298 | } | |
299 | else | |
300 | { | |
f5096897 | 301 | /* send PA-TNC message with the EXCL flag set */ |
b38d9d5a AS |
302 | result = out_msg->send(out_msg, TRUE); |
303 | } | |
304 | out_msg->destroy(out_msg); | |
305 | ||
306 | return result; | |
307 | } | |
308 | ||
309 | /** | |
310 | * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3 | |
311 | ||
312 | */ | |
313 | TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, | |
314 | TNC_ConnectionID connection_id, | |
315 | TNC_BufferReference msg, | |
316 | TNC_UInt32 msg_len, | |
317 | TNC_MessageType msg_type) | |
318 | { | |
319 | imc_state_t *state; | |
320 | imc_msg_t *in_msg; | |
321 | TNC_Result result; | |
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 | if (!imc_swid->get_state(imc_swid, connection_id, &state)) | |
329 | { | |
330 | return TNC_RESULT_FATAL; | |
331 | } | |
332 | in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type, | |
333 | chunk_create(msg, msg_len)); | |
334 | result = receive_message(state, in_msg); | |
335 | in_msg->destroy(in_msg); | |
336 | ||
337 | return result; | |
338 | } | |
339 | ||
340 | /** | |
341 | * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3 | |
342 | */ | |
343 | TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id, | |
344 | TNC_ConnectionID connection_id, | |
345 | TNC_UInt32 msg_flags, | |
346 | TNC_BufferReference msg, | |
347 | TNC_UInt32 msg_len, | |
348 | TNC_VendorID msg_vid, | |
349 | TNC_MessageSubtype msg_subtype, | |
350 | TNC_UInt32 src_imv_id, | |
351 | TNC_UInt32 dst_imc_id) | |
352 | { | |
353 | imc_state_t *state; | |
354 | imc_msg_t *in_msg; | |
355 | TNC_Result result; | |
356 | ||
357 | if (!imc_swid) | |
358 | { | |
359 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
360 | return TNC_RESULT_NOT_INITIALIZED; | |
361 | } | |
362 | if (!imc_swid->get_state(imc_swid, connection_id, &state)) | |
363 | { | |
364 | return TNC_RESULT_FATAL; | |
365 | } | |
366 | in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id, | |
367 | src_imv_id, dst_imc_id,msg_vid, msg_subtype, | |
368 | chunk_create(msg, msg_len)); | |
369 | result =receive_message(state, in_msg); | |
370 | in_msg->destroy(in_msg); | |
371 | ||
372 | return result; | |
373 | } | |
374 | ||
375 | /** | |
376 | * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3 | |
377 | */ | |
378 | TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id, | |
379 | TNC_ConnectionID connection_id) | |
380 | { | |
381 | if (!imc_swid) | |
382 | { | |
383 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
384 | return TNC_RESULT_NOT_INITIALIZED; | |
385 | } | |
386 | return TNC_RESULT_SUCCESS; | |
387 | } | |
388 | ||
389 | /** | |
390 | * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3 | |
391 | */ | |
392 | TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) | |
393 | { | |
394 | if (!imc_swid) | |
395 | { | |
396 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
397 | return TNC_RESULT_NOT_INITIALIZED; | |
398 | } | |
b38d9d5a AS |
399 | imc_swid->destroy(imc_swid); |
400 | imc_swid = NULL; | |
401 | ||
402 | return TNC_RESULT_SUCCESS; | |
403 | } | |
404 | ||
405 | /** | |
406 | * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3 | |
407 | */ | |
408 | TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id, | |
409 | TNC_TNCC_BindFunctionPointer bind_function) | |
410 | { | |
411 | if (!imc_swid) | |
412 | { | |
413 | DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); | |
414 | return TNC_RESULT_NOT_INITIALIZED; | |
415 | } | |
416 | return imc_swid->bind_functions(imc_swid, bind_function); | |
417 | } |