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