2 * Copyright (C) 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_os_state.h"
18 #include <utils/debug.h>
19 #include <collections/linked_list.h>
21 typedef struct private_imv_os_state_t private_imv_os_state_t
;
22 typedef struct package_entry_t package_entry_t
;
23 typedef struct entry_t entry_t
;
24 typedef struct instruction_entry_t instruction_entry_t
;
27 * Private data of an imv_os_state_t object.
29 struct private_imv_os_state_t
{
32 * Public members of imv_os_state_t
34 imv_os_state_t
public;
39 TNC_ConnectionID connection_id
;
42 * TNCCS connection state
44 TNC_ConnectionState state
;
47 * Does the TNCCS connection support long message types?
52 * Does the TNCCS connection support exclusive delivery?
57 * Maximum PA-TNC message size for this TNCCS connection
59 u_int32_t max_msg_len
;
62 * IMV action recommendation
64 TNC_IMV_Action_Recommendation rec
;
67 * IMV evaluation result
69 TNC_IMV_Evaluation_Result eval
;
72 * OS Product Information (concatenation of OS Name and Version)
92 * List of vulnerable or blacklisted packages
94 linked_list_t
*bad_packages
;
97 * Local copy of the reason string
102 * Local copy of the remediation instruction string
107 * Number of processed packages
112 * Number of not updated packages
117 * Number of blacklisted packages
122 * Number of whitelisted packages
127 * OS Installed Package request sent - mandatory response expected
129 bool package_request
;
144 * Store a bad package entry
146 struct package_entry_t
{
148 os_package_state_t state
;
152 * Free a bad package entry
154 static void free_package_entry(package_entry_t
*this)
161 * Define a language string entry
169 * Table of multi-lingual improper settings reason string entries
171 static entry_t settings_reasons
[] = {
172 { "en", "Improper OS settings were detected" },
173 { "de", "Unzulässige OS Einstellungen wurden festgestellt" }
177 * Table of multi-lingual reason string entries
179 static entry_t reasons
[] = {
180 { "en", "Vulnerable or blacklisted software packages were found" },
181 { "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" }
185 * Table of multi-lingual forwarding enable string entries
187 static entry_t instruction_fwd_enabled
[] = {
188 { "en", "Please disable IP forwarding" },
189 { "de", "Bitte deaktivieren Sie das IP Forwarding" }
193 * Table of multi-lingual default password enabled string entries
195 static entry_t instruction_default_pwd_enabled
[] = {
196 { "en", "Please change the default password" },
197 { "de", "Bitte ändern Sie das default Passwort" }
201 * Table of multi-lingual defaul install non market apps string entries
203 static entry_t instruction_non_market_apps
[] = {
204 { "en", "Do not allow the installation of apps from unknown sources" },
205 { "de", "Erlauben Sie nicht die Installation von Apps von unbekannten Quellen" }
209 * Define a remediation instruction string entry
211 struct instruction_entry_t
{
214 char *removal_string
;
218 * Tables of multi-lingual remediation instruction string entries
220 static instruction_entry_t instructions
[] = {
221 { "en", "Please update the following software packages:\n",
222 "Please remove the following software packages:\n" },
223 { "de", "Bitte updaten Sie die folgenden Softwarepakete\n",
224 "Bitte entfernen Sie die folgenden Softwarepakete\n" },
225 { "pl", "Proszę zaktualizować następujące pakiety:\n",
226 "Proszę usunąć następujące pakiety:\n" }
229 METHOD(imv_state_t
, get_connection_id
, TNC_ConnectionID
,
230 private_imv_os_state_t
*this)
232 return this->connection_id
;
235 METHOD(imv_state_t
, has_long
, bool,
236 private_imv_os_state_t
*this)
238 return this->has_long
;
241 METHOD(imv_state_t
, has_excl
, bool,
242 private_imv_os_state_t
*this)
244 return this->has_excl
;
247 METHOD(imv_state_t
, set_flags
, void,
248 private_imv_os_state_t
*this, bool has_long
, bool has_excl
)
250 this->has_long
= has_long
;
251 this->has_excl
= has_excl
;
254 METHOD(imv_state_t
, set_max_msg_len
, void,
255 private_imv_os_state_t
*this, u_int32_t max_msg_len
)
257 this->max_msg_len
= max_msg_len
;
260 METHOD(imv_state_t
, get_max_msg_len
, u_int32_t
,
261 private_imv_os_state_t
*this)
263 return this->max_msg_len
;
266 METHOD(imv_state_t
, change_state
, void,
267 private_imv_os_state_t
*this, TNC_ConnectionState new_state
)
269 this->state
= new_state
;
272 METHOD(imv_state_t
, get_recommendation
, void,
273 private_imv_os_state_t
*this, TNC_IMV_Action_Recommendation
*rec
,
274 TNC_IMV_Evaluation_Result
*eval
)
280 METHOD(imv_state_t
, set_recommendation
, void,
281 private_imv_os_state_t
*this, TNC_IMV_Action_Recommendation rec
,
282 TNC_IMV_Evaluation_Result eval
)
288 METHOD(imv_state_t
, get_reason_string
, bool,
289 private_imv_os_state_t
*this, enumerator_t
*language_enumerator
,
290 char **reason_string
, char **reason_language
)
294 int i
, i_chosen
= 0, len
= 0, nr_of_reasons
= 0;
296 if (!this->count_update
&& !this->count_blacklist
& !this->os_settings
)
301 while (language_enumerator
->enumerate(language_enumerator
, &lang
))
303 for (i
= 0; i
< countof(reasons
); i
++)
305 if (streq(lang
, reasons
[i
].lang
))
317 *reason_language
= reasons
[i_chosen
].lang
;
319 if (this->count_update
|| this->count_blacklist
)
321 len
+= strlen(reasons
[i_chosen
].string
);
324 if (this->os_settings
)
326 len
+= strlen(settings_reasons
[i_chosen
].string
);
330 /* Allocate memory for the reason string */
331 pos
= this->reasons
= malloc(len
+ nr_of_reasons
);
333 if (this->count_update
|| this->count_blacklist
)
335 strcpy(pos
, reasons
[i_chosen
].string
);
336 pos
+= strlen(reasons
[i_chosen
].string
);
342 if (this->os_settings
)
344 strcpy(pos
, settings_reasons
[i_chosen
].string
);
345 pos
+= strlen(settings_reasons
[i_chosen
].string
);
348 *reason_string
= this->reasons
;
353 METHOD(imv_state_t
, get_remediation_instructions
, bool,
354 private_imv_os_state_t
*this, enumerator_t
*language_enumerator
,
355 char **string
, char **lang_code
, char **uri
)
359 enumerator_t
*enumerator
;
360 package_entry_t
*entry
;
361 int i
, i_chosen
= 0, len
= 0, nr_of_instructions
= 0;
363 if (!this->count_update
&& !this->count_blacklist
& !this->os_settings
)
368 while (language_enumerator
->enumerate(language_enumerator
, &lang
))
370 for (i
= 0; i
< countof(instructions
); i
++)
372 if (streq(lang
, instructions
[i
].lang
))
384 *lang_code
= instructions
[i_chosen
].lang
;
386 /* Compute the size of the remediation string */
387 if (this->count_update
)
389 len
+= strlen(instructions
[i_chosen
].update_string
);
391 if (this->count_blacklist
)
393 len
+= strlen(instructions
[i_chosen
].removal_string
);
395 if (this->os_settings
& OS_SETTINGS_FWD_ENABLED
)
397 len
+= strlen(instruction_fwd_enabled
[i_chosen
].string
);
398 nr_of_instructions
++;
400 if (this->os_settings
& OS_SETTINGS_DEFAULT_PWD_ENABLED
)
402 len
+= strlen(instruction_default_pwd_enabled
[i_chosen
].string
);
403 nr_of_instructions
++;
405 if (this->os_settings
& OS_SETTINGS_NON_MARKET_APPS
)
407 len
+= strlen(instruction_non_market_apps
[i_chosen
].string
);
408 nr_of_instructions
++;
411 enumerator
= this->bad_packages
->create_enumerator(this->bad_packages
);
412 while (enumerator
->enumerate(enumerator
, &entry
))
414 len
+= strlen(entry
->name
) + 1;
416 enumerator
->destroy(enumerator
);
418 /* Allocate memory for the remediation instructions */
419 pos
= this->instructions
= malloc(len
+ nr_of_instructions
+ 1);
421 /* List of blacklisted packages, if any */
422 if (this->count_blacklist
)
424 strcpy(pos
, instructions
[i_chosen
].removal_string
);
425 pos
+= strlen(instructions
[i_chosen
].removal_string
);
427 enumerator
= this->bad_packages
->create_enumerator(this->bad_packages
);
428 while (enumerator
->enumerate(enumerator
, &entry
))
430 if (entry
->state
== OS_PACKAGE_STATE_BLACKLIST
)
432 strcpy(pos
, entry
->name
);
433 pos
+= strlen(entry
->name
);
437 enumerator
->destroy(enumerator
);
440 /* List of packages in need of an update, if any */
441 if (this->count_update
)
443 strcpy(pos
, instructions
[i_chosen
].update_string
);
444 pos
+= strlen(instructions
[i_chosen
].update_string
);
446 enumerator
= this->bad_packages
->create_enumerator(this->bad_packages
);
447 while (enumerator
->enumerate(enumerator
, &entry
))
449 if (entry
->state
!= OS_PACKAGE_STATE_BLACKLIST
)
451 strcpy(pos
, entry
->name
);
452 pos
+= strlen(entry
->name
);
456 enumerator
->destroy(enumerator
);
459 /* Add instructions concerning improper OS settings */
460 if (this->os_settings
& OS_SETTINGS_FWD_ENABLED
)
462 strcpy(pos
, instruction_fwd_enabled
[i_chosen
].string
);
463 pos
+= strlen(instruction_fwd_enabled
[i_chosen
].string
);
464 if (--nr_of_instructions
)
469 if (this->os_settings
& OS_SETTINGS_DEFAULT_PWD_ENABLED
)
471 strcpy(pos
, instruction_default_pwd_enabled
[i_chosen
].string
);
472 pos
+= strlen(instruction_default_pwd_enabled
[i_chosen
].string
);
473 if (--nr_of_instructions
)
478 if (this->os_settings
& OS_SETTINGS_NON_MARKET_APPS
)
480 strcpy(pos
, instruction_non_market_apps
[i_chosen
].string
);
481 pos
+= strlen(instruction_non_market_apps
[i_chosen
].string
);
485 *string
= this->instructions
;
486 *uri
= lib
->settings
->get_str(lib
->settings
,
487 "libimcv.plugins.imv-os.remediation_uri", NULL
);
492 METHOD(imv_state_t
, destroy
, void,
493 private_imv_os_state_t
*this)
495 this->bad_packages
->destroy_function(this->bad_packages
,
496 (void*)free_package_entry
);
498 free(this->instructions
);
500 free(this->name
.ptr
);
501 free(this->version
.ptr
);
505 METHOD(imv_os_state_t
, set_info
, void,
506 private_imv_os_state_t
*this, os_type_t type
, chunk_t name
, chunk_t version
)
508 int len
= name
.len
+ 1 + version
.len
+ 1;
510 /* OS info is a concatenation of OS name and OS version */
512 this->info
= malloc(len
);
513 snprintf(this->info
, len
, "%.*s %.*s", name
.len
, name
.ptr
,
514 version
.len
, version
.ptr
);
516 this->name
= chunk_clone(name
);
517 this->version
= chunk_clone(version
);
520 METHOD(imv_os_state_t
, get_info
, char*,
521 private_imv_os_state_t
*this, os_type_t
*type
, chunk_t
*name
,
534 *version
= this->version
;
539 METHOD(imv_os_state_t
, set_count
, void,
540 private_imv_os_state_t
*this, int count
, int count_update
,
541 int count_blacklist
, int count_ok
)
543 this->count
+= count
;
544 this->count_update
+= count_update
;
545 this->count_blacklist
+= count_blacklist
;
546 this->count_ok
+= count_ok
;
549 METHOD(imv_os_state_t
, get_count
, void,
550 private_imv_os_state_t
*this, int *count
, int *count_update
,
551 int *count_blacklist
, int *count_ok
)
555 *count
= this->count
;
559 *count_update
= this->count_update
;
563 *count_blacklist
= this->count_blacklist
;
567 *count_ok
= this->count_ok
;
571 METHOD(imv_os_state_t
, set_package_request
, void,
572 private_imv_os_state_t
*this, bool set
)
574 this->package_request
= set
;
577 METHOD(imv_os_state_t
, get_package_request
, bool,
578 private_imv_os_state_t
*this)
580 return this->package_request
;
583 METHOD(imv_os_state_t
, set_os_settings
, void,
584 private_imv_os_state_t
*this, u_int settings
)
586 this->os_settings
|= settings
;
589 METHOD(imv_os_state_t
, get_os_settings
, u_int
,
590 private_imv_os_state_t
*this)
592 return this->os_settings
;
595 METHOD(imv_os_state_t
, set_angel_count
, void,
596 private_imv_os_state_t
*this, bool start
)
598 this->angel_count
+= start ?
1 : -1;
601 METHOD(imv_os_state_t
, get_angel_count
, int,
602 private_imv_os_state_t
*this)
604 return this->angel_count
;
607 METHOD(imv_os_state_t
, add_bad_package
, void,
608 private_imv_os_state_t
*this, char *package
,
609 os_package_state_t package_state
)
611 package_entry_t
*entry
;
613 entry
= malloc_thing(package_entry_t
);
614 entry
->name
= strdup(package
);
615 entry
->state
= package_state
;
616 this->bad_packages
->insert_last(this->bad_packages
, entry
);
620 * Described in header.
622 imv_state_t
*imv_os_state_create(TNC_ConnectionID connection_id
)
624 private_imv_os_state_t
*this;
629 .get_connection_id
= _get_connection_id
,
630 .has_long
= _has_long
,
631 .has_excl
= _has_excl
,
632 .set_flags
= _set_flags
,
633 .set_max_msg_len
= _set_max_msg_len
,
634 .get_max_msg_len
= _get_max_msg_len
,
635 .change_state
= _change_state
,
636 .get_recommendation
= _get_recommendation
,
637 .set_recommendation
= _set_recommendation
,
638 .get_reason_string
= _get_reason_string
,
639 .get_remediation_instructions
= _get_remediation_instructions
,
642 .set_info
= _set_info
,
643 .get_info
= _get_info
,
644 .set_count
= _set_count
,
645 .get_count
= _get_count
,
646 .set_package_request
= _set_package_request
,
647 .get_package_request
= _get_package_request
,
648 .set_os_settings
= _set_os_settings
,
649 .get_os_settings
= _get_os_settings
,
650 .set_angel_count
= _set_angel_count
,
651 .get_angel_count
= _get_angel_count
,
652 .add_bad_package
= _add_bad_package
,
654 .state
= TNC_CONNECTION_STATE_CREATE
,
655 .rec
= TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
656 .eval
= TNC_IMV_EVALUATION_RESULT_DONT_KNOW
,
657 .connection_id
= connection_id
,
658 .bad_packages
= linked_list_create(),
661 return &this->public.interface
;