diff --git a/data/gui/accounts_window.ui b/data/gui/accounts_window.ui
index 4a1b0be37..e1e2a3dcc 100644
--- a/data/gui/accounts_window.ui
+++ b/data/gui/accounts_window.ui
@@ -451,48 +451,70 @@
True
True
-
diff --git a/src/common/config.py b/src/common/config.py
index 3a83be6e1..84562468f 100644
--- a/src/common/config.py
+++ b/src/common/config.py
@@ -298,6 +298,7 @@ class Config:
'hostname': [ opt_str, '', '', True ],
'anonymous_auth': [ opt_bool, False ],
'client_cert': [ opt_str, '', '', True ],
+ 'client_cert_encrypted': [ opt_bool, False, '', False ],
'savepass': [ opt_bool, False ],
'password': [ opt_str, '' ],
'resource': [ opt_str, 'gajim', '', True ],
diff --git a/src/common/connection.py b/src/common/connection.py
index e92dc57a0..e5ce35fd4 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -749,6 +749,7 @@ class Connection(CommonConnection, ConnectionHandlers):
self.pingalives = 0
self.client_cert = gajim.config.get_per('accounts', self.name,
'client_cert')
+ self.client_cert_passphrase = ''
def check_jid(self, jid):
return helpers.parse_jid(jid)
@@ -1155,29 +1156,42 @@ class Connection(CommonConnection, ConnectionHandlers):
secure_tuple = (self._current_type, cacerts, mycerts)
con = common.xmpp.NonBlockingClient(
- domain=self._hostname,
- caller=self,
- idlequeue=gajim.idlequeue)
+ domain=self._hostname,
+ caller=self,
+ idlequeue=gajim.idlequeue)
self.last_connection = con
# increase default timeout for server responses
- common.xmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = self.try_connecting_for_foo_secs
+ common.xmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = \
+ self.try_connecting_for_foo_secs
# FIXME: this is a hack; need a better way
if self.on_connect_success == self._on_new_account:
con.RegisterDisconnectHandler(self._on_new_account)
- self.log_hosttype_info(port)
- con.connect(
- hostname=self._current_host['host'],
- port=port,
- on_connect=self.on_connect_success,
- on_proxy_failure=self.on_proxy_failure,
- on_connect_failure=self.connect_to_next_type,
- proxy=self._proxy,
- secure_tuple = secure_tuple)
+ if self.client_cert and gajim.config.get_per('accounts', self.name,
+ 'client_cert_encrypted'):
+ gajim.nec.push_incoming_event(ClientCertPassphraseEvent(
+ None, conn=self, con=con, port=port,
+ secure_tuple=secure_tuple))
+ return
+ self.on_client_cert_passphrase(None, con, port, secure_tuple)
+
else:
self._connect_to_next_host(retry)
+ def on_client_cert_passphrase(self, passphrase, con, port, secure_tuple):
+ self.client_cert_passphrase = passphrase
+
+ self.log_hosttype_info(port)
+ con.connect(
+ hostname=self._current_host['host'],
+ port=port,
+ on_connect=self.on_connect_success,
+ on_proxy_failure=self.on_proxy_failure,
+ on_connect_failure=self.connect_to_next_type,
+ proxy=self._proxy,
+ secure_tuple = secure_tuple)
+
def log_hosttype_info(self, port):
msg = '>>>>>> Connecting to %s [%s:%d], type = %s' % (self.name,
self._current_host['host'], port, self._current_type)
diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py
index 63c7000ac..08b4ce2e7 100644
--- a/src/common/connection_handlers_events.py
+++ b/src/common/connection_handlers_events.py
@@ -2069,3 +2069,7 @@ class MessageOutgoingEvent(nec.NetworkIncomingEvent):
def generate(self):
return True
+
+class ClientCertPassphraseEvent(nec.NetworkIncomingEvent):
+ name = 'client-cert-passphrase'
+ base_network_events = []
diff --git a/src/common/xmpp/tls_nb.py b/src/common/xmpp/tls_nb.py
index 7a9c80f98..cc8393d52 100644
--- a/src/common/xmpp/tls_nb.py
+++ b/src/common/xmpp/tls_nb.py
@@ -359,7 +359,8 @@ class NonBlockingTLS(PlugIn):
tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
log.debug('Using client cert and key from %s' % conn.client_cert)
try:
- p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read())
+ p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(),
+ conn.client_cert_passphrase)
except OpenSSL.crypto.Error, exception_obj:
log.warning('Unable to load client pkcs12 certificate from '
'file %s: %s ... Is it a valid PKCS12 cert?' % \
diff --git a/src/config.py b/src/config.py
index d9610c713..cc3de416a 100644
--- a/src/config.py
+++ b/src/config.py
@@ -1851,6 +1851,10 @@ class AccountsWindow:
client_cert = gajim.config.get_per('accounts', account, 'client_cert')
self.xml.get_object('cert_entry1').set_text(client_cert)
+ client_cert_encrypted = gajim.config.get_per('accounts', account,
+ 'client_cert_encrypted')
+ self.xml.get_object('client_cert_encrypted_checkbutton1').\
+ set_active(client_cert_encrypted)
self.xml.get_object('adjust_priority_with_status_checkbutton1').\
set_active(gajim.config.get_per('accounts', account,
@@ -2222,6 +2226,12 @@ class AccountsWindow:
# if we showed ErrorDialog, there will not be dialog instance
return
+ def on_client_cert_encrypted_checkbutton1_toggled(self, widget):
+ if self.ignore_events:
+ return
+ self.on_checkbutton_toggled(widget, 'client_cert_encrypted',
+ account=self.current_account)
+
def on_autoconnect_checkbutton_toggled(self, widget):
if self.ignore_events:
return
diff --git a/src/gui_interface.py b/src/gui_interface.py
index e2e4ed255..86dd76fcd 100644
--- a/src/gui_interface.py
+++ b/src/gui_interface.py
@@ -671,6 +671,19 @@ class Interface:
_('You are currently connected without your OpenPGP key.'))
self.forget_gpg_passphrase(obj.keyID)
+ def handle_event_client_cert_passphrase(self, obj):
+ def on_ok(passphrase, checked):
+ obj.conn.on_client_cert_passphrase(passphrase, obj.con, obj.port,
+ obj.secure_tuple)
+
+ def on_cancel():
+ obj.conn.on_client_cert_passphrase('', obj.con, obj.port,
+ obj.secure_tuple)
+
+ dialogs.PassphraseDialog(_('Certificate Passphrase Required'),
+ _('Enter the passphrase for the certificate for account %s') % \
+ obj.conn.name, ok_handler=on_ok, cancel_handler=on_cancel)
+
def handle_event_gpg_password_required(self, obj):
#('GPG_PASSWORD_REQUIRED', account, (callback,))
if obj.keyid in self.gpg_passphrase:
@@ -1401,6 +1414,8 @@ class Interface:
'atom-entry-received': [self.handle_atom_entry],
'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase],
'bookmarks-received': [self.handle_event_bookmarks],
+ 'client-cert-passphrase': [
+ self.handle_event_client_cert_passphrase],
'connection-lost': [self.handle_event_connection_lost],
'failed-decrypt': [(self.handle_event_failed_decrypt, ged.GUI2)],
'file-request-error': [self.handle_event_file_request_error],