17f0cd46468d787caab3af5202dce9ca9873edcc
[strongswan.git] / src / libcharon / plugins / tnc_pdp / tnc_pdp.c
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 }