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

1.1       misho       1: /*
                      2:  * Copyright (C) 2010-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 "eap_tnc.h"
                     17: 
                     18: #include <tnc/tnc.h>
                     19: #include <tnc/tnccs/tnccs_manager.h>
                     20: #include <tls_eap.h>
                     21: #include <utils/debug.h>
                     22: #include <daemon.h>
                     23: 
                     24: #include <tncifimv.h>
                     25: #include <tncif_names.h>
                     26: 
                     27: /**
                     28:  * Maximum size of an EAP-TNC message
                     29:  */
                     30: #define EAP_TNC_MAX_MESSAGE_LEN 65535
                     31: 
                     32: /**
                     33:  * Maximum number of EAP-TNC messages allowed
                     34:  */
                     35: #define EAP_TNC_MAX_MESSAGE_COUNT 10
                     36: 
                     37: typedef struct private_eap_tnc_t private_eap_tnc_t;
                     38: 
                     39: /**
                     40:  * Private data of an eap_tnc_t object.
                     41:  */
                     42: struct private_eap_tnc_t {
                     43: 
                     44:        /**
                     45:         * Public authenticator_t interface.
                     46:         */
                     47:        eap_tnc_t public;
                     48: 
                     49:        /**
                     50:         * Inner EAP authentication type
                     51:         */
                     52:        eap_type_t type;
                     53: 
                     54:        /**
                     55:         * Outer EAP authentication type
                     56:         */
                     57:        eap_type_t auth_type;
                     58: 
                     59:        /**
                     60:         * TLS stack, wrapped by EAP helper
                     61:         */
                     62:        tls_eap_t *tls_eap;
                     63: 
                     64:        /**
                     65:         * TNCCS instance running over EAP-TNC
                     66:         */
                     67:        tnccs_t *tnccs;
                     68: 
                     69: };
                     70: 
                     71: /**
                     72:  * Callback function to get recommendation from TNCCS connection
                     73:  */
                     74: static bool enforce_recommendation(TNC_IMV_Action_Recommendation rec,
                     75:                                                                   TNC_IMV_Evaluation_Result eval)
                     76: {
                     77:        char *group;
                     78:        identification_t *id;
                     79:        ike_sa_t *ike_sa;
                     80:        auth_cfg_t *auth;
                     81:        bool no_access = FALSE;
                     82: 
                     83:        DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'",
                     84:                 TNC_IMV_Action_Recommendation_names, rec,
                     85:                 TNC_IMV_Evaluation_Result_names, eval);
                     86: 
                     87:        switch (rec)
                     88:        {
                     89:                case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
                     90:                        group = "allow";
                     91:                        break;
                     92:                case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
                     93:                        group = "isolate";
                     94:                        break;
                     95:                case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
                     96:                case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
                     97:                default:
                     98:                        group = "no access";
                     99:                        no_access = TRUE;
                    100:                        break;
                    101:        }
                    102: 
                    103:        ike_sa = charon->bus->get_sa(charon->bus);
                    104:        if (!ike_sa)
                    105:        {
                    106:                DBG1(DBG_TNC, "policy enforcement point did not find IKE_SA");
                    107:                return FALSE;
                    108:        }
                    109: 
                    110:        id = ike_sa->get_other_id(ike_sa);
                    111:        DBG0(DBG_TNC, "policy enforced on peer '%Y' is '%s'", id, group);
                    112: 
                    113:        if (no_access)
                    114:        {
                    115:                return FALSE;
                    116:        }
                    117:        else
                    118:        {
                    119:                auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
                    120:                id = identification_create_from_string(group);
                    121:                auth->add(auth, AUTH_RULE_GROUP, id);
                    122:                DBG1(DBG_TNC, "policy enforcement point added group membership '%s'",
                    123:                         group);
                    124:        }
                    125:        return TRUE;
                    126: }
                    127: 
                    128: METHOD(eap_method_t, initiate, status_t,
                    129:        private_eap_tnc_t *this, eap_payload_t **out)
                    130: {
                    131:        chunk_t data;
                    132:        uint32_t auth_type;
                    133: 
                    134:        /* Determine TNC Client Authentication Type */
                    135:        switch (this->auth_type)
                    136:        {
                    137:                case EAP_TLS:
                    138:                case EAP_TTLS:
                    139:                case EAP_PEAP:
                    140:                        auth_type = TNC_AUTH_X509_CERT;
                    141:                        break;
                    142:                case EAP_MD5:
                    143:                case EAP_MSCHAPV2:
                    144:                case EAP_GTC:
                    145:                case EAP_OTP:
                    146:                        auth_type = TNC_AUTH_PASSWORD;
                    147:                        break;
                    148:                case EAP_SIM:
                    149:                case EAP_AKA:
                    150:                        auth_type = TNC_AUTH_SIM;
                    151:                        break;
                    152:                default:
                    153:                        auth_type = TNC_AUTH_UNKNOWN;
                    154:        }
                    155:        this->tnccs->set_auth_type(this->tnccs, auth_type);
                    156: 
                    157:        if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE)
                    158:        {
                    159:                *out = eap_payload_create_data(data);
                    160:                free(data.ptr);
                    161:                return NEED_MORE;
                    162:        }
                    163:        return FAILED;
                    164: }
                    165: 
                    166: METHOD(eap_method_t, process, status_t,
                    167:        private_eap_tnc_t *this, eap_payload_t *in, eap_payload_t **out)
                    168: {
                    169:        status_t status;
                    170:        chunk_t data;
                    171: 
                    172:        data = in->get_data(in);
                    173:        status = this->tls_eap->process(this->tls_eap, data, &data);
                    174:        if (status == NEED_MORE)
                    175:        {
                    176:                *out = eap_payload_create_data(data);
                    177:                free(data.ptr);
                    178:        }
                    179:        return status;
                    180: }
                    181: 
                    182: METHOD(eap_method_t, get_type, eap_type_t,
                    183:        private_eap_tnc_t *this, uint32_t *vendor)
                    184: {
                    185:        *vendor = 0;
                    186:        return this->type;
                    187: }
                    188: 
                    189: METHOD(eap_method_t, get_msk, status_t,
                    190:        private_eap_tnc_t *this, chunk_t *msk)
                    191: {
                    192:        *msk = this->tls_eap->get_msk(this->tls_eap);
                    193:        if (msk->len)
                    194:        {
                    195:                return SUCCESS;
                    196:        }
                    197:        return FAILED;
                    198: }
                    199: 
                    200: METHOD(eap_method_t, get_identifier, uint8_t,
                    201:        private_eap_tnc_t *this)
                    202: {
                    203:        return this->tls_eap->get_identifier(this->tls_eap);
                    204: }
                    205: 
                    206: METHOD(eap_method_t, set_identifier, void,
                    207:        private_eap_tnc_t *this, uint8_t identifier)
                    208: {
                    209:        this->tls_eap->set_identifier(this->tls_eap, identifier);
                    210: }
                    211: 
                    212: METHOD(eap_method_t, is_mutual, bool,
                    213:        private_eap_tnc_t *this)
                    214: {
                    215:        return FALSE;
                    216: }
                    217: 
                    218: METHOD(eap_method_t, destroy, void,
                    219:        private_eap_tnc_t *this)
                    220: {
                    221:        chunk_t pdp_server;
                    222:        uint16_t pdp_port;
                    223:        tls_t *tls;
                    224: 
                    225:        pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port);
                    226:        if (pdp_server.len)
                    227:        {
                    228:                DBG2(DBG_TNC, "TODO: setup PT-TLS connection to %.*s:%u",
                    229:                         pdp_server.len, pdp_server.ptr, pdp_port);
                    230:        }
                    231:        tls = &this->tnccs->tls;
                    232:        tls->destroy(tls);
                    233:        this->tls_eap->destroy(this->tls_eap);
                    234:        free(this);
                    235: }
                    236: 
                    237: METHOD(eap_inner_method_t, get_auth_type, eap_type_t,
                    238:        private_eap_tnc_t *this)
                    239: {
                    240:        return this->auth_type;
                    241: }
                    242: 
                    243: METHOD(eap_inner_method_t, set_auth_type, void,
                    244:        private_eap_tnc_t *this, eap_type_t type)
                    245: {
                    246:        this->auth_type = type;
                    247: }
                    248: 
                    249: /**
                    250:  * Generic private constructor
                    251:  */
                    252: static eap_tnc_t *eap_tnc_create(identification_t *server,
                    253:                                                                 identification_t *peer, bool is_server,
                    254:                                                                 eap_type_t type)
                    255: {
                    256:        private_eap_tnc_t *this;
                    257:        int max_msg_count;
                    258:        char* protocol;
                    259:        ike_sa_t *ike_sa;
                    260:        host_t *server_ip, *peer_ip;
                    261:        tnccs_t *tnccs;
                    262:        tnccs_type_t tnccs_type;
                    263: 
                    264:        INIT(this,
                    265:                .public = {
                    266:                        .eap_inner_method = {
                    267:                                .eap_method = {
                    268:                                        .initiate = _initiate,
                    269:                                        .process = _process,
                    270:                                        .get_type = _get_type,
                    271:                                        .is_mutual = _is_mutual,
                    272:                                        .get_msk = _get_msk,
                    273:                                        .get_identifier = _get_identifier,
                    274:                                        .set_identifier = _set_identifier,
                    275:                                        .destroy = _destroy,
                    276:                                },
                    277:                                .get_auth_type = _get_auth_type,
                    278:                                .set_auth_type = _set_auth_type,
                    279:                        },
                    280:                },
                    281:                .type = type,
                    282:        );
                    283: 
                    284:        max_msg_count = lib->settings->get_int(lib->settings,
                    285:                                                "%s.plugins.eap-tnc.max_message_count",
                    286:                                                EAP_TNC_MAX_MESSAGE_COUNT, lib->ns);
                    287:        protocol = lib->settings->get_str(lib->settings,
                    288:                                                "%s.plugins.eap-tnc.protocol", "tnccs-2.0", lib->ns);
                    289:        if (strcaseeq(protocol, "tnccs-2.0"))
                    290:        {
                    291:                tnccs_type = TNCCS_2_0;
                    292:        }
                    293:        else if (strcaseeq(protocol, "tnccs-1.1"))
                    294:        {
                    295:                tnccs_type = TNCCS_1_1;
                    296:        }
                    297:        else if (strcaseeq(protocol, "tnccs-dynamic") && is_server)
                    298:        {
                    299:                tnccs_type = TNCCS_DYNAMIC;
                    300:        }
                    301:        else
                    302:        {
                    303:                DBG1(DBG_TNC, "TNCCS protocol '%s' not supported", protocol);
                    304:                free(this);
                    305:                return NULL;
                    306:        }
                    307: 
                    308:        /* Determine IP addresses of server and peer */
                    309:        ike_sa = charon->bus->get_sa(charon->bus);
                    310:        if (!ike_sa)
                    311:        {
                    312:                DBG1(DBG_TNC, "%N constructor did not find IKE_SA",
                    313:                                           eap_type_names, type);
                    314:                free(this);
                    315:                return NULL;
                    316:        }
                    317:        if (is_server)
                    318:        {
                    319:                server_ip = ike_sa->get_my_host(ike_sa);
                    320:                peer_ip = ike_sa->get_other_host(ike_sa);
                    321:        }
                    322:        else
                    323:        {
                    324:                peer_ip = ike_sa->get_my_host(ike_sa);
                    325:                server_ip = ike_sa->get_other_host(ike_sa);
                    326:        }
                    327: 
                    328:        tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
                    329:                                                is_server, server, peer, server_ip, peer_ip,
                    330:                                                (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
                    331:                                                enforce_recommendation);
                    332:        if (!tnccs)
                    333:        {
                    334:                DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol);
                    335:                free(this);
                    336:                return NULL;
                    337:        }
                    338:        if (!is_server)
                    339:        {
                    340:                tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
                    341:        }
                    342:        this->tnccs = tnccs->get_ref(tnccs);
                    343:        this->tls_eap = tls_eap_create(type, &tnccs->tls,
                    344:                                                                   EAP_TNC_MAX_MESSAGE_LEN,
                    345:                                                                   max_msg_count, FALSE);
                    346:        if (!this->tls_eap)
                    347:        {
                    348:                free(this);
                    349:                return NULL;
                    350:        }
                    351:        return &this->public;
                    352: }
                    353: 
                    354: eap_tnc_t *eap_tnc_create_server(identification_t *server,
                    355:                                                                 identification_t *peer)
                    356: {
                    357:        return eap_tnc_create(server, peer, TRUE, EAP_TNC);
                    358: }
                    359: 
                    360: eap_tnc_t *eap_tnc_create_peer(identification_t *server,
                    361:                                                           identification_t *peer)
                    362: {
                    363:        return eap_tnc_create(server, peer, FALSE, EAP_TNC);
                    364: }
                    365: 
                    366: eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
                    367:                                                                 identification_t *peer)
                    368: {
                    369:        return eap_tnc_create(server, peer, TRUE, EAP_PT_EAP);
                    370: }
                    371: 
                    372: eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
                    373:                                                           identification_t *peer)
                    374: {
                    375:        return eap_tnc_create(server, peer, FALSE, EAP_PT_EAP);
                    376: }

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