4f5a4b03970fcfb85321364512ae87e462dfc1ce
[strongswan.git] / src / libimcv / plugins / imv_os / imv_os_state.c
1 /*
2 * Copyright (C) 2012-2013 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "imv_os_state.h"
17
18 #include "imv/imv_lang_string.h"
19 #include "imv/imv_reason_string.h"
20 #include "imv/imv_remediation_string.h"
21
22 #include <tncif_policy.h>
23
24 #include <utils/debug.h>
25 #include <collections/linked_list.h>
26
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;
31
32 /**
33 * Private data of an imv_os_state_t object.
34 */
35 struct private_imv_os_state_t {
36
37 /**
38 * Public members of imv_os_state_t
39 */
40 imv_os_state_t public;
41
42 /**
43 * TNCCS connection ID
44 */
45 TNC_ConnectionID connection_id;
46
47 /**
48 * TNCCS connection state
49 */
50 TNC_ConnectionState state;
51
52 /**
53 * Does the TNCCS connection support long message types?
54 */
55 bool has_long;
56
57 /**
58 * Does the TNCCS connection support exclusive delivery?
59 */
60 bool has_excl;
61
62 /**
63 * Maximum PA-TNC message size for this TNCCS connection
64 */
65 u_int32_t max_msg_len;
66
67 /**
68 * Flags set for completed actions
69 */
70 u_int32_t action_flags;
71
72 /**
73 * Access Requestor ID Type
74 */
75 u_int32_t ar_id_type;
76
77 /**
78 * Access Requestor ID Value
79 */
80 chunk_t ar_id_value;
81
82 /**
83 * IMV database session associated with TNCCS connection
84 */
85 imv_session_t *session;
86
87 /**
88 * IMV action recommendation
89 */
90 TNC_IMV_Action_Recommendation rec;
91
92 /**
93 * IMV evaluation result
94 */
95 TNC_IMV_Evaluation_Result eval;
96
97 /**
98 * IMV OS handshake state
99 */
100 imv_os_handshake_state_t handshake_state;
101
102 /**
103 * OS Product Information (concatenation of OS Name and Version)
104 */
105 char *info;
106
107 /**
108 * OS Type
109 */
110 os_type_t type;
111
112 /**
113 * OS Name
114 */
115 chunk_t name;
116
117 /**
118 * OS Version
119 */
120 chunk_t version;
121
122 /**
123 * List of blacklisted packages to be removed
124 */
125 linked_list_t *remove_packages;
126
127 /**
128 * List of vulnerable packages to be updated
129 */
130 linked_list_t *update_packages;
131
132 /**
133 * TNC Reason String
134 */
135 imv_reason_string_t *reason_string;
136
137 /**
138 * IETF Remediation Instructions String
139 */
140 imv_remediation_string_t *remediation_string;
141
142 /**
143 * Dgevice ID
144 */
145 chunk_t device_id;
146
147 /**
148 * Number of processed packages
149 */
150 int count;
151
152 /**
153 * Number of not updated packages
154 */
155 int count_update;
156
157 /**
158 * Number of blacklisted packages
159 */
160 int count_blacklist;
161
162 /**
163 * Number of whitelisted packages
164 */
165 int count_ok;
166
167 /**
168 * OS Settings
169 */
170 u_int os_settings;
171
172 /**
173 * Angel count
174 */
175 int angel_count;
176
177 };
178
179 /**
180 * Supported languages
181 */
182 static char* languages[] = { "en", "de", "pl" };
183
184 /**
185 * Reason strings for "OS settings"
186 */
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" },
191 { NULL, NULL }
192 };
193
194 /**
195 * Reason strings for "installed software packages"
196 */
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" },
201 { NULL, NULL }
202 };
203
204 /**
205 * Instruction strings for "Software Security Updates"
206 */
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" },
211 { NULL, NULL }
212 };
213
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" },
218 { NULL, NULL }
219 };
220
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:" },
225 { NULL, NULL }
226 };
227
228 /**
229 * Instruction strings for "Blacklisted Software Packages"
230 */
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" },
235 { NULL, NULL }
236 };
237
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" },
242 { NULL, NULL }
243 };
244
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:" },
249 { NULL, NULL }
250 };
251
252 ;/**
253 * Instruction strings for "Forwarding Enabled"
254 */
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" },
259 { NULL, NULL }
260 };
261
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" },
266 { NULL, NULL }
267 };
268
269 /**
270 * Instruction strings for "Default Password Enabled"
271 */
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" },
276 { NULL, NULL }
277 };
278
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" },
283 { NULL, NULL }
284 };
285
286 /**
287 * Instruction strings for "Unknown Source"
288 */
289 static imv_lang_string_t instr_unknown_source_title[] = {
290 { "en", "Unknown Software Origin" },
291 { "de", "Unbekannte Softwareherkunft" },
292 { "pl", "Nieznane pochodzenie softwaru" },
293 { NULL, NULL }
294 };
295
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ł" },
300 { NULL, NULL }
301 };
302
303 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
304 private_imv_os_state_t *this)
305 {
306 return this->connection_id;
307 }
308
309 METHOD(imv_state_t, has_long, bool,
310 private_imv_os_state_t *this)
311 {
312 return this->has_long;
313 }
314
315 METHOD(imv_state_t, has_excl, bool,
316 private_imv_os_state_t *this)
317 {
318 return this->has_excl;
319 }
320
321 METHOD(imv_state_t, set_flags, void,
322 private_imv_os_state_t *this, bool has_long, bool has_excl)
323 {
324 this->has_long = has_long;
325 this->has_excl = has_excl;
326 }
327
328 METHOD(imv_state_t, set_max_msg_len, void,
329 private_imv_os_state_t *this, u_int32_t max_msg_len)
330 {
331 this->max_msg_len = max_msg_len;
332 }
333
334 METHOD(imv_state_t, get_max_msg_len, u_int32_t,
335 private_imv_os_state_t *this)
336 {
337 return this->max_msg_len;
338 }
339
340 METHOD(imv_state_t, set_action_flags, void,
341 private_imv_os_state_t *this, u_int32_t flags)
342 {
343 this->action_flags |= flags;
344 }
345
346 METHOD(imv_state_t, get_action_flags, u_int32_t,
347 private_imv_os_state_t *this)
348 {
349 return this->action_flags;
350 }
351
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)
354 {
355 this->ar_id_type = id_type;
356 this->ar_id_value = chunk_clone(id_value);
357 }
358
359 METHOD(imv_state_t, get_ar_id, chunk_t,
360 private_imv_os_state_t *this, u_int32_t *id_type)
361 {
362 if (id_type)
363 {
364 *id_type = this->ar_id_type;
365 }
366 return this->ar_id_value;
367 }
368
369 METHOD(imv_state_t, set_session, void,
370 private_imv_os_state_t *this, imv_session_t *session)
371 {
372 this->session = session;
373 }
374
375 METHOD(imv_state_t, get_session, imv_session_t*,
376 private_imv_os_state_t *this)
377 {
378 return this->session;
379 }
380
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)
384 {
385 *rec = this->rec;
386 *eval = this->eval;
387 }
388
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)
392 {
393 this->rec = rec;
394 this->eval = eval;
395 }
396
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)
400 {
401 this->rec = tncif_policy_update_recommendation(this->rec, rec);
402 this->eval = tncif_policy_update_evaluation(this->eval, eval);
403 }
404
405 METHOD(imv_state_t, change_state, void,
406 private_imv_os_state_t *this, TNC_ConnectionState new_state)
407 {
408 this->state = new_state;
409 }
410
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)
414 {
415 if (!this->count_update && !this->count_blacklist & !this->os_settings)
416 {
417 return FALSE;
418 }
419 *reason_language = imv_lang_string_select_lang(language_enumerator,
420 languages, countof(languages));
421
422 /* Instantiate a TNC Reason String object */
423 DESTROY_IF(this->reason_string);
424 this->reason_string = imv_reason_string_create(*reason_language, "\n");
425
426 if (this->count_update || this->count_blacklist)
427 {
428 this->reason_string->add_reason(this->reason_string, reason_packages);
429 }
430 if (this->os_settings)
431 {
432 this->reason_string->add_reason(this->reason_string, reason_settings);
433 }
434 *reason_string = this->reason_string->get_encoding(this->reason_string);
435
436 return TRUE;
437 }
438
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)
442 {
443 if (!this->count_update && !this->count_blacklist & !this->os_settings)
444 {
445 return FALSE;
446 }
447 *lang_code = imv_lang_string_select_lang(language_enumerator,
448 languages, countof(languages));
449
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);
454
455 /* List of blacklisted packages to be removed, if any */
456 if (this->count_blacklist)
457 {
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);
463 }
464
465 /* List of packages in need of an update, if any */
466 if (this->count_update)
467 {
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);
473 }
474
475 /* Add instructions concerning improper OS settings */
476 if (this->os_settings & OS_SETTINGS_FWD_ENABLED)
477 {
478 this->remediation_string->add_instruction(this->remediation_string,
479 instr_fwd_enabled_title,
480 instr_fwd_enabled_descr, NULL, NULL);
481 }
482 if (this->os_settings & OS_SETTINGS_DEFAULT_PWD_ENABLED)
483 {
484 this->remediation_string->add_instruction(this->remediation_string,
485 instr_default_pwd_enabled_title,
486 instr_default_pwd_enabled_descr, NULL, NULL);
487 }
488 if (this->os_settings & OS_SETTINGS_UNKNOWN_SOURCE)
489 {
490 this->remediation_string->add_instruction(this->remediation_string,
491 instr_unknown_source_title,
492 instr_unknown_source_descr, NULL, NULL);
493 }
494
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);
498
499 return TRUE;
500 }
501
502 METHOD(imv_state_t, destroy, void,
503 private_imv_os_state_t *this)
504 {
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);
510 free(this->info);
511 free(this->name.ptr);
512 free(this->version.ptr);
513 free(this->ar_id_value.ptr);
514 free(this->device_id.ptr);
515 free(this);
516 }
517
518 METHOD(imv_os_state_t, set_handshake_state, void,
519 private_imv_os_state_t *this, imv_os_handshake_state_t new_state)
520 {
521 this->handshake_state = new_state;
522 }
523
524 METHOD(imv_os_state_t, get_handshake_state, imv_os_handshake_state_t,
525 private_imv_os_state_t *this)
526 {
527 return this->handshake_state;
528 }
529
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)
532 {
533 int len = name.len + 1 + version.len + 1;
534
535 /* OS info is a concatenation of OS name and OS version */
536 free(this->info);
537 this->info = malloc(len);
538 snprintf(this->info, len, "%.*s %.*s", (int)name.len, name.ptr,
539 (int)version.len, version.ptr);
540 this->type = type;
541 this->name = chunk_clone(name);
542 this->version = chunk_clone(version);
543 }
544
545 METHOD(imv_os_state_t, get_info, char*,
546 private_imv_os_state_t *this, os_type_t *type, chunk_t *name,
547 chunk_t *version)
548 {
549 if (type)
550 {
551 *type = this->type;
552 }
553 if (name)
554 {
555 *name = this->name;
556 }
557 if (version)
558 {
559 *version = this->version;
560 }
561 return this->info;
562 }
563
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)
567 {
568 this->count += count;
569 this->count_update += count_update;
570 this->count_blacklist += count_blacklist;
571 this->count_ok += count_ok;
572 }
573
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)
577 {
578 if (count)
579 {
580 *count = this->count;
581 }
582 if (count_update)
583 {
584 *count_update = this->count_update;
585 }
586 if (count_blacklist)
587 {
588 *count_blacklist = this->count_blacklist;
589 }
590 if (count_ok)
591 {
592 *count_ok = this->count_ok;
593 }
594 }
595
596 METHOD(imv_os_state_t, set_device_id, void,
597 private_imv_os_state_t *this, chunk_t id)
598 {
599 this->device_id = chunk_clone(id);
600 }
601
602 METHOD(imv_os_state_t, get_device_id, chunk_t,
603 private_imv_os_state_t *this)
604 {
605 return this->device_id;
606 }
607
608 METHOD(imv_os_state_t, set_os_settings, void,
609 private_imv_os_state_t *this, u_int settings)
610 {
611 this->os_settings |= settings;
612 }
613
614 METHOD(imv_os_state_t, get_os_settings, u_int,
615 private_imv_os_state_t *this)
616 {
617 return this->os_settings;
618 }
619
620 METHOD(imv_os_state_t, set_angel_count, void,
621 private_imv_os_state_t *this, bool start)
622 {
623 this->angel_count += start ? 1 : -1;
624 }
625
626 METHOD(imv_os_state_t, get_angel_count, int,
627 private_imv_os_state_t *this)
628 {
629 return this->angel_count;
630 }
631
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)
635 {
636 package = strdup(package);
637
638 if (package_state == OS_PACKAGE_STATE_BLACKLIST)
639 {
640 this->remove_packages->insert_last(this->remove_packages, package);
641 }
642 else
643 {
644 this->update_packages->insert_last(this->update_packages, package);
645 }
646 }
647
648 /**
649 * Described in header.
650 */
651 imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
652 {
653 private_imv_os_state_t *this;
654
655 INIT(this,
656 .public = {
657 .interface = {
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,
676 .destroy = _destroy,
677 },
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,
691 },
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(),
698 );
699
700 return &this->public.interface;
701 }
702
703