imv_list consists of linked imv_t instances
[strongswan.git] / src / libcharon / plugins / tnc_imv / tnc_imv_recommendations.c
1 /*
2 * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include <debug.h>
16 #include <daemon.h>
17 #include <threading/mutex.h>
18 #include <tnc/tncifimv_names.h>
19 #include <tnc/imv/imv.h>
20 #include <tnc/imv/imv_recommendations.h>
21
22 typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
23 typedef struct recommendation_entry_t recommendation_entry_t;
24
25 /**
26 * Recommendation entry
27 */
28 struct recommendation_entry_t {
29
30 /**
31 * IMV ID
32 */
33 TNC_IMVID id;
34
35 /**
36 * Action Recommendation provided by IMV instance
37 */
38 TNC_IMV_Action_Recommendation rec;
39
40 /**
41 * Evaluation Result provided by IMV instance
42 */
43 TNC_IMV_Evaluation_Result eval;
44 };
45
46 /**
47 * Private data of a recommendations_t object.
48 */
49 struct private_tnc_imv_recommendations_t {
50
51 /**
52 * Public members of recommendations_t.
53 */
54 recommendations_t public;
55
56 /**
57 * list of recommendations and evaluations provided by IMVs
58 */
59 linked_list_t *recs;
60 };
61
62 METHOD(recommendations_t, provide_recommendation, TNC_Result,
63 private_tnc_imv_recommendations_t* this, TNC_IMVID id,
64 TNC_IMV_Action_Recommendation rec,
65 TNC_IMV_Evaluation_Result eval)
66 {
67 enumerator_t *enumerator;
68 recommendation_entry_t *entry;
69 bool found = FALSE;
70
71 DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'",
72 id, action_recommendation_names, rec, evaluation_result_names, eval);
73
74 enumerator = this->recs->create_enumerator(this->recs);
75 while (enumerator->enumerate(enumerator, &entry))
76 {
77 if (entry->id == id)
78 {
79 found = TRUE;
80 entry->rec = rec;
81 entry->eval = eval;
82 break;
83 }
84 }
85 enumerator->destroy(enumerator);
86 return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL;
87 }
88
89 METHOD(recommendations_t, have_recommendation, bool,
90 private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
91 TNC_IMV_Evaluation_Result *eval)
92 {
93 enumerator_t *enumerator;
94 recommendation_entry_t *entry;
95 recommendation_policy_t policy;
96 TNC_IMV_Action_Recommendation final_rec;
97 TNC_IMV_Evaluation_Result final_eval;
98 bool first = TRUE, incomplete = FALSE;
99
100 *rec = final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
101 *eval = final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
102
103 if (this->recs->get_count(this->recs) == 0)
104 {
105 DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
106 return TRUE;
107 }
108 policy = charon->imvs->get_recommendation_policy(charon->imvs);
109
110 enumerator = this->recs->create_enumerator(this->recs);
111 while (enumerator->enumerate(enumerator, &entry))
112 {
113 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION ||
114 entry->eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
115 {
116 incomplete = TRUE;
117 break;
118 }
119 if (first)
120 {
121 final_rec = entry->rec;
122 final_eval = entry->eval;
123 first = FALSE;
124 }
125 switch (policy)
126 {
127 case RECOMMENDATION_POLICY_DEFAULT:
128 /* Consolidate action recommendations */
129 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
130 {
131 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
132 }
133 else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
134 final_rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
135 {
136 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
137 }
138 else
139 {
140 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
141 }
142
143 /* Consolidate evaluation results */
144 if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
145 {
146 final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
147 }
148 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
149 final_eval != TNC_IMV_EVALUATION_RESULT_ERROR)
150 {
151 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
152 }
153 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
154 final_eval != TNC_IMV_EVALUATION_RESULT_ERROR &&
155 final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR)
156 {
157 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
158 }
159 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
160 {
161 final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
162 }
163 break;
164 case RECOMMENDATION_POLICY_ALL:
165 /* Consolidate action recommendations */
166 if (entry->rec != final_rec)
167 {
168 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
169 }
170
171 /* Consolidate evaluation results */
172 if (entry->eval != final_eval)
173 {
174 final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
175 }
176 break;
177 case RECOMMENDATION_POLICY_ANY:
178 /* Consolidate action recommendations */
179 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
180 {
181 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
182 }
183 else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
184 final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
185 {
186 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
187 }
188 else
189 {
190 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
191 }
192
193 /* Consolidate evaluation results */
194 if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
195 {
196 final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
197 }
198 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
199 final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
200 {
201 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
202 }
203 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
204 final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
205 final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
206 {
207 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
208 }
209 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
210 {
211 final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
212 }
213 }
214 }
215 enumerator->destroy(enumerator);
216
217 if (incomplete)
218 {
219 return FALSE;
220 }
221 *rec = final_rec;
222 *eval = final_eval;
223 return TRUE;
224 }
225
226
227 METHOD(recommendations_t, destroy, void,
228 private_tnc_imv_recommendations_t *this)
229 {
230 this->recs->destroy_function(this->recs, free);
231 free(this);
232 }
233
234 /**
235 * Described in header.
236 */
237 recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
238 {
239 private_tnc_imv_recommendations_t *this;
240 recommendation_entry_t *entry;
241 enumerator_t *enumerator;
242 imv_t *imv;
243
244 INIT(this,
245 .public = {
246 .provide_recommendation = _provide_recommendation,
247 .have_recommendation = _have_recommendation,
248 .destroy = _destroy,
249 },
250 .recs = linked_list_create(),
251 );
252
253 enumerator = imv_list->create_enumerator(imv_list);
254 while (enumerator->enumerate(enumerator, &imv))
255 {
256 entry = malloc_thing(recommendation_entry_t);
257 entry->id = imv->get_id(imv);
258 entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
259 entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
260 this->recs->insert_last(this->recs, entry);
261 }
262 enumerator->destroy(enumerator);
263
264 return &this->public;
265 }