comparison sat/memory/encryption.py @ 2733:e347e32aa07f

core (memory/encryption): new encryptionNamespaceGet and encryptionTrustUIGet methods: - encryptionNamespaceGet retrieves algorithm namespace from its short name - encryptionTrustUIGet retrieves trust mangement XMLUI from encryption plugin - new markAsUntrusted internal helper method, to add untrusted flag to message data
author Goffi <goffi@goffi.org>
date Wed, 02 Jan 2019 18:22:30 +0100
parents 4e130cc9bfc0
children da59ff099b32
comparison
equal deleted inserted replaced
2732:e55f871fa9db 2733:e347e32aa07f
49 def registerPlugin(cls, plg_instance, name, namespace, priority=0, directed=False): 49 def registerPlugin(cls, plg_instance, name, namespace, priority=0, directed=False):
50 """Register a plugin handling an encryption algorithm 50 """Register a plugin handling an encryption algorithm
51 51
52 @param plg_instance(object): instance of the plugin 52 @param plg_instance(object): instance of the plugin
53 it must have the following methods: 53 it must have the following methods:
54 - startEncryption(jid.JID): start an encryption session with a bare jid 54 - getTrustUI(entity): return a XMLUI for trust management
55 - stopEncryption(jid.JID): stop an encryption session with a bare jid 55 entity(jid.JID): entity to manage
56 The returned XMLUI must be a form
57
56 @param name(unicode): human readable name of the encryption algorithm 58 @param name(unicode): human readable name of the encryption algorithm
57 @param namespace(unicode): namespace of the encryption algorithm 59 @param namespace(unicode): namespace of the encryption algorithm
58 @param priority(int): priority of this plugin to encrypt an message when not 60 @param priority(int): priority of this plugin to encrypt an message when not
59 selected manually 61 selected manually
60 @param directed(bool): True if this plugin is directed (if it works with one 62 @param directed(bool): True if this plugin is directed (if it works with one
82 @classmethod 84 @classmethod
83 def getPlugins(cls): 85 def getPlugins(cls):
84 return cls.plugins 86 return cls.plugins
85 87
86 @classmethod 88 @classmethod
89 def getPlugin(cls, namespace):
90 try:
91 return next(p for p in cls.plugins if p.namespace == namespace)
92 except StopIteration:
93 raise exceptions.NotFound(_(
94 u"Can't find requested encryption plugin: {namespace}").format(
95 namespace=namespace))
96
97 @classmethod
87 def getNSFromName(cls, name): 98 def getNSFromName(cls, name):
88 """Retrieve plugin namespace from its name 99 """Retrieve plugin namespace from its name
89 100
90 @param name(unicode): name of the plugin (case insensitive) 101 @param name(unicode): name of the plugin (case insensitive)
91 @return (unicode): namespace of the plugin 102 @return (unicode): namespace of the plugin
92 @raise exceptions.NotFound: there is not encryption plugin of this name 103 @raise exceptions.NotFound: there is not encryption plugin of this name
93 """ 104 """
94 for p in cls.plugins: 105 for p in cls.plugins:
95 if p.name.lower() == name.lower(): 106 if p.name.lower() == name.lower():
96 return p.namespace 107 return p.namespace
97 raise exceptions.NotFound 108 raise exceptions.NotFound(_(
109 u"Can't find a plugin with the name \"{name}\".".format(
110 name=name)))
98 111
99 def getBridgeData(self, session): 112 def getBridgeData(self, session):
100 """Retrieve session data serialized for bridge. 113 """Retrieve session data serialized for bridge.
101 114
102 @param session(dict): encryption session 115 @param session(dict): encryption session
115 def start(self, entity, namespace=None, replace=False): 128 def start(self, entity, namespace=None, replace=False):
116 """Start an encryption session with an entity 129 """Start an encryption session with an entity
117 130
118 @param entity(jid.JID): entity to start an encryption session with 131 @param entity(jid.JID): entity to start an encryption session with
119 must be bare jid is the algorithm encrypt for all devices 132 must be bare jid is the algorithm encrypt for all devices
120 @param namespace(unicode, None): namespace of the encryption algorithm to use 133 @param namespace(unicode, None): namespace of the encryption algorithm
134 to use.
121 None to select automatically an algorithm 135 None to select automatically an algorithm
122 @param replace(bool): if True and an encrypted session already exists, 136 @param replace(bool): if True and an encrypted session already exists,
123 it will be replaced by the new one 137 it will be replaced by the new one
124 """ 138 """
125 if not self.plugins: 139 if not self.plugins:
127 u"an encryption session can't be started")) 141 u"an encryption session can't be started"))
128 142
129 if namespace is None: 143 if namespace is None:
130 plugin = self.plugins[0] 144 plugin = self.plugins[0]
131 else: 145 else:
132 try: 146 plugin = self.getPlugin(namespace)
133 plugin = next(p for p in self.plugins if p.namespace == namespace)
134 except StopIteration:
135 raise exceptions.NotFound(_(
136 u"Can't find requested encryption plugin: {namespace}").format(
137 namespace=namespace))
138 147
139 bare_jid = entity.userhostJID() 148 bare_jid = entity.userhostJID()
140 if bare_jid in self._sessions: 149 if bare_jid in self._sessions:
141 # we have already an encryption session with this contact 150 # we have already an encryption session with this contact
142 former_plugin = self._sessions[bare_jid]['plugin'] 151 former_plugin = self._sessions[bare_jid]['plugin']
143 if former_plugin.namespace == namespace: 152 if former_plugin.namespace == namespace:
144 log.info(_(u"Session with {bare_jid} is already encrypted with {name}. " 153 log.info(_(u"Session with {bare_jid} is already encrypted with {name}. "
145 u"Nothing to do.").format(bare_jid=bare_jid, name=plugin.name)) 154 u"Nothing to do.").format(
155 bare_jid=bare_jid, name=former_plugin.name))
146 return 156 return
147 157
148 if replace: 158 if replace:
149 # there is a conflict, but replacement is requested 159 # there is a conflict, but replacement is requested
150 # so we stop previous encryption to use new one 160 # so we stop previous encryption to use new one
253 must be a bare jid 263 must be a bare jid
254 @return (dict, None): encryption session data 264 @return (dict, None): encryption session data
255 None if there is not encryption for this session with this jid 265 None if there is not encryption for this session with this jid
256 """ 266 """
257 if entity.resource: 267 if entity.resource:
258 raise exceptions.InternalError(u"Full jid given when expecting bare jid") 268 raise ValueError(u"Full jid given when expecting bare jid")
259 return self._sessions.get(entity) 269 return self._sessions.get(entity)
270
271 def getTrustUI(self, entity_jid, namespace=None):
272 """Retrieve encryption UI
273
274 @param entity_jid(jid.JID): get the UI for this entity
275 must be a bare jid
276 @param namespace(unicode): namespace of the algorithm to manage
277 if None use current algorithm
278 @return D(xmlui): XMLUI for trust management
279 the xmlui is a form
280 None if there is not encryption for this session with this jid
281 @raise exceptions.NotFound: no algorithm/plugin found
282 @raise NotImplementedError: plugin doesn't handle UI management
283 """
284 if namespace is None:
285 session = self.getSession(entity_jid)
286 if not session:
287 raise exceptions.NotFound(
288 u"No encryption session currently active for {entity_jid}"
289 .format(entity_jid=entity_jid.full()))
290 plugin = session['plugin']
291 else:
292 plugin = self.getPlugin(namespace)
293 try:
294 get_trust_ui = plugin.instance.getTrustUI
295 except AttributeError:
296 raise NotImplementedError(
297 u"Encryption plugin doesn't handle trust management UI")
298 else:
299 return get_trust_ui(self.client, entity_jid)
260 300
261 ## Triggers ## 301 ## Triggers ##
262 302
263 def setEncryptionFlag(self, mess_data): 303 def setEncryptionFlag(self, mess_data):
264 """Set "encryption" key in mess_data if session with destinee is encrypted""" 304 """Set "encryption" key in mess_data if session with destinee is encrypted"""
281 the plugin 321 the plugin
282 @param mess_data(dict): message data as used in post treat workflow 322 @param mess_data(dict): message data as used in post treat workflow
283 """ 323 """
284 mess_data['encrypted'] = True 324 mess_data['encrypted'] = True
285 return mess_data 325 return mess_data
326
327 def markAsUntrusted(self, mess_data):
328 """Helper methor to mark a message as sent from an untrusted entity.
329
330 This should be used in the post_treat workflow of MessageReceived trigger of
331 the plugin
332 @param mess_data(dict): message data as used in post treat workflow
333 """
334 mess_data['untrusted'] = True
335 return mess_data