request GPG password only when connected to server, before sending presence. fixes #3483, #3375, #3115

This commit is contained in:
Yann Leboulanger 2007-11-22 10:41:57 +00:00
parent e52be0071b
commit 0ceb41f650
4 changed files with 142 additions and 119 deletions

View File

@ -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

View File

@ -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):

View File

@ -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'),

View File

@ -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)