comparison sat/memory/encryption.py @ 2651:ebcff5423465

core (memory/encryption): start improvments, stop and getSession: - "start" won't do anything if session is already encrypted with requested algorithm, and will raise a ConflictError if it's already encrypted but with an other algorithm - implemented "stop", with an optional namespace to check we are stopping the expected algorithm - "getSession" retrieve the current encryption session of a jid, if any
author Goffi <goffi@goffi.org>
date Sat, 11 Aug 2018 18:24:55 +0200
parents 712cb4ff3e13
children 4e130cc9bfc0
comparison
equal deleted inserted replaced
2650:3a8e7ec4648a 2651:ebcff5423465
59 name=name, 59 name=name,
60 namespace=namespace, 60 namespace=namespace,
61 priority=priority) 61 priority=priority)
62 cls.plugins.append(plg) 62 cls.plugins.append(plg)
63 cls.plugins.sort(key=lambda p: p.priority) 63 cls.plugins.sort(key=lambda p: p.priority)
64 log.info(_(u"Encryption plugin registered: {name}").format(name=name))
64 65
65 def start(self, entity, namespace=None): 66 def start(self, entity, namespace=None):
66 """Start an encrypted session with an entity 67 """Start an encrypted session with an entity
67 68
68 @param entity(jid.JID): entity to start an encrypted session with 69 @param entity(jid.JID): entity to start an encrypted session with
72 """ 73 """
73 if not self.plugins: 74 if not self.plugins:
74 raise exceptions.NotFound(_(u"No encryption plugin is registered, " 75 raise exceptions.NotFound(_(u"No encryption plugin is registered, "
75 u"an encryption session can't be started")) 76 u"an encryption session can't be started"))
76 77
77 bare_jid = entity.userhostJID()
78 if bare_jid in self._sessions:
79 plg = self._sessions[bare_jid]['plugin']
80
81 msg = (_(u"Session with {bare_jid} is already encrypted with {name}."
82 u"Please stop encryption session before changing algorithm.")
83 .format(bare_jid=bare_jid, name=plg.name))
84 log.warning(msg)
85 raise exceptions.ConflictError(msg)
86
87 if namespace is None: 78 if namespace is None:
88 plg = self.plugins[0] 79 plg = self.plugins[0]
89 else: 80 else:
90 try: 81 try:
91 plg = next(p for p in self.plugins if p.namespace == namespace) 82 plg = next(p for p in self.plugins if p.namespace == namespace)
92 except StopIteration: 83 except StopIteration:
93 raise exceptions.NotFound(_( 84 raise exceptions.NotFound(_(
94 u"Can't find requested encryption plugin: {namespace}").format( 85 u"Can't find requested encryption plugin: {namespace}").format(
95 namespace=namespace)) 86 namespace=namespace))
96 87
88 bare_jid = entity.userhostJID()
89 if bare_jid in self._sessions:
90 plg = self._sessions[bare_jid]['plugin']
91 if plg.namespace == namespace:
92 log.info(_(u"Session with {bare_jid} is already encrypted with {name}."
93 u"Nothing to do.")
94 .format(bare_jid=bare_jid, name=plg.name))
95 return
96
97 msg = (_(u"Session with {bare_jid} is already encrypted with {name}. "
98 u"Please stop encryption session before changing algorithm.")
99 .format(bare_jid=bare_jid, name=plg.name))
100 log.warning(msg)
101 raise exceptions.ConflictError(msg)
102
97 data = {"plugin": plg} 103 data = {"plugin": plg}
98 if entity.resource: 104 if entity.resource:
99 # indicate that we encrypt only for some devices 105 # indicate that we encrypt only for some devices
100 data['directed_devices'] = [entity.resource] 106 data['directed_devices'] = [entity.resource]
101 107
102 self._sessions[entity.userhostJID()] = data 108 self._sessions[entity.userhostJID()] = data
103 log.info(_(u"Encryption session as been set for {bare_jid} with " 109 log.info(_(u"Encryption session has been set for {bare_jid} with "
104 u"{encryption_name}").format( 110 u"{encryption_name}").format(
105 bare_jid=bare_jid.userhost(), encryption_name=plg.name)) 111 bare_jid=bare_jid.userhost(), encryption_name=plg.name))
112
113 def stop(self, entity, namespace=None):
114 """Stop an encrypted session with an entity
115
116 @param entity(jid.JID): entity with who the encrypted session must be stopped
117 must be bare jid is the algorithm encrypt for all devices
118 @param namespace(unicode): namespace of the session to stop
119 when specified, used to check we stop the right encryption session
120 """
121 session = self.getSession(entity.userhostJID())
122 if not session:
123 raise exceptions.NotFound(_(u"There is no encrypted session with this "
124 u"entity."))
125 if namespace is not None and session[u'plugin'].namespace != namespace:
126 raise exceptions.InternalError(_(
127 u"The encrypted session is not run with the expected plugin: encrypted "
128 u"with {current_name} and was expecting {expected_name}").format(
129 current_name=session[u'plugin'].namespace,
130 expected_name=namespace))
131 if entity.resource:
132 try:
133 directed_devices = session[u'directed_devices']
134 except KeyError:
135 raise exceptions.NotFound(_(
136 u"There is a session for the whole entity (i.e. all devices of the "
137 u"entity), not a directed one. Please use bare jid if you want to "
138 u"stop the whole encryption with this entity."))
139
140 try:
141 directed_devices.remove(entity.resource)
142 except ValueError:
143 raise exceptions.NotFound(_(u"There is no directed session with this "
144 u"entity."))
145 else:
146 del self._sessions[entity]
147
148 log.info(_(u"Encrypted session stopped with entity {entity}").format(
149 entity=entity.full()))
150
151 def getSession(self, entity):
152 """Get encryption session for this contact
153
154 @param entity(jid.JID): get the session for this entity
155 must be a bare jid
156 @return (dict, None): encrypted session data
157 None if there is not encryption for this session with this jid
158 """
159 if entity.resource:
160 raise exceptions.InternalError(u"Full jid given when expecting bare jid")
161 return self._sessions.get(entity)
106 162
107 ## Triggers ## 163 ## Triggers ##
108 164
109 def setEncryptionFlag(self, mess_data): 165 def setEncryptionFlag(self, mess_data):
110 """Set "encryption" key in mess_data if session with destinee is encrypted""" 166 """Set "encryption" key in mess_data if session with destinee is encrypted"""