updated gotr to version 1.5

This commit is contained in:
Kjell Braden
2012-04-16 21:37:24 +02:00
parent 38efc8c3b4
commit b4927cd30d
2 changed files with 64 additions and 32 deletions

View File

@@ -1,7 +1,7 @@
[info] [info]
name: Off-The-Record Encryption name: Off-The-Record Encryption
short_name: gotr short_name: gotr
version: 1.4 version: 1.5
description: See http://www.cypherpunks.ca/otr/ description: See http://www.cypherpunks.ca/otr/
authors: Kjell Braden <afflux.gajim@pentabarf.de> authors: Kjell Braden <afflux.gajim@pentabarf.de>
homepage: http://gajim-otr.pentabarf.de homepage: http://gajim-otr.pentabarf.de

View File

@@ -24,12 +24,12 @@
Off-The-Record encryption plugin. Off-The-Record encryption plugin.
:author: Kjell self.Braden <kb.otr@pentabarf.de> :author: Kjell self.Braden <kb.otr@pentabarf.de>
:since: 20 May 2011 :since: 2008
:copyright: Copyright (2011) Kjell Braden <kb.otr@pentabarf.de> :copyright: Copyright 2008-2012 Kjell Braden <afflux@pentabarf.de>
:license: GPL :license: GPL
''' '''
MINVERSION = (1,0,0,'beta4') MINVERSION = (1,0,0,'beta5')
IGNORE = True IGNORE = True
PASS = False PASS = False
@@ -77,11 +77,18 @@ try:
except ImportError: except ImportError:
HAS_POTR = False HAS_POTR = False
def get_jid_from_fjid(fjid):
return gajim.get_room_and_nick_from_fjid(fjid)[0]
class GajimContext(potr.context.Context): class GajimContext(potr.context.Context):
__slots__ = ['smpWindow'] # self.peer is fjid
# self.jid does not contain resource
__slots__ = ['smpWindow', 'jid']
def __init__(self, account, peer): def __init__(self, account, peer):
super(GajimContext, self).__init__(account, peer) super(GajimContext, self).__init__(account, peer)
self.jid = get_jid_from_fjid(peer)
self.trustName = self.jid
self.smpWindow = ui.ContactOtrSmpWindow(self) self.smpWindow = ui.ContactOtrSmpWindow(self)
def inject(self, msg, appdata=None): def inject(self, msg, appdata=None):
@@ -137,8 +144,7 @@ class GajimContext(potr.context.Context):
self.user.plugin.update_context_list() self.user.plugin.update_context_list()
def getPolicy(self, key): def getPolicy(self, key):
jid = gajim.get_room_and_nick_from_fjid(self.peer)[0] ret = self.user.plugin.get_flags(self.user.accountname, self.jid)[key]
ret = self.user.plugin.get_flags(self.user.accountname, jid)[key]
log.debug('getPolicy(key=%s) = %s', key, ret) log.debug('getPolicy(key=%s) = %s', key, ret)
return ret return ret
@@ -191,7 +197,8 @@ class GajimOtrAccount(potr.context.Account):
if acc != self.name or proto != PROTOCOL: if acc != self.name or proto != PROTOCOL:
continue continue
self.getContext(ctx, newCtxCb).setTrust(fpr, trust) jid = get_jid_from_fjid(ctx)
self.setTrust(jid, fpr, trust)
except IOError, e: except IOError, e:
if e.errno != 2: if e.errno != 2:
log.exception('IOError occurred when loading fpr file for %s', log.exception('IOError occurred when loading fpr file for %s',
@@ -200,10 +207,10 @@ class GajimOtrAccount(potr.context.Account):
def saveTrusts(self): def saveTrusts(self):
try: try:
with open(self.keyFilePath + '.fpr', 'w') as fprFile: with open(self.keyFilePath + '.fpr', 'w') as fprFile:
for uid, ctx in self.ctxs.iteritems(): for uid, trusts in self.trusts.iteritems():
for fpr, trust in ctx.trust.iteritems(): for fpr, trustVal in trusts.iteritems():
fprFile.write('\t'.join( fprFile.write('\t'.join(
(uid, self.name, PROTOCOL, fpr, trust))) (uid, self.name, PROTOCOL, fpr, trustVal)))
fprFile.write('\n') fprFile.write('\n')
except IOError, e: except IOError, e:
log.exception('IOError occurred when loading fpr file for %s', log.exception('IOError occurred when loading fpr file for %s',
@@ -237,6 +244,7 @@ class OtrPlugin(GajimPlugin):
acc = str(acc) acc = str(acc)
if acc not in self.config or None not in self.config[acc]: if acc not in self.config or None not in self.config[acc]:
self.config[acc] = {None:DEFAULTFLAGS.copy()} self.config[acc] = {None:DEFAULTFLAGS.copy()}
self.update_context_list()
@log_calls('OtrPlugin') @log_calls('OtrPlugin')
def activate(self): def activate(self):
@@ -370,27 +378,42 @@ class OtrPlugin(GajimPlugin):
def update_context_list(self): def update_context_list(self):
self.config_dialog.fpr_model.clear() self.config_dialog.fpr_model.clear()
for us in self.us.itervalues(): for us in self.us.itervalues():
for uid, ctx in us.ctxs.iteritems(): usedFpr = set()
for fpr, trust in ctx.trust.iteritems(): for fjid, ctx in us.ctxs.iteritems():
trust = False # get active contexts first
if ctx.state == potr.context.STATE_ENCRYPTED: key = ctx.getCurrentKey()
if ctx.getCurrentKey().cfingerprint() == fpr: if not key:
state = "encrypted" continue
tip = enc_tip fpr = key.cfingerprint()
trust = bool(ctx.getCurrentTrust()) usedFpr.add(fpr)
else:
state = "unused" human_hash = potr.human_hash(fpr)
tip = unused_tip trust = bool(us.getTrust(ctx.trustName, fpr))
elif ctx.state == potr.context.STATE_FINISHED:
state = "finished" if ctx.state == potr.context.STATE_ENCRYPTED:
tip = ended_tip state = "encrypted"
else: tip = enc_tip
state = 'inactive' elif ctx.state == potr.context.STATE_FINISHED:
tip = inactive_tip state = "finished"
tip = ended_tip
else:
state = 'inactive'
tip = inactive_tip
self.config_dialog.fpr_model.append((fjid, state, trust,
'<tt>%s</tt>' % human_hash, us.name, tip, fpr))
for uid, trusts in us.trusts.iteritems():
for fpr, trust in trusts.iteritems():
if fpr in usedFpr:
continue
state = 'inactive'
tip = inactive_tip
human_hash = potr.human_hash(fpr) human_hash = potr.human_hash(fpr)
self.config_dialog.fpr_model.append((uid, state, trust, self.config_dialog.fpr_model.append((uid, state, bool(trust),
'<tt>%s</tt>' % human_hash, us.name, tip, fpr)) '<tt>%s</tt>' % human_hash, us.name, tip, fpr))
@classmethod @classmethod
@@ -470,22 +493,31 @@ class OtrPlugin(GajimPlugin):
ctx = self.us[account].getContext(event.fjid) ctx = self.us[account].getContext(event.fjid)
msgtxt, tlvs = ctx.receiveMessage(event.msgtxt, msgtxt, tlvs = ctx.receiveMessage(event.msgtxt,
appdata={'session':event.session}) appdata={'session':event.session})
except potr.context.NotOTRMessage, e:
# received message was not OTR - pass it on
return PASS
except potr.context.UnencryptedMessage, e: except potr.context.UnencryptedMessage, e:
# we are encrypted but got some plaintext
# display it with a warning
tlvs = [] tlvs = []
msgtxt = _('The following message received from %(jid)s was ' msgtxt = _('The following message received from %(jid)s was '
'*not encrypted*: [%(error)s]') % {'jid': event.fjid, '*not encrypted*: [%(error)s]') % {'jid': event.fjid,
'error': e.args[0]} 'error': e.args[0]}
except potr.context.NotEncryptedError, e: except potr.context.NotEncryptedError, e:
# we got some encrypted data
# but we don't have an encrypted session
self.gajim_log(_('The encrypted message received from %s is ' self.gajim_log(_('The encrypted message received from %s is '
'unreadable, as you are not currently communicating ' 'unreadable, as you are not currently communicating '
'privately') % event.fjid, account, event.fjid) 'privately') % event.fjid, account, event.fjid)
return IGNORE return IGNORE
except potr.context.ErrorReceived, e: except potr.context.ErrorReceived, e:
# got a protocol error
self.gajim_log(_('We received the following OTR error ' self.gajim_log(_('We received the following OTR error '
'message from %(jid)s: [%(error)s]') % {'jid': event.fjid, 'message from %(jid)s: [%(error)s]') % {'jid': event.fjid,
'error': e.args[0].error}) 'error': e.args[0].error})
return IGNORE return IGNORE
except RuntimeError, e: except RuntimeError, e:
# generic library bug?
self.gajim_log(_('The following error occurred when trying to ' self.gajim_log(_('The following error occurred when trying to '
'decrypt a message from %(jid)s: [%(error)s]') % { 'decrypt a message from %(jid)s: [%(error)s]') % {
'jid': event.fjid, 'error': e}, 'jid': event.fjid, 'error': e},
@@ -494,12 +526,12 @@ class OtrPlugin(GajimPlugin):
if ctx is not None: if ctx is not None:
ctx.smpWindow.handle_tlv(tlvs) ctx.smpWindow.handle_tlv(tlvs)
if not msgtxt:
return IGNORE
event.msgtxt = unicode(msgtxt) event.msgtxt = unicode(msgtxt or '')
event.stanza.setBody(event.msgtxt) event.stanza.setBody(event.msgtxt)
# every message that went through OTR (ie. was OTR-related) gets
# stripped from html. I don't like html.
html_node = event.stanza.getTag('html') html_node = event.stanza.getTag('html')
if html_node: if html_node:
event.stanza.delChild(html_node) event.stanza.delChild(html_node)