diff --git a/src/common/check_paths.py b/src/common/check_paths.py index 29c6846c6..c9f7eae6c 100644 --- a/src/common/check_paths.py +++ b/src/common/check_paths.py @@ -269,6 +269,7 @@ def check_and_possibly_create_paths(): MY_CONFIG = configpaths.gajimpaths['MY_CONFIG'] MY_CACHE = configpaths.gajimpaths['MY_CACHE'] XTLS_CERTS = os.path.expanduser(jingle_xtls.CERTIFICATE_DIR) + LOCAL_XTLS_CERTS = os.path.expanduser(jingle_xtls.LOCAL_CERT_DIR) if not os.path.exists(MY_DATA): create_path(MY_DATA) @@ -337,9 +338,9 @@ def check_and_possibly_create_paths(): if not os.path.exists(XTLS_CERTS): create_path(XTLS_CERTS) - if not (os.path.exists(os.path.join(XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE + '.cert')) and - os.path.exists(os.path.join(XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE + '.pkey'))): - jingle_xtls.make_certs(os.path.join(XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE), 'gajim') + if not (os.path.exists(os.path.join(LOCAL_XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE + '.cert')) and + os.path.exists(os.path.join(LOCAL_XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE + '.pkey'))): + jingle_xtls.make_certs(os.path.join(LOCAL_XTLS_CERTS, jingle_xtls.SELF_SIGNED_CERTIFICATE), 'gajim') def create_path(directory): diff --git a/src/common/configpaths.py b/src/common/configpaths.py index 8c2df8b58..7cb10c666 100644 --- a/src/common/configpaths.py +++ b/src/common/configpaths.py @@ -151,7 +151,7 @@ class ConfigPaths: self.add(name, TYPE_CACHE, windowsify(d[name])) self.add('MY_CONFIG', TYPE_CONFIG, '') - self.add('MY_CERT', TYPE_CONFIG, 'localcert') + self.add('MY_CERT', TYPE_CONFIG, '') basedir = fse(os.environ.get(u'GAJIM_BASEDIR', defs.basedir)) self.add('DATA', None, os.path.join(basedir, windowsify(u'data'))) diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index ace3c1817..4cd097b2c 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -28,6 +28,16 @@ gajimpath = configpaths.gajimpaths PYOPENSSL_PRESENT = False +pending_sessions = {} # key-exchange id -> session, accept that session once key-exchange completes + +def key_exchange_pend(id, session): + pending_sessions[id] = session + +def approve_pending_session(id): + session = pending_sessions[id] + session.approve_session() + session.approve_content('file') + try: import OpenSSL PYOPENSSL_PRESENT = True @@ -40,7 +50,9 @@ if PYOPENSSL_PRESENT: from OpenSSL import crypto CERTIFICATE_DIR = gajimpath['MY_PEER_CERTS'] +LOCAL_CERT_DIR = gajimpath['MY_CERT'] print 'CERTIFICATE_DIR: ', CERTIFICATE_DIR +print 'MY_CERT_DIR: ', LOCAL_CERT_DIR SELF_SIGNED_CERTIFICATE = 'localcert' def default_callback(connection, certificate, error_num, depth, return_code): @@ -87,19 +99,20 @@ def get_context(fingerprint, verify_cb=None): ctx = SSL.Context(SSL.TLSv1_METHOD) if fingerprint == 'server': # for testing purposes only - ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb or default_callback) + 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) - ctx.use_privatekey_file (os.path.expanduser(os.path.join(CERTIFICATE_DIR, SELF_SIGNED_CERTIFICATE) + '.pkey')) - ctx.use_certificate_file(os.path.expanduser(os.path.join(CERTIFICATE_DIR, SELF_SIGNED_CERTIFICATE) + '.cert')) + ctx.use_privatekey_file (os.path.expanduser(os.path.join(LOCAL_CERT_DIR, SELF_SIGNED_CERTIFICATE) + '.pkey')) + ctx.use_certificate_file(os.path.expanduser(os.path.join(LOCAL_CERT_DIR, SELF_SIGNED_CERTIFICATE) + '.cert')) store = ctx.get_cert_store() for f in os.listdir(os.path.expanduser(CERTIFICATE_DIR)): load_cert_file(os.path.join(os.path.expanduser(CERTIFICATE_DIR), f), store) + print 'certificate file' + f + ' loaded', 'fingerprint', fingerprint return ctx def send_cert(con, jid_from, sid): - certpath = os.path.expanduser(os.path.join(CERTIFICATE_DIR, SELF_SIGNED_CERTIFICATE) + '.cert') + certpath = os.path.expanduser(os.path.join(LOCAL_CERT_DIR, SELF_SIGNED_CERTIFICATE) + '.cert') certfile = open(certpath, 'r') certificate = '' for line in certfile.readlines(): @@ -124,6 +137,8 @@ def handle_new_cert(con, obj, jid_from): certpath = os.path.join(os.path.expanduser(CERTIFICATE_DIR), jid) certpath += '.cert' + id = obj.getAttr('id') + x509cert = obj.getTag('pubkeys').getTag('keyinfo').getTag('x509cert') cert = x509cert.getData() @@ -133,12 +148,16 @@ def handle_new_cert(con, obj, jid_from): 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) - iq.setAttr('id', con.connection.getAnID()) + id = con.connection.getAnID() + iq.setAttr('id', id) pubkey = iq.setTag('pubkeys') pubkey.setNamespace(common.xmpp.NS_PUBKEY_PUBKEY) con.connection.send(iq) + return unicode(id) # the following code is partly due to pyopenssl examples diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 1de47a465..dc637adb8 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -141,7 +141,9 @@ class ConnectionBytestream: if not session.accepted: if session.get_content('file').use_security: - jingle_xtls.send_cert_request(self, file_props['receiver']) + id = jingle_xtls.send_cert_request(self, file_props['sender']) + jingle_xtls.key_exchange_pend(id, session) + return session.approve_session() session.approve_content('file') return