control_fmt.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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.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_fmt.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. /** Acts like sprintf, but writes its formatted string to the end of
  22. * <b>conn</b>-\>outbuf. */
  23. void
  24. connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
  25. {
  26. va_list ap;
  27. char *buf = NULL;
  28. int len;
  29. va_start(ap,format);
  30. len = tor_vasprintf(&buf, format, ap);
  31. va_end(ap);
  32. if (len < 0) {
  33. log_err(LD_BUG, "Unable to format string for controller.");
  34. tor_assert(0);
  35. }
  36. connection_buf_add(buf, (size_t)len, TO_CONN(conn));
  37. tor_free(buf);
  38. }
  39. /** Given an AP connection <b>conn</b> and a <b>len</b>-character buffer
  40. * <b>buf</b>, determine the address:port combination requested on
  41. * <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
  42. * failure. */
  43. int
  44. write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
  45. {
  46. char buf2[256];
  47. if (conn->chosen_exit_name)
  48. if (tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name)<0)
  49. return -1;
  50. if (!conn->socks_request)
  51. return -1;
  52. if (tor_snprintf(buf, len, "%s%s%s:%d",
  53. conn->socks_request->address,
  54. conn->chosen_exit_name ? buf2 : "",
  55. !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
  56. ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
  57. conn->socks_request->port)<0)
  58. return -1;
  59. return 0;
  60. }
  61. /** Figure out the best name for the target router of an OR connection
  62. * <b>conn</b>, and write it into the <b>len</b>-character buffer
  63. * <b>name</b>. */
  64. void
  65. orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
  66. {
  67. const node_t *node = node_get_by_id(conn->identity_digest);
  68. if (node) {
  69. tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
  70. node_get_verbose_nickname(node, name);
  71. } else if (! tor_digest_is_zero(conn->identity_digest)) {
  72. name[0] = '$';
  73. base16_encode(name+1, len-1, conn->identity_digest,
  74. DIGEST_LEN);
  75. } else {
  76. tor_snprintf(name, len, "%s:%d",
  77. conn->base_.address, conn->base_.port);
  78. }
  79. }
  80. /** Allocate and return a description of <b>circ</b>'s current status,
  81. * including its path (if any). */
  82. char *
  83. circuit_describe_status_for_controller(origin_circuit_t *circ)
  84. {
  85. char *rv;
  86. smartlist_t *descparts = smartlist_new();
  87. {
  88. char *vpath = circuit_list_path_for_controller(circ);
  89. if (*vpath) {
  90. smartlist_add(descparts, vpath);
  91. } else {
  92. tor_free(vpath); /* empty path; don't put an extra space in the result */
  93. }
  94. }
  95. {
  96. cpath_build_state_t *build_state = circ->build_state;
  97. smartlist_t *flaglist = smartlist_new();
  98. char *flaglist_joined;
  99. if (build_state->onehop_tunnel)
  100. smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
  101. if (build_state->is_internal)
  102. smartlist_add(flaglist, (void *)"IS_INTERNAL");
  103. if (build_state->need_capacity)
  104. smartlist_add(flaglist, (void *)"NEED_CAPACITY");
  105. if (build_state->need_uptime)
  106. smartlist_add(flaglist, (void *)"NEED_UPTIME");
  107. /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
  108. if (smartlist_len(flaglist)) {
  109. flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
  110. smartlist_add_asprintf(descparts, "BUILD_FLAGS=%s", flaglist_joined);
  111. tor_free(flaglist_joined);
  112. }
  113. smartlist_free(flaglist);
  114. }
  115. smartlist_add_asprintf(descparts, "PURPOSE=%s",
  116. circuit_purpose_to_controller_string(circ->base_.purpose));
  117. {
  118. const char *hs_state =
  119. circuit_purpose_to_controller_hs_state_string(circ->base_.purpose);
  120. if (hs_state != NULL) {
  121. smartlist_add_asprintf(descparts, "HS_STATE=%s", hs_state);
  122. }
  123. }
  124. if (circ->rend_data != NULL || circ->hs_ident != NULL) {
  125. char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
  126. const char *onion_address;
  127. if (circ->rend_data) {
  128. onion_address = rend_data_get_address(circ->rend_data);
  129. } else {
  130. hs_build_address(&circ->hs_ident->identity_pk, HS_VERSION_THREE, addr);
  131. onion_address = addr;
  132. }
  133. smartlist_add_asprintf(descparts, "REND_QUERY=%s", onion_address);
  134. }
  135. {
  136. char tbuf[ISO_TIME_USEC_LEN+1];
  137. format_iso_time_nospace_usec(tbuf, &circ->base_.timestamp_created);
  138. smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf);
  139. }
  140. // Show username and/or password if available.
  141. if (circ->socks_username_len > 0) {
  142. char* socks_username_escaped = esc_for_log_len(circ->socks_username,
  143. (size_t) circ->socks_username_len);
  144. smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
  145. socks_username_escaped);
  146. tor_free(socks_username_escaped);
  147. }
  148. if (circ->socks_password_len > 0) {
  149. char* socks_password_escaped = esc_for_log_len(circ->socks_password,
  150. (size_t) circ->socks_password_len);
  151. smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
  152. socks_password_escaped);
  153. tor_free(socks_password_escaped);
  154. }
  155. rv = smartlist_join_strings(descparts, " ", 0, NULL);
  156. SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
  157. smartlist_free(descparts);
  158. return rv;
  159. }
  160. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  161. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy the
  162. * contents of <b>data</b> into *<b>out</b>, adding a period before any period
  163. * that appears at the start of a line, and adding a period-CRLF line at
  164. * the end. Replace all LF characters sequences with CRLF. Return the number
  165. * of bytes in *<b>out</b>.
  166. */
  167. size_t
  168. write_escaped_data(const char *data, size_t len, char **out)
  169. {
  170. tor_assert(len < SIZE_MAX - 9);
  171. size_t sz_out = len+8+1;
  172. char *outp;
  173. const char *start = data, *end;
  174. size_t i;
  175. int start_of_line;
  176. for (i=0; i < len; ++i) {
  177. if (data[i] == '\n') {
  178. sz_out += 2; /* Maybe add a CR; maybe add a dot. */
  179. if (sz_out >= SIZE_T_CEILING) {
  180. log_warn(LD_BUG, "Input to write_escaped_data was too long");
  181. *out = tor_strdup(".\r\n");
  182. return 3;
  183. }
  184. }
  185. }
  186. *out = outp = tor_malloc(sz_out);
  187. end = data+len;
  188. start_of_line = 1;
  189. while (data < end) {
  190. if (*data == '\n') {
  191. if (data > start && data[-1] != '\r')
  192. *outp++ = '\r';
  193. start_of_line = 1;
  194. } else if (*data == '.') {
  195. if (start_of_line) {
  196. start_of_line = 0;
  197. *outp++ = '.';
  198. }
  199. } else {
  200. start_of_line = 0;
  201. }
  202. *outp++ = *data++;
  203. }
  204. if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
  205. *outp++ = '\r';
  206. *outp++ = '\n';
  207. }
  208. *outp++ = '.';
  209. *outp++ = '\r';
  210. *outp++ = '\n';
  211. *outp = '\0'; /* NUL-terminate just in case. */
  212. tor_assert(outp >= *out);
  213. tor_assert((size_t)(outp - *out) <= sz_out);
  214. return outp - *out;
  215. }
  216. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  217. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy
  218. * the contents of <b>data</b> into *<b>out</b>, removing any period
  219. * that appears at the start of a line, and replacing all CRLF sequences
  220. * with LF. Return the number of
  221. * bytes in *<b>out</b>. */
  222. size_t
  223. read_escaped_data(const char *data, size_t len, char **out)
  224. {
  225. char *outp;
  226. const char *next;
  227. const char *end;
  228. *out = outp = tor_malloc(len+1);
  229. end = data+len;
  230. while (data < end) {
  231. /* we're at the start of a line. */
  232. if (*data == '.')
  233. ++data;
  234. next = memchr(data, '\n', end-data);
  235. if (next) {
  236. size_t n_to_copy = next-data;
  237. /* Don't copy a CR that precedes this LF. */
  238. if (n_to_copy && *(next-1) == '\r')
  239. --n_to_copy;
  240. memcpy(outp, data, n_to_copy);
  241. outp += n_to_copy;
  242. data = next+1; /* This will point at the start of the next line,
  243. * or the end of the string, or a period. */
  244. } else {
  245. memcpy(outp, data, end-data);
  246. outp += (end-data);
  247. *outp = '\0';
  248. return outp - *out;
  249. }
  250. *outp++ = '\n';
  251. }
  252. *outp = '\0';
  253. return outp - *out;
  254. }