2 * Copyright (C) 2011-2012 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 "imv_test_state.h"
18 #include <imv/imv_agent.h>
19 #include <imv/imv_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_pa_tnc_error.h>
22 #include <ita/ita_attr.h>
23 #include <ita/ita_attr_command.h>
24 #include <ita/ita_attr_dummy.h>
26 #include <tncif_names.h>
27 #include <tncif_pa_subtypes.h>
34 static const char imv_name
[] = "Test";
36 static pen_type_t msg_types
[] = {
37 { PEN_ITA
, PA_SUBTYPE_ITA_TEST
}
40 static imv_agent_t
*imv_test
;
43 * see section 3.8.1 of TCG TNC IF-IMV Specification 1.3
45 TNC_Result
TNC_IMV_Initialize(TNC_IMVID imv_id
,
46 TNC_Version min_version
,
47 TNC_Version max_version
,
48 TNC_Version
*actual_version
)
52 DBG1(DBG_IMV
, "IMV \"%s\" has already been initialized", imv_name
);
53 return TNC_RESULT_ALREADY_INITIALIZED
;
55 imv_test
= imv_agent_create(imv_name
, msg_types
, 1, imv_id
, actual_version
);
58 return TNC_RESULT_FATAL
;
60 if (min_version
> TNC_IFIMV_VERSION_1
|| max_version
< TNC_IFIMV_VERSION_1
)
62 DBG1(DBG_IMV
, "no common IF-IMV version");
63 return TNC_RESULT_NO_COMMON_VERSION
;
65 return TNC_RESULT_SUCCESS
;
69 * see section 3.8.2 of TCG TNC IF-IMV Specification 1.3
71 TNC_Result
TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id
,
72 TNC_ConnectionID connection_id
,
73 TNC_ConnectionState new_state
)
79 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
80 return TNC_RESULT_NOT_INITIALIZED
;
84 case TNC_CONNECTION_STATE_CREATE
:
85 state
= imv_test_state_create(connection_id
);
86 return imv_test
->create_state(imv_test
, state
);
87 case TNC_CONNECTION_STATE_DELETE
:
88 return imv_test
->delete_state(imv_test
, connection_id
);
90 return imv_test
->change_state(imv_test
, connection_id
,
95 static TNC_Result
receive_message(imv_state_t
*state
, imv_msg_t
*in_msg
)
98 imv_test_state_t
*test_state
;
99 enumerator_t
*enumerator
;
101 pen_type_t attr_type
;
104 bool fatal_error
= FALSE
, received_command
= FALSE
, retry
= FALSE
;
106 /* parse received PA-TNC message and handle local and remote errors */
107 result
= in_msg
->receive(in_msg
, &fatal_error
);
108 if (result
!= TNC_RESULT_SUCCESS
)
113 /* add any new IMC and set its number of rounds */
114 rounds
= lib
->settings
->get_int(lib
->settings
,
115 "libimcv.plugins.imv-test.rounds", 0);
116 test_state
= (imv_test_state_t
*)state
;
117 test_state
->add_imc(test_state
, in_msg
->get_src_id(in_msg
), rounds
);
119 /* analyze PA-TNC attributes */
120 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
121 while (enumerator
->enumerate(enumerator
, &attr
))
123 attr_type
= attr
->get_type(attr
);
125 if (attr_type
.vendor_id
!= PEN_ITA
)
129 if (attr_type
.type
== ITA_ATTR_COMMAND
)
131 ita_attr_command_t
*ita_attr
;
134 received_command
= TRUE
;
135 ita_attr
= (ita_attr_command_t
*)attr
;
136 command
= ita_attr
->get_command(ita_attr
);
138 if (streq(command
, "allow"))
140 state
->set_recommendation(state
,
141 TNC_IMV_ACTION_RECOMMENDATION_ALLOW
,
142 TNC_IMV_EVALUATION_RESULT_COMPLIANT
);
144 else if (streq(command
, "isolate"))
146 state
->set_recommendation(state
,
147 TNC_IMV_ACTION_RECOMMENDATION_ISOLATE
,
148 TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR
);
150 else if (streq(command
, "block") || streq(command
, "none"))
152 state
->set_recommendation(state
,
153 TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS
,
154 TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR
);
156 else if (streq(command
, "retry"))
162 DBG1(DBG_IMV
, "unsupported ITA Command '%s'", command
);
163 state
->set_recommendation(state
,
164 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
165 TNC_IMV_EVALUATION_RESULT_ERROR
);
168 else if (attr_type
.type
== ITA_ATTR_DUMMY
)
170 ita_attr_dummy_t
*ita_attr
;
172 ita_attr
= (ita_attr_dummy_t
*)attr
;
173 DBG1(DBG_IMV
, "received dummy attribute value (%d bytes)",
174 ita_attr
->get_size(ita_attr
));
177 enumerator
->destroy(enumerator
);
181 state
->set_recommendation(state
,
182 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
183 TNC_IMV_EVALUATION_RESULT_ERROR
);
184 out_msg
= imv_msg_create_as_reply(in_msg
);
185 result
= out_msg
->send_assessment(out_msg
);
186 out_msg
->destroy(out_msg
);
187 if (result
!= TNC_RESULT_SUCCESS
)
191 return imv_test
->provide_recommendation(imv_test
, state
);
194 /* request a handshake retry ? */
197 test_state
->set_rounds(test_state
, rounds
);
198 return imv_test
->request_handshake_retry(imv_test
->get_id(imv_test
),
199 state
->get_connection_id(state
),
200 TNC_RETRY_REASON_IMV_SERIOUS_EVENT
);
203 /* repeat the measurement ? */
204 if (test_state
->another_round(test_state
, in_msg
->get_src_id(in_msg
)))
206 out_msg
= imv_msg_create_as_reply(in_msg
);
207 attr
= ita_attr_command_create("repeat");
208 out_msg
->add_attribute(out_msg
, attr
);
210 /* send PA-TNC message with excl flag set */
211 result
= out_msg
->send(out_msg
, TRUE
);
212 out_msg
->destroy(out_msg
);
217 if (received_command
)
219 out_msg
= imv_msg_create_as_reply(in_msg
);
220 result
= out_msg
->send_assessment(out_msg
);
221 out_msg
->destroy(out_msg
);
222 if (result
!= TNC_RESULT_SUCCESS
)
226 return imv_test
->provide_recommendation(imv_test
, state
);
230 return TNC_RESULT_SUCCESS
;
235 * see section 3.8.4 of TCG TNC IF-IMV Specification 1.3
237 TNC_Result
TNC_IMV_ReceiveMessage(TNC_IMVID imv_id
,
238 TNC_ConnectionID connection_id
,
239 TNC_BufferReference msg
,
241 TNC_MessageType msg_type
)
249 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
250 return TNC_RESULT_NOT_INITIALIZED
;
252 if (!imv_test
->get_state(imv_test
, connection_id
, &state
))
254 return TNC_RESULT_FATAL
;
256 in_msg
= imv_msg_create_from_data(imv_test
, state
, connection_id
, msg_type
,
257 chunk_create(msg
, msg_len
));
258 result
= receive_message(state
, in_msg
);
259 in_msg
->destroy(in_msg
);
265 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
267 TNC_Result
TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id
,
268 TNC_ConnectionID connection_id
,
269 TNC_UInt32 msg_flags
,
270 TNC_BufferReference msg
,
272 TNC_VendorID msg_vid
,
273 TNC_MessageSubtype msg_subtype
,
274 TNC_UInt32 src_imc_id
,
275 TNC_UInt32 dst_imv_id
)
283 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
284 return TNC_RESULT_NOT_INITIALIZED
;
286 if (!imv_test
->get_state(imv_test
, connection_id
, &state
))
288 return TNC_RESULT_FATAL
;
290 in_msg
= imv_msg_create_from_long_data(imv_test
, state
, connection_id
,
291 src_imc_id
, dst_imv_id
, msg_vid
, msg_subtype
,
292 chunk_create(msg
, msg_len
));
293 result
=receive_message(state
, in_msg
);
294 in_msg
->destroy(in_msg
);
300 * see section 3.8.7 of TCG TNC IF-IMV Specification 1.3
302 TNC_Result
TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id
,
303 TNC_ConnectionID connection_id
)
309 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
310 return TNC_RESULT_NOT_INITIALIZED
;
312 if (!imv_test
->get_state(imv_test
, connection_id
, &state
))
314 return TNC_RESULT_FATAL
;
316 return imv_test
->provide_recommendation(imv_test
, state
);
320 * see section 3.8.8 of TCG TNC IF-IMV Specification 1.3
322 TNC_Result
TNC_IMV_BatchEnding(TNC_IMVID imv_id
,
323 TNC_ConnectionID connection_id
)
327 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
328 return TNC_RESULT_NOT_INITIALIZED
;
330 return TNC_RESULT_SUCCESS
;
334 * see section 3.8.9 of TCG TNC IF-IMV Specification 1.3
336 TNC_Result
TNC_IMV_Terminate(TNC_IMVID imv_id
)
340 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
341 return TNC_RESULT_NOT_INITIALIZED
;
343 imv_test
->destroy(imv_test
);
346 return TNC_RESULT_SUCCESS
;
350 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.3
352 TNC_Result
TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id
,
353 TNC_TNCS_BindFunctionPointer bind_function
)
357 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
358 return TNC_RESULT_NOT_INITIALIZED
;
360 return imv_test
->bind_functions(imv_test
, bind_function
);