Line data Source code
1 : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 : /* See LICENSE for licensing information */
4 :
5 : /**
6 : * \file control_fmt.c
7 : * \brief Formatting functions for controller data.
8 : */
9 :
10 : #include "core/or/or.h"
11 :
12 : #include "core/mainloop/connection.h"
13 : #include "core/or/circuitbuild.h"
14 : #include "core/or/circuitlist.h"
15 : #include "core/or/connection_edge.h"
16 : #include "feature/control/control_fmt.h"
17 : #include "feature/control/control_proto.h"
18 : #include "feature/nodelist/nodelist.h"
19 :
20 : #include "core/or/cpath_build_state_st.h"
21 : #include "core/or/entry_connection_st.h"
22 : #include "core/or/or_connection_st.h"
23 : #include "core/or/origin_circuit_st.h"
24 : #include "core/or/socks_request_st.h"
25 : #include "feature/control/control_connection_st.h"
26 :
27 : /** Given an AP connection <b>conn</b> and a <b>len</b>-character buffer
28 : * <b>buf</b>, determine the address:port combination requested on
29 : * <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
30 : * failure. */
31 : int
32 0 : write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
33 : {
34 0 : char buf2[256];
35 0 : if (conn->chosen_exit_name)
36 0 : if (tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name)<0)
37 : return -1;
38 0 : if (!conn->socks_request)
39 : return -1;
40 0 : if (tor_snprintf(buf, len, "%s%s%s:%d",
41 0 : conn->socks_request->address,
42 0 : conn->chosen_exit_name ? buf2 : "",
43 0 : !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
44 0 : ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
45 0 : conn->socks_request->port)<0)
46 0 : return -1;
47 : return 0;
48 : }
49 :
50 : /** Figure out the best name for the target router of an OR connection
51 : * <b>conn</b>, and write it into the <b>len</b>-character buffer
52 : * <b>name</b>. */
53 : void
54 0 : orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
55 : {
56 0 : const node_t *node = node_get_by_id(conn->identity_digest);
57 0 : if (node) {
58 0 : tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
59 0 : node_get_verbose_nickname(node, name);
60 0 : } else if (! tor_digest_is_zero(conn->identity_digest)) {
61 0 : name[0] = '$';
62 0 : base16_encode(name+1, len-1, conn->identity_digest,
63 : DIGEST_LEN);
64 : } else {
65 0 : tor_snprintf(name, len, "%s:%d",
66 0 : conn->base_.address, conn->base_.port);
67 : }
68 0 : }
69 :
70 : /** Allocate and return a description of <b>circ</b>'s current status,
71 : * including its path (if any). */
72 : char *
73 0 : circuit_describe_status_for_controller(origin_circuit_t *circ)
74 : {
75 0 : char *rv;
76 0 : smartlist_t *descparts = smartlist_new();
77 :
78 : {
79 0 : char *vpath = circuit_list_path_for_controller(circ);
80 0 : if (*vpath) {
81 0 : smartlist_add(descparts, vpath);
82 : } else {
83 0 : tor_free(vpath); /* empty path; don't put an extra space in the result */
84 : }
85 : }
86 :
87 : {
88 0 : cpath_build_state_t *build_state = circ->build_state;
89 0 : smartlist_t *flaglist = smartlist_new();
90 0 : char *flaglist_joined;
91 :
92 0 : if (build_state->onehop_tunnel)
93 0 : smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
94 0 : if (build_state->is_internal)
95 0 : smartlist_add(flaglist, (void *)"IS_INTERNAL");
96 0 : if (build_state->need_capacity)
97 0 : smartlist_add(flaglist, (void *)"NEED_CAPACITY");
98 0 : if (build_state->need_uptime)
99 0 : smartlist_add(flaglist, (void *)"NEED_UPTIME");
100 :
101 : /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
102 0 : if (smartlist_len(flaglist)) {
103 0 : flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
104 :
105 0 : smartlist_add_asprintf(descparts, "BUILD_FLAGS=%s", flaglist_joined);
106 :
107 0 : tor_free(flaglist_joined);
108 : }
109 :
110 0 : smartlist_free(flaglist);
111 : }
112 :
113 0 : smartlist_add_asprintf(descparts, "PURPOSE=%s",
114 0 : circuit_purpose_to_controller_string(circ->base_.purpose));
115 :
116 : {
117 0 : const char *hs_state =
118 0 : circuit_purpose_to_controller_hs_state_string(circ->base_.purpose);
119 :
120 0 : if (hs_state != NULL) {
121 0 : smartlist_add_asprintf(descparts, "HS_STATE=%s", hs_state);
122 : }
123 : }
124 :
125 0 : if (circ->hs_ident != NULL) {
126 0 : char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
127 0 : const char *onion_address;
128 0 : hs_build_address(&circ->hs_ident->identity_pk, HS_VERSION_THREE, addr);
129 0 : onion_address = addr;
130 0 : smartlist_add_asprintf(descparts, "REND_QUERY=%s", onion_address);
131 : }
132 :
133 : {
134 0 : char tbuf[ISO_TIME_USEC_LEN+1];
135 0 : format_iso_time_nospace_usec(tbuf, &circ->base_.timestamp_created);
136 :
137 0 : smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf);
138 : }
139 :
140 : // Show username and/or password if available.
141 0 : if (circ->socks_username_len > 0) {
142 0 : char* socks_username_escaped = esc_for_log_len(circ->socks_username,
143 : (size_t) circ->socks_username_len);
144 0 : smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
145 : socks_username_escaped);
146 0 : tor_free(socks_username_escaped);
147 : }
148 0 : if (circ->socks_password_len > 0) {
149 0 : char* socks_password_escaped = esc_for_log_len(circ->socks_password,
150 : (size_t) circ->socks_password_len);
151 0 : smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
152 : socks_password_escaped);
153 0 : tor_free(socks_password_escaped);
154 : }
155 :
156 0 : rv = smartlist_join_strings(descparts, " ", 0, NULL);
157 :
158 0 : SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
159 0 : smartlist_free(descparts);
160 :
161 0 : return rv;
162 : }
163 :
164 : /** Allocate and return a description of <b>conn</b>'s current status. */
165 : char *
166 19 : entry_connection_describe_status_for_controller(const entry_connection_t *conn)
167 : {
168 19 : char *rv;
169 19 : smartlist_t *descparts = smartlist_new();
170 :
171 19 : if (conn->socks_request != NULL) {
172 : // Show username and/or password if available; used by IsolateSOCKSAuth.
173 19 : if (conn->socks_request->usernamelen > 0) {
174 19 : char* username_escaped = esc_for_log_len(conn->socks_request->username,
175 : (size_t) conn->socks_request->usernamelen);
176 19 : smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
177 : username_escaped);
178 19 : tor_free(username_escaped);
179 : }
180 19 : if (conn->socks_request->passwordlen > 0) {
181 19 : char* password_escaped = esc_for_log_len(conn->socks_request->password,
182 : (size_t) conn->socks_request->passwordlen);
183 19 : smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
184 : password_escaped);
185 19 : tor_free(password_escaped);
186 : }
187 :
188 19 : const char *client_protocol;
189 : // Show the client protocol; used by IsolateClientProtocol.
190 19 : switch (conn->socks_request->listener_type)
191 : {
192 3 : case CONN_TYPE_AP_LISTENER:
193 3 : switch (conn->socks_request->socks_version)
194 : {
195 : case 4: client_protocol = "SOCKS4"; break;
196 1 : case 5: client_protocol = "SOCKS5"; break;
197 1 : default: client_protocol = "UNKNOWN";
198 : }
199 : break;
200 : case CONN_TYPE_AP_TRANS_LISTENER: client_protocol = "TRANS"; break;
201 1 : case CONN_TYPE_AP_NATD_LISTENER: client_protocol = "NATD"; break;
202 1 : case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
203 1 : case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
204 1 : client_protocol = "HTTPCONNECT"; break;
205 0 : case CONN_TYPE_METRICS_LISTENER:
206 0 : client_protocol = "METRICS"; break;
207 12 : default: client_protocol = "UNKNOWN";
208 : }
209 19 : smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
210 : client_protocol);
211 : }
212 :
213 : // Show newnym epoch; used for stream isolation when NEWNYM is used.
214 19 : smartlist_add_asprintf(descparts, "NYM_EPOCH=%u",
215 19 : conn->nym_epoch);
216 :
217 : // Show session group; used for stream isolation of multiple listener ports.
218 19 : smartlist_add_asprintf(descparts, "SESSION_GROUP=%d",
219 19 : conn->entry_cfg.session_group);
220 :
221 : // Show isolation flags.
222 19 : smartlist_t *isoflaglist = smartlist_new();
223 19 : char *isoflaglist_joined;
224 19 : if (conn->entry_cfg.isolation_flags & ISO_DESTPORT) {
225 2 : smartlist_add(isoflaglist, (void *)"DESTPORT");
226 : }
227 19 : if (conn->entry_cfg.isolation_flags & ISO_DESTADDR) {
228 1 : smartlist_add(isoflaglist, (void *)"DESTADDR");
229 : }
230 19 : if (conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) {
231 2 : smartlist_add(isoflaglist, (void *)"SOCKS_USERNAME");
232 2 : smartlist_add(isoflaglist, (void *)"SOCKS_PASSWORD");
233 : }
234 19 : if (conn->entry_cfg.isolation_flags & ISO_CLIENTPROTO) {
235 1 : smartlist_add(isoflaglist, (void *)"CLIENT_PROTOCOL");
236 : }
237 19 : if (conn->entry_cfg.isolation_flags & ISO_CLIENTADDR) {
238 1 : smartlist_add(isoflaglist, (void *)"CLIENTADDR");
239 : }
240 19 : if (conn->entry_cfg.isolation_flags & ISO_SESSIONGRP) {
241 1 : smartlist_add(isoflaglist, (void *)"SESSION_GROUP");
242 : }
243 19 : if (conn->entry_cfg.isolation_flags & ISO_NYM_EPOCH) {
244 2 : smartlist_add(isoflaglist, (void *)"NYM_EPOCH");
245 : }
246 19 : isoflaglist_joined = smartlist_join_strings(isoflaglist, ",", 0, NULL);
247 19 : smartlist_add_asprintf(descparts, "ISO_FIELDS=%s", isoflaglist_joined);
248 19 : tor_free(isoflaglist_joined);
249 19 : smartlist_free(isoflaglist);
250 :
251 19 : rv = smartlist_join_strings(descparts, " ", 0, NULL);
252 :
253 133 : SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
254 19 : smartlist_free(descparts);
255 :
256 19 : return rv;
257 : }
258 :
259 : /** Return a longname the node whose identity is <b>id_digest</b>. If
260 : * node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
261 : * returned instead.
262 : *
263 : * This function is not thread-safe. Each call to this function invalidates
264 : * previous values returned by this function.
265 : */
266 78 : MOCK_IMPL(const char *,
267 : node_describe_longname_by_id,(const char *id_digest))
268 : {
269 78 : static char longname[MAX_VERBOSE_NICKNAME_LEN+1];
270 78 : node_get_verbose_nickname_by_id(id_digest, longname);
271 78 : return longname;
272 : }
|