pt_tls.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (C) 2012 Martin Willi
  3. * Copyright (C) 2012 revosec AG
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * for more details.
  14. */
  15. #include "pt_tls.h"
  16. #include <utils/debug.h>
  17. #include <pen/pen.h>
  18. /**
  19. * Described in header.
  20. */
  21. void libpttls_init(void)
  22. {
  23. /* empty */
  24. }
  25. /*
  26. * PT-TNC Message format:
  27. * 1 2 3
  28. * 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
  29. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  30. * | Reserved | Message Type Vendor ID |
  31. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  32. * | Message Type |
  33. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  34. * | Message Length |
  35. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. * | Message Identifier |
  37. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  38. * | Message Value (e.g. PB-TNC Batch) . . . |
  39. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  40. */
  41. ENUM(pt_tls_message_type_names, PT_TLS_EXPERIMENTAL, PT_TLS_ERROR,
  42. "Experimental",
  43. "Version Request",
  44. "Version Response",
  45. "SASL Mechanisms",
  46. "SASL Mechanism Selection",
  47. "SASL Authentication Data",
  48. "SASL Result",
  49. "PB-TNC Batch",
  50. "PT-TLS Error"
  51. );
  52. ENUM(pt_tls_sasl_result_names, PT_TLS_SASL_RESULT_SUCCESS,
  53. PT_TLS_SASL_RESULT_MECH_FAILURE,
  54. "Success",
  55. "Failure",
  56. "Abort",
  57. "Mechanism Failure"
  58. );
  59. /**
  60. * Read a chunk of data from TLS, returning a reader for it
  61. */
  62. static bio_reader_t* read_tls(tls_socket_t *tls, size_t len)
  63. {
  64. ssize_t got, total = 0;
  65. char *buf;
  66. buf = malloc(len);
  67. while (total < len)
  68. {
  69. got = tls->read(tls, buf + total, len - total, TRUE);
  70. if (got <= 0)
  71. {
  72. free(buf);
  73. return NULL;
  74. }
  75. total += got;
  76. }
  77. return bio_reader_create_own(chunk_create(buf, len));
  78. }
  79. /**
  80. * Read a PT-TLS message, return header data
  81. */
  82. bio_reader_t* pt_tls_read(tls_socket_t *tls, uint32_t *vendor,
  83. uint32_t *type, uint32_t *identifier)
  84. {
  85. bio_reader_t *reader;
  86. uint32_t len;
  87. uint8_t reserved;
  88. reader = read_tls(tls, PT_TLS_HEADER_LEN);
  89. if (!reader)
  90. {
  91. return NULL;
  92. }
  93. if (!reader->read_uint8(reader, &reserved) ||
  94. !reader->read_uint24(reader, vendor) ||
  95. !reader->read_uint32(reader, type) ||
  96. !reader->read_uint32(reader, &len) ||
  97. !reader->read_uint32(reader, identifier))
  98. {
  99. reader->destroy(reader);
  100. return NULL;
  101. }
  102. reader->destroy(reader);
  103. if (len < PT_TLS_HEADER_LEN)
  104. {
  105. DBG1(DBG_TNC, "received short PT-TLS header (%d bytes)", len);
  106. return NULL;
  107. }
  108. if (*vendor == PEN_IETF)
  109. {
  110. DBG2(DBG_TNC, "received PT-TLS message #%d of type '%N' (%d bytes)",
  111. *identifier, pt_tls_message_type_names, *type, len);
  112. }
  113. else
  114. {
  115. DBG2(DBG_TNC, "received PT-TLS message #%d of unknown type "
  116. "0x%06x/0x%08x (%d bytes)",
  117. *identifier, *vendor, *type, len);
  118. }
  119. return read_tls(tls, len - PT_TLS_HEADER_LEN);
  120. }
  121. /**
  122. * Prepend a PT-TLS header to a writer, send data, destroy writer
  123. */
  124. bool pt_tls_write(tls_socket_t *tls, pt_tls_message_type_t type,
  125. uint32_t identifier, chunk_t data)
  126. {
  127. bio_writer_t *writer;
  128. chunk_t out;
  129. ssize_t len;
  130. len = PT_TLS_HEADER_LEN + data.len;
  131. writer = bio_writer_create(len);
  132. /* write PT-TLS header */
  133. writer->write_uint8 (writer, 0);
  134. writer->write_uint24(writer, 0);
  135. writer->write_uint32(writer, type);
  136. writer->write_uint32(writer, len);
  137. writer->write_uint32(writer, identifier);
  138. /* write PT-TLS body */
  139. writer->write_data(writer, data);
  140. DBG2(DBG_TNC, "sending PT-TLS message #%d of type '%N' (%d bytes)",
  141. identifier, pt_tls_message_type_names, type, len);
  142. out = writer->get_buf(writer);
  143. len = tls->write(tls, out.ptr, out.len);
  144. writer->destroy(writer);
  145. return len == out.len;
  146. }