both sender and receiver request remote SSL certificate, but only if it's a new one.
Correctly verify remote SSL certificate.
This commit is contained in:
parent
6e410b463b
commit
df11617ddb
8 changed files with 141 additions and 58 deletions
|
@ -2053,8 +2053,11 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
||||||
self.fjid = self.conn._ft_get_from(self.stanza)
|
self.fjid = self.conn._ft_get_from(self.stanza)
|
||||||
self.jid = gajim.get_jid_without_resource(self.fjid)
|
self.jid = gajim.get_jid_without_resource(self.fjid)
|
||||||
if self.jingle_content:
|
if self.jingle_content:
|
||||||
self.FT_content.use_security = bool(self.jingle_content.getTag(
|
secu = self.jingle_content.getTag('security')
|
||||||
'security'))
|
self.FT_content.use_security = bool(secu)
|
||||||
|
fingerprint = secu.getTag('fingerprint')
|
||||||
|
if fingerprint:
|
||||||
|
self.FT_content.x509_fingerprint = fingerprint.getData()
|
||||||
if not self.FT_content.transport:
|
if not self.FT_content.transport:
|
||||||
self.FT_content.transport = JingleTransportSocks5()
|
self.FT_content.transport = JingleTransportSocks5()
|
||||||
self.FT_content.transport.set_our_jid(
|
self.FT_content.transport.set_our_jid(
|
||||||
|
|
|
@ -17,9 +17,12 @@
|
||||||
Handles Jingle contents (XEP 0166)
|
Handles Jingle contents (XEP 0166)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from common import gajim
|
from common import gajim
|
||||||
import nbxmpp
|
import nbxmpp
|
||||||
from common.jingle_transport import JingleTransportIBB
|
from common.jingle_transport import JingleTransportIBB
|
||||||
|
from jingle_xtls import SELF_SIGNED_CERTIFICATE
|
||||||
|
from jingle_xtls import load_cert_file
|
||||||
|
|
||||||
contents = {}
|
contents = {}
|
||||||
|
|
||||||
|
@ -213,12 +216,18 @@ class JingleContent(object):
|
||||||
if self.use_security:
|
if self.use_security:
|
||||||
security = nbxmpp.simplexml.Node(
|
security = nbxmpp.simplexml.Node(
|
||||||
tag=nbxmpp.NS_JINGLE_XTLS + ' security')
|
tag=nbxmpp.NS_JINGLE_XTLS + ' security')
|
||||||
# TODO: add fingerprint element
|
certpath = os.path.join(gajim.MY_CERT_DIR, SELF_SIGNED_CERTIFICATE)\
|
||||||
for m in ('x509', ): # supported authentication methods
|
+ '.cert'
|
||||||
method = nbxmpp.simplexml.Node(tag='method')
|
cert = load_cert_file(certpath)
|
||||||
method.setAttr('name', m)
|
if cert:
|
||||||
security.addChild(node=method)
|
digest_algo = cert.get_signature_algorithm().split('With')[0]
|
||||||
content.addChild(node=security)
|
security.addChild('fingerprint').addData(cert.digest(
|
||||||
|
digest_algo))
|
||||||
|
for m in ('x509', ): # supported authentication methods
|
||||||
|
method = nbxmpp.simplexml.Node(tag='method')
|
||||||
|
method.setAttr('name', m)
|
||||||
|
security.addChild(node=method)
|
||||||
|
content.addChild(node=security)
|
||||||
content.addChild(node=description_node)
|
content.addChild(node=description_node)
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
|
|
|
@ -22,6 +22,7 @@ Handles Jingle File Transfer (XEP 0234)
|
||||||
import hashlib
|
import hashlib
|
||||||
from common import gajim
|
from common import gajim
|
||||||
import nbxmpp
|
import nbxmpp
|
||||||
|
import jingle_xtls
|
||||||
from common.jingle_content import contents, JingleContent
|
from common.jingle_content import contents, JingleContent
|
||||||
from common.jingle_transport import *
|
from common.jingle_transport import *
|
||||||
from common import helpers
|
from common import helpers
|
||||||
|
@ -68,6 +69,7 @@ class JingleFileTransfer(JingleContent):
|
||||||
self.callbacks['transport-info'] += [self.__on_transport_info]
|
self.callbacks['transport-info'] += [self.__on_transport_info]
|
||||||
self.callbacks['iq-result'] += [self.__on_iq_result]
|
self.callbacks['iq-result'] += [self.__on_iq_result]
|
||||||
self.use_security = use_security
|
self.use_security = use_security
|
||||||
|
self.x509_fingerprint = None
|
||||||
self.file_props = file_props
|
self.file_props = file_props
|
||||||
self.weinitiate = self.session.weinitiate
|
self.weinitiate = self.session.weinitiate
|
||||||
self.werequest = self.session.werequest
|
self.werequest = self.session.werequest
|
||||||
|
@ -165,17 +167,37 @@ class JingleFileTransfer(JingleContent):
|
||||||
h.addHash(hash_, self.file_props.algo)
|
h.addHash(hash_, self.file_props.algo)
|
||||||
return h
|
return h
|
||||||
|
|
||||||
|
def on_cert_received(self):
|
||||||
|
self.session.approve_session()
|
||||||
|
self.session.approve_content('file', name=self.name)
|
||||||
|
|
||||||
def __on_session_accept(self, stanza, content, error, action):
|
def __on_session_accept(self, stanza, content, error, action):
|
||||||
log.info("__on_session_accept")
|
log.info("__on_session_accept")
|
||||||
con = self.session.connection
|
con = self.session.connection
|
||||||
|
# We ack the session accept
|
||||||
|
response = stanza.buildReply('result')
|
||||||
|
response.delChild(response.getQuery())
|
||||||
|
con.connection.send(response)
|
||||||
security = content.getTag('security')
|
security = content.getTag('security')
|
||||||
if not security: # responder can not verify our fingerprint
|
if not security: # responder can not verify our fingerprint
|
||||||
self.use_security = False
|
self.use_security = False
|
||||||
|
else:
|
||||||
|
fingerprint = security.getTag('fingerprint')
|
||||||
|
if fingerprint:
|
||||||
|
fingerprint = fingerprint.getData()
|
||||||
|
self.x509_fingerprint = fingerprint
|
||||||
|
if not jingle_xtls.check_cert(gajim.get_jid_without_resource(
|
||||||
|
self.session.responder), fingerprint):
|
||||||
|
id_ = jingle_xtls.send_cert_request(con,
|
||||||
|
self.session.responder)
|
||||||
|
jingle_xtls.key_exchange_pend(id_,
|
||||||
|
self.continue_session_accept, [stanza])
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
self.continue_session_accept(stanza)
|
||||||
|
|
||||||
|
def continue_session_accept(self, stanza):
|
||||||
|
con = self.session.connection
|
||||||
if self.state == STATE_TRANSPORT_REPLACE:
|
if self.state == STATE_TRANSPORT_REPLACE:
|
||||||
# We ack the session accept
|
|
||||||
response = stanza.buildReply('result')
|
|
||||||
response.delChild(response.getQuery())
|
|
||||||
con.connection.send(response)
|
|
||||||
# If we are requesting we don't have the file
|
# If we are requesting we don't have the file
|
||||||
if self.session.werequest:
|
if self.session.werequest:
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
@ -186,16 +208,13 @@ class JingleFileTransfer(JingleContent):
|
||||||
# Calculate file hash in a new thread
|
# Calculate file hash in a new thread
|
||||||
# if we haven't sent the hash already.
|
# if we haven't sent the hash already.
|
||||||
if self.file_props.hash_ is None and self.file_props.algo and \
|
if self.file_props.hash_ is None and self.file_props.algo and \
|
||||||
not self.werequest:
|
not self.werequest:
|
||||||
self.hashThread = threading.Thread(target=self.__send_hash)
|
self.hashThread = threading.Thread(target=self.__send_hash)
|
||||||
self.hashThread.start()
|
self.hashThread.start()
|
||||||
for host in self.file_props.streamhosts:
|
for host in self.file_props.streamhosts:
|
||||||
host['initiator'] = self.session.initiator
|
host['initiator'] = self.session.initiator
|
||||||
host['target'] = self.session.responder
|
host['target'] = self.session.responder
|
||||||
host['sid'] = self.file_props.sid
|
host['sid'] = self.file_props.sid
|
||||||
response = stanza.buildReply('result')
|
|
||||||
response.delChild(response.getQuery())
|
|
||||||
con.connection.send(response)
|
|
||||||
fingerprint = None
|
fingerprint = None
|
||||||
if self.use_security:
|
if self.use_security:
|
||||||
fingerprint = 'client'
|
fingerprint = 'client'
|
||||||
|
@ -204,7 +223,7 @@ class JingleFileTransfer(JingleContent):
|
||||||
self.file_props.sid, self.on_connect,
|
self.file_props.sid, self.on_connect,
|
||||||
self._on_connect_error, fingerprint=fingerprint,
|
self._on_connect_error, fingerprint=fingerprint,
|
||||||
receiving=False)
|
receiving=False)
|
||||||
return
|
raise nbxmpp.NodeProcessed
|
||||||
self.__state_changed(STATE_TRANSFERING)
|
self.__state_changed(STATE_TRANSFERING)
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,8 @@ class JingleTransportSocks5(JingleTransport):
|
||||||
candidates.append(cand)
|
candidates.append(cand)
|
||||||
|
|
||||||
# we need this when we construct file_props on session-initiation
|
# we need this when we construct file_props on session-initiation
|
||||||
self.remote_candidates = candidates
|
if candidates:
|
||||||
|
self.remote_candidates = candidates
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,17 @@ log = logging.getLogger('gajim.c.jingle_xtls')
|
||||||
|
|
||||||
PYOPENSSL_PRESENT = False
|
PYOPENSSL_PRESENT = False
|
||||||
|
|
||||||
pending_contents = {} # key-exchange id -> session, accept that session once key-exchange completes
|
# key-exchange id -> [callback, args], accept that session once key-exchange completes
|
||||||
|
pending_contents = {}
|
||||||
|
|
||||||
def key_exchange_pend(id_, content):
|
def key_exchange_pend(id_, cb, args):
|
||||||
pending_contents[id_] = content
|
# args is a list
|
||||||
|
pending_contents[id_] = [cb, args]
|
||||||
|
|
||||||
def approve_pending_content(id_):
|
def approve_pending_content(id_):
|
||||||
content = pending_contents[id_]
|
cb = pending_contents[id_][0]
|
||||||
content.session.approve_session()
|
args = pending_contents[id_][1]
|
||||||
content.session.approve_content('file', name=content.name)
|
cb(*args)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import OpenSSL.SSL
|
import OpenSSL.SSL
|
||||||
|
@ -56,18 +58,18 @@ def default_callback(connection, certificate, error_num, depth, return_code):
|
||||||
log.info("certificate: %s" % certificate)
|
log.info("certificate: %s" % certificate)
|
||||||
return return_code
|
return return_code
|
||||||
|
|
||||||
def load_cert_file(cert_path, cert_store):
|
def load_cert_file(cert_path, cert_store=None):
|
||||||
"""
|
"""
|
||||||
This is almost identical to the one in nbxmpp.tls_nb
|
This is almost identical to the one in nbxmpp.tls_nb
|
||||||
"""
|
"""
|
||||||
if not os.path.isfile(cert_path):
|
if not os.path.isfile(cert_path):
|
||||||
return
|
return None
|
||||||
try:
|
try:
|
||||||
f = open(cert_path)
|
f = open(cert_path)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
log.warning('Unable to open certificate file %s: %s' % (cert_path,
|
log.warning('Unable to open certificate file %s: %s' % (cert_path,
|
||||||
str(e)))
|
str(e)))
|
||||||
return
|
return None
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
i = 0
|
i = 0
|
||||||
begin = -1
|
begin = -1
|
||||||
|
@ -79,7 +81,9 @@ def load_cert_file(cert_path, cert_store):
|
||||||
try:
|
try:
|
||||||
x509cert = OpenSSL.crypto.load_certificate(
|
x509cert = OpenSSL.crypto.load_certificate(
|
||||||
OpenSSL.crypto.FILETYPE_PEM, cert)
|
OpenSSL.crypto.FILETYPE_PEM, cert)
|
||||||
cert_store.add_cert(x509cert)
|
if cert_store:
|
||||||
|
cert_store.add_cert(x509cert)
|
||||||
|
return x509cert
|
||||||
except OpenSSL.crypto.Error as exception_obj:
|
except OpenSSL.crypto.Error as exception_obj:
|
||||||
log.warning('Unable to load a certificate from file %s: %s' %\
|
log.warning('Unable to load a certificate from file %s: %s' %\
|
||||||
(cert_path, exception_obj.args[0][0][2]))
|
(cert_path, exception_obj.args[0][0][2]))
|
||||||
|
@ -90,7 +94,7 @@ def load_cert_file(cert_path, cert_store):
|
||||||
i += 1
|
i += 1
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def get_context(fingerprint, verify_cb=None):
|
def get_context(fingerprint, verify_cb=None, remote_jid=None):
|
||||||
"""
|
"""
|
||||||
constructs and returns the context objects
|
constructs and returns the context objects
|
||||||
"""
|
"""
|
||||||
|
@ -130,22 +134,28 @@ def get_context(fingerprint, verify_cb=None):
|
||||||
% (default_dh_params_name, err))
|
% (default_dh_params_name, err))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
store = ctx.get_cert_store()
|
if remote_jid:
|
||||||
for f in os.listdir(os.path.expanduser(gajim.MY_PEER_CERTS_PATH)):
|
store = ctx.get_cert_store()
|
||||||
load_cert_file(os.path.join(os.path.expanduser(
|
path = os.path.join(os.path.expanduser(gajim.MY_PEER_CERTS_PATH),
|
||||||
gajim.MY_PEER_CERTS_PATH), f), store)
|
remote_jid) + '.cert'
|
||||||
log.debug('certificate file ' + f + ' loaded fingerprint ' + \
|
if os.path.exists(path):
|
||||||
fingerprint)
|
load_cert_file(path, cert_store=store)
|
||||||
|
log.debug('certificate file ' + path + ' loaded fingerprint ' + \
|
||||||
|
fingerprint)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
def send_cert(con, jid_from, sid):
|
def read_cert(certpath):
|
||||||
certpath = os.path.join(gajim.MY_CERT_DIR, SELF_SIGNED_CERTIFICATE) + \
|
|
||||||
'.cert'
|
|
||||||
certificate = ''
|
certificate = ''
|
||||||
with open(certpath, 'r') as certfile:
|
with open(certpath, 'r') as certfile:
|
||||||
for line in certfile.readlines():
|
for line in certfile.readlines():
|
||||||
if not line.startswith('-'):
|
if not line.startswith('-'):
|
||||||
certificate += line
|
certificate += line
|
||||||
|
return certificate
|
||||||
|
|
||||||
|
def send_cert(con, jid_from, sid):
|
||||||
|
certpath = os.path.join(gajim.MY_CERT_DIR, SELF_SIGNED_CERTIFICATE) + \
|
||||||
|
'.cert'
|
||||||
|
certificate = read_cert(certpath)
|
||||||
iq = nbxmpp.Iq('result', to=jid_from);
|
iq = nbxmpp.Iq('result', to=jid_from);
|
||||||
iq.setAttr('id', sid)
|
iq.setAttr('id', sid)
|
||||||
|
|
||||||
|
@ -175,9 +185,21 @@ def handle_new_cert(con, obj, jid_from):
|
||||||
f.write('-----BEGIN CERTIFICATE-----\n')
|
f.write('-----BEGIN CERTIFICATE-----\n')
|
||||||
f.write(cert)
|
f.write(cert)
|
||||||
f.write('-----END CERTIFICATE-----\n')
|
f.write('-----END CERTIFICATE-----\n')
|
||||||
|
f.close()
|
||||||
|
|
||||||
approve_pending_content(id_)
|
approve_pending_content(id_)
|
||||||
|
|
||||||
|
def check_cert(jid, fingerprint):
|
||||||
|
certpath = os.path.join(os.path.expanduser(gajim.MY_PEER_CERTS_PATH), jid)
|
||||||
|
certpath += '.cert'
|
||||||
|
if os.path.exists(certpath):
|
||||||
|
cert = load_cert_file(certpath)
|
||||||
|
if cert:
|
||||||
|
digest_algo = cert.get_signature_algorithm().split('With')[0]
|
||||||
|
if cert.digest(digest_algo) == fingerprint:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def send_cert_request(con, to_jid):
|
def send_cert_request(con, to_jid):
|
||||||
iq = nbxmpp.Iq('get', to=to_jid)
|
iq = nbxmpp.Iq('get', to=to_jid)
|
||||||
id_ = con.connection.getAnID()
|
id_ = con.connection.getAnID()
|
||||||
|
@ -201,12 +223,12 @@ def createKeyPair(type, bits):
|
||||||
pkey.generate_key(type, bits)
|
pkey.generate_key(type, bits)
|
||||||
return pkey
|
return pkey
|
||||||
|
|
||||||
def createCertRequest(pkey, digest="sha1", **name):
|
def createCertRequest(pkey, digest="sha256", **name):
|
||||||
"""
|
"""
|
||||||
Create a certificate request.
|
Create a certificate request.
|
||||||
|
|
||||||
Arguments: pkey - The key to associate with the request
|
Arguments: pkey - The key to associate with the request
|
||||||
digest - Digestion method to use for signing, default is sha1
|
digest - Digestion method to use for signing, default is sha256
|
||||||
**name - The name of the subject of the request, possible
|
**name - The name of the subject of the request, possible
|
||||||
arguments are:
|
arguments are:
|
||||||
C - Country name
|
C - Country name
|
||||||
|
@ -228,7 +250,7 @@ def createCertRequest(pkey, digest="sha1", **name):
|
||||||
req.sign(pkey, digest)
|
req.sign(pkey, digest)
|
||||||
return req
|
return req
|
||||||
|
|
||||||
def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, digest="sha1"):
|
def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, digest="shai256"):
|
||||||
"""
|
"""
|
||||||
Generate a certificate given a certificate request.
|
Generate a certificate given a certificate request.
|
||||||
|
|
||||||
|
@ -240,7 +262,7 @@ def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, d
|
||||||
starts being valid
|
starts being valid
|
||||||
notAfter - Timestamp (relative to now) when the certificate
|
notAfter - Timestamp (relative to now) when the certificate
|
||||||
stops being valid
|
stops being valid
|
||||||
digest - Digest method to use for signing, default is sha1
|
digest - Digest method to use for signing, default is sha256
|
||||||
Returns: The signed certificate in an X509 object
|
Returns: The signed certificate in an X509 object
|
||||||
"""
|
"""
|
||||||
cert = crypto.X509()
|
cert = crypto.X509()
|
||||||
|
|
|
@ -153,11 +153,17 @@ class ConnectionBytestream:
|
||||||
if not content:
|
if not content:
|
||||||
return
|
return
|
||||||
if not session.accepted:
|
if not session.accepted:
|
||||||
if session.get_content('file', content.name).use_security:
|
content = session.get_content('file', content.name)
|
||||||
id_ = jingle_xtls.send_cert_request(self,
|
if content.use_security:
|
||||||
file_props.sender)
|
fingerprint = content.x509_fingerprint
|
||||||
jingle_xtls.key_exchange_pend(id_, content)
|
if not jingle_xtls.check_cert(
|
||||||
return
|
gajim.get_jid_without_resource(file_props.sender),
|
||||||
|
fingerprint):
|
||||||
|
id_ = jingle_xtls.send_cert_request(self,
|
||||||
|
file_props.sender)
|
||||||
|
jingle_xtls.key_exchange_pend(id_,
|
||||||
|
content.on_cert_received, [])
|
||||||
|
return
|
||||||
session.approve_session()
|
session.approve_session()
|
||||||
|
|
||||||
session.approve_content('file', content.name)
|
session.approve_content('file', content.name)
|
||||||
|
|
|
@ -119,8 +119,7 @@ class SocksQueue:
|
||||||
streamhosts_to_test = []
|
streamhosts_to_test = []
|
||||||
# Remove local IPs to not connect to ourself
|
# Remove local IPs to not connect to ourself
|
||||||
for streamhost in file_props.streamhosts:
|
for streamhost in file_props.streamhosts:
|
||||||
if streamhost['host'] == '127.0.0.1' or \
|
if streamhost['host'] == '127.0.0.1' or streamhost['host'] == '::1':
|
||||||
streamhost['host'] == '::1':
|
|
||||||
continue
|
continue
|
||||||
streamhosts_to_test.append(streamhost)
|
streamhosts_to_test.append(streamhost)
|
||||||
if not streamhosts_to_test:
|
if not streamhosts_to_test:
|
||||||
|
@ -327,7 +326,7 @@ class SocksQueue:
|
||||||
if listener.file_props.type_ == 's' and \
|
if listener.file_props.type_ == 's' and \
|
||||||
not self.isHashInSockObjs(self.senders, sock_hash):
|
not self.isHashInSockObjs(self.senders, sock_hash):
|
||||||
sockobj = Socks5SenderServer(self.idlequeue, sock_hash, self,
|
sockobj = Socks5SenderServer(self.idlequeue, sock_hash, self,
|
||||||
sock[0], sock[1][0], sock[1][1], fingerprint='server',
|
sock[0], sock[1][0], sock[1][1], fingerprint='server',
|
||||||
file_props=listener.file_props)
|
file_props=listener.file_props)
|
||||||
self._add(sockobj, self.senders, listener.file_props, sock_hash)
|
self._add(sockobj, self.senders, listener.file_props, sock_hash)
|
||||||
# Start waiting for data
|
# Start waiting for data
|
||||||
|
@ -416,7 +415,7 @@ class SocksQueue:
|
||||||
self.connected -= 1
|
self.connected -= 1
|
||||||
|
|
||||||
|
|
||||||
class Socks5:
|
class Socks5(object):
|
||||||
def __init__(self, idlequeue, host, port, initiator, target, sid):
|
def __init__(self, idlequeue, host, port, initiator, target, sid):
|
||||||
if host is not None:
|
if host is not None:
|
||||||
try:
|
try:
|
||||||
|
@ -440,12 +439,20 @@ class Socks5:
|
||||||
self.file = None
|
self.file = None
|
||||||
self.connected = False
|
self.connected = False
|
||||||
self.mode = ''
|
self.mode = ''
|
||||||
|
self.ssl_cert = None
|
||||||
|
self.ssl_errnum = 0
|
||||||
|
|
||||||
def _is_connected(self):
|
def _is_connected(self):
|
||||||
if self.state < 5:
|
if self.state < 5:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def ssl_verify_cb(self, ssl_conn, cert, error_num, depth, return_code):
|
||||||
|
if depth == 0:
|
||||||
|
self.ssl_cert = cert
|
||||||
|
self.ssl_errnum = error_num
|
||||||
|
return True
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""
|
"""
|
||||||
Create the socket and plug it to the idlequeue
|
Create the socket and plug it to the idlequeue
|
||||||
|
@ -456,8 +463,16 @@ class Socks5:
|
||||||
try:
|
try:
|
||||||
self._sock = socket.socket(*ai[:3])
|
self._sock = socket.socket(*ai[:3])
|
||||||
if not self.fingerprint is None:
|
if not self.fingerprint is None:
|
||||||
|
if self.file_props.type_ == 's':
|
||||||
|
remote_jid = gajim.get_jid_without_resource(
|
||||||
|
self.file_props.receiver)
|
||||||
|
else:
|
||||||
|
remote_jid = gajim.get_jid_without_resource(
|
||||||
|
self.file_props.sender)
|
||||||
self._sock = OpenSSL.SSL.Connection(
|
self._sock = OpenSSL.SSL.Connection(
|
||||||
jingle_xtls.get_context('client'), self._sock)
|
jingle_xtls.get_context('client',
|
||||||
|
verify_cb=self.ssl_verify_cb, remote_jid=remote_jid),
|
||||||
|
self._sock)
|
||||||
# this will not block the GUI
|
# this will not block the GUI
|
||||||
self._sock.setblocking(False)
|
self._sock.setblocking(False)
|
||||||
self._server = ai[4]
|
self._server = ai[4]
|
||||||
|
@ -477,9 +492,10 @@ class Socks5:
|
||||||
def do_connect(self):
|
def do_connect(self):
|
||||||
try:
|
try:
|
||||||
self._sock.connect(self._server)
|
self._sock.connect(self._server)
|
||||||
self._sock.setblocking(False)
|
|
||||||
self._send=self._sock.send
|
self._send=self._sock.send
|
||||||
self._recv=self._sock.recv
|
self._recv=self._sock.recv
|
||||||
|
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
|
||||||
|
pass
|
||||||
except Exception as ee:
|
except Exception as ee:
|
||||||
errnum = ee.errno
|
errnum = ee.errno
|
||||||
self.connect_timeout += 1
|
self.connect_timeout += 1
|
||||||
|
@ -887,7 +903,6 @@ class Socks5Sender(IdleObject):
|
||||||
"""
|
"""
|
||||||
Class for sending file to socket over socks5
|
Class for sending file to socket over socks5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, idlequeue, sock_hash, parent, _sock, host=None,
|
def __init__(self, idlequeue, sock_hash, parent, _sock, host=None,
|
||||||
port=None, fingerprint = None, connected=True, file_props={}):
|
port=None, fingerprint = None, connected=True, file_props={}):
|
||||||
self.fingerprint = fingerprint
|
self.fingerprint = fingerprint
|
||||||
|
@ -968,7 +983,6 @@ class Socks5Sender(IdleObject):
|
||||||
|
|
||||||
|
|
||||||
class Socks5Receiver(IdleObject):
|
class Socks5Receiver(IdleObject):
|
||||||
|
|
||||||
def __init__(self, idlequeue, streamhost, sid, file_props = None,
|
def __init__(self, idlequeue, streamhost, sid, file_props = None,
|
||||||
fingerprint=None):
|
fingerprint=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1231,6 +1245,14 @@ class Socks5Client(Socks5):
|
||||||
self.state += 1
|
self.state += 1
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def send_file(self):
|
||||||
|
if self.ssl_errnum > 0:
|
||||||
|
log.error('remote certificate does not match the announced one.' + \
|
||||||
|
'\nSSL Error: %d\nCancelling file transfer' % self.ssl_errnum)
|
||||||
|
self.file_props.error = -12
|
||||||
|
return -1
|
||||||
|
return super(Socks5Client, self).send_file()
|
||||||
|
|
||||||
def pollin(self):
|
def pollin(self):
|
||||||
self.idlequeue.remove_timeout(self.fd)
|
self.idlequeue.remove_timeout(self.fd)
|
||||||
if self.connected:
|
if self.connected:
|
||||||
|
@ -1312,9 +1334,8 @@ class Socks5SenderServer(Socks5Server, Socks5Sender):
|
||||||
|
|
||||||
|
|
||||||
class Socks5ReceiverClient(Socks5Client, Socks5Receiver):
|
class Socks5ReceiverClient(Socks5Client, Socks5Receiver):
|
||||||
|
|
||||||
def __init__(self, idlequeue, streamhost, sid, file_props = None,
|
def __init__(self, idlequeue, streamhost, sid, file_props = None,
|
||||||
fingerprint=None):
|
fingerprint=None):
|
||||||
Socks5Client.__init__(self, idlequeue, streamhost['host'],
|
Socks5Client.__init__(self, idlequeue, streamhost['host'],
|
||||||
int(streamhost['port']), streamhost['initiator'],
|
int(streamhost['port']), streamhost['initiator'],
|
||||||
streamhost['target'], sid)
|
streamhost['target'], sid)
|
||||||
|
@ -1436,4 +1457,3 @@ class Socks5Listener(IdleObject):
|
||||||
self.connections.append(_sock[0])
|
self.connections.append(_sock[0])
|
||||||
return _sock
|
return _sock
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1022,6 +1022,9 @@ class Interface:
|
||||||
error_msg=_('Error opening file'))
|
error_msg=_('Error opening file'))
|
||||||
elif file_props.error == -10:
|
elif file_props.error == -10:
|
||||||
ft.show_hash_error(jid, file_props, account)
|
ft.show_hash_error(jid, file_props, account)
|
||||||
|
elif file_props.error == -12:
|
||||||
|
ft.show_stopped(jid, file_props,
|
||||||
|
error_msg=_('SSL certificate error'))
|
||||||
return
|
return
|
||||||
|
|
||||||
msg_type = ''
|
msg_type = ''
|
||||||
|
|
Loading…
Add table
Reference in a new issue