24f803d47225d6040404a8becb1550a4020d8f4f
[strongswan.git] / src / libimcv / plugins / imv_os / imv_os_state.c
1 /*
2 * Copyright (C) 2012-2014 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 #include "imv/imv_os_info.h"
22
23 #include <tncif_policy.h>
24
25 #include <utils/debug.h>
26 #include <collections/linked_list.h>
27
28 typedef struct private_imv_os_state_t private_imv_os_state_t;
29 typedef struct package_entry_t package_entry_t;
30 typedef struct entry_t entry_t;
31 typedef struct instruction_entry_t instruction_entry_t;
32
33 /**
34 * Private data of an imv_os_state_t object.
35 */
36 struct private_imv_os_state_t {
37
38 /**
39 * Public members of imv_os_state_t
40 */
41 imv_os_state_t public;
42
43 /**
44 * TNCCS connection ID
45 */
46 TNC_ConnectionID connection_id;
47
48 /**
49 * TNCCS connection state
50 */
51 TNC_ConnectionState state;
52
53 /**
54 * Does the TNCCS connection support long message types?
55 */
56 bool has_long;
57
58 /**
59 * Does the TNCCS connection support exclusive delivery?
60 */
61 bool has_excl;
62
63 /**
64 * Maximum PA-TNC message size for this TNCCS connection
65 */
66 uint32_t max_msg_len;
67
68 /**
69 * Flags set for completed actions
70 */
71 uint32_t action_flags;
72
73 /**
74 * IMV database session associated with TNCCS connection
75 */
76 imv_session_t *session;
77
78 /**
79 * PA-TNC attribute segmentation contracts associated with TNCCS connection
80 */
81 seg_contract_manager_t *contracts;
82
83 /**
84 * IMV action recommendation
85 */
86 TNC_IMV_Action_Recommendation rec;
87
88 /**
89 * IMV evaluation result
90 */
91 TNC_IMV_Evaluation_Result eval;
92
93 /**
94 * IMV OS handshake state
95 */
96 imv_os_handshake_state_t handshake_state;
97
98 /**
99 * List of blacklisted packages to be removed
100 */
101 linked_list_t *remove_packages;
102
103 /**
104 h* List of vulnerable packages to be updated
105 */
106 linked_list_t *update_packages;
107
108 /**
109 * TNC Reason String
110 */
111 imv_reason_string_t *reason_string;
112
113 /**
114 * IETF Remediation Instructions String
115 */
116 imv_remediation_string_t *remediation_string;
117
118 /**
119 * Number of processed packages
120 */
121 int count;
122
123 /**
124 * Number of not updated packages
125 */
126 int count_update;
127
128 /**
129 * Number of blacklisted packages
130 */
131 int count_blacklist;
132
133 /**
134 * Number of whitelisted packages
135 */
136 int count_ok;
137
138 /**
139 * OS Settings
140 */
141 u_int os_settings;
142
143 /**
144 * Angel count
145 */
146 int angel_count;
147
148 };
149
150 /**
151 * Supported languages
152 */
153 static char* languages[] = { "en", "de", "pl" };
154
155 /**
156 * Reason strings for "OS settings"
157 */
158 static imv_lang_string_t reason_settings[] = {
159 { "en", "Improper OS settings were detected" },
160 { "de", "Unzulässige OS Einstellungen wurden festgestellt" },
161 { "pl", "Stwierdzono niewłaściwe ustawienia OS" },
162 { NULL, NULL }
163 };
164
165 /**
166 * Reason strings for "installed software packages"
167 */
168 static imv_lang_string_t reason_packages[] = {
169 { "en", "Vulnerable or blacklisted software packages were found" },
170 { "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" },
171 { "pl", "Znaleziono pakiety podatne na atak lub będące na czarnej liście" },
172 { NULL, NULL }
173 };
174
175 /**
176 * Instruction strings for "Software Security Updates"
177 */
178 static imv_lang_string_t instr_update_packages_title[] = {
179 { "en", "Software Security Updates" },
180 { "de", "Software Sicherheitsupdates" },
181 { "pl", "Aktualizacja softwaru zabezpieczającego" },
182 { NULL, NULL }
183 };
184
185 static imv_lang_string_t instr_update_packages_descr[] = {
186 { "en", "Packages with security vulnerabilities were found" },
187 { "de", "Softwarepakete mit Sicherheitsschwachstellen wurden gefunden" },
188 { "pl", "Znaleziono pakiety podatne na atak" },
189 { NULL, NULL }
190 };
191
192 static imv_lang_string_t instr_update_packages_header[] = {
193 { "en", "Please update the following software packages:" },
194 { "de", "Bitte updaten Sie die folgenden Softwarepakete:" },
195 { "pl", "Proszę zaktualizować następujące pakiety:" },
196 { NULL, NULL }
197 };
198
199 /**
200 * Instruction strings for "Blacklisted Software Packages"
201 */
202 static imv_lang_string_t instr_remove_packages_title[] = {
203 { "en", "Blacklisted Software Packages" },
204 { "de", "Gesperrte Softwarepakete" },
205 { "pl", "Pakiety będące na czarnej liście" },
206 { NULL, NULL }
207 };
208
209 static imv_lang_string_t instr_remove_packages_descr[] = {
210 { "en", "Dangerous software packages were found" },
211 { "de", "Gefährliche Softwarepakete wurden gefunden" },
212 { "pl", "Znaleziono niebezpieczne pakiety" },
213 { NULL, NULL }
214 };
215
216 static imv_lang_string_t instr_remove_packages_header[] = {
217 { "en", "Please remove the following software packages:" },
218 { "de", "Bitte entfernen Sie die folgenden Softwarepakete:" },
219 { "pl", "Proszę usunąć następujące pakiety:" },
220 { NULL, NULL }
221 };
222
223 ;/**
224 * Instruction strings for "Forwarding Enabled"
225 */
226 static imv_lang_string_t instr_fwd_enabled_title[] = {
227 { "en", "IP Packet Forwarding" },
228 { "de", "Weiterleitung von IP Paketen" },
229 { "pl", "Przekazywanie pakietów IP" },
230 { NULL, NULL }
231 };
232
233 static imv_lang_string_t instr_fwd_enabled_descr[] = {
234 { "en", "Please disable the forwarding of IP packets" },
235 { "de", "Bitte deaktivieren Sie das Forwarding von IP Paketen" },
236 { "pl", "Proszę zdezaktywować przekazywanie pakietów IP" },
237 { NULL, NULL }
238 };
239
240 /**
241 * Instruction strings for "Default Password Enabled"
242 */
243 static imv_lang_string_t instr_default_pwd_enabled_title[] = {
244 { "en", "Default Password" },
245 { "de", "Default Passwort" },
246 { "pl", "Hasło domyślne" },
247 { NULL, NULL }
248 };
249
250 static imv_lang_string_t instr_default_pwd_enabled_descr[] = {
251 { "en", "Please change the default password" },
252 { "de", "Bitte ändern Sie das Default Passwort" },
253 { "pl", "Proszę zmienić domyślne hasło" },
254 { NULL, NULL }
255 };
256
257 /**
258 * Instruction strings for "Unknown Source"
259 */
260 static imv_lang_string_t instr_unknown_source_title[] = {
261 { "en", "Unknown Software Origin" },
262 { "de", "Unbekannte Softwareherkunft" },
263 { "pl", "Nieznane pochodzenie softwaru" },
264 { NULL, NULL }
265 };
266
267 static imv_lang_string_t instr_unknown_source_descr[] = {
268 { "en", "Do not allow the installation of apps from unknown sources" },
269 { "de", "Erlauben Sie nicht die Installation von Apps aus unbekannten Quellen" },
270 { "pl", "Proszę nie dopuszczać do instalacji Apps z nieznanych źródeł" },
271 { NULL, NULL }
272 };
273
274 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
275 private_imv_os_state_t *this)
276 {
277 return this->connection_id;
278 }
279
280 METHOD(imv_state_t, has_long, bool,
281 private_imv_os_state_t *this)
282 {
283 return this->has_long;
284 }
285
286 METHOD(imv_state_t, has_excl, bool,
287 private_imv_os_state_t *this)
288 {
289 return this->has_excl;
290 }
291
292 METHOD(imv_state_t, set_flags, void,
293 private_imv_os_state_t *this, bool has_long, bool has_excl)
294 {
295 this->has_long = has_long;
296 this->has_excl = has_excl;
297 }
298
299 METHOD(imv_state_t, set_max_msg_len, void,
300 private_imv_os_state_t *this, uint32_t max_msg_len)
301 {
302 this->max_msg_len = max_msg_len;
303 }
304
305 METHOD(imv_state_t, get_max_msg_len, uint32_t,
306 private_imv_os_state_t *this)
307 {
308 return this->max_msg_len;
309 }
310
311 METHOD(imv_state_t, set_action_flags, void,
312 private_imv_os_state_t *this, uint32_t flags)
313 {
314 this->action_flags |= flags;
315 }
316
317 METHOD(imv_state_t, get_action_flags, uint32_t,
318 private_imv_os_state_t *this)
319 {
320 return this->action_flags;
321 }
322
323 METHOD(imv_state_t, set_session, void,
324 private_imv_os_state_t *this, imv_session_t *session)
325 {
326 this->session = session;
327 }
328
329 METHOD(imv_state_t, get_session, imv_session_t*,
330 private_imv_os_state_t *this)
331 {
332 return this->session;
333 }
334
335 METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
336 private_imv_os_state_t *this)
337 {
338 return this->contracts;
339 }
340
341 METHOD(imv_state_t, get_recommendation, void,
342 private_imv_os_state_t *this, TNC_IMV_Action_Recommendation *rec,
343 TNC_IMV_Evaluation_Result *eval)
344 {
345 *rec = this->rec;
346 *eval = this->eval;
347 }
348
349 METHOD(imv_state_t, set_recommendation, void,
350 private_imv_os_state_t *this, TNC_IMV_Action_Recommendation rec,
351 TNC_IMV_Evaluation_Result eval)
352 {
353 this->rec = rec;
354 this->eval = eval;
355 }
356
357 METHOD(imv_state_t, update_recommendation, void,
358 private_imv_os_state_t *this, TNC_IMV_Action_Recommendation rec,
359 TNC_IMV_Evaluation_Result eval)
360 {
361 this->rec = tncif_policy_update_recommendation(this->rec, rec);
362 this->eval = tncif_policy_update_evaluation(this->eval, eval);
363 }
364
365 METHOD(imv_state_t, change_state, void,
366 private_imv_os_state_t *this, TNC_ConnectionState new_state)
367 {
368 this->state = new_state;
369 }
370
371 METHOD(imv_state_t, get_reason_string, bool,
372 private_imv_os_state_t *this, enumerator_t *language_enumerator,
373 chunk_t *reason_string, char **reason_language)
374 {
375 if (!this->count_update && !this->count_blacklist & !this->os_settings)
376 {
377 return FALSE;
378 }
379 *reason_language = imv_lang_string_select_lang(language_enumerator,
380 languages, countof(languages));
381
382 /* Instantiate a TNC Reason String object */
383 DESTROY_IF(this->reason_string);
384 this->reason_string = imv_reason_string_create(*reason_language, "\n");
385
386 if (this->count_update || this->count_blacklist)
387 {
388 this->reason_string->add_reason(this->reason_string, reason_packages);
389 }
390 if (this->os_settings)
391 {
392 this->reason_string->add_reason(this->reason_string, reason_settings);
393 }
394 *reason_string = this->reason_string->get_encoding(this->reason_string);
395
396 return TRUE;
397 }
398
399 METHOD(imv_state_t, get_remediation_instructions, bool,
400 private_imv_os_state_t *this, enumerator_t *language_enumerator,
401 chunk_t *string, char **lang_code, char **uri)
402 {
403 imv_os_info_t *os_info;
404 bool as_xml = FALSE;
405
406 if (!this->count_update && !this->count_blacklist & !this->os_settings)
407 {
408 return FALSE;
409 }
410 *lang_code = imv_lang_string_select_lang(language_enumerator,
411 languages, countof(languages));
412
413 /* Instantiate an IETF Remediation Instructions String object */
414 DESTROY_IF(this->remediation_string);
415 if (this->session)
416 {
417 os_info = this->session->get_os_info(this->session);
418 as_xml = os_info->get_type(os_info) == OS_TYPE_ANDROID;
419 }
420 this->remediation_string = imv_remediation_string_create(as_xml, *lang_code);
421
422 /* List of blacklisted packages to be removed, if any */
423 if (this->count_blacklist)
424 {
425 this->remediation_string->add_instruction(this->remediation_string,
426 instr_remove_packages_title,
427 instr_remove_packages_descr,
428 instr_remove_packages_header,
429 this->remove_packages);
430 }
431
432 /* List of packages in need of an update, if any */
433 if (this->count_update)
434 {
435 this->remediation_string->add_instruction(this->remediation_string,
436 instr_update_packages_title,
437 instr_update_packages_descr,
438 instr_update_packages_header,
439 this->update_packages);
440 }
441
442 /* Add instructions concerning improper OS settings */
443 if (this->os_settings & OS_SETTINGS_FWD_ENABLED)
444 {
445 this->remediation_string->add_instruction(this->remediation_string,
446 instr_fwd_enabled_title,
447 instr_fwd_enabled_descr, NULL, NULL);
448 }
449 if (this->os_settings & OS_SETTINGS_DEFAULT_PWD_ENABLED)
450 {
451 this->remediation_string->add_instruction(this->remediation_string,
452 instr_default_pwd_enabled_title,
453 instr_default_pwd_enabled_descr, NULL, NULL);
454 }
455 if (this->os_settings & OS_SETTINGS_UNKNOWN_SOURCE)
456 {
457 this->remediation_string->add_instruction(this->remediation_string,
458 instr_unknown_source_title,
459 instr_unknown_source_descr, NULL, NULL);
460 }
461
462 *string = this->remediation_string->get_encoding(this->remediation_string);
463 *uri = lib->settings->get_str(lib->settings,
464 "%s.plugins.imv-os.remediation_uri", NULL, lib->ns);
465
466 return TRUE;
467 }
468
469 METHOD(imv_state_t, destroy, void,
470 private_imv_os_state_t *this)
471 {
472 DESTROY_IF(this->session);
473 DESTROY_IF(this->reason_string);
474 DESTROY_IF(this->remediation_string);
475 this->contracts->destroy(this->contracts);
476 this->update_packages->destroy_function(this->update_packages, free);
477 this->remove_packages->destroy_function(this->remove_packages, free);
478 free(this);
479 }
480
481 METHOD(imv_os_state_t, set_handshake_state, void,
482 private_imv_os_state_t *this, imv_os_handshake_state_t new_state)
483 {
484 this->handshake_state = new_state;
485 }
486
487 METHOD(imv_os_state_t, get_handshake_state, imv_os_handshake_state_t,
488 private_imv_os_state_t *this)
489 {
490 return this->handshake_state;
491 }
492
493
494 METHOD(imv_os_state_t, set_count, void,
495 private_imv_os_state_t *this, int count, int count_update,
496 int count_blacklist, int count_ok)
497 {
498 this->count += count;
499 this->count_update += count_update;
500 this->count_blacklist += count_blacklist;
501 this->count_ok += count_ok;
502 }
503
504 METHOD(imv_os_state_t, get_count, void,
505 private_imv_os_state_t *this, int *count, int *count_update,
506 int *count_blacklist, int *count_ok)
507 {
508 if (count)
509 {
510 *count = this->count;
511 }
512 if (count_update)
513 {
514 *count_update = this->count_update;
515 }
516 if (count_blacklist)
517 {
518 *count_blacklist = this->count_blacklist;
519 }
520 if (count_ok)
521 {
522 *count_ok = this->count_ok;
523 }
524 }
525
526 METHOD(imv_os_state_t, set_os_settings, void,
527 private_imv_os_state_t *this, u_int settings)
528 {
529 this->os_settings |= settings;
530 }
531
532 METHOD(imv_os_state_t, get_os_settings, u_int,
533 private_imv_os_state_t *this)
534 {
535 return this->os_settings;
536 }
537
538 METHOD(imv_os_state_t, set_angel_count, void,
539 private_imv_os_state_t *this, bool start)
540 {
541 this->angel_count += start ? 1 : -1;
542 }
543
544 METHOD(imv_os_state_t, get_angel_count, int,
545 private_imv_os_state_t *this)
546 {
547 return this->angel_count;
548 }
549
550 METHOD(imv_os_state_t, add_bad_package, void,
551 private_imv_os_state_t *this, char *package,
552 os_package_state_t package_state)
553 {
554 package = strdup(package);
555
556 if (package_state == OS_PACKAGE_STATE_BLACKLIST)
557 {
558 this->remove_packages->insert_last(this->remove_packages, package);
559 }
560 else
561 {
562 this->update_packages->insert_last(this->update_packages, package);
563 }
564 }
565
566 /**
567 * Described in header.
568 */
569 imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
570 {
571 private_imv_os_state_t *this;
572
573 INIT(this,
574 .public = {
575 .interface = {
576 .get_connection_id = _get_connection_id,
577 .has_long = _has_long,
578 .has_excl = _has_excl,
579 .set_flags = _set_flags,
580 .set_max_msg_len = _set_max_msg_len,
581 .get_max_msg_len = _get_max_msg_len,
582 .set_action_flags = _set_action_flags,
583 .get_action_flags = _get_action_flags,
584 .set_session = _set_session,
585 .get_session = _get_session,
586 .get_contracts = _get_contracts,
587 .change_state = _change_state,
588 .get_recommendation = _get_recommendation,
589 .set_recommendation = _set_recommendation,
590 .update_recommendation = _update_recommendation,
591 .get_reason_string = _get_reason_string,
592 .get_remediation_instructions = _get_remediation_instructions,
593 .destroy = _destroy,
594 },
595 .set_handshake_state = _set_handshake_state,
596 .get_handshake_state = _get_handshake_state,
597 .set_count = _set_count,
598 .get_count = _get_count,
599 .set_os_settings = _set_os_settings,
600 .get_os_settings = _get_os_settings,
601 .set_angel_count = _set_angel_count,
602 .get_angel_count = _get_angel_count,
603 .add_bad_package = _add_bad_package,
604 },
605 .state = TNC_CONNECTION_STATE_CREATE,
606 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
607 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
608 .connection_id = connection_id,
609 .contracts = seg_contract_manager_create(),
610 .update_packages = linked_list_create(),
611 .remove_packages = linked_list_create(),
612 );
613
614 return &this->public.interface;
615 }
616
617