Added TCG-SWID error handling
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 28 Aug 2013 20:53:57 +0000 (22:53 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 28 Aug 2013 20:53:57 +0000 (22:53 +0200)
src/libpts/Makefile.am
src/libpts/plugins/imc_swid/imc_swid.c
src/libpts/plugins/imv_swid/imv_swid_agent.c
src/libpts/swid/swid_error.c [new file with mode: 0644]
src/libpts/swid/swid_error.h [new file with mode: 0644]
src/libpts/tcg/swid/tcg_swid_attr_req.c

index e545e01..02d5642 100644 (file)
@@ -35,6 +35,7 @@ libpts_la_SOURCES = \
        pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
        pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
        pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+       swid/swid_error.h swid/swid_error.c \
        swid/swid_tag.h swid/swid_tag.c \
        swid/swid_tag_id.h swid/swid_tag_id.c \
        tcg/tcg_attr.h tcg/tcg_attr.c \
index aec5af4..a90e5ad 100644 (file)
@@ -18,6 +18,7 @@
 #include "libpts.h"
 #include "swid/swid_tag.h"
 #include "swid/swid_tag_id.h"
+#include "swid/swid_error.h"
 #include "tcg/swid/tcg_swid_attr_req.h"
 #include "tcg/swid/tcg_swid_attr_tag_inv.h"
 #include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
@@ -199,6 +200,14 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
                request_id = attr_req->get_request_id(attr_req);
                eid_epoch = swid_state->get_eid_epoch(swid_state);
 
+               if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
+               {
+                       attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id,
+                                                                        0, "no subscription available yet");
+                       out_msg->add_attribute(out_msg, attr);
+                       break;
+               }
+
                if (flags & TCG_SWID_ATTR_REQ_FLAG_R)
                {
                        swid_tag_id_t *tag_id;
index 3050b00..db1a98f 100644 (file)
 #include "imv_swid_state.h"
 
 #include "libpts.h"
+#include "swid/swid_error.h"
 #include "tcg/swid/tcg_swid_attr_req.h"
 #include "tcg/swid/tcg_swid_attr_tag_inv.h"
 #include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
 
 #include <imcv.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
 #include <imv/imv_agent.h>
 #include <imv/imv_msg.h>
 
@@ -30,6 +32,7 @@
 
 #include <pen/pen.h>
 #include <utils/debug.h>
+#include <bio/bio_reader.h>
 
 typedef struct private_imv_swid_agent_t private_imv_swid_agent_t;
 
@@ -89,7 +92,6 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
        imv_session_t *session;
        enumerator_t *enumerator;
        pa_tnc_attr_t *attr;
-       pen_type_t type;
        TNC_Result result;
        bool fatal_error = FALSE;
 
@@ -108,6 +110,7 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
        {
                TNC_IMV_Evaluation_Result eval;
                TNC_IMV_Action_Recommendation rec;
+               pen_type_t type;
                u_int32_t request_id, last_eid, eid_epoch;
                int tag_count = 0;
                char result_str[BUF_LEN], *tag_item;
@@ -116,10 +119,56 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
                
                type = attr->get_type(attr);
 
-               if (type.vendor_id != PEN_TCG)
+               if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
+               {
+                       ietf_attr_pa_tnc_error_t *error_attr;
+                       pen_type_t error_code;
+                       chunk_t msg_info, description;
+                       bio_reader_t *reader;
+                       u_int32_t request_id = 0, max_attr_size;
+                       bool success;
+
+                       error_attr = (ietf_attr_pa_tnc_error_t*)attr;
+                       error_code = error_attr->get_error_code(error_attr);
+
+                       if (error_code.vendor_id == PEN_TCG)
+                       {
+                               fatal_error = TRUE;
+                               msg_info = error_attr->get_msg_info(error_attr);
+                               reader = bio_reader_create(msg_info);
+                               success = reader->read_uint32(reader, &request_id);
+
+                               DBG1(DBG_IMV, "received TCG error '%N' for request %d",
+                                        swid_error_code_names, error_code.type, request_id);
+                               if (!success)
+                               {
+                                       reader->destroy(reader);
+                                       continue;
+                               }
+                               if (error_code.type == TCG_SWID_RESPONSE_TOO_LARGE)
+                               {
+                                       if (!reader->read_uint32(reader, &max_attr_size))
+                                       {
+                                               reader->destroy(reader);
+                                               continue;
+                                       }
+                                       DBG1(DBG_IMV, "  maximum PA-TNC attribute size is %u bytes",
+                                               max_attr_size);
+                               }
+                               description = reader->peek(reader);
+                               if (description.len)
+                               { 
+                                       DBG1(DBG_IMV, "  description: %.*s", description.len,
+                                                                                                                description.ptr);
+                               }
+                               reader->destroy(reader);
+                       }
+               }
+               else if (type.vendor_id != PEN_TCG)
                {
                        continue;
                }
+
                switch (type.type)
                {
                        case TCG_SWID_TAG_ID_INVENTORY:
diff --git a/src/libpts/swid/swid_error.c b/src/libpts/swid/swid_error.c
new file mode 100644 (file)
index 0000000..7f7da76
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * 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 "swid_error.h"
+
+#include <bio/bio_writer.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+ENUM(swid_error_code_names, TCG_SWID_ERROR, TCG_SWID_RESPONSE_TOO_LARGE,
+       "SWID Error",
+       "SWID Subscription Denied",
+       "SWID Response Too Large"
+);
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
+                                                                u_int32_t max_attr_size, char *description)
+{
+       bio_writer_t *writer;
+       chunk_t msg_info;
+       pa_tnc_attr_t *attr;
+       pen_type_t error_code;
+
+       error_code = pen_type_create( PEN_TCG, code);
+       writer = bio_writer_create(4);
+       writer->write_uint32(writer, request_id);
+       if (code == TCG_SWID_RESPONSE_TOO_LARGE)
+       {
+               writer->write_uint16(writer, max_attr_size);
+       }
+       if (description)
+       {
+               writer->write_data(writer, chunk_from_str(description));
+       }
+       msg_info = writer->get_buf(writer);
+       attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+       writer->destroy(writer);
+
+       return attr;
+}
+
diff --git a/src/libpts/swid/swid_error.h b/src/libpts/swid/swid_error.h
new file mode 100644 (file)
index 0000000..1da6148
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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 swid_error swid_error
+ * @{ @ingroup swid
+ */
+
+#ifndef SWID_ERROR_H_
+#define SWID_ERROR_H_
+
+typedef enum swid_error_code_t swid_error_code_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+
+
+/**
+ * SWID Error Codes
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum swid_error_code_t {
+       TCG_SWID_ERROR =                        0x20,
+       TCG_SWID_SUBSCRIPTION_DENIED =  0x21,
+       TCG_SWID_RESPONSE_TOO_LARGE =   0x22
+};
+
+/**
+ * enum name for swid_error_code_t.
+ */
+extern enum_name_t *swid_error_code_names;
+
+/**
+ * Creates a SWID Error Attribute
+ * see section 4.12 of TNC SWID Message and Attributes for IF-M
+ *
+ * @param code                         SWID error code
+ * @param request                      SWID request ID
+ * @param max_attr_size                Maximum IF-M attribute size (if applicable)
+ * @param description          Optional description string or NULL
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request,
+                                                                u_int32_t max_attr_size, char *description);
+
+#endif /** SWID_ERROR_H_ @}*/
index 67772c2..50cca8d 100644 (file)
@@ -175,6 +175,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
        reader->read_uint24(reader, &tag_id_count);
        reader->read_uint32(reader, &this->request_id);
        reader->read_uint32(reader, &this->earliest_eid);
+
+       if (this->request_id == 0)
+       {
+               *offset = 4;
+               return FAILED;
+       }
        *offset = SWID_REQ_SIZE;
 
        this->flags &= SWID_REQ_RESERVED_MASK;