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