diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-10-13 20:34:50 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-10-13 20:34:50 +0200 |
commit | 07a3dee937b61dcd05e78dcd9e7a416bf944eb83 (patch) | |
tree | 1de1fdaad4f43652e2e126fb20473f1f296c5818 /src | |
parent | 4bc119afb75009f8af398bea4c93b908d8940f9c (diff) | |
download | strongswan-07a3dee937b61dcd05e78dcd9e7a416bf944eb83.tar.bz2 strongswan-07a3dee937b61dcd05e78dcd9e7a416bf944eb83.tar.xz |
implemented IETF Operational Status attribute
Diffstat (limited to 'src')
-rw-r--r-- | src/libimcv/Makefile.am | 1 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr.c | 4 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_op_status.c | 313 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_op_status.h | 107 | ||||
-rw-r--r-- | src/libimcv/os_info/os_info.c | 27 | ||||
-rw-r--r-- | src/libimcv/os_info/os_info.h | 9 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os.c | 24 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os.c | 18 |
8 files changed, 501 insertions, 2 deletions
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 249d5aeee..a33187091 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -15,6 +15,7 @@ libimcv_la_SOURCES = \ ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \ ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \ ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \ + ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \ ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \ ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \ ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \ diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c index 8aa05c186..f183e06f7 100644 --- a/src/libimcv/ietf/ietf_attr.c +++ b/src/libimcv/ietf/ietf_attr.c @@ -19,6 +19,7 @@ #include "ietf/ietf_attr_fwd_enabled.h" #include "ietf/ietf_attr_default_pwd_enabled.h" #include "ietf/ietf_attr_installed_packages.h" +#include "ietf/ietf_attr_op_status.h" #include "ietf/ietf_attr_pa_tnc_error.h" #include "ietf/ietf_attr_port_filter.h" #include "ietf/ietf_attr_product_info.h" @@ -54,6 +55,8 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value) return ietf_attr_product_info_create_from_data(value); case IETF_ATTR_STRING_VERSION: return ietf_attr_string_version_create_from_data(value); + case IETF_ATTR_OPERATIONAL_STATUS: + return ietf_attr_op_status_create_from_data(value); case IETF_ATTR_PORT_FILTER: return ietf_attr_port_filter_create_from_data(value); case IETF_ATTR_INSTALLED_PACKAGES: @@ -68,7 +71,6 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value) return ietf_attr_default_pwd_enabled_create_from_data(value); case IETF_ATTR_TESTING: case IETF_ATTR_NUMERIC_VERSION: - case IETF_ATTR_OPERATIONAL_STATUS: case IETF_ATTR_REMEDIATION_INSTRUCTIONS: case IETF_ATTR_RESERVED: default: diff --git a/src/libimcv/ietf/ietf_attr_op_status.c b/src/libimcv/ietf/ietf_attr_op_status.c new file mode 100644 index 000000000..9f3af09a3 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_op_status.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2012 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ietf_attr_op_status.h" + +#include <pa_tnc/pa_tnc_msg.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <debug.h> + +#include <time.h> + +typedef struct private_ietf_attr_op_status_t private_ietf_attr_op_status_t; + +ENUM(op_status_names, OP_STATUS_UNKNOWN, OP_STATUS_OPERATIONAL, + "unknown", + "not installed", + "installed", + "operational" +); + +ENUM(op_result_names, OP_RESULT_UNKNOWN, OP_RESULT_UNSUCCESSFUL, + "unknown", + "successful", + "errored", + "unsuccessful" +); + +/** + * PA-TNC Operational Status type (see section 4.2.5 of RFC 5792) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Status | Result | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Last Use | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Last Use (continued) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Last Use (continued) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Last Use (continued) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Last Use (continued) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define OP_STATUS_SIZE 24 + +/** + * Private data of an ietf_attr_op_status_t object. + */ +struct private_ietf_attr_op_status_t { + + /** + * Public members of ietf_attr_op_status_t + */ + ietf_attr_op_status_t public; + + /** + * Vendor-specific attribute type + */ + pen_type_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * Status + */ + u_int8_t status; + + /** + * Result + */ + u_int8_t result; + + /** + * Last Use + */ + time_t last_use; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(pa_tnc_attr_t, get_type, pen_type_t, + private_ietf_attr_op_status_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ietf_attr_op_status_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ietf_attr_op_status_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ietf_attr_op_status_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ietf_attr_op_status_t *this) +{ + bio_writer_t *writer; + char last_use[24]; + struct tm t; + + if (this->value.ptr) + { + return; + } + + /* Conversion from time_t to RFC 3339 ASCII string */ + gmtime_r(&this->last_use, &t); + snprintf(last_use, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.tm_year, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + + writer = bio_writer_create(OP_STATUS_SIZE); + writer->write_uint8 (writer, this->status); + writer->write_uint8 (writer, this->result); + writer->write_uint16(writer, 0x0000); + writer->write_data (writer, chunk_create(last_use, 20)); + + this->value = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ietf_attr_op_status_t *this, u_int32_t *offset) +{ + bio_reader_t *reader; + chunk_t last_use; + u_int16_t reserved; + struct tm t; + int nr; + + *offset = 0; + + if (this->value.len != OP_STATUS_SIZE) + { + DBG1(DBG_TNC, "incorrect size for IETF operational status"); + return FAILED; + } + reader = bio_reader_create(this->value); + reader->read_uint8 (reader, &this->status); + reader->read_uint8 (reader, &this->result); + reader->read_uint16(reader, &reserved); + reader->read_data (reader, 20, &last_use); + reader->destroy(reader); + + if (this->status > OP_STATUS_ROOF) + { + DBG1(DBG_TNC, "invalid status value %c for IETF operational status", + this->status); + return FAILED; + } + + *offset = 1; + + if (this->result > OP_RESULT_ROOF) + { + DBG1(DBG_TNC, "invalid result value %c for IETF operational status", + this->result); + return FAILED; + } + + *offset = 4; + + /* Conversion from RFC 3339 ASCII string to time_t */ + if (sscanf(last_use.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t.tm_year, &t.tm_mon, + &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6) + { + DBG1(DBG_TNC, "invalid last_use time format in IETF operational status"); + return FAILED; + } + t.tm_year -= 1900; + t.tm_mon -= 1; + t.tm_isdst = 0; + this->last_use = mktime(&t) - timezone; + + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, + private_ietf_attr_op_status_t *this) +{ + ref_get(&this->ref); + return &this->public.pa_tnc_attribute; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ietf_attr_op_status_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->value.ptr); + free(this); + } +} + +METHOD(ietf_attr_op_status_t, get_status, u_int8_t, + private_ietf_attr_op_status_t *this) +{ + return this->status; +} + +METHOD(ietf_attr_op_status_t, get_result, u_int8_t, + private_ietf_attr_op_status_t *this) +{ + return this->result; +} + +METHOD(ietf_attr_op_status_t, get_last_use, time_t, + private_ietf_attr_op_status_t *this) +{ + return this->last_use; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_op_status_create(u_int8_t status, u_int8_t result, + time_t last_use) +{ + private_ietf_attr_op_status_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_type = _get_type, + .get_value = _get_value, + .get_noskip_flag = _get_noskip_flag, + .set_noskip_flag = _set_noskip_flag, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_status = _get_status, + .get_result = _get_result, + .get_last_use = _get_last_use, + }, + .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS }, + .status = status, + .result = result, + .last_use = last_use, + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_op_status_create_from_data(chunk_t data) +{ + private_ietf_attr_op_status_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_type = _get_type, + .get_value = _get_value, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_status = _get_status, + .get_result = _get_result, + .get_last_use = _get_last_use, + }, + .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS }, + .value = chunk_clone(data), + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + diff --git a/src/libimcv/ietf/ietf_attr_op_status.h b/src/libimcv/ietf/ietf_attr_op_status.h new file mode 100644 index 000000000..2e14148c4 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_op_status.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup ietf_attr_op_statust ietf_attr_op_status + * @{ @ingroup ietf + */ + +#ifndef IETF_ATTR_OP_STATUS_H_ +#define IETF_ATTR_OP_STATUS_H_ + +typedef struct ietf_attr_op_status_t ietf_attr_op_status_t; +typedef enum op_status_t op_status_t; +typedef enum op_result_t op_result_t; + +#include "ietf_attr.h" +#include "pa_tnc/pa_tnc_attr.h" + +/** + * Operational Status type + */ +enum op_status_t { + OP_STATUS_UNKNOWN = 0, + OP_STATUS_NOT_INSTALLED = 1, + OP_STATUS_INSTALLED = 2, + OP_STATUS_OPERATIONAL = 3, + OP_STATUS_ROOF = 3 +}; + +extern enum_name_t *op_status_names; + +/** + * Operational Result type + */ +enum op_result_t { + OP_RESULT_UNKNOWN = 0, + OP_RESULT_SUCCESSFUL = 1, + OP_RESULT_ERRORED = 2, + OP_RESULT_UNSUCCESSFUL = 3, + OP_RESULT_ROOF = 3 +}; + +extern enum_name_t *op_result_names; + +/** + * Class implementing the IETF PA-TNC Operational Status attribute. + * + */ +struct ietf_attr_op_status_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + + /** + * Gets the Operational Status + * + * @return Operational Status + */ + u_int8_t (*get_status)(ietf_attr_op_status_t *this); + + /** + * Gets the Operational Result + * + * @return Operational Result + */ + u_int8_t (*get_result)(ietf_attr_op_status_t *this); + + /** + * Gets the time of last use + * + * @return Time of last use + */ + time_t (*get_last_use)(ietf_attr_op_status_t *this); +}; + +/** + * Creates an ietf_attr_op_status_t object + * + * @param status Operational Status + * @param result Operational Result + * @param last_use Time of last use + */ +pa_tnc_attr_t* ietf_attr_op_status_create(u_int8_t status, u_int8_t result, + time_t last_use); + +/** + * Creates an ietf_attr_op_status_t object from received data + * + * @param value unparsed attribute value + */ +pa_tnc_attr_t* ietf_attr_op_status_create_from_data(chunk_t value); + +#endif /** IETF_ATTR_OP_STATUS_H_ @}*/ diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 25d64676e..fd7d6ce48 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -95,20 +95,44 @@ METHOD(os_info_t, get_fwd_status, os_fwd_status_t, { DBG1(DBG_IMC, "could not read from \"%s\"", ip_forward); } + fclose(file); } else { DBG1(DBG_IMC, "failed to open \"%s\"", ip_forward); } - fclose(file); return fwd_status; } +METHOD(os_info_t, get_uptime, time_t, + private_os_info_t *this) +{ + const char proc_uptime[] = "/proc/uptime"; + FILE *file; + time_t uptime; + + file = fopen(proc_uptime, "r"); + if (!file) + { + DBG1(DBG_IMC, "failed to open \"%s\"", proc_uptime); + return 0; + } + if (fscanf(file, "%u", &uptime) != 1) + { + DBG1(DBG_IMC, "failed to read file \"%s\"", proc_uptime); + uptime = 0; + } + fclose(file); + + return uptime; +} + METHOD(os_info_t, create_package_enumerator, enumerator_t*, private_os_info_t *this) { /* TODO */ + return NULL; } @@ -345,6 +369,7 @@ os_info_t *os_info_create(void) .get_name = _get_name, .get_version = _get_version, .get_fwd_status = _get_fwd_status, + .get_uptime = _get_uptime, .create_package_enumerator = _create_package_enumerator, .destroy = _destroy, }, diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h index 104426397..f39d8ae41 100644 --- a/src/libimcv/os_info/os_info.h +++ b/src/libimcv/os_info/os_info.h @@ -26,6 +26,8 @@ typedef enum os_fwd_status_t os_fwd_status_t; #include <library.h> +#include <time.h> + /** * Defines the IPv4 forwarding status */ @@ -64,6 +66,13 @@ struct os_info_t { os_fwd_status_t (*get_fwd_status)(os_info_t *this); /** + * Get the OS uptime in seconds + * + * @return OS uptime + */ + time_t (*get_uptime)(os_info_t *this); + + /** * Enumerates over all installed packages * * @return return package enumerator diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index cbadc9c94..beaec2fe0 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -23,6 +23,7 @@ #include <ietf/ietf_attr_default_pwd_enabled.h> #include <ietf/ietf_attr_fwd_enabled.h> #include <ietf/ietf_attr_installed_packages.h> +#include <ietf/ietf_attr_op_status.h> #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> #include <ietf/ietf_attr_string_version.h> @@ -140,6 +141,25 @@ static void add_string_version(linked_list_t *attr_list) } /** + * Add IETF Operational Status attribute to the send queue + */ +static void add_op_status(linked_list_t *attr_list) +{ + pa_tnc_attr_t *attr; + time_t uptime, last_boot; + + uptime = os->get_uptime(os); + last_boot = uptime ? time(NULL) - uptime : UNDEFINED_TIME; + if (last_boot != UNDEFINED_TIME) + { + DBG1(DBG_IMC, "last boot: %T, %u s ago", &last_boot, TRUE, uptime); + } + attr = ietf_attr_op_status_create(OP_STATUS_OPERATIONAL, + OP_RESULT_SUCCESSFUL, last_boot); + attr_list->insert_last(attr_list, attr); +} + +/** * Add IETF Forwarding Enabled attribute to the send queue */ static void add_fwd_enabled(linked_list_t *attr_list) @@ -207,6 +227,7 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, attr_list = linked_list_create(); add_product_info(attr_list); add_string_version(attr_list); + add_op_status(attr_list); add_fwd_enabled(attr_list); add_default_pwd_enabled(attr_list); result = imc_os->send_message(imc_os, connection_id, FALSE, 0, @@ -296,6 +317,9 @@ static TNC_Result receive_message(TNC_IMCID imc_id, case IETF_ATTR_STRING_VERSION: add_string_version(attr_list); break; + case IETF_ATTR_OPERATIONAL_STATUS: + add_op_status(attr_list); + break; case IETF_ATTR_FORWARDING_ENABLED: add_fwd_enabled(attr_list); break; diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index 655d1bf9f..b085b85a3 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -22,6 +22,7 @@ #include <ietf/ietf_attr_default_pwd_enabled.h> #include <ietf/ietf_attr_fwd_enabled.h> #include <ietf/ietf_attr_installed_packages.h> +#include <ietf/ietf_attr_op_status.h> #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> #include <ietf/ietf_attr_string_version.h> @@ -181,6 +182,22 @@ static TNC_Result receive_message(TNC_IMVID imv_id, } break; } + case IETF_ATTR_OPERATIONAL_STATUS: + { + ietf_attr_op_status_t *attr_cast; + op_status_t op_status; + op_result_t op_result; + time_t last_boot; + + attr_cast = (ietf_attr_op_status_t*)attr; + op_status = attr_cast->get_status(attr_cast); + op_result = attr_cast->get_result(attr_cast); + last_boot = attr_cast->get_last_use(attr_cast); + DBG1(DBG_IMV, "operational status: %N, result: %N", + op_status_names, op_status, op_result_names, op_result); + DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE); + break; + } case IETF_ATTR_FORWARDING_ENABLED: { ietf_attr_fwd_enabled_t *attr_cast; @@ -364,6 +381,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, IETF_ATTR_PRODUCT_INFORMATION); attr_cast = (ietf_attr_attr_request_t*)attr; attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION); + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS); attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED); attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED); attr_list->insert_last(attr_list, attr); |