mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Skeleton ExtORPort implementation. Needs testing, documentation.
Does not implement TransportControlPort yet.
This commit is contained in:
parent
f45e1fbd5b
commit
8bf0382b22
@ -1702,6 +1702,54 @@ fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
#define EXT_OR_CMD_HEADER_SIZE 4
|
||||||
|
/*DOCDOC*/
|
||||||
|
int
|
||||||
|
fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
|
||||||
|
{
|
||||||
|
char hdr[EXT_OR_CMD_HEADER_SIZE];
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
|
check();
|
||||||
|
if (buf->datalen < EXT_OR_CMD_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
peek_from_buf(hdr, sizeof(hdr), buf);
|
||||||
|
len = ntohs(get_uint16(hdr+2));
|
||||||
|
if (buf->datalen < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
*out = ext_or_cmd_new(len);
|
||||||
|
(*out)->cmd = ntohs(get_uint16(hdr));
|
||||||
|
(*out)->len = len;
|
||||||
|
buf_remove_from_front(buf, EXT_OR_CMD_HEADER_SIZE);
|
||||||
|
fetch_from_buf((*out)->body, len, buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_BUFFEREVENTS
|
||||||
|
/*DOCDOC*/
|
||||||
|
int
|
||||||
|
fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out)
|
||||||
|
{
|
||||||
|
char hdr[EXT_OR_CMD_HEADER_SIZE];
|
||||||
|
uint16_t len;
|
||||||
|
size_t buf_len = evbuffer_get_length(buf);
|
||||||
|
|
||||||
|
if (buf_len < EXT_OR_CMD_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
evbuffer_copyout(buf, hdr, EXT_OR_CMD_HEADER_SIZE);
|
||||||
|
len = ntohs(get_uint16(hdr+2));
|
||||||
|
if (buf_len < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
*out = ext_or_cmd_new(len);
|
||||||
|
(*out)->cmd = ntohs(get_uint16(hdr));
|
||||||
|
(*out)->len = len;
|
||||||
|
evbuffer_drain(buf, EXT_OR_CMD_HEADER_SIZE);
|
||||||
|
evbuffer_remove(buf, (*out)->body, len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Implementation helper to implement fetch_from_*_socks. Instead of looking
|
/** Implementation helper to implement fetch_from_*_socks. Instead of looking
|
||||||
* at a buffer's contents, we look at the <b>datalen</b> bytes of data in
|
* at a buffer's contents, we look at the <b>datalen</b> bytes of data in
|
||||||
* <b>data</b>. Instead of removing data from the buffer, we set
|
* <b>data</b>. Instead of removing data from the buffer, we set
|
||||||
|
@ -53,6 +53,8 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
|
|||||||
|
|
||||||
int peek_buf_has_control0_command(buf_t *buf);
|
int peek_buf_has_control0_command(buf_t *buf);
|
||||||
|
|
||||||
|
int fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out);
|
||||||
|
|
||||||
#ifdef USE_BUFFEREVENTS
|
#ifdef USE_BUFFEREVENTS
|
||||||
int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
|
int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
|
||||||
int linkproto);
|
int linkproto);
|
||||||
@ -68,6 +70,8 @@ int peek_evbuffer_has_control0_command(struct evbuffer *buf);
|
|||||||
int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
|
int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
|
||||||
const char *data, size_t data_len,
|
const char *data, size_t data_len,
|
||||||
int done);
|
int done);
|
||||||
|
int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf,
|
||||||
|
ext_or_cmd_t **out);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_BUFFEREVENTS
|
#ifdef USE_BUFFEREVENTS
|
||||||
|
@ -230,6 +230,7 @@ static config_var_t option_vars_[] = {
|
|||||||
V(ExitPolicyRejectPrivate, BOOL, "1"),
|
V(ExitPolicyRejectPrivate, BOOL, "1"),
|
||||||
V(ExitPortStatistics, BOOL, "0"),
|
V(ExitPortStatistics, BOOL, "0"),
|
||||||
V(ExtendAllowPrivateAddresses, BOOL, "0"),
|
V(ExtendAllowPrivateAddresses, BOOL, "0"),
|
||||||
|
VPORT(ExtORPort, LINELIST, NULL),
|
||||||
V(ExtraInfoStatistics, BOOL, "1"),
|
V(ExtraInfoStatistics, BOOL, "1"),
|
||||||
V(FallbackDir, LINELIST, NULL),
|
V(FallbackDir, LINELIST, NULL),
|
||||||
|
|
||||||
@ -5687,6 +5688,14 @@ parse_ports(or_options_t *options, int validate_only,
|
|||||||
*msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
|
*msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (parse_port_config(ports,
|
||||||
|
options->ExtORPort_lines, NULL,
|
||||||
|
"ExtOR", CONN_TYPE_EXT_OR_LISTENER,
|
||||||
|
"127.0.0.1", 0,
|
||||||
|
CL_PORT_SERVER_OPTIONS) < 0) {
|
||||||
|
*msg = tor_strdup("Invalid ExtORPort configuration");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
if (parse_port_config(ports,
|
if (parse_port_config(ports,
|
||||||
options->DirPort_lines, options->DirListenAddress,
|
options->DirPort_lines, options->DirListenAddress,
|
||||||
"Dir", CONN_TYPE_DIR_LISTENER,
|
"Dir", CONN_TYPE_DIR_LISTENER,
|
||||||
|
@ -98,6 +98,7 @@ static smartlist_t *outgoing_addrs = NULL;
|
|||||||
|
|
||||||
#define CASE_ANY_LISTENER_TYPE \
|
#define CASE_ANY_LISTENER_TYPE \
|
||||||
case CONN_TYPE_OR_LISTENER: \
|
case CONN_TYPE_OR_LISTENER: \
|
||||||
|
case CONN_TYPE_EXT_OR_LISTENER: \
|
||||||
case CONN_TYPE_AP_LISTENER: \
|
case CONN_TYPE_AP_LISTENER: \
|
||||||
case CONN_TYPE_DIR_LISTENER: \
|
case CONN_TYPE_DIR_LISTENER: \
|
||||||
case CONN_TYPE_CONTROL_LISTENER: \
|
case CONN_TYPE_CONTROL_LISTENER: \
|
||||||
@ -129,6 +130,8 @@ conn_type_to_string(int type)
|
|||||||
case CONN_TYPE_CPUWORKER: return "CPU worker";
|
case CONN_TYPE_CPUWORKER: return "CPU worker";
|
||||||
case CONN_TYPE_CONTROL_LISTENER: return "Control listener";
|
case CONN_TYPE_CONTROL_LISTENER: return "Control listener";
|
||||||
case CONN_TYPE_CONTROL: return "Control";
|
case CONN_TYPE_CONTROL: return "Control";
|
||||||
|
case CONN_TYPE_EXT_OR: return "Extended OR";
|
||||||
|
case CONN_TYPE_EXT_OR_LISTENER: return "Extended OR listener";
|
||||||
default:
|
default:
|
||||||
log_warn(LD_BUG, "unknown connection type %d", type);
|
log_warn(LD_BUG, "unknown connection type %d", type);
|
||||||
tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
|
tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
|
||||||
@ -165,6 +168,12 @@ conn_state_to_string(int type, int state)
|
|||||||
case OR_CONN_STATE_OPEN: return "open";
|
case OR_CONN_STATE_OPEN: return "open";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
|
switch (state) {
|
||||||
|
case EXT_OR_CONN_STATE_OPEN: return "open";
|
||||||
|
case EXT_OR_CONN_STATE_FLUSHING: return "flushing final OKAY";
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case EXIT_CONN_STATE_RESOLVING: return "waiting for dest info";
|
case EXIT_CONN_STATE_RESOLVING: return "waiting for dest info";
|
||||||
@ -229,6 +238,7 @@ connection_type_uses_bufferevent(connection_t *conn)
|
|||||||
case CONN_TYPE_DIR:
|
case CONN_TYPE_DIR:
|
||||||
case CONN_TYPE_CONTROL:
|
case CONN_TYPE_CONTROL:
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
case CONN_TYPE_CPUWORKER:
|
case CONN_TYPE_CPUWORKER:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
@ -259,14 +269,18 @@ dir_connection_new(int socket_family)
|
|||||||
* Set active_circuit_pqueue_last_recalibrated to current cell_ewma tick.
|
* Set active_circuit_pqueue_last_recalibrated to current cell_ewma tick.
|
||||||
*/
|
*/
|
||||||
or_connection_t *
|
or_connection_t *
|
||||||
or_connection_new(int socket_family)
|
or_connection_new(int type, int socket_family)
|
||||||
{
|
{
|
||||||
or_connection_t *or_conn = tor_malloc_zero(sizeof(or_connection_t));
|
or_connection_t *or_conn = tor_malloc_zero(sizeof(or_connection_t));
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
connection_init(now, TO_CONN(or_conn), CONN_TYPE_OR, socket_family);
|
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
|
||||||
|
connection_init(now, TO_CONN(or_conn), type, socket_family);
|
||||||
|
|
||||||
or_conn->timestamp_last_added_nonpadding = time(NULL);
|
or_conn->timestamp_last_added_nonpadding = time(NULL);
|
||||||
|
|
||||||
|
if (type == CONN_TYPE_EXT_OR)
|
||||||
|
connection_or_set_ext_or_identifier(or_conn);
|
||||||
|
|
||||||
return or_conn;
|
return or_conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +349,8 @@ connection_new(int type, int socket_family)
|
|||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
return TO_CONN(or_connection_new(socket_family));
|
case CONN_TYPE_EXT_OR:
|
||||||
|
return TO_CONN(or_connection_new(type, socket_family));
|
||||||
|
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
return TO_CONN(edge_connection_new(type, socket_family));
|
return TO_CONN(edge_connection_new(type, socket_family));
|
||||||
@ -377,6 +392,7 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
conn->magic = OR_CONNECTION_MAGIC;
|
conn->magic = OR_CONNECTION_MAGIC;
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
@ -445,6 +461,7 @@ connection_free_(connection_t *conn)
|
|||||||
|
|
||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
|
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
|
||||||
mem = TO_OR_CONN(conn);
|
mem = TO_OR_CONN(conn);
|
||||||
memlen = sizeof(or_connection_t);
|
memlen = sizeof(or_connection_t);
|
||||||
@ -575,6 +592,9 @@ connection_free_(connection_t *conn)
|
|||||||
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
|
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
|
||||||
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
|
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
|
||||||
}
|
}
|
||||||
|
if (conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR)
|
||||||
|
connection_or_remove_from_ext_or_id_map(TO_OR_CONN(conn));
|
||||||
|
|
||||||
#ifdef USE_BUFFEREVENTS
|
#ifdef USE_BUFFEREVENTS
|
||||||
if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
|
if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
|
||||||
ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
|
ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
|
||||||
@ -638,6 +658,7 @@ connection_about_to_close_connection(connection_t *conn)
|
|||||||
connection_dir_about_to_close(TO_DIR_CONN(conn));
|
connection_dir_about_to_close(TO_DIR_CONN(conn));
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
connection_or_about_to_close(TO_OR_CONN(conn));
|
connection_or_about_to_close(TO_OR_CONN(conn));
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
@ -1374,6 +1395,9 @@ connection_init_accepted_conn(connection_t *conn,
|
|||||||
connection_start_reading(conn);
|
connection_start_reading(conn);
|
||||||
|
|
||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
|
conn->state = EXT_OR_CONN_STATE_OPEN;
|
||||||
|
break;
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
|
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
|
||||||
rv = connection_tls_start_handshake(TO_OR_CONN(conn), 1);
|
rv = connection_tls_start_handshake(TO_OR_CONN(conn), 1);
|
||||||
@ -2886,6 +2910,8 @@ connection_handle_read_impl(connection_t *conn)
|
|||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR_LISTENER:
|
case CONN_TYPE_OR_LISTENER:
|
||||||
return connection_handle_listener_read(conn, CONN_TYPE_OR);
|
return connection_handle_listener_read(conn, CONN_TYPE_OR);
|
||||||
|
case CONN_TYPE_EXT_OR_LISTENER:
|
||||||
|
return connection_handle_listener_read(conn, CONN_TYPE_EXT_OR);
|
||||||
case CONN_TYPE_AP_LISTENER:
|
case CONN_TYPE_AP_LISTENER:
|
||||||
case CONN_TYPE_AP_TRANS_LISTENER:
|
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||||
case CONN_TYPE_AP_NATD_LISTENER:
|
case CONN_TYPE_AP_NATD_LISTENER:
|
||||||
@ -3918,6 +3944,7 @@ int
|
|||||||
connection_is_listener(connection_t *conn)
|
connection_is_listener(connection_t *conn)
|
||||||
{
|
{
|
||||||
if (conn->type == CONN_TYPE_OR_LISTENER ||
|
if (conn->type == CONN_TYPE_OR_LISTENER ||
|
||||||
|
conn->type == CONN_TYPE_EXT_OR_LISTENER ||
|
||||||
conn->type == CONN_TYPE_AP_LISTENER ||
|
conn->type == CONN_TYPE_AP_LISTENER ||
|
||||||
conn->type == CONN_TYPE_AP_TRANS_LISTENER ||
|
conn->type == CONN_TYPE_AP_TRANS_LISTENER ||
|
||||||
conn->type == CONN_TYPE_AP_DNS_LISTENER ||
|
conn->type == CONN_TYPE_AP_DNS_LISTENER ||
|
||||||
@ -3940,6 +3967,7 @@ connection_state_is_open(connection_t *conn)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
|
if ((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
|
||||||
|
(conn->type == CONN_TYPE_EXT_OR) ||
|
||||||
(conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
|
(conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
|
||||||
(conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN) ||
|
(conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN) ||
|
||||||
(conn->type == CONN_TYPE_CONTROL &&
|
(conn->type == CONN_TYPE_CONTROL &&
|
||||||
@ -4109,6 +4137,8 @@ connection_process_inbuf(connection_t *conn, int package_partial)
|
|||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
return connection_or_process_inbuf(TO_OR_CONN(conn));
|
return connection_or_process_inbuf(TO_OR_CONN(conn));
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
|
return connection_ext_or_process_inbuf(TO_OR_CONN(conn));
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
return connection_edge_process_inbuf(TO_EDGE_CONN(conn),
|
return connection_edge_process_inbuf(TO_EDGE_CONN(conn),
|
||||||
@ -4169,6 +4199,8 @@ connection_finished_flushing(connection_t *conn)
|
|||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
return connection_or_finished_flushing(TO_OR_CONN(conn));
|
return connection_or_finished_flushing(TO_OR_CONN(conn));
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
|
return connection_ext_or_finished_flushing(TO_OR_CONN(conn));
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
return connection_edge_finished_flushing(TO_EDGE_CONN(conn));
|
return connection_edge_finished_flushing(TO_EDGE_CONN(conn));
|
||||||
@ -4224,6 +4256,7 @@ connection_reached_eof(connection_t *conn)
|
|||||||
{
|
{
|
||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
|
case CONN_TYPE_EXT_OR:
|
||||||
return connection_or_reached_eof(TO_OR_CONN(conn));
|
return connection_or_reached_eof(TO_OR_CONN(conn));
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
|
@ -19,7 +19,7 @@ const char *conn_type_to_string(int type);
|
|||||||
const char *conn_state_to_string(int type, int state);
|
const char *conn_state_to_string(int type, int state);
|
||||||
|
|
||||||
dir_connection_t *dir_connection_new(int socket_family);
|
dir_connection_t *dir_connection_new(int socket_family);
|
||||||
or_connection_t *or_connection_new(int socket_family);
|
or_connection_t *or_connection_new(int type, int socket_family);
|
||||||
edge_connection_t *edge_connection_new(int type, int socket_family);
|
edge_connection_t *edge_connection_new(int type, int socket_family);
|
||||||
entry_connection_t *entry_connection_new(int type, int socket_family);
|
entry_connection_t *entry_connection_new(int type, int socket_family);
|
||||||
control_connection_t *control_connection_new(int socket_family);
|
control_connection_t *control_connection_new(int socket_family);
|
||||||
|
@ -75,6 +75,9 @@ static void connection_or_handle_event_cb(struct bufferevent *bufev,
|
|||||||
* they form a linked list, with next_with_same_id as the next pointer. */
|
* they form a linked list, with next_with_same_id as the next pointer. */
|
||||||
static digestmap_t *orconn_identity_map = NULL;
|
static digestmap_t *orconn_identity_map = NULL;
|
||||||
|
|
||||||
|
/**DOCDOC */
|
||||||
|
static digestmap_t *orconn_ext_or_id_map = NULL;
|
||||||
|
|
||||||
/** If conn is listed in orconn_identity_map, remove it, and clear
|
/** If conn is listed in orconn_identity_map, remove it, and clear
|
||||||
* conn->identity_digest. Otherwise do nothing. */
|
* conn->identity_digest. Otherwise do nothing. */
|
||||||
void
|
void
|
||||||
@ -174,6 +177,52 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
connection_or_remove_from_ext_or_id_map(or_connection_t *conn)
|
||||||
|
{
|
||||||
|
or_connection_t *tmp;
|
||||||
|
if (!orconn_identity_map)
|
||||||
|
orconn_identity_map = digestmap_new();
|
||||||
|
|
||||||
|
tmp = digestmap_remove(orconn_ext_or_id_map, conn->ext_or_conn_id);
|
||||||
|
if (!tor_digest_is_zero(conn->ext_or_conn_id))
|
||||||
|
tor_assert(tmp == conn);
|
||||||
|
|
||||||
|
memset(conn->ext_or_conn_id, 0, EXT_OR_CONN_ID_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
void
|
||||||
|
connection_or_clear_ext_or_id_map(void)
|
||||||
|
{
|
||||||
|
digestmap_free(orconn_ext_or_id_map, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*DOCDOC
|
||||||
|
sets it to a random value */
|
||||||
|
void
|
||||||
|
connection_or_set_ext_or_identifier(or_connection_t *conn)
|
||||||
|
{
|
||||||
|
char random_id[EXT_OR_CONN_ID_LEN];
|
||||||
|
or_connection_t *tmp;
|
||||||
|
|
||||||
|
if (!orconn_ext_or_id_map)
|
||||||
|
orconn_ext_or_id_map = digestmap_new();
|
||||||
|
|
||||||
|
if (!tor_digest_is_zero(conn->ext_or_conn_id))
|
||||||
|
connection_or_remove_from_ext_or_id_map(conn);
|
||||||
|
|
||||||
|
do {
|
||||||
|
crypto_rand(random_id, sizeof(random_id));
|
||||||
|
} while (digestmap_get(orconn_ext_or_id_map, random_id));
|
||||||
|
|
||||||
|
memcpy(conn->ext_or_conn_id, random_id, EXT_OR_CONN_ID_LEN);
|
||||||
|
|
||||||
|
tmp = digestmap_set(orconn_ext_or_id_map, random_id, conn);
|
||||||
|
tor_assert(!tmp);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
/** Map from a string describing what a non-open OR connection was doing when
|
/** Map from a string describing what a non-open OR connection was doing when
|
||||||
@ -228,7 +277,7 @@ connection_or_get_state_description(or_connection_t *orconn,
|
|||||||
const char *conn_state;
|
const char *conn_state;
|
||||||
char tls_state[256];
|
char tls_state[256];
|
||||||
|
|
||||||
tor_assert(conn->type == CONN_TYPE_OR);
|
tor_assert(conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR);
|
||||||
|
|
||||||
conn_state = conn_state_to_string(conn->type, conn->state);
|
conn_state = conn_state_to_string(conn->type, conn->state);
|
||||||
tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state));
|
tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state));
|
||||||
@ -423,6 +472,23 @@ var_cell_free(var_cell_t *cell)
|
|||||||
tor_free(cell);
|
tor_free(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
ext_or_cmd_t *
|
||||||
|
ext_or_cmd_new(uint16_t len)
|
||||||
|
{
|
||||||
|
size_t size = STRUCT_OFFSET(ext_or_cmd_t, body) + len;
|
||||||
|
ext_or_cmd_t *cmd = tor_malloc(size);
|
||||||
|
cmd->len = len;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
void
|
||||||
|
ext_or_cmd_free(ext_or_cmd_t *cmd)
|
||||||
|
{
|
||||||
|
tor_free(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
/** We've received an EOF from <b>conn</b>. Mark it for close and return. */
|
/** We've received an EOF from <b>conn</b>. Mark it for close and return. */
|
||||||
int
|
int
|
||||||
connection_or_reached_eof(or_connection_t *conn)
|
connection_or_reached_eof(or_connection_t *conn)
|
||||||
@ -1077,7 +1143,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = or_connection_new(tor_addr_family(&addr));
|
conn = or_connection_new(CONN_TYPE_OR, tor_addr_family(&addr));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up conn so it's got all the data we need to remember for channels
|
* Set up conn so it's got all the data we need to remember for channels
|
||||||
@ -1470,7 +1536,8 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event,
|
|||||||
int
|
int
|
||||||
connection_or_nonopen_was_started_here(or_connection_t *conn)
|
connection_or_nonopen_was_started_here(or_connection_t *conn)
|
||||||
{
|
{
|
||||||
tor_assert(conn->base_.type == CONN_TYPE_OR);
|
tor_assert(conn->base_.type == CONN_TYPE_OR ||
|
||||||
|
conn->base_.type == CONN_TYPE_EXT_OR);
|
||||||
if (!conn->tls)
|
if (!conn->tls)
|
||||||
return 1; /* it's still in proxy states or something */
|
return 1; /* it's still in proxy states or something */
|
||||||
if (conn->handshake_state)
|
if (conn->handshake_state)
|
||||||
@ -2365,3 +2432,132 @@ connection_or_send_authenticate_cell(or_connection_t *conn, int authtype)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
static int
|
||||||
|
connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
|
||||||
|
{
|
||||||
|
IF_HAS_BUFFEREVENT(conn, {
|
||||||
|
struct evbuffer *input = bufferevent_get_input(conn->bufev);
|
||||||
|
return fetch_ext_or_command_from_evbuffer(input, out);
|
||||||
|
}) ELSE_IF_NO_BUFFEREVENT {
|
||||||
|
return fetch_ext_or_command_from_buf(conn->inbuf, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
static int
|
||||||
|
connection_write_ext_or_command(connection_t *conn,
|
||||||
|
uint16_t command,
|
||||||
|
const char *body,
|
||||||
|
size_t bodylen)
|
||||||
|
{
|
||||||
|
char header[4];
|
||||||
|
if (bodylen > UINT16_MAX)
|
||||||
|
return -1;
|
||||||
|
set_uint16(header, htons(command));
|
||||||
|
set_uint16(header+2, htons(bodylen));
|
||||||
|
connection_write_to_buf(header, 4, conn);
|
||||||
|
if (bodylen) {
|
||||||
|
tor_assert(body);
|
||||||
|
connection_write_to_buf(body, bodylen, conn);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
static void
|
||||||
|
connection_ext_or_transition(or_connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(conn->base_.type == CONN_TYPE_EXT_OR);
|
||||||
|
|
||||||
|
conn->base_.type = CONN_TYPE_OR;
|
||||||
|
control_event_or_conn_status(conn, OR_CONN_EVENT_NEW, 0);
|
||||||
|
connection_tls_start_handshake(conn, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*XXXX make these match the spec .*/
|
||||||
|
#define EXT_OR_CMD_DONE 0x0001
|
||||||
|
#define EXT_OR_CMD_USERADDR 0x0002
|
||||||
|
#define EXT_OR_CMD_WANT_CONTROL 0x0003
|
||||||
|
#define EXT_OR_CMD_OKAY 0x1001
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
int
|
||||||
|
connection_ext_or_process_inbuf(or_connection_t *or_conn)
|
||||||
|
{
|
||||||
|
connection_t *conn = TO_CONN(or_conn);
|
||||||
|
ext_or_cmd_t *command;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
command = NULL;
|
||||||
|
r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
|
||||||
|
if (r < 0)
|
||||||
|
return -1;
|
||||||
|
else if (r == 0)
|
||||||
|
return 0; /* need to wait for more data */
|
||||||
|
|
||||||
|
/* Got a command! */
|
||||||
|
tor_assert(command);
|
||||||
|
|
||||||
|
if (command->cmd == EXT_OR_CMD_DONE) {
|
||||||
|
if (connection_get_inbuf_len(conn)) {
|
||||||
|
/* The inbuf isn't empty; the client is misbehaving. */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
connection_write_ext_or_command(conn, EXT_OR_CMD_OKAY, NULL, 0);
|
||||||
|
|
||||||
|
/* can't transition immediately; need to flush first. */
|
||||||
|
conn->state = EXT_OR_CONN_STATE_FLUSHING;
|
||||||
|
connection_stop_reading(conn);
|
||||||
|
} else if (command->cmd == EXT_OR_CMD_USERADDR) {
|
||||||
|
/* Copy address string. */
|
||||||
|
tor_addr_t addr;
|
||||||
|
uint16_t port;
|
||||||
|
char *addr_str;
|
||||||
|
char *address_part=NULL;
|
||||||
|
int res;
|
||||||
|
addr_str = tor_malloc(command->len + 1);
|
||||||
|
memcpy(addr_str, command->body, command->len);
|
||||||
|
addr_str[command->len] = 0;
|
||||||
|
|
||||||
|
res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port);
|
||||||
|
tor_free(addr_str);
|
||||||
|
if (res<0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
res = tor_addr_parse(&addr, address_part);
|
||||||
|
tor_free(address_part);
|
||||||
|
if (res<0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* record the address */
|
||||||
|
tor_addr_copy(&conn->addr, &addr);
|
||||||
|
conn->port = port;
|
||||||
|
} else if (command->cmd == EXT_OR_CMD_WANT_CONTROL) {
|
||||||
|
char response[128];
|
||||||
|
char *cp;
|
||||||
|
memcpy(response, or_conn->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
|
||||||
|
cp = response+EXT_OR_CONN_ID_LEN;
|
||||||
|
/* XXXX write the TransportControlPort; advance cp. */
|
||||||
|
connection_write_ext_or_command(conn, EXT_OR_CMD_OKAY, response,
|
||||||
|
cp-response);
|
||||||
|
}
|
||||||
|
|
||||||
|
ext_or_cmd_free(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
ext_or_cmd_free(command);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
connection_ext_or_finished_flushing(or_connection_t *conn)
|
||||||
|
{
|
||||||
|
if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) {
|
||||||
|
connection_start_reading(TO_CONN(conn));
|
||||||
|
connection_ext_or_transition(conn);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -95,5 +95,14 @@ void var_cell_free(var_cell_t *cell);
|
|||||||
/** DOCDOC */
|
/** DOCDOC */
|
||||||
#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4
|
#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4
|
||||||
|
|
||||||
|
ext_or_cmd_t *ext_or_cmd_new(uint16_t len);
|
||||||
|
void ext_or_cmd_free(ext_or_cmd_t *cmd);
|
||||||
|
void connection_or_set_ext_or_identifier(or_connection_t *conn);
|
||||||
|
void connection_or_remove_from_ext_or_id_map(or_connection_t *conn);
|
||||||
|
void connection_or_clear_ext_or_id_map(void);
|
||||||
|
|
||||||
|
int connection_ext_or_finished_flushing(or_connection_t *conn);
|
||||||
|
int connection_ext_or_process_inbuf(or_connection_t *or_conn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
31
src/or/or.h
31
src/or/or.h
@ -228,8 +228,13 @@ typedef enum {
|
|||||||
#define CONN_TYPE_AP_NATD_LISTENER 14
|
#define CONN_TYPE_AP_NATD_LISTENER 14
|
||||||
/** Type for sockets listening for DNS requests. */
|
/** Type for sockets listening for DNS requests. */
|
||||||
#define CONN_TYPE_AP_DNS_LISTENER 15
|
#define CONN_TYPE_AP_DNS_LISTENER 15
|
||||||
#define CONN_TYPE_MAX_ 15
|
|
||||||
/* !!!! If CONN_TYPE_MAX_ is ever over 15, we must grow the type field in
|
/** DOCDOC */
|
||||||
|
#define CONN_TYPE_EXT_OR 16
|
||||||
|
#define CONN_TYPE_EXT_OR_LISTENER 17
|
||||||
|
|
||||||
|
#define CONN_TYPE_MAX_ 17
|
||||||
|
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
|
||||||
* connection_t. */
|
* connection_t. */
|
||||||
|
|
||||||
/* Proxy client types */
|
/* Proxy client types */
|
||||||
@ -309,6 +314,12 @@ typedef enum {
|
|||||||
#define OR_CONN_STATE_OPEN 8
|
#define OR_CONN_STATE_OPEN 8
|
||||||
#define OR_CONN_STATE_MAX_ 8
|
#define OR_CONN_STATE_MAX_ 8
|
||||||
|
|
||||||
|
/*DOCDOC*/
|
||||||
|
#define _EXT_OR_CONN_STATE_MIN 1
|
||||||
|
#define EXT_OR_CONN_STATE_OPEN 1
|
||||||
|
#define EXT_OR_CONN_STATE_FLUSHING 2
|
||||||
|
#define _EXT_OR_CONN_STATE_MAX 2
|
||||||
|
|
||||||
#define EXIT_CONN_STATE_MIN_ 1
|
#define EXIT_CONN_STATE_MIN_ 1
|
||||||
/** State for an exit connection: waiting for response from DNS farm. */
|
/** State for an exit connection: waiting for response from DNS farm. */
|
||||||
#define EXIT_CONN_STATE_RESOLVING 1
|
#define EXIT_CONN_STATE_RESOLVING 1
|
||||||
@ -1082,6 +1093,13 @@ typedef struct var_cell_t {
|
|||||||
uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
|
uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
|
||||||
} var_cell_t;
|
} var_cell_t;
|
||||||
|
|
||||||
|
/* DOCDOC */
|
||||||
|
typedef struct ext_or_cmd_t {
|
||||||
|
uint16_t cmd;
|
||||||
|
uint16_t len;
|
||||||
|
char body[FLEXIBLE_ARRAY_MEMBER];
|
||||||
|
} ext_or_cmd_t;
|
||||||
|
|
||||||
/** A cell as packed for writing to the network. */
|
/** A cell as packed for writing to the network. */
|
||||||
typedef struct packed_cell_t {
|
typedef struct packed_cell_t {
|
||||||
/** Next cell queued on this circuit. */
|
/** Next cell queued on this circuit. */
|
||||||
@ -1163,7 +1181,7 @@ typedef struct connection_t {
|
|||||||
* *_CONNECTION_MAGIC. */
|
* *_CONNECTION_MAGIC. */
|
||||||
|
|
||||||
uint8_t state; /**< Current state of this connection. */
|
uint8_t state; /**< Current state of this connection. */
|
||||||
unsigned int type:4; /**< What kind of connection is this? */
|
unsigned int type:5; /**< What kind of connection is this? */
|
||||||
unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
|
unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
|
||||||
|
|
||||||
/* The next fields are all one-bit booleans. Some are only applicable to
|
/* The next fields are all one-bit booleans. Some are only applicable to
|
||||||
@ -1405,6 +1423,9 @@ typedef struct or_handshake_state_t {
|
|||||||
/**@}*/
|
/**@}*/
|
||||||
} or_handshake_state_t;
|
} or_handshake_state_t;
|
||||||
|
|
||||||
|
/* DOCDOC */
|
||||||
|
#define EXT_OR_CONN_ID_LEN 20
|
||||||
|
|
||||||
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
||||||
* cells over TLS. */
|
* cells over TLS. */
|
||||||
typedef struct or_connection_t {
|
typedef struct or_connection_t {
|
||||||
@ -1413,6 +1434,8 @@ typedef struct or_connection_t {
|
|||||||
/** Hash of the public RSA key for the other side's identity key, or zeroes
|
/** Hash of the public RSA key for the other side's identity key, or zeroes
|
||||||
* if the other side hasn't shown us a valid identity key. */
|
* if the other side hasn't shown us a valid identity key. */
|
||||||
char identity_digest[DIGEST_LEN];
|
char identity_digest[DIGEST_LEN];
|
||||||
|
/*DOCDOC*/
|
||||||
|
char ext_or_conn_id[EXT_OR_CONN_ID_LEN];
|
||||||
char *nickname; /**< Nickname of OR on other side (if any). */
|
char *nickname; /**< Nickname of OR on other side (if any). */
|
||||||
|
|
||||||
tor_tls_t *tls; /**< TLS connection state. */
|
tor_tls_t *tls; /**< TLS connection state. */
|
||||||
@ -3428,6 +3451,8 @@ typedef struct {
|
|||||||
char *User; /**< Name of user to run Tor as. */
|
char *User; /**< Name of user to run Tor as. */
|
||||||
char *Group; /**< Name of group to run Tor as. */
|
char *Group; /**< Name of group to run Tor as. */
|
||||||
config_line_t *ORPort_lines; /**< Ports to listen on for OR connections. */
|
config_line_t *ORPort_lines; /**< Ports to listen on for OR connections. */
|
||||||
|
/** Ports to listen on for extended OR connections. */
|
||||||
|
config_line_t *ExtORPort_lines;
|
||||||
/** Ports to listen on for SOCKS connections. */
|
/** Ports to listen on for SOCKS connections. */
|
||||||
config_line_t *SocksPort_lines;
|
config_line_t *SocksPort_lines;
|
||||||
/** Ports to listen on for transparent pf/netfilter connections. */
|
/** Ports to listen on for transparent pf/netfilter connections. */
|
||||||
|
Loading…
Reference in New Issue
Block a user