request GPG password only when connected to server, before sending presence. fixes #3483, #3375, #3115
This commit is contained in:
parent
e52be0071b
commit
0ceb41f650
|
@ -139,18 +139,13 @@ class Connection(ConnectionHandlers):
|
|||
self.blocked_contacts = []
|
||||
self.blocked_groups = []
|
||||
self.pep_supported = False
|
||||
# Do we continue connection when we get roster (send presence,get vcard...)
|
||||
# Do we continue connection when we get roster (send presence,get vcard..)
|
||||
self.continue_connect_info = None
|
||||
# To know the groupchat jid associated with a sranza ID. Useful to
|
||||
# request vcard or os info... to a real JID but act as if it comes from
|
||||
# the fake jid
|
||||
self.groupchat_jids = {} # {ID : groupchat_jid}
|
||||
if USE_GPG:
|
||||
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
|
||||
gajim.config.set('usegpg', True)
|
||||
else:
|
||||
gajim.config.set('usegpg', False)
|
||||
|
||||
|
||||
self.on_connect_success = None
|
||||
self.on_connect_failure = None
|
||||
self.retrycount = 0
|
||||
|
@ -179,9 +174,8 @@ class Connection(ConnectionHandlers):
|
|||
self.connected = 1
|
||||
self.dispatch('STATUS', 'connecting')
|
||||
self.retrycount += 1
|
||||
signed = self.get_signed_msg(self.status)
|
||||
self.on_connect_auth = self._init_roster
|
||||
self.connect_and_init(self.old_show, self.status, signed)
|
||||
self.connect_and_init(self.old_show, self.status, self.gpg != None)
|
||||
else:
|
||||
# reconnect succeeded
|
||||
self.time_to_reconnect = None
|
||||
|
@ -539,7 +533,8 @@ class Connection(ConnectionHandlers):
|
|||
gajim.log.debug("Couldn't authenticate to %s" % self._hostname)
|
||||
self.disconnect(on_purpose = True)
|
||||
self.dispatch('STATUS', 'offline')
|
||||
self.dispatch('ERROR', (_('Authentication failed with "%s"') % self._hostname,
|
||||
self.dispatch('ERROR', (_('Authentication failed with "%s"') % \
|
||||
self._hostname,
|
||||
_('Please check your login and password for correctness.')))
|
||||
if self.on_connect_auth:
|
||||
self.on_connect_auth(None)
|
||||
|
@ -670,29 +665,32 @@ class Connection(ConnectionHandlers):
|
|||
self.dispatch('SIGNED_IN', ())
|
||||
|
||||
def test_gpg_passphrase(self, password):
|
||||
if not self.gpg:
|
||||
return False
|
||||
self.gpg.passphrase = password
|
||||
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
||||
signed = self.gpg.sign('test', keyID)
|
||||
self.gpg.password = None
|
||||
return signed != 'BAD_PASSPHRASE'
|
||||
|
||||
def get_signed_msg(self, msg):
|
||||
def get_signed_msg(self, msg, callback = None):
|
||||
'''returns the signed message if possible
|
||||
or an empty string if gpg is not used
|
||||
or None if waiting for passphrase.
|
||||
callback is the function to call when user give the passphrase'''
|
||||
signed = ''
|
||||
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
||||
if keyID and USE_GPG:
|
||||
if keyID and self.gpg:
|
||||
use_gpg_agent = gajim.config.get('use_gpg_agent')
|
||||
if self.connected < 2 and self.gpg.passphrase is None and \
|
||||
not use_gpg_agent:
|
||||
if self.gpg.passphrase is None and not use_gpg_agent:
|
||||
# We didn't set a passphrase
|
||||
self.dispatch('ERROR', (_('OpenPGP passphrase was not given'),
|
||||
#%s is the account name here
|
||||
_('You will be connected to %s without OpenPGP.') % self.name))
|
||||
elif self.gpg.passphrase is not None or use_gpg_agent:
|
||||
return None
|
||||
if self.gpg.passphrase is not None or use_gpg_agent:
|
||||
signed = self.gpg.sign(msg, keyID)
|
||||
if signed == 'BAD_PASSPHRASE':
|
||||
self.gpg = None
|
||||
signed = ''
|
||||
if self.connected < 2:
|
||||
self.dispatch('BAD_PASSPHRASE', ())
|
||||
self.dispatch('BAD_PASSPHRASE', ())
|
||||
return signed
|
||||
|
||||
def connect_and_auth(self):
|
||||
|
@ -700,21 +698,22 @@ class Connection(ConnectionHandlers):
|
|||
self.on_connect_failure = self._connect_failure
|
||||
self.connect()
|
||||
|
||||
def connect_and_init(self, show, msg, signed):
|
||||
self.continue_connect_info = [show, msg, signed]
|
||||
def connect_and_init(self, show, msg, signe_msg):
|
||||
self.continue_connect_info = [show, msg, signe_msg]
|
||||
self.on_connect_auth = self._init_roster
|
||||
self.connect_and_auth()
|
||||
|
||||
def _init_roster(self, con):
|
||||
self.connection = con
|
||||
if self.connection:
|
||||
con.set_send_timeout(self.keepalives, self.send_keepalive)
|
||||
self.connection.onreceive(None)
|
||||
iq = common.xmpp.Iq('get', common.xmpp.NS_PRIVACY, xmlns = '')
|
||||
id = self.connection.getAnID()
|
||||
iq.setID(id)
|
||||
self.awaiting_answers[id] = (PRIVACY_ARRIVED, )
|
||||
self.connection.send(iq)
|
||||
if not self.connection:
|
||||
return
|
||||
self.connection.set_send_timeout(self.keepalives, self.send_keepalive)
|
||||
self.connection.onreceive(None)
|
||||
iq = common.xmpp.Iq('get', common.xmpp.NS_PRIVACY, xmlns = '')
|
||||
id = self.connection.getAnID()
|
||||
iq.setID(id)
|
||||
self.awaiting_answers[id] = (PRIVACY_ARRIVED, )
|
||||
self.connection.send(iq)
|
||||
|
||||
def send_custom_status(self, show, msg, jid):
|
||||
if not show in STATUS_LIST:
|
||||
|
@ -749,9 +748,9 @@ class Connection(ConnectionHandlers):
|
|||
if not msg:
|
||||
msg = ''
|
||||
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
||||
signed = ''
|
||||
signe_msg = False
|
||||
if not auto and not show == 'offline':
|
||||
signed = self.get_signed_msg(msg)
|
||||
signe_msg = True
|
||||
self.status = msg
|
||||
if show != 'offline' and not self.connected:
|
||||
# set old_show to requested 'show' in case we need to
|
||||
|
@ -766,7 +765,12 @@ class Connection(ConnectionHandlers):
|
|||
safe_substitute({
|
||||
'hostname': socket.gethostname()
|
||||
})
|
||||
self.connect_and_init(show, msg, signed)
|
||||
if USE_GPG and not self.gpg:
|
||||
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
|
||||
gajim.config.set('usegpg', True)
|
||||
else:
|
||||
gajim.config.set('usegpg', False)
|
||||
self.connect_and_init(show, msg, signe_msg)
|
||||
|
||||
elif show == 'offline':
|
||||
self.connected = 0
|
||||
|
@ -801,6 +805,7 @@ class Connection(ConnectionHandlers):
|
|||
p = self.add_sha(p)
|
||||
if msg:
|
||||
p.setStatus(msg)
|
||||
signed = self.get_signed_msg(msg)
|
||||
if signed:
|
||||
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
||||
if self.connection:
|
||||
|
@ -839,7 +844,7 @@ class Connection(ConnectionHandlers):
|
|||
fjid += '/' + resource
|
||||
msgtxt = msg
|
||||
msgenc = ''
|
||||
if keyID and USE_GPG:
|
||||
if keyID and self.gpg:
|
||||
#encrypt
|
||||
msgenc, error = self.gpg.encrypt(msg, [keyID])
|
||||
if msgenc and not error:
|
||||
|
@ -1377,7 +1382,7 @@ class Connection(ConnectionHandlers):
|
|||
self.connection.send(iq)
|
||||
|
||||
def gpg_passphrase(self, passphrase):
|
||||
if USE_GPG:
|
||||
if self.gpg:
|
||||
use_gpg_agent = gajim.config.get('use_gpg_agent')
|
||||
if use_gpg_agent:
|
||||
self.gpg.passphrase = None
|
||||
|
@ -1385,13 +1390,13 @@ class Connection(ConnectionHandlers):
|
|||
self.gpg.passphrase = passphrase
|
||||
|
||||
def ask_gpg_keys(self):
|
||||
if USE_GPG:
|
||||
if self.gpg:
|
||||
keys = self.gpg.get_keys()
|
||||
return keys
|
||||
return None
|
||||
|
||||
def ask_gpg_secrete_keys(self):
|
||||
if USE_GPG:
|
||||
if self.gpg:
|
||||
keys = self.gpg.get_secret_keys()
|
||||
return keys
|
||||
return None
|
||||
|
|
|
@ -1419,7 +1419,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
|||
qp.setTagData('utc', strftime('%Y%m%dT%T', gmtime()))
|
||||
qp.setTagData('tz', tzname[daylight])
|
||||
qp.setTagData('display', helpers.decode_string(strftime('%c',
|
||||
localtime())))
|
||||
localtime()))
|
||||
self.connection.send(iq_obj)
|
||||
raise common.xmpp.NodeProcessed
|
||||
|
||||
|
@ -2129,41 +2129,62 @@ returns the session that we last sent a message to.'''
|
|||
|
||||
# continue connection
|
||||
if self.connected > 1 and self.continue_connect_info:
|
||||
show = self.continue_connect_info[0]
|
||||
msg = self.continue_connect_info[1]
|
||||
signed = self.continue_connect_info[2]
|
||||
self.connected = STATUS_LIST.index(show)
|
||||
sshow = helpers.get_xmpp_show(show)
|
||||
# send our presence
|
||||
if show == 'invisible':
|
||||
self.send_invisible_presence(msg, signed, True)
|
||||
return
|
||||
priority = gajim.get_priority(self.name, sshow)
|
||||
vcard = self.get_cached_vcard(jid)
|
||||
if vcard and vcard.has_key('PHOTO') and vcard['PHOTO'].has_key('SHA'):
|
||||
self.vcard_sha = vcard['PHOTO']['SHA']
|
||||
p = common.xmpp.Presence(typ = None, priority = priority, show = sshow)
|
||||
p = self.add_sha(p)
|
||||
if msg:
|
||||
p.setStatus(msg)
|
||||
if signed:
|
||||
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
||||
to_be_signed = self.continue_connect_info[2]
|
||||
signed = ''
|
||||
if to_be_signed:
|
||||
signed = self.get_signed_msg(to_be_signed,
|
||||
self._send_first_presence)
|
||||
if signed is None:
|
||||
self.dispatch('GPG_PASSWORD_REQUIRED',
|
||||
(self._send_first_presence,))
|
||||
# _send_first_presence will be called when user enter passphrase
|
||||
return
|
||||
self._send_first_presence(signed)
|
||||
|
||||
if self.connection:
|
||||
self.connection.send(p)
|
||||
self.priority = priority
|
||||
self.dispatch('STATUS', show)
|
||||
# ask our VCard
|
||||
self.request_vcard(None)
|
||||
def _send_first_presence(self, signed = ''):
|
||||
show = self.continue_connect_info[0]
|
||||
msg = self.continue_connect_info[1]
|
||||
to_be_signed = self.continue_connect_info[2]
|
||||
if to_be_signed and not signed:
|
||||
signed = self.get_signed_msg(self.continue_connect_info[2])
|
||||
if signed is None:
|
||||
self.dispatch('ERROR', (_('OpenPGP passphrase was not given'),
|
||||
#%s is the account name here
|
||||
_('You will be connected to %s without OpenPGP.') % self.name))
|
||||
signed = ''
|
||||
self.connected = STATUS_LIST.index(show)
|
||||
sshow = helpers.get_xmpp_show(show)
|
||||
# send our presence
|
||||
if show == 'invisible':
|
||||
self.send_invisible_presence(msg, signed, True)
|
||||
return
|
||||
priority = gajim.get_priority(self.name, sshow)
|
||||
our_jid = helpers.parse_jid(gajim.get_jid_from_account(self.name))
|
||||
vcard = self.get_cached_vcard(our_jid)
|
||||
if vcard and vcard.has_key('PHOTO') and vcard['PHOTO'].has_key('SHA'):
|
||||
self.vcard_sha = vcard['PHOTO']['SHA']
|
||||
p = common.xmpp.Presence(typ = None, priority = priority, show = sshow)
|
||||
p = self.add_sha(p)
|
||||
if msg:
|
||||
p.setStatus(msg)
|
||||
if signed:
|
||||
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
||||
|
||||
# Get bookmarks from private namespace
|
||||
self.get_bookmarks()
|
||||
if self.connection:
|
||||
self.connection.send(p)
|
||||
self.priority = priority
|
||||
self.dispatch('STATUS', show)
|
||||
# ask our VCard
|
||||
self.request_vcard(None)
|
||||
|
||||
# Get annotations from private namespace
|
||||
self.get_annotations()
|
||||
# Get bookmarks from private namespace
|
||||
self.get_bookmarks()
|
||||
|
||||
#Inform GUI we just signed in
|
||||
self.dispatch('SIGNED_IN', ())
|
||||
# Get annotations from private namespace
|
||||
self.get_annotations()
|
||||
|
||||
# Inform GUI we just signed in
|
||||
self.dispatch('SIGNED_IN', ())
|
||||
self.continue_connect_info = None
|
||||
|
||||
def request_gmail_notifications(self):
|
||||
|
|
40
src/gajim.py
40
src/gajim.py
|
@ -1365,15 +1365,51 @@ class Interface:
|
|||
notify.popup(event_type, jid, account, 'gc-invitation', path,
|
||||
event_type, room_jid)
|
||||
|
||||
def forget_gpg_passphrase(self, keyid):
|
||||
if self.gpg_passphrase.has_key(keyid):
|
||||
del self.gpg_passphrase[keyid]
|
||||
return False
|
||||
|
||||
def handle_event_bad_passphrase(self, account, array):
|
||||
use_gpg_agent = gajim.config.get('use_gpg_agent')
|
||||
if use_gpg_agent:
|
||||
return
|
||||
keyID = gajim.config.get_per('accounts', account, 'keyid')
|
||||
self.roster.forget_gpg_passphrase(keyID)
|
||||
self.forget_gpg_passphrase(keyID)
|
||||
dialogs.WarningDialog(_('Your passphrase is incorrect'),
|
||||
_('You are currently connected without your OpenPGP key.'))
|
||||
|
||||
def handle_event_gpg_password_required(self, account, array):
|
||||
#('GPG_PASSWORD_REQUIRED', account, (callback,))
|
||||
callback = array[0]
|
||||
keyid = gajim.config.get_per('accounts', account, 'keyid')
|
||||
if self.gpg_passphrase.has_key(keyid):
|
||||
gajim.connections[account].gpg_passphrase(self.gpg_passphrase[keyid])
|
||||
callback()
|
||||
return
|
||||
password_ok = False
|
||||
count = 0
|
||||
title = _('Passphrase Required')
|
||||
second = _('Enter GPG key passphrase for account %s.') % account
|
||||
while not password_ok and count < 3:
|
||||
count += 1
|
||||
w = dialogs.PassphraseDialog(title, second, '')
|
||||
passphrase, save = w.run()
|
||||
if passphrase == -1:
|
||||
# User pressed cancel
|
||||
passphrase = None
|
||||
password_ok = True
|
||||
else:
|
||||
password_ok = gajim.connections[account].\
|
||||
test_gpg_passphrase(passphrase)
|
||||
title = _('Wrong Passphrase')
|
||||
second = _('Please retype your GPG passphrase or press Cancel.')
|
||||
if passphrase != None:
|
||||
self.gpg_passphrase[keyid] = passphrase
|
||||
gobject.timeout_add(30000, self.forget_gpg_passphrase, keyid)
|
||||
gajim.connections[account].gpg_passphrase(passphrase)
|
||||
callback()
|
||||
|
||||
def handle_event_roster_info(self, account, array):
|
||||
#('ROSTER_INFO', account, (jid, name, sub, ask, groups))
|
||||
jid = array[0]
|
||||
|
@ -2463,6 +2499,7 @@ class Interface:
|
|||
self.handle_event_unique_room_id_unsupported,
|
||||
'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported,
|
||||
'SESSION_NEG': self.handle_session_negotiation,
|
||||
'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required,
|
||||
}
|
||||
gajim.handlers = self.handlers
|
||||
|
||||
|
@ -2578,6 +2615,7 @@ class Interface:
|
|||
self.minimized_controls = {}
|
||||
self.status_sent_to_users = {}
|
||||
self.status_sent_to_groups = {}
|
||||
self.gpg_passphrase = {}
|
||||
self.default_colors = {
|
||||
'inmsgcolor': gajim.config.get('inmsgcolor'),
|
||||
'outmsgcolor': gajim.config.get('outmsgcolor'),
|
||||
|
|
|
@ -1498,9 +1498,10 @@ class RosterWindow:
|
|||
name = account_name, show = connection.get_status(), sub = '',
|
||||
status = connection.status,
|
||||
resource = connection.server_resource,
|
||||
priority = connection.priority,
|
||||
keyID = gajim.config.get_per('accounts', connection.name,
|
||||
'keyid'))
|
||||
priority = connection.priority)
|
||||
if gajim.connections[account].gpg:
|
||||
contact.keyID = gajim.config.get_per('accounts', connection.name,
|
||||
'keyid')
|
||||
contacts.append(contact)
|
||||
# if we're online ...
|
||||
if connection.connection:
|
||||
|
@ -3426,11 +3427,6 @@ class RosterWindow:
|
|||
on_response_ok = (on_ok2, list_))
|
||||
|
||||
|
||||
def forget_gpg_passphrase(self, keyid):
|
||||
if self.gpg_passphrase.has_key(keyid):
|
||||
del self.gpg_passphrase[keyid]
|
||||
return False
|
||||
|
||||
def set_connecting_state(self, account):
|
||||
model = self.tree.get_model()
|
||||
accountIter = self.get_account_iter(account)
|
||||
|
@ -3468,46 +3464,10 @@ class RosterWindow:
|
|||
gajim.config.set_per('accounts', account, 'savepass', True)
|
||||
passwords.save_password(account, passphrase)
|
||||
|
||||
keyid = None
|
||||
use_gpg_agent = gajim.config.get('use_gpg_agent')
|
||||
# we don't need to bother with the passphrase if we use the agent
|
||||
keyid = gajim.config.get_per('accounts', account, 'keyid')
|
||||
if keyid and not gajim.config.get('usegpg'):
|
||||
dialog = dialogs.WarningDialog(_('GPG is not usable'), _('You will be connected to %s without OpenPGP.') % account)
|
||||
if keyid and gajim.connections[account].connected < 2 and \
|
||||
gajim.config.get('usegpg'):
|
||||
|
||||
if use_gpg_agent:
|
||||
self.gpg_passphrase[keyid] = None
|
||||
else:
|
||||
if self.gpg_passphrase.has_key(keyid):
|
||||
passphrase = self.gpg_passphrase[keyid]
|
||||
save = False
|
||||
else:
|
||||
password_ok = False
|
||||
count = 0
|
||||
title = _('Passphrase Required')
|
||||
second = _('Enter GPG key passphrase for account %s.') % \
|
||||
account
|
||||
while not password_ok and count < 3:
|
||||
count += 1
|
||||
w = dialogs.PassphraseDialog(title, second,
|
||||
_('Save passphrase'))
|
||||
passphrase, save = w.run()
|
||||
if passphrase == -1:
|
||||
passphrase = None
|
||||
password_ok = True
|
||||
else:
|
||||
password_ok = gajim.connections[account].\
|
||||
test_gpg_passphrase(passphrase)
|
||||
title = _('Wrong Passphrase')
|
||||
second = _('Please retype your GPG passphrase or '
|
||||
'press Cancel.')
|
||||
if passphrase != None:
|
||||
self.gpg_passphrase[keyid] = passphrase
|
||||
gobject.timeout_add(30000, self.forget_gpg_passphrase,
|
||||
keyid)
|
||||
gajim.connections[account].gpg_passphrase(passphrase)
|
||||
keyid = gajim.config.get_per('accounts', account, 'keyid')
|
||||
if keyid and not common.connection.USE_GPG:
|
||||
dialog = dialogs.WarningDialog(_('GPG is not usable'),
|
||||
_('You will be connected to %s without OpenPGP.') % account)
|
||||
|
||||
if gajim.account_is_connected(account):
|
||||
if status == 'online' and gajim.interface.sleeper.getState() != \
|
||||
|
@ -5302,7 +5262,6 @@ class RosterWindow:
|
|||
|
||||
self.popups_notification_height = 0
|
||||
self.popup_notification_windows = []
|
||||
self.gpg_passphrase = {}
|
||||
|
||||
#(icon, name, type, jid, account, editable, secondary_pixbuf)
|
||||
model = gtk.TreeStore(gtk.Image, str, str, str, str, gtk.gdk.Pixbuf)
|
||||
|
|
Loading…
Reference in New Issue