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