mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Add an ap_bridge function to do a socketpair and skip socks.
This allows us to do a directory connection *through* tor just as if we're doing it as an application. Make ap_conns tolerate it when the application sends stuff before The socks handshake is done (it just buffers it). Tell directory_initiate_command the length of the payload (because it might include nuls). Add a directory_has_arrived function to, for example, start building the rendezvous service descriptor. svn:r1412
This commit is contained in:
@@ -72,6 +72,9 @@ void relay_header_unpack(relay_header_t *dest, const char *src) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* mark and return -1 if there was an unexpected error with the conn,
|
||||
* else return 0.
|
||||
*/
|
||||
int connection_edge_process_inbuf(connection_t *conn) {
|
||||
|
||||
assert(conn);
|
||||
@@ -119,10 +122,14 @@ int connection_edge_process_inbuf(connection_t *conn) {
|
||||
}
|
||||
return 0;
|
||||
case EXIT_CONN_STATE_CONNECTING:
|
||||
log_fn(LOG_INFO,"text from server while in 'connecting' state at exit. Leaving it on buffer.");
|
||||
case AP_CONN_STATE_CIRCUIT_WAIT:
|
||||
case AP_CONN_STATE_CONNECT_WAIT:
|
||||
log_fn(LOG_INFO,"data from edge while in '%s' state. Leaving it on buffer.",
|
||||
conn_state_to_string[conn->type][conn->state]);
|
||||
return 0;
|
||||
}
|
||||
log_fn(LOG_WARN,"Got unexpected state %d. Closing.",conn->state);
|
||||
connection_mark_for_close(conn, END_STREAM_REASON_MISC);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -192,8 +199,9 @@ int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_lay
|
||||
return 0;
|
||||
}
|
||||
|
||||
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command,
|
||||
void *payload, int payload_len, crypt_path_t *cpath_layer) {
|
||||
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
int relay_command, void *payload,
|
||||
int payload_len, crypt_path_t *cpath_layer) {
|
||||
cell_t cell;
|
||||
relay_header_t rh;
|
||||
int cell_direction;
|
||||
@@ -207,7 +215,6 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re
|
||||
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
cell.command = CELL_RELAY;
|
||||
// if(fromconn && fromconn->type == CONN_TYPE_AP) {
|
||||
if(cpath_layer) {
|
||||
cell.circ_id = circ->n_circ_id;
|
||||
cell_direction = CELL_DIRECTION_OUT;
|
||||
@@ -238,8 +245,9 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re
|
||||
|
||||
/* an incoming relay cell has arrived. return -1 if you want to tear down the
|
||||
* circuit, else 0. */
|
||||
int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn,
|
||||
int edge_type, crypt_path_t *layer_hint) {
|
||||
int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn, int edge_type,
|
||||
crypt_path_t *layer_hint) {
|
||||
static int num_seen=0;
|
||||
uint32_t addr;
|
||||
relay_header_t rh;
|
||||
@@ -275,7 +283,6 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
|
||||
if (rh.length >= 4) {
|
||||
memcpy(&addr, cell->payload + RELAY_HEADER_SIZE, 4);
|
||||
addr = ntohl(addr);
|
||||
// addr = ntohl(*(uint32_t*)(cell->payload + RELAY_HEADER_SIZE));
|
||||
client_dns_set_entry(conn->socks_request->address, addr);
|
||||
}
|
||||
log_fn(LOG_INFO,"'connected' received after %d seconds.",
|
||||
@@ -283,6 +290,11 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
|
||||
circuit_log_path(LOG_INFO,circ);
|
||||
connection_ap_handshake_socks_reply(conn, NULL, 0, 1);
|
||||
conn->socks_request->has_finished = 1;
|
||||
/* handle anything that might have queued */
|
||||
if (connection_edge_package_raw_inbuf(conn) < 0) {
|
||||
connection_mark_for_close(conn, END_STREAM_REASON_MISC);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
log_fn(LOG_WARN,"Got an unexpected relay command %d, in state %d (%s). Closing.",
|
||||
@@ -353,7 +365,6 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
|
||||
*/
|
||||
memcpy(&addr, cell->payload+RELAY_HEADER_SIZE+1, 4);
|
||||
addr = ntohl(addr);
|
||||
// addr = ntohl(*(uint32_t*)(cell->payload+RELAY_HEADER_SIZE+1));
|
||||
client_dns_set_entry(conn->socks_request->address, addr);
|
||||
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
||||
if(connection_ap_handshake_attach_circuit(conn) >= 0)
|
||||
@@ -503,7 +514,7 @@ int connection_edge_finished_flushing(connection_t *conn) {
|
||||
connection_stop_writing(conn);
|
||||
return 0;
|
||||
default:
|
||||
log_fn(LOG_WARN,"BUG: called in unexpected state: %d", conn->state);
|
||||
log_fn(LOG_WARN,"BUG: called in unexpected state %d.", conn->state);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -849,6 +860,59 @@ static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t
|
||||
return;
|
||||
}
|
||||
|
||||
/* make an ap connection_t, do a socketpair and attach one side
|
||||
* to the conn, connection_add it, initialize it to circuit_wait,
|
||||
* and call connection_ap_handshake_attach_circuit(conn) on it.
|
||||
* Return the other end of the socketpair, or -1 if error.
|
||||
*/
|
||||
int connection_ap_make_bridge(char *address, uint16_t port) {
|
||||
int fd[2];
|
||||
connection_t *conn;
|
||||
|
||||
log_fn(LOG_INFO,"Making AP bridge to %s:%d ...",address,port);
|
||||
|
||||
if(tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
|
||||
log(LOG_ERR, "Couldn't construct socketpair: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_socket_nonblocking(fd[0]);
|
||||
set_socket_nonblocking(fd[1]);
|
||||
|
||||
conn = connection_new(CONN_TYPE_AP);
|
||||
conn->s = fd[0];
|
||||
|
||||
/* populate conn->socks_request */
|
||||
|
||||
/* leave version at zero, so the socks_reply is empty */
|
||||
conn->socks_request->socks_version = 0;
|
||||
conn->socks_request->has_finished = 0; /* waiting for 'connected' */
|
||||
strcpy(conn->socks_request->address, address);
|
||||
conn->socks_request->port = port;
|
||||
|
||||
conn->address = tor_strdup("(local bridge)");
|
||||
conn->addr = ntohs(0);
|
||||
conn->port = 0;
|
||||
|
||||
if(connection_add(conn) < 0) { /* no space, forget it */
|
||||
connection_free(conn); /* this closes fd[0] */
|
||||
close(fd[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
||||
connection_start_reading(conn);
|
||||
|
||||
if (connection_ap_handshake_attach_circuit(conn) < 0) {
|
||||
connection_mark_for_close(conn, 0);
|
||||
close(fd[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_fn(LOG_INFO,"... AP bridge created and connected.");
|
||||
return fd[1];
|
||||
}
|
||||
|
||||
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
|
||||
int replylen, char success) {
|
||||
char buf[256];
|
||||
@@ -877,7 +941,8 @@ void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
|
||||
The spec doesn't seem to say what to do here. -RD */
|
||||
connection_write_to_buf(buf,10,conn);
|
||||
}
|
||||
/* if socks_version isn't 4 or 5, don't send anything */
|
||||
/* If socks_version isn't 4 or 5, don't send anything.
|
||||
* This can happen in the case of AP bridges. */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+29
-24
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "or.h"
|
||||
|
||||
static void directory_send_command(connection_t *conn,
|
||||
int purpose, const char *payload);
|
||||
static void directory_send_command(connection_t *conn, int purpose,
|
||||
const char *payload, int payload_len);
|
||||
static int directory_handle_command(connection_t *conn);
|
||||
|
||||
/********* START VARIABLES **********/
|
||||
@@ -18,23 +18,18 @@ extern int has_fetched_directory;
|
||||
|
||||
/********* END VARIABLES ************/
|
||||
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload) {
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose,
|
||||
const char *payload, int payload_len) {
|
||||
connection_t *conn;
|
||||
|
||||
switch(purpose) {
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
log_fn(LOG_DEBUG,"initiating directory fetch");
|
||||
break;
|
||||
case DIR_PURPOSE_FETCH_HIDSERV:
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_DIR:
|
||||
log_fn(LOG_DEBUG,"initiating server descriptor upload");
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_HIDSERV:
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
|
||||
break;
|
||||
}
|
||||
if(purpose == DIR_PURPOSE_FETCH_DIR)
|
||||
log_fn(LOG_DEBUG,"initiating directory fetch");
|
||||
if(purpose == DIR_PURPOSE_FETCH_HIDSERV)
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
|
||||
if(purpose == DIR_PURPOSE_UPLOAD_DIR)
|
||||
log_fn(LOG_DEBUG,"initiating server descriptor upload");
|
||||
if(purpose == DIR_PURPOSE_UPLOAD_HIDSERV)
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
|
||||
|
||||
if (!router) { /* i guess they didn't have one in mind for me to use */
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
|
||||
@@ -59,7 +54,7 @@ void directory_initiate_command(routerinfo_t *router, int purpose, const char *p
|
||||
}
|
||||
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, purpose, payload);
|
||||
directory_send_command(conn, purpose, payload, payload_len);
|
||||
|
||||
if(purpose == DIR_PURPOSE_FETCH_DIR ||
|
||||
purpose == DIR_PURPOSE_UPLOAD_DIR) {
|
||||
@@ -86,14 +81,20 @@ void directory_initiate_command(routerinfo_t *router, int purpose, const char *p
|
||||
* populate it and add it at the right state
|
||||
* socketpair and hook up both sides
|
||||
*/
|
||||
conn->s = connection_ap_make_bridge(conn->address, conn->port);
|
||||
if(conn->s < 0) {
|
||||
log_fn(LOG_WARN,"Making AP bridge to dirserver failed.");
|
||||
connection_mark_for_close(conn, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING;
|
||||
connection_set_poll_socket(conn);
|
||||
}
|
||||
}
|
||||
|
||||
static void directory_send_command(connection_t *conn,
|
||||
int purpose, const char *payload) {
|
||||
static void directory_send_command(connection_t *conn, int purpose,
|
||||
const char *payload, int payload_len) {
|
||||
char fetchstring[] = "GET / HTTP/1.0\r\n\r\n";
|
||||
char tmp[8192];
|
||||
|
||||
@@ -107,7 +108,7 @@ static void directory_send_command(connection_t *conn,
|
||||
case DIR_PURPOSE_UPLOAD_DIR:
|
||||
assert(payload);
|
||||
snprintf(tmp, sizeof(tmp), "POST / HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
|
||||
(int)strlen(payload), payload);
|
||||
payload_len, payload);
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
break;
|
||||
case DIR_PURPOSE_FETCH_HIDSERV:
|
||||
@@ -118,9 +119,10 @@ static void directory_send_command(connection_t *conn,
|
||||
case DIR_PURPOSE_UPLOAD_HIDSERV:
|
||||
assert(payload);
|
||||
snprintf(tmp, sizeof(tmp),
|
||||
"POST /hidserv/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
|
||||
(int)strlen(payload), payload);
|
||||
"POST /hidserv/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n", payload_len);
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
/* could include nuls, need to write it separately */
|
||||
connection_write_to_buf(payload, payload_len, conn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +232,10 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
} else {
|
||||
log_fn(LOG_INFO,"updated routers.");
|
||||
}
|
||||
has_fetched_directory=1;
|
||||
if (has_fetched_directory==0) {
|
||||
has_fetched_directory=1;
|
||||
directory_has_arrived(); /* do things we've been waiting to do */
|
||||
}
|
||||
if(options.ORPort) { /* connect to them all */
|
||||
router_retry_connections();
|
||||
}
|
||||
|
||||
+17
-3
@@ -277,6 +277,15 @@ static void conn_close_if_marked(int i) {
|
||||
}
|
||||
}
|
||||
|
||||
void directory_has_arrived(void) {
|
||||
|
||||
log_fn(LOG_INFO, "We now have a directory.");
|
||||
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
DIR_PURPOSE_FETCH_HIDSERV, "foo", 3);
|
||||
|
||||
}
|
||||
|
||||
/* Perform regular maintenance tasks for a single connection. This
|
||||
* function gets run once per second per connection by run_housekeeping.
|
||||
*/
|
||||
@@ -329,7 +338,7 @@ static void run_scheduled_events(time_t now) {
|
||||
/* NOTE directory servers do not currently fetch directories.
|
||||
* Hope this doesn't bite us later. */
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
DIR_PURPOSE_FETCH_DIR, NULL);
|
||||
DIR_PURPOSE_FETCH_DIR, NULL, 0);
|
||||
} else {
|
||||
/* We're a directory; dump any old descriptors. */
|
||||
dirserv_remove_old_servers();
|
||||
@@ -362,7 +371,7 @@ static void run_scheduled_events(time_t now) {
|
||||
* that became dirty more than NewCircuitPeriod seconds ago,
|
||||
* and we make a new circ if there are no clean circuits.
|
||||
*/
|
||||
if((has_fetched_directory || options.DirPort) &&
|
||||
if(has_fetched_directory &&
|
||||
(options.SocksPort || options.RunTesting)) {
|
||||
|
||||
if (options.SocksPort)
|
||||
@@ -521,7 +530,7 @@ static int do_hup(void) {
|
||||
} else {
|
||||
/* fetch a new directory */
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
DIR_PURPOSE_FETCH_DIR, NULL);
|
||||
DIR_PURPOSE_FETCH_DIR, NULL, 0);
|
||||
}
|
||||
if(options.ORPort) {
|
||||
router_rebuild_descriptor();
|
||||
@@ -558,6 +567,11 @@ static int do_main_loop(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(options.DirPort) { /* the directory is already here, run startup things */
|
||||
has_fetched_directory = 1;
|
||||
directory_has_arrived();
|
||||
}
|
||||
|
||||
if(options.ORPort) {
|
||||
cpu_init(); /* launch cpuworkers. Need to do this *after* we've read the onion key. */
|
||||
router_upload_desc_to_dirservers(); /* upload our descriptor to all dirservers */
|
||||
|
||||
+12
-7
@@ -793,16 +793,18 @@ void relay_header_unpack(relay_header_t *dest, const char *src);
|
||||
int connection_edge_process_inbuf(connection_t *conn);
|
||||
int connection_edge_destroy(uint16_t circ_id, connection_t *conn);
|
||||
int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer);
|
||||
|
||||
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command,
|
||||
void *payload, int payload_len, crypt_path_t *cpath_layer);
|
||||
|
||||
int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn,
|
||||
int edge_type, crypt_path_t *layer_hint);
|
||||
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
int relay_command, void *payload,
|
||||
int payload_len, crypt_path_t *cpath_layer);
|
||||
int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn, int edge_type,
|
||||
crypt_path_t *layer_hint);
|
||||
int connection_edge_finished_flushing(connection_t *conn);
|
||||
|
||||
int connection_edge_package_raw_inbuf(connection_t *conn);
|
||||
|
||||
int connection_ap_make_bridge(char *address, uint16_t port);
|
||||
|
||||
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
|
||||
int replylen, char success);
|
||||
|
||||
@@ -843,7 +845,8 @@ int assign_to_cpuworker(connection_t *cpuworker, unsigned char question_type,
|
||||
|
||||
/********************************* directory.c ***************************/
|
||||
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload);
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose,
|
||||
const char *payload, int payload_len);
|
||||
int connection_dir_process_inbuf(connection_t *conn);
|
||||
int connection_dir_finished_flushing(connection_t *conn);
|
||||
|
||||
@@ -874,6 +877,8 @@ int connection_is_writing(connection_t *conn);
|
||||
void connection_stop_writing(connection_t *conn);
|
||||
void connection_start_writing(connection_t *conn);
|
||||
|
||||
void directory_has_arrived(void);
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
/********************************* onion.c ***************************/
|
||||
|
||||
@@ -255,7 +255,7 @@ void router_upload_desc_to_dirservers(void) {
|
||||
for(i=0;i<rl->n_routers;i++) {
|
||||
router = rl->routers[i];
|
||||
if(router->dir_port > 0)
|
||||
directory_initiate_command(router, DIR_PURPOSE_UPLOAD_DIR, s);
|
||||
directory_initiate_command(router, DIR_PURPOSE_UPLOAD_DIR, s, strlen(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user