Annotation of embedaddon/strongswan/src/libcharon/plugins/tnc_pdp/tnc_pdp.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>