瀏覽代碼

Disable .exit notation unless AllowDotExit is 1.

Roger Dingledine 15 年之前
父節點
當前提交
3e4379c2e7
共有 5 個文件被更改,包括 32 次插入11 次删除
  1. 7 0
      doc/tor.1.in
  2. 1 0
      src/or/config.c
  3. 12 6
      src/or/connection_edge.c
  4. 8 1
      src/or/or.h
  5. 4 4
      src/or/test.c

+ 7 - 0
doc/tor.1.in

@@ -690,6 +690,13 @@ resolved.  This helps trap accidental attempts to resolve URLs and so on.
 (Default: 0)
 (Default: 0)
 .LP
 .LP
 .TP
 .TP
+\fBAllowDotOnion \fR\fB0\fR|\fB1\fR\fP
+If enabled, we convert "www.google.com.foo.exit" addresses on the
+SocksPort/TransPort/NatdPort into "www.google.com" addresses that exit
+from the node "foo". Disabled by default since attacking websites and
+exit relays can use it to manipulate your path selection. (Default: 0)
+.LP
+.TP
 \fBFastFirstHopPK \fR\fB0\fR|\fB1\fR\fP
 \fBFastFirstHopPK \fR\fB0\fR|\fB1\fR\fP
 When this option is disabled, Tor uses the public key step for the first
 When this option is disabled, Tor uses the public key step for the first
 hop of creating circuits. Skipping it is generally safe since we have
 hop of creating circuits. Skipping it is generally safe since we have

+ 1 - 0
src/or/config.c

@@ -134,6 +134,7 @@ static config_var_t _option_vars[] = {
   V(AccountingMax,               MEMUNIT,  "0 bytes"),
   V(AccountingMax,               MEMUNIT,  "0 bytes"),
   V(AccountingStart,             STRING,   NULL),
   V(AccountingStart,             STRING,   NULL),
   V(Address,                     STRING,   NULL),
   V(Address,                     STRING,   NULL),
+  V(AllowDotExit,                BOOL,     "0"),
   V(AllowInvalidNodes,           CSV,      "middle,rendezvous"),
   V(AllowInvalidNodes,           CSV,      "middle,rendezvous"),
   V(AllowNonRFC953Hostnames,     BOOL,     "0"),
   V(AllowNonRFC953Hostnames,     BOOL,     "0"),
   V(AllowSingleHopCircuits,      BOOL,     "0"),
   V(AllowSingleHopCircuits,      BOOL,     "0"),

+ 12 - 6
src/or/connection_edge.c

@@ -1483,7 +1483,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
   /* Parse the address provided by SOCKS.  Modify it in-place if it
   /* Parse the address provided by SOCKS.  Modify it in-place if it
    * specifies a hidden-service (.onion) or particular exit node (.exit).
    * specifies a hidden-service (.onion) or particular exit node (.exit).
    */
    */
-  addresstype = parse_extended_hostname(socks->address);
+  addresstype = parse_extended_hostname(socks->address,
+                         remapped_to_exit || options->AllowDotExit);
 
 
   if (addresstype == BAD_HOSTNAME) {
   if (addresstype == BAD_HOSTNAME) {
     log_warn(LD_APP, "Invalid onion hostname %s; rejecting",
     log_warn(LD_APP, "Invalid onion hostname %s; rejecting",
@@ -1496,7 +1497,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
 
 
   if (addresstype == EXIT_HOSTNAME) {
   if (addresstype == EXIT_HOSTNAME) {
     /* foo.exit -- modify conn->chosen_exit_node to specify the exit
     /* foo.exit -- modify conn->chosen_exit_node to specify the exit
-     * node, and conn->address to hold only the address portion.*/
+     * node, and conn->address to hold only the address portion. */
     char *s = strrchr(socks->address,'.');
     char *s = strrchr(socks->address,'.');
     tor_assert(!automap);
     tor_assert(!automap);
     if (s) {
     if (s) {
@@ -2902,14 +2903,14 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
 /** If address is of the form "y.onion" with a well-formed handle y:
 /** If address is of the form "y.onion" with a well-formed handle y:
  *     Put a NUL after y, lower-case it, and return ONION_HOSTNAME.
  *     Put a NUL after y, lower-case it, and return ONION_HOSTNAME.
  *
  *
- * If address is of the form "y.exit":
+ * If address is of the form "y.exit" and <b>allowdotexit</b> is true:
  *     Put a NUL after y and return EXIT_HOSTNAME.
  *     Put a NUL after y and return EXIT_HOSTNAME.
  *
  *
  * Otherwise:
  * Otherwise:
  *     Return NORMAL_HOSTNAME and change nothing.
  *     Return NORMAL_HOSTNAME and change nothing.
  */
  */
 hostname_type_t
 hostname_type_t
-parse_extended_hostname(char *address)
+parse_extended_hostname(char *address, int allowdotexit)
 {
 {
     char *s;
     char *s;
     char query[REND_SERVICE_ID_LEN_BASE32+1];
     char query[REND_SERVICE_ID_LEN_BASE32+1];
@@ -2918,8 +2919,13 @@ parse_extended_hostname(char *address)
     if (!s)
     if (!s)
       return NORMAL_HOSTNAME; /* no dot, thus normal */
       return NORMAL_HOSTNAME; /* no dot, thus normal */
     if (!strcmp(s+1,"exit")) {
     if (!strcmp(s+1,"exit")) {
-      *s = 0; /* NUL-terminate it */
+      if (allowdotexit) {
-      return EXIT_HOSTNAME; /* .exit */
+        *s = 0; /* NUL-terminate it */
+        return EXIT_HOSTNAME; /* .exit */
+      } /* else */
+      log_warn(LD_APP, "The \".exit\" notation is disabled in Tor due to "
+               "security risks. Set AllowDotExit in your torrc to enable it.");
+      /* FFFF send a controller event too to notify Vidalia users */
     }
     }
     if (strcmp(s+1,"onion"))
     if (strcmp(s+1,"onion"))
       return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
       return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */

+ 8 - 1
src/or/or.h

@@ -2508,6 +2508,13 @@ typedef struct {
    * exit allows it, we use it. */
    * exit allows it, we use it. */
   int AllowSingleHopCircuits;
   int AllowSingleHopCircuits;
 
 
+  /** If true, we convert "www.google.com.foo.exit" addresses on the
+   * socks/trans/natd ports into "www.google.com" addresses that
+   * exit from the node "foo". Disabled by default since attacking
+   * websites and exit relays can use it to manipulate your path
+   * selection. */
+  int AllowDotExit;
+
   /** If true, the user wants us to collect statistics on clients
   /** If true, the user wants us to collect statistics on clients
    * requesting network statuses from us as directory. */
    * requesting network statuses from us as directory. */
   int DirReqStatistics;
   int DirReqStatistics;
@@ -3133,7 +3140,7 @@ int hostname_is_noconnect_address(const char *address);
 typedef enum hostname_type_t {
 typedef enum hostname_type_t {
   NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME
   NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME
 } hostname_type_t;
 } hostname_type_t;
-hostname_type_t parse_extended_hostname(char *address);
+hostname_type_t parse_extended_hostname(char *address, int allowdotexit);
 
 
 #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
 #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
 int get_pf_socket(void);
 int get_pf_socket(void);

+ 4 - 4
src/or/test.c

@@ -4489,10 +4489,10 @@ test_rend_fns(void)
   char address3[] = "fooaddress.exit";
   char address3[] = "fooaddress.exit";
   char address4[] = "www.torproject.org";
   char address4[] = "www.torproject.org";
 
 
-  test_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
+  test_assert(BAD_HOSTNAME == parse_extended_hostname(address1, 1));
-  test_assert(ONION_HOSTNAME == parse_extended_hostname(address2));
+  test_assert(ONION_HOSTNAME == parse_extended_hostname(address2, 1));
-  test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
+  test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3, 1));
-  test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
+  test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4, 1));
 
 
   pk1 = pk_generate(0);
   pk1 = pk_generate(0);
   pk2 = pk_generate(1);
   pk2 = pk_generate(1);