Implemented TCG/PB-PDP_Referral message
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 17 Sep 2013 19:57:08 +0000 (21:57 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 17 Sep 2013 19:57:08 +0000 (21:57 +0200)
src/libcharon/plugins/tnc_pdp/tnc_pdp.c
src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.c
src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.h
src/libtnccs/plugins/tnccs_20/tnccs_20.c
testing/tests/tnc/tnccs-20-pdp/evaltest.dat

index 7fa1857..31cee9e 100644 (file)
@@ -69,6 +69,11 @@ struct private_tnc_pdp_t {
        eap_type_t type;
 
        /**
+        * PT-TLS port of the server
+        */
+       u_int16_t pt_tls_port;
+
+       /**
         * PT-TLS IPv4 socket
         */
        int pt_tls_ipv4;
@@ -798,6 +803,8 @@ tnc_pdp_t *tnc_pdp_create(void)
                        destroy(this);
                        return NULL;
                }
+               this->pt_tls_port = pt_tls_port;
+
                if (this->pt_tls_ipv4)
                {
                        lib->watcher->add(lib->watcher, this->pt_tls_ipv4, WATCHER_READ,
@@ -807,6 +814,7 @@ tnc_pdp_t *tnc_pdp_create(void)
                {
                        DBG1(DBG_NET, "could not open IPv4 PT-TLS socket, IPv4 disabled");
                }
+
                if (this->pt_tls_ipv6)
                {
                        lib->watcher->add(lib->watcher, this->pt_tls_ipv6, WATCHER_READ,
@@ -816,6 +824,10 @@ tnc_pdp_t *tnc_pdp_create(void)
                {
                        DBG1(DBG_NET, "could not open IPv6 PT-TLS socket, IPv6 disabled");
                }
+
+               /* register PT-TLS service */
+               lib->set(lib, "pt-tls-server", this->server);
+               lib->set(lib, "pt-tls-port", &this->pt_tls_port);
        }
 
        /* Create IPv4 and IPv6 RADIUS listening sockets */
index 6dacfc6..ef0faf2 100644 (file)
@@ -396,7 +396,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
                msg_type_names = pb_tnc_msg_type_names;
                msg_infos = pb_tnc_msg_infos;
        }
-       else if (vendor_id == PEN_IETF && msg_type <= PB_TCG_MSG_ROOF)
+       else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF)
        {
                msg_type_names = pb_tnc_tcg_msg_type_names;
                msg_infos = pb_tnc_tcg_msg_infos;
@@ -414,16 +414,16 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
 
                if (noskip_flag)
                {
-                       DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / "
-                                                 "Type 0x%08x)", vendor_id, msg_type);
+                       DBG1(DBG_TNC, "reject PB-TNC message 0x%06x/0x%08x)",
+                                                  vendor_id, msg_type);
                        msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
                                                        PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
                        goto fatal;
                }
                else
                {
-                       DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / "
-                                                 "Type 0x%08x)", vendor_id, msg_type);
+                       DBG1(DBG_TNC, "ignore PB-TNC message 0x%06x/0x%08x)",
+                                                  vendor_id, msg_type);
                        this->offset += msg_len;
                        return SUCCESS;
                }
index f8c78b6..1c8538e 100644 (file)
@@ -79,6 +79,11 @@ typedef struct private_pb_pdp_referral_msg_t private_pb_pdp_referral_msg_t;
  *
  */
 
+# define PDP_REFERRAL_HEADER_SIZE              8
+# define PDP_REFERRAL_ID_HEADER_SIZE   4
+# define PDP_REFERRAL_RESERVED                 0x00
+# define PDP_REFERRAL_PROTOCOL                 0x00
+
 /**
  * Private data of a pb_pdp_referral_msg_t object.
  *
@@ -105,6 +110,21 @@ struct private_pb_pdp_referral_msg_t {
        chunk_t identifier;
 
        /**
+        * PDP FQDN Identifier
+        */
+       chunk_t fqdn;
+
+       /**
+        * PT protocol the PDP is using
+        */
+       u_int8_t protocol;
+
+       /**
+        * PT port the PDP is using
+        */
+       u_int16_t port;
+
+       /**
         * Encoded message
         */
        chunk_t encoding;
@@ -131,10 +151,11 @@ METHOD(pb_tnc_msg_t, build, void,
        {
                return;
        }
-       writer = bio_writer_create(64);
-       writer->write_uint32(writer, this->identifier_type.vendor_id);
+       writer = bio_writer_create(PDP_REFERRAL_HEADER_SIZE + this->identifier.len);
+       writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
+       writer->write_uint24(writer, this->identifier_type.vendor_id);
        writer->write_uint32(writer, this->identifier_type.type);
-       writer->write_data(writer, this->identifier);
+       writer->write_data  (writer, this->identifier);
 
        this->encoding = writer->get_buf(writer);
        this->encoding = chunk_clone(this->encoding);
@@ -146,7 +167,6 @@ METHOD(pb_tnc_msg_t, process, status_t,
 {
        bio_reader_t *reader;
        u_int8_t reserved;
-       status_t status = SUCCESS;
 
        *offset = 0;
 
@@ -160,11 +180,25 @@ METHOD(pb_tnc_msg_t, process, status_t,
        this->identifier = chunk_clone(this->identifier);
        reader->destroy(reader);
 
-       if (this->identifier_type.vendor_id == PEN_TCG)
+       if (this->identifier_type.vendor_id == PEN_TCG &&
+               this->identifier_type.type == PB_PDP_ID_FQDN)
        {
-               /* TODO parse PDP Identifier Types */
+               reader = bio_reader_create(this->identifier);
+               *offset += PDP_REFERRAL_HEADER_SIZE;
+
+               if (this->identifier.len <= PDP_REFERRAL_ID_HEADER_SIZE)
+               {
+                       reader->destroy(reader);
+                       return FAILED;
+               }
+               reader->read_uint8 (reader, &reserved);
+               reader->read_uint8 (reader, &this->protocol);
+               reader->read_uint16(reader, &this->port);
+               reader->read_data  (reader, reader->remaining(reader), &this->fqdn);
+               this->fqdn = chunk_clone(this->fqdn);
+               reader->destroy(reader);
        }
-       return status;
+       return SUCCESS;
 }
 
 METHOD(pb_tnc_msg_t, destroy, void,
@@ -172,6 +206,7 @@ METHOD(pb_tnc_msg_t, destroy, void,
 {
        free(this->encoding.ptr);
        free(this->identifier.ptr);
+       free(this->fqdn.ptr);
        free(this);
 }
 
@@ -187,6 +222,20 @@ METHOD(pb_pdp_referral_msg_t, get_identifier, chunk_t,
        return this->identifier;
 }
 
+METHOD(pb_pdp_referral_msg_t, get_fqdn, chunk_t,
+       private_pb_pdp_referral_msg_t *this, u_int8_t *protocol, u_int16_t *port)
+{
+       if (protocol)
+       {
+               *protocol = this->protocol;
+       }
+       if (port)
+       {
+               *port = this->port;
+       }
+       return this->fqdn;
+}
+
 /**
  * See header
  */
@@ -218,6 +267,27 @@ pb_tnc_msg_t* pb_pdp_referral_msg_create(pen_type_t identifier_type,
 /**
  * See header
  */
+pb_tnc_msg_t* pb_pdp_referral_msg_create_from_fqdn(chunk_t fqdn, u_int16_t port)
+{
+       pb_tnc_msg_t *msg;
+       bio_writer_t *writer;
+       pen_type_t type = { PEN_TCG, PB_PDP_ID_FQDN };
+
+       writer = bio_writer_create(PDP_REFERRAL_ID_HEADER_SIZE + fqdn.len);
+       writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
+       writer->write_uint8 (writer, PDP_REFERRAL_PROTOCOL);
+       writer->write_uint16(writer, port);
+       writer->write_data  (writer, fqdn);
+
+       msg = pb_pdp_referral_msg_create(type, writer->get_buf(writer));
+       writer->destroy(writer);
+
+       return msg;
+}
+
+/**
+ * See header
+ */
 pb_tnc_msg_t *pb_pdp_referral_msg_create_from_data(chunk_t data)
 {
        private_pb_pdp_referral_msg_t *this;
@@ -233,6 +303,7 @@ pb_tnc_msg_t *pb_pdp_referral_msg_create_from_data(chunk_t data)
                        },
                        .get_identifier_type = _get_identifier_type,
                        .get_identifier = _get_identifier,
+                       .get_fqdn = _get_fqdn,
                },
                .type = { PEN_TCG, PB_TCG_MSG_PDP_REFERRAL },
                .encoding = chunk_clone(data),
index a472557..b225f33 100644 (file)
@@ -67,6 +67,16 @@ struct pb_pdp_referral_msg_t {
         */
        chunk_t (*get_identifier)(pb_pdp_referral_msg_t *this);
 
+       /**
+        * Get the PDP Identifier Value
+        *
+        * @param protocol              PT transport protocol
+        * @param port                  PT port the PDP is listening on
+        * @return                              Fully Qualified Domain Name of PDP
+        */
+       chunk_t (*get_fqdn)(pb_pdp_referral_msg_t *this, u_int8_t *protocol,
+                                               u_int16_t *port);
+
 };
 
 /**
@@ -79,6 +89,14 @@ pb_tnc_msg_t* pb_pdp_referral_msg_create(pen_type_t identifier_type,
                                                                                 chunk_t identifier);
 
 /**
+ * Create a PB-PDP-Referral message of TCG Type PDP FQDN Identifier
+ *
+ * @param fqdn                         Fully Qualified Domain Name of PDP
+ * @param port                         PT-TLS port the PDP is listening on 
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create_from_fqdn(chunk_t fqdn, u_int16_t port);
+
+/**
  * Create an unprocessed PB-PDP-Referral message from raw data
  *
   * @param data                PB-PDP-Referral message data
index 6759c92..b5b1ceb 100644 (file)
@@ -24,6 +24,7 @@
 #include "messages/ietf/pb_remediation_parameters_msg.h"
 #include "messages/ietf/pb_reason_string_msg.h"
 #include "messages/ietf/pb_language_preference_msg.h"
+#include "messages/tcg/pb_pdp_referral_msg.h"
 #include "state_machine/pb_tnc_state_machine.h"
 
 #include <tncif_names.h>
@@ -452,8 +453,31 @@ static void handle_tcg_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
        switch (msg_type.type)
        {
                case PB_TCG_MSG_PDP_REFERRAL:
-                       /* TODO handle PDP Referral */
+               {
+                       pb_pdp_referral_msg_t *pdp_msg;
+                       pen_type_t pdp_id_type;
+                       chunk_t pdp_server;
+                       u_int8_t pdp_protocol;
+                       u_int16_t pdp_port;
+
+                       pdp_msg = (pb_pdp_referral_msg_t*)msg;
+                       pdp_id_type = pdp_msg->get_identifier_type(pdp_msg);
+
+                       if (pdp_id_type.vendor_id == PEN_TCG &&
+                               pdp_id_type.type == PB_PDP_ID_FQDN)
+                       {
+                               pdp_server = pdp_msg->get_fqdn(pdp_msg, &pdp_protocol,
+                                                                                          &pdp_port);
+                               if (pdp_protocol != 0)
+                               {
+                                       DBG1(DBG_TNC, "unsupported PDP transport protocol");
+                                       break;
+                               }
+                               DBG1(DBG_TNC, "PDP server '%.*s' is listening on port %u",
+                                                          pdp_server.len, pdp_server.ptr, pdp_port);
+                       }
                        break;
+               }
                default:
                        break;
        }
@@ -510,6 +534,8 @@ METHOD(tls_t, process, status_t,
        pb_tnc_batch_t *batch;
        pb_tnc_msg_t *msg;
        enumerator_t *enumerator;
+       identification_t *pdp_server;
+       u_int16_t *pdp_port;
        status_t status;
 
        if (this->is_server && !this->connection_id)
@@ -526,6 +552,19 @@ METHOD(tls_t, process, status_t,
                                                                                        TNC_CONNECTION_STATE_CREATE);
                tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
                                                                                        TNC_CONNECTION_STATE_HANDSHAKE);
+
+               /* Send a PB-TNC TCG PDP Referral message if PDP is known */
+               pdp_server = (identification_t*)lib->get(lib, "pt-tls-server");
+               pdp_port = (u_int16_t*)lib->get(lib, "pt-tls-port");
+
+               if ((this->transport == TNC_IFT_EAP_1_1 ||
+                        this->transport == TNC_IFT_EAP_2_0) && pdp_server && pdp_port)
+               {
+                       msg = pb_pdp_referral_msg_create_from_fqdn(
+                                               pdp_server->get_encoding(pdp_server), *pdp_port);
+                       this->messages->insert_last(this->messages, msg);
+               }
+
        }
 
        data = chunk_create(buf, buflen);
index f028ec6..505a4d0 100644 (file)
@@ -1,8 +1,10 @@
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature successful::YES
+carol::cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on port 271::YES
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is .*Access Allowed::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature successful::YES
+dave:: cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on port 271::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is .*Quarantined::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES