diff --git a/src/common/jingle.py b/src/common/jingle.py index 0ee21e28e..c98a3ed3e 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -48,7 +48,7 @@ class ConnectionJingle(object): def __init__(self): # dictionary: sessionid => JingleSession object - self.__sessions = {} + self.__sessions__ = {} # dictionary: (jid, iq stanza id) => JingleSession object, # one time callbacks @@ -58,12 +58,12 @@ class ConnectionJingle(object): """ Remove a jingle session from a jingle stanza dispatcher """ - if sid in self.__sessions: + if sid in self.__sessions__: #FIXME: Move this elsewhere? - for content in self.__sessions[sid].contents.values(): + for content in self.__sessions__[sid].contents.values(): content.destroy() - self.__sessions[sid].callbacks = [] - del self.__sessions[sid] + self.__sessions__[sid].callbacks = [] + del self.__sessions__[sid] def _JingleCB(self, con, stanza): """ @@ -91,23 +91,23 @@ class ConnectionJingle(object): sid = jingle.getAttr('sid') else: sid = None - for sesn in self.__sessions.values(): + for sesn in self.__sessions__.values(): if id in sesn.iq_ids: sesn.on_stanza(stanza) return # do we need to create a new jingle object - if sid not in self.__sessions: + if sid not in self.__sessions__: #TODO: tie-breaking and other things... newjingle = JingleSession(con=self, weinitiate=False, jid=jid, iq_id = id, sid=sid) - self.__sessions[sid] = newjingle + self.__sessions__[sid] = newjingle # we already have such session in dispatcher... - self.__sessions[sid].collect_iq_id(id) - self.__sessions[sid].on_stanza(stanza) + self.__sessions__[sid].collect_iq_id(id) + self.__sessions__[sid].on_stanza(stanza) # Delete invalid/unneeded sessions - if sid in self.__sessions and self.__sessions[sid].state == JingleStates.ended: + if sid in self.__sessions__ and self.__sessions__[sid].state == JingleStates.ended: self.delete_jingle_session(sid) raise xmpp.NodeProcessed @@ -120,7 +120,7 @@ class ConnectionJingle(object): jingle.add_content('voice', JingleAudio(jingle)) else: jingle = JingleSession(self, weinitiate=True, jid=jid) - self.__sessions[jingle.sid] = jingle + self.__sessions__[jingle.sid] = jingle jingle.add_content('voice', JingleAudio(jingle)) jingle.start_session() return jingle.sid @@ -133,7 +133,7 @@ class ConnectionJingle(object): jingle.add_content('video', JingleVideo(jingle)) else: jingle = JingleSession(self, weinitiate=True, jid=jid) - self.__sessions[jingle.sid] = jingle + self.__sessions__[jingle.sid] = jingle jingle.add_content('video', JingleVideo(jingle)) jingle.start_session() return jingle.sid @@ -150,24 +150,25 @@ class ConnectionJingle(object): file_props['sid'] = jingle.sid c = JingleFileTransfer(jingle, file_props=file_props, use_security=use_security) - jingle.add_content('file', c) + jingle.add_content('file' + helpers.get_random_string_16(), c) + jingle.on_session_state_changed(c) else: jingle = JingleSession(self, weinitiate=True, jid=jid) - self.__sessions[jingle.sid] = jingle + self.__sessions__[jingle.sid] = jingle file_props['sid'] = jingle.sid c = JingleFileTransfer(jingle, file_props=file_props, use_security=use_security) - jingle.add_content('file', c) + jingle.add_content('file' + helpers.get_random_string_16(), c) jingle.start_session() return c.transport.sid def iter_jingle_sessions(self, jid, sid=None, media=None): if sid: - return (session for session in self.__sessions.values() if session.sid == sid) - sessions = (session for session in self.__sessions.values() if session.peerjid == jid) + return (session for session in self.__sessions__.values() if session.sid == sid) + sessions = (session for session in self.__sessions__.values() if session.peerjid == jid) if media: - if media not in ('audio', 'video'): + if media not in ('audio', 'video', 'file'): return tuple() else: return (session for session in sessions if session.get_content(media)) @@ -177,14 +178,14 @@ class ConnectionJingle(object): def get_jingle_session(self, jid, sid=None, media=None): if sid: - if sid in self.__sessions: - return self.__sessions[sid] + if sid in self.__sessions__: + return self.__sessions__[sid] else: return None elif media: - if media not in ('audio', 'video'): + if media not in ('audio', 'video', 'file'): return None - for session in self.__sessions.values(): + for session in self.__sessions__.values(): if session.peerjid == jid and session.get_content(media): return session diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 647819383..89c261e2e 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -44,6 +44,7 @@ class JingleFileTransfer(JingleContent): # events we might be interested in self.callbacks['session-initiate'] += [self.__on_session_initiate] + self.callbacks['content-add'] += [self.__on_session_initiate] self.callbacks['session-accept'] += [self.__on_session_accept] self.callbacks['session-terminate'] += [self.__on_session_terminate] self.callbacks['transport-accept'] += [self.__on_transport_accept] @@ -249,7 +250,7 @@ class JingleFileTransfer(JingleContent): content = xmpp.Node('content') content.setAttr('creator', 'initiator') - content.setAttr('name', 'file') + content.setAttr('name', self.name) transport = xmpp.Node('transport') transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM) diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index 7a1bcc2c8..7124e7b33 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -85,14 +85,14 @@ class JingleSession(object): if not sid: sid = con.connection.getAnID() self.sid = sid # sessionid - + # iq stanza id, used to determine which sessions to summon callback # later on when iq-result stanza arrives if iq_id is not None: self.iq_ids = [iq_id] else: self.iq_ids = [] - + self.accepted = True # is this session accepted by user @@ -127,7 +127,7 @@ class JingleSession(object): def collect_iq_id(self, iq_id): if iq_id is not None: self.iq_ids.append(iq_id) - + def approve_session(self): """ Called when user accepts session in UI (when we aren't the initiator) @@ -340,7 +340,7 @@ class JingleSession(object): break elif child.getNamespace() == xmpp.NS_STANZAS: error_name = child.getName() - self.__dispatch_error(error_name, text, error.getAttribute('type')) + self.__dispatch_error(error_name, text, error.getAttr('type')) # FIXME: Not sure when we would want to do that... def __on_transport_replace(self, stanza, jingle, error, action): @@ -482,13 +482,13 @@ class JingleSession(object): # for cn in self.contents.values(): # cn.on_stanza(stanza, None, error, action) # return - + # special case: iq-result stanza does not come with a jingle element if action == 'iq-result': for cn in self.contents.values(): cn.on_stanza(stanza, None, error, action) return - + for content in jingle.iterTags('content'): name = content['name'] creator = content['creator'] @@ -673,7 +673,8 @@ class JingleSession(object): stanza, jingle = self.__make_jingle('content-add') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-add-sent') - self.connection.connection.send(stanza) + id_ = self.connection.connection.send(stanza) + self.collect_iq_id(id_) def __content_accept(self, content): # TODO: test @@ -681,7 +682,8 @@ class JingleSession(object): stanza, jingle = self.__make_jingle('content-accept') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-accept-sent') - self.connection.connection.send(stanza) + id_ = self.connection.connection.send(stanza) + self.collect_iq_id(id_) def __content_reject(self, content): assert self.state != JingleStates.ended diff --git a/src/common/jingle_transport.py b/src/common/jingle_transport.py index 04b3da912..ff47a7c23 100644 --- a/src/common/jingle_transport.py +++ b/src/common/jingle_transport.py @@ -224,6 +224,13 @@ class JingleTransportSocks5(JingleTransport): proxy_cand.append(c) self.candidates += proxy_cand + def get_content(self): + sesn = self.connection.get_jingle_session(self.ourjid, + self.file_props['session-sid']) + for content in sesn.contents.values(): + if content.transport == self: + return content + def _on_proxy_auth_ok(self, proxy): log.info('proxy auth ok for ' + str(proxy)) # send activate request to proxy, send activated confirmation to peer @@ -242,15 +249,15 @@ class JingleTransportSocks5(JingleTransport): content = xmpp.Node('content') content.setAttr('creator', 'initiator') - content.setAttr('name', 'file') + c = self.get_content() + content.setAttr('name', c.name) transport = xmpp.Node('transport') transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM) activated = xmpp.Node('activated') cid = None for host in self.candidates: - if host['host'] == proxy['host'] and \ - host['jid'] == proxy['jid'] and \ - host['port'] == proxy['port']: + if host['host'] == proxy['host'] and host['jid'] == proxy['jid'] \ + and host['port'] == proxy['port']: cid = host['candidate_id'] break if cid is None: diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index 3aee03a9d..e36527158 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -29,7 +29,7 @@ pending_sessions = {} # key-exchange id -> session, accept that session once key def key_exchange_pend(id, session): pending_sessions[id] = session - + def approve_pending_session(id): session = pending_sessions[id] session.approve_session() @@ -45,9 +45,11 @@ if PYOPENSSL_PRESENT: from OpenSSL import SSL from OpenSSL.SSL import Context from OpenSSL import crypto + TYPE_RSA = crypto.TYPE_RSA + TYPE_DSA = crypto.TYPE_DSA SELF_SIGNED_CERTIFICATE = 'localcert' - + def default_callback(connection, certificate, error_num, depth, return_code): log.info("certificate: %s" % certificate) return return_code @@ -95,7 +97,7 @@ def get_context(fingerprint, verify_cb=None): ctx.set_verify(SSL.VERIFY_NONE|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb or default_callback) elif fingerprint == 'client': ctx.set_verify(SSL.VERIFY_PEER, verify_cb or default_callback) - + cert_name = os.path.join(gajim.MY_CERT_DIR, SELF_SIGNED_CERTIFICATE) ctx.use_privatekey_file (cert_name + '.pkey') ctx.use_certificate_file(cert_name + '.cert') @@ -114,16 +116,16 @@ def send_cert(con, jid_from, sid): certificate += line iq = common.xmpp.Iq('result', to=jid_from); iq.setAttr('id', sid) - + pubkey = iq.setTag('pubkeys') pubkey.setNamespace(common.xmpp.NS_PUBKEY_PUBKEY) - + keyinfo = pubkey.setTag('keyinfo') name = keyinfo.setTag('name') name.setData('CertificateHash') cert = keyinfo.setTag('x509cert') cert.setData(certificate) - + con.send(iq) def handle_new_cert(con, obj, jid_from): @@ -132,18 +134,18 @@ def handle_new_cert(con, obj, jid_from): certpath += '.cert' id = obj.getAttr('id') - + x509cert = obj.getTag('pubkeys').getTag('keyinfo').getTag('x509cert') - + cert = x509cert.getData() - - f = open(certpath, 'w') + + f = open(certpath, 'w') f.write('-----BEGIN CERTIFICATE-----\n') f.write(cert) f.write('-----END CERTIFICATE-----\n') - + approve_pending_session(id) - + def send_cert_request(con, to_jid): iq = common.xmpp.Iq('get', to=to_jid) id = con.connection.getAnID() @@ -155,9 +157,6 @@ def send_cert_request(con, to_jid): # the following code is partly due to pyopenssl examples -TYPE_RSA = crypto.TYPE_RSA -TYPE_DSA = crypto.TYPE_DSA - def createKeyPair(type, bits): """ Create a public/private key pair. diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 0fa7a361e..3dca76e51 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -148,7 +148,8 @@ class ConnectionBytestream: jingle_xtls.key_exchange_pend(id_, session) return session.approve_session() - session.approve_content('file') + + session.approve_content('file') return iq = xmpp.Iq(to=unicode(file_props['sender']), typ='result') diff --git a/src/common/socks5.py b/src/common/socks5.py index e735f7ac5..6dc70f955 100644 --- a/src/common/socks5.py +++ b/src/common/socks5.py @@ -914,7 +914,7 @@ class Socks5Listener(IdleObject): # try the different possibilities (ipv6, ipv4, etc.) try: self._serv = socket.socket(*ai[:3]) - if not self.fingerprint is None: + if self.fingerprint is not None: self._serv = OpenSSL.SSL.Connection( jingle_xtls.get_context('server'), self._serv) except socket.error, e: