control_proto.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  2. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  3. /* See LICENSE for licensing information */
  4. /**
  5. * \file control_proto.c
  6. * \brief Formatting functions for controller data.
  7. */
  8. #include "core/or/or.h"
  9. #include "core/mainloop/connection.h"
  10. #include "core/or/circuitbuild.h"
  11. #include "core/or/circuitlist.h"
  12. #include "core/or/connection_edge.h"
  13. #include "feature/control/control_proto.h"
  14. #include "feature/nodelist/nodelist.h"
  15. #include "core/or/cpath_build_state_st.h"
  16. #include "core/or/entry_connection_st.h"
  17. #include "core/or/or_connection_st.h"
  18. #include "core/or/origin_circuit_st.h"
  19. #include "core/or/socks_request_st.h"
  20. #include "feature/control/control_connection_st.h"
  21. /** Append a NUL-terminated string <b>s</b> to the end of
  22. * <b>conn</b>-\>outbuf.
  23. */
  24. void
  25. connection_write_str_to_buf(const char *s, control_connection_t *conn)
  26. {
  27. size_t len = strlen(s);
  28. connection_buf_add(s, len, TO_CONN(conn));
  29. }
  30. /** Acts like sprintf, but writes its formatted string to the end of
  31. * <b>conn</b>-\>outbuf. */
  32. void
  33. connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
  34. {
  35. va_list ap;
  36. char *buf = NULL;
  37. int len;
  38. va_start(ap,format);
  39. len = tor_vasprintf(&buf, format, ap);
  40. va_end(ap);
  41. if (len < 0) {
  42. log_err(LD_BUG, "Unable to format string for controller.");
  43. tor_assert(0);
  44. }
  45. connection_buf_add(buf, (size_t)len, TO_CONN(conn));
  46. tor_free(buf);
  47. }
  48. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  49. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy the
  50. * contents of <b>data</b> into *<b>out</b>, adding a period before any period
  51. * that appears at the start of a line, and adding a period-CRLF line at
  52. * the end. Replace all LF characters sequences with CRLF. Return the number
  53. * of bytes in *<b>out</b>.
  54. */
  55. size_t
  56. write_escaped_data(const char *data, size_t len, char **out)
  57. {
  58. tor_assert(len < SIZE_MAX - 9);
  59. size_t sz_out = len+8+1;
  60. char *outp;
  61. const char *start = data, *end;
  62. size_t i;
  63. int start_of_line;
  64. for (i=0; i < len; ++i) {
  65. if (data[i] == '\n') {
  66. sz_out += 2; /* Maybe add a CR; maybe add a dot. */
  67. if (sz_out >= SIZE_T_CEILING) {
  68. log_warn(LD_BUG, "Input to write_escaped_data was too long");
  69. *out = tor_strdup(".\r\n");
  70. return 3;
  71. }
  72. }
  73. }
  74. *out = outp = tor_malloc(sz_out);
  75. end = data+len;
  76. start_of_line = 1;
  77. while (data < end) {
  78. if (*data == '\n') {
  79. if (data > start && data[-1] != '\r')
  80. *outp++ = '\r';
  81. start_of_line = 1;
  82. } else if (*data == '.') {
  83. if (start_of_line) {
  84. start_of_line = 0;
  85. *outp++ = '.';
  86. }
  87. } else {
  88. start_of_line = 0;
  89. }
  90. *outp++ = *data++;
  91. }
  92. if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
  93. *outp++ = '\r';
  94. *outp++ = '\n';
  95. }
  96. *outp++ = '.';
  97. *outp++ = '\r';
  98. *outp++ = '\n';
  99. *outp = '\0'; /* NUL-terminate just in case. */
  100. tor_assert(outp >= *out);
  101. tor_assert((size_t)(outp - *out) <= sz_out);
  102. return outp - *out;
  103. }
  104. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  105. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy
  106. * the contents of <b>data</b> into *<b>out</b>, removing any period
  107. * that appears at the start of a line, and replacing all CRLF sequences
  108. * with LF. Return the number of
  109. * bytes in *<b>out</b>. */
  110. size_t
  111. read_escaped_data(const char *data, size_t len, char **out)
  112. {
  113. char *outp;
  114. const char *next;
  115. const char *end;
  116. *out = outp = tor_malloc(len+1);
  117. end = data+len;
  118. while (data < end) {
  119. /* we're at the start of a line. */
  120. if (*data == '.')
  121. ++data;
  122. next = memchr(data, '\n', end-data);
  123. if (next) {
  124. size_t n_to_copy = next-data;
  125. /* Don't copy a CR that precedes this LF. */
  126. if (n_to_copy && *(next-1) == '\r')
  127. --n_to_copy;
  128. memcpy(outp, data, n_to_copy);
  129. outp += n_to_copy;
  130. data = next+1; /* This will point at the start of the next line,
  131. * or the end of the string, or a period. */
  132. } else {
  133. memcpy(outp, data, end-data);
  134. outp += (end-data);
  135. *outp = '\0';
  136. return outp - *out;
  137. }
  138. *outp++ = '\n';
  139. }
  140. *outp = '\0';
  141. return outp - *out;
  142. }
  143. /** Send a "DONE" message down the control connection <b>conn</b>. */
  144. void
  145. send_control_done(control_connection_t *conn)
  146. {
  147. connection_write_str_to_buf("250 OK\r\n", conn);
  148. }