mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
r16282@catbus: nickm | 2007-10-30 14:28:58 -0400
Implement lots of proposal 105. None of it is enabled yet. svn:r12285
This commit is contained in:
parent
c0c2001a5b
commit
57f7c852f8
17
doc/TODO
17
doc/TODO
@ -42,16 +42,21 @@ Things we'd like to do in 0.2.0.x:
|
||||
- 105+TLS, if possible.
|
||||
- 105 only
|
||||
- Need to get a finished proposal 105
|
||||
- "Pick a version" function
|
||||
o "Pick a version" function
|
||||
- Have a 'waiting_for_version' state.
|
||||
- Store version in or_connection_t.
|
||||
- Generate netinfo cells
|
||||
- Accept netinfo cells
|
||||
o Store version in or_connection_t.
|
||||
o Generate netinfo cells
|
||||
o Accept netinfo cells
|
||||
. Add an is_canonical field to or_connection_t.
|
||||
o Set it when we get a match in the netinfo.
|
||||
o Set it when we get a match for a routerinfo we have.
|
||||
- Don't extend a circuit over a noncanonical connection with
|
||||
mismatched address.
|
||||
- Version negotiation: send a version cell and enter
|
||||
waiting-for-version; when version cell arrives, pick version
|
||||
and send netinfo and be "open".
|
||||
- On netinfo, warn if there's skew from a server.
|
||||
- Handle IP addresses in netinfo properly.
|
||||
o On netinfo, warn if there's skew from a server.
|
||||
- Learn our outgoing IP address from netinfo cells?
|
||||
- TLS only
|
||||
- Need to get a finished TLS normalization proposal
|
||||
- Revised authentication.
|
||||
|
@ -4,7 +4,7 @@ Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Nick Mathewson, Roger Dingledine
|
||||
Created:
|
||||
Status: Open
|
||||
Status: Accepted
|
||||
|
||||
Overview:
|
||||
|
||||
@ -120,7 +120,7 @@ Proposal:
|
||||
When a Tor connection is established, both parties normally send a
|
||||
VERSIONS cell before sending any other cells. (But see below.)
|
||||
|
||||
VersionsLen [1 byte]
|
||||
VersionsLen [2 byte]
|
||||
Versions [VersionsLen bytes]
|
||||
|
||||
"Versions" is a sequence of VersionsLen bytes. Each value between 1 and
|
||||
@ -157,6 +157,8 @@ Proposal:
|
||||
The VERSIONS cell must be sent as a v1 cell (2 bytes of circuitID, 1
|
||||
byte of command, 509 bytes of payload).
|
||||
|
||||
[NOTE: The VERSIONS cell is assigned the command number 7.]
|
||||
|
||||
2.2. MITM-prevention and time checking
|
||||
|
||||
If we negotiate a v2 connection or higher, the second cell we send SHOULD
|
||||
@ -195,6 +197,7 @@ Proposal:
|
||||
given in the EXTEND cell is not listed in the NETINFO cell, the first
|
||||
party SHOULD close the connection as a likely MITM attack.
|
||||
|
||||
[NOTE: The NETINFO cell is assigned the command number 8.]
|
||||
|
||||
Discussion: Versions versus feature lists
|
||||
|
||||
|
165
src/or/command.c
165
src/or/command.c
@ -25,12 +25,16 @@ uint64_t stats_n_create_cells_processed = 0;
|
||||
uint64_t stats_n_created_cells_processed = 0;
|
||||
uint64_t stats_n_relay_cells_processed = 0;
|
||||
uint64_t stats_n_destroy_cells_processed = 0;
|
||||
uint64_t stats_n_versions_cells_processed = 0;
|
||||
uint64_t stats_n_netinfo_cells_processed = 0;
|
||||
|
||||
/* These are the main four functions for processing cells */
|
||||
/* These are the main functions for processing cells */
|
||||
static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
|
||||
static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
|
||||
static void command_process_relay_cell(cell_t *cell, or_connection_t *conn);
|
||||
static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
|
||||
static void command_process_versions_cell(cell_t *cell, or_connection_t *conn);
|
||||
static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn);
|
||||
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
/** This is a wrapper function around the actual function that processes the
|
||||
@ -99,6 +103,16 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN { \
|
||||
++num ## tp; \
|
||||
command_time_process_cell(cl, cn, & tp ## time , \
|
||||
command_process_ ## tp ## _cell); \
|
||||
} STMT_END
|
||||
#else
|
||||
#define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn)
|
||||
#endif
|
||||
|
||||
switch (cell->command) {
|
||||
case CELL_PADDING:
|
||||
++stats_n_padding_cells_processed;
|
||||
@ -107,47 +121,31 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
|
||||
case CELL_CREATE:
|
||||
case CELL_CREATE_FAST:
|
||||
++stats_n_create_cells_processed;
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
++num_create;
|
||||
command_time_process_cell(cell, conn, &create_time,
|
||||
command_process_create_cell);
|
||||
#else
|
||||
command_process_create_cell(cell, conn);
|
||||
#endif
|
||||
PROCESS_CELL(create, cell, conn);
|
||||
break;
|
||||
case CELL_CREATED:
|
||||
case CELL_CREATED_FAST:
|
||||
++stats_n_created_cells_processed;
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
++num_created;
|
||||
command_time_process_cell(cell, conn, &created_time,
|
||||
command_process_created_cell);
|
||||
#else
|
||||
command_process_created_cell(cell, conn);
|
||||
#endif
|
||||
PROCESS_CELL(created, cell, conn);
|
||||
break;
|
||||
case CELL_RELAY:
|
||||
++stats_n_relay_cells_processed;
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
++num_relay;
|
||||
command_time_process_cell(cell, conn, &relay_time,
|
||||
command_process_relay_cell);
|
||||
#else
|
||||
command_process_relay_cell(cell, conn);
|
||||
#endif
|
||||
PROCESS_CELL(relay, cell, conn);
|
||||
break;
|
||||
case CELL_DESTROY:
|
||||
++stats_n_destroy_cells_processed;
|
||||
#ifdef KEEP_TIMING_STATS
|
||||
++num_destroy;
|
||||
command_time_process_cell(cell, conn, &destroy_time,
|
||||
command_process_destroy_cell);
|
||||
#else
|
||||
command_process_destroy_cell(cell, conn);
|
||||
#endif
|
||||
PROCESS_CELL(destroy, cell, conn);
|
||||
break;
|
||||
case CELL_VERSIONS:
|
||||
++stats_n_versions_cells_processed;
|
||||
PROCESS_CELL(versions, cell, conn);
|
||||
break;
|
||||
case CELL_NETINFO:
|
||||
++stats_n_netinfo_cells_processed;
|
||||
PROCESS_CELL(netinfo, cell, conn);
|
||||
break;
|
||||
default:
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
log_fn(LOG_INFO, LD_PROTOCOL,
|
||||
"Cell of unknown type (%d) received. Dropping.", cell->command);
|
||||
break;
|
||||
}
|
||||
@ -389,3 +387,110 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a 'versions' cell. The current link protocol version must be 0
|
||||
* to indicate that no version has yet been negotiated. DOCDOC say more. */
|
||||
static void
|
||||
command_process_versions_cell(cell_t *cell, or_connection_t *conn)
|
||||
{
|
||||
uint16_t versionslen;
|
||||
int highest_supported_version = 0;
|
||||
const char *cp, *end;
|
||||
if (conn->link_proto != 0) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
||||
"Received a VERSIONS cell on a connection with its version "
|
||||
"already set to %d; dropping", (int) conn->link_proto);
|
||||
return;
|
||||
}
|
||||
versionslen = ntohs(get_uint16(cell->payload));
|
||||
end = cell->payload + 2 + versionslen;
|
||||
if (end > cell->payload + CELL_PAYLOAD_SIZE)
|
||||
end = cell->payload + CELL_PAYLOAD_SIZE; /*XXXX020 warn?*/
|
||||
for (cp = cell->payload + 2; cp < end; ++cp) {
|
||||
uint8_t v = *cp;
|
||||
if (v == 1) {
|
||||
if (v > highest_supported_version)
|
||||
highest_supported_version = v;
|
||||
}
|
||||
}
|
||||
if (!versionslen) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
||||
"Couldn't find a version in common; defaulting to v1.");
|
||||
/*XXXX020 or just break the connection?*/
|
||||
conn->link_proto = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a 'netinfo' cell. DOCDOC say more. */
|
||||
static void
|
||||
command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
|
||||
{
|
||||
time_t timestamp;
|
||||
uint8_t my_addr_type;
|
||||
uint8_t my_addr_len;
|
||||
const char *my_addr_ptr;
|
||||
const char *cp, *end;
|
||||
uint8_t n_other_addrs;
|
||||
time_t now = time(NULL);
|
||||
|
||||
/*XXXX020 reject duplicat netinfos. */
|
||||
|
||||
if (conn->link_proto < 2) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
||||
"Received a NETINFO cell on %s connection; dropping.",
|
||||
conn->link_proto == 0 ? "non-versioned" : "a v1");
|
||||
return;
|
||||
}
|
||||
/* Decode the cell. */
|
||||
timestamp = ntohl(get_uint32(cell->payload));
|
||||
my_addr_type = (uint8_t) cell->payload[4];
|
||||
my_addr_len = (uint8_t) cell->payload[5];
|
||||
my_addr_ptr = cell->payload + 6;
|
||||
/* Possibly learn my address. XXXX020 */
|
||||
end = cell->payload + CELL_PAYLOAD_SIZE;
|
||||
cp = cell->payload + 6 + my_addr_len;
|
||||
if (cp >= end) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
||||
"Address too long in netinfo cell; dropping.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*XXXX020 magic number 3600 */
|
||||
if (abs(timestamp - now) > 3600 &&
|
||||
router_get_by_digest(conn->identity_digest)) {
|
||||
long delta = now - timestamp;
|
||||
char dbuf[64];
|
||||
/*XXXX020 not always warn!*/
|
||||
format_time_interval(dbuf, sizeof(dbuf), delta);
|
||||
log_fn(LOG_WARN, LD_HTTP, "Received NETINFO cell with skewed time from "
|
||||
"server at %s:%d. It seems that our clock is %s by %s, or "
|
||||
"that theirs is %s. Tor requires an accurate clock to work: "
|
||||
"please check your time and date settings.",
|
||||
conn->_base.address, (int)conn->_base.port,
|
||||
delta>0 ? "ahead" : "behind", dbuf,
|
||||
delta>0 ? "behind" : "ahead");
|
||||
control_event_general_status(LOG_WARN,
|
||||
"CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d",
|
||||
delta, conn->_base.address, conn->_base.port);
|
||||
}
|
||||
|
||||
n_other_addrs = (uint8_t) *cp++;
|
||||
while (n_other_addrs && cp < end-2) {
|
||||
/* Consider all the other addresses; if any matches, this connection is
|
||||
* "canonical." */
|
||||
uint8_t other_addr_type = (uint8_t) *cp++;
|
||||
uint8_t other_addr_len = (uint8_t) *cp++;
|
||||
if (cp + other_addr_len >= end)
|
||||
break; /*XXXX020 protocol warn. */
|
||||
if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) {
|
||||
uint32_t addr = ntohl(get_uint32(cp));
|
||||
if (addr == conn->real_addr) {
|
||||
conn->is_canonical = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cp += other_addr_len;
|
||||
--n_other_addrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,11 +356,16 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
connection_or_set_identity_digest(conn, id_digest);
|
||||
conn->_base.addr = addr;
|
||||
conn->_base.port = port;
|
||||
conn->real_addr = addr;
|
||||
if (r) {
|
||||
if (conn->_base.addr == r->addr)
|
||||
conn->is_canonical = 1;
|
||||
if (!started_here) {
|
||||
/* Override the addr/port, so our log messages will make sense.
|
||||
* This is dangerous, since if we ever try looking up a conn by
|
||||
* its actual addr/port, we won't remember. Careful! */
|
||||
/* XXXX020 this is stupid, and it's the reason we need real_addr to
|
||||
* track is_canonical properly. */
|
||||
conn->_base.addr = r->addr;
|
||||
conn->_base.port = r->or_port;
|
||||
}
|
||||
@ -740,6 +745,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
|
||||
}
|
||||
connection_watch_events(TO_CONN(conn), EV_READ);
|
||||
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
|
||||
|
||||
conn->link_proto = 1; /* Version negotiation not yet enabled.XXX020 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -773,7 +780,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
|
||||
char buf[CELL_NETWORK_SIZE];
|
||||
cell_t cell;
|
||||
|
||||
loop:
|
||||
loop:
|
||||
log_debug(LD_OR,
|
||||
"%d: starting, inbuf_datalen %d (%d pending in tls object).",
|
||||
conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
|
||||
@ -825,3 +832,56 @@ connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static int
|
||||
connection_or_send_versions(or_connection_t *conn)
|
||||
{
|
||||
cell_t cell;
|
||||
uint8_t versions[] = { 1 };
|
||||
int n_versions = sizeof(versions) / sizeof(uint8_t);
|
||||
int i;
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
cell.command = CELL_VERSIONS;
|
||||
set_uint16(cell.payload, htons(n_versions));
|
||||
for (i = 0; i < n_versions; ++i) {
|
||||
uint8_t v = versions[i];
|
||||
tor_assert(v > 0 && v < 128);
|
||||
cell.payload[2+i] = v;
|
||||
}
|
||||
|
||||
connection_or_write_cell_to_buf(&cell, conn);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static int
|
||||
connection_or_send_netinfo(or_connection_t *conn)
|
||||
{
|
||||
cell_t cell;
|
||||
time_t now = time(NULL);
|
||||
routerinfo_t *me;
|
||||
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
cell.command = CELL_NETINFO;
|
||||
|
||||
/* Their address. */
|
||||
set_uint32(cell.payload, htonl(now));
|
||||
cell.payload[4] = RESOLVED_TYPE_IPV4;
|
||||
cell.payload[5] = 4;
|
||||
set_uint32(cell.payload+6, htonl(conn->_base.addr));
|
||||
|
||||
/* My address. */
|
||||
if ((me = router_get_my_routerinfo())) {
|
||||
cell.payload[10] = 1; /* only one address is supported. */
|
||||
cell.payload[11] = RESOLVED_TYPE_IPV4;
|
||||
cell.payload[12] = 4;
|
||||
set_uint32(cell.payload+13, htonl(me->addr));
|
||||
} else {
|
||||
cell.payload[10] = 0;
|
||||
}
|
||||
|
||||
connection_or_write_cell_to_buf(&cell, conn);
|
||||
|
||||
/*XXXX020 remove these once we send netinfo and versions cells. */
|
||||
(void) connection_or_send_netinfo;
|
||||
(void) connection_or_send_versions;
|
||||
}
|
||||
|
@ -651,6 +651,8 @@ typedef enum {
|
||||
#define CELL_DESTROY 4
|
||||
#define CELL_CREATE_FAST 5
|
||||
#define CELL_CREATED_FAST 6
|
||||
#define CELL_VERSIONS 7
|
||||
#define CELL_NETINFO 8
|
||||
|
||||
/** How long to test reachability before complaining to the user. */
|
||||
#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
|
||||
@ -868,9 +870,14 @@ typedef struct or_connection_t {
|
||||
* recent, we can rate limit it further. */
|
||||
time_t client_used;
|
||||
|
||||
uint32_t real_addr; /**DOCDOC */
|
||||
|
||||
circ_id_type_t circ_id_type:2; /**< When we send CREATE cells along this
|
||||
* connection, which half of the space should
|
||||
* we use? */
|
||||
unsigned int is_canonical; /**< DOCDOC */
|
||||
uint8_t link_proto; /**< What protocol version are we using? 0 for
|
||||
* "none negotiated yet." */
|
||||
uint16_t next_circ_id; /**< Which circ_id do we try to use next on
|
||||
* this connection? This is always in the
|
||||
* range 0..1<<15-1. */
|
||||
|
@ -1570,6 +1570,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
result = tor_snprintf(s, maxlen,
|
||||
"router %s %s %d 0 %d\n"
|
||||
"platform %s\n"
|
||||
"opt protocols Link 1 Circuit 1\n"
|
||||
"published %s\n"
|
||||
"opt fingerprint %s\n"
|
||||
"uptime %ld\n"
|
||||
|
Loading…
Reference in New Issue
Block a user