+ o Major features:
+ - You can now configure Tor so that streams from different
+ applications are isolated on different circuits, to prevent an
+ attacker who sees your streams leaving an exit node from linking
+ your sessions to one another. To do this, choose some way to
+ distinguish the applications -- have them connect to different
+ SocksPorts, or have one of them use SOCKS4 while the other uses
+ SOCKS5, or have them pass different authentication strings to
+ the SOCKS proxy. Then use the new SocksPort syntax to configure
+ the degree of isolation you need. This implements Proposal 171.
+
o Minor features:
- There's a new syntax for specifying multiple client ports (such as
SOCKSPort, TransPort, DNSPort, NATDPort): you can now just declare
unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+int n_bits_set_u8(uint8_t v);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
* and positive <b>b</b>. Works on integer types only. Not defined if a+b can
return 0;
}
}
+
+ if (!connection_edge_compatible_with_circuit(conn, origin_circ)) {
+ /* conn needs to be isolated from other conns that have already used
+ * origin_circ */
+ return 0;
+ }
+
return 1;
}
/** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for
- * <b>purpose</b>, and return 0 otherwise. Used by circuit_get_best.
+ * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best.
*/
static int
circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
- uint8_t purpose)
+ const edge_connection_t *conn)
{
const circuit_t *a = TO_CIRCUIT(oa);
const circuit_t *b = TO_CIRCUIT(ob);
+ const uint8_t purpose = conn->_base.purpose;
+ int a_bits, b_bits;
switch (purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
return 1;
break;
}
+
+ /* XXXX023 Maybe this check should get a higher priority to avoid
+ * using up circuits too rapidly. */
+
+ a_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)oa, 1);
+ b_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)ob, 1);
+ /* if x_bits < 0, then we have not used x for anything; better not to dirty
+ * a connection if we can help it. */
+ if (a_bits < 0) {
+ return 0;
+ } else if (b_bits < 0) {
+ return 1;
+ }
+ a_bits &= ~ oa->isolation_flags_mixed;
+ a_bits &= ~ ob->isolation_flags_mixed;
+ if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) {
+ /* The fewer new restrictions we need to make on a circuit for stream
+ * isolation, the better. */
+ return 1;
+ }
+
return 0;
}
/* now this is an acceptable circ to hand back. but that doesn't
* mean it's the *best* circ to hand back. try to decide.
*/
- if (!best || circuit_is_better(origin_circ,best,purpose))
+ if (!best || circuit_is_better(origin_circ,best,conn))
best = origin_circ;
}
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
apconn->cpath_layer = circ->cpath->prev;
}
+
+ connection_edge_update_circuit_isolation(apconn, circ, 0);
}
/** Return true iff <b>address</b> is matched by one of the entries in