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.
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.
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
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.
*/
conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */
connection_start_writing(conn);
-
}
void connection_increment_send_timeval(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;
* 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)
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
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;
}
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) {
#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);
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
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);
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");
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);
}
#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.");
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;
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;
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);