Commit 31f8b4fa authored by Nick Mathewson's avatar Nick Mathewson 🎨
Browse files

Merge branch 'stream-socks-auth' into bug19859_merged

parents 68b6d852 f487da51
o Minor features (controller):
- Add stream isolation data to STREAM event. Closes ticket 19859.
......@@ -201,7 +201,7 @@ problem function-size /src/feature/control/control_auth.c:handle_control_authent
problem function-size /src/feature/control/control_cmd.c:handle_control_extendcircuit() 150
problem function-size /src/feature/control/control_cmd.c:handle_control_add_onion() 256
problem function-size /src/feature/control/control_cmd.c:add_onion_helper_keyarg() 118
problem function-size /src/feature/control/control_events.c:control_event_stream_status() 118
problem function-size /src/feature/control/control_events.c:control_event_stream_status() 124
problem include-count /src/feature/control/control_getinfo.c 54
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc() 108
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 297
......
......@@ -833,13 +833,19 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event(EVENT_STREAM_STATUS,
"650 STREAM %"PRIu64" %s %lu %s%s%s%s\r\n",
{
char *conndesc = entry_connection_describe_status_for_controller(conn);
const char *sp = strlen(conndesc) ? " " : "";
send_control_event(EVENT_STREAM_STATUS,
"650 STREAM %"PRIu64" %s %lu %s%s%s%s%s%s\r\n",
(ENTRY_TO_CONN(conn)->global_identifier),
status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf, reason_buf, addrport_buf, purpose);
buf, reason_buf, addrport_buf, purpose, sp, conndesc);
tor_free(conndesc);
}
/* XXX need to specify its intended exit, etc? */
......
......@@ -165,6 +165,99 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
return rv;
}
/** Allocate and return a description of <b>conn</b>'s current status. */
char *
entry_connection_describe_status_for_controller(const entry_connection_t *conn)
{
char *rv;
smartlist_t *descparts = smartlist_new();
if (conn->socks_request != NULL) {
// Show username and/or password if available; used by IsolateSOCKSAuth.
if (conn->socks_request->usernamelen > 0) {
char* username_escaped = esc_for_log_len(conn->socks_request->username,
(size_t) conn->socks_request->usernamelen);
smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
username_escaped);
tor_free(username_escaped);
}
if (conn->socks_request->passwordlen > 0) {
char* password_escaped = esc_for_log_len(conn->socks_request->password,
(size_t) conn->socks_request->passwordlen);
smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
password_escaped);
tor_free(password_escaped);
}
const char *client_protocol;
// Show the client protocol; used by IsolateClientProtocol.
switch (conn->socks_request->listener_type)
{
case CONN_TYPE_AP_LISTENER:
switch (conn->socks_request->socks_version)
{
case 4: client_protocol = "SOCKS4"; break;
case 5: client_protocol = "SOCKS5"; break;
default: client_protocol = "UNKNOWN";
}
break;
case CONN_TYPE_AP_TRANS_LISTENER: client_protocol = "TRANS"; break;
case CONN_TYPE_AP_NATD_LISTENER: client_protocol = "NATD"; break;
case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
client_protocol = "HTTPCONNECT"; break;
default: client_protocol = "UNKNOWN";
}
smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
client_protocol);
}
// Show newnym epoch; used for stream isolation when NEWNYM is used.
smartlist_add_asprintf(descparts, "NYM_EPOCH=%u",
conn->nym_epoch);
// Show session group; used for stream isolation of multiple listener ports.
smartlist_add_asprintf(descparts, "SESSION_GROUP=%d",
conn->entry_cfg.session_group);
// Show isolation flags.
smartlist_t *isoflaglist = smartlist_new();
char *isoflaglist_joined;
if (conn->entry_cfg.isolation_flags & ISO_DESTPORT) {
smartlist_add(isoflaglist, (void *)"DESTPORT");
}
if (conn->entry_cfg.isolation_flags & ISO_DESTADDR) {
smartlist_add(isoflaglist, (void *)"DESTADDR");
}
if (conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) {
smartlist_add(isoflaglist, (void *)"SOCKS_USERNAME");
smartlist_add(isoflaglist, (void *)"SOCKS_PASSWORD");
}
if (conn->entry_cfg.isolation_flags & ISO_CLIENTPROTO) {
smartlist_add(isoflaglist, (void *)"CLIENT_PROTOCOL");
}
if (conn->entry_cfg.isolation_flags & ISO_CLIENTADDR) {
smartlist_add(isoflaglist, (void *)"CLIENTADDR");
}
if (conn->entry_cfg.isolation_flags & ISO_SESSIONGRP) {
smartlist_add(isoflaglist, (void *)"SESSION_GROUP");
}
if (conn->entry_cfg.isolation_flags & ISO_NYM_EPOCH) {
smartlist_add(isoflaglist, (void *)"NYM_EPOCH");
}
isoflaglist_joined = smartlist_join_strings(isoflaglist, ",", 0, NULL);
smartlist_add_asprintf(descparts, "ISO_FIELDS=%s", isoflaglist_joined);
tor_free(isoflaglist_joined);
smartlist_free(isoflaglist);
rv = smartlist_join_strings(descparts, " ", 0, NULL);
SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
smartlist_free(descparts);
return rv;
}
/** Return a longname the node whose identity is <b>id_digest</b>. If
* node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
* returned instead.
......
......@@ -17,6 +17,8 @@ int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn);
char *circuit_describe_status_for_controller(origin_circuit_t *circ);
char *entry_connection_describe_status_for_controller(const
entry_connection_t *conn);
MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
......
......@@ -16,11 +16,14 @@
#include "core/or/orconn_event.h"
#include "core/mainloop/connection.h"
#include "feature/control/control_events.h"
#include "feature/control/control_fmt.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "core/or/entry_connection_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/socks_request_st.h"
static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
......@@ -537,6 +540,133 @@ test_cntev_orconn_state_proxy(void *arg)
UNMOCK(queue_control_event_string);
}
static void
test_cntev_format_stream(void *arg)
{
entry_connection_t *ec = NULL;
char *conndesc = NULL;
(void)arg;
ec = entry_connection_new(CONN_TYPE_AP, AF_INET);
char *username = tor_strdup("jeremy");
char *password = tor_strdup("letmein");
ec->socks_request->username = username; // steal reference
ec->socks_request->usernamelen = strlen(username);
ec->socks_request->password = password; // steal reference
ec->socks_request->passwordlen = strlen(password);
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "SOCKS_USERNAME=\"jeremy\""));
tt_assert(strstr(conndesc, "SOCKS_PASSWORD=\"letmein\""));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
ec->socks_request->socks_version = 4;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS4"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
ec->socks_request->socks_version = 5;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS5"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
ec->socks_request->socks_version = 6;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_TRANS_LISTENER;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=TRANS"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_NATD_LISTENER;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=NATD"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_DNS_LISTENER;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=DNS"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=HTTPCONNECT"));
tor_free(conndesc);
ec->socks_request->listener_type = CONN_TYPE_OR;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
tor_free(conndesc);
ec->nym_epoch = 1337;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "NYM_EPOCH=1337"));
tor_free(conndesc);
ec->entry_cfg.session_group = 4321;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "SESSION_GROUP=4321"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_DESTPORT;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=DESTPORT"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTPORT,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_DESTADDR;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=DESTADDR"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTADDR,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_SOCKSAUTH;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_CLIENTPROTO;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_CLIENTADDR;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENTADDR"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENTADDR,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_SESSIONGRP;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=SESSION_GROUP"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=SESSION_GROUP,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_NYM_EPOCH;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc, "ISO_FIELDS=NYM_EPOCH"));
tt_assert(!strstr(conndesc, "ISO_FIELDS=NYM_EPOCH,"));
tor_free(conndesc);
ec->entry_cfg.isolation_flags = ISO_DESTPORT | ISO_SOCKSAUTH | ISO_NYM_EPOCH;
conndesc = entry_connection_describe_status_for_controller(ec);
tt_assert(strstr(conndesc,
"ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH"));
tt_assert(!strstr(conndesc,
"ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH,"));
done:
tor_free(conndesc);
connection_free_minimal(ENTRY_TO_CONN(ec));
}
#define TEST(name, flags) \
{ #name, test_cntev_ ## name, flags, 0, NULL }
......@@ -548,6 +678,7 @@ struct testcase_t controller_event_tests[] = {
TEST(append_cell_stats, TT_FORK),
TEST(format_cell_stats, TT_FORK),
TEST(event_mask, TT_FORK),
TEST(format_stream, TT_FORK),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment