f378510cba8396832b6a4f2adcf815c5110d1680
[strongswan.git] / src / libcharon / plugins / tnc_imv / tnc_imv_manager.c
1 /*
2 * Copyright (C) 2006 Mike McCauley
3 * Copyright (C) 2010 Andreas Steffen, 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 "tnc_imv_manager.h"
17 #include "tnc_imv_recommendations.h"
18
19 #include <tnc/imv/imv_manager.h>
20 #include <tnc/tncifimv.h>
21 #include <tnc/tncifimv_names.h>
22
23 #include <debug.h>
24 #include <daemon.h>
25 #include <threading/mutex.h>
26
27 typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t;
28
29
30 /**
31 * Private data of an imv_manager_t object.
32 */
33 struct private_tnc_imv_manager_t {
34
35 /**
36 * Public members of imv_manager_t.
37 */
38 imv_manager_t public;
39
40 /**
41 * Linked list of IMVs
42 */
43 linked_list_t *imvs;
44
45 /**
46 * Next IMV ID to be assigned
47 */
48 TNC_IMVID next_imv_id;
49
50 /**
51 * Policy defining how to derive final recommendation from individual ones
52 */
53 recommendation_policy_t policy;
54 };
55
56 METHOD(imv_manager_t, add, bool,
57 private_tnc_imv_manager_t *this, imv_t *imv)
58 {
59 TNC_Version version;
60
61 /* Initialize the IMV module */
62 imv->set_id(imv, this->next_imv_id);
63 if (imv->initialize(imv->get_id(imv), TNC_IFIMV_VERSION_1,
64 TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
65 {
66 DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv));
67 return FALSE;
68 }
69 this->imvs->insert_last(this->imvs, imv);
70 this->next_imv_id++;
71
72 if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction)
73 != TNC_RESULT_SUCCESS)
74 {
75 DBG1(DBG_TNC, "IMV \"%s\" could failed to obtain bind function",
76 imv->get_name(imv));
77 this->imvs->remove_last(this->imvs, (void**)&imv);
78 return FALSE;
79 }
80
81 return TRUE;
82 }
83
84 METHOD(imv_manager_t, remove_, imv_t*,
85 private_tnc_imv_manager_t *this, TNC_IMVID id)
86 {
87 enumerator_t *enumerator;
88 imv_t *imv;
89
90 enumerator = this->imvs->create_enumerator(this->imvs);
91 while (enumerator->enumerate(enumerator, &imv))
92 {
93 if (id == imv->get_id(imv))
94 {
95 this->imvs->remove_at(this->imvs, enumerator);
96 return imv;
97 }
98 }
99 enumerator->destroy(enumerator);
100 return NULL;
101 }
102
103 METHOD(imv_manager_t, create_recommendations, recommendations_t*,
104 private_tnc_imv_manager_t *this)
105 {
106 return tnc_imv_recommendations_create(this->imvs);
107 }
108
109 METHOD(imv_manager_t, enforce_recommendation, bool,
110 private_tnc_imv_manager_t *this, TNC_IMV_Action_Recommendation rec)
111 {
112 char *group;
113 identification_t *id;
114 ike_sa_t *ike_sa;
115 auth_cfg_t *auth;
116
117 switch (rec)
118 {
119 case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
120 DBG1(DBG_TNC, "TNC recommendation is allow");
121 group = "allow";
122 break;
123 case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
124 DBG1(DBG_TNC, "TNC recommendation is isolate");
125 group = "isolate";
126 break;
127 case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
128 case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
129 default:
130 DBG1(DBG_TNC, "TNC recommendation is none");
131 return FALSE;
132 }
133 ike_sa = charon->bus->get_sa(charon->bus);
134 if (ike_sa)
135 {
136 auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
137 id = identification_create_from_string(group);
138 auth->add(auth, AUTH_RULE_GROUP, id);
139 DBG1(DBG_TNC, "TNC added group membership '%s'", group);
140 }
141 return TRUE;
142 }
143
144
145 METHOD(imv_manager_t, notify_connection_change, void,
146 private_tnc_imv_manager_t *this, TNC_ConnectionID id,
147 TNC_ConnectionState state)
148 {
149 enumerator_t *enumerator;
150 imv_t *imv;
151
152 enumerator = this->imvs->create_enumerator(this->imvs);
153 while (enumerator->enumerate(enumerator, &imv))
154 {
155 if (imv->notify_connection_change)
156 {
157 imv->notify_connection_change(imv->get_id(imv), id, state);
158 }
159 }
160 enumerator->destroy(enumerator);
161 }
162
163 METHOD(imv_manager_t, set_message_types, TNC_Result,
164 private_tnc_imv_manager_t *this, TNC_IMVID id,
165 TNC_MessageTypeList supported_types,
166 TNC_UInt32 type_count)
167 {
168 enumerator_t *enumerator;
169 imv_t *imv;
170 TNC_Result result = TNC_RESULT_FATAL;
171
172 enumerator = this->imvs->create_enumerator(this->imvs);
173 while (enumerator->enumerate(enumerator, &imv))
174 {
175 if (id == imv->get_id(imv))
176 {
177 imv->set_message_types(imv, supported_types, type_count);
178 result = TNC_RESULT_SUCCESS;
179 break;
180 }
181 }
182 enumerator->destroy(enumerator);
183 return result;
184 }
185
186 METHOD(imv_manager_t, solicit_recommendation, void,
187 private_tnc_imv_manager_t *this, TNC_ConnectionID id)
188 {
189 enumerator_t *enumerator;
190 imv_t *imv;
191
192 enumerator = this->imvs->create_enumerator(this->imvs);
193 while (enumerator->enumerate(enumerator, &imv))
194 {
195 imv->solicit_recommendation(imv->get_id(imv), id);
196 }
197 enumerator->destroy(enumerator);
198 }
199
200 METHOD(imv_manager_t, receive_message, void,
201 private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
202 TNC_BufferReference message,
203 TNC_UInt32 message_len,
204 TNC_MessageType message_type)
205 {
206 enumerator_t *enumerator;
207 imv_t *imv;
208
209 enumerator = this->imvs->create_enumerator(this->imvs);
210 while (enumerator->enumerate(enumerator, &imv))
211 {
212 if (imv->receive_message && imv->type_supported(imv, message_type))
213 {
214 imv->receive_message(imv->get_id(imv), connection_id,
215 message, message_len, message_type);
216 }
217 }
218 enumerator->destroy(enumerator);
219 }
220
221 METHOD(imv_manager_t, batch_ending, void,
222 private_tnc_imv_manager_t *this, TNC_ConnectionID id)
223 {
224 enumerator_t *enumerator;
225 imv_t *imv;
226
227 enumerator = this->imvs->create_enumerator(this->imvs);
228 while (enumerator->enumerate(enumerator, &imv))
229 {
230 if (imv->batch_ending)
231 {
232 imv->batch_ending(imv->get_id(imv), id);
233 }
234 }
235 enumerator->destroy(enumerator);
236 }
237
238 METHOD(imv_manager_t, destroy, void,
239 private_tnc_imv_manager_t *this)
240 {
241 imv_t *imv;
242
243 while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
244 {
245 if (imv->terminate &&
246 imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
247 {
248 DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
249 imv->get_name(imv));
250 }
251 imv->destroy(imv);
252 }
253 this->imvs->destroy(this->imvs);
254 free(this);
255 }
256
257 /**
258 * Described in header.
259 */
260 imv_manager_t* tnc_imv_manager_create(void)
261 {
262 private_tnc_imv_manager_t *this;
263 recommendation_policy_t policy;
264
265 INIT(this,
266 .public = {
267 .add = _add,
268 .remove = _remove_, /* avoid name conflict with stdio.h */
269 .create_recommendations = _create_recommendations,
270 .enforce_recommendation = _enforce_recommendation,
271 .notify_connection_change = _notify_connection_change,
272 .set_message_types = _set_message_types,
273 .solicit_recommendation = _solicit_recommendation,
274 .receive_message = _receive_message,
275 .batch_ending = _batch_ending,
276 .destroy = _destroy,
277 },
278 .imvs = linked_list_create(),
279 .next_imv_id = 1,
280 );
281 policy = enum_from_name(recommendation_policy_names,
282 lib->settings->get_str(lib->settings,
283 "charon.plugins.tnc-imv.recommendation_policy", "any"));
284 this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_NONE;
285
286 return &this->public;
287 }