2 * Copyright (C) 2013 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imc_swid_state.h"
19 #include "swid/swid_inventory.h"
20 #include "swid/swid_error.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"
25 #include <imc/imc_agent.h>
26 #include <imc/imc_msg.h>
28 #include <tncif_pa_subtypes.h>
31 #include <utils/debug.h>
36 static const char imc_name
[] = "SWID";
38 static pen_type_t msg_types
[] = {
39 { PEN_TCG
, PA_SUBTYPE_TCG_SWID
}
42 static imc_agent_t
*imc_swid
;
45 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
47 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
48 TNC_Version min_version
,
49 TNC_Version max_version
,
50 TNC_Version
*actual_version
)
54 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
55 return TNC_RESULT_ALREADY_INITIALIZED
;
57 imc_swid
= imc_agent_create(imc_name
, msg_types
, countof(msg_types
),
58 imc_id
, actual_version
);
61 return TNC_RESULT_FATAL
;
66 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
68 DBG1(DBG_IMC
, "no common IF-IMC version");
69 return TNC_RESULT_NO_COMMON_VERSION
;
71 return TNC_RESULT_SUCCESS
;
75 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
77 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
78 TNC_ConnectionID connection_id
,
79 TNC_ConnectionState new_state
)
85 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
86 return TNC_RESULT_NOT_INITIALIZED
;
90 case TNC_CONNECTION_STATE_CREATE
:
91 state
= imc_swid_state_create(connection_id
);
92 return imc_swid
->create_state(imc_swid
, state
);
93 case TNC_CONNECTION_STATE_HANDSHAKE
:
94 if (imc_swid
->change_state(imc_swid
, connection_id
, new_state
,
95 &state
) != TNC_RESULT_SUCCESS
)
97 return TNC_RESULT_FATAL
;
99 state
->set_result(state
, imc_id
,
100 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
101 return TNC_RESULT_SUCCESS
;
102 case TNC_CONNECTION_STATE_DELETE
:
103 return imc_swid
->delete_state(imc_swid
, connection_id
);
105 return imc_swid
->change_state(imc_swid
, connection_id
,
111 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
113 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
114 TNC_ConnectionID connection_id
)
120 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
121 return TNC_RESULT_NOT_INITIALIZED
;
123 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
125 return TNC_RESULT_FATAL
;
128 return TNC_RESULT_SUCCESS
;
131 static TNC_Result
receive_message(imc_state_t
*state
, imc_msg_t
*in_msg
)
134 imc_swid_state_t
*swid_state
;
135 enumerator_t
*enumerator
;
139 bool fatal_error
= FALSE
;
141 /* parse received PA-TNC message and handle local and remote errors */
142 result
= in_msg
->receive(in_msg
, &fatal_error
);
143 if (result
!= TNC_RESULT_SUCCESS
)
147 out_msg
= imc_msg_create_as_reply(in_msg
);
148 swid_state
= (imc_swid_state_t
*)state
;
150 /* analyze PA-TNC attributes */
151 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
152 while (enumerator
->enumerate(enumerator
, &attr
))
154 tcg_swid_attr_req_t
*attr_req
;
156 u_int32_t request_id
, eid_epoch
;
157 swid_inventory_t
*swid_inventory
, *targets
;
158 char *swid_directory
;
161 type
= attr
->get_type(attr
);
163 if (type
.vendor_id
!= PEN_TCG
|| type
.type
!= TCG_SWID_REQUEST
)
168 attr_req
= (tcg_swid_attr_req_t
*)attr
;
169 flags
= attr_req
->get_flags(attr_req
);
170 request_id
= attr_req
->get_request_id(attr_req
);
171 targets
= attr_req
->get_targets(attr_req
);
172 eid_epoch
= swid_state
->get_eid_epoch(swid_state
);
174 if (flags
& (TCG_SWID_ATTR_REQ_FLAG_S
| TCG_SWID_ATTR_REQ_FLAG_C
))
176 attr
= swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED
, request_id
,
177 0, "no subscription available yet");
178 out_msg
->add_attribute(out_msg
, attr
);
181 full_tags
= (flags
& TCG_SWID_ATTR_REQ_FLAG_R
) == 0;
183 swid_directory
= lib
->settings
->get_str(lib
->settings
,
184 "%s.plugins.imc-swid.swid_directory",
185 SWID_DIRECTORY
, lib
->ns
);
186 swid_inventory
= swid_inventory_create(full_tags
);
187 if (!swid_inventory
->collect(swid_inventory
, swid_directory
, targets
))
189 swid_inventory
->destroy(swid_inventory
);
190 attr
= swid_error_create(TCG_SWID_ERROR
, request_id
,
191 0, "error in SWID tag collection");
192 out_msg
->add_attribute(out_msg
, attr
);
195 DBG1(DBG_IMC
, "collected %d SWID tag%s%s",
196 swid_inventory
->get_count(swid_inventory
), full_tags ?
"" : " ID",
197 swid_inventory
->get_count(swid_inventory
) == 1 ?
"" : "s");
201 attr
= tcg_swid_attr_tag_inv_create(request_id
, eid_epoch
, 1,
206 attr
= tcg_swid_attr_tag_id_inv_create(request_id
, eid_epoch
, 1,
209 out_msg
->add_attribute(out_msg
, attr
);
211 enumerator
->destroy(enumerator
);
215 result
= TNC_RESULT_FATAL
;
219 result
= out_msg
->send(out_msg
, TRUE
);
221 out_msg
->destroy(out_msg
);
227 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
230 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
231 TNC_ConnectionID connection_id
,
232 TNC_BufferReference msg
,
234 TNC_MessageType msg_type
)
242 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
243 return TNC_RESULT_NOT_INITIALIZED
;
245 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
247 return TNC_RESULT_FATAL
;
249 in_msg
= imc_msg_create_from_data(imc_swid
, state
, connection_id
, msg_type
,
250 chunk_create(msg
, msg_len
));
251 result
= receive_message(state
, in_msg
);
252 in_msg
->destroy(in_msg
);
258 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
260 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
261 TNC_ConnectionID connection_id
,
262 TNC_UInt32 msg_flags
,
263 TNC_BufferReference msg
,
265 TNC_VendorID msg_vid
,
266 TNC_MessageSubtype msg_subtype
,
267 TNC_UInt32 src_imv_id
,
268 TNC_UInt32 dst_imc_id
)
276 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
277 return TNC_RESULT_NOT_INITIALIZED
;
279 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
281 return TNC_RESULT_FATAL
;
283 in_msg
= imc_msg_create_from_long_data(imc_swid
, state
, connection_id
,
284 src_imv_id
, dst_imc_id
,msg_vid
, msg_subtype
,
285 chunk_create(msg
, msg_len
));
286 result
=receive_message(state
, in_msg
);
287 in_msg
->destroy(in_msg
);
293 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
295 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
296 TNC_ConnectionID connection_id
)
300 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
301 return TNC_RESULT_NOT_INITIALIZED
;
303 return TNC_RESULT_SUCCESS
;
307 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
309 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
313 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
314 return TNC_RESULT_NOT_INITIALIZED
;
319 imc_swid
->destroy(imc_swid
);
322 return TNC_RESULT_SUCCESS
;
326 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
328 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
329 TNC_TNCC_BindFunctionPointer bind_function
)
333 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
334 return TNC_RESULT_NOT_INITIALIZED
;
336 return imc_swid
->bind_functions(imc_swid
, bind_function
);