comparison mod_privilege/mod_privilege.lua @ 1955:f719d5e6c627

mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
author Goffi <goffi@goffi.org>
date Tue, 24 Nov 2015 15:32:54 +0100
parents 0d78bb31348e
children 2c9b227dd580
comparison
equal deleted inserted replaced
1952:9d0c33ebbcc5 1955:f719d5e6c627
38 local _ALLOWED_PRESENCE = set.new({'none', 'managed_entity', 'roster'}) 38 local _ALLOWED_PRESENCE = set.new({'none', 'managed_entity', 'roster'})
39 local _PRESENCE_MANAGED = set.new({'managed_entity', 'roster'}) 39 local _PRESENCE_MANAGED = set.new({'managed_entity', 'roster'})
40 local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE} 40 local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE}
41 local _PRIV_ENT_NS = 'urn:xmpp:privilege:1' 41 local _PRIV_ENT_NS = 'urn:xmpp:privilege:1'
42 local _FORWARDED_NS = 'urn:xmpp:forward:0' 42 local _FORWARDED_NS = 'urn:xmpp:forward:0'
43 local _MODULE_HOST = module:get_host()
43 44
44 45
45 module:log("debug", "Loading privileged entity module "); 46 module:log("debug", "Loading privileged entity module ");
46 47
47 48
48 --> Permissions management <-- 49 --> Permissions management <--
49 50
50 local privileges = module:get_option("privileged_entities", {}) 51 local privileges = module:get_option("privileged_entities", {})
52
53 local function get_session_privileges(session, host)
54 if not session.privileges then return nil end
55 return session.privileges[host]
56 end
57
51 58
52 local function advertise_perm(session, to_jid, perms) 59 local function advertise_perm(session, to_jid, perms)
53 -- send <message/> stanza to advertise permissions 60 -- send <message/> stanza to advertise permissions
54 -- as expained in § 4.2 61 -- as expained in § 4.2
55 local message = st.message({from=module.host, to=to_jid}) 62 local message = st.message({from=module.host, to=to_jid})
118 -- Check if entity is privileged according to configuration, 125 -- Check if entity is privileged according to configuration,
119 -- and set session.privileges accordingly 126 -- and set session.privileges accordingly
120 127
121 local session = event.session 128 local session = event.session
122 local bare_jid = jid.join(session.username, session.host) 129 local bare_jid = jid.join(session.username, session.host)
130 if not session.privileges then
131 session.privileges = {}
132 end
123 133
124 local ent_priv = privileges[bare_jid] 134 local ent_priv = privileges[bare_jid]
125 if ent_priv ~= nil then 135 if ent_priv ~= nil then
126 module:log("debug", "Entity is privileged") 136 module:log("debug", "Entity is privileged")
127 for perm_type, allowed_values in pairs(_TO_CHECK) do 137 for perm_type, allowed_values in pairs(_TO_CHECK) do
136 ent_priv[perm_type] = nil 146 ent_priv[perm_type] = nil
137 end 147 end
138 end 148 end
139 end 149 end
140 -- extra checks for presence permission 150 -- extra checks for presence permission
141 if ent_priv.permission == 'roster' and not _ROSTER_GET_PERM:contains(session.privileges.roster) then 151 if ent_priv.presence == 'roster' and not _ROSTER_GET_PERM:contains(ent_priv.roster) then
142 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") 152 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege")
143 module:log("warn", "Setting presence permission to none") 153 module:log("warn", "Setting presence permission to none")
144 ent_priv.permission = nil 154 ent_priv.presence = nil
145 end 155 end
146 156
147 if session.type == "component" then 157 if session.type == "component" then
148 -- we send the message stanza only for component 158 -- we send the message stanza only for component
149 -- it will be sent at first <presence/> for other entities 159 -- it will be sent at first <presence/> for other entities
151 set_presence_perm_set(bare_jid, ent_priv) 161 set_presence_perm_set(bare_jid, ent_priv)
152 advertise_presences(session, bare_jid, ent_priv) 162 advertise_presences(session, bare_jid, ent_priv)
153 end 163 end
154 end 164 end
155 165
156 session.privileges = ent_priv 166 session.privileges[_MODULE_HOST] = ent_priv
157 end 167 end
158 168
159 local function on_presence(event) 169 local function on_presence(event)
160 -- Permission are already checked at this point, 170 -- Permission are already checked at this point,
161 -- we only advertise them to the entity 171 -- we only advertise them to the entity
162 local session = event.origin 172 local session = event.origin
163 if session.privileges then 173 local session_privileges = get_session_privileges(session, _MODULE_HOST)
164 advertise_perm(session, session.full_jid, session.privileges) 174 if session_privileges then
165 set_presence_perm_set(session.full_jid, session.privileges) 175 advertise_perm(session, session.full_jid, session_privileges)
166 advertise_presences(session, session.full_jid, session.privileges) 176 set_presence_perm_set(session.full_jid, session_privileges)
177 advertise_presences(session, session.full_jid, session_privileges)
167 end 178 end
168 end 179 end
169 180
170 local function on_component_auth(event) 181 local function on_component_auth(event)
171 -- react to component-authenticated event from this host 182 -- react to component-authenticated event from this host
191 local session, stanza = event.origin, event.stanza; 202 local session, stanza = event.origin, event.stanza;
192 if not stanza.attr.to then 203 if not stanza.attr.to then
193 -- we don't want stanzas addressed to /self 204 -- we don't want stanzas addressed to /self
194 return; 205 return;
195 end 206 end
196 207 local node, host = jid.split(stanza.attr.to);
197 if session.privileges and _ROSTER_GET_PERM:contains(session.privileges.roster) then 208 local session_privileges = get_session_privileges(session, host)
209
210 if session_privileges and _ROSTER_GET_PERM:contains(session_privileges.roster) then
198 module:log("debug", "Roster get from allowed privileged entity received") 211 module:log("debug", "Roster get from allowed privileged entity received")
199 -- following code is adapted from mod_remote_roster 212 -- following code is adapted from mod_remote_roster
200 local node, host = jid.split(stanza.attr.to);
201 local roster = roster_manager.load_roster(node, host); 213 local roster = roster_manager.load_roster(node, host);
202 214
203 local reply = st.reply(stanza):query("jabber:iq:roster"); 215 local reply = st.reply(stanza):query("jabber:iq:roster");
204 for entity_jid, item in pairs(roster) do 216 for entity_jid, item in pairs(roster) do
205 if entity_jid and entity_jid ~= "pending" then 217 if entity_jid and entity_jid ~= "pending" then
230 local session, stanza = event.origin, event.stanza; 242 local session, stanza = event.origin, event.stanza;
231 if not stanza.attr.to then 243 if not stanza.attr.to then
232 -- we don't want stanzas addressed to /self 244 -- we don't want stanzas addressed to /self
233 return; 245 return;
234 end 246 end
235 247 local from_node, from_host = jid.split(stanza.attr.to);
236 if session.privileges and _ROSTER_SET_PERM:contains(session.privileges.roster) then 248 local session_privileges = get_session_privileges(session, from_host)
249
250 if session_privileges and _ROSTER_SET_PERM:contains(session_privileges.roster) then
237 module:log("debug", "Roster set from allowed privileged entity received") 251 module:log("debug", "Roster set from allowed privileged entity received")
238 -- following code is adapted from mod_remote_roster 252 -- following code is adapted from mod_remote_roster
239 local from_node, from_host = jid.split(stanza.attr.to);
240 if not(user_manager.user_exists(from_node, from_host)) then return; end 253 if not(user_manager.user_exists(from_node, from_host)) then return; end
241 local roster = roster_manager.load_roster(from_node, from_host); 254 local roster = roster_manager.load_roster(from_node, from_host);
242 if not(roster) then return; end 255 if not(roster) then return; end
243 256
244 local query = stanza.tags[1]; 257 local query = stanza.tags[1];
321 334
322 module:hook("message/host", function(event) 335 module:hook("message/host", function(event)
323 local session, stanza = event.origin, event.stanza; 336 local session, stanza = event.origin, event.stanza;
324 local privilege_elt = stanza:get_child('privilege', _PRIV_ENT_NS) 337 local privilege_elt = stanza:get_child('privilege', _PRIV_ENT_NS)
325 if privilege_elt==nil then return; end 338 if privilege_elt==nil then return; end
326 if session.privileges and session.privileges.message=="outgoing" then 339 local _, to_host = jid.split(stanza.attr.to)
340 local session_privileges = get_session_privileges(session, to_host)
341
342 if session_privileges and session_privileges.message=="outgoing" then
327 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded" 343 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded"
328 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then 344 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then
329 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') 345 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client')
330 if message_elt ~= nil then 346 if message_elt ~= nil then
331 local _, from_host, from_resource = jid.split(message_elt.attr.from) 347 local _, from_host, from_resource = jid.split(message_elt.attr.from)