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 static pen_type_t msg_types
[] = {
42 { PEN_IETF
, PA_SUBTYPE_IETF_OPERATING_SYSTEM
}
45 static imc_agent_t
*imc_os
;
49 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
51 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
52 TNC_Version min_version
,
53 TNC_Version max_version
,
54 TNC_Version
*actual_version
)
58 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
59 return TNC_RESULT_ALREADY_INITIALIZED
;
61 imc_os
= imc_agent_create(imc_name
, msg_types
, 1, 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
, PEN_IETF
, PA_SUBTYPE_IETF_OPERATING_SYSTEM
,
236 attr_list
->destroy(attr_list
);
242 static TNC_Result
receive_message(TNC_IMCID imc_id
,
243 TNC_ConnectionID connection_id
,
244 TNC_UInt32 msg_flags
,
246 TNC_VendorID msg_vid
,
247 TNC_MessageSubtype msg_subtype
,
248 TNC_UInt32 src_imv_id
,
249 TNC_UInt32 dst_imc_id
)
251 pa_tnc_msg_t
*pa_tnc_msg
;
253 pen_type_t attr_type
;
254 linked_list_t
*attr_list
;
256 enumerator_t
*enumerator
;
258 TNC_UInt32 target_imc_id
;
263 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
264 return TNC_RESULT_NOT_INITIALIZED
;
267 /* get current IMC state */
268 if (!imc_os
->get_state(imc_os
, connection_id
, &state
))
270 return TNC_RESULT_FATAL
;
273 /* parse received PA-TNC message and automatically handle any errors */
274 result
= imc_os
->receive_message(imc_os
, state
, msg
, msg_vid
,
275 msg_subtype
, src_imv_id
, dst_imc_id
, &pa_tnc_msg
);
277 /* no parsed PA-TNC attributes available if an error occurred */
282 target_imc_id
= (dst_imc_id
== TNC_IMCID_ANY
) ? imc_id
: dst_imc_id
;
284 /* preprocess any IETF standard error attributes */
285 fatal_error
= pa_tnc_msg
->process_ietf_std_errors(pa_tnc_msg
);
287 /* analyze PA-TNC attributes */
288 attr_list
= linked_list_create();
289 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
290 while (enumerator
->enumerate(enumerator
, &attr
))
292 attr_type
= attr
->get_type(attr
);
294 if (attr_type
.vendor_id
!= PEN_IETF
)
298 if (attr_type
.type
== IETF_ATTR_ATTRIBUTE_REQUEST
)
300 ietf_attr_attr_request_t
*attr_cast
;
304 attr_cast
= (ietf_attr_attr_request_t
*)attr
;
306 e
= attr_cast
->create_enumerator(attr_cast
);
307 while (e
->enumerate(e
, &entry
))
309 if (entry
->vendor_id
!= PEN_IETF
)
315 case IETF_ATTR_PRODUCT_INFORMATION
:
316 add_product_info(attr_list
);
318 case IETF_ATTR_STRING_VERSION
:
319 add_string_version(attr_list
);
321 case IETF_ATTR_OPERATIONAL_STATUS
:
322 add_op_status(attr_list
);
324 case IETF_ATTR_FORWARDING_ENABLED
:
325 add_fwd_enabled(attr_list
);
327 case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED
:
328 add_default_pwd_enabled(attr_list
);
330 case IETF_ATTR_INSTALLED_PACKAGES
:
331 add_installed_packages(attr_list
);
339 else if (attr_type
.type
== IETF_ATTR_ASSESSMENT_RESULT
)
341 ietf_attr_assess_result_t
*attr_cast
;
343 attr_cast
= (ietf_attr_assess_result_t
*)attr
;
344 state
->set_result(state
, target_imc_id
,
345 attr_cast
->get_result(attr_cast
));
348 enumerator
->destroy(enumerator
);
349 pa_tnc_msg
->destroy(pa_tnc_msg
);
353 attr_list
->destroy_offset(attr_list
, offsetof(pa_tnc_attr_t
, destroy
));
354 return TNC_RESULT_FATAL
;
357 if (attr_list
->get_count(attr_list
))
359 result
= imc_os
->send_message(imc_os
, connection_id
, TRUE
, imc_id
,
360 src_imv_id
, PEN_IETF
, PA_SUBTYPE_IETF_OPERATING_SYSTEM
,
365 result
= TNC_RESULT_SUCCESS
;
367 attr_list
->destroy(attr_list
);
373 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
376 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
377 TNC_ConnectionID connection_id
,
378 TNC_BufferReference msg
,
380 TNC_MessageType msg_type
)
382 TNC_VendorID msg_vid
;
383 TNC_MessageSubtype msg_subtype
;
385 msg_vid
= msg_type
>> 8;
386 msg_subtype
= msg_type
& TNC_SUBTYPE_ANY
;
388 return receive_message(imc_id
, connection_id
, 0, chunk_create(msg
, msg_len
),
389 msg_vid
, msg_subtype
, 0, TNC_IMCID_ANY
);
393 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
395 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
396 TNC_ConnectionID connection_id
,
397 TNC_UInt32 msg_flags
,
398 TNC_BufferReference msg
,
400 TNC_VendorID msg_vid
,
401 TNC_MessageSubtype msg_subtype
,
402 TNC_UInt32 src_imv_id
,
403 TNC_UInt32 dst_imc_id
)
405 return receive_message(imc_id
, connection_id
, msg_flags
,
406 chunk_create(msg
, msg_len
), msg_vid
, msg_subtype
,
407 src_imv_id
, dst_imc_id
);
411 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
413 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
414 TNC_ConnectionID connection_id
)
418 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
419 return TNC_RESULT_NOT_INITIALIZED
;
421 return TNC_RESULT_SUCCESS
;
425 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
427 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
431 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
432 return TNC_RESULT_NOT_INITIALIZED
;
434 imc_os
->destroy(imc_os
);
440 return TNC_RESULT_SUCCESS
;
444 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
446 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
447 TNC_TNCC_BindFunctionPointer bind_function
)
451 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
452 return TNC_RESULT_NOT_INITIALIZED
;
454 return imc_os
->bind_functions(imc_os
, bind_function
);