Annotation of embedaddon/strongswan/src/libimcv/plugins/imv_os/imv_os_agent.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013-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: #define _GNU_SOURCE
                     17: #include <stdio.h>
                     18: 
                     19: #include "imv_os_agent.h"
                     20: #include "imv_os_state.h"
                     21: #include "imv_os_database.h"
                     22: 
                     23: #include <imcv.h>
                     24: #include <imv/imv_agent.h>
                     25: #include <imv/imv_msg.h>
                     26: #include <generic/generic_attr_bool.h>
                     27: #include <generic/generic_attr_string.h>
                     28: #include <ietf/ietf_attr.h>
                     29: #include <ietf/ietf_attr_attr_request.h>
                     30: #include <ietf/ietf_attr_installed_packages.h>
                     31: #include <ietf/ietf_attr_numeric_version.h>
                     32: #include <ietf/ietf_attr_op_status.h>
                     33: #include <ietf/ietf_attr_pa_tnc_error.h>
                     34: #include <ietf/ietf_attr_product_info.h>
                     35: #include <ietf/ietf_attr_remediation_instr.h>
                     36: #include <ietf/ietf_attr_string_version.h>
                     37: #include <ita/ita_attr.h>
                     38: #include <ita/ita_attr_get_settings.h>
                     39: #include <ita/ita_attr_settings.h>
                     40: #include "tcg/seg/tcg_seg_attr_max_size.h"
                     41: #include "tcg/seg/tcg_seg_attr_seg_env.h"
                     42: 
                     43: #include <tncif_names.h>
                     44: #include <tncif_pa_subtypes.h>
                     45: 
                     46: #include <pen/pen.h>
                     47: #include <utils/debug.h>
                     48: 
                     49: #define INSTALLED_PACKAGES_MAX_ATTR_SIZE       100000000
                     50: 
                     51: typedef struct private_imv_os_agent_t private_imv_os_agent_t;
                     52: typedef enum imv_os_attr_t imv_os_attr_t;
                     53: 
                     54: /* Subscribed PA-TNC message subtypes */
                     55: static pen_type_t msg_types[] = {
                     56:        { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }
                     57: };
                     58: 
                     59: static char unknown_source_str[] = "install_non_market_apps";
                     60: 
                     61: /**
                     62:  * Flag set when corresponding attribute has been received
                     63:  */
                     64: enum imv_os_attr_t {
                     65:        IMV_OS_ATTR_PRODUCT_INFORMATION =         (1<<0),
                     66:        IMV_OS_ATTR_STRING_VERSION =              (1<<1),
                     67:        IMV_OS_ATTR_NUMERIC_VERSION =             (1<<2),
                     68:        IMV_OS_ATTR_OPERATIONAL_STATUS =          (1<<3),
                     69:        IMV_OS_ATTR_FORWARDING_ENABLED =          (1<<4),
                     70:        IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED = (1<<5),
                     71:        IMV_OS_ATTR_DEVICE_ID =                   (1<<6),
                     72:        IMV_OS_ATTR_MUST =                        (1<<7)-1,
                     73:        IMV_OS_ATTR_INSTALLED_PACKAGES =          (1<<7),
                     74:        IMV_OS_ATTR_SETTINGS =                    (1<<8)
                     75: };
                     76: 
                     77: /**
                     78:  * Private data of an imv_os_agent_t object.
                     79:  */
                     80: struct private_imv_os_agent_t {
                     81: 
                     82:        /**
                     83:         * Public members of imv_os_agent_t
                     84:         */
                     85:        imv_agent_if_t public;
                     86: 
                     87:        /**
                     88:         * IMV agent responsible for generic functions
                     89:         */
                     90:        imv_agent_t *agent;
                     91: 
                     92:        /**
                     93:         * IMV OS database
                     94:         */
                     95:        imv_os_database_t *db;
                     96: 
                     97: };
                     98: 
                     99: METHOD(imv_agent_if_t, bind_functions, TNC_Result,
                    100:        private_imv_os_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
                    101: {
                    102:        return this->agent->bind_functions(this->agent, bind_function);
                    103: }
                    104: 
                    105: METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
                    106:        private_imv_os_agent_t *this, TNC_ConnectionID id,
                    107:        TNC_ConnectionState new_state)
                    108: {
                    109:        TNC_IMV_Action_Recommendation rec;
                    110:        imv_state_t *state;
                    111:        imv_session_t *session;
                    112: 
                    113:        switch (new_state)
                    114:        {
                    115:                case TNC_CONNECTION_STATE_CREATE:
                    116:                        state = imv_os_state_create(id);
                    117:                        return this->agent->create_state(this->agent, state);
                    118:                case TNC_CONNECTION_STATE_DELETE:
                    119:                        return this->agent->delete_state(this->agent, id);
                    120:                case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
                    121:                case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
                    122:                case TNC_CONNECTION_STATE_ACCESS_NONE:
                    123:                        if (this->agent->get_state(this->agent, id, &state) && imcv_db)
                    124:                        {
                    125:                                session = state->get_session(state);
                    126: 
                    127:                                if (session->get_policy_started(session))
                    128:                                {
                    129:                                        switch (new_state)
                    130:                                        {
                    131:                                                case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
                    132:                                                        rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
                    133:                                                        break;
                    134:                                                case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
                    135:                                                        rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
                    136:                                                        break;
                    137:                                                case TNC_CONNECTION_STATE_ACCESS_NONE:
                    138:                                                default:
                    139:                                                        rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
                    140:                                        }
                    141:                                        imcv_db->add_recommendation(imcv_db, session, rec);
                    142:                                        if (!imcv_db->policy_script(imcv_db, session, FALSE))
                    143:                                        {
                    144:                                                DBG1(DBG_IMV, "error in policy script stop");
                    145:                                        }
                    146:                                }
                    147:                        }
                    148:                        /* fall through to default state */
                    149:                default:
                    150:                        return this->agent->change_state(this->agent, id, new_state, NULL);
                    151:        }
                    152: }
                    153: 
                    154: /**
                    155:  * Process a received message
                    156:  */
                    157: static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
                    158:                                                          imv_msg_t *in_msg)
                    159: {
                    160:        imv_msg_t *out_msg;
                    161:        imv_os_state_t *os_state;
                    162:        imv_session_t *session;
                    163:        imv_os_info_t *os_info = NULL;
                    164:        enumerator_t *enumerator;
                    165:        pa_tnc_attr_t *attr;
                    166:        pen_type_t type;
                    167:        TNC_Result result;
                    168:        chunk_t os_name = chunk_empty;
                    169:        chunk_t os_version = chunk_empty;
                    170:        bool fatal_error = FALSE, assessment = FALSE;
                    171:        uint16_t missing;
                    172: 
                    173:        os_state = (imv_os_state_t*)state;
                    174:        session = state->get_session(state);
                    175:        os_info = session->get_os_info(session);
                    176: 
                    177:        /* generate an outgoing PA-TNC message - we might need it */
                    178:        out_msg = imv_msg_create_as_reply(in_msg);
                    179: 
                    180:        /* parse received PA-TNC message and handle local and remote errors */
                    181:        result = in_msg->receive(in_msg,out_msg, &fatal_error);
                    182:        if (result != TNC_RESULT_SUCCESS)
                    183:        {
                    184:                out_msg->destroy(out_msg);
                    185:                return result;
                    186:        }
                    187: 
                    188:        /* analyze PA-TNC attributes */
                    189:        enumerator = in_msg->create_attribute_enumerator(in_msg);
                    190:        while (enumerator->enumerate(enumerator, &attr))
                    191:        {
                    192:                type = attr->get_type(attr);
                    193: 
                    194:                if (type.vendor_id == PEN_IETF)
                    195:                {
                    196:                        switch (type.type)
                    197:                        {
                    198:                                case IETF_ATTR_PRODUCT_INFORMATION:
                    199:                                {
                    200:                                        ietf_attr_product_info_t *attr_cast;
                    201:                                        pen_t vendor_id;
                    202: 
                    203:                                        state->set_action_flags(state,
                    204:                                                                                        IMV_OS_ATTR_PRODUCT_INFORMATION);
                    205:                                        attr_cast = (ietf_attr_product_info_t*)attr;
                    206:                                        os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
                    207:                                        os_info->set_name(os_info, os_name);
                    208: 
                    209:                                        if (vendor_id != PEN_IETF)
                    210:                                        {
                    211:                                                DBG1(DBG_IMV, "operating system name is '%.*s' "
                    212:                                                                          "from vendor %N", os_name.len, os_name.ptr,
                    213:                                                                           pen_names, vendor_id);
                    214:                                        }
                    215:                                        else
                    216:                                        {
                    217:                                                DBG1(DBG_IMV, "operating system name is '%.*s'",
                    218:                                                                           os_name.len, os_name.ptr);
                    219:                                        }
                    220:                                        break;
                    221:                                }
                    222:                                case IETF_ATTR_STRING_VERSION:
                    223:                                {
                    224:                                        ietf_attr_string_version_t *attr_cast;
                    225: 
                    226:                                        state->set_action_flags(state,
                    227:                                                                                        IMV_OS_ATTR_STRING_VERSION);
                    228:                                        attr_cast = (ietf_attr_string_version_t*)attr;
                    229:                                        os_version = attr_cast->get_version(attr_cast, NULL, NULL);
                    230:                                        os_info->set_version(os_info, os_version);
                    231: 
                    232:                                        if (os_version.len)
                    233:                                        {
                    234:                                                DBG1(DBG_IMV, "operating system version is '%.*s'",
                    235:                                                                           os_version.len, os_version.ptr);
                    236:                                        }
                    237:                                        break;
                    238:                                }
                    239:                                case IETF_ATTR_NUMERIC_VERSION:
                    240:                                {
                    241:                                        ietf_attr_numeric_version_t *attr_cast;
                    242:                                        uint32_t major, minor;
                    243: 
                    244:                                        state->set_action_flags(state,
                    245:                                                                                        IMV_OS_ATTR_NUMERIC_VERSION);
                    246:                                        attr_cast = (ietf_attr_numeric_version_t*)attr;
                    247:                                        attr_cast->get_version(attr_cast, &major, &minor);
                    248:                                        DBG1(DBG_IMV, "operating system numeric version is %d.%d",
                    249:                                                                   major, minor);
                    250:                                        break;
                    251:                                }
                    252:                                case IETF_ATTR_OPERATIONAL_STATUS:
                    253:                                {
                    254:                                        ietf_attr_op_status_t *attr_cast;
                    255:                                        op_status_t op_status;
                    256:                                        op_result_t op_result;
                    257:                                        time_t last_boot;
                    258: 
                    259:                                        state->set_action_flags(state,
                    260:                                                                                        IMV_OS_ATTR_OPERATIONAL_STATUS);
                    261:                                        attr_cast = (ietf_attr_op_status_t*)attr;
                    262:                                        op_status = attr_cast->get_status(attr_cast);
                    263:                                        op_result = attr_cast->get_result(attr_cast);
                    264:                                        last_boot = attr_cast->get_last_use(attr_cast);
                    265:                                        DBG1(DBG_IMV, "operational status: %N, result: %N",
                    266:                                                 op_status_names, op_status, op_result_names, op_result);
                    267:                                        DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE);
                    268:                                        break;
                    269:                                }
                    270:                                case IETF_ATTR_FORWARDING_ENABLED:
                    271:                                {
                    272:                                        generic_attr_bool_t *attr_cast;
                    273:                                        os_fwd_status_t fwd_status;
                    274: 
                    275:                                        state->set_action_flags(state,
                    276:                                                                                        IMV_OS_ATTR_FORWARDING_ENABLED);
                    277:                                        attr_cast = (generic_attr_bool_t*)attr;
                    278:                                        fwd_status = attr_cast->get_status(attr_cast);
                    279:                                        DBG1(DBG_IMV, "IPv4 forwarding is %N",
                    280:                                                                   os_fwd_status_names, fwd_status);
                    281:                                        if (fwd_status == OS_FWD_ENABLED)
                    282:                                        {
                    283:                                                os_state->set_os_settings(os_state,
                    284:                                                                                        OS_SETTINGS_FWD_ENABLED);
                    285:                                        }
                    286:                                        break;
                    287:                                }
                    288:                                case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
                    289:                                {
                    290:                                        generic_attr_bool_t *attr_cast;
                    291:                                        bool default_pwd_status;
                    292: 
                    293:                                        state->set_action_flags(state,
                    294:                                                                        IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
                    295:                                        attr_cast = (generic_attr_bool_t*)attr;
                    296:                                        default_pwd_status = attr_cast->get_status(attr_cast);
                    297:                                        DBG1(DBG_IMV, "factory default password is %sabled",
                    298:                                                                   default_pwd_status ? "en":"dis");
                    299:                                        if (default_pwd_status)
                    300:                                        {
                    301:                                                os_state->set_os_settings(os_state,
                    302:                                                                                        OS_SETTINGS_DEFAULT_PWD_ENABLED);
                    303:                                        }
                    304:                                        break;
                    305:                                }
                    306:                                case IETF_ATTR_INSTALLED_PACKAGES:
                    307:                                {
                    308:                                        ietf_attr_installed_packages_t *attr_cast;
                    309:                                        enumerator_t *e;
                    310:                                        status_t status;
                    311: 
                    312:                                        state->set_action_flags(state,
                    313:                                                                                        IMV_OS_ATTR_INSTALLED_PACKAGES);
                    314:                                        if (!this->db)
                    315:                                        {
                    316:                                                break;
                    317:                                        }
                    318:                                        attr_cast = (ietf_attr_installed_packages_t*)attr;
                    319: 
                    320:                                        e = attr_cast->create_enumerator(attr_cast);
                    321:                                        status = this->db->check_packages(this->db, os_state, e);
                    322:                                        e->destroy(e);
                    323: 
                    324:                                        if (status == FAILED)
                    325:                                        {
                    326:                                                state->set_recommendation(state,
                    327:                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                    328:                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
                    329:                                                assessment = TRUE;
                    330:                                        }
                    331:                                        missing = attr_cast->get_count(attr_cast);
                    332:                                        os_state->set_missing(os_state, missing);
                    333:                                        attr_cast->clear_packages(attr_cast);
                    334:                                        break;
                    335:                                }
                    336:                                default:
                    337:                                        break;
                    338:                        }
                    339:                }
                    340:                else if (type.vendor_id == PEN_ITA)
                    341:                {
                    342:                        switch (type.type)
                    343:                        {
                    344:                                case ITA_ATTR_SETTINGS:
                    345:                                {
                    346:                                        ita_attr_settings_t *attr_cast;
                    347:                                        enumerator_t *e;
                    348:                                        char *name;
                    349:                                        chunk_t value;
                    350: 
                    351:                                        state->set_action_flags(state, IMV_OS_ATTR_SETTINGS);
                    352: 
                    353:                                        attr_cast = (ita_attr_settings_t*)attr;
                    354:                                        e = attr_cast->create_enumerator(attr_cast);
                    355:                                        while (e->enumerate(e, &name, &value))
                    356:                                        {
                    357:                                                if (streq(name, unknown_source_str) &&
                    358:                                                        chunk_equals(value, chunk_from_chars('1')))
                    359:                                                {
                    360:                                                        os_state->set_os_settings(os_state,
                    361:                                                                                                OS_SETTINGS_UNKNOWN_SOURCE);
                    362:                                                }
                    363:                                                DBG1(DBG_IMV, "setting '%s'\n  %.*s",
                    364:                                                         name, value.len, value.ptr);
                    365:                                        }
                    366:                                        e->destroy(e);
                    367:                                        break;
                    368:                                }
                    369:                                case ITA_ATTR_DEVICE_ID:
                    370:                                {
                    371:                                        chunk_t value;
                    372: 
                    373:                                        state->set_action_flags(state, IMV_OS_ATTR_DEVICE_ID);
                    374: 
                    375:                                        value = attr->get_value(attr);
                    376:                                        DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
                    377:                                        session->set_device_id(session, value);
                    378:                                        break;
                    379:                                }
                    380:                                default:
                    381:                                        break;
                    382:                        }
                    383:                }
                    384:        }
                    385:        enumerator->destroy(enumerator);
                    386: 
                    387:        if (fatal_error)
                    388:        {
                    389:                state->set_recommendation(state,
                    390:                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                    391:                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
                    392:                assessment = TRUE;
                    393:        }
                    394: 
                    395:        if (assessment)
                    396:        {
                    397:                os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
                    398:                result = out_msg->send_assessment(out_msg);
                    399:                if (result == TNC_RESULT_SUCCESS)
                    400:                {
                    401:                        result = this->agent->provide_recommendation(this->agent, state);
                    402:                }
                    403:        }
                    404:        else
                    405:        {
                    406:                /* send PA-TNC message with the EXCL flag set */
                    407:                result = out_msg->send(out_msg, TRUE);
                    408:        }
                    409:        out_msg->destroy(out_msg);
                    410: 
                    411:        return result;
                    412: }
                    413: 
                    414: METHOD(imv_agent_if_t, receive_message, TNC_Result,
                    415:        private_imv_os_agent_t *this, TNC_ConnectionID id,
                    416:        TNC_MessageType msg_type, chunk_t msg)
                    417: {
                    418:        imv_state_t *state;
                    419:        imv_msg_t *in_msg;
                    420:        TNC_Result result;
                    421: 
                    422:        if (!this->agent->get_state(this->agent, id, &state))
                    423:        {
                    424:                return TNC_RESULT_FATAL;
                    425:        }
                    426:        in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
                    427:        result = receive_msg(this, state, in_msg);
                    428:        in_msg->destroy(in_msg);
                    429: 
                    430:        return result;
                    431: }
                    432: 
                    433: METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
                    434:        private_imv_os_agent_t *this, TNC_ConnectionID id,
                    435:        TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
                    436:        TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
                    437: {
                    438:        imv_state_t *state;
                    439:        imv_msg_t *in_msg;
                    440:        TNC_Result result;
                    441: 
                    442:        if (!this->agent->get_state(this->agent, id, &state))
                    443:        {
                    444:                return TNC_RESULT_FATAL;
                    445:        }
                    446:        in_msg = imv_msg_create_from_long_data(this->agent, state, id,
                    447:                                        src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
                    448:        result = receive_msg(this, state, in_msg);
                    449:        in_msg->destroy(in_msg);
                    450: 
                    451:        return result;
                    452: 
                    453: }
                    454: 
                    455: /**
                    456:  * Build an IETF Attribute Request attribute for missing attributes
                    457:  */
                    458: static pa_tnc_attr_t* build_attr_request(uint32_t received)
                    459: {
                    460:        pa_tnc_attr_t *attr;
                    461:        ietf_attr_attr_request_t *attr_cast;
                    462: 
                    463:        attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
                    464:        attr_cast = (ietf_attr_attr_request_t*)attr;
                    465: 
                    466:        if (!(received & IMV_OS_ATTR_PRODUCT_INFORMATION) ||
                    467:                !(received & IMV_OS_ATTR_STRING_VERSION))
                    468:        {
                    469:                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION);
                    470:                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
                    471:        }
                    472:        if (!(received & IMV_OS_ATTR_NUMERIC_VERSION))
                    473:        {
                    474:                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_NUMERIC_VERSION);
                    475:        }
                    476:        if (!(received & IMV_OS_ATTR_OPERATIONAL_STATUS))
                    477:        {
                    478:                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS);
                    479:        }
                    480:        if (!(received & IMV_OS_ATTR_FORWARDING_ENABLED))
                    481:        {
                    482:                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED);
                    483:        }
                    484:        if (!(received & IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED))
                    485:        {
                    486:                attr_cast->add(attr_cast, PEN_IETF,
                    487:                                                                  IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
                    488:        }
                    489:        if (!(received & IMV_OS_ATTR_DEVICE_ID))
                    490:        {
                    491:                attr_cast->add(attr_cast, PEN_ITA,  ITA_ATTR_DEVICE_ID);
                    492:        }
                    493: 
                    494:        return attr;
                    495: }
                    496: 
                    497: METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                    498:        private_imv_os_agent_t *this, TNC_ConnectionID id)
                    499: {
                    500:        imv_msg_t *out_msg;
                    501:        imv_state_t *state;
                    502:        imv_session_t *session;
                    503:        imv_workitem_t *workitem;
                    504:        imv_os_state_t *os_state;
                    505:        imv_os_handshake_state_t handshake_state;
                    506:        pa_tnc_attr_t *attr;
                    507:        TNC_IMVID imv_id;
                    508:        TNC_Result result = TNC_RESULT_SUCCESS;
                    509:        bool no_workitems = TRUE;
                    510:        enumerator_t *enumerator;
                    511:        uint32_t received;
                    512: 
                    513:        if (!this->agent->get_state(this->agent, id, &state))
                    514:        {
                    515:                return TNC_RESULT_FATAL;
                    516:        }
                    517:        os_state = (imv_os_state_t*)state;
                    518:        handshake_state = os_state->get_handshake_state(os_state);
                    519:        received = state->get_action_flags(state);
                    520:        session = state->get_session(state);
                    521:        imv_id = this->agent->get_id(this->agent);
                    522: 
                    523:        if (handshake_state == IMV_OS_STATE_END)
                    524:        {
                    525:                return TNC_RESULT_SUCCESS;
                    526:        }
                    527: 
                    528:        /* create an empty out message - we might need it */
                    529:        out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
                    530:                                                         msg_types[0]);
                    531: 
                    532:        if (handshake_state == IMV_OS_STATE_INIT)
                    533:        {
                    534:                size_t max_attr_size = INSTALLED_PACKAGES_MAX_ATTR_SIZE;
                    535:                size_t max_seg_size;
                    536:                seg_contract_t *contract;
                    537:                seg_contract_manager_t *contracts;
                    538:                char buf[BUF_LEN];
                    539: 
                    540:                /* Determine maximum PA-TNC attribute segment size */
                    541:                max_seg_size = state->get_max_msg_len(state)
                    542:                                                                - PA_TNC_HEADER_SIZE
                    543:                                                                - PA_TNC_ATTR_HEADER_SIZE
                    544:                                                                - TCG_SEG_ATTR_SEG_ENV_HEADER;
                    545: 
                    546:                /* Announce support of PA-TNC segmentation to IMC */
                    547:                contract = seg_contract_create(msg_types[0], max_attr_size,
                    548:                                                                                max_seg_size, TRUE, imv_id, FALSE);
                    549:                contract->get_info_string(contract, buf, BUF_LEN, TRUE);
                    550:                DBG2(DBG_IMV, "%s", buf);
                    551:                contracts = state->get_contracts(state);
                    552:                contracts->add_contract(contracts, contract);
                    553:                attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
                    554:                out_msg->add_attribute(out_msg, attr);
                    555: 
                    556:                if ((received & IMV_OS_ATTR_MUST) != IMV_OS_ATTR_MUST)
                    557:                {
                    558:                        /* create attribute request for missing mandatory attributes */
                    559:                        out_msg->add_attribute(out_msg, build_attr_request(received));
                    560:                }
                    561:        }
                    562: 
                    563:        if (handshake_state < IMV_OS_STATE_POLICY_START)
                    564:        {
                    565:                if (session->get_policy_started(session))
                    566:                {
                    567:                        /* the policy script has already been started by another IMV */
                    568:                        handshake_state = IMV_OS_STATE_POLICY_START;
                    569:                }
                    570:                else
                    571:                {
                    572:                        if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) &&
                    573:                                 (received & IMV_OS_ATTR_STRING_VERSION)) &&
                    574:                                ((received & IMV_OS_ATTR_DEVICE_ID) ||
                    575:                                 (handshake_state == IMV_OS_STATE_ATTR_REQ)))
                    576:                        {
                    577:                                if (!session->get_device_id(session, NULL))
                    578:                                {
                    579:                                        session->set_device_id(session, chunk_empty);
                    580:                                }
                    581:                                if (imcv_db)
                    582:                                {
                    583:                                        /* start the policy script */
                    584:                                        if (!imcv_db->policy_script(imcv_db, session, TRUE))
                    585:                                        {
                    586:                                                DBG1(DBG_IMV, "error in policy script start");
                    587:                                        }
                    588:                                }
                    589:                                else
                    590:                                {
                    591:                                        DBG2(DBG_IMV, "no workitems available - "
                    592:                                                                  "no evaluation possible");
                    593:                                        state->set_recommendation(state,
                    594:                                                                        TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
                    595:                                                                        TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
                    596:                                        session->set_policy_started(session, TRUE);
                    597:                                }
                    598:                                handshake_state = IMV_OS_STATE_POLICY_START;
                    599:                        }
                    600:                        else if (handshake_state == IMV_OS_STATE_ATTR_REQ)
                    601:                        {
                    602:                                /**
                    603:                                 * both the IETF Product Information and IETF String Version
                    604:                                 * attribute should have been present
                    605:                                 */
                    606:                                state->set_recommendation(state,
                    607:                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                    608:                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
                    609: 
                    610:                                /* send assessment */
                    611:                                result = out_msg->send_assessment(out_msg);
                    612:                                out_msg->destroy(out_msg);
                    613: 
                    614:                                if (result != TNC_RESULT_SUCCESS)
                    615:                                {
                    616:                                        return result;
                    617:                                }
                    618:                                return this->agent->provide_recommendation(this->agent, state);
                    619:                        }
                    620:                        else
                    621:                        {
                    622:                                handshake_state = IMV_OS_STATE_ATTR_REQ;
                    623:                        }
                    624:                }
                    625:                os_state->set_handshake_state(os_state, handshake_state);
                    626:        }
                    627: 
                    628:        if (handshake_state == IMV_OS_STATE_POLICY_START)
                    629:        {
                    630:                enumerator = session->create_workitem_enumerator(session);
                    631:                if (enumerator)
                    632:                {
                    633:                        while (enumerator->enumerate(enumerator, &workitem))
                    634:                        {
                    635:                                if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY)
                    636:                                {
                    637:                                        continue;
                    638:                                }
                    639: 
                    640:                                switch (workitem->get_type(workitem))
                    641:                                {
                    642:                                        case IMV_WORKITEM_PACKAGES:
                    643:                                                attr = ietf_attr_attr_request_create(PEN_IETF,
                    644:                                                                                IETF_ATTR_INSTALLED_PACKAGES);
                    645:                                                out_msg->add_attribute(out_msg, attr);
                    646:                                                break;
                    647:                                        case IMV_WORKITEM_UNKNOWN_SOURCE:
                    648:                                                attr = ita_attr_get_settings_create(unknown_source_str);
                    649:                                                out_msg->add_attribute(out_msg, attr);
                    650:                                                break;
                    651:                                        case IMV_WORKITEM_FORWARDING:
                    652:                                        case IMV_WORKITEM_DEFAULT_PWD:
                    653:                                                break;
                    654:                                        default:
                    655:                                                continue;
                    656:                                }
                    657:                                workitem->set_imv_id(workitem, imv_id);
                    658:                                no_workitems = FALSE;
                    659:                        }
                    660:                        enumerator->destroy(enumerator);
                    661: 
                    662:                        if (no_workitems)
                    663:                        {
                    664:                                DBG2(DBG_IMV, "IMV %d has no workitems - "
                    665:                                                          "no evaluation requested", imv_id);
                    666:                                state->set_recommendation(state,
                    667:                                                                TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
                    668:                                                                TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
                    669:                        }
                    670:                        handshake_state = IMV_OS_STATE_WORKITEMS;
                    671:                        os_state->set_handshake_state(os_state, handshake_state);
                    672:                }
                    673:        }
                    674: 
                    675:        if (handshake_state == IMV_OS_STATE_WORKITEMS)
                    676:        {
                    677:                TNC_IMV_Evaluation_Result eval;
                    678:                TNC_IMV_Action_Recommendation rec;
                    679:                char result_str[BUF_LEN];
                    680:                bool fail;
                    681: 
                    682:                enumerator = session->create_workitem_enumerator(session);
                    683:                while (enumerator->enumerate(enumerator, &workitem))
                    684:                {
                    685:                        if (workitem->get_imv_id(workitem) != imv_id)
                    686:                        {
                    687:                                continue;
                    688:                        }
                    689: 
                    690:                        switch (workitem->get_type(workitem))
                    691:                        {
                    692:                                case IMV_WORKITEM_PACKAGES:
                    693:                                {
                    694:                                        int count, count_update, count_blacklist, count_ok;
                    695: 
                    696:                                        if (!(received & IMV_OS_ATTR_INSTALLED_PACKAGES) ||
                    697:                                                os_state->get_missing(os_state) > 0)
                    698:                                        {
                    699:                                                continue;
                    700:                                        }
                    701:                                        os_state->get_count(os_state, &count, &count_update,
                    702:                                                                                &count_blacklist, &count_ok);
                    703:                                        fail = count_update || count_blacklist;
                    704:                                        eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR :
                    705:                                                                  TNC_IMV_EVALUATION_RESULT_COMPLIANT;
                    706:                                        snprintf(result_str, BUF_LEN, "processed %d packages: "
                    707:                                                        "%d vulnerable, %d blacklisted, %d ok, %d unknown",
                    708:                                                        count, count_update, count_blacklist, count_ok,
                    709:                                                        count - count_update - count_blacklist - count_ok);
                    710:                                        break;
                    711:                                }
                    712:                                case IMV_WORKITEM_UNKNOWN_SOURCE:
                    713:                                        if (!(received & IMV_OS_ATTR_SETTINGS))
                    714:                                        {
                    715:                                                continue;
                    716:                                        }
                    717:                                        fail = os_state->get_os_settings(os_state) &
                    718:                                                                OS_SETTINGS_UNKNOWN_SOURCE;
                    719:                                        eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR :
                    720:                                                                  TNC_IMV_EVALUATION_RESULT_COMPLIANT;
                    721:                                        snprintf(result_str, BUF_LEN, "unknown sources%s enabled",
                    722:                                                         fail ? "" : " not");
                    723:                                        break;
                    724:                                case IMV_WORKITEM_FORWARDING:
                    725:                                        if (!(received & IMV_OS_ATTR_FORWARDING_ENABLED))
                    726:                                        {
                    727:                                                continue;
                    728:                                        }
                    729:                                        fail = os_state->get_os_settings(os_state) &
                    730:                                                                OS_SETTINGS_FWD_ENABLED;
                    731:                                        eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR :
                    732:                                                                  TNC_IMV_EVALUATION_RESULT_COMPLIANT;
                    733:                                        snprintf(result_str, BUF_LEN, "forwarding%s enabled",
                    734:                                                         fail ? "" : " not");
                    735:                                        break;
                    736:                                case IMV_WORKITEM_DEFAULT_PWD:
                    737:                                        if (!(received & IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED))
                    738:                                        {
                    739:                                                continue;
                    740:                                        }
                    741:                                        fail = os_state->get_os_settings(os_state) &
                    742:                                                                OS_SETTINGS_DEFAULT_PWD_ENABLED;
                    743:                                        eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR :
                    744:                                                                  TNC_IMV_EVALUATION_RESULT_COMPLIANT;
                    745:                                        snprintf(result_str, BUF_LEN, "factory default password%s enabled",
                    746:                                                         fail ? "" : " not");
                    747:                                        break;
                    748:                                default:
                    749:                                        continue;
                    750:                        }
                    751:                        session->remove_workitem(session, enumerator);
                    752:                        rec = workitem->set_result(workitem, result_str, eval);
                    753:                        state->update_recommendation(state, rec, eval);
                    754:                        imcv_db->finalize_workitem(imcv_db, workitem);
                    755:                        workitem->destroy(workitem);
                    756:                }
                    757:                enumerator->destroy(enumerator);
                    758: 
                    759:                /* finalized all workitems ? */
                    760:                if (session->get_workitem_count(session, imv_id) == 0)
                    761:                {
                    762:                        os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
                    763: 
                    764:                        result = out_msg->send_assessment(out_msg);
                    765:                        out_msg->destroy(out_msg);
                    766:                        if (result != TNC_RESULT_SUCCESS)
                    767:                        {
                    768:                                return result;
                    769:                        }
                    770:                        return this->agent->provide_recommendation(this->agent, state);
                    771:                }
                    772:        }
                    773: 
                    774:        /* send non-empty PA-TNC message with excl flag not set */
                    775:        if (out_msg->get_attribute_count(out_msg))
                    776:        {
                    777:                result = out_msg->send(out_msg, FALSE);
                    778:        }
                    779:        out_msg->destroy(out_msg);
                    780: 
                    781:        return result;
                    782: }
                    783: 
                    784: METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
                    785:        private_imv_os_agent_t *this, TNC_ConnectionID id)
                    786: {
                    787:        imv_state_t *state;
                    788: 
                    789:        if (!this->agent->get_state(this->agent, id, &state))
                    790:        {
                    791:                return TNC_RESULT_FATAL;
                    792:        }
                    793:        return this->agent->provide_recommendation(this->agent, state);
                    794: }
                    795: 
                    796: METHOD(imv_agent_if_t, destroy, void,
                    797:        private_imv_os_agent_t *this)
                    798: {
                    799:        DESTROY_IF(this->agent);
                    800:        DESTROY_IF(this->db);
                    801:        free(this);
                    802: }
                    803: 
                    804: /**
                    805:  * Described in header.
                    806:  */
                    807: imv_agent_if_t *imv_os_agent_create(const char *name, TNC_IMVID id,
                    808:                                                                        TNC_Version *actual_version)
                    809: {
                    810:        private_imv_os_agent_t *this;
                    811:        imv_agent_t *agent;
                    812: 
                    813:        agent = imv_agent_create(name, msg_types, countof(msg_types), id,
                    814:                                                         actual_version);
                    815:        if (!agent)
                    816:        {
                    817:                return NULL;
                    818:        }
                    819: 
                    820:        INIT(this,
                    821:                .public = {
                    822:                        .bind_functions = _bind_functions,
                    823:                        .notify_connection_change = _notify_connection_change,
                    824:                        .receive_message = _receive_message,
                    825:                        .receive_message_long = _receive_message_long,
                    826:                        .batch_ending = _batch_ending,
                    827:                        .solicit_recommendation = _solicit_recommendation,
                    828:                        .destroy = _destroy,
                    829:                },
                    830:                .agent = agent,
                    831:                .db = imv_os_database_create(imcv_db),
                    832:        );
                    833: 
                    834:        return &this->public;
                    835: }
                    836: 

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