realtime notification of esession begin/end
This commit is contained in:
parent
00ad2846c0
commit
88f017a20d
|
@ -1057,10 +1057,7 @@ class ChatControl(ChatControlBase):
|
|||
if self.contact.jid in gajim.encrypted_chats[self.account]:
|
||||
self.xml.get_widget('gpg_togglebutton').set_active(True)
|
||||
|
||||
self.session = session
|
||||
|
||||
# does this window have an existing, active esession?
|
||||
self.esessioned = False
|
||||
self.set_session(session)
|
||||
|
||||
self.status_tooltip = gtk.Tooltips()
|
||||
self.update_ui()
|
||||
|
@ -1467,6 +1464,23 @@ class ChatControl(ChatControlBase):
|
|||
self.mouse_over_in_last_30_secs = False
|
||||
self.kbd_activity_in_last_30_secs = False
|
||||
|
||||
|
||||
# print esession settings to textview
|
||||
def print_esession_details(self):
|
||||
if self.session and self.session.enable_encryption:
|
||||
msg = _('E2E encryption enabled')
|
||||
ChatControlBase.print_conversation_line(self, msg, 'status', '', None)
|
||||
|
||||
if self.session.loggable:
|
||||
msg = _('Session WILL be logged')
|
||||
else:
|
||||
msg = _('Session WILL NOT be logged')
|
||||
|
||||
ChatControlBase.print_conversation_line(self, msg, 'status', '', None)
|
||||
else:
|
||||
msg = _('E2E encryption disabled')
|
||||
ChatControlBase.print_conversation_line(self, msg, 'status', '', None)
|
||||
|
||||
def print_conversation(self, text, frm = '', tim = None,
|
||||
encrypted = False, subject = None, xhtml = None):
|
||||
'''Print a line in the conversation:
|
||||
|
@ -1486,41 +1500,21 @@ class ChatControl(ChatControlBase):
|
|||
kind = 'info'
|
||||
name = ''
|
||||
else:
|
||||
# ESessions
|
||||
if self.session and self.session.enable_encryption:
|
||||
if not self.esessioned:
|
||||
msg = _('Encryption enabled')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
|
||||
if self.session.loggable:
|
||||
msg = _('Session WILL be logged')
|
||||
else:
|
||||
msg = _('Session WILL NOT be logged')
|
||||
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
|
||||
self.esessioned = True
|
||||
elif not encrypted:
|
||||
if not encrypted:
|
||||
msg = _('The following message was NOT encrypted')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
elif self.esessioned:
|
||||
msg = _('Encryption disabled')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
self.esessioned = False
|
||||
else:
|
||||
# GPG encryption
|
||||
ec = gajim.encrypted_chats[self.account]
|
||||
if encrypted and jid not in ec:
|
||||
msg = _('Encryption enabled')
|
||||
msg = _('OpenPGP Encryption enabled')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
ec.append(jid)
|
||||
elif not encrypted and jid in ec:
|
||||
msg = _('Encryption disabled')
|
||||
msg = _('OpenPGP Encryption disabled')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', tim)
|
||||
ec.remove(jid)
|
||||
|
@ -2003,12 +1997,16 @@ class ChatControl(ChatControlBase):
|
|||
|
||||
def read_queue(self):
|
||||
'''read queue and print messages containted in it'''
|
||||
|
||||
jid = self.contact.jid
|
||||
jid_with_resource = jid
|
||||
if self.resource:
|
||||
jid_with_resource += '/' + self.resource
|
||||
events = gajim.events.get_events(self.account, jid_with_resource)
|
||||
|
||||
if hasattr(self, 'session') and self.session and self.session.enable_encryption:
|
||||
self.print_esession_details()
|
||||
|
||||
# Is it a pm ?
|
||||
is_pm = False
|
||||
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
|
||||
|
@ -2169,18 +2167,18 @@ class ChatControl(ChatControlBase):
|
|||
msg = _('Encryption disabled')
|
||||
ChatControlBase.print_conversation_line(self, msg,
|
||||
'status', '', None)
|
||||
self.esessioned = False
|
||||
|
||||
jid = str(self.session.jid)
|
||||
|
||||
gajim.connections[self.account].delete_session(jid,
|
||||
self.session.thread_id)
|
||||
|
||||
self.session = gajim.connections[self.account].make_new_session(jid)
|
||||
self.set_session(gajim.connections[self.account].make_new_session(jid))
|
||||
else:
|
||||
if not self.session:
|
||||
self.session = gajim.connections[self.account].make_new_session(
|
||||
self.contact.jid)
|
||||
fjid = self.contact.get_full_jid()
|
||||
new_sess = gajim.connections[self.account].make_new_session(fjid)
|
||||
self.set_session(new_sess)
|
||||
|
||||
# XXX decide whether to use 4 or 3 message negotiation
|
||||
self.session.negotiate_e2e(False)
|
||||
|
|
|
@ -71,8 +71,10 @@ class StanzaSession(object):
|
|||
def cancelled_negotiation(self):
|
||||
'''A negotiation has been cancelled, so reset this session to its default state.'''
|
||||
|
||||
# XXX notify the user
|
||||
|
||||
if hasattr(self, 'control'):
|
||||
msg = _('Session negotiation cancelled')
|
||||
self.control.print_conversation_line(self, msg, 'status', '', None)
|
||||
|
||||
self.status = None
|
||||
self.negotiated = {}
|
||||
|
||||
|
@ -92,7 +94,7 @@ class StanzaSession(object):
|
|||
self.status = None
|
||||
|
||||
def acknowledge_termination(self):
|
||||
# we could send an acknowledgement message here, but we won't.
|
||||
# we could send an acknowledgement message to the remote client here
|
||||
self.status = None
|
||||
|
||||
if gajim.HAVE_PYCRYPTO:
|
||||
|
@ -105,7 +107,7 @@ if gajim.HAVE_PYCRYPTO:
|
|||
import secrets
|
||||
|
||||
# an encrypted stanza negotiation has several states. i've represented them
|
||||
# as the following values in the 'status'
|
||||
# as the following values in the 'status'
|
||||
# attribute of the session object:
|
||||
|
||||
# 1. None:
|
||||
|
@ -143,7 +145,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
|
||||
# _s denotes 'self' (ie. this client)
|
||||
self._kc_s = None
|
||||
|
||||
|
||||
# _o denotes 'other' (ie. the client at the other end of the session)
|
||||
self._kc_o = None
|
||||
|
||||
|
@ -161,17 +163,17 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
self._kc_o = value
|
||||
self.decrypter = self.cipher.new(self._kc_o, self.cipher.MODE_CTR,
|
||||
counter=self.decryptcounter)
|
||||
|
||||
|
||||
def get_kc_o(self):
|
||||
return self._kc_o
|
||||
|
||||
kc_s = property(get_kc_s, set_kc_s)
|
||||
kc_o = property(get_kc_o, set_kc_o)
|
||||
|
||||
|
||||
def encryptcounter(self):
|
||||
self.c_s = (self.c_s + 1) % (2 ** self.n)
|
||||
return crypto.encode_mpi_with_padding(self.c_s)
|
||||
|
||||
|
||||
def decryptcounter(self):
|
||||
self.c_o = (self.c_o + 1) % (2 ** self.n)
|
||||
return crypto.encode_mpi_with_padding(self.c_o)
|
||||
|
@ -231,7 +233,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
|
||||
def decompress(self, compressed):
|
||||
if self.compression == None:
|
||||
return compressed
|
||||
return compressed
|
||||
|
||||
def encrypt(self, encryptable):
|
||||
padded = crypto.pad_to_multiple(encryptable, 16, ' ', False)
|
||||
|
@ -343,7 +345,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
content += self.form_o + form_o2
|
||||
|
||||
mac_o_calculated = self.hmac(self.ks_o, content)
|
||||
|
||||
|
||||
if self.negotiated['recv_pubkey']:
|
||||
hash = crypto.sha256(mac_o_calculated)
|
||||
|
||||
|
@ -380,7 +382,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
if self.negotiated['send_pubkey'] == 'hash':
|
||||
b64ed = base64.b64encode(self.hash(pubkey_s))
|
||||
pubkey_s = '<fingerprint>%s</fingerprint>' % b64ed
|
||||
|
||||
|
||||
id_s = self.encrypt(pubkey_s + sign_s)
|
||||
else:
|
||||
id_s = self.encrypt(mac_s)
|
||||
|
@ -395,7 +397,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
if self.sigmai:
|
||||
# XXX save retained secret?
|
||||
self.check_identity(lambda : ())
|
||||
|
||||
|
||||
return (xmpp.DataField(name='identity', value=base64.b64encode(id_s)), \
|
||||
xmpp.DataField(name='mac', value=base64.b64encode(m_s)))
|
||||
|
||||
|
@ -437,7 +439,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
x.addChild(node=xmpp.DataField(name='sign_algs', value='http://www.w3.org/2000/09/xmldsig#rsa-sha256', typ='hidden'))
|
||||
|
||||
self.n_s = crypto.generate_nonce()
|
||||
|
||||
|
||||
x.addChild(node=xmpp.DataField(name='my_nonce', value=base64.b64encode(self.n_s), typ='hidden'))
|
||||
|
||||
modp_options = [ 5, 14, 2, 1 ]
|
||||
|
@ -454,7 +456,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
self.status = 'requested-e2e'
|
||||
|
||||
self.send(request)
|
||||
|
||||
|
||||
# 4.3 esession response (bob)
|
||||
def verify_options_bob(self, form):
|
||||
negotiated = {'recv_pubkey': None, 'send_pubkey': None}
|
||||
|
@ -570,8 +572,8 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
self.d = crypto.powmod(g, self.y, p)
|
||||
|
||||
to_add = { 'my_nonce': self.n_s,
|
||||
'dhkeys': crypto.encode_mpi(self.d),
|
||||
'counter': crypto.encode_mpi(self.c_o),
|
||||
'dhkeys': crypto.encode_mpi(self.d),
|
||||
'counter': crypto.encode_mpi(self.c_o),
|
||||
'nonce': self.n_o }
|
||||
|
||||
for name in to_add:
|
||||
|
@ -666,7 +668,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
self.kc_o, self.km_o, self.ks_o = self.generate_responder_keys(self.k)
|
||||
self.verify_identity(form, self.d, True, 'b')
|
||||
else:
|
||||
srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped())
|
||||
srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped())
|
||||
rshashes = [self.hmac(self.n_s, rs) for (rs,v) in srses]
|
||||
|
||||
if not rshashes:
|
||||
|
@ -677,7 +679,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
rshashes = [base64.b64encode(rshash) for rshash in rshashes]
|
||||
result.addChild(node=xmpp.DataField(name='rshashes', value=rshashes))
|
||||
result.addChild(node=xmpp.DataField(name='dhkeys', value=base64.b64encode(crypto.encode_mpi(e))))
|
||||
|
||||
|
||||
self.form_o = ''.join(map(lambda el: xmpp.c14n.c14n(el), form.getChildren()))
|
||||
|
||||
# MUST securely destroy K unless it will be used later to generate the final shared secret
|
||||
|
@ -687,13 +689,13 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
|
||||
feature.addChild(node=result)
|
||||
self.send(accept)
|
||||
|
||||
|
||||
if self.sigmai:
|
||||
self.status = 'active'
|
||||
self.enable_encryption = True
|
||||
else:
|
||||
self.status = 'identified-alice'
|
||||
|
||||
|
||||
# 4.5 esession accept (bob)
|
||||
def accept_e2e_bob(self, form):
|
||||
response = xmpp.Message()
|
||||
|
@ -724,7 +726,7 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
# 4.5.4 generating bob's final session keys
|
||||
|
||||
srs = ''
|
||||
|
||||
|
||||
srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped())
|
||||
rshashes = [base64.b64decode(rshash) for rshash in form.getField('rshashes').getValues()]
|
||||
|
||||
|
@ -767,6 +769,9 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
self.status = 'active'
|
||||
self.enable_encryption = True
|
||||
|
||||
if hasattr(self, 'control'):
|
||||
self.control.print_esession_details()
|
||||
|
||||
def final_steps_alice(self, form):
|
||||
srs = ''
|
||||
srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped())
|
||||
|
@ -793,13 +798,16 @@ class EncryptedStanzaSession(StanzaSession):
|
|||
|
||||
self.verify_identity(form, self.d, False, 'b')
|
||||
# Note: If Alice discovers an error then she SHOULD ignore any encrypted content she received in the stanza.
|
||||
|
||||
|
||||
if self.negotiated['logging'] == 'mustnot':
|
||||
self.loggable = False
|
||||
|
||||
self.status = 'active'
|
||||
self.enable_encryption = True
|
||||
|
||||
if hasattr(self, 'control'):
|
||||
self.control.print_esession_details()
|
||||
|
||||
# calculate and store the new retained secret
|
||||
# prompt the user to check the remote party's identity (if necessary)
|
||||
def do_retained_secret(self, k, srs):
|
||||
|
|
|
@ -2031,7 +2031,8 @@ class Interface:
|
|||
ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account)
|
||||
|
||||
if ctrl:
|
||||
ctrl.session = gajim.connections[account].make_new_session(str(jid))
|
||||
new_sess = gajim.connections[account].make_new_session(str(jid))
|
||||
ctrl.set_session(new_sess)
|
||||
|
||||
return
|
||||
|
||||
|
@ -2044,7 +2045,8 @@ class Interface:
|
|||
contact = gajim.contacts.get_contact(account, str(jid), resource)
|
||||
if not contact:
|
||||
connection = gajim.connections[account]
|
||||
contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status())
|
||||
contact = gajim.contacts.create_contact(jid = jid.getStripped(),
|
||||
resource = resource, show = connection.get_status())
|
||||
self.roster.new_chat(contact, account, resource = resource)
|
||||
|
||||
ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account)
|
||||
|
|
|
@ -117,15 +117,26 @@ class MessageControl:
|
|||
return len(gajim.events.get_events(self.account, self.contact.jid))
|
||||
|
||||
def set_session(self, session):
|
||||
if session == self.session:
|
||||
if hasattr(self, 'session') and session == self.session:
|
||||
return
|
||||
|
||||
if self.session:
|
||||
was_encrypted = False
|
||||
|
||||
if hasattr(self, 'session') and self.session:
|
||||
if self.session.enable_encryption:
|
||||
was_encrypted = True
|
||||
|
||||
print "starting a new session, dropping the old one!"
|
||||
gajim.connections[self.account].delete_session(self.session.jid, self.session.thread_id)
|
||||
|
||||
self.session = session
|
||||
|
||||
if session:
|
||||
session.control = self
|
||||
|
||||
if was_encrypted:
|
||||
self.print_esession_details()
|
||||
|
||||
def send_message(self, message, keyID = '', type = 'chat',
|
||||
chatstate = None, msg_id = None, composing_xep = None, resource = None,
|
||||
user_nick = None):
|
||||
|
@ -134,7 +145,10 @@ class MessageControl:
|
|||
jid = self.contact.jid
|
||||
|
||||
if not self.session:
|
||||
self.session = gajim.connections[self.account].make_new_session(self.contact.get_full_jid())
|
||||
fjid = self.contact.get_full_jid()
|
||||
new_session = gajim.connections[self.account].make_new_session(fjid)
|
||||
|
||||
self.set_session(new_session)
|
||||
|
||||
# Send and update history
|
||||
return gajim.connections[self.account].send_message(jid, message, keyID,
|
||||
|
|
Loading…
Reference in New Issue