control_fmt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. /** 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 an AP connection <b>conn</b> and a <b>len</b>-character buffer
  49. * <b>buf</b>, determine the address:port combination requested on
  50. * <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
  51. * failure. */
  52. int
  53. write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
  54. {
  55. char buf2[256];
  56. if (conn->chosen_exit_name)
  57. if (tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name)<0)
  58. return -1;
  59. if (!conn->socks_request)
  60. return -1;
  61. if (tor_snprintf(buf, len, "%s%s%s:%d",
  62. conn->socks_request->address,
  63. conn->chosen_exit_name ? buf2 : "",
  64. !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
  65. ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
  66. conn->socks_request->port)<0)
  67. return -1;
  68. return 0;
  69. }
  70. /** Figure out the best name for the target router of an OR connection
  71. * <b>conn</b>, and write it into the <b>len</b>-character buffer
  72. * <b>name</b>. */
  73. void
  74. orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
  75. {
  76. const node_t *node = node_get_by_id(conn->identity_digest);
  77. if (node) {
  78. tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
  79. node_get_verbose_nickname(node, name);
  80. } else if (! tor_digest_is_zero(conn->identity_digest)) {
  81. name[0] = '$';
  82. base16_encode(name+1, len-1, conn->identity_digest,
  83. DIGEST_LEN);
  84. } else {
  85. tor_snprintf(name, len, "%s:%d",
  86. conn->base_.address, conn->base_.port);
  87. }
  88. }
  89. /** Allocate and return a description of <b>circ</b>'s current status,
  90. * including its path (if any). */
  91. char *
  92. circuit_describe_status_for_controller(origin_circuit_t *circ)
  93. {
  94. char *rv;
  95. smartlist_t *descparts = smartlist_new();
  96. {
  97. char *vpath = circuit_list_path_for_controller(circ);
  98. if (*vpath) {
  99. smartlist_add(descparts, vpath);
  100. } else {
  101. tor_free(vpath); /* empty path; don't put an extra space in the result */
  102. }
  103. }
  104. {
  105. cpath_build_state_t *build_state = circ->build_state;
  106. smartlist_t *flaglist = smartlist_new();
  107. char *flaglist_joined;
  108. if (build_state->onehop_tunnel)
  109. smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
  110. if (build_state->is_internal)
  111. smartlist_add(flaglist, (void *)"IS_INTERNAL");
  112. if (build_state->need_capacity)
  113. smartlist_add(flaglist, (void *)"NEED_CAPACITY");
  114. if (build_state->need_uptime)
  115. smartlist_add(flaglist, (void *)"NEED_UPTIME");
  116. /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
  117. if (smartlist_len(flaglist)) {
  118. flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
  119. smartlist_add_asprintf(descparts, "BUILD_FLAGS=%s", flaglist_joined);
  120. tor_free(flaglist_joined);
  121. }
  122. smartlist_free(flaglist);
  123. }
  124. smartlist_add_asprintf(descparts, "PURPOSE=%s",
  125. circuit_purpose_to_controller_string(circ->base_.purpose));
  126. {
  127. const char *hs_state =
  128. circuit_purpose_to_controller_hs_state_string(circ->base_.purpose);
  129. if (hs_state != NULL) {
  130. smartlist_add_asprintf(descparts, "HS_STATE=%s", hs_state);
  131. }
  132. }
  133. if (circ->rend_data != NULL || circ->hs_ident != NULL) {
  134. char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
  135. const char *onion_address;
  136. if (circ->rend_data) {
  137. onion_address = rend_data_get_address(circ->rend_data);
  138. } else {
  139. hs_build_address(&circ->hs_ident->identity_pk, HS_VERSION_THREE, addr);
  140. onion_address = addr;
  141. }
  142. smartlist_add_asprintf(descparts, "REND_QUERY=%s", onion_address);
  143. }
  144. {
  145. char tbuf[ISO_TIME_USEC_LEN+1];
  146. format_iso_time_nospace_usec(tbuf, &circ->base_.timestamp_created);
  147. smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf);
  148. }
  149. // Show username and/or password if available.
  150. if (circ->socks_username_len > 0) {
  151. char* socks_username_escaped = esc_for_log_len(circ->socks_username,
  152. (size_t) circ->socks_username_len);
  153. smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
  154. socks_username_escaped);
  155. tor_free(socks_username_escaped);
  156. }
  157. if (circ->socks_password_len > 0) {
  158. char* socks_password_escaped = esc_for_log_len(circ->socks_password,
  159. (size_t) circ->socks_password_len);
  160. smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
  161. socks_password_escaped);
  162. tor_free(socks_password_escaped);
  163. }
  164. rv = smartlist_join_strings(descparts, " ", 0, NULL);
  165. SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
  166. smartlist_free(descparts);
  167. return rv;
  168. }
  169. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  170. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy the
  171. * contents of <b>data</b> into *<b>out</b>, adding a period before any period
  172. * that appears at the start of a line, and adding a period-CRLF line at
  173. * the end. Replace all LF characters sequences with CRLF. Return the number
  174. * of bytes in *<b>out</b>.
  175. */
  176. size_t
  177. write_escaped_data(const char *data, size_t len, char **out)
  178. {
  179. tor_assert(len < SIZE_MAX - 9);
  180. size_t sz_out = len+8+1;
  181. char *outp;
  182. const char *start = data, *end;
  183. size_t i;
  184. int start_of_line;
  185. for (i=0; i < len; ++i) {
  186. if (data[i] == '\n') {
  187. sz_out += 2; /* Maybe add a CR; maybe add a dot. */
  188. if (sz_out >= SIZE_T_CEILING) {
  189. log_warn(LD_BUG, "Input to write_escaped_data was too long");
  190. *out = tor_strdup(".\r\n");
  191. return 3;
  192. }
  193. }
  194. }
  195. *out = outp = tor_malloc(sz_out);
  196. end = data+len;
  197. start_of_line = 1;
  198. while (data < end) {
  199. if (*data == '\n') {
  200. if (data > start && data[-1] != '\r')
  201. *outp++ = '\r';
  202. start_of_line = 1;
  203. } else if (*data == '.') {
  204. if (start_of_line) {
  205. start_of_line = 0;
  206. *outp++ = '.';
  207. }
  208. } else {
  209. start_of_line = 0;
  210. }
  211. *outp++ = *data++;
  212. }
  213. if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
  214. *outp++ = '\r';
  215. *outp++ = '\n';
  216. }
  217. *outp++ = '.';
  218. *outp++ = '\r';
  219. *outp++ = '\n';
  220. *outp = '\0'; /* NUL-terminate just in case. */
  221. tor_assert(outp >= *out);
  222. tor_assert((size_t)(outp - *out) <= sz_out);
  223. return outp - *out;
  224. }
  225. /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  226. * terminated by CRLF, allocate a new string in *<b>out</b>, and copy
  227. * the contents of <b>data</b> into *<b>out</b>, removing any period
  228. * that appears at the start of a line, and replacing all CRLF sequences
  229. * with LF. Return the number of
  230. * bytes in *<b>out</b>. */
  231. size_t
  232. read_escaped_data(const char *data, size_t len, char **out)
  233. {
  234. char *outp;
  235. const char *next;
  236. const char *end;
  237. *out = outp = tor_malloc(len+1);
  238. end = data+len;
  239. while (data < end) {
  240. /* we're at the start of a line. */
  241. if (*data == '.')
  242. ++data;
  243. next = memchr(data, '\n', end-data);
  244. if (next) {
  245. size_t n_to_copy = next-data;
  246. /* Don't copy a CR that precedes this LF. */
  247. if (n_to_copy && *(next-1) == '\r')
  248. --n_to_copy;
  249. memcpy(outp, data, n_to_copy);
  250. outp += n_to_copy;
  251. data = next+1; /* This will point at the start of the next line,
  252. * or the end of the string, or a period. */
  253. } else {
  254. memcpy(outp, data, end-data);
  255. outp += (end-data);
  256. *outp = '\0';
  257. return outp - *out;
  258. }
  259. *outp++ = '\n';
  260. }
  261. *outp = '\0';
  262. return outp - *out;
  263. }
  264. /** Send a "DONE" message down the control connection <b>conn</b>. */
  265. void
  266. send_control_done(control_connection_t *conn)
  267. {
  268. connection_write_str_to_buf("250 OK\r\n", conn);
  269. }
  270. /** If the first <b>in_len_max</b> characters in <b>start</b> contain a
  271. * double-quoted string with escaped characters, return the length of that
  272. * string (as encoded, including quotes). Otherwise return -1. */
  273. static inline int
  274. get_escaped_string_length(const char *start, size_t in_len_max,
  275. int *chars_out)
  276. {
  277. const char *cp, *end;
  278. int chars = 0;
  279. if (*start != '\"')
  280. return -1;
  281. cp = start+1;
  282. end = start+in_len_max;
  283. /* Calculate length. */
  284. while (1) {
  285. if (cp >= end) {
  286. return -1; /* Too long. */
  287. } else if (*cp == '\\') {
  288. if (++cp == end)
  289. return -1; /* Can't escape EOS. */
  290. ++cp;
  291. ++chars;
  292. } else if (*cp == '\"') {
  293. break;
  294. } else {
  295. ++cp;
  296. ++chars;
  297. }
  298. }
  299. if (chars_out)
  300. *chars_out = chars;
  301. return (int)(cp - start+1);
  302. }
  303. /** As decode_escaped_string, but does not decode the string: copies the
  304. * entire thing, including quotation marks. */
  305. const char *
  306. extract_escaped_string(const char *start, size_t in_len_max,
  307. char **out, size_t *out_len)
  308. {
  309. int length = get_escaped_string_length(start, in_len_max, NULL);
  310. if (length<0)
  311. return NULL;
  312. *out_len = length;
  313. *out = tor_strndup(start, *out_len);
  314. return start+length;
  315. }
  316. /** Given a pointer to a string starting at <b>start</b> containing
  317. * <b>in_len_max</b> characters, decode a string beginning with one double
  318. * quote, containing any number of non-quote characters or characters escaped
  319. * with a backslash, and ending with a final double quote. Place the resulting
  320. * string (unquoted, unescaped) into a newly allocated string in *<b>out</b>;
  321. * store its length in <b>out_len</b>. On success, return a pointer to the
  322. * character immediately following the escaped string. On failure, return
  323. * NULL. */
  324. const char *
  325. decode_escaped_string(const char *start, size_t in_len_max,
  326. char **out, size_t *out_len)
  327. {
  328. const char *cp, *end;
  329. char *outp;
  330. int len, n_chars = 0;
  331. len = get_escaped_string_length(start, in_len_max, &n_chars);
  332. if (len<0)
  333. return NULL;
  334. end = start+len-1; /* Index of last quote. */
  335. tor_assert(*end == '\"');
  336. outp = *out = tor_malloc(len+1);
  337. *out_len = n_chars;
  338. cp = start+1;
  339. while (cp < end) {
  340. if (*cp == '\\')
  341. ++cp;
  342. *outp++ = *cp++;
  343. }
  344. *outp = '\0';
  345. tor_assert((outp - *out) == (int)*out_len);
  346. return end+1;
  347. }