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_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"
26 #include <imc/imc_agent.h>
27 #include <imc/imc_msg.h>
29 #include <tncif_pa_subtypes.h>
32 #include <utils/debug.h>
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"
41 " <name>5.1.1dr1</name>\n"
46 " <review>dr1</review>\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"
58 " <unique_id>strongSwan-5-1-1-dr1</unique_id>\n"
59 " <tag_creator_regid>regid.2004-03.org.strongswan</tag_creator_regid>\n"
62 " <name>strongSwan Project</name>\n"
63 " <regid>regid.2004-03.org.strongswan</regid>\n"
65 "</software_identification_tag>\n";
69 static const char imc_name
[] = "SWID";
71 static pen_type_t msg_types
[] = {
72 { PEN_TCG
, PA_SUBTYPE_TCG_SWID
}
75 static imc_agent_t
*imc_swid
;
78 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
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
)
87 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
88 return TNC_RESULT_ALREADY_INITIALIZED
;
90 imc_swid
= imc_agent_create(imc_name
, msg_types
, countof(msg_types
),
91 imc_id
, actual_version
);
94 return TNC_RESULT_FATAL
;
99 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
101 DBG1(DBG_IMC
, "no common IF-IMC version");
102 return TNC_RESULT_NO_COMMON_VERSION
;
104 return TNC_RESULT_SUCCESS
;
108 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
110 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
111 TNC_ConnectionID connection_id
,
112 TNC_ConnectionState new_state
)
118 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
119 return TNC_RESULT_NOT_INITIALIZED
;
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
)
130 return TNC_RESULT_FATAL
;
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
);
138 return imc_swid
->change_state(imc_swid
, connection_id
,
144 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
146 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
147 TNC_ConnectionID connection_id
)
153 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
154 return TNC_RESULT_NOT_INITIALIZED
;
156 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
158 return TNC_RESULT_FATAL
;
161 return TNC_RESULT_SUCCESS
;
164 static TNC_Result
receive_message(imc_state_t
*state
, imc_msg_t
*in_msg
)
167 imc_swid_state_t
*swid_state
;
168 enumerator_t
*enumerator
;
172 bool fatal_error
= FALSE
;
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
)
180 out_msg
= imc_msg_create_as_reply(in_msg
);
181 swid_state
= (imc_swid_state_t
*)state
;
183 /* analyze PA-TNC attributes */
184 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
185 while (enumerator
->enumerate(enumerator
, &attr
))
187 tcg_swid_attr_req_t
*attr_req
;
189 u_int32_t request_id
, eid_epoch
;
191 type
= attr
->get_type(attr
);
193 if (type
.vendor_id
!= PEN_TCG
|| type
.type
!= TCG_SWID_REQUEST
)
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
);
203 if (flags
& (TCG_SWID_ATTR_REQ_FLAG_S
| TCG_SWID_ATTR_REQ_FLAG_C
))
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
);
211 if (flags
& TCG_SWID_ATTR_REQ_FLAG_R
)
213 swid_tag_id_t
*tag_id
;
214 tcg_swid_attr_tag_id_inv_t
*attr_cast
;
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"),
222 attr_cast
->add_tag_id(attr_cast
, tag_id
);
227 tcg_swid_attr_tag_inv_t
*attr_cast
;
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
);
234 out_msg
->add_attribute(out_msg
, attr
);
236 enumerator
->destroy(enumerator
);
240 result
= TNC_RESULT_FATAL
;
244 result
= out_msg
->send(out_msg
, TRUE
);
246 out_msg
->destroy(out_msg
);
252 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
255 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
256 TNC_ConnectionID connection_id
,
257 TNC_BufferReference msg
,
259 TNC_MessageType msg_type
)
267 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
268 return TNC_RESULT_NOT_INITIALIZED
;
270 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
272 return TNC_RESULT_FATAL
;
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
);
283 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
285 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
286 TNC_ConnectionID connection_id
,
287 TNC_UInt32 msg_flags
,
288 TNC_BufferReference msg
,
290 TNC_VendorID msg_vid
,
291 TNC_MessageSubtype msg_subtype
,
292 TNC_UInt32 src_imv_id
,
293 TNC_UInt32 dst_imc_id
)
301 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
302 return TNC_RESULT_NOT_INITIALIZED
;
304 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
306 return TNC_RESULT_FATAL
;
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
);
318 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
320 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
321 TNC_ConnectionID connection_id
)
325 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
326 return TNC_RESULT_NOT_INITIALIZED
;
328 return TNC_RESULT_SUCCESS
;
332 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
334 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
338 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
339 return TNC_RESULT_NOT_INITIALIZED
;
344 imc_swid
->destroy(imc_swid
);
347 return TNC_RESULT_SUCCESS
;
351 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
353 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
354 TNC_TNCC_BindFunctionPointer bind_function
)
358 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
359 return TNC_RESULT_NOT_INITIALIZED
;
361 return imc_swid
->bind_functions(imc_swid
, bind_function
);