Software /
code /
prosody-modules
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 |
parent | 1775:0d78bb31348e |
child | 1989: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) |