Return to tnc_pdp.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / tnc_pdp |
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: }