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 "imc_os_state.h"
18 #include <imc/imc_agent.h>
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_assess_result.h>
22 #include <ietf/ietf_attr_attr_request.h>
23 #include <ietf/ietf_attr_default_pwd_enabled.h>
24 #include <ietf/ietf_attr_fwd_enabled.h>
25 #include <ietf/ietf_attr_installed_packages.h>
26 #include <ietf/ietf_attr_op_status.h>
27 #include <ietf/ietf_attr_pa_tnc_error.h>
28 #include <ietf/ietf_attr_product_info.h>
29 #include <ietf/ietf_attr_string_version.h>
30 #include <os_info/os_info.h>
32 #include <tncif_pa_subtypes.h>
39 static const char imc_name
[] = "OS";
41 #define IMC_VENDOR_ID PEN_IETF
42 #define IMC_SUBTYPE PA_SUBTYPE_IETF_OPERATING_SYSTEM
44 static imc_agent_t
*imc_os
;
48 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
50 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
51 TNC_Version min_version
,
52 TNC_Version max_version
,
53 TNC_Version
*actual_version
)
57 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
58 return TNC_RESULT_ALREADY_INITIALIZED
;
60 imc_os
= imc_agent_create(imc_name
, IMC_VENDOR_ID
, IMC_SUBTYPE
,
61 imc_id
, actual_version
);
64 return TNC_RESULT_FATAL
;
67 os
= os_info_create();
70 imc_os
->destroy(imc_os
);
73 return TNC_RESULT_FATAL
;
76 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
78 DBG1(DBG_IMC
, "no common IF-IMC version");
79 return TNC_RESULT_NO_COMMON_VERSION
;
81 return TNC_RESULT_SUCCESS
;
85 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
87 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
88 TNC_ConnectionID connection_id
,
89 TNC_ConnectionState new_state
)
95 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
96 return TNC_RESULT_NOT_INITIALIZED
;
100 case TNC_CONNECTION_STATE_CREATE
:
101 state
= imc_os_state_create(connection_id
);
102 return imc_os
->create_state(imc_os
, state
);
103 case TNC_CONNECTION_STATE_HANDSHAKE
:
104 if (imc_os
->change_state(imc_os
, connection_id
, new_state
,
105 &state
) != TNC_RESULT_SUCCESS
)
107 return TNC_RESULT_FATAL
;
109 state
->set_result(state
, imc_id
,
110 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
111 return TNC_RESULT_SUCCESS
;
112 case TNC_CONNECTION_STATE_DELETE
:
113 return imc_os
->delete_state(imc_os
, connection_id
);
115 return imc_os
->change_state(imc_os
, connection_id
,
121 * Add IETF Product Information attribute to the send queue
123 static void add_product_info(linked_list_t
*attr_list
)
127 attr
= ietf_attr_product_info_create(PEN_IETF
, 0, os
->get_name(os
));
128 attr_list
->insert_last(attr_list
, attr
);
132 * Add IETF String Version attribute to the send queue
134 static void add_string_version(linked_list_t
*attr_list
)
138 attr
= ietf_attr_string_version_create(os
->get_version(os
),
139 chunk_empty
, chunk_empty
);
140 attr_list
->insert_last(attr_list
, attr
);
144 * Add IETF Operational Status attribute to the send queue
146 static void add_op_status(linked_list_t
*attr_list
)
149 time_t uptime
, last_boot
;
151 uptime
= os
->get_uptime(os
);
152 last_boot
= uptime ?
time(NULL
) - uptime
: UNDEFINED_TIME
;
153 if (last_boot
!= UNDEFINED_TIME
)
155 DBG1(DBG_IMC
, "last boot: %T, %u s ago", &last_boot
, TRUE
, uptime
);
157 attr
= ietf_attr_op_status_create(OP_STATUS_OPERATIONAL
,
158 OP_RESULT_SUCCESSFUL
, last_boot
);
159 attr_list
->insert_last(attr_list
, attr
);
163 * Add IETF Forwarding Enabled attribute to the send queue
165 static void add_fwd_enabled(linked_list_t
*attr_list
)
168 os_fwd_status_t fwd_status
;
170 fwd_status
= os
->get_fwd_status(os
);
171 DBG1(DBG_IMC
, "IPv4 forwarding status: %N",
172 os_fwd_status_names
, fwd_status
);
173 attr
= ietf_attr_fwd_enabled_create(fwd_status
);
174 attr_list
->insert_last(attr_list
, attr
);
178 * Add IETF Factory Default Password Enabled attribute to the send queue
180 static void add_default_pwd_enabled(linked_list_t
*attr_list
)
184 DBG1(DBG_IMC
, "factory default password: disabled");
185 attr
= ietf_attr_default_pwd_enabled_create(FALSE
);
186 attr_list
->insert_last(attr_list
, attr
);
190 * Add an IETF Installed Packages attribute to the send queue
192 static void add_installed_packages(linked_list_t
*attr_list
)
195 ietf_attr_installed_packages_t
*attr_cast
;
196 chunk_t libc_name
= { "libc-bin", 8 };
197 chunk_t libc_version
= { "2.15-0ubuntu10.2", 16 };
198 chunk_t selinux_name
= { "selinux", 7 };
199 chunk_t selinux_version
= { "1:0.11", 6 };
201 attr
= ietf_attr_installed_packages_create();
202 attr_cast
= (ietf_attr_installed_packages_t
*)attr
;
203 attr_cast
->add(attr_cast
, libc_name
, libc_version
);
204 attr_cast
->add(attr_cast
, selinux_name
, selinux_version
);
205 attr_list
->insert_last(attr_list
, attr
);
209 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
211 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
212 TNC_ConnectionID connection_id
)
214 TNC_Result result
= TNC_RESULT_SUCCESS
;
218 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
219 return TNC_RESULT_NOT_INITIALIZED
;
222 if (lib
->settings
->get_bool(lib
->settings
,
223 "libimcv.plugins.imc-os.send_info", TRUE
))
225 linked_list_t
*attr_list
;
227 attr_list
= linked_list_create();
228 add_product_info(attr_list
);
229 add_string_version(attr_list
);
230 add_op_status(attr_list
);
231 add_fwd_enabled(attr_list
);
232 add_default_pwd_enabled(attr_list
);
233 result
= imc_os
->send_message(imc_os
, connection_id
, FALSE
, 0,
234 TNC_IMVID_ANY
, attr_list
);
235 attr_list
->destroy(attr_list
);
241 static TNC_Result
receive_message(TNC_IMCID imc_id
,
242 TNC_ConnectionID connection_id
,
243 TNC_UInt32 msg_flags
,
245 TNC_VendorID msg_vid
,
246 TNC_MessageSubtype msg_subtype
,
247 TNC_UInt32 src_imv_id
,
248 TNC_UInt32 dst_imc_id
)
250 pa_tnc_msg_t
*pa_tnc_msg
;
252 pen_type_t attr_type
;
253 linked_list_t
*attr_list
;
255 enumerator_t
*enumerator
;
257 TNC_UInt32 target_imc_id
;
262 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
263 return TNC_RESULT_NOT_INITIALIZED
;
266 /* get current IMC state */
267 if (!imc_os
->get_state(imc_os
, connection_id
, &state
))
269 return TNC_RESULT_FATAL
;
272 /* parse received PA-TNC message and automatically handle any errors */
273 result
= imc_os
->receive_message(imc_os
, state
, msg
, msg_vid
,
274 msg_subtype
, src_imv_id
, dst_imc_id
, &pa_tnc_msg
);
276 /* no parsed PA-TNC attributes available if an error occurred */
281 target_imc_id
= (dst_imc_id
== TNC_IMCID_ANY
) ? imc_id
: dst_imc_id
;
283 /* preprocess any IETF standard error attributes */
284 fatal_error
= pa_tnc_msg
->process_ietf_std_errors(pa_tnc_msg
);
286 /* analyze PA-TNC attributes */
287 attr_list
= linked_list_create();
288 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
289 while (enumerator
->enumerate(enumerator
, &attr
))
291 attr_type
= attr
->get_type(attr
);
293 if (attr_type
.vendor_id
!= PEN_IETF
)
297 if (attr_type
.type
== IETF_ATTR_ATTRIBUTE_REQUEST
)
299 ietf_attr_attr_request_t
*attr_cast
;
303 attr_cast
= (ietf_attr_attr_request_t
*)attr
;
305 e
= attr_cast
->create_enumerator(attr_cast
);
306 while (e
->enumerate(e
, &entry
))
308 if (entry
->vendor_id
!= PEN_IETF
)
314 case IETF_ATTR_PRODUCT_INFORMATION
:
315 add_product_info(attr_list
);
317 case IETF_ATTR_STRING_VERSION
:
318 add_string_version(attr_list
);
320 case IETF_ATTR_OPERATIONAL_STATUS
:
321 add_op_status(attr_list
);
323 case IETF_ATTR_FORWARDING_ENABLED
:
324 add_fwd_enabled(attr_list
);
326 case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED
:
327 add_default_pwd_enabled(attr_list
);
329 case IETF_ATTR_INSTALLED_PACKAGES
:
330 add_installed_packages(attr_list
);
338 else if (attr_type
.type
== IETF_ATTR_ASSESSMENT_RESULT
)
340 ietf_attr_assess_result_t
*attr_cast
;
342 attr_cast
= (ietf_attr_assess_result_t
*)attr
;
343 state
->set_result(state
, target_imc_id
,
344 attr_cast
->get_result(attr_cast
));
347 enumerator
->destroy(enumerator
);
348 pa_tnc_msg
->destroy(pa_tnc_msg
);
352 attr_list
->destroy_offset(attr_list
, offsetof(pa_tnc_attr_t
, destroy
));
353 return TNC_RESULT_FATAL
;
356 if (attr_list
->get_count(attr_list
))
358 result
= imc_os
->send_message(imc_os
, connection_id
, TRUE
, imc_id
,
359 src_imv_id
, attr_list
);
363 result
= TNC_RESULT_SUCCESS
;
365 attr_list
->destroy(attr_list
);
371 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
374 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
375 TNC_ConnectionID connection_id
,
376 TNC_BufferReference msg
,
378 TNC_MessageType msg_type
)
380 TNC_VendorID msg_vid
;
381 TNC_MessageSubtype msg_subtype
;
383 msg_vid
= msg_type
>> 8;
384 msg_subtype
= msg_type
& TNC_SUBTYPE_ANY
;
386 return receive_message(imc_id
, connection_id
, 0, chunk_create(msg
, msg_len
),
387 msg_vid
, msg_subtype
, 0, TNC_IMCID_ANY
);
391 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
393 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
394 TNC_ConnectionID connection_id
,
395 TNC_UInt32 msg_flags
,
396 TNC_BufferReference msg
,
398 TNC_VendorID msg_vid
,
399 TNC_MessageSubtype msg_subtype
,
400 TNC_UInt32 src_imv_id
,
401 TNC_UInt32 dst_imc_id
)
403 return receive_message(imc_id
, connection_id
, msg_flags
,
404 chunk_create(msg
, msg_len
), msg_vid
, msg_subtype
,
405 src_imv_id
, dst_imc_id
);
409 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
411 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
412 TNC_ConnectionID connection_id
)
416 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
417 return TNC_RESULT_NOT_INITIALIZED
;
419 return TNC_RESULT_SUCCESS
;
423 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
425 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
429 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
430 return TNC_RESULT_NOT_INITIALIZED
;
432 imc_os
->destroy(imc_os
);
438 return TNC_RESULT_SUCCESS
;
442 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
444 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
445 TNC_TNCC_BindFunctionPointer bind_function
)
449 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
450 return TNC_RESULT_NOT_INITIALIZED
;
452 return imc_os
->bind_functions(imc_os
, bind_function
);