Use PWG HCD PA-TNC subtypes to transport HCD attributes
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 26 Jul 2015 09:41:08 +0000 (11:41 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 18 Aug 2015 19:25:39 +0000 (21:25 +0200)
src/libimcv/plugins/imc_hcd/imc_hcd.c
src/libimcv/plugins/imc_os/imc_os.c
src/libimcv/plugins/imv_hcd/imv_hcd_agent.c
src/libimcv/plugins/imv_hcd/imv_hcd_state.c
src/libimcv/plugins/imv_hcd/imv_hcd_state.h

index e50758f..7043837 100644 (file)
@@ -23,6 +23,7 @@
 #include <generic/generic_attr_string.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
+#include "ietf/ietf_attr_fwd_enabled.h"
 #include <pwg/pwg_attr.h>
 #include <pwg/pwg_attr_vendor_smi_code.h>
 
@@ -47,6 +48,22 @@ static pen_type_t msg_types[] = {
 static imc_agent_t *imc_hcd;
 static imc_os_info_t *os;
 
+typedef struct section_subtype_t section_subtype_t;
+
+struct section_subtype_t {
+       char *section;
+       pa_subtype_pwg_t subtype;
+};
+
+static section_subtype_t section_subtypes[] = {
+       { "system",    PA_SUBTYPE_PWG_HCD_SYSTEM    },
+       { "console",   PA_SUBTYPE_PWG_HCD_CONSOLE   },
+       { "marker",    PA_SUBTYPE_PWG_HCD_MARKER    },
+       { "finisher",  PA_SUBTYPE_PWG_HCD_FINISHER  },
+       { "interface", PA_SUBTYPE_PWG_HCD_INTERFACE },
+       { "scanner"  , PA_SUBTYPE_PWG_HCD_SCANNER   }
+};
+
 typedef struct quadruple_t quadruple_t;
 
 struct quadruple_t {
@@ -167,9 +184,7 @@ static void add_default_pwd_enabled(imc_msg_t *msg)
        pa_tnc_attr_t *attr;
        bool status;
 
-       status = lib->settings->get_bool(lib->settings,
-                               "%s.plugins.imc-hcd.subtypes.system.default_password_enabled",
-                               FALSE, lib->ns);
+       status = os->get_default_pwd_status(os);
        DBG2(DBG_IMC, "  %N: %s", pwg_attr_names, PWG_HCD_DEFAULT_PWD_ENABLED,
                                status ? "yes" : "no");
        attr = generic_attr_bool_create(status,
@@ -183,14 +198,12 @@ static void add_default_pwd_enabled(imc_msg_t *msg)
 static void add_forwarding_enabled(imc_msg_t *msg)
 {
        pa_tnc_attr_t *attr;
-       bool status;
+       os_fwd_status_t fwd_status;
 
-       status = lib->settings->get_bool(lib->settings,
-                               "%s.plugins.imc-hcd.subtypes.system.forwarding_enabled",
-                               FALSE, lib->ns);
-       DBG2(DBG_IMC, "  %N: %s", pwg_attr_names, PWG_HCD_FORWARDING_ENABLED,
-                               status ? "yes" : "no");
-       attr = generic_attr_bool_create(status,
+       fwd_status = os->get_fwd_status(os);
+       DBG2(DBG_IMC, "  %N: %N", pwg_attr_names, PWG_HCD_FORWARDING_ENABLED,
+                               os_fwd_status_names, fwd_status);
+       attr = ietf_attr_fwd_enabled_create(fwd_status,
                                pen_type_create(PEN_PWG, PWG_HCD_FORWARDING_ENABLED));
        msg->add_attribute(msg, attr);
 }
@@ -483,37 +496,24 @@ TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
        while (enumerator->enumerate(enumerator, &section) &&
                   result == TNC_RESULT_SUCCESS)
        {
-               if (streq(section, "system"))
-               {
-                       subtype = PA_SUBTYPE_PWG_HCD_SYSTEM;
-               }
-               else if (streq(section, "console"))
-               {
-                       subtype = PA_SUBTYPE_PWG_HCD_CONSOLE;
-               }
-               else if (streq(section, "marker"))
-               {
-                       subtype = PA_SUBTYPE_PWG_HCD_MARKER;
-               }
-               else if (streq(section, "finisher"))
-               {
-                       subtype = PA_SUBTYPE_PWG_HCD_FINISHER;
-               }
-               else if (streq(section, "interface"))
-               {
-                       subtype = PA_SUBTYPE_PWG_HCD_INTERFACE;
-               }
-               else if (streq(section, "scanner"))
+               subtype = PA_SUBTYPE_PWG_HCD_UNKNOWN;
+
+               for (i = 0; i < countof(section_subtypes); i++)
                {
-                       subtype = PA_SUBTYPE_PWG_HCD_SCANNER;
+                       if (streq(section, section_subtypes[i].section))
+                       {
+                               subtype = section_subtypes[i].subtype;
+                               break;
+                       }
                }
-               else
+               if (subtype == PA_SUBTYPE_PWG_HCD_UNKNOWN)
                {
                        DBG1(DBG_IMC, "HCD subtype '%s' not supported", section);
                        continue;
                }
                DBG2(DBG_IMC, "retrieving attributes for PA subtype %N/%N",
                         pen_names, PEN_PWG, pa_subtype_pwg_names, subtype);
+
                msg_type = pen_type_create(PEN_PWG, subtype);
                out_msg = imc_msg_create(imc_hcd, state, connection_id, imc_id,
                                                                 TNC_IMVID_ANY, msg_type);
@@ -556,8 +556,10 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
        imc_msg_t *out_msg;
        enumerator_t *enumerator;
        pa_tnc_attr_t *attr;
-       pen_type_t type;
+       pen_type_t type, msg_type;
        TNC_Result result;
+       char *section = NULL;
+       int i;
        bool fatal_error = FALSE, pushed_info;
 
        /* generate an outgoing PA-TNC message - we might need it */
@@ -570,6 +572,16 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
                out_msg->destroy(out_msg);
                return result;
        }
+       msg_type = in_msg->get_msg_type(in_msg);
+
+       for (i = 0; i < countof(section_subtypes); i++)
+       {
+               if (msg_type.type == section_subtypes[i].subtype)
+               {
+                       section = section_subtypes[i].section;
+                       break;
+               }
+       }
        pushed_info = lib->settings->get_bool(lib->settings,
                                                "%s.plugins.imc-hcd.push_info", FALSE, lib->ns);
 
@@ -597,7 +609,7 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
                                                switch (entry->type)
                                                {
                                                        case PWG_HCD_ATTRS_NATURAL_LANG:
-                                                               add_attrs_natural_lang(out_msg, "system");
+                                                               add_attrs_natural_lang(out_msg, section);
                                                                break;
                                                        case PWG_HCD_DEFAULT_PWD_ENABLED:
                                                                add_default_pwd_enabled(out_msg);
@@ -643,13 +655,13 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
                                                switch (entry->type)
                                                {
                                                        case PWG_HCD_FIRMWARE_NAME:
-                                                               add_quadruple(out_msg, "system", &quadruples[0]);
+                                                               add_quadruple(out_msg, section, &quadruples[0]);
                                                                break;
                                                        case PWG_HCD_RESIDENT_APP_NAME:
-                                                               add_quadruple(out_msg, "system", &quadruples[1]);
+                                                               add_quadruple(out_msg, section, &quadruples[1]);
                                                                break;
                                                        case PWG_HCD_USER_APP_NAME:
-                                                               add_quadruple(out_msg, "system", &quadruples[2]);
+                                                               add_quadruple(out_msg, section, &quadruples[2]);
                                                                break;
                                                        default:
                                                                break;
index 86cf06d..af1862a 100644 (file)
@@ -22,6 +22,7 @@
 #include <generic/generic_attr_string.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
+#include "ietf/ietf_attr_fwd_enabled.h"
 #include <ietf/ietf_attr_installed_packages.h>
 #include <ietf/ietf_attr_numeric_version.h>
 #include <ietf/ietf_attr_op_status.h>
@@ -211,10 +212,9 @@ static void add_fwd_enabled(imc_msg_t *msg)
        os_fwd_status_t fwd_status;
 
        fwd_status = os->get_fwd_status(os);
-       DBG1(DBG_IMC, "IPv4 forwarding is %N",
-                                  os_fwd_status_names, fwd_status);
-       attr = generic_attr_bool_create(fwd_status, pen_type_create(PEN_IETF,
-                                                                       IETF_ATTR_FORWARDING_ENABLED));
+       DBG1(DBG_IMC, "IPv4 forwarding is %N", os_fwd_status_names, fwd_status);
+       attr = ietf_attr_fwd_enabled_create(fwd_status,
+                               pen_type_create(PEN_IETF, IETF_ATTR_FORWARDING_ENABLED));
        msg->add_attribute(msg, attr);
 }
 
@@ -224,10 +224,12 @@ static void add_fwd_enabled(imc_msg_t *msg)
 static void add_default_pwd_enabled(imc_msg_t *msg)
 {
        pa_tnc_attr_t *attr;
+       bool status;
 
-       DBG1(DBG_IMC, "factory default password is disabled");
-       attr = generic_attr_bool_create(FALSE, pen_type_create(PEN_IETF,
-                                                                       IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED));
+       status = os->get_default_pwd_status(os);
+       DBG1(DBG_IMC, "factory default password is %sabled", status ? "en" : "dis");
+       attr = generic_attr_bool_create(status,
+                       pen_type_create(PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED));
        msg->add_attribute(msg, attr);
 }
 
index 9d39801..5fce45d 100644 (file)
@@ -27,6 +27,7 @@
 #include <generic/generic_attr_string.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
+#include <ietf/ietf_attr_fwd_enabled.h>
 #include <pwg/pwg_attr.h>
 #include <pwg/pwg_attr_vendor_smi_code.h>
 #include "tcg/seg/tcg_seg_attr_max_size.h"
@@ -41,7 +42,6 @@
 #define HCD_MAX_ATTR_SIZE      10000000
 
 typedef struct private_imv_hcd_agent_t private_imv_hcd_agent_t;
-typedef enum imv_hcd_attr_t imv_hcd_attr_t;
 
 /* Subscribed PA-TNC message subtypes */
 static pen_type_t msg_types[] = {
@@ -54,60 +54,42 @@ static pen_type_t msg_types[] = {
        { PEN_PWG, PA_SUBTYPE_PWG_HCD_SCANNER }
 };
 
-/**
- * Flag set when corresponding attribute has been received
- */
-enum imv_hcd_attr_t {
-       IMV_HCD_ATTR_NONE =                          0,
-       IMV_HCD_ATTR_NATURAL_LANG =              (1<<0),
-       IMV_HCD_ATTR_DEFAULT_PWD_ENABLED =       (1<<1),
-       IMV_HCD_ATTR_FIREWALL_SETTING =          (1<<2),
-       IMV_HCD_ATTR_FIRMWARE_NAME =             (1<<3),
-       IMV_HCD_ATTR_FORWARDING_ENABLED =        (1<<4),
-       IMV_HCD_ATTR_MACHINE_TYPE_MODEL =        (1<<5),
-       IMV_HCD_ATTR_PSTN_FAX_ENABLED =          (1<<6),
-       IMV_HCD_ATTR_RESIDENT_APP_NAME =         (1<<7),
-       IMV_HCD_ATTR_TIME_SOURCE =               (1<<8),
-       IMV_HCD_ATTR_USER_APP_ENABLED =          (1<<9),
-       IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED =  (1<<10),
-       IMV_HCD_ATTR_USER_APP_NAME =             (1<<11),
-       IMV_HCD_ATTR_VENDOR_NAME =               (1<<12),
-       IMV_HCD_ATTR_VENDOR_SMI_CODE =           (1<<13),
-       IMV_HCD_ATTR_MUST =                      (1<<14)-1
-};
-
 static imv_hcd_attr_t attr_type_to_flag(pwg_attr_t attr_type)
 {
        switch (attr_type)
        {
-               case PWG_HCD_ATTRS_NATURAL_LANG:
-                       return IMV_HCD_ATTR_NATURAL_LANG;
                case PWG_HCD_DEFAULT_PWD_ENABLED:
                        return IMV_HCD_ATTR_DEFAULT_PWD_ENABLED;
                case PWG_HCD_FIREWALL_SETTING:
                        return IMV_HCD_ATTR_FIREWALL_SETTING;
-               case PWG_HCD_FIRMWARE_NAME:
-                       return IMV_HCD_ATTR_FIRMWARE_NAME;
                case PWG_HCD_FORWARDING_ENABLED:
                        return IMV_HCD_ATTR_FORWARDING_ENABLED;
                case PWG_HCD_MACHINE_TYPE_MODEL:
                        return IMV_HCD_ATTR_MACHINE_TYPE_MODEL;
                case PWG_HCD_PSTN_FAX_ENABLED:
                        return IMV_HCD_ATTR_PSTN_FAX_ENABLED;
-               case PWG_HCD_RESIDENT_APP_NAME:
-                       return IMV_HCD_ATTR_RESIDENT_APP_NAME;
                case PWG_HCD_TIME_SOURCE:
                        return IMV_HCD_ATTR_TIME_SOURCE;
                case PWG_HCD_USER_APP_ENABLED:
                        return IMV_HCD_ATTR_USER_APP_ENABLED;
                case PWG_HCD_USER_APP_PERSIST_ENABLED:
                        return IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED;
-               case PWG_HCD_USER_APP_NAME:
-                       return IMV_HCD_ATTR_USER_APP_NAME;
                case PWG_HCD_VENDOR_NAME:
                        return IMV_HCD_ATTR_VENDOR_NAME;
                case PWG_HCD_VENDOR_SMI_CODE:
                        return IMV_HCD_ATTR_VENDOR_SMI_CODE;
+               case PWG_HCD_CERTIFICATION_STATE:
+                       return IMV_HCD_ATTR_CERTIFICATION_STATE;
+               case PWG_HCD_CONFIGURATION_STATE:
+                       return IMV_HCD_ATTR_CONFIGURATION_STATE;
+               case PWG_HCD_ATTRS_NATURAL_LANG:
+                       return IMV_HCD_ATTR_NATURAL_LANG;
+               case PWG_HCD_FIRMWARE_NAME:
+                       return IMV_HCD_ATTR_FIRMWARE_NAME;
+               case PWG_HCD_RESIDENT_APP_NAME:
+                       return IMV_HCD_ATTR_RESIDENT_APP_NAME;
+               case PWG_HCD_USER_APP_NAME:
+                       return IMV_HCD_ATTR_USER_APP_NAME;
                default:
                        return IMV_HCD_ATTR_NONE;
        }
@@ -194,7 +176,8 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
        imv_msg_t *out_msg;
        imv_hcd_state_t *hcd_state;
        pa_tnc_attr_t *attr;
-       pen_type_t type;
+       enum_name_t *pa_subtype_names; 
+       pen_type_t type, msg_type;
        TNC_Result result;
        bool fatal_error = FALSE, assessment = FALSE;
        enumerator_t *enumerator;
@@ -211,6 +194,20 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
                out_msg->destroy(out_msg);
                return result;
        }
+       msg_type = in_msg->get_msg_type(in_msg);
+       pa_subtype_names = get_pa_subtype_names(msg_type.vendor_id);
+       DBG2(DBG_IMV, "received attributes for PA subtype %N/%N",
+                pen_names, msg_type.vendor_id, pa_subtype_names, msg_type.type);
+
+       /* set current subtype */
+       if (msg_type.vendor_id == PEN_IETF)
+       {
+               hcd_state->set_subtype(hcd_state, PA_SUBTYPE_PWG_HCD_SYSTEM);
+       }
+       else
+       {
+               hcd_state->set_subtype(hcd_state, msg_type.type);
+       }
 
        /* analyze PA-TNC attributes */
        enumerator = in_msg->create_attribute_enumerator(in_msg);
@@ -218,7 +215,41 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
        {
                type = attr->get_type(attr);
 
-               if (type.vendor_id == PEN_PWG)
+               if (type.vendor_id == PEN_IETF)
+               {
+                       switch (type.type)
+                       {
+                               case IETF_ATTR_FORWARDING_ENABLED:
+                               {
+                                       ietf_attr_fwd_enabled_t *attr_cast;
+                                       os_fwd_status_t fwd_status;
+
+                                       attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+                                       fwd_status = attr_cast->get_status(attr_cast);
+                                       DBG2(DBG_IMV, "  %N: %N", ietf_attr_names, type.type,
+                                                                  os_fwd_status_names, fwd_status);
+                                       state->set_action_flags(state,
+                                                                                       IMV_HCD_ATTR_FORWARDING_ENABLED);
+                                       break;
+                               }
+                               case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
+                               {
+                                       generic_attr_bool_t *attr_cast;
+                                       bool status;
+
+                                       attr_cast = (generic_attr_bool_t*)attr;
+                                       status = attr_cast->get_status(attr_cast);
+                                       DBG2(DBG_IMV, "  %N: %s", ietf_attr_names, type.type,
+                                                                  status ? "yes" : "no");
+                                       state->set_action_flags(state,
+                                                                                       IMV_HCD_ATTR_DEFAULT_PWD_ENABLED);
+                                       break;
+                               }
+                               default:
+                                       break;
+                       }
+               }
+               else if (type.vendor_id == PEN_PWG)
                {
                        state->set_action_flags(state, attr_type_to_flag(type.type));
 
@@ -241,7 +272,7 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
                                        chunk_t value;
 
                                        value = attr->get_value(attr);
-                                       DBG2(DBG_IMV, "%N: %.*s", pwg_attr_names, type.type,
+                                       DBG2(DBG_IMV, "  %N: %.*s", pwg_attr_names, type.type,
                                                                   value.len, value.ptr);
                                        break;
                                }
@@ -252,7 +283,7 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
                                        chunk_t value;
 
                                        value = attr->get_value(attr);
-                                       DBG2(DBG_IMV, "%N: %#B", pwg_attr_names, type.type, &value);
+                                       DBG2(DBG_IMV, "  %N: %#B", pwg_attr_names, type.type, &value);
                                        break;
                                }
                                case PWG_HCD_CERTIFICATION_STATE:
@@ -261,11 +292,10 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
                                        chunk_t value;
 
                                        value = attr->get_value(attr);
-                                       DBG2(DBG_IMV, "%N: %B", pwg_attr_names, type.type, &value);
+                                       DBG2(DBG_IMV, "  %N: %B", pwg_attr_names, type.type, &value);
                                        break;
                                }
                                case PWG_HCD_DEFAULT_PWD_ENABLED:
-                               case PWG_HCD_FORWARDING_ENABLED:
                                case PWG_HCD_PSTN_FAX_ENABLED:
                                case PWG_HCD_USER_APP_ENABLED:
                                case PWG_HCD_USER_APP_PERSIST_ENABLED:
@@ -275,17 +305,28 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
 
                                        attr_cast = (generic_attr_bool_t*)attr;
                                        status = attr_cast->get_status(attr_cast);
-                                       DBG2(DBG_IMV, "%N: %s", pwg_attr_names, type.type,
+                                       DBG2(DBG_IMV, "  %N: %s", pwg_attr_names, type.type,
                                                                   status ? "yes" : "no");
 
                                        if (type.type == PWG_HCD_USER_APP_ENABLED && !status)
                                        {
                                                /* do not request user applications */
-                                               state->set_action_flags(state,
-                                                                                               IMV_HCD_ATTR_USER_APP_NAME);
+                                               hcd_state->set_user_app_disabled(hcd_state);
                                        }               
                                        break;
                                }
+                               case PWG_HCD_FORWARDING_ENABLED:
+                               {
+                                       ietf_attr_fwd_enabled_t *attr_cast;
+                                       os_fwd_status_t fwd_status;
+
+                                       attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+                                       fwd_status = attr_cast->get_status(attr_cast);
+                                       DBG2(DBG_IMV, "  %N: %N", pwg_attr_names, type.type,
+                                                                  os_fwd_status_names, fwd_status);
+                                       break;
+                               }
+
                                case PWG_HCD_VENDOR_SMI_CODE:
                                {
                                        pwg_attr_vendor_smi_code_t *attr_cast;
@@ -293,7 +334,7 @@ static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
 
                                        attr_cast = (pwg_attr_vendor_smi_code_t*)attr;
                                        smi_code = attr_cast->get_vendor_smi_code(attr_cast);
-                                       DBG2(DBG_IMV, "%N: 0x%06x (%u)", pwg_attr_names, type.type,
+                                       DBG2(DBG_IMV, "  %N: 0x%06x (%u)", pwg_attr_names, type.type,
                                                                  smi_code, smi_code);
                                        break;
                                }
@@ -439,9 +480,14 @@ static pa_tnc_attr_t* build_attr_request(uint32_t received)
        {
                attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_VENDOR_SMI_CODE);
        }
-       attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CERTIFICATION_STATE);
-       attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CONFIGURATION_STATE);
-
+       if (!(received & IMV_HCD_ATTR_CERTIFICATION_STATE))
+       {
+               attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CERTIFICATION_STATE);
+       }
+       if (!(received & IMV_HCD_ATTR_CONFIGURATION_STATE))
+       {
+               attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CONFIGURATION_STATE);
+       }
        return attr;
 }
 
@@ -455,7 +501,6 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
        pa_tnc_attr_t *attr;
        TNC_IMVID imv_id;
        TNC_Result result = TNC_RESULT_SUCCESS;
-       uint32_t received;
 
        if (!this->agent->get_state(this->agent, id, &state))
        {
@@ -463,7 +508,6 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
        }
        hcd_state = (imv_hcd_state_t*)state;
        handshake_state = hcd_state->get_handshake_state(hcd_state);
-       received = state->get_action_flags(state);
        imv_id = this->agent->get_id(this->agent);
 
        if (handshake_state == IMV_HCD_STATE_END)
@@ -471,10 +515,6 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                return TNC_RESULT_SUCCESS;
        }
 
-       /* create an empty out message - we might need it */
-       out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
-                                                        msg_types[0]);
-
        if (handshake_state == IMV_HCD_STATE_INIT)
        {
                size_t max_attr_size = HCD_MAX_ATTR_SIZE;
@@ -482,6 +522,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                seg_contract_t *contract;
                seg_contract_manager_t *contracts;
                char buf[BUF_LEN];
+               uint32_t received;
+               int i;
 
                /* Determine maximum PA-TNC attribute segment size */
                max_seg_size = state->get_max_msg_len(state)
@@ -490,32 +532,42 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                                                                - TCG_SEG_ATTR_SEG_ENV_HEADER
                                                                - PA_TNC_ATTR_HEADER_SIZE
                                                                - TCG_SEG_ATTR_MAX_SIZE_SIZE;
-
-               /* Announce support of PA-TNC segmentation to IMC */
-               contract = seg_contract_create(msg_types[0], max_attr_size,
-                                                                               max_seg_size, TRUE, imv_id, FALSE);
-               contract->get_info_string(contract, buf, BUF_LEN, TRUE);
-               DBG2(DBG_IMV, "%s", buf);
                contracts = state->get_contracts(state);
-               contracts->add_contract(contracts, contract);
-               attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
-               out_msg->add_attribute(out_msg, attr);
 
-               if ((received & IMV_HCD_ATTR_MUST) != IMV_HCD_ATTR_MUST)
+               for (i = 1; i < countof(msg_types); i++)
                {
-                       /* create attribute request for missing mandatory attributes */
-                       out_msg->add_attribute(out_msg, build_attr_request(received));
+                       out_msg = imv_msg_create(this->agent, state, id, imv_id,
+                                                                        TNC_IMCID_ANY, msg_types[i]);
+
+                       /* Announce support of PA-TNC segmentation to IMC */
+                       contract = seg_contract_create(msg_types[i], max_attr_size,
+                                                                                  max_seg_size, TRUE, imv_id, FALSE);
+                       contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+                       DBG2(DBG_IMV, "%s", buf);
+                       contracts->add_contract(contracts, contract);
+                       attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size,
+                                                                                               TRUE);
+                       out_msg->add_attribute(out_msg, attr);
+
+                       hcd_state->set_subtype(hcd_state, msg_types[i].type);   
+                       received = state->get_action_flags(state);
+
+                       if ((received & IMV_HCD_ATTR_MUST) != IMV_HCD_ATTR_MUST)
+                       {
+                               /* create attribute request for missing mandatory attributes */
+                               out_msg->add_attribute(out_msg, build_attr_request(received));
+                       }
+                       result = out_msg->send(out_msg, FALSE);
+                       out_msg->destroy(out_msg);
+
+                       if (result != TNC_RESULT_SUCCESS)
+                       {
+                               break;
+                       }
                }
                hcd_state->set_handshake_state(hcd_state, IMV_HCD_STATE_ATTR_REQ);
        }
 
-       /* send non-empty PA-TNC message with excl flag not set */
-       if (out_msg->get_attribute_count(out_msg))
-       {
-               result = out_msg->send(out_msg, FALSE);
-       }
-       out_msg->destroy(out_msg);
-
        return result;
 }
 
index 69cb375..48614a6 100644 (file)
 #include <utils/debug.h>
 
 typedef struct private_imv_hcd_state_t private_imv_hcd_state_t;
+typedef struct subtype_action_flags_t subtype_action_flags_t;
+
+struct subtype_action_flags_t {
+       pa_subtype_pwg_t subtype;
+       uint32_t action_flags;
+};
 
 /**
  * Private data of an imv_hcd_state_t object.
@@ -57,9 +63,14 @@ struct private_imv_hcd_state_t {
        uint32_t max_msg_len;
 
        /**
-        * Flags set for completed actions
+        * Current flags set for completed actions
         */
-       uint32_t action_flags;
+       uint32_t *action_flags;
+
+       /**
+        * Action flags for all PA subtypes
+        */
+       subtype_action_flags_t subtype_action_flags[6];
 
        /**
         * IMV database session associated with TNCCS connection
@@ -128,13 +139,13 @@ METHOD(imv_state_t, get_max_msg_len, uint32_t,
 METHOD(imv_state_t, set_action_flags, void,
        private_imv_hcd_state_t *this, uint32_t flags)
 {
-       this->action_flags |= flags;
+       *this->action_flags |= flags;
 }
 
 METHOD(imv_state_t, get_action_flags, uint32_t,
        private_imv_hcd_state_t *this)
 {
-       return this->action_flags;
+       return *this->action_flags;
 }
 
 METHOD(imv_state_t, set_session, void,
@@ -219,6 +230,32 @@ METHOD(imv_hcd_state_t, get_handshake_state, imv_hcd_handshake_state_t,
        return this->handshake_state;
 }
 
+METHOD(imv_hcd_state_t, set_subtype, void,
+       private_imv_hcd_state_t *this, pa_subtype_pwg_t subtype)
+{
+       int i;
+
+       for (i = 0; i < countof(this->subtype_action_flags); i++)
+       {
+               if (subtype == this->subtype_action_flags[i].subtype)
+               {
+                       this->action_flags = &this->subtype_action_flags[i].action_flags;
+                       break;
+               }
+       }
+}
+
+METHOD(imv_hcd_state_t, set_user_app_disabled, void,
+       private_imv_hcd_state_t *this)
+{
+       int i;
+
+       for (i = 0; i < countof(this->subtype_action_flags); i++)
+       {
+               this->subtype_action_flags[i].action_flags |= IMV_HCD_ATTR_USER_APP_NAME;
+       }
+}
+
 /**
  * Described in header.
  */
@@ -250,14 +287,26 @@ imv_state_t *imv_hcd_state_create(TNC_ConnectionID connection_id)
                        },
                        .set_handshake_state = _set_handshake_state,
                        .get_handshake_state = _get_handshake_state,
+                       .set_subtype = _set_subtype,
+                       .set_user_app_disabled = _set_user_app_disabled,
                },
                .state = TNC_CONNECTION_STATE_CREATE,
                .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
                .connection_id = connection_id,
                .contracts = seg_contract_manager_create(),
+               .subtype_action_flags = {
+                       { PA_SUBTYPE_PWG_HCD_SYSTEM,    IMV_HCD_ATTR_NONE        },
+                       { PA_SUBTYPE_PWG_HCD_CONSOLE,   IMV_HCD_ATTR_SYSTEM_ONLY },
+                       { PA_SUBTYPE_PWG_HCD_MARKER,    IMV_HCD_ATTR_SYSTEM_ONLY },
+                       { PA_SUBTYPE_PWG_HCD_FINISHER,  IMV_HCD_ATTR_SYSTEM_ONLY },
+                       { PA_SUBTYPE_PWG_HCD_INTERFACE, IMV_HCD_ATTR_SYSTEM_ONLY },
+                       { PA_SUBTYPE_PWG_HCD_SCANNER,   IMV_HCD_ATTR_SYSTEM_ONLY },
+               }
        );
 
+       this->action_flags = &this->subtype_action_flags[0].action_flags;
+
        return &this->public.interface;
 }
 
index 2b1c02c..dce9b30 100644 (file)
 #include <imv/imv_state.h>
 #include <library.h>
 
+#include <tncif_pa_subtypes.h>
+
 typedef struct imv_hcd_state_t imv_hcd_state_t;
+typedef enum imv_hcd_attr_t imv_hcd_attr_t;
 typedef enum imv_hcd_handshake_state_t imv_hcd_handshake_state_t;
 typedef enum os_settings_t os_settings_t;
 
 /**
+ * Flag set when corresponding attribute has been received
+ */
+enum imv_hcd_attr_t {
+       IMV_HCD_ATTR_NONE =                          0,
+       IMV_HCD_ATTR_DEFAULT_PWD_ENABLED =       (1<<0),
+       IMV_HCD_ATTR_FIREWALL_SETTING =          (1<<1),
+       IMV_HCD_ATTR_FORWARDING_ENABLED =        (1<<2),
+       IMV_HCD_ATTR_MACHINE_TYPE_MODEL =        (1<<3),
+       IMV_HCD_ATTR_PSTN_FAX_ENABLED =          (1<<4),
+       IMV_HCD_ATTR_TIME_SOURCE =               (1<<5),
+       IMV_HCD_ATTR_USER_APP_ENABLED =          (1<<6),
+       IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED =  (1<<7),
+       IMV_HCD_ATTR_VENDOR_NAME =               (1<<8),
+       IMV_HCD_ATTR_VENDOR_SMI_CODE =           (1<<9),
+       IMV_HCD_ATTR_CERTIFICATION_STATE =       (1<<10),
+       IMV_HCD_ATTR_CONFIGURATION_STATE =       (1<<11),
+
+       IMV_HCD_ATTR_SYSTEM_ONLY =               (1<<12)-1,
+
+       IMV_HCD_ATTR_NATURAL_LANG =              (1<<12),
+       IMV_HCD_ATTR_FIRMWARE_NAME =             (1<<13),
+       IMV_HCD_ATTR_RESIDENT_APP_NAME =         (1<<14),
+       IMV_HCD_ATTR_USER_APP_NAME =             (1<<15),
+
+       IMV_HCD_ATTR_MUST =                      (1<<16)-1
+};
+
+/**
  * IMV OS Handshake States (state machine)
  */
 enum imv_hcd_handshake_state_t {
@@ -65,6 +96,18 @@ struct imv_hcd_state_t {
         */
        imv_hcd_handshake_state_t (*get_handshake_state)(imv_hcd_state_t *this);
 
+       /**
+        * Set the PWG HCD PA subtype currently being handled
+        *
+        * @param subtype                       PWG HCD PA subtype
+        */
+       void (*set_subtype)(imv_hcd_state_t *this, pa_subtype_pwg_t subtype);
+
+       /**
+        * Set User Application Disabled
+        */
+       void (*set_user_app_disabled)(imv_hcd_state_t *this);
+
 };
 
 /**