use correct SID in Jingle FT to compute hostname of SOCKS5 connection. Fixes #8703

This commit is contained in:
Yann Leboulanger 2017-08-16 15:27:35 +02:00
parent 4f4a58e51a
commit 21e144d89d
8 changed files with 54 additions and 64 deletions

View File

@ -2328,6 +2328,7 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
si = self.stanza.getTag('si')
self.file_props = FilesProp.getNewFileProp(self.conn.name,
si.getAttr('id'))
self.file_props.transport_sid = self.file_props.sid
profile = si.getAttr('profile')
if profile != nbxmpp.NS_FILE:
self.conn.send_file_rejection(self.file_props, code='400',

View File

@ -171,6 +171,7 @@ class ConnectionJingle(object):
file_props=file_props,
use_security=use_security,
senders=senders)
file_props.transport_sid = transport.sid
file_props.algo = self.__hash_support(contact)
jingle.add_content('file' + helpers.get_random_string_16(), c)
jingle.start_session()

View File

@ -237,8 +237,9 @@ class JingleFileTransfer(JingleContent):
if self.use_security:
fingerprint = 'client'
if self.transport.type_ == TransportType.SOCKS5:
sid = self.file_props.transport_sid
gajim.socks5queue.connect_to_hosts(self.session.connection.name,
self.file_props.sid,
sid,
self.on_connect,
self._on_connect_error,
fingerprint=fingerprint,
@ -286,7 +287,7 @@ class JingleFileTransfer(JingleContent):
self.__state_changed(State.TRANSFERING)
raise nbxmpp.NodeProcessed
else:
args = {'cand_error' : True}
args = {'candError' : True}
self.__state_changed(State.CAND_RECEIVED, args)
return
if cand_used:

View File

@ -53,10 +53,8 @@ class StateInitialized(JingleFileTransferStates):
fingerprint = 'client'
# Connect to the candidate host, on success call on_connect method
gajim.socks5queue.connect_to_hosts(self.jft.session.connection.name,
self.jft.file_props.sid,
self.jft.on_connect,
self.jft._on_connect_error,
fingerprint=fingerprint)
self.jft.file_props.transport_sid, self.jft.on_connect,
self.jft._on_connect_error, fingerprint=fingerprint)
class StateCandSent(JingleFileTransferStates):
@ -156,11 +154,11 @@ class StateTransfering(JingleFileTransferStates):
if self.jft.is_our_candidate_used():
mode = 'client'
streamhost_used = self.jft.nominated_cand['our-cand']
gajim.socks5queue.remove_server(self.jft.file_props.sid)
gajim.socks5queue.remove_server(self.jft.file_props.transport_sid)
else:
mode = 'server'
streamhost_used = self.jft.nominated_cand['peer-cand']
gajim.socks5queue.remove_client(self.jft.file_props.sid)
gajim.socks5queue.remove_client(self.jft.file_props.transport_sid)
# our_cand = self.jft.nominated_cand['our-cand']
# gajim.socks5queue.remove_receiver(our_cand['idx'])
if streamhost_used['type'] == 'proxy':
@ -187,7 +185,7 @@ class StateTransfering(JingleFileTransferStates):
else:
raise TypeError
self.jft.file_props.streamhost_used = True
streamhost_used['sid'] = self.jft.file_props.sid
streamhost_used['sid'] = self.jft.file_props.transport_sid
self.jft.file_props.streamhosts = []
self.jft.file_props.streamhosts.append(streamhost_used)
self.jft.file_props.proxyhosts = []
@ -203,9 +201,8 @@ class StateTransfering(JingleFileTransferStates):
file_props=self.jft.file_props)
else:
sockobj = Socks5ReceiverClient(gajim.idlequeue, streamhost_used,
sid=self.jft.file_props.sid,
file_props=self.jft.file_props,
fingerprint=None)
transport_sid=self.jft.file_props.transport_sid,
file_props=self.jft.file_props, fingerprint=None)
sockobj.proxy = True
sockobj.streamhost = streamhost_used
gajim.socks5queue.add_sockobj(self.jft.session.connection.name,
@ -214,8 +211,8 @@ class StateTransfering(JingleFileTransferStates):
# If we offered the nominated candidate used, we activate
# the proxy
if not self.jft.is_our_candidate_used():
gajim.socks5queue.on_success[self.jft.file_props.sid] = \
self.jft.transport._on_proxy_auth_ok
gajim.socks5queue.on_success[self.jft.file_props.transport_sid]\
= self.jft.transport._on_proxy_auth_ok
# TODO: add on failure
else:
jid = gajim.get_jid_without_resource(self.jft.session.ourjid)

View File

@ -415,7 +415,6 @@ class JingleSession:
self.contents[(creator, name)].state = State.TRANSPORT_REPLACE
self.__ack(stanza, jingle, error, action)
self.__session_accept()
self.contents[(creator, name)].start_IBB_transfer()
else:
stanza, jingle = self.__make_jingle('transport-reject')
content = jingle.setTag('content', attrs={'creator': creator,

View File

@ -678,7 +678,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
return
frm = self._ft_get_from(iq_obj)
id_ = real_id[3:]
file_props = FilesProp.getFilePropBySid(id_)
file_props = FilesProp.getFilePropByTransportSid(self.name, id_)
if file_props.streamhost_used:
for host in file_props.proxyhosts:
if host['initiator'] == frm and 'idx' in host:

View File

@ -102,21 +102,21 @@ class SocksQueue:
if file_props.streamhost_used == True:
for proxy in file_props.proxyhosts:
if proxy['host'] == streamhost['host']:
self.on_success[file_props.sid](proxy)
self.on_success[file_props.transport_sid](proxy)
return 1
return 0
for host in file_props.streamhosts:
if streamhost['state'] == 1:
return 0
streamhost['state'] = 1
self.on_success[file_props.sid](streamhost)
self.on_success[file_props.transport_sid](streamhost)
return 1
def connect_to_hosts(self, account, sid, on_success=None, on_failure=None,
fingerprint=None, receiving=True):
self.on_success[sid] = on_success
self.on_failure[sid] = on_failure
file_props = FilesProp.getFileProp(account, sid)
def connect_to_hosts(self, account, transport_sid, on_success=None,
on_failure=None, fingerprint=None, receiving=True):
self.on_success[transport_sid] = on_success
self.on_failure[transport_sid] = on_failure
file_props = FilesProp.getFilePropByTransportSid(account, transport_sid)
file_props.failure_cb = on_failure
streamhosts_to_test = []
# Remove local IPs to not connect to ourself
@ -125,7 +125,7 @@ class SocksQueue:
continue
streamhosts_to_test.append(streamhost)
if not streamhosts_to_test:
on_failure(file_props.sid)
on_failure(file_props.transport_sid)
# add streamhosts to the queue
for streamhost in streamhosts_to_test:
if 'type' in streamhost and streamhost['type'] == 'proxy':
@ -141,7 +141,7 @@ class SocksQueue:
streamhost['jid'])
file_props.type_ = 'r'
socks5obj = Socks5ReceiverClient(self.idlequeue, streamhost,
sid, file_props, fingerprint=fp)
transport_sid, file_props, fingerprint=fp)
self.add_sockobj(account, socks5obj)
else:
if 'candidate_id' in streamhost:
@ -223,7 +223,7 @@ class SocksQueue:
host['state'] = 0
# FIXME: make the sender reconnect also
client = Socks5ReceiverClient(self.idlequeue, host,
host['sid'], file_props)
client.sid, file_props)
self.add_sockobj(client.account, client)
host['idx'] = client.queue_idx
# we still have chances to connect
@ -256,7 +256,7 @@ class SocksQueue:
self.readers = {}
# failure_cb exists - this means that it has never been called
if file_props.failure_cb:
file_props.failure_cb(file_props.sid)
file_props.failure_cb(file_props.transport_sid)
file_props.failure_cb = None
def add_sockobj(self, account, sockobj):
@ -284,7 +284,7 @@ class SocksQueue:
'''
Adds the sockobj to the current list of sockobjects
'''
keys = (file_props.sid, file_props.name, hash_)
keys = (file_props.transport_sid, file_props.name, hash_)
sockobjects[keys] = sockobj
def result_sha(self, sha_str, idx):
@ -320,13 +320,7 @@ class SocksQueue:
def send_file(self, file_props, account, mode):
for key in self.senders.keys():
if self.senders == {}:
# Python acts very weird with this. When there is no keys
# in the dictionary It says that it has a key.
# Maybe it is my machine. Without this there is a KeyError
# traceback.
return
if file_props.name in key and file_props.sid in key \
if file_props.name in key and file_props.transport_sid in key \
and self.senders[key].mode == mode:
log.info('socks5: sending file')
sender = self.senders[key]
@ -364,8 +358,8 @@ class SocksQueue:
sh['initiator'] = None
sh['target'] = None
sockobj = Socks5ReceiverServer(idlequeue=self.idlequeue,
streamhost=sh,sid=None, file_props=listener.file_props,
fingerprint=None)
streamhost=sh,transport_sid=None,
file_props=listener.file_props, fingerprint=None)
self._add(sockobj, self.readers, listener.file_props, sock_hash)
sockobj.set_sock(sock[0])
@ -440,19 +434,19 @@ class SocksQueue:
self.listener = None
self.connected -= 1
def remove_by_mode(self, sid, mode, do_disconnect=True):
def remove_by_mode(self, transport_sid, mode, do_disconnect=True):
for (key, sock) in self.senders.copy().items():
if key[0] == sid and sock.mode == mode:
if key[0] == transport_sid and sock.mode == mode:
self.remove_sender_by_key(key)
for (key, sock) in self.readers.copy().items():
if key[0] == sid and sock.mode == mode:
if key[0] == transport_sid and sock.mode == mode:
self.remove_receiver_by_key(key)
def remove_server(self, sid, do_disconnect=True):
self.remove_by_mode(sid, 'server')
def remove_server(self, transport_sid, do_disconnect=True):
self.remove_by_mode(transport_sid, 'server')
def remove_client(self, sid, do_disconnect=True):
self.remove_by_mode(sid, 'client')
def remove_client(self, transport_sid, do_disconnect=True):
self.remove_by_mode(transport_sid, 'client')
class Socks5(object):
def __init__(self, idlequeue, host, port, initiator, target, sid):
@ -838,15 +832,10 @@ class Socks5(object):
"""
Parse the initial message and create a list of auth mechanisms
"""
auth_mechanisms = []
try:
num_auth = struct.unpack('!xB', buff[:2])[0]
for i in range(num_auth):
mechanism, = struct.unpack('!B', buff[1 + i])
auth_mechanisms.append(mechanism)
except Exception:
if buff[0] != 5:
return None
return auth_mechanisms
num_auth = buff[1]
return list(buff[2:2+num_auth])
def _get_auth_response(self):
"""
@ -882,7 +871,7 @@ class Socks5(object):
host, = '.'.join(str(s) for s in host_arr)
host_len = len(host)
elif host_type == 0x03:
host_len, = struct.unpack('!B', buff[4])
host_len = buff[4]
host, = struct.unpack('!%ds' % host_len, buff[5:5 + host_len])
portlen = len(buff[host_len + 5:])
if portlen == 1:
@ -1031,6 +1020,7 @@ class Socks5Receiver(IdleObject):
self.connect_timeout = 0
self.connected = False
self.pauses = 0
self.sid = sid
self.file_props = file_props
self.file_props.disconnect_cb = self.disconnect
self.file_props.error = 0
@ -1349,7 +1339,7 @@ class Socks5SenderClient(Socks5Client, Socks5Sender):
port=None, fingerprint = None, connected=True, file_props=None,
initiator=None, target=None):
Socks5Client.__init__(self, idlequeue, host, port, initiator, target,
file_props.sid)
file_props.transport_sid)
Socks5Sender.__init__(self,idlequeue, sock_hash, parent,_sock,
host, port, fingerprint , connected, file_props)
@ -1359,30 +1349,30 @@ class Socks5SenderServer(Socks5Server, Socks5Sender):
def __init__(self, idlequeue, sock_hash, parent,_sock, host=None,
port=None, fingerprint = None, connected=True, file_props=None):
Socks5Server.__init__(self, idlequeue, host, port, None, None,
file_props.sid)
file_props.transport_sid)
Socks5Sender.__init__(self,idlequeue, sock_hash, parent, _sock,
host, port, fingerprint , connected, file_props)
class Socks5ReceiverClient(Socks5Client, Socks5Receiver):
def __init__(self, idlequeue, streamhost, sid, file_props=None,
def __init__(self, idlequeue, streamhost, transport_sid, file_props=None,
fingerprint=None):
Socks5Client.__init__(self, idlequeue, streamhost['host'],
int(streamhost['port']), streamhost['initiator'],
streamhost['target'], sid)
Socks5Receiver.__init__(self, idlequeue, streamhost, sid, file_props,
fingerprint)
streamhost['target'], transport_sid)
Socks5Receiver.__init__(self, idlequeue, streamhost, transport_sid,
file_props, fingerprint)
class Socks5ReceiverServer(Socks5Server, Socks5Receiver):
def __init__(self, idlequeue, streamhost, sid, file_props=None,
def __init__(self, idlequeue, streamhost, transport_sid, file_props=None,
fingerprint=None):
Socks5Server.__init__(self, idlequeue, streamhost['host'],
int(streamhost['port']), streamhost['initiator'],
streamhost['target'], sid)
Socks5Receiver.__init__(self, idlequeue, streamhost, sid, file_props,
fingerprint)
streamhost['target'], transport_sid)
Socks5Receiver.__init__(self, idlequeue, streamhost, transport_sid,
file_props, fingerprint)
class Socks5Listener(IdleObject):

View File

@ -365,6 +365,7 @@ class FileTransfersWindow:
self.add_transfer(account, contact, file_props)
else:
log.info("contact does not support jingle file transfer")
file_props.transport_sid = file_props.sid
gajim.connections[account].send_file_request(file_props)
self.add_transfer(account, contact, file_props)
return True