Added reason string support to HCD IMV
[strongswan.git] / src / libimcv / plugins / imv_hcd / imv_hcd_state.c
1 /*
2 * Copyright (C) 2015 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_hcd_state.h"
17 #include "imv/imv_lang_string.h"
18 #include "imv/imv_reason_string.h"
19
20 #include <tncif_policy.h>
21
22 #include <utils/debug.h>
23
24 typedef struct private_imv_hcd_state_t private_imv_hcd_state_t;
25 typedef struct subtype_action_flags_t subtype_action_flags_t;
26
27 struct subtype_action_flags_t {
28 pa_subtype_pwg_t subtype;
29 uint32_t action_flags;
30 };
31
32 /**
33 * Private data of an imv_hcd_state_t object.
34 */
35 struct private_imv_hcd_state_t {
36
37 /**
38 * Public members of imv_hcd_state_t
39 */
40 imv_hcd_state_t public;
41
42 /**
43 * TNCCS connection ID
44 */
45 TNC_ConnectionID connection_id;
46
47 /**
48 * TNCCS connection state
49 */
50 TNC_ConnectionState state;
51
52 /**
53 * Does the TNCCS connection support long message types?
54 */
55 bool has_long;
56
57 /**
58 * Does the TNCCS connection support exclusive delivery?
59 */
60 bool has_excl;
61
62 /**
63 * Maximum PA-TNC message size for this TNCCS connection
64 */
65 uint32_t max_msg_len;
66
67 /**
68 * Current flags set for completed actions
69 */
70 uint32_t *action_flags;
71
72 /**
73 * Action flags for all PA subtypes
74 */
75 subtype_action_flags_t subtype_action_flags[6];
76
77 /**
78 * IMV database session associated with TNCCS connection
79 */
80 imv_session_t *session;
81
82 /**
83 * PA-TNC attribute segmentation contracts associated with TNCCS connection
84 */
85 seg_contract_manager_t *contracts;
86
87 /**
88 * IMV action recommendation
89 */
90 TNC_IMV_Action_Recommendation rec;
91
92 /**
93 * IMV evaluation result
94 */
95 TNC_IMV_Evaluation_Result eval;
96
97 /**
98 * IMV OS handshake state
99 */
100 imv_hcd_handshake_state_t handshake_state;
101
102 /**
103 * TNC Reason String
104 */
105 imv_reason_string_t *reason_string;
106
107 };
108
109 /**
110 * Supported languages
111 */
112 static char* languages[] = { "en", "de", "fr", "pl" };
113
114 /**
115 * Reason strings for "Port Filter"
116 */
117 static imv_lang_string_t reasons[] = {
118 { "en", "Mandatory HCD attributes are missing" },
119 { "de", "Obligatorische HCD Attribute fehlen" },
120 { "fr", "Il manque des attributes HCD obligatoires" },
121 { "pl", "Brakuje atrybutów obowiązkowych" },
122 { NULL, NULL }
123 };
124
125 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
126 private_imv_hcd_state_t *this)
127 {
128 return this->connection_id;
129 }
130
131 METHOD(imv_state_t, has_long, bool,
132 private_imv_hcd_state_t *this)
133 {
134 return this->has_long;
135 }
136
137 METHOD(imv_state_t, has_excl, bool,
138 private_imv_hcd_state_t *this)
139 {
140 return this->has_excl;
141 }
142
143 METHOD(imv_state_t, set_flags, void,
144 private_imv_hcd_state_t *this, bool has_long, bool has_excl)
145 {
146 this->has_long = has_long;
147 this->has_excl = has_excl;
148 }
149
150 METHOD(imv_state_t, set_max_msg_len, void,
151 private_imv_hcd_state_t *this, uint32_t max_msg_len)
152 {
153 this->max_msg_len = max_msg_len;
154 }
155
156 METHOD(imv_state_t, get_max_msg_len, uint32_t,
157 private_imv_hcd_state_t *this)
158 {
159 return this->max_msg_len;
160 }
161
162 METHOD(imv_state_t, set_action_flags, void,
163 private_imv_hcd_state_t *this, uint32_t flags)
164 {
165 *this->action_flags |= flags;
166 }
167
168 METHOD(imv_state_t, get_action_flags, uint32_t,
169 private_imv_hcd_state_t *this)
170 {
171 return *this->action_flags;
172 }
173
174 METHOD(imv_state_t, set_session, void,
175 private_imv_hcd_state_t *this, imv_session_t *session)
176 {
177 this->session = session;
178 }
179
180 METHOD(imv_state_t, get_session, imv_session_t*,
181 private_imv_hcd_state_t *this)
182 {
183 return this->session;
184 }
185
186 METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
187 private_imv_hcd_state_t *this)
188 {
189 return this->contracts;
190 }
191
192 METHOD(imv_state_t, get_recommendation, void,
193 private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation *rec,
194 TNC_IMV_Evaluation_Result *eval)
195 {
196 *rec = this->rec;
197 *eval = this->eval;
198 }
199
200 METHOD(imv_state_t, set_recommendation, void,
201 private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation rec,
202 TNC_IMV_Evaluation_Result eval)
203 {
204 this->rec = rec;
205 this->eval = eval;
206 }
207
208 METHOD(imv_state_t, update_recommendation, void,
209 private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation rec,
210 TNC_IMV_Evaluation_Result eval)
211 {
212 this->rec = tncif_policy_update_recommendation(this->rec, rec);
213 this->eval = tncif_policy_update_evaluation(this->eval, eval);
214 }
215
216 METHOD(imv_state_t, change_state, void,
217 private_imv_hcd_state_t *this, TNC_ConnectionState new_state)
218 {
219 this->state = new_state;
220 }
221
222 METHOD(imv_state_t, get_reason_string, bool,
223 private_imv_hcd_state_t *this, enumerator_t *language_enumerator,
224 chunk_t *reason_string, char **reason_language)
225 {
226 if (this->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
227 {
228 return FALSE;
229 }
230 *reason_language = imv_lang_string_select_lang(language_enumerator,
231 languages, countof(languages));
232
233 /* Instantiate a TNC Reason String object */
234 DESTROY_IF(this->reason_string);
235 this->reason_string = imv_reason_string_create(*reason_language, "\n");
236 this->reason_string->add_reason(this->reason_string, reasons);
237 *reason_string = this->reason_string->get_encoding(this->reason_string);
238
239 return TRUE;
240 }
241
242 METHOD(imv_state_t, get_remediation_instructions, bool,
243 private_imv_hcd_state_t *this, enumerator_t *language_enumerator,
244 chunk_t *string, char **lang_code, char **uri)
245 {
246 return FALSE;
247 }
248
249 METHOD(imv_state_t, destroy, void,
250 private_imv_hcd_state_t *this)
251 {
252 DESTROY_IF(this->session);
253 DESTROY_IF(this->reason_string);
254 this->contracts->destroy(this->contracts);
255 free(this);
256 }
257
258 METHOD(imv_hcd_state_t, set_handshake_state, void,
259 private_imv_hcd_state_t *this, imv_hcd_handshake_state_t new_state)
260 {
261 this->handshake_state = new_state;
262 }
263
264 METHOD(imv_hcd_state_t, get_handshake_state, imv_hcd_handshake_state_t,
265 private_imv_hcd_state_t *this)
266 {
267 return this->handshake_state;
268 }
269
270 METHOD(imv_hcd_state_t, set_subtype, void,
271 private_imv_hcd_state_t *this, pa_subtype_pwg_t subtype)
272 {
273 int i;
274
275 for (i = 0; i < countof(this->subtype_action_flags); i++)
276 {
277 if (subtype == this->subtype_action_flags[i].subtype)
278 {
279 this->action_flags = &this->subtype_action_flags[i].action_flags;
280 break;
281 }
282 }
283 }
284
285 METHOD(imv_hcd_state_t, set_user_app_disabled, void,
286 private_imv_hcd_state_t *this)
287 {
288 int i;
289
290 for (i = 0; i < countof(this->subtype_action_flags); i++)
291 {
292 this->subtype_action_flags[i].action_flags |= IMV_HCD_ATTR_USER_APP_NAME;
293 }
294 }
295
296 /**
297 * Described in header.
298 */
299 imv_state_t *imv_hcd_state_create(TNC_ConnectionID connection_id)
300 {
301 private_imv_hcd_state_t *this;
302
303 INIT(this,
304 .public = {
305 .interface = {
306 .get_connection_id = _get_connection_id,
307 .has_long = _has_long,
308 .has_excl = _has_excl,
309 .set_flags = _set_flags,
310 .set_max_msg_len = _set_max_msg_len,
311 .get_max_msg_len = _get_max_msg_len,
312 .set_action_flags = _set_action_flags,
313 .get_action_flags = _get_action_flags,
314 .set_session = _set_session,
315 .get_session = _get_session,
316 .get_contracts = _get_contracts,
317 .change_state = _change_state,
318 .get_recommendation = _get_recommendation,
319 .set_recommendation = _set_recommendation,
320 .update_recommendation = _update_recommendation,
321 .get_reason_string = _get_reason_string,
322 .get_remediation_instructions = _get_remediation_instructions,
323 .destroy = _destroy,
324 },
325 .set_handshake_state = _set_handshake_state,
326 .get_handshake_state = _get_handshake_state,
327 .set_subtype = _set_subtype,
328 .set_user_app_disabled = _set_user_app_disabled,
329 },
330 .state = TNC_CONNECTION_STATE_CREATE,
331 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
332 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
333 .connection_id = connection_id,
334 .contracts = seg_contract_manager_create(),
335 .subtype_action_flags = {
336 { PA_SUBTYPE_PWG_HCD_SYSTEM, IMV_HCD_ATTR_NONE },
337 { PA_SUBTYPE_PWG_HCD_CONSOLE, IMV_HCD_ATTR_SYSTEM_ONLY },
338 { PA_SUBTYPE_PWG_HCD_MARKER, IMV_HCD_ATTR_SYSTEM_ONLY },
339 { PA_SUBTYPE_PWG_HCD_FINISHER, IMV_HCD_ATTR_SYSTEM_ONLY },
340 { PA_SUBTYPE_PWG_HCD_INTERFACE, IMV_HCD_ATTR_SYSTEM_ONLY },
341 { PA_SUBTYPE_PWG_HCD_SCANNER, IMV_HCD_ATTR_SYSTEM_ONLY },
342 }
343 );
344
345 this->action_flags = &this->subtype_action_flags[0].action_flags;
346
347 return &this->public.interface;
348 }
349
350