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