Annotation of embedaddon/strongswan/src/libcharon/plugins/tnc_pdp/tnc_pdp.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-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 "tnc_pdp.h"
17: #include "tnc_pdp_connections.h"
18:
19: #include <errno.h>
20: #include <unistd.h>
21: #include <time.h>
22:
23: #include <radius_message.h>
24: #include <radius_mppe.h>
25:
26: #include <pt_tls_server.h>
27:
28: #include <tnc/tnc.h>
29:
30: #include <tncifimv.h>
31: #include <tncif_names.h>
32:
33: #include <daemon.h>
34: #include <utils/debug.h>
35: #include <pen/pen.h>
36: #include <threading/thread.h>
37: #include <processing/jobs/callback_job.h>
38: #include <sa/eap/eap_method.h>
39:
40: typedef struct private_tnc_pdp_t private_tnc_pdp_t;
41: typedef struct client_entry_t client_entry_t;
42: /**
43: * Default RADIUS port, when not configured
44: */
45: #define RADIUS_PORT 1812
46:
47: /**
48: * Maximum size of a RADIUS IP packet
49: */
50: #define MAX_PACKET 4096
51:
52: #define RADIUS_RETRANSMIT_TIMEOUT 30 /* seconds */
53:
54: /**
55: * private data of tnc_pdp_t
56: */
57: struct private_tnc_pdp_t {
58:
59: /**
60: * implements tnc_pdp_t interface
61: */
62: tnc_pdp_t public;
63:
64: /**
65: * ID of the server
66: */
67: identification_t *server;
68:
69: /**
70: * EAP method type to be used
71: */
72: eap_type_t type;
73:
74: /**
75: * PT-TLS port of the server
76: */
77: uint16_t pt_tls_port;
78:
79: /**
80: * PT-TLS IPv4 socket
81: */
82: int pt_tls_ipv4;
83:
84: /**
85: * PT-TLS IPv6 socket
86: */
87: int pt_tls_ipv6;
88:
89: /**
90: * RADIUS IPv4 socket
91: */
92: int radius_ipv4;
93:
94: /**
95: * RADIUS IPv6 socket
96: */
97: int radius_ipv6;
98:
99: /**
100: * RADIUS shared secret
101: */
102: chunk_t secret;
103:
104: /**
105: * RADIUS clients
106: */
107: linked_list_t *clients;
108:
109: /**
110: * MD5 hasher
111: */
112: hasher_t *hasher;
113:
114: /**
115: * HMAC MD5 signer, with secret set
116: */
117: signer_t *signer;
118:
119: /**
120: * Nonce generator for MS-MPPE salt values
121: */
122: nonce_gen_t *ng;
123:
124: /**
125: * List of registered TNC-PDP connections
126: */
127: tnc_pdp_connections_t *connections;
128:
129: };
130:
131: /**
132: * Client entry helping to detect RADIUS packet retransmissions
133: */
134: struct client_entry_t {
135:
136: /**
137: * IP host address and port of client
138: */
139: host_t *host;
140:
141: /**
142: * Time of last RADIUS Access-Request received from client
143: */
144: time_t last_time;
145:
146: /**
147: * Identifier of last RADIUS Access-Request received from client
148: */
149: uint8_t last_id;
150: };
151:
152: static void free_client_entry(client_entry_t *this)
153: {
154: this->host->destroy(this->host);
155: free(this);
156: }
157:
158: /**
159: * Open IPv4 or IPv6 UDP socket
160: */
161: static int open_udp_socket(int family, uint16_t port)
162: {
163: int on = TRUE;
164: struct sockaddr_storage addr;
165: socklen_t addrlen;
166: int skt;
167:
168: memset(&addr, 0, sizeof(addr));
169: addr.ss_family = family;
170:
171: /* precalculate constants depending on address family */
172: switch (family)
173: {
174: case AF_INET:
175: {
176: struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
177:
178: htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
179: htoun16(&sin->sin_port, port);
180: addrlen = sizeof(struct sockaddr_in);
181: break;
182: }
183: case AF_INET6:
184: {
185: struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
186:
187: memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
188: htoun16(&sin6->sin6_port, port);
189: addrlen = sizeof(struct sockaddr_in6);
190: break;
191: }
192: default:
193: return 0;
194: }
195:
196: /* open the socket */
197: skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
198: if (skt < 0)
199: {
200: DBG1(DBG_CFG, "opening UDP socket failed: %s", strerror(errno));
201: return 0;
202: }
203: if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
204: {
205: DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s",
206: strerror(errno));
207: close(skt);
208: return 0;
209: }
210: if (family == AF_INET6)
211: {
212: if (setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY,
213: (void *)&on, sizeof(on)) < 0)
214: {
215: DBG1(DBG_CFG, "unable to set IPV6_V6ONLY on socket: %s",
216: strerror(errno));
217: close(skt);
218: return 0;
219: }
220: }
221:
222: /* bind the socket */
223: if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
224: {
225: DBG1(DBG_CFG, "unable to bind UDP socket: %s", strerror(errno));
226: close(skt);
227: return 0;
228: }
229:
230: return skt;
231: }
232:
233: /**
234: * Open IPv4 or IPv6 TCP socket
235: */
236: static int open_tcp_socket(int family, uint16_t port)
237: {
238: int on = TRUE;
239: struct sockaddr_storage addr;
240: socklen_t addrlen;
241: int skt;
242:
243: memset(&addr, 0, sizeof(addr));
244: addr.ss_family = family;
245:
246: /* precalculate constants depending on address family */
247: switch (family)
248: {
249: case AF_INET:
250: {
251: struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
252:
253: htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
254: htoun16(&sin->sin_port, port);
255: addrlen = sizeof(struct sockaddr_in);
256: break;
257: }
258: case AF_INET6:
259: {
260: struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
261:
262: memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
263: htoun16(&sin6->sin6_port, port);
264: addrlen = sizeof(struct sockaddr_in6);
265: break;
266: }
267: default:
268: return 0;
269: }
270:
271: /* open the socket */
272: skt = socket(family, SOCK_STREAM, IPPROTO_TCP);
273: if (skt < 0)
274: {
275: DBG1(DBG_CFG, "opening TCP socket failed: %s", strerror(errno));
276: return 0;
277: }
278: if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
279: {
280: DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s",
281: strerror(errno));
282: close(skt);
283: return 0;
284: }
285: if (family == AF_INET6)
286: {
287: if (setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY,
288: (void *)&on, sizeof(on)) < 0)
289: {
290: DBG1(DBG_CFG, "unable to set IPV6_V6ONLY on socket: %s",
291: strerror(errno));
292: close(skt);
293: return 0;
294: }
295: }
296:
297: /* bind the socket */
298: if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
299: {
300: DBG1(DBG_CFG, "unable to bind TCP socket: %s", strerror(errno));
301: close(skt);
302: return 0;
303: }
304:
305: /* start listening on socket */
306: if (listen(skt, 5) == -1)
307: {
308: DBG1(DBG_TNC, "listen on TCP socket failed: %s", strerror(errno));
309: close(skt);
310: return 0;
311: }
312:
313: return skt;
314: }
315:
316: /**
317: * Send a RADIUS message to client
318: */
319: static void send_message(private_tnc_pdp_t *this, radius_message_t *message,
320: host_t *client)
321: {
322: int fd;
323: chunk_t data;
324:
325: fd = (client->get_family(client) == AF_INET) ?
326: this->radius_ipv4 : this->radius_ipv6;
327: data = message->get_encoding(message);
328:
329: DBG2(DBG_CFG, "sending RADIUS packet to %#H", client);
330: DBG3(DBG_CFG, "%B", &data);
331:
332: if (sendto(fd, data.ptr, data.len, 0, client->get_sockaddr(client),
333: *client->get_sockaddr_len(client)) != data.len)
334: {
335: DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
336: }
337: }
338:
339: /**
340: * Encrypt a MS-MPPE-Send/Recv-Key
341: */
342: static chunk_t encrypt_mppe_key(private_tnc_pdp_t *this, uint8_t type,
343: chunk_t key, uint16_t *salt,
344: radius_message_t *request)
345: {
346: chunk_t a, r, seed, data;
347: u_char b[HASH_SIZE_MD5], *c;
348: mppe_key_t *mppe_key;
349:
350: /**
351: * From RFC2548 (encryption):
352: * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1)
353: * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2)
354: * . . .
355: * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i)
356: */
357:
358: data = chunk_alloc(sizeof(mppe_key_t) +
359: HASH_SIZE_MD5 * (1 + key.len / HASH_SIZE_MD5));
360: memset(data.ptr, 0x00, data.len);
361:
362: mppe_key = (mppe_key_t*)data.ptr;
363: mppe_key->id = htonl(PEN_MICROSOFT);
364: mppe_key->type = type;
365: mppe_key->length = data.len - sizeof(mppe_key->id);
366: mppe_key->key[0] = key.len;
367:
368: memcpy(&mppe_key->key[1], key.ptr, key.len);
369:
370: /**
371: * generate a 16 bit unique random salt value for the MPPE stream cipher
372: * the MSB of the salt MUST be set to 1
373: */
374: a = chunk_create((u_char*)&(mppe_key->salt), sizeof(mppe_key->salt));
375: do
376: {
377: if (!this->ng->get_nonce(this->ng, a.len, a.ptr))
378: {
379: free(data.ptr);
380: return chunk_empty;
381: }
382: *a.ptr |= 0x80;
383: }
384: while (mppe_key->salt == *salt);
385:
386: /* update the salt value */
387: *salt = mppe_key->salt;
388:
389: r = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5);
390: seed = chunk_cata("cc", r, a);
391:
392: c = mppe_key->key;
393: while (c < data.ptr + data.len)
394: {
395: /* b(i) = MD5(S + c(i-1)) */
396: if (!this->hasher->get_hash(this->hasher, this->secret, NULL) ||
397: !this->hasher->get_hash(this->hasher, seed, b))
398: {
399: free(data.ptr);
400: return chunk_empty;
401: }
402:
403: /* c(i) = b(i) xor p(1) */
404: memxor(c, b, HASH_SIZE_MD5);
405:
406: /* prepare next round */
407: seed = chunk_create(c, HASH_SIZE_MD5);
408: c += HASH_SIZE_MD5;
409: }
410:
411: return data;
412: }
413:
414: /**
415: * Send a RADIUS response for a request
416: */
417: static void send_response(private_tnc_pdp_t *this, radius_message_t *request,
418: radius_message_code_t code, eap_payload_t *eap,
419: identification_t *group, chunk_t msk, host_t *client)
420: {
421: radius_message_t *response;
422: chunk_t data, recv, send;
423: uint32_t tunnel_type;
424: uint16_t salt = 0;
425:
426: response = radius_message_create(code);
427: data = eap->get_data(eap);
428: DBG3(DBG_CFG, "%N payload %B", eap_type_names, this->type, &data);
429:
430: /* fragment data suitable for RADIUS */
431: while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE)
432: {
433: response->add(response, RAT_EAP_MESSAGE,
434: chunk_create(data.ptr, MAX_RADIUS_ATTRIBUTE_SIZE));
435: data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE);
436: }
437: response->add(response, RAT_EAP_MESSAGE, data);
438:
439: if (group)
440: {
441: tunnel_type = RADIUS_TUNNEL_TYPE_ESP;
442: htoun32(data.ptr, tunnel_type);
443: data.len = sizeof(tunnel_type);
444: response->add(response, RAT_TUNNEL_TYPE, data);
445: response->add(response, RAT_FILTER_ID, group->get_encoding(group));
446: }
447: if (msk.len)
448: {
449: recv = chunk_create(msk.ptr, msk.len / 2);
450: data = encrypt_mppe_key(this, MS_MPPE_RECV_KEY, recv, &salt, request);
451: response->add(response, RAT_VENDOR_SPECIFIC, data);
452: chunk_free(&data);
453:
454: send = chunk_create(msk.ptr + recv.len, msk.len - recv.len);
455: data = encrypt_mppe_key(this, MS_MPPE_SEND_KEY, send, &salt, request);
456: response->add(response, RAT_VENDOR_SPECIFIC, data);
457: chunk_free(&data);
458: }
459: response->set_identifier(response, request->get_identifier(request));
460: if (response->sign(response, request->get_authenticator(request),
461: this->secret, this->hasher, this->signer, NULL, TRUE))
462: {
463: DBG1(DBG_CFG, "sending RADIUS %N to client '%H'",
464: radius_message_code_names, code, client);
465: send_message(this, response, client);
466: }
467: response->destroy(response);
468: }
469:
470: /**
471: * Process EAP message
472: */
473: static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
474: host_t *source)
475: {
476: enumerator_t *enumerator;
477: eap_payload_t *in, *out = NULL;
478: eap_method_t *method;
479: eap_type_t eap_type;
480: uint32_t eap_vendor;
481: chunk_t data, message = chunk_empty, msk = chunk_empty;
482: chunk_t user_name = chunk_empty, nas_id = chunk_empty;
483: identification_t *group = NULL;
484: radius_message_code_t code = RMC_ACCESS_CHALLENGE;
485: int type;
486:
487: enumerator = request->create_enumerator(request);
488: while (enumerator->enumerate(enumerator, &type, &data))
489: {
490: switch (type)
491: {
492: case RAT_USER_NAME:
493: user_name = data;
494: break;
495: case RAT_NAS_IDENTIFIER:
496: nas_id = data;
497: break;
498: case RAT_EAP_MESSAGE:
499: if (data.len)
500: {
501: message = chunk_cat("mc", message, data);
502: }
503: break;
504: default:
505: break;
506: }
507: }
508: enumerator->destroy(enumerator);
509:
510: if (message.len)
511: {
512: in = eap_payload_create_data(message);
513:
514: /* apply EAP method selected by RADIUS server */
515: eap_type = in->get_type(in, &eap_vendor);
516:
517: DBG3(DBG_CFG, "%N payload %B", eap_type_names, eap_type, &message);
518:
519: if (eap_type == EAP_IDENTITY)
520: {
521: identification_t *peer;
522: chunk_t eap_identity;
523:
524: if (message.len < 5)
525: {
526: goto end;
527: }
528: eap_identity = chunk_create(message.ptr + 5, message.len - 5);
529: peer = identification_create_from_data(eap_identity);
530: method = charon->eap->create_instance(charon->eap, this->type,
531: 0, EAP_SERVER, this->server, peer);
532: if (!method)
533: {
534: peer->destroy(peer);
535: goto end;
536: }
537: this->connections->add(this->connections, nas_id, user_name, peer,
538: method);
539: if (method->initiate(method, &out) == NEED_MORE)
540: {
541: send_response(this, request, code, out, group, msk, source);
542: }
543: }
544: else
545: {
546: ike_sa_t *ike_sa;
547: auth_cfg_t *auth;
548: auth_rule_t type;
549: identification_t *data;
550: enumerator_t *e;
551:
552: method = this->connections->get_state(this->connections, nas_id,
553: user_name, &ike_sa);
554: if (!method)
555: {
556: goto end;
557: }
558: charon->bus->set_sa(charon->bus, ike_sa);
559:
560: switch (method->process(method, in, &out))
561: {
562: case NEED_MORE:
563: code = RMC_ACCESS_CHALLENGE;
564: break;
565: case SUCCESS:
566: code = RMC_ACCESS_ACCEPT;
567: method->get_msk(method, &msk);
568: auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
569: e = auth->create_enumerator(auth);
570: while (e->enumerate(e, &type, &data))
571: {
572: /* look for group memberships */
573: if (type == AUTH_RULE_GROUP)
574: {
575: group = data;
576: }
577: }
578: e->destroy(e);
579:
580: DESTROY_IF(out);
581: out = eap_payload_create_code(EAP_SUCCESS,
582: in->get_identifier(in));
583: break;
584: case FAILED:
585: default:
586: code = RMC_ACCESS_REJECT;
587: DESTROY_IF(out);
588: out = eap_payload_create_code(EAP_FAILURE,
589: in->get_identifier(in));
590: }
591: charon->bus->set_sa(charon->bus, NULL);
592: send_response(this, request, code, out, group, msk, source);
593: this->connections->unlock(this->connections);
594: }
595:
596: if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT)
597: {
598: this->connections->remove(this->connections, nas_id, user_name);
599: }
600:
601: out->destroy(out);
602: end:
603: free(message.ptr);
604: in->destroy(in);
605: }
606: }
607:
608: /**
609: * Callback function to get recommendation from TNCCS connection
610: */
611: static bool get_recommendation(TNC_IMV_Action_Recommendation rec,
612: TNC_IMV_Evaluation_Result eval)
613: {
614: DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'",
615: TNC_IMV_Action_Recommendation_names, rec,
616: TNC_IMV_Evaluation_Result_names, eval);
617:
618: return TRUE;
619: }
620:
621: /**
622: * Get more data on a PT-TLS connection
623: */
624: static bool pt_tls_receive_more(pt_tls_server_t *this, int fd,
625: watcher_event_t event)
626: {
627: switch (this->handle(this))
628: {
629: case NEED_MORE:
630: return TRUE;
631: case FAILED:
632: case SUCCESS:
633: default:
634: DBG1(DBG_TNC, "PT-TLS connection terminates");
635: this->destroy(this);
636: close(fd);
637: return FALSE;
638: }
639: }
640:
641: /**
642: * Accept TCP connection received on the PT-TLS listening socket
643: */
644: static bool pt_tls_receive(private_tnc_pdp_t *this, int fd, watcher_event_t event)
645: {
646: int pt_tls_fd;
647: struct sockaddr_storage addr;
648: socklen_t addrlen = sizeof(addr);
649: identification_t *client_id;
650: host_t *server_ip, *client_ip;
651: pt_tls_server_t *pt_tls;
652: tnccs_t *tnccs;
653: pt_tls_auth_t auth = PT_TLS_AUTH_TLS_OR_SASL;
654:
655: pt_tls_fd = accept(fd, (sockaddr_t*)&addr, &addrlen);
656: if (pt_tls_fd == -1)
657: {
658: DBG1(DBG_TNC, "accepting PT-TLS stream failed: %s", strerror(errno));
659: return FALSE;
660: }
661: client_ip = host_create_from_sockaddr((sockaddr_t*)&addr);
662: DBG1(DBG_TNC, "accepting PT-TLS stream from %H", client_ip);
663:
664: /* Currently we do not determine the IP address of the server interface */
665: server_ip = host_create_any(client_ip->get_family(client_ip));
666:
667: /* At this moment the client identity is not known yet */
668: client_id = identification_create_from_encoding(ID_ANY, chunk_empty);
669:
670: tnccs = tnc->tnccs->create_instance(tnc->tnccs, TNCCS_2_0, TRUE,
671: this->server, client_id, server_ip,
672: client_ip, TNC_IFT_TLS_2_0,
673: (tnccs_cb_t)get_recommendation);
674: client_id->destroy(client_id);
675: server_ip->destroy(server_ip);
676: client_ip->destroy(client_ip);
677:
678: if (!tnccs)
679: {
680: DBG1(DBG_TNC, "could not create TNCCS 2.0 connection instance");
681: close(pt_tls_fd);
682: return FALSE;
683: }
684:
685: pt_tls = pt_tls_server_create(this->server, pt_tls_fd, auth, tnccs);
686: if (!pt_tls)
687: {
688: DBG1(DBG_TNC, "could not create PT-TLS connection instance");
689: close(pt_tls_fd);
690: return FALSE;
691: }
692:
693: lib->watcher->add(lib->watcher, pt_tls_fd, WATCHER_READ,
694: (watcher_cb_t)pt_tls_receive_more, pt_tls);
695:
696: return TRUE;
697: }
698:
699: /**
700: * Process packets received on the RADIUS socket
701: */
702: static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t event)
703: {
704: radius_message_t *request;
705: char buffer[MAX_PACKET];
706: client_entry_t *client;
707: bool retransmission = FALSE, found = FALSE, stale;
708: enumerator_t *enumerator;
709: int bytes_read = 0;
710: host_t *source;
711: uint8_t id;
712: time_t now;
713:
714: union {
715: struct sockaddr_in in4;
716: struct sockaddr_in6 in6;
717: } src;
718:
719: struct iovec iov = {
720: .iov_base = buffer,
721: .iov_len = MAX_PACKET,
722: };
723:
724: struct msghdr msg = {
725: .msg_name = &src,
726: .msg_namelen = sizeof(src),
727: .msg_iov = &iov,
728: .msg_iovlen = 1,
729: };
730:
731: /* read received packet */
732: bytes_read = recvmsg(fd, &msg, 0);
733: if (bytes_read < 0)
734: {
735: DBG1(DBG_CFG, "error reading RADIUS socket: %s", strerror(errno));
736: return FALSE;
737: }
738: if (msg.msg_flags & MSG_TRUNC)
739: {
740: DBG1(DBG_CFG, "receive buffer too small, RADIUS packet discarded");
741: return FALSE;
742: }
743: source = host_create_from_sockaddr((sockaddr_t*)&src);
744: DBG2(DBG_CFG, "received RADIUS packet from %#H", source);
745: DBG3(DBG_CFG, "%b", buffer, bytes_read);
746: request = radius_message_parse(chunk_create(buffer, bytes_read));
747: if (request)
748: {
749: DBG1(DBG_CFG, "received RADIUS %N from client '%H'",
750: radius_message_code_names, request->get_code(request), source);
751:
752: if (request->verify(request, NULL, this->secret, this->hasher,
753: this->signer))
754: {
755: id = request->get_identifier(request);
756: now = time(NULL);
757:
758: enumerator = this->clients->create_enumerator(this->clients);
759: while (enumerator->enumerate(enumerator, &client))
760: {
761: stale = client->last_time < now - RADIUS_RETRANSMIT_TIMEOUT;
762:
763: if (source->equals(source, client->host))
764: {
765: retransmission = !stale && client->last_id == id;
766: client->last_id = id;
767: client->last_time = now;
768: found = TRUE;
769: }
770: else if (stale)
771: {
772: this->clients->remove_at(this->clients, enumerator);
773: free_client_entry(client);
774: }
775: }
776: enumerator->destroy(enumerator);
777:
778: if (!found)
779: {
780: client = malloc_thing(client_entry_t);
781: client->host = source->clone(source);
782: client->last_id = id;
783: client->last_time = now;
784: this->clients->insert_last(this->clients, client);
785: }
786: if (retransmission)
787: {
788: DBG1(DBG_CFG, "ignoring RADIUS Access-Request 0x%02x, "
789: "already processing", id);
790: }
791: else
792: {
793: process_eap(this, request, source);
794: }
795: }
796: request->destroy(request);
797: }
798: else
799: {
800: DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
801: }
802: source->destroy(source);
803: return TRUE;
804: }
805:
806: METHOD(tnc_pdp_t, destroy, void,
807: private_tnc_pdp_t *this)
808: {
809: if (this->pt_tls_ipv4)
810: {
811: lib->watcher->remove(lib->watcher, this->pt_tls_ipv4);
812: close(this->pt_tls_ipv4);
813: }
814: if (this->pt_tls_ipv6)
815: {
816: lib->watcher->remove(lib->watcher, this->pt_tls_ipv6);
817: close(this->pt_tls_ipv6);
818: }
819: if (this->radius_ipv4)
820: {
821: lib->watcher->remove(lib->watcher, this->radius_ipv4);
822: close(this->radius_ipv4);
823: }
824: if (this->radius_ipv6)
825: {
826: lib->watcher->remove(lib->watcher, this->radius_ipv6);
827: close(this->radius_ipv6);
828: }
829: if (this->clients)
830: {
831: this->clients->destroy_function(this->clients, (void*)free_client_entry);
832: }
833: DESTROY_IF(this->server);
834: DESTROY_IF(this->signer);
835: DESTROY_IF(this->hasher);
836: DESTROY_IF(this->ng);
837: DESTROY_IF(this->connections);
838: free(this);
839: }
840:
841: /*
842: * see header file
843: */
844: tnc_pdp_t *tnc_pdp_create(void)
845: {
846: private_tnc_pdp_t *this;
847: char *secret, *server, *eap_type_str;
848: int radius_port, pt_tls_port;
849: bool radius_enable, pt_tls_enable;
850:
851: server = lib->settings->get_str(lib->settings,
852: "%s.plugins.tnc-pdp.server", NULL, lib->ns);
853: pt_tls_enable = lib->settings->get_bool(lib->settings,
854: "%s.plugins.tnc-pdp.pt_tls.enable", TRUE, lib->ns);
855: pt_tls_port = lib->settings->get_int(lib->settings,
856: "%s.plugins.tnc-pdp.pt_tls.port", PT_TLS_PORT, lib->ns);
857: radius_enable = lib->settings->get_bool(lib->settings,
858: "%s.plugins.tnc-pdp.radius.enable", TRUE, lib->ns);
859: radius_port = lib->settings->get_int(lib->settings,
860: "%s.plugins.tnc-pdp.radius.port", RADIUS_PORT, lib->ns);
861: secret = lib->settings->get_str(lib->settings,
862: "%s.plugins.tnc-pdp.radius.secret", NULL, lib->ns);
863: eap_type_str = lib->settings->get_str(lib->settings,
864: "%s.plugins.tnc-pdp.radius.method", "ttls", lib->ns);
865:
866: if (!pt_tls_enable && !radius_enable)
867: {
868: DBG1(DBG_CFG, " neither PT-TLS and RADIUS protocols enabled, PDP disabled");
869: return NULL;
870: }
871: if (!server)
872: {
873: DBG1(DBG_CFG, "missing PDP server name, PDP disabled");
874: return NULL;
875: }
876:
877: INIT(this,
878: .public = {
879: .destroy = _destroy,
880: },
881: .server = identification_create_from_string(server),
882: .connections = tnc_pdp_connections_create(),
883: );
884:
885: /* Create IPv4 and IPv6 PT-TLS listening sockets */
886: if (pt_tls_enable)
887: {
888: this->pt_tls_ipv4 = open_tcp_socket(AF_INET, pt_tls_port);
889: this->pt_tls_ipv6 = open_tcp_socket(AF_INET6, pt_tls_port);
890:
891: if (!this->pt_tls_ipv4 && !this->pt_tls_ipv6)
892: {
893: DBG1(DBG_NET, "could not create any PT-TLS sockets");
894: destroy(this);
895: return NULL;
896: }
897: this->pt_tls_port = pt_tls_port;
898:
899: if (this->pt_tls_ipv4)
900: {
901: lib->watcher->add(lib->watcher, this->pt_tls_ipv4, WATCHER_READ,
902: (watcher_cb_t)pt_tls_receive, this);
903: }
904: else
905: {
906: DBG1(DBG_NET, "could not open IPv4 PT-TLS socket, IPv4 disabled");
907: }
908:
909: if (this->pt_tls_ipv6)
910: {
911: lib->watcher->add(lib->watcher, this->pt_tls_ipv6, WATCHER_READ,
912: (watcher_cb_t)pt_tls_receive, this);
913: }
914: else
915: {
916: DBG1(DBG_NET, "could not open IPv6 PT-TLS socket, IPv6 disabled");
917: }
918:
919: /* register PT-TLS service */
920: lib->set(lib, "pt-tls-server", this->server);
921: lib->set(lib, "pt-tls-port", &this->pt_tls_port);
922: }
923:
924: /* Create IPv4 and IPv6 RADIUS listening sockets */
925: if (radius_enable)
926: {
927: if (!secret)
928: {
929: DBG1(DBG_CFG, "missing RADIUS secret, PDP disabled");
930: destroy(this);
931: return NULL;
932: }
933:
934: this->radius_ipv4 = open_udp_socket(AF_INET, radius_port);
935: this->radius_ipv6 = open_udp_socket(AF_INET6, radius_port);
936: this->secret = chunk_from_str(secret);
937: this->clients = linked_list_create();
938: this->type = eap_type_from_string(eap_type_str);
939: this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
940: this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
941: this->ng = lib->crypto->create_nonce_gen(lib->crypto);
942:
943: if (!this->hasher || !this->signer || !this->ng)
944: {
945: DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/NG required");
946: destroy(this);
947: return NULL;
948: }
949: if (!this->radius_ipv4 && !this->radius_ipv6)
950: {
951: DBG1(DBG_NET, "could not create any RADIUS sockets");
952: destroy(this);
953: return NULL;
954: }
955: if (this->radius_ipv4)
956: {
957: lib->watcher->add(lib->watcher, this->radius_ipv4, WATCHER_READ,
958: (watcher_cb_t)radius_receive, this);
959: }
960: else
961: {
962: DBG1(DBG_NET, "could not open IPv4 RADIUS socket, IPv4 disabled");
963: }
964: if (this->radius_ipv6)
965: {
966: lib->watcher->add(lib->watcher, this->radius_ipv6, WATCHER_READ,
967: (watcher_cb_t)radius_receive, this);
968: }
969: else
970: {
971: DBG1(DBG_NET, "could not open IPv6 RADIUS socket, IPv6 disabled");
972: }
973:
974: if (!this->signer->set_key(this->signer, this->secret))
975: {
976: DBG1(DBG_CFG, "could not set signer key");
977: destroy(this);
978: return NULL;
979: }
980: if (this->type == 0)
981: {
982: DBG1(DBG_CFG, "unrecognized eap method \"%s\"", eap_type_str);
983: destroy(this);
984: return NULL;
985: }
986: DBG1(DBG_IKE, "eap method %N selected", eap_type_names, this->type);
987: }
988:
989: return &this->public;
990: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>