Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_tnc/eap_tnc.c, revision 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>