2 * Copyright (C) 2012-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 "imv_os_state.h"
18 #include "imv/imv_lang_string.h"
19 #include "imv/imv_reason_string.h"
20 #include "imv/imv_remediation_string.h"
22 #include <tncif_policy.h>
24 #include <utils/debug.h>
25 #include <collections/linked_list.h>
27 typedef struct private_imv_os_state_t private_imv_os_state_t
;
28 typedef struct package_entry_t package_entry_t
;
29 typedef struct entry_t entry_t
;
30 typedef struct instruction_entry_t instruction_entry_t
;
33 * Private data of an imv_os_state_t object.
35 struct private_imv_os_state_t
{
38 * Public members of imv_os_state_t
40 imv_os_state_t
public;
45 TNC_ConnectionID connection_id
;
48 * TNCCS connection state
50 TNC_ConnectionState state
;
53 * Does the TNCCS connection support long message types?
58 * Does the TNCCS connection support exclusive delivery?
63 * Maximum PA-TNC message size for this TNCCS connection
65 u_int32_t max_msg_len
;
68 * Flags set for completed actions
70 u_int32_t action_flags
;
73 * Access Requestor ID Type
78 * Access Requestor ID Value
83 * IMV database session associated with TNCCS connection
85 imv_session_t
*session
;
88 * IMV action recommendation
90 TNC_IMV_Action_Recommendation rec
;
93 * IMV evaluation result
95 TNC_IMV_Evaluation_Result eval
;
98 * IMV OS handshake state
100 imv_os_handshake_state_t handshake_state
;
103 * OS Product Information (concatenation of OS Name and Version)
123 * List of blacklisted packages to be removed
125 linked_list_t
*remove_packages
;
128 * List of vulnerable packages to be updated
130 linked_list_t
*update_packages
;
135 imv_reason_string_t
*reason_string
;
138 * IETF Remediation Instructions String
140 imv_remediation_string_t
*remediation_string
;
148 * Number of processed packages
153 * Number of not updated packages
158 * Number of blacklisted packages
163 * Number of whitelisted packages
180 * Supported languages
182 static char* languages
[] = { "en", "de", "pl" };
185 * Reason strings for "OS settings"
187 static imv_lang_string_t reason_settings
[] = {
188 { "en", "Improper OS settings were detected" },
189 { "de", "Unzulässige OS Einstellungen wurden festgestellt" },
190 { "pl", "Stwierdzono niewłaściwe ustawienia OS" },
195 * Reason strings for "installed software packages"
197 static imv_lang_string_t reason_packages
[] = {
198 { "en", "Vulnerable or blacklisted software packages were found" },
199 { "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" },
200 { "pl", "Znaleziono pakiety podatne na atak lub będące na czarnej liście" },
205 * Instruction strings for "Software Security Updates"
207 static imv_lang_string_t instr_update_packages_title
[] = {
208 { "en", "Software Security Updates" },
209 { "de", "Software Sicherheitsupdates" },
210 { "pl", "Aktualizacja softwaru zabezpieczającego" },
214 static imv_lang_string_t instr_update_packages_descr
[] = {
215 { "en", "Packages with security vulnerabilities were found" },
216 { "de", "Softwarepakete mit Sicherheitsschwachstellen wurden gefunden" },
217 { "pl", "Znaleziono pakiety podatne na atak" },
221 static imv_lang_string_t instr_update_packages_header
[] = {
222 { "en", "Please update the following software packages:" },
223 { "de", "Bitte updaten Sie die folgenden Softwarepakete:" },
224 { "pl", "Proszę zaktualizować następujące pakiety:" },
229 * Instruction strings for "Blacklisted Software Packages"
231 static imv_lang_string_t instr_remove_packages_title
[] = {
232 { "en", "Blacklisted Software Packages" },
233 { "de", "Gesperrte Softwarepakete" },
234 { "pl", "Pakiety będące na czarnej liście" },
238 static imv_lang_string_t instr_remove_packages_descr
[] = {
239 { "en", "Dangerous software packages were found" },
240 { "de", "Gefährliche Softwarepakete wurden gefunden" },
241 { "pl", "Znaleziono niebezpieczne pakiety" },
245 static imv_lang_string_t instr_remove_packages_header
[] = {
246 { "en", "Please remove the following software packages:" },
247 { "de", "Bitte entfernen Sie die folgenden Softwarepakete:" },
248 { "pl", "Proszę usunąć następujące pakiety:" },
253 * Instruction strings for "Forwarding Enabled"
255 static imv_lang_string_t instr_fwd_enabled_title
[] = {
256 { "en", "IP Packet Forwarding" },
257 { "de", "Weiterleitung von IP Paketen" },
258 { "pl", "Przekazywanie pakietów IP" },
262 static imv_lang_string_t instr_fwd_enabled_descr
[] = {
263 { "en", "Please disable the forwarding of IP packets" },
264 { "de", "Bitte deaktivieren Sie das Forwarding von IP Paketen" },
265 { "pl", "Proszę zdezaktywować przekazywanie pakietów IP" },
270 * Instruction strings for "Default Password Enabled"
272 static imv_lang_string_t instr_default_pwd_enabled_title
[] = {
273 { "en", "Default Password" },
274 { "de", "Default Passwort" },
275 { "pl", "Hasło domyślne" },
279 static imv_lang_string_t instr_default_pwd_enabled_descr
[] = {
280 { "en", "Please change the default password" },
281 { "de", "Bitte ändern Sie das Default Passwort" },
282 { "pl", "Proszę zmienić domyślne hasło" },
287 * Instruction strings for "Unknown Source"
289 static imv_lang_string_t instr_unknown_source_title
[] = {
290 { "en", "Unknown Software Origin" },
291 { "de", "Unbekannte Softwareherkunft" },
292 { "pl", "Nieznane pochodzenie softwaru" },
296 static imv_lang_string_t instr_unknown_source_descr
[] = {
297 { "en", "Do not allow the installation of apps from unknown sources" },
298 { "de", "Erlauben Sie nicht die Installation von Apps aus unbekannten Quellen" },
299 { "pl", "Proszę nie dopuszczać do instalacji Apps z nieznanych źródeł" },
303 METHOD(imv_state_t
, get_connection_id
, TNC_ConnectionID
,
304 private_imv_os_state_t
*this)
306 return this->connection_id
;
309 METHOD(imv_state_t
, has_long
, bool,
310 private_imv_os_state_t
*this)
312 return this->has_long
;
315 METHOD(imv_state_t
, has_excl
, bool,
316 private_imv_os_state_t
*this)
318 return this->has_excl
;
321 METHOD(imv_state_t
, set_flags
, void,
322 private_imv_os_state_t
*this, bool has_long
, bool has_excl
)
324 this->has_long
= has_long
;
325 this->has_excl
= has_excl
;
328 METHOD(imv_state_t
, set_max_msg_len
, void,
329 private_imv_os_state_t
*this, u_int32_t max_msg_len
)
331 this->max_msg_len
= max_msg_len
;
334 METHOD(imv_state_t
, get_max_msg_len
, u_int32_t
,
335 private_imv_os_state_t
*this)
337 return this->max_msg_len
;
340 METHOD(imv_state_t
, set_action_flags
, void,
341 private_imv_os_state_t
*this, u_int32_t flags
)
343 this->action_flags
|= flags
;
346 METHOD(imv_state_t
, get_action_flags
, u_int32_t
,
347 private_imv_os_state_t
*this)
349 return this->action_flags
;
352 METHOD(imv_state_t
, set_ar_id
, void,
353 private_imv_os_state_t
*this, u_int32_t id_type
, chunk_t id_value
)
355 this->ar_id_type
= id_type
;
356 this->ar_id_value
= chunk_clone(id_value
);
359 METHOD(imv_state_t
, get_ar_id
, chunk_t
,
360 private_imv_os_state_t
*this, u_int32_t
*id_type
)
364 *id_type
= this->ar_id_type
;
366 return this->ar_id_value
;
369 METHOD(imv_state_t
, set_session
, void,
370 private_imv_os_state_t
*this, imv_session_t
*session
)
372 this->session
= session
;
375 METHOD(imv_state_t
, get_session
, imv_session_t
*,
376 private_imv_os_state_t
*this)
378 return this->session
;
381 METHOD(imv_state_t
, get_recommendation
, void,
382 private_imv_os_state_t
*this, TNC_IMV_Action_Recommendation
*rec
,
383 TNC_IMV_Evaluation_Result
*eval
)
389 METHOD(imv_state_t
, set_recommendation
, void,
390 private_imv_os_state_t
*this, TNC_IMV_Action_Recommendation rec
,
391 TNC_IMV_Evaluation_Result eval
)
397 METHOD(imv_state_t
, update_recommendation
, void,
398 private_imv_os_state_t
*this, TNC_IMV_Action_Recommendation rec
,
399 TNC_IMV_Evaluation_Result eval
)
401 this->rec
= tncif_policy_update_recommendation(this->rec
, rec
);
402 this->eval
= tncif_policy_update_evaluation(this->eval
, eval
);
405 METHOD(imv_state_t
, change_state
, void,
406 private_imv_os_state_t
*this, TNC_ConnectionState new_state
)
408 this->state
= new_state
;
411 METHOD(imv_state_t
, get_reason_string
, bool,
412 private_imv_os_state_t
*this, enumerator_t
*language_enumerator
,
413 chunk_t
*reason_string
, char **reason_language
)
415 if (!this->count_update
&& !this->count_blacklist
& !this->os_settings
)
419 *reason_language
= imv_lang_string_select_lang(language_enumerator
,
420 languages
, countof(languages
));
422 /* Instantiate a TNC Reason String object */
423 DESTROY_IF(this->reason_string
);
424 this->reason_string
= imv_reason_string_create(*reason_language
, "\n");
426 if (this->count_update
|| this->count_blacklist
)
428 this->reason_string
->add_reason(this->reason_string
, reason_packages
);
430 if (this->os_settings
)
432 this->reason_string
->add_reason(this->reason_string
, reason_settings
);
434 *reason_string
= this->reason_string
->get_encoding(this->reason_string
);
439 METHOD(imv_state_t
, get_remediation_instructions
, bool,
440 private_imv_os_state_t
*this, enumerator_t
*language_enumerator
,
441 chunk_t
*string
, char **lang_code
, char **uri
)
443 if (!this->count_update
&& !this->count_blacklist
& !this->os_settings
)
447 *lang_code
= imv_lang_string_select_lang(language_enumerator
,
448 languages
, countof(languages
));
450 /* Instantiate an IETF Remediation Instructions String object */
451 DESTROY_IF(this->remediation_string
);
452 this->remediation_string
= imv_remediation_string_create(
453 this->type
== OS_TYPE_ANDROID
, *lang_code
);
455 /* List of blacklisted packages to be removed, if any */
456 if (this->count_blacklist
)
458 this->remediation_string
->add_instruction(this->remediation_string
,
459 instr_remove_packages_title
,
460 instr_remove_packages_descr
,
461 instr_remove_packages_header
,
462 this->remove_packages
);
465 /* List of packages in need of an update, if any */
466 if (this->count_update
)
468 this->remediation_string
->add_instruction(this->remediation_string
,
469 instr_update_packages_title
,
470 instr_update_packages_descr
,
471 instr_update_packages_header
,
472 this->update_packages
);
475 /* Add instructions concerning improper OS settings */
476 if (this->os_settings
& OS_SETTINGS_FWD_ENABLED
)
478 this->remediation_string
->add_instruction(this->remediation_string
,
479 instr_fwd_enabled_title
,
480 instr_fwd_enabled_descr
, NULL
, NULL
);
482 if (this->os_settings
& OS_SETTINGS_DEFAULT_PWD_ENABLED
)
484 this->remediation_string
->add_instruction(this->remediation_string
,
485 instr_default_pwd_enabled_title
,
486 instr_default_pwd_enabled_descr
, NULL
, NULL
);
488 if (this->os_settings
& OS_SETTINGS_UNKNOWN_SOURCE
)
490 this->remediation_string
->add_instruction(this->remediation_string
,
491 instr_unknown_source_title
,
492 instr_unknown_source_descr
, NULL
, NULL
);
495 *string
= this->remediation_string
->get_encoding(this->remediation_string
);
496 *uri
= lib
->settings
->get_str(lib
->settings
,
497 "%s.plugins.imv-os.remediation_uri", NULL
, lib
->ns
);
502 METHOD(imv_state_t
, destroy
, void,
503 private_imv_os_state_t
*this)
505 DESTROY_IF(this->session
);
506 DESTROY_IF(this->reason_string
);
507 DESTROY_IF(this->remediation_string
);
508 this->update_packages
->destroy_function(this->update_packages
, free
);
509 this->remove_packages
->destroy_function(this->remove_packages
, free
);
511 free(this->name
.ptr
);
512 free(this->version
.ptr
);
513 free(this->ar_id_value
.ptr
);
514 free(this->device_id
.ptr
);
518 METHOD(imv_os_state_t
, set_handshake_state
, void,
519 private_imv_os_state_t
*this, imv_os_handshake_state_t new_state
)
521 this->handshake_state
= new_state
;
524 METHOD(imv_os_state_t
, get_handshake_state
, imv_os_handshake_state_t
,
525 private_imv_os_state_t
*this)
527 return this->handshake_state
;
530 METHOD(imv_os_state_t
, set_info
, void,
531 private_imv_os_state_t
*this, os_type_t type
, chunk_t name
, chunk_t version
)
533 int len
= name
.len
+ 1 + version
.len
+ 1;
535 /* OS info is a concatenation of OS name and OS version */
537 this->info
= malloc(len
);
538 snprintf(this->info
, len
, "%.*s %.*s", (int)name
.len
, name
.ptr
,
539 (int)version
.len
, version
.ptr
);
541 this->name
= chunk_clone(name
);
542 this->version
= chunk_clone(version
);
545 METHOD(imv_os_state_t
, get_info
, char*,
546 private_imv_os_state_t
*this, os_type_t
*type
, chunk_t
*name
,
559 *version
= this->version
;
564 METHOD(imv_os_state_t
, set_count
, void,
565 private_imv_os_state_t
*this, int count
, int count_update
,
566 int count_blacklist
, int count_ok
)
568 this->count
+= count
;
569 this->count_update
+= count_update
;
570 this->count_blacklist
+= count_blacklist
;
571 this->count_ok
+= count_ok
;
574 METHOD(imv_os_state_t
, get_count
, void,
575 private_imv_os_state_t
*this, int *count
, int *count_update
,
576 int *count_blacklist
, int *count_ok
)
580 *count
= this->count
;
584 *count_update
= this->count_update
;
588 *count_blacklist
= this->count_blacklist
;
592 *count_ok
= this->count_ok
;
596 METHOD(imv_os_state_t
, set_device_id
, void,
597 private_imv_os_state_t
*this, chunk_t id
)
599 this->device_id
= chunk_clone(id
);
602 METHOD(imv_os_state_t
, get_device_id
, chunk_t
,
603 private_imv_os_state_t
*this)
605 return this->device_id
;
608 METHOD(imv_os_state_t
, set_os_settings
, void,
609 private_imv_os_state_t
*this, u_int settings
)
611 this->os_settings
|= settings
;
614 METHOD(imv_os_state_t
, get_os_settings
, u_int
,
615 private_imv_os_state_t
*this)
617 return this->os_settings
;
620 METHOD(imv_os_state_t
, set_angel_count
, void,
621 private_imv_os_state_t
*this, bool start
)
623 this->angel_count
+= start ?
1 : -1;
626 METHOD(imv_os_state_t
, get_angel_count
, int,
627 private_imv_os_state_t
*this)
629 return this->angel_count
;
632 METHOD(imv_os_state_t
, add_bad_package
, void,
633 private_imv_os_state_t
*this, char *package
,
634 os_package_state_t package_state
)
636 package
= strdup(package
);
638 if (package_state
== OS_PACKAGE_STATE_BLACKLIST
)
640 this->remove_packages
->insert_last(this->remove_packages
, package
);
644 this->update_packages
->insert_last(this->update_packages
, package
);
649 * Described in header.
651 imv_state_t
*imv_os_state_create(TNC_ConnectionID connection_id
)
653 private_imv_os_state_t
*this;
658 .get_connection_id
= _get_connection_id
,
659 .has_long
= _has_long
,
660 .has_excl
= _has_excl
,
661 .set_flags
= _set_flags
,
662 .set_max_msg_len
= _set_max_msg_len
,
663 .get_max_msg_len
= _get_max_msg_len
,
664 .set_action_flags
= _set_action_flags
,
665 .get_action_flags
= _get_action_flags
,
666 .set_ar_id
= _set_ar_id
,
667 .get_ar_id
= _get_ar_id
,
668 .set_session
= _set_session
,
669 .get_session
= _get_session
,
670 .change_state
= _change_state
,
671 .get_recommendation
= _get_recommendation
,
672 .set_recommendation
= _set_recommendation
,
673 .update_recommendation
= _update_recommendation
,
674 .get_reason_string
= _get_reason_string
,
675 .get_remediation_instructions
= _get_remediation_instructions
,
678 .set_handshake_state
= _set_handshake_state
,
679 .get_handshake_state
= _get_handshake_state
,
680 .set_info
= _set_info
,
681 .get_info
= _get_info
,
682 .set_count
= _set_count
,
683 .get_count
= _get_count
,
684 .set_device_id
= _set_device_id
,
685 .get_device_id
= _get_device_id
,
686 .set_os_settings
= _set_os_settings
,
687 .get_os_settings
= _get_os_settings
,
688 .set_angel_count
= _set_angel_count
,
689 .get_angel_count
= _get_angel_count
,
690 .add_bad_package
= _add_bad_package
,
692 .state
= TNC_CONNECTION_STATE_CREATE
,
693 .rec
= TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
694 .eval
= TNC_IMV_EVALUATION_RESULT_DONT_KNOW
,
695 .connection_id
= connection_id
,
696 .update_packages
= linked_list_create(),
697 .remove_packages
= linked_list_create(),
700 return &this->public.interface
;