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
;
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 eid_epoch
= swid_state
->get_eid_epoch(swid_state
);
173 if (flags
& (TCG_SWID_ATTR_REQ_FLAG_S
| TCG_SWID_ATTR_REQ_FLAG_C
))
175 attr
= swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED
, request_id
,
176 0, "no subscription available yet");
177 out_msg
->add_attribute(out_msg
, attr
);
180 full_tags
= (flags
& TCG_SWID_ATTR_REQ_FLAG_R
) == 0;
182 swid_directory
= lib
->settings
->get_str(lib
->settings
,
183 "libimcv.plugins.imc-swid.swid_directory",
185 swid_inventory
= swid_inventory_create(full_tags
);
186 if (!swid_inventory
->collect(swid_inventory
, swid_directory
))
188 swid_inventory
->destroy(swid_inventory
);
189 attr
= swid_error_create(TCG_SWID_ERROR
, request_id
,
190 0, "error in SWID tag collection");
191 out_msg
->add_attribute(out_msg
, attr
);
194 DBG1(DBG_IMC
, "collected %d SWID tag%s%s",
195 swid_inventory
->get_count(swid_inventory
), full_tags ?
"" : " ID",
196 swid_inventory
->get_count(swid_inventory
) == 1 ?
"" : "s");
200 attr
= tcg_swid_attr_tag_inv_create(request_id
, eid_epoch
, 1,
205 attr
= tcg_swid_attr_tag_id_inv_create(request_id
, eid_epoch
, 1,
208 out_msg
->add_attribute(out_msg
, attr
);
210 enumerator
->destroy(enumerator
);
214 result
= TNC_RESULT_FATAL
;
218 result
= out_msg
->send(out_msg
, TRUE
);
220 out_msg
->destroy(out_msg
);
226 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
229 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
230 TNC_ConnectionID connection_id
,
231 TNC_BufferReference msg
,
233 TNC_MessageType msg_type
)
241 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
242 return TNC_RESULT_NOT_INITIALIZED
;
244 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
246 return TNC_RESULT_FATAL
;
248 in_msg
= imc_msg_create_from_data(imc_swid
, state
, connection_id
, msg_type
,
249 chunk_create(msg
, msg_len
));
250 result
= receive_message(state
, in_msg
);
251 in_msg
->destroy(in_msg
);
257 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
259 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
260 TNC_ConnectionID connection_id
,
261 TNC_UInt32 msg_flags
,
262 TNC_BufferReference msg
,
264 TNC_VendorID msg_vid
,
265 TNC_MessageSubtype msg_subtype
,
266 TNC_UInt32 src_imv_id
,
267 TNC_UInt32 dst_imc_id
)
275 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
276 return TNC_RESULT_NOT_INITIALIZED
;
278 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
280 return TNC_RESULT_FATAL
;
282 in_msg
= imc_msg_create_from_long_data(imc_swid
, state
, connection_id
,
283 src_imv_id
, dst_imc_id
,msg_vid
, msg_subtype
,
284 chunk_create(msg
, msg_len
));
285 result
=receive_message(state
, in_msg
);
286 in_msg
->destroy(in_msg
);
292 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
294 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
295 TNC_ConnectionID connection_id
)
299 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
300 return TNC_RESULT_NOT_INITIALIZED
;
302 return TNC_RESULT_SUCCESS
;
306 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
308 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
312 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
313 return TNC_RESULT_NOT_INITIALIZED
;
318 imc_swid
->destroy(imc_swid
);
321 return TNC_RESULT_SUCCESS
;
325 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
327 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
328 TNC_TNCC_BindFunctionPointer bind_function
)
332 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
333 return TNC_RESULT_NOT_INITIALIZED
;
335 return imc_swid
->bind_functions(imc_swid
, bind_function
);