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