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