mutex.h is not needed any more
[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 <tnc/tncifimv_names.h>
18 #include <tnc/imv/imv.h>
19 #include <tnc/imv/imv_recommendations.h>
20
21 typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
22 typedef struct recommendation_entry_t recommendation_entry_t;
23
24 /**
25 * Recommendation entry
26 */
27 struct recommendation_entry_t {
28
29 /**
30 * IMV ID
31 */
32 TNC_IMVID id;
33
34 /**
35 * Action Recommendation provided by IMV instance
36 */
37 TNC_IMV_Action_Recommendation rec;
38
39 /**
40 * Evaluation Result provided by IMV instance
41 */
42 TNC_IMV_Evaluation_Result eval;
43 };
44
45 /**
46 * Private data of a recommendations_t object.
47 */
48 struct private_tnc_imv_recommendations_t {
49
50 /**
51 * Public members of recommendations_t.
52 */
53 recommendations_t public;
54
55 /**
56 * list of recommendations and evaluations provided by IMVs
57 */
58 linked_list_t *recs;
59 };
60
61 METHOD(recommendations_t, provide_recommendation, TNC_Result,
62 private_tnc_imv_recommendations_t* this, TNC_IMVID id,
63 TNC_IMV_Action_Recommendation rec,
64 TNC_IMV_Evaluation_Result eval)
65 {
66 enumerator_t *enumerator;
67 recommendation_entry_t *entry;
68 bool found = FALSE;
69
70 DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'",
71 id, action_recommendation_names, rec, evaluation_result_names, eval);
72
73 enumerator = this->recs->create_enumerator(this->recs);
74 while (enumerator->enumerate(enumerator, &entry))
75 {
76 if (entry->id == id)
77 {
78 found = TRUE;
79 entry->rec = rec;
80 entry->eval = eval;
81 break;
82 }
83 }
84 enumerator->destroy(enumerator);
85 return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL;
86 }
87
88 METHOD(recommendations_t, have_recommendation, bool,
89 private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
90 TNC_IMV_Evaluation_Result *eval)
91 {
92 enumerator_t *enumerator;
93 recommendation_entry_t *entry;
94 recommendation_policy_t policy;
95 TNC_IMV_Action_Recommendation final_rec;
96 TNC_IMV_Evaluation_Result final_eval;
97 bool first = TRUE, incomplete = FALSE;
98
99 *rec = final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
100 *eval = final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
101
102 if (this->recs->get_count(this->recs) == 0)
103 {
104 DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
105 return TRUE;
106 }
107 policy = charon->imvs->get_recommendation_policy(charon->imvs);
108
109 enumerator = this->recs->create_enumerator(this->recs);
110 while (enumerator->enumerate(enumerator, &entry))
111 {
112 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION ||
113 entry->eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
114 {
115 incomplete = TRUE;
116 break;
117 }
118 if (first)
119 {
120 final_rec = entry->rec;
121 final_eval = entry->eval;
122 first = FALSE;
123 }
124 switch (policy)
125 {
126 case RECOMMENDATION_POLICY_DEFAULT:
127 /* Consolidate action recommendations */
128 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
129 {
130 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
131 }
132 else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
133 final_rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
134 {
135 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
136 }
137 else
138 {
139 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
140 }
141
142 /* Consolidate evaluation results */
143 if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
144 {
145 final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
146 }
147 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
148 final_eval != TNC_IMV_EVALUATION_RESULT_ERROR)
149 {
150 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
151 }
152 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
153 final_eval != TNC_IMV_EVALUATION_RESULT_ERROR &&
154 final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR)
155 {
156 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
157 }
158 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
159 {
160 final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
161 }
162 break;
163 case RECOMMENDATION_POLICY_ALL:
164 /* Consolidate action recommendations */
165 if (entry->rec != final_rec)
166 {
167 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
168 }
169
170 /* Consolidate evaluation results */
171 if (entry->eval != final_eval)
172 {
173 final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
174 }
175 break;
176 case RECOMMENDATION_POLICY_ANY:
177 /* Consolidate action recommendations */
178 if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
179 {
180 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
181 }
182 else if (entry->rec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
183 final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
184 {
185 final_rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
186 }
187 else
188 {
189 final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
190 }
191
192 /* Consolidate evaluation results */
193 if (entry->eval == TNC_IMV_EVALUATION_RESULT_COMPLIANT)
194 {
195 final_eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
196 }
197 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR &&
198 final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
199 {
200 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
201 }
202 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR &&
203 final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
204 final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
205 {
206 final_eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
207 }
208 else if (entry->eval == TNC_IMV_EVALUATION_RESULT_ERROR)
209 {
210 final_eval = TNC_IMV_EVALUATION_RESULT_ERROR;
211 }
212 }
213 }
214 enumerator->destroy(enumerator);
215
216 if (incomplete)
217 {
218 return FALSE;
219 }
220 *rec = final_rec;
221 *eval = final_eval;
222 return TRUE;
223 }
224
225
226 METHOD(recommendations_t, destroy, void,
227 private_tnc_imv_recommendations_t *this)
228 {
229 this->recs->destroy_function(this->recs, free);
230 free(this);
231 }
232
233 /**
234 * Described in header.
235 */
236 recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
237 {
238 private_tnc_imv_recommendations_t *this;
239 recommendation_entry_t *entry;
240 enumerator_t *enumerator;
241 imv_t *imv;
242
243 INIT(this,
244 .public = {
245 .provide_recommendation = _provide_recommendation,
246 .have_recommendation = _have_recommendation,
247 .destroy = _destroy,
248 },
249 .recs = linked_list_create(),
250 );
251
252 enumerator = imv_list->create_enumerator(imv_list);
253 while (enumerator->enumerate(enumerator, &imv))
254 {
255 entry = malloc_thing(recommendation_entry_t);
256 entry->id = imv->get_id(imv);
257 entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
258 entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
259 this->recs->insert_last(this->recs, entry);
260 }
261 enumerator->destroy(enumerator);
262
263 return &this->public;
264 }