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) |