Browse Source

Allow non-printable characters for exit streams (both for
connecting and for resolving). Now we tolerate applications
that don't follow the RFCs. But continue to block malformed
names at the socks side.


svn:r6193

Roger Dingledine 19 years ago
parent
commit
d1d0813cf3
5 changed files with 57 additions and 52 deletions
  1. 6 6
      src/or/connection.c
  2. 5 3
      src/or/connection_edge.c
  3. 39 37
      src/or/dns.c
  4. 6 5
      src/or/main.c
  5. 1 1
      src/or/routerparse.c

+ 6 - 6
src/or/connection.c

@@ -774,7 +774,7 @@ connection_connect(connection_t *conn, char *address,
   } else if (!SOCKET_IS_POLLABLE(s)) {
   } else if (!SOCKET_IS_POLLABLE(s)) {
     log_warn(LD_NET,
     log_warn(LD_NET,
             "Too many connections; can't create pollable connection to %s",
             "Too many connections; can't create pollable connection to %s",
-             safe_str(address));
+             escaped_safe_str(address));
     tor_close_socket(s);
     tor_close_socket(s);
     return -1;
     return -1;
   }
   }
@@ -804,15 +804,15 @@ connection_connect(connection_t *conn, char *address,
   dest_addr.sin_port = htons(port);
   dest_addr.sin_port = htons(port);
   dest_addr.sin_addr.s_addr = htonl(addr);
   dest_addr.sin_addr.s_addr = htonl(addr);
 
 
-  log_debug(LD_NET,"Connecting to %s:%u.",safe_str(address),port);
+  log_debug(LD_NET,"Connecting to %s:%u.",escaped_safe_str(address),port);
 
 
   if (connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
   if (connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
     int e = tor_socket_errno(s);
     int e = tor_socket_errno(s);
     if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
     if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
       /* yuck. kill it. */
       /* yuck. kill it. */
       log_info(LD_NET,
       log_info(LD_NET,
-               "connect() to %s:%u failed: %s",safe_str(address),port,
-               tor_socket_strerror(e));
+               "connect() to %s:%u failed: %s",escaped_safe_str(address),
+               port, tor_socket_strerror(e));
       tor_close_socket(s);
       tor_close_socket(s);
       return -1;
       return -1;
     } else {
     } else {
@@ -825,8 +825,8 @@ connection_connect(connection_t *conn, char *address,
 
 
   /* it succeeded. we're connected. */
   /* it succeeded. we're connected. */
   log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET,
   log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET,
-         "Connection to %s:%u %s (sock %d).",safe_str(address),port,
-         inprogress?"in progress":"established",s);
+         "Connection to %s:%u %s (sock %d).",escaped_safe_str(address),
+         port, inprogress?"in progress":"established", s);
   conn->s = s;
   conn->s = s;
   if (connection_add(conn) < 0) /* no space, forget it */
   if (connection_add(conn) < 0) /* no space, forget it */
     return -1;
     return -1;

+ 5 - 3
src/or/connection_edge.c

@@ -281,7 +281,7 @@ connection_edge_finished_connecting(connection_t *conn)
   in.s_addr = htonl(conn->addr);
   in.s_addr = htonl(conn->addr);
   tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
   tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
   log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
   log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
-           safe_str(conn->address),conn->port,safe_str(valbuf));
+           escaped_safe_str(conn->address),conn->port,safe_str(valbuf));
 
 
   conn->state = EXIT_CONN_STATE_OPEN;
   conn->state = EXIT_CONN_STATE_OPEN;
   connection_watch_events(conn, EV_READ); /* stop writing, continue reading */
   connection_watch_events(conn, EV_READ); /* stop writing, continue reading */
@@ -1533,6 +1533,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
     tor_free(address);
     tor_free(address);
     return 0;
     return 0;
   }
   }
+#if 0
   if (!tor_strisprint(address)) {
   if (!tor_strisprint(address)) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Non-printing characters in address %s in relay "
            "Non-printing characters in address %s in relay "
@@ -1540,6 +1541,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
     tor_free(address);
     tor_free(address);
     return 0;
     return 0;
   }
   }
+#endif
 
 
   log_debug(LD_EXIT,"Creating new exit connection.");
   log_debug(LD_EXIT,"Creating new exit connection.");
   n_stream = connection_new(CONN_TYPE_EXIT);
   n_stream = connection_new(CONN_TYPE_EXIT);
@@ -1685,7 +1687,7 @@ connection_exit_connect(connection_t *conn)
   if (!connection_edge_is_rendezvous_stream(conn) &&
   if (!connection_edge_is_rendezvous_stream(conn) &&
       router_compare_to_my_exit_policy(conn)) {
       router_compare_to_my_exit_policy(conn)) {
     log_info(LD_EXIT,"%s:%d failed exit policy. Closing.",
     log_info(LD_EXIT,"%s:%d failed exit policy. Closing.",
-             safe_str(conn->address), conn->port);
+             escaped_safe_str(conn->address), conn->port);
     connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, conn->cpath_layer);
     connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, conn->cpath_layer);
     circuit_detach_stream(circuit_get_by_edge_conn(conn), conn);
     circuit_detach_stream(circuit_get_by_edge_conn(conn), conn);
     connection_free(conn);
     connection_free(conn);
@@ -1707,7 +1709,7 @@ connection_exit_connect(connection_t *conn)
           in.s_addr = htonl(addr);
           in.s_addr = htonl(addr);
           tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
           tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
           log_debug(LD_EXIT, "Redirecting connection from %s:%d to %s:%d",
           log_debug(LD_EXIT, "Redirecting connection from %s:%d to %s:%d",
-                    safe_str(conn->address), conn->port,
+                    escaped_safe_str(conn->address), conn->port,
                     safe_str(tmpbuf), port);
                     safe_str(tmpbuf), port);
         }
         }
         break;
         break;

+ 39 - 37
src/or/dns.c

@@ -162,11 +162,12 @@ purge_expired_resolves(uint32_t now)
     resolve = oldest_cached_resolve;
     resolve = oldest_cached_resolve;
     log_debug(LD_EXIT,
     log_debug(LD_EXIT,
               "Forgetting old cached resolve (address %s, expires %lu)",
               "Forgetting old cached resolve (address %s, expires %lu)",
-              safe_str(resolve->address), (unsigned long)resolve->expire);
+              escaped_safe_str(resolve->address),
+              (unsigned long)resolve->expire);
     if (resolve->state == CACHE_STATE_PENDING) {
     if (resolve->state == CACHE_STATE_PENDING) {
       log_debug(LD_EXIT,
       log_debug(LD_EXIT,
-                "Bug: Expiring a dns resolve ('%s') that's still pending."
-                " Forgot to cull it?", safe_str(resolve->address));
+                "Bug: Expiring a dns resolve %s that's still pending."
+                " Forgot to cull it?", escaped_safe_str(resolve->address));
       tor_fragile_assert();
       tor_fragile_assert();
     }
     }
     if (resolve->pending_connections) {
     if (resolve->pending_connections) {
@@ -300,20 +301,20 @@ dns_resolve(connection_t *exitconn)
         pending_connection->next = resolve->pending_connections;
         pending_connection->next = resolve->pending_connections;
         resolve->pending_connections = pending_connection;
         resolve->pending_connections = pending_connection;
         log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS "
         log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS "
-                  "resolve of '%s'",
-                  exitconn->s, safe_str(exitconn->address));
+                  "resolve of %s",
+                  exitconn->s, escaped_safe_str(exitconn->address));
         exitconn->state = EXIT_CONN_STATE_RESOLVING;
         exitconn->state = EXIT_CONN_STATE_RESOLVING;
         return 0;
         return 0;
       case CACHE_STATE_VALID:
       case CACHE_STATE_VALID:
         exitconn->addr = resolve->addr;
         exitconn->addr = resolve->addr;
-        log_debug(LD_EXIT,"Connection (fd %d) found cached answer for '%s'",
-                  exitconn->s, safe_str(exitconn->address));
+        log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
+                  exitconn->s, escaped_safe_str(exitconn->address));
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
           send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
           send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
         return 1;
         return 1;
       case CACHE_STATE_FAILED:
       case CACHE_STATE_FAILED:
-        log_debug(LD_EXIT,"Connection (fd %d) found cached error for '%s'",
-                  exitconn->s, safe_str(exitconn->address));
+        log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
+                  exitconn->s, escaped_safe_str(exitconn->address));
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
           send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
           send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
         circ = circuit_get_by_edge_conn(exitconn);
         circ = circuit_get_by_edge_conn(exitconn);
@@ -369,9 +370,9 @@ assign_to_dnsworker(connection_t *exitconn)
   }
   }
 
 
   log_debug(LD_EXIT,
   log_debug(LD_EXIT,
-            "Connection (fd %d) needs to resolve '%s'; assigning "
-            "to DNSWorker (fd %d)",
-            exitconn->s, safe_str(exitconn->address), dnsconn->s);
+            "Connection (fd %d) needs to resolve %s; assigning "
+            "to DNSWorker (fd %d)", exitconn->s,
+            escaped_safe_str(exitconn->address), dnsconn->s);
 
 
   tor_free(dnsconn->address);
   tor_free(dnsconn->address);
   dnsconn->address = tor_strdup(exitconn->address);
   dnsconn->address = tor_strdup(exitconn->address);
@@ -404,9 +405,8 @@ connection_dns_remove(connection_t *conn)
 
 
   resolve = HT_FIND(cache_map, &cache_root, &search);
   resolve = HT_FIND(cache_map, &cache_root, &search);
   if (!resolve) {
   if (!resolve) {
-    /* XXXX RD This *is* a bug, right? -NM */
-    log_notice(LD_BUG, "Address '%s' is not pending. Dropping.",
-               safe_str(conn->address));
+    log_notice(LD_BUG, "Address %s is not pending. Dropping.",
+               escaped_safe_str(conn->address));
     return;
     return;
   }
   }
 
 
@@ -419,8 +419,8 @@ connection_dns_remove(connection_t *conn)
     resolve->pending_connections = pend->next;
     resolve->pending_connections = pend->next;
     tor_free(pend);
     tor_free(pend);
     log_debug(LD_EXIT, "First connection (fd %d) no longer waiting "
     log_debug(LD_EXIT, "First connection (fd %d) no longer waiting "
-              "for resolve of '%s'",
-              conn->s, safe_str(conn->address));
+              "for resolve of %s",
+              conn->s, escaped_safe_str(conn->address));
     return;
     return;
   } else {
   } else {
     for ( ; pend->next; pend = pend->next) {
     for ( ; pend->next; pend = pend->next) {
@@ -429,8 +429,8 @@ connection_dns_remove(connection_t *conn)
         pend->next = victim->next;
         pend->next = victim->next;
         tor_free(victim);
         tor_free(victim);
         log_debug(LD_EXIT,
         log_debug(LD_EXIT,
-                  "Connection (fd %d) no longer waiting for resolve of '%s'",
-                  conn->s, safe_str(conn->address));
+                  "Connection (fd %d) no longer waiting for resolve of %s",
+                  conn->s, escaped_safe_str(conn->address));
         return; /* more are pending */
         return; /* more are pending */
       }
       }
     }
     }
@@ -491,17 +491,16 @@ dns_cancel_pending_resolve(char *address)
 
 
   resolve = HT_FIND(cache_map, &cache_root, &search);
   resolve = HT_FIND(cache_map, &cache_root, &search);
   if (!resolve) {
   if (!resolve) {
-    /* XXXX RD This *is* a bug, right? -NM */
-    log_notice(LD_BUG,"Address '%s' is not pending. Dropping.",
-               safe_str(address));
+    log_notice(LD_BUG,"Address %s is not pending. Dropping.",
+               escaped_safe_str(address));
     return;
     return;
   }
   }
 
 
   if (!resolve->pending_connections) {
   if (!resolve->pending_connections) {
     /* XXX this should never trigger, but sometimes it does */
     /* XXX this should never trigger, but sometimes it does */
     log_warn(LD_BUG,
     log_warn(LD_BUG,
-             "Bug: Address '%s' is pending but has no pending connections!",
-             safe_str(address));
+             "Bug: Address %s is pending but has no pending connections!",
+             escaped_safe_str(address));
     tor_fragile_assert();
     tor_fragile_assert();
     return;
     return;
   }
   }
@@ -509,8 +508,8 @@ dns_cancel_pending_resolve(char *address)
 
 
   /* mark all pending connections to fail */
   /* mark all pending connections to fail */
   log_debug(LD_EXIT,
   log_debug(LD_EXIT,
-             "Failing all connections waiting on DNS resolve of '%s'",
-             safe_str(address));
+             "Failing all connections waiting on DNS resolve of %s",
+             escaped_safe_str(address));
   while (resolve->pending_connections) {
   while (resolve->pending_connections) {
     pend = resolve->pending_connections;
     pend = resolve->pending_connections;
     pend->conn->state = EXIT_CONN_STATE_RESOLVEFAILED;
     pend->conn->state = EXIT_CONN_STATE_RESOLVEFAILED;
@@ -581,8 +580,8 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
 
 
   resolve = HT_FIND(cache_map, &cache_root, &search);
   resolve = HT_FIND(cache_map, &cache_root, &search);
   if (!resolve) {
   if (!resolve) {
-    log_info(LD_EXIT,"Resolved unasked address '%s'; caching anyway.",
-             safe_str(address));
+    log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.",
+             escaped_safe_str(address));
     resolve = tor_malloc_zero(sizeof(cached_resolve_t));
     resolve = tor_malloc_zero(sizeof(cached_resolve_t));
     resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
     resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
       CACHE_STATE_VALID : CACHE_STATE_FAILED;
       CACHE_STATE_VALID : CACHE_STATE_FAILED;
@@ -595,8 +594,8 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
   if (resolve->state != CACHE_STATE_PENDING) {
   if (resolve->state != CACHE_STATE_PENDING) {
     /* XXXX Maybe update addr? or check addr for consistency? Or let
     /* XXXX Maybe update addr? or check addr for consistency? Or let
      * VALID replace FAILED? */
      * VALID replace FAILED? */
-    log_notice(LD_EXIT, "Resolved '%s' which was already resolved; ignoring",
-               safe_str(address));
+    log_notice(LD_EXIT, "Resolved %s which was already resolved; ignoring",
+               escaped_safe_str(address));
     tor_assert(resolve->pending_connections == NULL);
     tor_assert(resolve->pending_connections == NULL);
     return;
     return;
   }
   }
@@ -715,8 +714,8 @@ connection_dns_process_inbuf(connection_t *conn)
   if (conn->state != DNSWORKER_STATE_BUSY && buf_datalen(conn->inbuf)) {
   if (conn->state != DNSWORKER_STATE_BUSY && buf_datalen(conn->inbuf)) {
     log_warn(LD_BUG,
     log_warn(LD_BUG,
              "Bug: read data (%d bytes) from an idle dns worker (fd %d, "
              "Bug: read data (%d bytes) from an idle dns worker (fd %d, "
-             "address '%s'). Please report.",
-             (int)buf_datalen(conn->inbuf), conn->s, safe_str(conn->address));
+             "address %s). Please report.", (int)buf_datalen(conn->inbuf),
+             conn->s, escaped_safe_str(conn->address));
     tor_fragile_assert();
     tor_fragile_assert();
 
 
     /* Pull it off the buffer anyway, or it will just stay there.
     /* Pull it off the buffer anyway, or it will just stay there.
@@ -738,8 +737,8 @@ connection_dns_process_inbuf(connection_t *conn)
   connection_fetch_from_buf(&success,1,conn);
   connection_fetch_from_buf(&success,1,conn);
   connection_fetch_from_buf((char *)&addr,sizeof(uint32_t),conn);
   connection_fetch_from_buf((char *)&addr,sizeof(uint32_t),conn);
 
 
-  log_debug(LD_EXIT, "DNSWorker (fd %d) returned answer for '%s'",
-            conn->s, safe_str(conn->address));
+  log_debug(LD_EXIT, "DNSWorker (fd %d) returned answer for %s",
+            conn->s, escaped_safe_str(conn->address));
 
 
   tor_assert(success >= DNS_RESOLVE_FAILED_TRANSIENT);
   tor_assert(success >= DNS_RESOLVE_FAILED_TRANSIENT);
   tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
   tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
@@ -796,6 +795,7 @@ dnsworker_main(void *data)
 {
 {
   char address[MAX_ADDRESSLEN];
   char address[MAX_ADDRESSLEN];
   unsigned char address_len;
   unsigned char address_len;
+  char *log_address;
   char answer[5];
   char answer[5];
   uint32_t ip;
   uint32_t ip;
   int *fdarray = data;
   int *fdarray = data;
@@ -840,6 +840,7 @@ dnsworker_main(void *data)
     }
     }
     address[address_len] = 0; /* null terminate it */
     address[address_len] = 0; /* null terminate it */
 
 
+    log_address = esc_for_log(safe_str(address));
     result = tor_lookup_hostname(address, &ip);
     result = tor_lookup_hostname(address, &ip);
     /* Make 0.0.0.0 an error, so that we can use "0" to mean "no addr") */
     /* Make 0.0.0.0 an error, so that we can use "0" to mean "no addr") */
     if (!ip)
     if (!ip)
@@ -848,19 +849,20 @@ dnsworker_main(void *data)
       case 1:
       case 1:
         /* XXX result can never be 1, because we set it to -1 above on error */
         /* XXX result can never be 1, because we set it to -1 above on error */
         log_info(LD_NET,"Could not resolve dest addr %s (transient).",
         log_info(LD_NET,"Could not resolve dest addr %s (transient).",
-                 safe_str(address));
+                 log_address);
         answer[0] = DNS_RESOLVE_FAILED_TRANSIENT;
         answer[0] = DNS_RESOLVE_FAILED_TRANSIENT;
         break;
         break;
       case -1:
       case -1:
         log_info(LD_NET,"Could not resolve dest addr %s (permanent).",
         log_info(LD_NET,"Could not resolve dest addr %s (permanent).",
-                 safe_str(address));
+                 log_address);
         answer[0] = DNS_RESOLVE_FAILED_PERMANENT;
         answer[0] = DNS_RESOLVE_FAILED_PERMANENT;
         break;
         break;
       case 0:
       case 0:
-        log_info(LD_NET,"Resolved address '%s'.",safe_str(address));
+        log_info(LD_NET,"Resolved address %s.", log_address);
         answer[0] = DNS_RESOLVE_SUCCEEDED;
         answer[0] = DNS_RESOLVE_SUCCEEDED;
         break;
         break;
     }
     }
+    tor_free(log_address);
     set_uint32(answer+1, ip);
     set_uint32(answer+1, ip);
     if (write_all(fd, answer, 5, 1) != 5) {
     if (write_all(fd, answer, 5, 1) != 5) {
       log_err(LD_NET,"writing answer failed. Child exiting.");
       log_err(LD_NET,"writing answer failed. Child exiting.");

+ 6 - 5
src/or/main.c

@@ -479,8 +479,8 @@ conn_close_if_marked(int i)
       log_info(LD_NET,
       log_info(LD_NET,
                "Conn (addr %s, fd %d, type %s, state %d) marked, but wants "
                "Conn (addr %s, fd %d, type %s, state %d) marked, but wants "
                "to flush %d bytes. (Marked at %s:%d)",
                "to flush %d bytes. (Marked at %s:%d)",
-               conn->address, conn->s, conn_type_to_string(conn->type),
-               conn->state,
+               escaped_safe_str(conn->address),
+               conn->s, conn_type_to_string(conn->type), conn->state,
                (int)conn->outbuf_flushlen,
                (int)conn->outbuf_flushlen,
                 conn->marked_for_close_file, conn->marked_for_close);
                 conn->marked_for_close_file, conn->marked_for_close);
     if (connection_speaks_cells(conn)) {
     if (connection_speaks_cells(conn)) {
@@ -514,8 +514,8 @@ conn_close_if_marked(int i)
              "We tried to write %d bytes to addr %s (fd %d, type %s, state %d)"
              "We tried to write %d bytes to addr %s (fd %d, type %s, state %d)"
              " but timed out. (Marked at %s:%d)",
              " but timed out. (Marked at %s:%d)",
              (int)buf_datalen(conn->outbuf),
              (int)buf_datalen(conn->outbuf),
-             safe_str(conn->address), conn->s, conn_type_to_string(conn->type),
-             conn->state,
+             escaped_safe_str(conn->address), conn->s,
+             conn_type_to_string(conn->type), conn->state,
              conn->marked_for_close_file,
              conn->marked_for_close_file,
              conn->marked_for_close);
              conn->marked_for_close);
     }
     }
@@ -1346,7 +1346,8 @@ dumpstats(int severity)
         (int)(now - conn->timestamp_created));
         (int)(now - conn->timestamp_created));
     if (!connection_is_listener(conn)) {
     if (!connection_is_listener(conn)) {
       log(severity,LD_GENERAL,
       log(severity,LD_GENERAL,
-          "Conn %d is to '%s:%d'.",i,safe_str(conn->address), conn->port);
+          "Conn %d is to '%s:%d'.", i,
+          escaped_safe_str(conn->address), conn->port);
       log(severity,LD_GENERAL,
       log(severity,LD_GENERAL,
           "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
           "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
           i,
           i,

+ 1 - 1
src/or/routerparse.c

@@ -1020,7 +1020,7 @@ routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens)
   }
   }
 
 
   if (tor_inet_aton(tok->args[5], &in) == 0) {
   if (tor_inet_aton(tok->args[5], &in) == 0) {
-    log_warn(LD_DIR, "Error parsing address '%s'", escaped(tok->args[5]));
+    log_warn(LD_DIR, "Error parsing address %s", escaped(tok->args[5]));
     goto err;
     goto err;
   }
   }
   rs->addr = ntohl(in.s_addr);
   rs->addr = ntohl(in.s_addr);