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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2018 Tobias Brunner
                      3:  * Copyright (C) 2009 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "eap_radius.h"
                     18: #include "eap_radius_plugin.h"
                     19: #include "eap_radius_forward.h"
                     20: #include "eap_radius_provider.h"
                     21: #include "eap_radius_accounting.h"
                     22: 
                     23: #include <radius_message.h>
                     24: #include <radius_client.h>
                     25: #include <bio/bio_writer.h>
                     26: 
                     27: #include <daemon.h>
                     28: 
                     29: typedef struct private_eap_radius_t private_eap_radius_t;
                     30: 
                     31: /**
                     32:  * Private data of an eap_radius_t object.
                     33:  */
                     34: struct private_eap_radius_t {
                     35: 
                     36:        /**
                     37:         * Public authenticator_t interface.
                     38:         */
                     39:        eap_radius_t public;
                     40: 
                     41:        /**
                     42:         * ID of the server
                     43:         */
                     44:        identification_t *server;
                     45: 
                     46:        /**
                     47:         * ID of the peer
                     48:         */
                     49:        identification_t *peer;
                     50: 
                     51:        /**
                     52:         * EAP method type we are proxying
                     53:         */
                     54:        eap_type_t type;
                     55: 
                     56:        /**
                     57:         * EAP vendor, if any
                     58:         */
                     59:        uint32_t vendor;
                     60: 
                     61:        /**
                     62:         * EAP message identifier
                     63:         */
                     64:        uint8_t identifier;
                     65: 
                     66:        /**
                     67:         * RADIUS client instance
                     68:         */
                     69:        radius_client_t *client;
                     70: 
                     71:        /**
                     72:         * TRUE to use EAP-Start, FALSE to send EAP-Identity Response directly
                     73:         */
                     74:        bool eap_start;
                     75: 
                     76:        /**
                     77:         * Prefix to prepend to EAP identity
                     78:         */
                     79:        char *id_prefix;
                     80: };
                     81: 
                     82: /**
                     83:  * Add EAP-Identity to RADIUS message
                     84:  */
                     85: static void add_eap_identity(private_eap_radius_t *this,
                     86:                                                         radius_message_t *request)
                     87: {
                     88:        struct {
                     89:                /** EAP code (REQUEST/RESPONSE) */
                     90:                uint8_t code;
                     91:                /** unique message identifier */
                     92:                uint8_t identifier;
                     93:                /** length of whole message */
                     94:                uint16_t length;
                     95:                /** EAP type */
                     96:                uint8_t type;
                     97:                /** identity data */
                     98:                uint8_t data[];
                     99:        } __attribute__((__packed__)) *hdr;
                    100:        chunk_t id, prefix;
                    101:        size_t len;
                    102: 
                    103:        id = this->peer->get_encoding(this->peer);
                    104:        prefix = chunk_create(this->id_prefix, strlen(this->id_prefix));
                    105:        len = sizeof(*hdr) + prefix.len + id.len;
                    106: 
                    107:        hdr = alloca(len);
                    108:        hdr->code = EAP_RESPONSE;
                    109:        hdr->identifier = this->identifier;
                    110:        hdr->length = htons(len);
                    111:        hdr->type = EAP_IDENTITY;
                    112:        memcpy(hdr->data, prefix.ptr, prefix.len);
                    113:        memcpy(hdr->data + prefix.len, id.ptr, id.len);
                    114: 
                    115:        request->add(request, RAT_EAP_MESSAGE, chunk_create((u_char*)hdr, len));
                    116: }
                    117: 
                    118: /**
                    119:  * Copy EAP-Message attribute from RADIUS message to an new EAP payload
                    120:  */
                    121: static bool radius2ike(private_eap_radius_t *this,
                    122:                                           radius_message_t *msg, eap_payload_t **out)
                    123: {
                    124:        enumerator_t *enumerator;
                    125:        eap_payload_t *payload;
                    126:        chunk_t data, message = chunk_empty;
                    127:        int type;
                    128: 
                    129:        enumerator = msg->create_enumerator(msg);
                    130:        while (enumerator->enumerate(enumerator, &type, &data))
                    131:        {
                    132:                if (type == RAT_EAP_MESSAGE && data.len)
                    133:                {
                    134:                        message = chunk_cat("mc", message, data);
                    135:                }
                    136:        }
                    137:        enumerator->destroy(enumerator);
                    138:        if (message.len)
                    139:        {
                    140:                *out = payload = eap_payload_create_data(message);
                    141: 
                    142:                /* apply EAP method selected by RADIUS server */
                    143:                this->type = payload->get_type(payload, &this->vendor);
                    144: 
                    145:                DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &message);
                    146:                free(message.ptr);
                    147:                return TRUE;
                    148:        }
                    149:        return FALSE;
                    150: }
                    151: 
                    152: /**
                    153:  * See header.
                    154:  */
                    155: void eap_radius_build_attributes(radius_message_t *request)
                    156: {
                    157:        ike_sa_t *ike_sa;
                    158:        host_t *host;
                    159:        char buf[40], *station_id_fmt, *session_id;
                    160:        uint32_t value;
                    161:        chunk_t chunk;
                    162: 
                    163:        /* virtual NAS-Port-Type */
                    164:        value = htonl(5);
                    165:        request->add(request, RAT_NAS_PORT_TYPE, chunk_from_thing(value));
                    166:        /* framed ServiceType */
                    167:        value = htonl(2);
                    168:        request->add(request, RAT_SERVICE_TYPE, chunk_from_thing(value));
                    169: 
                    170:        ike_sa = charon->bus->get_sa(charon->bus);
                    171:        if (ike_sa)
                    172:        {
                    173:                value = htonl(ike_sa->get_unique_id(ike_sa));
                    174:                request->add(request, RAT_NAS_PORT, chunk_from_thing(value));
                    175:                request->add(request, RAT_NAS_PORT_ID,
                    176:                                         chunk_from_str(ike_sa->get_name(ike_sa)));
                    177: 
                    178:                host = ike_sa->get_my_host(ike_sa);
                    179:                chunk = host->get_address(host);
                    180:                switch (host->get_family(host))
                    181:                {
                    182:                        case AF_INET:
                    183:                                request->add(request, RAT_NAS_IP_ADDRESS, chunk);
                    184:                                break;
                    185:                        case AF_INET6:
                    186:                                request->add(request, RAT_NAS_IPV6_ADDRESS, chunk);
                    187:                        default:
                    188:                                break;
                    189:                }
                    190:                if (lib->settings->get_bool(lib->settings,
                    191:                                                                        "%s.plugins.eap-radius.station_id_with_port",
                    192:                                                                        TRUE, lib->ns))
                    193:                {
                    194:                        station_id_fmt = "%#H";
                    195:                }
                    196:                else
                    197:                {
                    198:                        station_id_fmt = "%H";
                    199:                }
                    200:                snprintf(buf, sizeof(buf), station_id_fmt, host);
                    201:                request->add(request, RAT_CALLED_STATION_ID, chunk_from_str(buf));
                    202:                host = ike_sa->get_other_host(ike_sa);
                    203:                snprintf(buf, sizeof(buf), station_id_fmt, host);
                    204:                request->add(request, RAT_CALLING_STATION_ID, chunk_from_str(buf));
                    205: 
                    206:                session_id = eap_radius_accounting_session_id(ike_sa);
                    207:                if (session_id)
                    208:                {
                    209:                        request->add(request, RAT_ACCT_SESSION_ID,
                    210:                                                 chunk_from_str(session_id));
                    211:                        free(session_id);
                    212:                }
                    213:        }
                    214: }
                    215: 
                    216: /**
                    217:  * Add a set of RADIUS attributes to a request message
                    218:  */
                    219: static void add_radius_request_attrs(private_eap_radius_t *this,
                    220:                                                                         radius_message_t *request)
                    221: {
                    222:        chunk_t chunk;
                    223: 
                    224:        chunk = chunk_from_str(this->id_prefix);
                    225:        chunk = chunk_cata("cc", chunk, this->peer->get_encoding(this->peer));
                    226:        request->add(request, RAT_USER_NAME, chunk);
                    227: 
                    228:        eap_radius_build_attributes(request);
                    229:        eap_radius_forward_from_ike(request);
                    230: }
                    231: 
                    232: METHOD(eap_method_t, initiate, status_t,
                    233:        private_eap_radius_t *this, eap_payload_t **out)
                    234: {
                    235:        radius_message_t *request, *response;
                    236:        status_t status = FAILED;
                    237: 
                    238:        request = radius_message_create(RMC_ACCESS_REQUEST);
                    239:        add_radius_request_attrs(this, request);
                    240: 
                    241:        if (this->eap_start)
                    242:        {
                    243:                request->add(request, RAT_EAP_MESSAGE, chunk_empty);
                    244:        }
                    245:        else
                    246:        {
                    247:                add_eap_identity(this, request);
                    248:        }
                    249: 
                    250:        response = this->client->request(this->client, request);
                    251:        if (response)
                    252:        {
                    253:                eap_radius_forward_to_ike(response);
                    254:                switch (response->get_code(response))
                    255:                {
                    256:                        case RMC_ACCESS_CHALLENGE:
                    257:                                if (radius2ike(this, response, out))
                    258:                                {
                    259:                                        status = NEED_MORE;
                    260:                                }
                    261:                                break;
                    262:                        case RMC_ACCESS_ACCEPT:
                    263:                                /* Microsoft RADIUS servers can run in a mode where they respond
                    264:                                 * like this on the first request (i.e. without authentication),
                    265:                                 * we treat this as Access-Reject */
                    266:                        case RMC_ACCESS_REJECT:
                    267:                        default:
                    268:                                DBG1(DBG_IKE, "RADIUS authentication of '%Y' failed",
                    269:                                         this->peer);
                    270:                                break;
                    271:                }
                    272:                response->destroy(response);
                    273:        }
                    274:        else
                    275:        {
                    276:                eap_radius_handle_timeout(NULL);
                    277:        }
                    278:        request->destroy(request);
                    279:        return status;
                    280: }
                    281: 
                    282: /**
                    283:  * Handle the Class attribute
                    284:  */
                    285: static void process_class(radius_message_t *msg)
                    286: {
                    287:        enumerator_t *enumerator;
                    288:        ike_sa_t *ike_sa;
                    289:        identification_t *id;
                    290:        auth_cfg_t *auth;
                    291:        chunk_t data;
                    292:        bool class_group, class_send;
                    293:        int type;
                    294: 
                    295:        class_group = lib->settings->get_bool(lib->settings,
                    296:                                "%s.plugins.eap-radius.class_group", FALSE, lib->ns);
                    297:        class_send = lib->settings->get_bool(lib->settings,
                    298:                                "%s.plugins.eap-radius.accounting_send_class", FALSE, lib->ns);
                    299:        ike_sa = charon->bus->get_sa(charon->bus);
                    300: 
                    301:        if ((!class_group && !class_send) || !ike_sa)
                    302:        {
                    303:                return;
                    304:        }
                    305: 
                    306:        enumerator = msg->create_enumerator(msg);
                    307:        while (enumerator->enumerate(enumerator, &type, &data))
                    308:        {
                    309:                if (type == RAT_CLASS)
                    310:                {
                    311:                        if (class_group && data.len < 44)
                    312:                        {       /* quirk: ignore long class attributes, these are used for
                    313:                                 * other purposes by some RADIUS servers (such as NPS). */
                    314:                                auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
                    315:                                id = identification_create_from_data(data);
                    316:                                DBG1(DBG_CFG, "received group membership '%Y' from RADIUS",
                    317:                                         id);
                    318:                                auth->add(auth, AUTH_RULE_GROUP, id);
                    319:                        }
                    320:                        if (class_send)
                    321:                        {
                    322:                                eap_radius_accounting_add_class(ike_sa, data);
                    323:                        }
                    324:                }
                    325:        }
                    326:        enumerator->destroy(enumerator);
                    327: }
                    328: 
                    329: /**
                    330:  * Handle the Filter-Id attribute as IPsec CHILD_SA name
                    331:  */
                    332: static void process_filter_id(radius_message_t *msg)
                    333: {
                    334:        enumerator_t *enumerator;
                    335:        int type;
                    336:        uint8_t tunnel_tag;
                    337:        uint32_t tunnel_type;
                    338:        chunk_t filter_id = chunk_empty, data;
                    339:        bool is_esp_tunnel = FALSE;
                    340: 
                    341:        enumerator = msg->create_enumerator(msg);
                    342:        while (enumerator->enumerate(enumerator, &type, &data))
                    343:        {
                    344:                switch (type)
                    345:                {
                    346:                        case RAT_TUNNEL_TYPE:
                    347:                                if (data.len != 4)
                    348:                                {
                    349:                                        continue;
                    350:                                }
                    351:                                tunnel_tag = *data.ptr;
                    352:                                *data.ptr = 0x00;
                    353:                                tunnel_type = untoh32(data.ptr);
                    354:                                DBG1(DBG_IKE, "received RADIUS attribute Tunnel-Type: "
                    355:                                                          "tag = %u, value = %u", tunnel_tag, tunnel_type);
                    356:                                is_esp_tunnel = (tunnel_type == RADIUS_TUNNEL_TYPE_ESP);
                    357:                                break;
                    358:                        case RAT_FILTER_ID:
                    359:                                filter_id = data;
                    360:                                DBG1(DBG_IKE, "received RADIUS attribute Filter-Id: "
                    361:                                                          "'%.*s'", (int)filter_id.len, filter_id.ptr);
                    362:                                break;
                    363:                        default:
                    364:                                break;
                    365:                }
                    366:        }
                    367:        enumerator->destroy(enumerator);
                    368: 
                    369:        if (is_esp_tunnel && filter_id.len)
                    370:        {
                    371:                identification_t *id;
                    372:                ike_sa_t *ike_sa;
                    373:                auth_cfg_t *auth;
                    374: 
                    375:                ike_sa = charon->bus->get_sa(charon->bus);
                    376:                if (ike_sa)
                    377:                {
                    378:                        auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
                    379:                        id = identification_create_from_data(filter_id);
                    380:                        auth->add(auth, AUTH_RULE_GROUP, id);
                    381:                }
                    382:        }
                    383: }
                    384: 
                    385: /**
                    386:  * Handle Session-Timeout attribute and Interim updates
                    387:  */
                    388: static void process_timeout(radius_message_t *msg)
                    389: {
                    390:        enumerator_t *enumerator;
                    391:        ike_sa_t *ike_sa;
                    392:        chunk_t data;
                    393:        int type;
                    394: 
                    395:        ike_sa = charon->bus->get_sa(charon->bus);
                    396:        if (ike_sa)
                    397:        {
                    398:                enumerator = msg->create_enumerator(msg);
                    399:                while (enumerator->enumerate(enumerator, &type, &data))
                    400:                {
                    401:                        if (type == RAT_SESSION_TIMEOUT && data.len == 4)
                    402:                        {
                    403:                                ike_sa->set_auth_lifetime(ike_sa, untoh32(data.ptr));
                    404:                        }
                    405:                        else if (type == RAT_ACCT_INTERIM_INTERVAL && data.len == 4)
                    406:                        {
                    407:                                eap_radius_accounting_start_interim(ike_sa, untoh32(data.ptr));
                    408:                        }
                    409:                }
                    410:                enumerator->destroy(enumerator);
                    411:        }
                    412: }
                    413: 
                    414: /**
                    415:  * Add a Cisco Unity configuration attribute
                    416:  */
                    417: static void add_unity_attribute(eap_radius_provider_t *provider, uint32_t id,
                    418:                                                                int type, chunk_t data)
                    419: {
                    420:        switch (type)
                    421:        {
                    422:                case 15: /* CVPN3000-IPSec-Banner1 */
                    423:                case 36: /* CVPN3000-IPSec-Banner2 */
                    424:                        provider->add_attribute(provider, id, UNITY_BANNER, data);
                    425:                        break;
                    426:                case 28: /* CVPN3000-IPSec-Default-Domain */
                    427:                        provider->add_attribute(provider, id, UNITY_DEF_DOMAIN, data);
                    428:                        break;
                    429:                case 29: /* CVPN3000-IPSec-Split-DNS-Names */
                    430:                        provider->add_attribute(provider, id, UNITY_SPLITDNS_NAME, data);
                    431:                        break;
                    432:        }
                    433: }
                    434: 
                    435: /**
                    436:  * Add a DNS/NBNS configuration attribute
                    437:  */
                    438: static void add_nameserver_attribute(eap_radius_provider_t *provider,
                    439:                                                                         uint32_t id, int type, chunk_t data)
                    440: {
                    441:        /* these are from different vendors, but there is currently no conflict */
                    442:        switch (type)
                    443:        {
                    444:                case  5: /* CVPN3000-Primary-DNS */
                    445:                case  6: /* CVPN3000-Secondary-DNS */
                    446:                case 28: /* MS-Primary-DNS-Server */
                    447:                case 29: /* MS-Secondary-DNS-Server */
                    448:                        provider->add_attribute(provider, id, INTERNAL_IP4_DNS, data);
                    449:                        break;
                    450:                case  7: /* CVPN3000-Primary-WINS */
                    451:                case  8: /* CVPN3000-Secondary-WINS */
                    452:                case 30: /* MS-Primary-NBNS-Server */
                    453:                case 31: /* MS-Secondary-NBNS-Server */
                    454:                        provider->add_attribute(provider, id, INTERNAL_IP4_NBNS, data);
                    455:                        break;
                    456:                case RAT_FRAMED_IPV6_DNS_SERVER:
                    457:                        provider->add_attribute(provider, id, INTERNAL_IP6_DNS, data);
                    458:                        break;
                    459:        }
                    460: }
                    461: 
                    462: /**
                    463:  * Add a UNITY_LOCAL_LAN or UNITY_SPLIT_INCLUDE attribute
                    464:  */
                    465: static void add_unity_split_attribute(eap_radius_provider_t *provider,
                    466:                                                        uint32_t id, configuration_attribute_type_t type,
                    467:                                                        chunk_t data)
                    468: {
                    469:        enumerator_t *enumerator;
                    470:        bio_writer_t *writer;
                    471:        char buffer[256], *token, *slash;
                    472: 
                    473:        if (snprintf(buffer, sizeof(buffer), "%.*s", (int)data.len,
                    474:                                 data.ptr) >= sizeof(buffer))
                    475:        {
                    476:                return;
                    477:        }
                    478:        writer = bio_writer_create(16); /* two IPv4 addresses and 6 bytes padding */
                    479:        enumerator = enumerator_create_token(buffer, ",", " ");
                    480:        while (enumerator->enumerate(enumerator, &token))
                    481:        {
                    482:                host_t *net, *mask = NULL;
                    483:                chunk_t padding;
                    484: 
                    485:                slash = strchr(token, '/');
                    486:                if (slash)
                    487:                {
                    488:                        *slash++ = '\0';
                    489:                        mask = host_create_from_string(slash, 0);
                    490:                }
                    491:                if (!mask)
                    492:                {       /* default to /32 */
                    493:                        mask = host_create_from_string("255.255.255.255", 0);
                    494:                }
                    495:                net = host_create_from_string(token, 0);
                    496:                if (!net || net->get_family(net) != AF_INET ||
                    497:                         mask->get_family(mask) != AF_INET)
                    498:                {
                    499:                        mask->destroy(mask);
                    500:                        DESTROY_IF(net);
                    501:                        continue;
                    502:                }
                    503:                writer->write_data(writer, net->get_address(net));
                    504:                writer->write_data(writer, mask->get_address(mask));
                    505:                padding = writer->skip(writer, 6); /* 6 bytes padding */
                    506:                memset(padding.ptr, 0, padding.len);
                    507:                mask->destroy(mask);
                    508:                net->destroy(net);
                    509:        }
                    510:        enumerator->destroy(enumerator);
                    511: 
                    512:        data = writer->get_buf(writer);
                    513:        if (data.len)
                    514:        {
                    515:                provider->add_attribute(provider, id, type, data);
                    516:        }
                    517:        writer->destroy(writer);
                    518: }
                    519: 
                    520: /**
                    521:  * Handle Framed-IP-Address and other IKE configuration attributes
                    522:  */
                    523: static void process_cfg_attributes(radius_message_t *msg)
                    524: {
                    525:        eap_radius_provider_t *provider;
                    526:        enumerator_t *enumerator;
                    527:        ike_sa_t *ike_sa;
                    528:        host_t *host;
                    529:        chunk_t data;
                    530:        configuration_attribute_type_t split_type = 0;
                    531:        int type, vendor;
                    532: 
                    533:        ike_sa = charon->bus->get_sa(charon->bus);
                    534:        provider = eap_radius_provider_get();
                    535:        if (provider && ike_sa)
                    536:        {
                    537:                enumerator = msg->create_enumerator(msg);
                    538:                while (enumerator->enumerate(enumerator, &type, &data))
                    539:                {
                    540:                        if ((type == RAT_FRAMED_IP_ADDRESS && data.len == 4) ||
                    541:                                (type == RAT_FRAMED_IPV6_ADDRESS && data.len == 16))
                    542:                        {
                    543:                                host = host_create_from_chunk(AF_UNSPEC, data, 0);
                    544:                                if (host)
                    545:                                {
                    546:                                        provider->add_framed_ip(provider,
                    547:                                                                        ike_sa->get_unique_id(ike_sa), host);
                    548:                                }
                    549:                        }
                    550:                        else if (type == RAT_FRAMED_IP_NETMASK && data.len == 4)
                    551:                        {
                    552:                                provider->add_attribute(provider, ike_sa->get_unique_id(ike_sa),
                    553:                                                                                INTERNAL_IP4_NETMASK, data);
                    554:                        }
                    555:                        else if (type == RAT_FRAMED_IPV6_DNS_SERVER && data.len == 16)
                    556:                        {
                    557:                                add_nameserver_attribute(provider,
                    558:                                                                        ike_sa->get_unique_id(ike_sa), type, data);
                    559:                        }
                    560:                }
                    561:                enumerator->destroy(enumerator);
                    562: 
                    563:                enumerator = msg->create_vendor_enumerator(msg);
                    564:                while (enumerator->enumerate(enumerator, &vendor, &type, &data))
                    565:                {
                    566:                        if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */)
                    567:                        {
                    568:                                switch (type)
                    569:                                {
                    570:                                        case  5: /* CVPN3000-Primary-DNS */
                    571:                                        case  6: /* CVPN3000-Secondary-DNS */
                    572:                                        case  7: /* CVPN3000-Primary-WINS */
                    573:                                        case  8: /* CVPN3000-Secondary-WINS */
                    574:                                                if (data.len == 4)
                    575:                                                {
                    576:                                                        add_nameserver_attribute(provider,
                    577:                                                                        ike_sa->get_unique_id(ike_sa), type, data);
                    578:                                                }
                    579:                                                break;
                    580:                                        case 15: /* CVPN3000-IPSec-Banner1 */
                    581:                                        case 28: /* CVPN3000-IPSec-Default-Domain */
                    582:                                        case 29: /* CVPN3000-IPSec-Split-DNS-Names */
                    583:                                        case 36: /* CVPN3000-IPSec-Banner2 */
                    584:                                                if (ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
                    585:                                                {
                    586:                                                        add_unity_attribute(provider,
                    587:                                                                        ike_sa->get_unique_id(ike_sa), type, data);
                    588:                                                }
                    589:                                                break;
                    590:                                        case 55: /* CVPN3000-IPSec-Split-Tunneling-Policy */
                    591:                                                if (data.len)
                    592:                                                {
                    593:                                                        switch (data.ptr[data.len - 1])
                    594:                                                        {
                    595:                                                                case 0: /* tunnelall */
                    596:                                                                default:
                    597:                                                                        break;
                    598:                                                                case 1: /* tunnelspecified */
                    599:                                                                        split_type = UNITY_SPLIT_INCLUDE;
                    600:                                                                        break;
                    601:                                                                case 2: /* excludespecified */
                    602:                                                                        split_type = UNITY_LOCAL_LAN;
                    603:                                                                        break;
                    604:                                                        }
                    605:                                                }
                    606:                                                break;
                    607:                                        default:
                    608:                                                break;
                    609:                                }
                    610:                        }
                    611:                        if (vendor == PEN_MICROSOFT)
                    612:                        {
                    613:                                switch (type)
                    614:                                {
                    615:                                        case 28: /* MS-Primary-DNS-Server */
                    616:                                        case 29: /* MS-Secondary-DNS-Server */
                    617:                                        case 30: /* MS-Primary-NBNS-Server */
                    618:                                        case 31: /* MS-Secondary-NBNS-Server */
                    619:                                                if (data.len == 4)
                    620:                                                {
                    621:                                                        add_nameserver_attribute(provider,
                    622:                                                                        ike_sa->get_unique_id(ike_sa), type, data);
                    623:                                                }
                    624:                                                break;
                    625:                                }
                    626:                        }
                    627:                }
                    628:                enumerator->destroy(enumerator);
                    629: 
                    630:                if (split_type != 0 &&
                    631:                        ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
                    632:                {
                    633:                        enumerator = msg->create_vendor_enumerator(msg);
                    634:                        while (enumerator->enumerate(enumerator, &vendor, &type, &data))
                    635:                        {
                    636:                                if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */ &&
                    637:                                        type == 27 /* CVPN3000-IPSec-Split-Tunnel-List */)
                    638:                                {
                    639:                                        add_unity_split_attribute(provider,
                    640:                                                        ike_sa->get_unique_id(ike_sa), split_type, data);
                    641:                                }
                    642:                        }
                    643:                        enumerator->destroy(enumerator);
                    644:                }
                    645:        }
                    646: }
                    647: 
                    648: /**
                    649:  * See header.
                    650:  */
                    651: void eap_radius_process_attributes(radius_message_t *message)
                    652: {
                    653:        process_class(message);
                    654:        if (lib->settings->get_bool(lib->settings,
                    655:                                                "%s.plugins.eap-radius.filter_id", FALSE, lib->ns))
                    656:        {
                    657:                process_filter_id(message);
                    658:        }
                    659:        process_timeout(message);
                    660:        process_cfg_attributes(message);
                    661: }
                    662: 
                    663: METHOD(eap_method_t, process, status_t,
                    664:        private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out)
                    665: {
                    666:        radius_message_t *request, *response;
                    667:        status_t status = FAILED;
                    668:        chunk_t data;
                    669: 
                    670:        request = radius_message_create(RMC_ACCESS_REQUEST);
                    671:        add_radius_request_attrs(this, request);
                    672: 
                    673:        data = in->get_data(in);
                    674:        DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &data);
                    675: 
                    676:        /* fragment data suitable for RADIUS */
                    677:        while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE)
                    678:        {
                    679:                request->add(request, RAT_EAP_MESSAGE,
                    680:                                         chunk_create(data.ptr,MAX_RADIUS_ATTRIBUTE_SIZE));
                    681:                data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE);
                    682:        }
                    683:        request->add(request, RAT_EAP_MESSAGE, data);
                    684: 
                    685:        response = this->client->request(this->client, request);
                    686:        if (response)
                    687:        {
                    688:                eap_radius_forward_to_ike(response);
                    689:                switch (response->get_code(response))
                    690:                {
                    691:                        case RMC_ACCESS_CHALLENGE:
                    692:                                if (radius2ike(this, response, out))
                    693:                                {
                    694:                                        status = NEED_MORE;
                    695:                                        break;
                    696:                                }
                    697:                                status = FAILED;
                    698:                                break;
                    699:                        case RMC_ACCESS_ACCEPT:
                    700:                                eap_radius_process_attributes(response);
                    701:                                DBG1(DBG_IKE, "RADIUS authentication of '%Y' successful",
                    702:                                         this->peer);
                    703:                                status = SUCCESS;
                    704:                                break;
                    705:                        case RMC_ACCESS_REJECT:
                    706:                        default:
                    707:                                DBG1(DBG_IKE, "RADIUS authentication of '%Y' failed",
                    708:                                         this->peer);
                    709:                                status = FAILED;
                    710:                                break;
                    711:                }
                    712:                response->destroy(response);
                    713:        }
                    714:        request->destroy(request);
                    715:        return status;
                    716: }
                    717: 
                    718: METHOD(eap_method_t, get_type, eap_type_t,
                    719:        private_eap_radius_t *this, uint32_t *vendor)
                    720: {
                    721:        *vendor = this->vendor;
                    722:        return this->type;
                    723: }
                    724: 
                    725: METHOD(eap_method_t, get_msk, status_t,
                    726:        private_eap_radius_t *this, chunk_t *out)
                    727: {
                    728:        chunk_t msk;
                    729: 
                    730:        msk = this->client->get_msk(this->client);
                    731:        if (msk.len)
                    732:        {
                    733:                *out = msk;
                    734:                return SUCCESS;
                    735:        }
                    736:        return FAILED;
                    737: }
                    738: 
                    739: METHOD(eap_method_t, get_identifier, uint8_t,
                    740:        private_eap_radius_t *this)
                    741: {
                    742:        return this->identifier;
                    743: }
                    744: 
                    745: METHOD(eap_method_t, set_identifier, void,
                    746:        private_eap_radius_t *this, uint8_t identifier)
                    747: {
                    748:        this->identifier = identifier;
                    749: }
                    750: 
                    751: METHOD(eap_method_t, is_mutual, bool,
                    752:        private_eap_radius_t *this)
                    753: {
                    754:        switch (this->type)
                    755:        {
                    756:                case EAP_AKA:
                    757:                case EAP_SIM:
                    758:                        return TRUE;
                    759:                default:
                    760:                        return FALSE;
                    761:        }
                    762: }
                    763: 
                    764: METHOD(eap_method_t, destroy, void,
                    765:        private_eap_radius_t *this)
                    766: {
                    767:        this->peer->destroy(this->peer);
                    768:        this->server->destroy(this->server);
                    769:        this->client->destroy(this->client);
                    770:        free(this);
                    771: }
                    772: 
                    773: /**
                    774:  * Generic constructor
                    775:  */
                    776: eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer)
                    777: {
                    778:        private_eap_radius_t *this;
                    779: 
                    780:        INIT(this,
                    781:                .public = {
                    782:                        .eap_method = {
                    783:                                .initiate = _initiate,
                    784:                                .process = _process,
                    785:                                .get_type = _get_type,
                    786:                                .is_mutual = _is_mutual,
                    787:                                .get_msk = _get_msk,
                    788:                                .get_identifier = _get_identifier,
                    789:                                .set_identifier = _set_identifier,
                    790:                                .destroy = _destroy,
                    791:                        },
                    792:                },
                    793:                /* initially EAP_RADIUS, but is set to the method selected by RADIUS */
                    794:                .type = EAP_RADIUS,
                    795:                .eap_start = lib->settings->get_bool(lib->settings,
                    796:                                                                        "%s.plugins.eap-radius.eap_start", FALSE,
                    797:                                                                        lib->ns),
                    798:                .id_prefix = lib->settings->get_str(lib->settings,
                    799:                                                                        "%s.plugins.eap-radius.id_prefix", "",
                    800:                                                                        lib->ns),
                    801:        );
                    802:        this->client = eap_radius_create_client();
                    803:        if (!this->client)
                    804:        {
                    805:                free(this);
                    806:                return NULL;
                    807:        }
                    808:        this->peer = peer->clone(peer);
                    809:        this->server = server->clone(server);
                    810:        return &this->public;
                    811: }

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