diff options
-rw-r--r-- | doc/tor-spec.txt | 14 | ||||
-rw-r--r-- | src/or/connection.c | 65 | ||||
-rw-r--r-- | src/or/connection_edge.c | 18 | ||||
-rw-r--r-- | src/or/or.h | 8 |
4 files changed, 67 insertions, 38 deletions
diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt index 196349d4c3..58c4fdf2a4 100644 --- a/doc/tor-spec.txt +++ b/doc/tor-spec.txt @@ -281,12 +281,6 @@ which reveals the downstream node. The value of Version is currently 2. - The forward and backward ciphers fields can take the following values: - 0: Identity - 1: Single DES in OFB - 2: RC4 - 3: Triple DES (encrypt-decrypt-encrypt) in OFB - The port and address field denote the IPV4 address and port of the next onion router in the circuit, or are set to 0 for the last hop. @@ -316,7 +310,7 @@ which reveals the downstream node. D. Encrypt the first 128 bytes of M with the RSA key of OR_I, using no padding. Encrypt the remaining portion of - M with DES/OFB, using K1_I as a key and an all-0 IV. + M with 3DES/OFB, using K1_I as a key and an all-0 IV. 3. M is now the onion. @@ -365,7 +359,7 @@ which reveals the downstream node. in the past, then tear down the circuit (see section 4.2). Compute K1 through K3 as above. Use K1 to decrypt the rest - of the onion using DES/OFB. + of the onion using 3DES/OFB. If we are not the exit node, remove the first layer from the decrypted onion, and send the remainder to the next OR @@ -403,14 +397,14 @@ which reveals the downstream node. Otherwise, if the OR is not at the OP edge of the circuit (that is, either an 'exit node' or a non-edge node), it de/encrypts the length - field and the payload with DES/OFB, as follows: + field and the payload with 3DES/OFB, as follows: 'Forward' data cell (same direction as onion): Use K2 as key; encrypt. 'Back' data cell (opposite direction from onion): Use K3 as key; decrypt. Otherwise, if the data cell has arrived to the OP edge of the circuit, - the OP de/encrypts the length and payload fields with DES/OFB as + the OP de/encrypts the length and payload fields with 3DES/OFB as follows: OP sends data cell: For I=1...N, decrypt with K2_I. diff --git a/src/or/connection.c b/src/or/connection.c index c15eb00100..4ef246d838 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -543,7 +543,6 @@ void connection_send_cell(connection_t *conn) { */ conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */ connection_start_writing(conn); - } void connection_increment_send_timeval(connection_t *conn) { @@ -584,12 +583,7 @@ int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn) { char networkcell[CELL_NETWORK_SIZE]; char *n = networkcell; - memset(n,0,CELL_NETWORK_SIZE); /* zero it out to start */ - *(aci_t *)n = htons(cellp->aci); - *(n+2) = cellp->command; - *(n+3) = cellp->length; - /* seq is reserved, leave zero */ - memcpy(n+8,cellp->payload,CELL_PAYLOAD_SIZE); + cell_pack(n, cellp); if(connection_encrypt_cell(n,conn)<0) { return -1; @@ -676,7 +670,7 @@ repeat_connection_package_raw_inbuf: * compressing. * 2) */ - len = connection_compress_from_buf(cell.payload + TOPIC_HEADER_SIZE, + len = connection_compress_from_buf(cell.payload, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE, conn, Z_SYNC_FLUSH); if (len < 0) @@ -690,7 +684,7 @@ repeat_connection_package_raw_inbuf: cell.length = amount_to_process; } - if(connection_fetch_from_buf(cell.payload+TOPIC_HEADER_SIZE, cell.length, conn) < 0) + if(connection_fetch_from_buf(cell.payload, cell.length, conn) < 0) return -1; #endif @@ -702,10 +696,11 @@ repeat_connection_package_raw_inbuf: log(LOG_DEBUG,"connection_package_raw_inbuf(): (%d) Packaging %d bytes (%d waiting).",conn->s,cell.length, conn->inbuf_datalen); - *(uint16_t *)(cell.payload+2) = htons(conn->topic_id); - *cell.payload = TOPIC_COMMAND_DATA; - cell.length += TOPIC_HEADER_SIZE; + cell.command = CELL_DATA; + cell.topic_command = TOPIC_COMMAND_DATA; + cell.topic_id = conn->topic_id; + cell.length += TOPIC_HEADER_SIZE; if(conn->type == CONN_TYPE_EXIT) { cell.aci = circ->p_aci; @@ -756,10 +751,10 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { } memset(&cell, 0, sizeof(cell_t)); - *(uint16_t *)(cell.payload+2) = htons(conn->topic_id); - *cell.payload = TOPIC_COMMAND_SENDME; - cell.length += TOPIC_HEADER_SIZE; cell.command = CELL_DATA; + cell.topic_command = TOPIC_COMMAND_SENDME; + cell.topic_id = conn->topic_id; + cell.length += TOPIC_HEADER_SIZE; if(edge_type == EDGE_EXIT) { /* we're at an exit */ if(conn->p_receive_topicwindow < TOPICWINDOW_START - TOPICWINDOW_INCREMENT) { @@ -850,11 +845,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) { #endif /* retrieve cell info from outbuf (create the host-order struct from the network-order string) */ - memset(&cell,0,sizeof(cell_t)); /* zero it out to start */ - cell.aci = ntohs(*(aci_t *)outbuf); - cell.command = *(outbuf+2); - cell.length = *(outbuf+3); - memcpy(cell.payload, outbuf+8, CELL_PAYLOAD_SIZE); + cell_unpack(&cell, outbuf); // log(LOG_DEBUG,"connection_process_cell_from_inbuf(): Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci); command_process_cell(&cell, conn); @@ -862,6 +853,40 @@ int connection_process_cell_from_inbuf(connection_t *conn) { return connection_process_inbuf(conn); /* process the remainder of the buffer */ } +void +cell_pack(char *dest, const cell_t *src) +{ + *(uint16_t*)dest = htons(src->aci); + *(uint8_t*)(dest+2) = src->command; + *(uint8_t*)(dest+3) = src->length; + *(uint32_t*)(dest+4) = 0; /* Reserved */ + if (src->command != CELL_DATA) { + memcpy(dest+8, src->payload, CELL_PAYLOAD_SIZE); + } else { + *(uint8_t*)(dest+8) = src->topic_command; + *(uint8_t*)(dest+9) = 0; + *(uint16_t*)(dest+10) = htons(src->topic_id); + memcpy(dest+12, src->payload, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE); + } +} + +void +cell_unpack(cell_t *dest, const char *src) +{ + dest->aci = ntohs(*(uint16_t*)(src)); + dest->command = *(uint8_t*)(src+2); + dest->length = *(uint8_t*)(src+3); + dest->seq = ntohl(*(uint32_t*)(src+4)); + if (dest->command != CELL_DATA) { + memcpy(dest->payload, src+8, CELL_PAYLOAD_SIZE); + } else { + dest->topic_command = *(uint8_t*)(src+8); + /* zero = *(uint8_t*)(src+9); */ + dest->topic_id = ntohs(*(uint16_t*)(src+10)); + memcpy(dest->payload, src+12, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE); + } +} + /* Local Variables: mode:c diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 4f0a25b990..4a82d65a90 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -27,9 +27,10 @@ int connection_edge_process_inbuf(connection_t *conn) { memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_DATA; cell.length = TOPIC_HEADER_SIZE; - *(uint16_t *)(cell.payload+2) = htons(conn->topic_id); - *cell.payload = TOPIC_COMMAND_END; + cell.topic_command = TOPIC_COMMAND_END; + cell.topic_id = conn->topic_id; cell.aci = circ->n_aci; + if (circuit_deliver_data_cell_from_edge(&cell, circ, conn->type) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_data_cell_from_edge failed. Closing"); circuit_close(circ); @@ -75,8 +76,9 @@ int connection_edge_send_command(connection_t *conn, circuit_t *circ, int topic_ else cell.aci = circ->p_aci; cell.command = CELL_DATA; - *(uint16_t *)(cell.payload+2) = htons(conn->topic_id); - *cell.payload = topic_command; + cell.topic_command = topic_command; + cell.topic_id = conn->topic_id; + cell.length = TOPIC_HEADER_SIZE; log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", topic_command, conn->type == CONN_TYPE_AP ? "forward" : "backward"); @@ -98,8 +100,8 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty assert(cell && circ); - topic_command = *cell->payload; - topic_id = ntohs(*(uint16_t *)(cell->payload+2)); + topic_command = cell->topic_command; + topic_id = cell->topic_id; log(LOG_DEBUG,"connection_edge_process_data_cell(): command %d topic %d", topic_command, topic_id); num_seen++; log(LOG_DEBUG,"connection_edge_process_data_cell(): Now seen %d data cells here.", num_seen); @@ -151,7 +153,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty } #ifdef USE_ZLIB - if(connection_decompress_to_buf(cell->payload + TOPIC_HEADER_SIZE, + if(connection_decompress_to_buf(cell->payload, cell->length - TOPIC_HEADER_SIZE, conn, Z_SYNC_FLUSH) < 0) { log(LOG_INFO,"connection_edge_process_data_cell(): write to buf failed. Marking for close."); @@ -159,7 +161,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty return 0; } #else - if(connection_write_to_buf(cell->payload + TOPIC_HEADER_SIZE, + if(connection_write_to_buf(cell->payload, cell->length - TOPIC_HEADER_SIZE, conn) < 0) { conn->marked_for_close = 1; return 0; diff --git a/src/or/or.h b/src/or/or.h index 5e84ec3b83..1687cae38d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -197,6 +197,11 @@ typedef struct { unsigned char command; unsigned char length; /* of payload if data cell, else value of sendme */ uint32_t seq; /* sequence number */ + + /* The following 2 fields are only set when command is CELL_DATA */ + unsigned char topic_command; + uint16_t topic_id; + unsigned char payload[CELL_PAYLOAD_SIZE]; } cell_t; @@ -614,6 +619,9 @@ int connection_process_cell_from_inbuf(connection_t *conn); int connection_consider_sending_sendme(connection_t *conn, int edge_type); int connection_finished_flushing(connection_t *conn); +void cell_pack(char *dest, const cell_t *src); +void cell_unpack(cell_t *dest, const char *src); + /********************************* connection_ap.c ****************************/ int ap_handshake_process_socks(connection_t *conn); |