commit ddf7aa7a21bfc8418488b27e05fa7e53ef4f514c Author: Ravi Chandra Padmala neenaoffline@gmail.com Date: Mon Sep 24 20:16:18 2012 +0530
Fixing a bunch of things after cr #6951
https://trac.torproject.org/projects/tor/ticket/6951 --- stem/control.py | 3 +- stem/response/mapaddress.py | 9 +++-- test/integ/control/controller.py | 8 +++- test/runner.py | 2 +- test/settings.cfg | 1 - test/unit/response/mapaddress.py | 3 +- test/util.py | 66 ++++++++++++++++++++++++++++++++++++++ test/utils.py | 61 ----------------------------------- 8 files changed, 82 insertions(+), 71 deletions(-)
diff --git a/stem/control.py b/stem/control.py index 8b407cb..a5a7868 100644 --- a/stem/control.py +++ b/stem/control.py @@ -1148,7 +1148,8 @@ class Controller(BaseController): :returns: dictionary with original -> replacement address mappings """
- response = self.msg("MAPADDRESS %s" % " ".join([k + "=" + mapping[k] for k in mapping.iterkeys()])) + mapaddress_arg = " ".join(["%s=%s" % (k, v) for (k, v) in mapping.items()]) + response = self.msg("MAPADDRESS %s" % mapaddress_arg) stem.response.convert("MAPADDRESS", response)
return response.entries diff --git a/stem/response/mapaddress.py b/stem/response/mapaddress.py index 2d1a498..d4e33de 100644 --- a/stem/response/mapaddress.py +++ b/stem/response/mapaddress.py @@ -31,8 +31,9 @@ class MapAddressResponse(stem.response.ControlMessage):
for code, _, message in self.content(): if code == "250": - try: key, value = message.split("=", 1) - except ValueError: raise stem.socket.ProtocolError(None, "Not a mapping") - - self.entries[key] = value + try: + key, value = message.split("=", 1) + self.entries[key] = value + except ValueError: + raise stem.socket.ProtocolError(None, "MAPADDRESS returned '%s', which isn't a mapping" % message)
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py index f8fd56e..2af68c3 100644 --- a/test/integ/control/controller.py +++ b/test/integ/control/controller.py @@ -409,6 +409,7 @@ class TestController(unittest.TestCase): def test_mapaddress(self):
if test.runner.require_control(self): return + elif test.runner.require_online(self): return
runner = test.runner.get_runner()
@@ -418,9 +419,12 @@ class TestController(unittest.TestCase): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', int(controller.get_conf('SocksPort')))) test.utils.negotiate_socks(s, '1.2.1.2', 80) - s.sendall(test.utils.ip_request) + s.sendall(test.utils.ip_request) # make the http request for the ip address response = s.recv(1000) + + # everything after the blank line is the 'data' in a HTTP response. + # The response data for our request for request should be an IP address + '\n' ip_addr = response[response.find("\r\n\r\n"):].strip()
- socket.inet_aton(ip_addr) # validate IP + stem.util.connection.is_valid_ip_address(ip_addr)
diff --git a/test/runner.py b/test/runner.py index b748bfe..a372c42 100644 --- a/test/runner.py +++ b/test/runner.py @@ -69,7 +69,7 @@ ERROR_ATTR = (term.Color.RED, term.Attr.BOLD)
BASE_TORRC = """# configuration for stem integration tests DataDirectory %s -SocksPort 29327 +SocksPort 1112 DownloadExtraInfo 1 """
diff --git a/test/settings.cfg b/test/settings.cfg index 75d5078..44e28ab 100644 --- a/test/settings.cfg +++ b/test/settings.cfg @@ -76,7 +76,6 @@ target.prereq RUN_PTRACE => TORRC_DISABLE_DEBUGGER_ATTACHMENT # means that each of these targets will have a dedicated integration test run.
target.torrc RUN_NONE => -target.torrc ONLINE => PORT target.torrc RUN_OPEN => PORT target.torrc RUN_PASSWORD => PORT, PASSWORD target.torrc RUN_COOKIE => PORT, COOKIE diff --git a/test/unit/response/mapaddress.py b/test/unit/response/mapaddress.py index b8045c1..3c2a372 100644 --- a/test/unit/response/mapaddress.py +++ b/test/unit/response/mapaddress.py @@ -62,8 +62,8 @@ class TestMapAddressResponse(unittest.TestCase):
control_message = mocking.get_message(UNRECOGNIZED_KEYS_RESPONSE) self.assertRaises(stem.socket.InvalidRequest, stem.response.convert, "MAPADDRESS", control_message) - control_message = mocking.get_message(UNRECOGNIZED_KEYS_RESPONSE) expected = { "23": "324" } + control_message = mocking.get_message(PARTIAL_FAILURE_RESPONSE) stem.response.convert("MAPADDRESS", control_message) self.assertEqual(expected, control_message.entries) @@ -77,6 +77,7 @@ class TestMapAddressResponse(unittest.TestCase):
control_message = mocking.get_message(INVALID_EMPTY_RESPONSE) self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "MAPADDRESS", control_message) + control_message = mocking.get_message(INVALID_RESPONSE) self.assertRaises(stem.socket.ProtocolError, stem.response.convert, "MAPADDRESS", control_message)
diff --git a/test/util.py b/test/util.py new file mode 100644 index 0000000..51e9bd9 --- /dev/null +++ b/test/util.py @@ -0,0 +1,66 @@ +import struct +import socket + +from stem.socket import ProtocolError +import test.runner + +error_msgs = { + 0x5a: "SOCKS4A request granted", + 0x5b: "SOCKS4A request rejected or failed", + 0x5c: "SOCKS4A request failed because client is not running identd (or not reachable from the server)", + 0x5d: "SOCKS4A request failed because client's identd could not confirm the user ID string in the request", +} + +ip_request = """GET /ip HTTP/1.0 +Host: ifconfig.me +Accept-Encoding: identity + +""" + +def external_ip(sock): + """ + Returns the externally visible IP address when using a SOCKS4a proxy. + Negotiates the socks connection, connects to ipconfig.me and requests + http://ifconfig.me/ip to find out the externally visible IP. + + :param socket sock: socket connected to a SOCKS4a proxy server + + :returns: externally visible IP address, or None if it isn't able to + """ + + try: + negotiate_socks(sock, "ifconfig.me", 80) + s.sendall(req) + response = s.recv(1000) + + # everything after the blank line is the 'data' in a HTTP response + # The response data for our request for request should be an IP address + '\n' + return response[response.find("\r\n\r\n"):].strip() + except: + pass + +def negotiate_socks(sock, host, port): + """ + Negotiate with a socks4a server. Closes the socket and raises an exception on + failure. + + :param socket sock: socket connected to socks4a server + :param str host: host to connect to + :param int port: port to connect to + + :raises: :class:`stem.socket.ProtocolError` if the socks server doesn't grant our request + + :returns: a list with the IP address and the port that the proxy connected to + """ + + # SOCKS4a request here - http://en.wikipedia.org/wiki/SOCKS#Protocol + request = "\x04\x01" + struct.pack("!H", port) + "\x00\x00\x00\x01" + "\x00" + host + "\x00" + sock.sendall(request) + response = sock.recv(8) + + if len(response) != 8 or response[0] != "\x00" or response[1] != "\x5a": + sock.close() + raise ProtocolError(error_msgs.get(response[1], "SOCKS server returned unrecognized error code")) + + return [socket.inet_ntoa(response[4:]), struct.unpack("!H", response[2:4])[0]] + diff --git a/test/utils.py b/test/utils.py deleted file mode 100644 index 8ed9297..0000000 --- a/test/utils.py +++ /dev/null @@ -1,61 +0,0 @@ -import struct -import socket - -from stem.socket import ProtocolError -import test.runner - -error_msgs = { - 0x5a: "SOCKS4A request granted", - 0x5b: "SOCKS4A request rejected or failed", - 0x5c: "SOCKS4A request failed because client is not running identd (or not reachable from the server)", - 0x5d: "SOCKS4A request failed because client's identd could not confirm the user ID string in the request", -} - -ip_request = """GET /ip HTTP/1.0 -Host: ifconfig.me -Accept-Encoding: identity - -""" - -def external_ip(sock): - """ - Returns the externally visible IP address when using a SOCKS4a proxy. - - :param socket sock: socket connected to a SOCKS4a proxy server - - :returns: externally visible IP address, or None if it isn't able to - """ - - try: - negotiate_socks(sock, "ifconfig.me", 80) - s.sendall(req) - response = s.recv(1000) - - return response[response.find("\n\n"):].strip() - except: - pass - -def negotiate_socks(sock, host, port): - """ - Negotiate with a socks4a server. Closes the socket and raises an exception on - failure. - - :param socket sock: socket connected to socks4a server - :param str host: host to connect to - :param int port: port to connect to - - :raises: :class:`stem.socket.ProtocolError` if the socks server doesn't grant our request - - :returns: a list with the IP address and the port that the proxy connected to - """ - - request = "\x04\x01" + struct.pack("!H", port) + "\x00\x00\x00\x01" + "\x00" + host + "\x00" - sock.sendall(request) - response = sock.recv(8) - - if len(response) != 8 or response[0] != "\x00" or response[1] != "\x5a": - sock.close() - raise ProtocolError(error_msgs.get(response[1], "SOCKS server returned unrecognized error code")) - - return [socket.inet_ntoa(response[4:]), struct.unpack("!H", response[2:4])[0]] -
tor-commits@lists.torproject.org