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