LCOV - code coverage report
Current view: top level - feature/control - control_fmt.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 57 132 43.2 %
Date: 2021-11-24 03:28:48 Functions: 2 5 40.0 %

          Line data    Source code
       1             : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       2             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       3             : /* See LICENSE for licensing information */
       4             : 
       5             : /**
       6             :  * \file control_fmt.c
       7             :  * \brief Formatting functions for controller data.
       8             :  */
       9             : 
      10             : #include "core/or/or.h"
      11             : 
      12             : #include "core/mainloop/connection.h"
      13             : #include "core/or/circuitbuild.h"
      14             : #include "core/or/circuitlist.h"
      15             : #include "core/or/connection_edge.h"
      16             : #include "feature/control/control_fmt.h"
      17             : #include "feature/control/control_proto.h"
      18             : #include "feature/nodelist/nodelist.h"
      19             : 
      20             : #include "core/or/cpath_build_state_st.h"
      21             : #include "core/or/entry_connection_st.h"
      22             : #include "core/or/or_connection_st.h"
      23             : #include "core/or/origin_circuit_st.h"
      24             : #include "core/or/socks_request_st.h"
      25             : #include "feature/control/control_connection_st.h"
      26             : 
      27             : /** Given an AP connection <b>conn</b> and a <b>len</b>-character buffer
      28             :  * <b>buf</b>, determine the address:port combination requested on
      29             :  * <b>conn</b>, and write it to <b>buf</b>.  Return 0 on success, -1 on
      30             :  * failure. */
      31             : int
      32           0 : write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
      33             : {
      34           0 :   char buf2[256];
      35           0 :   if (conn->chosen_exit_name)
      36           0 :     if (tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name)<0)
      37             :       return -1;
      38           0 :   if (!conn->socks_request)
      39             :     return -1;
      40           0 :   if (tor_snprintf(buf, len, "%s%s%s:%d",
      41           0 :                conn->socks_request->address,
      42           0 :                conn->chosen_exit_name ? buf2 : "",
      43           0 :                !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
      44           0 :                                      ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
      45           0 :                conn->socks_request->port)<0)
      46           0 :     return -1;
      47             :   return 0;
      48             : }
      49             : 
      50             : /** Figure out the best name for the target router of an OR connection
      51             :  * <b>conn</b>, and write it into the <b>len</b>-character buffer
      52             :  * <b>name</b>. */
      53             : void
      54           0 : orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
      55             : {
      56           0 :   const node_t *node = node_get_by_id(conn->identity_digest);
      57           0 :   if (node) {
      58           0 :     tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
      59           0 :     node_get_verbose_nickname(node, name);
      60           0 :   } else if (! tor_digest_is_zero(conn->identity_digest)) {
      61           0 :     name[0] = '$';
      62           0 :     base16_encode(name+1, len-1, conn->identity_digest,
      63             :                   DIGEST_LEN);
      64             :   } else {
      65           0 :     tor_snprintf(name, len, "%s:%d",
      66           0 :                  conn->base_.address, conn->base_.port);
      67             :   }
      68           0 : }
      69             : 
      70             : /** Allocate and return a description of <b>circ</b>'s current status,
      71             :  * including its path (if any). */
      72             : char *
      73           0 : circuit_describe_status_for_controller(origin_circuit_t *circ)
      74             : {
      75           0 :   char *rv;
      76           0 :   smartlist_t *descparts = smartlist_new();
      77             : 
      78             :   {
      79           0 :     char *vpath = circuit_list_path_for_controller(circ);
      80           0 :     if (*vpath) {
      81           0 :       smartlist_add(descparts, vpath);
      82             :     } else {
      83           0 :       tor_free(vpath); /* empty path; don't put an extra space in the result */
      84             :     }
      85             :   }
      86             : 
      87             :   {
      88           0 :     cpath_build_state_t *build_state = circ->build_state;
      89           0 :     smartlist_t *flaglist = smartlist_new();
      90           0 :     char *flaglist_joined;
      91             : 
      92           0 :     if (build_state->onehop_tunnel)
      93           0 :       smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
      94           0 :     if (build_state->is_internal)
      95           0 :       smartlist_add(flaglist, (void *)"IS_INTERNAL");
      96           0 :     if (build_state->need_capacity)
      97           0 :       smartlist_add(flaglist, (void *)"NEED_CAPACITY");
      98           0 :     if (build_state->need_uptime)
      99           0 :       smartlist_add(flaglist, (void *)"NEED_UPTIME");
     100             : 
     101             :     /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
     102           0 :     if (smartlist_len(flaglist)) {
     103           0 :       flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
     104             : 
     105           0 :       smartlist_add_asprintf(descparts, "BUILD_FLAGS=%s", flaglist_joined);
     106             : 
     107           0 :       tor_free(flaglist_joined);
     108             :     }
     109             : 
     110           0 :     smartlist_free(flaglist);
     111             :   }
     112             : 
     113           0 :   smartlist_add_asprintf(descparts, "PURPOSE=%s",
     114           0 :                     circuit_purpose_to_controller_string(circ->base_.purpose));
     115             : 
     116             :   {
     117           0 :     const char *hs_state =
     118           0 :       circuit_purpose_to_controller_hs_state_string(circ->base_.purpose);
     119             : 
     120           0 :     if (hs_state != NULL) {
     121           0 :       smartlist_add_asprintf(descparts, "HS_STATE=%s", hs_state);
     122             :     }
     123             :   }
     124             : 
     125           0 :   if (circ->hs_ident != NULL) {
     126           0 :     char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
     127           0 :     const char *onion_address;
     128           0 :     hs_build_address(&circ->hs_ident->identity_pk, HS_VERSION_THREE, addr);
     129           0 :     onion_address = addr;
     130           0 :     smartlist_add_asprintf(descparts, "REND_QUERY=%s", onion_address);
     131             :   }
     132             : 
     133             :   {
     134           0 :     char tbuf[ISO_TIME_USEC_LEN+1];
     135           0 :     format_iso_time_nospace_usec(tbuf, &circ->base_.timestamp_created);
     136             : 
     137           0 :     smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf);
     138             :   }
     139             : 
     140             :   // Show username and/or password if available.
     141           0 :   if (circ->socks_username_len > 0) {
     142           0 :     char* socks_username_escaped = esc_for_log_len(circ->socks_username,
     143             :                                      (size_t) circ->socks_username_len);
     144           0 :     smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
     145             :                            socks_username_escaped);
     146           0 :     tor_free(socks_username_escaped);
     147             :   }
     148           0 :   if (circ->socks_password_len > 0) {
     149           0 :     char* socks_password_escaped = esc_for_log_len(circ->socks_password,
     150             :                                      (size_t) circ->socks_password_len);
     151           0 :     smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
     152             :                            socks_password_escaped);
     153           0 :     tor_free(socks_password_escaped);
     154             :   }
     155             : 
     156           0 :   rv = smartlist_join_strings(descparts, " ", 0, NULL);
     157             : 
     158           0 :   SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
     159           0 :   smartlist_free(descparts);
     160             : 
     161           0 :   return rv;
     162             : }
     163             : 
     164             : /** Allocate and return a description of <b>conn</b>'s current status. */
     165             : char *
     166          19 : entry_connection_describe_status_for_controller(const entry_connection_t *conn)
     167             : {
     168          19 :   char *rv;
     169          19 :   smartlist_t *descparts = smartlist_new();
     170             : 
     171          19 :   if (conn->socks_request != NULL) {
     172             :     // Show username and/or password if available; used by IsolateSOCKSAuth.
     173          19 :     if (conn->socks_request->usernamelen > 0) {
     174          19 :       char* username_escaped = esc_for_log_len(conn->socks_request->username,
     175             :                                  (size_t) conn->socks_request->usernamelen);
     176          19 :       smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
     177             :                              username_escaped);
     178          19 :       tor_free(username_escaped);
     179             :     }
     180          19 :     if (conn->socks_request->passwordlen > 0) {
     181          19 :       char* password_escaped = esc_for_log_len(conn->socks_request->password,
     182             :                                  (size_t) conn->socks_request->passwordlen);
     183          19 :       smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
     184             :                              password_escaped);
     185          19 :       tor_free(password_escaped);
     186             :     }
     187             : 
     188          19 :     const char *client_protocol;
     189             :     // Show the client protocol; used by IsolateClientProtocol.
     190          19 :     switch (conn->socks_request->listener_type)
     191             :       {
     192           3 :       case CONN_TYPE_AP_LISTENER:
     193           3 :         switch (conn->socks_request->socks_version)
     194             :           {
     195             :           case 4: client_protocol = "SOCKS4"; break;
     196           1 :           case 5: client_protocol = "SOCKS5"; break;
     197           1 :           default: client_protocol = "UNKNOWN";
     198             :           }
     199             :         break;
     200             :       case CONN_TYPE_AP_TRANS_LISTENER: client_protocol = "TRANS"; break;
     201           1 :       case CONN_TYPE_AP_NATD_LISTENER: client_protocol = "NATD"; break;
     202           1 :       case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
     203           1 :       case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
     204           1 :         client_protocol = "HTTPCONNECT"; break;
     205           0 :       case CONN_TYPE_METRICS_LISTENER:
     206           0 :         client_protocol = "METRICS"; break;
     207          12 :       default: client_protocol = "UNKNOWN";
     208             :       }
     209          19 :     smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
     210             :                            client_protocol);
     211             :   }
     212             : 
     213             :   // Show newnym epoch; used for stream isolation when NEWNYM is used.
     214          19 :   smartlist_add_asprintf(descparts, "NYM_EPOCH=%u",
     215          19 :                          conn->nym_epoch);
     216             : 
     217             :   // Show session group; used for stream isolation of multiple listener ports.
     218          19 :   smartlist_add_asprintf(descparts, "SESSION_GROUP=%d",
     219          19 :                          conn->entry_cfg.session_group);
     220             : 
     221             :   // Show isolation flags.
     222          19 :   smartlist_t *isoflaglist = smartlist_new();
     223          19 :   char *isoflaglist_joined;
     224          19 :   if (conn->entry_cfg.isolation_flags & ISO_DESTPORT) {
     225           2 :     smartlist_add(isoflaglist, (void *)"DESTPORT");
     226             :   }
     227          19 :   if (conn->entry_cfg.isolation_flags & ISO_DESTADDR) {
     228           1 :     smartlist_add(isoflaglist, (void *)"DESTADDR");
     229             :   }
     230          19 :   if (conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) {
     231           2 :     smartlist_add(isoflaglist, (void *)"SOCKS_USERNAME");
     232           2 :     smartlist_add(isoflaglist, (void *)"SOCKS_PASSWORD");
     233             :   }
     234          19 :   if (conn->entry_cfg.isolation_flags & ISO_CLIENTPROTO) {
     235           1 :     smartlist_add(isoflaglist, (void *)"CLIENT_PROTOCOL");
     236             :   }
     237          19 :   if (conn->entry_cfg.isolation_flags & ISO_CLIENTADDR) {
     238           1 :     smartlist_add(isoflaglist, (void *)"CLIENTADDR");
     239             :   }
     240          19 :   if (conn->entry_cfg.isolation_flags & ISO_SESSIONGRP) {
     241           1 :     smartlist_add(isoflaglist, (void *)"SESSION_GROUP");
     242             :   }
     243          19 :   if (conn->entry_cfg.isolation_flags & ISO_NYM_EPOCH) {
     244           2 :     smartlist_add(isoflaglist, (void *)"NYM_EPOCH");
     245             :   }
     246          19 :   isoflaglist_joined = smartlist_join_strings(isoflaglist, ",", 0, NULL);
     247          19 :   smartlist_add_asprintf(descparts, "ISO_FIELDS=%s", isoflaglist_joined);
     248          19 :   tor_free(isoflaglist_joined);
     249          19 :   smartlist_free(isoflaglist);
     250             : 
     251          19 :   rv = smartlist_join_strings(descparts, " ", 0, NULL);
     252             : 
     253         133 :   SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
     254          19 :   smartlist_free(descparts);
     255             : 
     256          19 :   return rv;
     257             : }
     258             : 
     259             : /** Return a longname the node whose identity is <b>id_digest</b>. If
     260             :  * node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
     261             :  * returned instead.
     262             :  *
     263             :  * This function is not thread-safe.  Each call to this function invalidates
     264             :  * previous values returned by this function.
     265             :  */
     266          78 : MOCK_IMPL(const char *,
     267             : node_describe_longname_by_id,(const char *id_digest))
     268             : {
     269          78 :   static char longname[MAX_VERBOSE_NICKNAME_LEN+1];
     270          78 :   node_get_verbose_nickname_by_id(id_digest, longname);
     271          78 :   return longname;
     272             : }

Generated by: LCOV version 1.14