Mercurial > libervia-backend
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 |