Optimized PT-TLS data transfer
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 13 Aug 2013 15:09:53 +0000 (17:09 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 15 Aug 2013 21:34:23 +0000 (23:34 +0200)
src/libpttls/pt_tls.c
src/libpttls/pt_tls.h
src/libpttls/pt_tls_client.c
src/libpttls/pt_tls_server.c

index b59ef7c..3c1f874 100644 (file)
@@ -134,31 +134,32 @@ bio_reader_t* pt_tls_read(tls_socket_t *tls, u_int32_t *vendor,
 /**
  * Prepend a PT-TLS header to a writer, send data, destroy writer
  */
 /**
  * Prepend a PT-TLS header to a writer, send data, destroy writer
  */
-bool pt_tls_write(tls_socket_t *tls, bio_writer_t *writer,
-                                 pt_tls_message_type_t type, u_int32_t identifier)
+bool pt_tls_write(tls_socket_t *tls, pt_tls_message_type_t type,
+                                 u_int32_t identifier, chunk_t data)
 {
 {
-       bio_writer_t *header;
+       bio_writer_t *writer;
+       chunk_t out;
        ssize_t len;
        ssize_t len;
-       chunk_t data;
 
 
-       data =  writer->get_buf(writer);
        len = PT_TLS_HEADER_LEN + data.len;
        len = PT_TLS_HEADER_LEN + data.len;
-       header = bio_writer_create(len);
-       header->write_uint8(header, 0);
-       header->write_uint24(header, 0);
-       header->write_uint32(header, type);
-       header->write_uint32(header, len);
-       header->write_uint32(header, identifier);
-
-       header->write_data(header, data);
-       writer->destroy(writer);
+       writer = bio_writer_create(len);
+
+       /* write PT-TLS header */
+       writer->write_uint8 (writer, 0);
+       writer->write_uint24(writer, 0);
+       writer->write_uint32(writer, type);
+       writer->write_uint32(writer, len);
+       writer->write_uint32(writer, identifier);
+
+       /* write PT-TLS body */
+       writer->write_data(writer, data);
 
        DBG2(DBG_TNC, "sending PT-TLS message #%d of type '%N' (%d bytes)",
                                   identifier, pt_tls_message_type_names, type, len);
 
 
        DBG2(DBG_TNC, "sending PT-TLS message #%d of type '%N' (%d bytes)",
                                   identifier, pt_tls_message_type_names, type, len);
 
-       data = header->get_buf(header);
-       len = tls->write(tls, data.ptr, data.len);
-       header->destroy(header);
+       out = writer->get_buf(writer);
+       len = tls->write(tls, out.ptr, out.len);
+       writer->destroy(writer);
 
 
-       return len == data.len;
+       return len == out.len;
 }
 }
index f7ea75b..dd3d250 100644 (file)
 #define PT_TLS_HEADER_LEN 16
 
 /**
 #define PT_TLS_HEADER_LEN 16
 
 /**
+ * Maximum size of a PT-TLS message
+ */
+#define PT_TLS_MAX_MESSAGE_LEN  8 * TLS_MAX_FRAGMENT_LEN - PT_TLS_HEADER_LEN
+
+/**
  * Default PT-TLS port
  */
 #define PT_TLS_PORT     271
  * Default PT-TLS port
  */
 #define PT_TLS_PORT     271
@@ -107,13 +112,13 @@ bio_reader_t* pt_tls_read(tls_socket_t *tls, u_int32_t *vendor,
  * Prepend a PT-TLS header to a writer, send data, destroy writer.
  *
  * @param tls                  TLS socket to write to
  * Prepend a PT-TLS header to a writer, send data, destroy writer.
  *
  * @param tls                  TLS socket to write to
- * @param writer               prepared Message value to write
  * @param type                 Message Type to write
  * @param identifier   Message Identifier to write
  * @param type                 Message Type to write
  * @param identifier   Message Identifier to write
+ * @param data                 Message value to write
  * @return                             TRUE if data written successfully
  */
  * @return                             TRUE if data written successfully
  */
-bool pt_tls_write(tls_socket_t *tls, bio_writer_t *writer,
-                                 pt_tls_message_type_t type, u_int32_t identifier);
+bool pt_tls_write(tls_socket_t *tls, pt_tls_message_type_t type,
+                                 u_int32_t identifier, chunk_t data);
 
 /**
  * @}
 
 /**
  * @}
index 6df3235..01a84cd 100644 (file)
@@ -102,6 +102,7 @@ static bool negotiate_version(private_pt_tls_client_t *this)
        bio_reader_t *reader;
        u_int32_t type, vendor, identifier, reserved;
        u_int8_t version;
        bio_reader_t *reader;
        u_int32_t type, vendor, identifier, reserved;
        u_int8_t version;
+       bool res;
 
        DBG1(DBG_TNC, "sending offer for PT-TLS version %d", PT_TLS_VERSION);
 
 
        DBG1(DBG_TNC, "sending offer for PT-TLS version %d", PT_TLS_VERSION);
 
@@ -110,8 +111,10 @@ static bool negotiate_version(private_pt_tls_client_t *this)
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer->write_uint8(writer, PT_TLS_VERSION);
-       if (!pt_tls_write(this->tls, writer, PT_TLS_VERSION_REQUEST,
-                                         this->identifier++))
+       res = pt_tls_write(this->tls, PT_TLS_VERSION_REQUEST, this->identifier++,
+                                          writer->get_buf(writer));
+       writer->destroy(writer);
+       if (!res)
        {
                return FALSE;
        }
        {
                return FALSE;
        }
@@ -144,6 +147,7 @@ static status_t do_sasl(private_pt_tls_client_t *this, sasl_mechanism_t *sasl)
        bio_reader_t *reader;
        bio_writer_t *writer;
        chunk_t data;
        bio_reader_t *reader;
        bio_writer_t *writer;
        chunk_t data;
+       bool res;
 
        writer = bio_writer_create(32);
        writer->write_data8(writer, chunk_from_str(sasl->get_name(sasl)));
 
        writer = bio_writer_create(32);
        writer->write_data8(writer, chunk_from_str(sasl->get_name(sasl)));
@@ -164,8 +168,10 @@ static status_t do_sasl(private_pt_tls_client_t *this, sasl_mechanism_t *sasl)
                        writer->destroy(writer);
                        return FAILED;
        }
                        writer->destroy(writer);
                        return FAILED;
        }
-       if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_MECH_SELECTION,
-                                         this->identifier++))
+       res = pt_tls_write(this->tls, PT_TLS_SASL_MECH_SELECTION,
+                                          this->identifier++, writer->get_buf(writer));
+       writer->destroy(writer);
+       if (!res)
        {
                return FAILED;
        }
        {
                return FAILED;
        }
@@ -253,8 +259,10 @@ static status_t do_sasl(private_pt_tls_client_t *this, sasl_mechanism_t *sasl)
                                writer->destroy(writer);
                                return FAILED;
                }
                                writer->destroy(writer);
                                return FAILED;
                }
-               if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA,
-                                                 this->identifier++))
+               res = pt_tls_write(this->tls, PT_TLS_SASL_AUTH_DATA,
+                                                  this->identifier++, writer->get_buf(writer));
+               writer->destroy(writer);
+               if (!res)
                {
                        return FAILED;
                }
                {
                        return FAILED;
                }
@@ -351,44 +359,30 @@ static bool assess(private_pt_tls_client_t *this, tls_t *tnccs)
 {
        while (TRUE)
        {
 {
        while (TRUE)
        {
-               bio_writer_t *writer;
+               size_t msglen;
+               size_t buflen = PT_TLS_MAX_MESSAGE_LEN;
+               char buf[buflen];
                bio_reader_t *reader;
                u_int32_t vendor, type, identifier;
                chunk_t data;
 
                bio_reader_t *reader;
                u_int32_t vendor, type, identifier;
                chunk_t data;
 
-               writer = bio_writer_create(32);
-               while (TRUE)
+               switch (tnccs->build(tnccs, buf, &buflen, &msglen))
                {
                {
-                       char buf[2048];
-                       size_t buflen, msglen;
-
-                       buflen = sizeof(buf);
-                       switch (tnccs->build(tnccs, buf, &buflen, &msglen))
-                       {
-                               case SUCCESS:
-                                       writer->destroy(writer);
-                                       return tnccs->is_complete(tnccs);
-                               case FAILED:
-                               default:
-                                       writer->destroy(writer);
+                       case SUCCESS:
+                               return tnccs->is_complete(tnccs);
+                       case ALREADY_DONE:
+                               data = chunk_create(buf, buflen);
+                               if (!pt_tls_write(this->tls, PT_TLS_PB_TNC_BATCH,
+                                                                 this->identifier++, data))
+                               {
                                        return FALSE;
                                        return FALSE;
-                               case INVALID_STATE:
-                                       writer->destroy(writer);
-                                       break;
-                               case NEED_MORE:
-                                       writer->write_data(writer, chunk_create(buf, buflen));
-                                       continue;
-                               case ALREADY_DONE:
-                                       writer->write_data(writer, chunk_create(buf, buflen));
-                                       if (!pt_tls_write(this->tls, writer, PT_TLS_PB_TNC_BATCH,
-                                                                         this->identifier++))
-                                       {
-                                               return FALSE;
-                                       }
-                                       writer = bio_writer_create(32);
-                                       continue;
-                       }
-                       break;
+                               }
+                               break;
+                       case INVALID_STATE:
+                               break;
+                       case FAILED:
+                       default:
+                               return FALSE;
                }
 
                reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
                }
 
                reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
index 32b5073..69dcdc0 100644 (file)
@@ -73,6 +73,7 @@ static bool negotiate_version(private_pt_tls_server_t *this)
        bio_writer_t *writer;
        u_int32_t vendor, type, identifier;
        u_int8_t reserved, vmin, vmax, vpref;
        bio_writer_t *writer;
        u_int32_t vendor, type, identifier;
        u_int8_t reserved, vmin, vmax, vpref;
+       bool res;
 
        reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
        if (!reader)
 
        reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
        if (!reader)
@@ -100,9 +101,10 @@ static bool negotiate_version(private_pt_tls_server_t *this)
        writer = bio_writer_create(4);
        writer->write_uint24(writer, 0);
        writer->write_uint8(writer, PT_TLS_VERSION);
        writer = bio_writer_create(4);
        writer->write_uint24(writer, 0);
        writer->write_uint8(writer, PT_TLS_VERSION);
-
-       return pt_tls_write(this->tls, writer, PT_TLS_VERSION_RESPONSE,
-                                               this->identifier++);
+       res = pt_tls_write(this->tls, PT_TLS_VERSION_RESPONSE,
+                                          this->identifier++, writer->get_buf(writer));
+       writer->destroy(writer);
+       return res;
 }
 
 /**
 }
 
 /**
@@ -114,6 +116,7 @@ static status_t process_sasl(private_pt_tls_server_t *this,
        bio_writer_t *writer;
        identification_t *client;
        tnccs_t *tnccs;
        bio_writer_t *writer;
        identification_t *client;
        tnccs_t *tnccs;
+       bool res;
 
        switch (sasl->process(sasl, data))
        {
 
        switch (sasl->process(sasl, data))
        {
@@ -135,12 +138,10 @@ static status_t process_sasl(private_pt_tls_server_t *this,
                        }
                        writer = bio_writer_create(1);
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
                        }
                        writer = bio_writer_create(1);
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
-                       if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
-                                                        this->identifier++))
-                       {
-                               return SUCCESS;
-                       }
-                       return FAILED;
+                       res = pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+                                                          this->identifier++, writer->get_buf(writer));
+                       writer->destroy(writer);
+                       return res ? SUCCESS : FAILED;
                case FAILED:
                default:
                        DBG1(DBG_TNC, "SASL %s authentication failed",
                case FAILED:
                default:
                        DBG1(DBG_TNC, "SASL %s authentication failed",
@@ -148,8 +149,8 @@ static status_t process_sasl(private_pt_tls_server_t *this,
                        writer = bio_writer_create(1);
                        /* sending abort does not allow the client to retry */
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT);
                        writer = bio_writer_create(1);
                        /* sending abort does not allow the client to retry */
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT);
-                       pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
-                                                this->identifier++);
+                       pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+                                                this->identifier++, writer->get_buf(writer));
                        return FAILED;
        }
 }
                        return FAILED;
        }
 }
@@ -189,19 +190,15 @@ static status_t write_sasl(private_pt_tls_server_t *this,
 {
        bio_writer_t *writer;
        chunk_t chunk;
 {
        bio_writer_t *writer;
        chunk_t chunk;
+       bool res;
 
        switch (sasl->build(sasl, &chunk))
        {
                case NEED_MORE:
 
        switch (sasl->build(sasl, &chunk))
        {
                case NEED_MORE:
-                       writer = bio_writer_create(chunk.len);
-                       writer->write_data(writer, chunk);
+                       res = pt_tls_write(this->tls, PT_TLS_SASL_AUTH_DATA,
+                                                          this->identifier++, chunk);
                        free(chunk.ptr);
                        free(chunk.ptr);
-                       if (pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA,
-                                                        this->identifier++))
-                       {
-                               return NEED_MORE;
-                       }
-                       return FAILED;
+                       return res ? NEED_MORE : FAILED;
                case SUCCESS:
                        DBG1(DBG_TNC, "SASL %s authentication successful",
                                 sasl->get_name(sasl));
                case SUCCESS:
                        DBG1(DBG_TNC, "SASL %s authentication successful",
                                 sasl->get_name(sasl));
@@ -209,21 +206,18 @@ static status_t write_sasl(private_pt_tls_server_t *this,
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
                        writer->write_data(writer, chunk);
                        free(chunk.ptr);
                        writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
                        writer->write_data(writer, chunk);
                        free(chunk.ptr);
-                       if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
-                                                        this->identifier++))
-                       {
-                               return SUCCESS;
-                       }
-                       return FAILED;
+                       res = pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+                                                          this->identifier++, writer->get_buf(writer));
+                       writer->destroy(writer);
+                       return res ? SUCCESS : FAILED;
                case FAILED:
                default:
                        DBG1(DBG_TNC, "SASL %s authentication failed",
                                 sasl->get_name(sasl));
                case FAILED:
                default:
                        DBG1(DBG_TNC, "SASL %s authentication failed",
                                 sasl->get_name(sasl));
-                       writer = bio_writer_create(1);
                        /* sending abort does not allow the client to retry */
                        /* sending abort does not allow the client to retry */
-                       writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT);
-                       pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
-                                                this->identifier++);
+                       chunk = chunk_from_chars(PT_TLS_SASL_RESULT_ABORT);
+                       pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+                                                this->identifier++, chunk);
                        return FAILED;
        }
 }
                        return FAILED;
        }
 }
@@ -236,6 +230,7 @@ static bool send_sasl_mechs(private_pt_tls_server_t *this)
        enumerator_t *enumerator;
        bio_writer_t *writer = NULL;
        char *name;
        enumerator_t *enumerator;
        bio_writer_t *writer = NULL;
        char *name;
+       bool res;
 
        enumerator = sasl_mechanism_create_enumerator(TRUE);
        while (enumerator->enumerate(enumerator, &name))
 
        enumerator = sasl_mechanism_create_enumerator(TRUE);
        while (enumerator->enumerate(enumerator, &name))
@@ -253,8 +248,10 @@ static bool send_sasl_mechs(private_pt_tls_server_t *this)
        {       /* no mechanisms available? */
                return FALSE;
        }
        {       /* no mechanisms available? */
                return FALSE;
        }
-       return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
-                                               this->identifier++);
+       res = pt_tls_write(this->tls, PT_TLS_SASL_MECHS,
+                                          this->identifier++, writer->get_buf(writer));
+       writer->destroy(writer);
+       return res;
 }
 
 /**
 }
 
 /**
@@ -394,11 +391,8 @@ static bool authenticate(private_pt_tls_server_t *this)
        if (do_sasl(this))
        {
                /* complete SASL with emtpy mechanism list */
        if (do_sasl(this))
        {
                /* complete SASL with emtpy mechanism list */
-               bio_writer_t *writer;
-
-               writer = bio_writer_create(0);
-               return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
-                                                       this->identifier++);
+               return pt_tls_write(this->tls, PT_TLS_SASL_MECHS, this->identifier++,
+                                                       chunk_empty);
        }
        return FALSE;
 }
        }
        return FALSE;
 }
@@ -410,44 +404,30 @@ static bool assess(private_pt_tls_server_t *this, tls_t *tnccs)
 {
        while (TRUE)
        {
 {
        while (TRUE)
        {
-               bio_writer_t *writer;
+               size_t msglen;
+               size_t buflen = PT_TLS_MAX_MESSAGE_LEN;
+               char buf[buflen];
                bio_reader_t *reader;
                u_int32_t vendor, type, identifier;
                chunk_t data;
 
                bio_reader_t *reader;
                u_int32_t vendor, type, identifier;
                chunk_t data;
 
-               writer = bio_writer_create(32);
-               while (TRUE)
+               switch (tnccs->build(tnccs, buf, &buflen, &msglen))
                {
                {
-                       char buf[2048];
-                       size_t buflen, msglen;
-
-                       buflen = sizeof(buf);
-                       switch (tnccs->build(tnccs, buf, &buflen, &msglen))
-                       {
-                               case SUCCESS:
-                                       writer->destroy(writer);
-                                       return tnccs->is_complete(tnccs);
-                               case FAILED:
-                               default:
-                                       writer->destroy(writer);
+                       case SUCCESS:
+                               return tnccs->is_complete(tnccs);
+                       case ALREADY_DONE:
+                               data = chunk_create(buf, buflen);
+                               if (!pt_tls_write(this->tls, PT_TLS_PB_TNC_BATCH,
+                                                                 this->identifier++, data))
+                               {
                                        return FALSE;
                                        return FALSE;
-                               case INVALID_STATE:
-                                       writer->destroy(writer);
-                                       break;
-                               case NEED_MORE:
-                                       writer->write_data(writer, chunk_create(buf, buflen));
-                                       continue;
-                               case ALREADY_DONE:
-                                       writer->write_data(writer, chunk_create(buf, buflen));
-                                       if (!pt_tls_write(this->tls, writer, PT_TLS_PB_TNC_BATCH,
-                                                                         this->identifier++))
-                                       {
-                                               return FALSE;
-                                       }
-                                       writer = bio_writer_create(32);
-                                       continue;
-                       }
-                       break;
+                               }
+                               break;
+                       case INVALID_STATE:
+                               break;
+                       case FAILED:
+                       default:
+                               return FALSE;
                }
 
                reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
                }
 
                reader = pt_tls_read(this->tls, &vendor, &type, &identifier);