This file is indexed.

/usr/share/arm/test.py is in tor-arm 1.4.5.0-1.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python

"""
Handler for arm tests and demos.
"""

import time
from util import connections, torTools, uiTools

MENU = """Arm Test Options:
  1. Resolver Performance Test
  2. Resolver Dump
  3. Glyph Demo
  4. Exit Policy Check
  q. Quit

Selection: """

def printDivider():
  print("\n" + "-" * 40 + "\n")

conn = None
while True:
  userInput = raw_input(MENU)
  
  # initiate the TorCtl connection if the test needs it
  if userInput in ("1", "2", "4") and not conn:
    conn = torTools.getConn()
    conn.init()
    
    # prefetch pid so extra system calls don't effect the timing of tests
    conn.getMyPid()
  
  if userInput == "q":
    break # quit test script
  elif userInput == "1":
    systemResolvers = connections.getSystemResolvers()
    printDivider()
    
    allConnectionResults = []
    for resolver in systemResolvers:
      startTime = time.time()
      connectionResults = connections.getConnections(resolver, "tor", conn.getMyPid())
      connectionResults.sort()
      allConnectionResults.append(connectionResults)
      
      resolverLabel = "%-10s" % resolver
      countLabel = "%4i results" % len(connectionResults)
      timeLabel = "%0.4f seconds" % (time.time() - startTime)
      print "%s %s     %s" % (resolverLabel, countLabel, timeLabel)
    
    allResolversMatch = True
    firstResult = allConnectionResults.pop()
    while allConnectionResults:
      if allConnectionResults.pop() != firstResult:
        allResolversMatch = False
        break
    
    if allResolversMatch:
      print("\nThe results of all the connection resolvers match")
    else:
      print("\nWarning: Connection resolver results differ")
    
    printDivider()
  elif userInput == "2":
    # use the given resolver to fetch tor's connections
    while True:
      # provide the selection options
      printDivider()
      print("Select a resolver:")
      availableResolvers = connections.Resolver.values()
      for i in range(len(availableResolvers)):
        print("  %i. %s" % (i, availableResolvers[i]))
      print("  q. Go back to the main menu")
      
      userSelection = raw_input("\nSelection: ")
      if userSelection == "q":
        printDivider()
        break
      
      if userSelection.isdigit() and int(userSelection) in range(0, 7):
        try:
          resolver = connections.Resolver.values()[int(userSelection)]
          startTime = time.time()
          
          print(connections.getResolverCommand(resolver, "tor", conn.getMyPid()))
          connectionResults = connections.getConnections(resolver, "tor", conn.getMyPid())
          connectionResults.sort()
          
          # prints results
          printDivider()
          for lIp, lPort, fIp, fPort in connectionResults:
            print("  %s:%s -> %s:%s" % (lIp, lPort, fIp, fPort))
          
          print("\n  Runtime: %0.4f seconds" % (time.time() - startTime))
        except (IOError, IndexError), exc:
          print exc
      else:
        print("'%s' isn't a valid selection\n" % userSelection)
  elif userInput == "3":
    uiTools.demoGlyphs()
    
    # Switching to a curses context and back repeatedly seems to screw up the
    # terminal. Just to be safe this ends the process after the demo.
    break
  elif userInput == "4":
    # display the current exit policy and query if destinations are allowed by it
    exitPolicy = conn.getExitPolicy()
    print("Exit Policy: %s" % exitPolicy)
    printDivider()
    
    while True:
      # provide the selection options
      userSelection = raw_input("\nCheck if destination is allowed (q to go back): ")
      userSelection = userSelection.replace(" ", "").strip() # removes all whitespace
      
      isValidQuery, isExitAllowed = True, False
      if userSelection == "q":
        printDivider()
        break
      elif connections.isValidIpAddress(userSelection):
        # just an ip address (use port 80)
        isExitAllowed = exitPolicy.check(userSelection, 80)
      elif userSelection.isdigit():
        # just a port (use a common ip like 4.2.2.2)
        isExitAllowed = exitPolicy.check("4.2.2.2", userSelection)
      elif ":" in userSelection:
        # ip/port combination
        ipAddr, port = userSelection.split(":", 1)
        
        if connections.isValidIpAddress(ipAddr) and port.isdigit():
          isExitAllowed = exitPolicy.check(ipAddr, port)
        else: isValidQuery = False
      else: isValidQuery = False # invalid input
      
      if isValidQuery:
        resultStr = "is" if isExitAllowed else "is *not*"
        print("Exiting %s allowed to that destination" % resultStr)
      else:
        print("'%s' isn't a valid destination (should be an ip, port, or ip:port)\n" % userSelection)
    
  else:
    print("'%s' isn't a valid selection\n" % userInput)