Beispiel #1
0
 def test_normalize_data(self):
     variables, _ = protocol.Query.normalize_data(
         protocol.QueryType.open_ticket, self.OPEN_TICKET_VARS_RETRY,
         util.DataChunk(b'\x00\x00\x00', 0))
     for var, data in variables.items():
         self.assertIsInstance(data, int)
     variables, _ = protocol.Query.normalize_data(
         protocol.QueryType.open_ticket, self.REQUEST_DATA_VARS_RETRY,
         util.DataChunk(b'\x00\x00\x00', 0))
     for var, data in variables.items():
         if var == 'bf':
             self.assertEqual(b'\xab\xcd\xef\xab\xcd\xef\xab\xcd\xef', data)
         else:
             self.assertIsInstance(data, int)
     variables, _ = protocol.Query.normalize_data(
         protocol.QueryType.open_ticket, self.CHECK_REQUEST_VARS_RETRY,
         util.DataChunk(b'\x00\x00\x00', 0))
     for var, data in variables.items():
         self.assertIsInstance(data, int)
     variables, _ = protocol.Query.normalize_data(
         protocol.QueryType.open_ticket, self.FETCH_RESPONSE_VARS_RETRY,
         util.DataChunk(b'\x00\x00\x00', 0))
     for var, data in variables.items():
         self.assertIsInstance(data, int)
     variables, _ = protocol.Query.normalize_data(
         protocol.QueryType.open_ticket, self.CLOSE_TICKET_VARS_RETRY,
         util.DataChunk(b'\x00\x00\x00', 0))
     self.assertIsInstance(variables['retry'], int)
     self.assertIsInstance(variables['ac'], bool)  # unchanged
     self.assertIsInstance(variables['id'], int)
Beispiel #2
0
    def test_encode(self):
        payload = util.DataChunk(b'\x00\x00\x00', 0)
        query = protocol.Query.create('0', self.OPEN_TICKET_VARS, payload)
        record = query.encode()
        self.assertEqual(
            'sz-00000044.rn-12345678.id-00000001.v0.tun.vpnoverdns.com.',
            record.fqdn)
        self.assertEqual(protocol.chunk_to_ipv4(payload), record.value)

        query = protocol.Query.create('0', self.REQUEST_DATA_VARS, payload)
        record = query.encode()
        self.assertEqual(
            'bf-abcdefabcdefabcdef.wr-00000000.id-98765432.v0.tun.vpnoverdns.com.',
            record.fqdn)
        self.assertEqual(protocol.chunk_to_ipv4(payload), record.value)

        query = protocol.Query.create('0', self.CHECK_REQUEST_VARS, payload)
        record = query.encode()
        self.assertEqual('ck-00000020.id-98765432.v0.tun.vpnoverdns.com.',
                         record.fqdn)
        self.assertEqual(protocol.chunk_to_ipv4(payload), record.value)

        query = protocol.Query.create('0', self.FETCH_RESPONSE_VARS, payload)
        record = query.encode()
        self.assertEqual(
            'ln-00000048.rd-00000000.id-98765432.v0.tun.vpnoverdns.com.',
            record.fqdn)
        self.assertEqual(protocol.chunk_to_ipv4(payload), record.value)

        query = protocol.Query.create('0', self.CLOSE_TICKET_VARS, payload)
        record = query.encode()
        self.assertEqual('ac.id-98765432.v0.tun.vpnoverdns.com.', record.fqdn)
        self.assertEqual(protocol.chunk_to_ipv4(payload), record.value)
Beispiel #3
0
 def test_build_from_records_text_request_data(self):
     payload = util.DataChunk(b'E\x00', 0)  # E0 means no error (success)
     queries = [
         protocol.Query.create(
             '0', {
                 'bf':
                 binascii.hexlify(
                     self.TEXT_REQUEST[i:i + 30]).decode('ascii'),
                 'wr':
                 i,
                 'id':
                 12345678
             }, payload) for i in range(0, len(self.TEXT_REQUEST), 30)
     ]
     records = [q.encode() for q in queries]
     self._random.shuffle(records)
     self._db.build_from_records(records)
     self.assertIn(12345678, self._db)
     self.assertEqual(12345678, self._db[12345678].ticket_id)
     self.assertFalse(self._db[12345678].collision)
     self.assertIsNone(self._db[12345678].random_number)
     self.assertEqual(len(self.TEXT_REQUEST),
                      self._db[12345678].raw_request_length)
     self.assertEqual(self.TEXT_REQUEST,
                      self._db[12345678].raw_request_data)
     self.assertEqual(self.TEXT_REQUEST_MESSAGE,
                      self._db[12345678].request_message)
     self.assertIsNone(self._db[12345678].request_data)
Beispiel #4
0
 def test_type_deduction(self):
     querytype = protocol.QueryType.deduce(
         '0', self.OPEN_TICKET_VARS, util.DataChunk(b'\x00\x00\x00', 0))
     self.assertEqual(protocol.QueryType.open_ticket, querytype)
     querytype = protocol.QueryType.deduce(
         '0', self.REQUEST_DATA_VARS, util.DataChunk(b'\x00\x00\x00', 0))
     self.assertEqual(protocol.QueryType.request_data, querytype)
     querytype = protocol.QueryType.deduce(
         '0', self.CHECK_REQUEST_VARS, util.DataChunk(b'\x00\x00\x00', 0))
     self.assertEqual(protocol.QueryType.check_request, querytype)
     querytype = protocol.QueryType.deduce(
         '0', self.FETCH_RESPONSE_VARS, util.DataChunk(b'\x00\x00\x00', 0))
     self.assertEqual(protocol.QueryType.fetch_response, querytype)
     querytype = protocol.QueryType.deduce(
         '0', self.CLOSE_TICKET_VARS, util.DataChunk(b'\x00\x00\x00', 0))
     self.assertEqual(protocol.QueryType.close_ticket, querytype)
Beispiel #5
0
    def test_build_from_records_binary_response_data(self):
        compressed_length = len(self.COMPRESSED_BINARY_RESPONSE)
        response_segments = [
            self.COMPRESSED_BINARY_RESPONSE[i:i + 48]
            for i in range(0, compressed_length, 48)
        ]
        records = []
        for i, segment in enumerate(response_segments):
            query_vars = {'ln': len(segment), 'rd': i * 48, 'id': 12345678}
            for off in range(0, len(segment), 3):
                query = protocol.Query.create(
                    '0', query_vars, util.DataChunk(segment[off:off + 3], off))
                records.append(query.encode())

        self._random.shuffle(records)
        self._db.build_from_records(records)
        self.assertIn(12345678, self._db)
        self.assertEqual(12345678, self._db[12345678].ticket_id)
        self.assertFalse(self._db[12345678].collision)
        self.assertIsNone(self._db[12345678].random_number)
        self.assertIsNone(self._db[12345678].raw_request_data)
        self.assertIsNone(self._db[12345678].raw_request_length)
        self.assertEqual(len(self.COMPRESSED_BINARY_RESPONSE),
                         self._db[12345678].raw_response_length)
        self.assertEqual(self.COMPRESSED_BINARY_RESPONSE,
                         self._db[12345678].raw_response_data)
        self.assertEqual(self.BINARY_RESPONSE_DATA,
                         self._db[12345678].response_data)
        self.assertEqual(self.BINARY_RESPONSE_MESSAGE,
                         self._db[12345678].response_message)
 def _generate_data(self, length, alignment):
     assert length > 0
     assert alignment > 0
     data = os.urandom(length)
     return data, [
         util.DataChunk(data[i:i + alignment], i)
         for i in range(0, len(data), alignment)
     ]
def ipv4_to_chunk(addr):
    octets = addr.split('.')
    if len(octets) != 4:
        raise ValueError('IPv4 addresses must have 4 octets')
    octets = map(int, octets)
    try:
        data = ipv4_to_chunk.packer.pack(*octets)
    except struct.error as e:
        raise ValueError('every octet must be within [0,255]') from e

    length = (data[0] >> 6) & 0x3
    offset = (data[0] & 0x3f) * 3
    return util.DataChunk(data[1:length + 1], offset)
Beispiel #8
0
class TestQueryParser(unittest.TestCase):
    DEFAULT_RECORD = dnsrecord.DnsRecord(
        'foo-12345678.bar-00000000.v0.tun.vpnoverdns.com.', 'IN', 'A',
        '192.178.115.214')
    CUSTOM_RECORD = dnsrecord.DnsRecord(
        'foo-12345678.bar-00000000.v0.illinois.edu.', 'IN', 'A',
        '192.178.115.214')
    VARIABLES = {'foo': '12345678', 'bar': '00000000'}
    DATA = util.DataChunk(b'\xb2\x73\xd6', 0)

    def test_default_suffix(self):
        parser = protocol.QueryParser()
        query = parser.parse(self.DEFAULT_RECORD)
        self.assertEqual('0', query.version)
        self.assertEqual(self.VARIABLES, query.variables)
        self.assertEqual(self.DATA, query.payload)

    def test_custom_suffix_nodot(self):
        parser = protocol.QueryParser(fqdn_suffix='illinois.edu')
        query = parser.parse(self.CUSTOM_RECORD)
        self.assertEqual('0', query.version)
        self.assertEqual(self.VARIABLES, query.variables)
        self.assertEqual(self.DATA, query.payload)

    def test_custom_suffix_begindot(self):
        parser = protocol.QueryParser(fqdn_suffix='.illinois.edu')
        query = parser.parse(self.CUSTOM_RECORD)
        self.assertEqual('0', query.version)
        self.assertEqual(self.VARIABLES, query.variables)
        self.assertEqual(self.DATA, query.payload)

    def test_custom_suffix_enddot(self):
        parser = protocol.QueryParser(fqdn_suffix='illinois.edu.')
        query = parser.parse(self.CUSTOM_RECORD)
        self.assertEqual('0', query.version)
        self.assertEqual(self.VARIABLES, query.variables)
        self.assertEqual(self.DATA, query.payload)

    def test_flags(self):
        parser = protocol.QueryParser()
        record = dnsrecord.DnsRecord('ac.' + self.DEFAULT_RECORD.fqdn,
                                     *self.DEFAULT_RECORD[1:])
        expected_vars = self.VARIABLES
        expected_vars['ac'] = True
        query = parser.parse(record)
        self.assertEqual('0', query.version)
        self.assertEqual(expected_vars, query.variables)
        self.assertEqual(self.DATA, query.payload)
Beispiel #9
0
 def test_error(self):
     error_payload = util.DataChunk(b'E\x0a', 0)
     query = protocol.Query.create('0', self.OPEN_TICKET_VARS,
                                   error_payload)
     self.assertEqual(10, query.error)
     query = protocol.Query.create('0', self.REQUEST_DATA_VARS,
                                   error_payload)
     self.assertEqual(10, query.error)
     query = protocol.Query.create('0', self.CHECK_REQUEST_VARS,
                                   error_payload)
     self.assertEqual(10, query.error)
     query = protocol.Query.create('0', self.FETCH_RESPONSE_VARS,
                                   error_payload)
     self.assertEqual(10, query.error)
     query = protocol.Query.create('0', self.CLOSE_TICKET_VARS,
                                   error_payload)
     self.assertEqual(10, query.error)
def chunk_to_ipv4(chunk):
    if not isinstance(chunk, util.DataChunk):
        chunk = util.DataChunk(*chunk)
    length = len(chunk.data)
    if length <= 0:
        raise ValueError('length must be at least 1')
    elif length > 3:
        raise ValueError('cannot encode chunks longer than 3 bytes')
    elif chunk.offset % 3 != 0:
        raise ValueError('chunk offset must be multiples of 3')
    elif chunk.offset < 0:
        raise ValueError('chunk offset cannot be negative')
    elif chunk.offset // 3 >= 0x3f:
        raise ValueError('chunk offset cannot exceed {}'.format(0x3f))
    return '{}.{}.{}.{}'.format((length << 6) + (chunk.offset // 3),
                                chunk.data[0],
                                chunk.data[1] if length >= 2 else 255,
                                chunk.data[2] if length == 3 else 255)
Beispiel #11
0
 def test_type_deduction_unknown_version(self):
     with self.assertRaises(protocol.UnknownVersionError):
         # Version 1 is not known to the implementation
         protocol.QueryType.deduce('1', self.OPEN_TICKET_VARS,
                                   util.DataChunk(b'\x00', 0))