Annotation of embedaddon/strongswan/src/libtnccs/plugins/tnccs_20/tnccs_20.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Sansar Choinyambuu
                      3:  * Copyright (C) 2010-2015 Andreas Steffen
                      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 "tnccs_20.h"
                     18: #include "tnccs_20_handler.h"
                     19: #include "tnccs_20_server.h"
                     20: #include "tnccs_20_client.h"
                     21: #include "batch/pb_tnc_batch.h"
                     22: #include "messages/pb_tnc_msg.h"
                     23: #include "messages/ietf/pb_pa_msg.h"
                     24: 
                     25: #include <tncif_names.h>
                     26: #include <tncif_pa_subtypes.h>
                     27: 
                     28: #include <utils/debug.h>
                     29: 
                     30: typedef struct private_tnccs_20_t private_tnccs_20_t;
                     31: 
                     32: /**
                     33:  * Private data of a tnccs_20_t object.
                     34:  */
                     35: struct private_tnccs_20_t {
                     36: 
                     37:        /**
                     38:         * Public tnccs_t interface.
                     39:         */
                     40:        tnccs_t public;
                     41: 
                     42:        /**
                     43:         * TNCC if TRUE, TNCS if FALSE
                     44:         */
                     45:        bool is_server;
                     46: 
                     47:        /**
                     48:         * Server identity
                     49:         */
                     50:        identification_t *server_id;
                     51: 
                     52:        /**
                     53:         * Client identity
                     54:         */
                     55:        identification_t *peer_id;
                     56: 
                     57:        /**
                     58:         * Server IP address
                     59:         */
                     60:        host_t *server_ip;
                     61: 
                     62:        /**
                     63:         * Client IP address
                     64:         */
                     65:        host_t *peer_ip;
                     66: 
                     67:        /**
                     68:         * Underlying TNC IF-T transport protocol
                     69:         */
                     70:        tnc_ift_type_t transport;
                     71: 
                     72:        /**
                     73:         *  TNC IF-T transport protocol for EAP methods
                     74:         */
                     75:        bool eap_transport;
                     76: 
                     77:        /**
                     78:         * Type of TNC client authentication
                     79:         */
                     80:        uint32_t auth_type;
                     81: 
                     82:        /**
                     83:         * Mutual PB-TNC protocol enabled
                     84:         */
                     85:        bool mutual;
                     86: 
                     87:        /**
                     88:         * Direction the next batch will go to
                     89:         */
                     90:        bool to_server;
                     91: 
                     92:        /**
                     93:         * TNC Server
                     94:         */
                     95:        tnccs_20_handler_t *tnc_server;
                     96: 
                     97:        /**
                     98:         * TNC Client
                     99:         */
                    100:        tnccs_20_handler_t *tnc_client;
                    101: 
                    102:        /**
                    103:         * Active TNCSS handler
                    104:         */
                    105:        tnccs_20_handler_t *tnccs_handler;
                    106: 
                    107:        /**
                    108:         * Maximum PB-TNC batch size
                    109:         */
                    110:        size_t max_batch_len;
                    111: 
                    112:        /**
                    113:         * Maximum PA-TNC message size
                    114:         */
                    115:        size_t max_msg_len;
                    116: 
                    117:        /**
                    118:         * Callback function to communicate recommendation (TNC Server only)
                    119:         */
                    120:        tnccs_cb_t callback;
                    121: 
                    122:        /**
                    123:         * reference count
                    124:         */
                    125:        refcount_t ref;
                    126: 
                    127: };
                    128: 
                    129: METHOD(tls_t, is_complete, bool,
                    130:        private_tnccs_20_t *this)
                    131: {
                    132:        TNC_IMV_Action_Recommendation rec;
                    133:        TNC_IMV_Evaluation_Result eval;
                    134:        tnccs_20_server_t *tnc_server;
                    135: 
                    136:        if (this->tnc_server)
                    137:        {
                    138:                tnc_server = (tnccs_20_server_t*)this->tnc_server;
                    139:                if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
                    140:                {
                    141:                        return this->callback ? this->callback(rec, eval) : TRUE;
                    142:                }
                    143:        }
                    144:        return FALSE;
                    145: }
                    146: 
                    147: METHOD(tnccs_t, send_msg, TNC_Result,
                    148:        private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
                    149:                                                          TNC_UInt32 msg_flags,
                    150:                                                          TNC_BufferReference msg,
                    151:                                                          TNC_UInt32 msg_len,
                    152:                                                          TNC_VendorID msg_vid,
                    153:                                                          TNC_MessageSubtype msg_subtype)
                    154: {
                    155:        pb_tnc_msg_t *pb_tnc_msg;
                    156:        enum_name_t *pa_subtype_names;
                    157:        bool excl;
                    158: 
                    159:        if (!this->tnccs_handler->get_send_flag(this->tnccs_handler))
                    160:        {
                    161:                DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
                    162:                                           this->to_server ? "IMC" : "IMV",
                    163:                                           this->to_server ? imc_id : imv_id);
                    164: 
                    165:                return TNC_RESULT_ILLEGAL_OPERATION;
                    166:        }
                    167:        excl = (msg_flags & TNC_MESSAGE_FLAGS_EXCLUSIVE) != 0;
                    168: 
                    169:        pb_tnc_msg = pb_pa_msg_create(msg_vid, msg_subtype, imc_id, imv_id,
                    170:                                                                  excl, chunk_create(msg, msg_len));
                    171: 
                    172:        pa_subtype_names = get_pa_subtype_names(msg_vid);
                    173:        if (pa_subtype_names)
                    174:        {
                    175:                DBG2(DBG_TNC, "creating PB-PA message type '%N/%N' 0x%06x/0x%08x",
                    176:                                           pen_names, msg_vid, pa_subtype_names, msg_subtype,
                    177:                                           msg_vid, msg_subtype);
                    178:        }
                    179:        else
                    180:        {
                    181:                DBG2(DBG_TNC, "creating PB-PA message type '%N' 0x%06x/0x%08x",
                    182:                                           pen_names, msg_vid, msg_vid, msg_subtype);
                    183:        }
                    184:        this->tnccs_handler->add_msg(this->tnccs_handler, pb_tnc_msg);
                    185: 
                    186:        return TNC_RESULT_SUCCESS;
                    187: }
                    188: 
                    189: METHOD(tls_t, process, status_t,
                    190:        private_tnccs_20_t *this, void *buf, size_t buflen)
                    191: {
                    192:        pb_tnc_batch_t *batch;
                    193:        bool from_server, fatal_header_error = FALSE;
                    194:        status_t status;
                    195:        chunk_t data;
                    196: 
                    197:        /* On arrival of first batch from TNC client create TNC server */
                    198:        if (this->is_server && !this->tnc_server)
                    199:        {
                    200:                this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
                    201:                                                                        this->max_batch_len, this->max_msg_len,
                    202:                                                                        this->eap_transport);
                    203:                if (!this->tnc_server)
                    204:                {
                    205:                        return FAILED;
                    206:                }
                    207:                this->tnccs_handler = this->tnc_server;
                    208:                this->tnccs_handler->begin_handshake(this->tnccs_handler, FALSE);
                    209:        }
                    210: 
                    211:        data = chunk_create(buf, buflen);
                    212:        DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len);
                    213:        DBG3(DBG_TNC, "%B", &data);
                    214: 
                    215:        /* Parse the header of the received PB-TNC batch */
                    216:        batch = pb_tnc_batch_create_from_data(data);
                    217:        status = batch->process_header(batch, !this->mutual, this->is_server,
                    218:                                                                   &from_server);
                    219:        if (status == FAILED)
                    220:        {
                    221:                fatal_header_error = TRUE;
                    222:                status = VERIFY_ERROR;
                    223:        }
                    224:        this->to_server = this->mutual ? from_server : !this->is_server;
                    225: 
                    226:        /* In the mutual case, first batch from TNC server requires a TNC client */
                    227:        if (this->to_server && !this->tnc_client)
                    228:        {
                    229:                this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
                    230:                                                                        this->max_batch_len, this->max_msg_len);
                    231:                if (!this->tnc_client)
                    232:                {
                    233:                        batch->destroy(batch);
                    234:                        return FAILED;
                    235:                }
                    236:                this->tnccs_handler = this->tnc_client;
                    237:                this->tnccs_handler->begin_handshake(this->tnccs_handler, this->mutual);
                    238:        }
                    239:        else
                    240:        {
                    241:                /* Set active TNCCS handler for processing */
                    242:                this->tnccs_handler = this->to_server ? this->tnc_client :
                    243:                                                                                                this->tnc_server;
                    244:        }
                    245:        DBG2(DBG_TNC, "TNC %s is handling inbound connection",
                    246:                                   this->to_server ? "client" : "server");
                    247: 
                    248:        if (status == SUCCESS)
                    249:        {
                    250:                status = this->tnccs_handler->process(this->tnccs_handler, batch);
                    251:        }
                    252:        if (status == VERIFY_ERROR)
                    253:        {
                    254:                this->tnccs_handler->handle_errors(this->tnccs_handler, batch,
                    255:                                                                                   fatal_header_error);
                    256:                status = NEED_MORE;
                    257:        }
                    258:        batch->destroy(batch);
                    259: 
                    260:        /* Has a mutual connection been established? */
                    261:        this->mutual = this->is_server ?
                    262:                                   this->tnc_server->get_mutual(this->tnc_server) :
                    263:                                   this->tnc_client->get_mutual(this->tnc_client);
                    264: 
                    265:        if (this->mutual && !this->is_server)
                    266:        {
                    267:                pb_tnc_state_t client_state, server_state;
                    268: 
                    269:                client_state = !this->tnc_client ? PB_STATE_INIT :
                    270:                                                this->tnc_client->get_state(this->tnc_client);
                    271:                server_state = !this->tnc_server ? PB_STATE_INIT :
                    272:                                                this->tnc_server->get_state(this->tnc_server);
                    273: 
                    274:                /* In half-duplex mutual mode toggle the direction on the client side */
                    275:                if ((!this->to_server && client_state != PB_STATE_DECIDED) ||
                    276:                        ( this->to_server && server_state != PB_STATE_END))
                    277:                {
                    278:                        this->to_server = !this->to_server;
                    279:                }
                    280:                else if (client_state == PB_STATE_DECIDED &&
                    281:                                 server_state == PB_STATE_END)
                    282:                {
                    283:                        /* Cause the final CLOSE batch to be sent to the TNC server */
                    284:                        this->to_server = TRUE;
                    285:                }
                    286: 
                    287:                /* Suppress a successful CLOSE batch coming from the TNC server */
                    288:                if (status == SUCCESS)
                    289:                {
                    290:                        is_complete(this);
                    291:                        status = NEED_MORE;
                    292:                }
                    293:        }
                    294: 
                    295:        return status;
                    296: }
                    297: 
                    298: METHOD(tls_t, build, status_t,
                    299:        private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
                    300: {
                    301:        if (this->to_server)
                    302:        {
                    303:                DBG2(DBG_TNC, "TNC client is handling outbound connection");
                    304: 
                    305:                /* Before sending the first PB-TNC batch create TNC client */
                    306:                if (this->tnc_client)
                    307:                {
                    308:                        this->tnccs_handler = this->tnc_client;
                    309:                }
                    310:                else
                    311:                {
                    312:                        this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
                    313:                                                                                                          this->max_batch_len,
                    314:                                                                                                          this->max_msg_len);
                    315:                        if (!this->tnc_client)
                    316:                        {
                    317:                                return FAILED;
                    318:                        }
                    319:                        this->tnccs_handler = this->tnc_client;
                    320:                        this->tnccs_handler->begin_handshake(this->tnccs_handler,
                    321:                                                                                                 this->mutual);
                    322:                }
                    323:        }
                    324:        else
                    325:        {
                    326:                DBG2(DBG_TNC, "TNC server is handling outbound connection");
                    327: 
                    328:                /* Before sending the first PB-TNC batch create TNC server */
                    329:                if (this->tnc_server)
                    330:                {
                    331:                        this->tnccs_handler = this->tnc_server;
                    332:                }
                    333:                else
                    334:                {
                    335:                        this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
                    336:                                                                                this->max_batch_len, this->max_msg_len,
                    337:                                                                                this->eap_transport);
                    338:                        if (!this->tnc_server)
                    339:                        {
                    340:                                return FAILED;
                    341:                        }
                    342:                        this->tnccs_handler = this->tnc_server;
                    343:                        this->tnccs_handler->begin_handshake(this->tnccs_handler,
                    344:                                                                                                 this->mutual);
                    345:                }
                    346:        }
                    347:        return this->tnccs_handler->build(this->tnccs_handler, buf, buflen, msglen);
                    348: }
                    349: 
                    350: METHOD(tls_t, is_server, bool,
                    351:        private_tnccs_20_t *this)
                    352: {
                    353:        return this->is_server;
                    354: }
                    355: 
                    356: METHOD(tls_t, get_server_id, identification_t*,
                    357:        private_tnccs_20_t *this)
                    358: {
                    359:        return this->server_id;
                    360: }
                    361: 
                    362: METHOD(tls_t, set_peer_id, void,
                    363:        private_tnccs_20_t *this, identification_t *id)
                    364: {
                    365:        DESTROY_IF(this->peer_id);
                    366:        this->peer_id = id->clone(id);
                    367: }
                    368: 
                    369: METHOD(tls_t, get_peer_id, identification_t*,
                    370:        private_tnccs_20_t *this)
                    371: {
                    372:        return this->peer_id;
                    373: }
                    374: 
                    375: METHOD(tls_t, get_purpose, tls_purpose_t,
                    376:        private_tnccs_20_t *this)
                    377: {
                    378:        return TLS_PURPOSE_EAP_TNC;
                    379: }
                    380: 
                    381: METHOD(tls_t, get_eap_msk, chunk_t,
                    382:        private_tnccs_20_t *this)
                    383: {
                    384:        return chunk_empty;
                    385: }
                    386: 
                    387: METHOD(tls_t, destroy, void,
                    388:        private_tnccs_20_t *this)
                    389: {
                    390:        if (ref_put(&this->ref))
                    391:        {
                    392:                DESTROY_IF(this->tnc_server);
                    393:                DESTROY_IF(this->tnc_client);
                    394:                this->server_id->destroy(this->server_id);
                    395:                this->peer_id->destroy(this->peer_id);
                    396:                this->server_ip->destroy(this->server_ip);
                    397:                this->peer_ip->destroy(this->peer_ip);
                    398:                free(this);
                    399:        }
                    400: }
                    401: 
                    402: METHOD(tnccs_t, get_server_ip, host_t*,
                    403:        private_tnccs_20_t *this)
                    404: {
                    405:        return this->server_ip;
                    406: }
                    407: 
                    408: METHOD(tnccs_t, get_peer_ip, host_t*,
                    409:        private_tnccs_20_t *this)
                    410: {
                    411:        return this->peer_ip;
                    412: }
                    413: 
                    414: METHOD(tnccs_t, get_transport, tnc_ift_type_t,
                    415:        private_tnccs_20_t *this)
                    416: {
                    417:        return this->transport;
                    418: }
                    419: 
                    420: METHOD(tnccs_t, set_transport, void,
                    421:        private_tnccs_20_t *this, tnc_ift_type_t transport)
                    422: {
                    423:        this->transport = transport;
                    424: }
                    425: 
                    426: METHOD(tnccs_t, get_auth_type, uint32_t,
                    427:        private_tnccs_20_t *this)
                    428: {
                    429:        return this->auth_type;
                    430: }
                    431: 
                    432: METHOD(tnccs_t, set_auth_type, void,
                    433:        private_tnccs_20_t *this, uint32_t auth_type)
                    434: {
                    435:        this->auth_type = auth_type;
                    436: }
                    437: 
                    438: METHOD(tnccs_t, get_pdp_server, chunk_t,
                    439:        private_tnccs_20_t *this, uint16_t *port)
                    440: {
                    441:        if (this->tnc_client)
                    442:        {
                    443:                tnccs_20_client_t *tnc_client;
                    444: 
                    445:                tnc_client = (tnccs_20_client_t*)this->tnc_client;
                    446: 
                    447:                return tnc_client->get_pdp_server(tnc_client, port);
                    448:        }
                    449:        else
                    450:        {
                    451:                *port = 0;
                    452:                return chunk_empty;
                    453:        }
                    454: }
                    455: 
                    456: METHOD(tnccs_t, get_ref, tnccs_t*,
                    457:        private_tnccs_20_t *this)
                    458: {
                    459:        ref_get(&this->ref);
                    460:        return &this->public;
                    461: }
                    462: 
                    463: /**
                    464:  * See header
                    465:  */
                    466: tnccs_t* tnccs_20_create(bool is_server, identification_t *server_id,
                    467:                                                 identification_t *peer_id, host_t *server_ip,
                    468:                                                 host_t *peer_ip, tnc_ift_type_t transport,
                    469:                                                 tnccs_cb_t cb)
                    470: {
                    471:        private_tnccs_20_t *this;
                    472:        size_t max_batch_size, default_max_batch_size;
                    473:        size_t max_message_size, default_max_message_size;
                    474: 
                    475:        /* Determine the maximum PB-TNC batch size and PA-TNC message size */
                    476:        switch (transport)
                    477:        {
                    478:                case TNC_IFT_TLS_2_0:
                    479:                case TNC_IFT_TLS_1_0:
                    480:                        default_max_batch_size = 128 * TLS_MAX_FRAGMENT_LEN - 16;
                    481:                        break;
                    482:                case TNC_IFT_EAP_2_0:
                    483:                case TNC_IFT_EAP_1_1:
                    484:                case TNC_IFT_EAP_1_0:
                    485:                case TNC_IFT_UNKNOWN:
                    486:                default:
                    487:                        default_max_batch_size =   4 * TLS_MAX_FRAGMENT_LEN - 14;
                    488:                        break;
                    489:        }
                    490: 
                    491:        max_batch_size = min(default_max_batch_size,
                    492:                                                lib->settings->get_int(lib->settings,
                    493:                                                                "%s.plugins.tnccs-20.max_batch_size",
                    494:                                                                 default_max_batch_size, lib->ns));
                    495: 
                    496:        default_max_message_size = max_batch_size - PB_TNC_BATCH_HEADER_SIZE
                    497:                                                                                          - PB_TNC_MSG_HEADER_SIZE
                    498:                                                                                          - PB_PA_MSG_HEADER_SIZE;
                    499: 
                    500:        max_message_size = min(default_max_message_size,
                    501:                                                        lib->settings->get_int(lib->settings,
                    502:                                                                "%s.plugins.tnccs-20.max_message_size",
                    503:                                                                 default_max_message_size, lib->ns));
                    504: 
                    505:        INIT(this,
                    506:                .public = {
                    507:                        .tls = {
                    508:                                .process = _process,
                    509:                                .build = _build,
                    510:                                .is_server = _is_server,
                    511:                                .get_server_id = _get_server_id,
                    512:                                .set_peer_id = _set_peer_id,
                    513:                                .get_peer_id = _get_peer_id,
                    514:                                .get_purpose = _get_purpose,
                    515:                                .is_complete = _is_complete,
                    516:                                .get_eap_msk = _get_eap_msk,
                    517:                                .destroy = _destroy,
                    518:                        },
                    519:                        .get_server_ip = _get_server_ip,
                    520:                        .get_peer_ip = _get_peer_ip,
                    521:                        .get_transport = _get_transport,
                    522:                        .set_transport = _set_transport,
                    523:                        .get_auth_type = _get_auth_type,
                    524:                        .set_auth_type = _set_auth_type,
                    525:                        .get_pdp_server = _get_pdp_server,
                    526:                        .get_ref = _get_ref,
                    527:                },
                    528:                .is_server = is_server,
                    529:                .to_server = !is_server,
                    530:                .server_id = server_id->clone(server_id),
                    531:                .peer_id = peer_id->clone(peer_id),
                    532:                .server_ip = server_ip->clone(server_ip),
                    533:                .peer_ip = peer_ip->clone(peer_ip),
                    534:                .transport = transport,
                    535:                .eap_transport = transport == TNC_IFT_EAP_1_1 ||
                    536:                                                 transport == TNC_IFT_EAP_2_0,
                    537:                .callback = cb,
                    538:                .max_batch_len = max_batch_size,
                    539:                .max_msg_len = max_message_size,
                    540:                .ref = 1,
                    541:        );
                    542: 
                    543:        return &this->public;
                    544: }

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