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