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:
Nick Mathewson 2007-10-30 18:31:30 +00:00
parent c0c2001a5b
commit 57f7c852f8
6 changed files with 220 additions and 39 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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. */

View File

@ -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"