Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_tnc/eap_tnc.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2010-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 "eap_tnc.h"
17:
18: #include <tnc/tnc.h>
19: #include <tnc/tnccs/tnccs_manager.h>
20: #include <tls_eap.h>
21: #include <utils/debug.h>
22: #include <daemon.h>
23:
24: #include <tncifimv.h>
25: #include <tncif_names.h>
26:
27: /**
28: * Maximum size of an EAP-TNC message
29: */
30: #define EAP_TNC_MAX_MESSAGE_LEN 65535
31:
32: /**
33: * Maximum number of EAP-TNC messages allowed
34: */
35: #define EAP_TNC_MAX_MESSAGE_COUNT 10
36:
37: typedef struct private_eap_tnc_t private_eap_tnc_t;
38:
39: /**
40: * Private data of an eap_tnc_t object.
41: */
42: struct private_eap_tnc_t {
43:
44: /**
45: * Public authenticator_t interface.
46: */
47: eap_tnc_t public;
48:
49: /**
50: * Inner EAP authentication type
51: */
52: eap_type_t type;
53:
54: /**
55: * Outer EAP authentication type
56: */
57: eap_type_t auth_type;
58:
59: /**
60: * TLS stack, wrapped by EAP helper
61: */
62: tls_eap_t *tls_eap;
63:
64: /**
65: * TNCCS instance running over EAP-TNC
66: */
67: tnccs_t *tnccs;
68:
69: };
70:
71: /**
72: * Callback function to get recommendation from TNCCS connection
73: */
74: static bool enforce_recommendation(TNC_IMV_Action_Recommendation rec,
75: TNC_IMV_Evaluation_Result eval)
76: {
77: char *group;
78: identification_t *id;
79: ike_sa_t *ike_sa;
80: auth_cfg_t *auth;
81: bool no_access = FALSE;
82:
83: DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'",
84: TNC_IMV_Action_Recommendation_names, rec,
85: TNC_IMV_Evaluation_Result_names, eval);
86:
87: switch (rec)
88: {
89: case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
90: group = "allow";
91: break;
92: case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
93: group = "isolate";
94: break;
95: case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
96: case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
97: default:
98: group = "no access";
99: no_access = TRUE;
100: break;
101: }
102:
103: ike_sa = charon->bus->get_sa(charon->bus);
104: if (!ike_sa)
105: {
106: DBG1(DBG_TNC, "policy enforcement point did not find IKE_SA");
107: return FALSE;
108: }
109:
110: id = ike_sa->get_other_id(ike_sa);
111: DBG0(DBG_TNC, "policy enforced on peer '%Y' is '%s'", id, group);
112:
113: if (no_access)
114: {
115: return FALSE;
116: }
117: else
118: {
119: auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
120: id = identification_create_from_string(group);
121: auth->add(auth, AUTH_RULE_GROUP, id);
122: DBG1(DBG_TNC, "policy enforcement point added group membership '%s'",
123: group);
124: }
125: return TRUE;
126: }
127:
128: METHOD(eap_method_t, initiate, status_t,
129: private_eap_tnc_t *this, eap_payload_t **out)
130: {
131: chunk_t data;
132: uint32_t auth_type;
133:
134: /* Determine TNC Client Authentication Type */
135: switch (this->auth_type)
136: {
137: case EAP_TLS:
138: case EAP_TTLS:
139: case EAP_PEAP:
140: auth_type = TNC_AUTH_X509_CERT;
141: break;
142: case EAP_MD5:
143: case EAP_MSCHAPV2:
144: case EAP_GTC:
145: case EAP_OTP:
146: auth_type = TNC_AUTH_PASSWORD;
147: break;
148: case EAP_SIM:
149: case EAP_AKA:
150: auth_type = TNC_AUTH_SIM;
151: break;
152: default:
153: auth_type = TNC_AUTH_UNKNOWN;
154: }
155: this->tnccs->set_auth_type(this->tnccs, auth_type);
156:
157: if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE)
158: {
159: *out = eap_payload_create_data(data);
160: free(data.ptr);
161: return NEED_MORE;
162: }
163: return FAILED;
164: }
165:
166: METHOD(eap_method_t, process, status_t,
167: private_eap_tnc_t *this, eap_payload_t *in, eap_payload_t **out)
168: {
169: status_t status;
170: chunk_t data;
171:
172: data = in->get_data(in);
173: status = this->tls_eap->process(this->tls_eap, data, &data);
174: if (status == NEED_MORE)
175: {
176: *out = eap_payload_create_data(data);
177: free(data.ptr);
178: }
179: return status;
180: }
181:
182: METHOD(eap_method_t, get_type, eap_type_t,
183: private_eap_tnc_t *this, uint32_t *vendor)
184: {
185: *vendor = 0;
186: return this->type;
187: }
188:
189: METHOD(eap_method_t, get_msk, status_t,
190: private_eap_tnc_t *this, chunk_t *msk)
191: {
192: *msk = this->tls_eap->get_msk(this->tls_eap);
193: if (msk->len)
194: {
195: return SUCCESS;
196: }
197: return FAILED;
198: }
199:
200: METHOD(eap_method_t, get_identifier, uint8_t,
201: private_eap_tnc_t *this)
202: {
203: return this->tls_eap->get_identifier(this->tls_eap);
204: }
205:
206: METHOD(eap_method_t, set_identifier, void,
207: private_eap_tnc_t *this, uint8_t identifier)
208: {
209: this->tls_eap->set_identifier(this->tls_eap, identifier);
210: }
211:
212: METHOD(eap_method_t, is_mutual, bool,
213: private_eap_tnc_t *this)
214: {
215: return FALSE;
216: }
217:
218: METHOD(eap_method_t, destroy, void,
219: private_eap_tnc_t *this)
220: {
221: chunk_t pdp_server;
222: uint16_t pdp_port;
223: tls_t *tls;
224:
225: pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port);
226: if (pdp_server.len)
227: {
228: DBG2(DBG_TNC, "TODO: setup PT-TLS connection to %.*s:%u",
229: pdp_server.len, pdp_server.ptr, pdp_port);
230: }
231: tls = &this->tnccs->tls;
232: tls->destroy(tls);
233: this->tls_eap->destroy(this->tls_eap);
234: free(this);
235: }
236:
237: METHOD(eap_inner_method_t, get_auth_type, eap_type_t,
238: private_eap_tnc_t *this)
239: {
240: return this->auth_type;
241: }
242:
243: METHOD(eap_inner_method_t, set_auth_type, void,
244: private_eap_tnc_t *this, eap_type_t type)
245: {
246: this->auth_type = type;
247: }
248:
249: /**
250: * Generic private constructor
251: */
252: static eap_tnc_t *eap_tnc_create(identification_t *server,
253: identification_t *peer, bool is_server,
254: eap_type_t type)
255: {
256: private_eap_tnc_t *this;
257: int max_msg_count;
258: char* protocol;
259: ike_sa_t *ike_sa;
260: host_t *server_ip, *peer_ip;
261: tnccs_t *tnccs;
262: tnccs_type_t tnccs_type;
263:
264: INIT(this,
265: .public = {
266: .eap_inner_method = {
267: .eap_method = {
268: .initiate = _initiate,
269: .process = _process,
270: .get_type = _get_type,
271: .is_mutual = _is_mutual,
272: .get_msk = _get_msk,
273: .get_identifier = _get_identifier,
274: .set_identifier = _set_identifier,
275: .destroy = _destroy,
276: },
277: .get_auth_type = _get_auth_type,
278: .set_auth_type = _set_auth_type,
279: },
280: },
281: .type = type,
282: );
283:
284: max_msg_count = lib->settings->get_int(lib->settings,
285: "%s.plugins.eap-tnc.max_message_count",
286: EAP_TNC_MAX_MESSAGE_COUNT, lib->ns);
287: protocol = lib->settings->get_str(lib->settings,
288: "%s.plugins.eap-tnc.protocol", "tnccs-2.0", lib->ns);
289: if (strcaseeq(protocol, "tnccs-2.0"))
290: {
291: tnccs_type = TNCCS_2_0;
292: }
293: else if (strcaseeq(protocol, "tnccs-1.1"))
294: {
295: tnccs_type = TNCCS_1_1;
296: }
297: else if (strcaseeq(protocol, "tnccs-dynamic") && is_server)
298: {
299: tnccs_type = TNCCS_DYNAMIC;
300: }
301: else
302: {
303: DBG1(DBG_TNC, "TNCCS protocol '%s' not supported", protocol);
304: free(this);
305: return NULL;
306: }
307:
308: /* Determine IP addresses of server and peer */
309: ike_sa = charon->bus->get_sa(charon->bus);
310: if (!ike_sa)
311: {
312: DBG1(DBG_TNC, "%N constructor did not find IKE_SA",
313: eap_type_names, type);
314: free(this);
315: return NULL;
316: }
317: if (is_server)
318: {
319: server_ip = ike_sa->get_my_host(ike_sa);
320: peer_ip = ike_sa->get_other_host(ike_sa);
321: }
322: else
323: {
324: peer_ip = ike_sa->get_my_host(ike_sa);
325: server_ip = ike_sa->get_other_host(ike_sa);
326: }
327:
328: tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
329: is_server, server, peer, server_ip, peer_ip,
330: (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
331: enforce_recommendation);
332: if (!tnccs)
333: {
334: DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol);
335: free(this);
336: return NULL;
337: }
338: if (!is_server)
339: {
340: tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
341: }
342: this->tnccs = tnccs->get_ref(tnccs);
343: this->tls_eap = tls_eap_create(type, &tnccs->tls,
344: EAP_TNC_MAX_MESSAGE_LEN,
345: max_msg_count, FALSE);
346: if (!this->tls_eap)
347: {
348: free(this);
349: return NULL;
350: }
351: return &this->public;
352: }
353:
354: eap_tnc_t *eap_tnc_create_server(identification_t *server,
355: identification_t *peer)
356: {
357: return eap_tnc_create(server, peer, TRUE, EAP_TNC);
358: }
359:
360: eap_tnc_t *eap_tnc_create_peer(identification_t *server,
361: identification_t *peer)
362: {
363: return eap_tnc_create(server, peer, FALSE, EAP_TNC);
364: }
365:
366: eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
367: identification_t *peer)
368: {
369: return eap_tnc_create(server, peer, TRUE, EAP_PT_EAP);
370: }
371:
372: eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
373: identification_t *peer)
374: {
375: return eap_tnc_create(server, peer, FALSE, EAP_PT_EAP);
376: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>