Mercurial > prosody-modules
comparison mod_privilege/mod_privilege.lua @ 1707:64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
| author | Goffi <goffi@goffi.org> |
|---|---|
| date | Fri, 10 Apr 2015 15:55:44 +0200 |
| parents | c81a981479d4 |
| children | ad7afcf86131 |
comparison
equal
deleted
inserted
replaced
| 1670:5f5ff061b316 | 1707:64b3d1eb0cfe |
|---|---|
| 42 module:log("debug", "Loading privileged entity module "); | 42 module:log("debug", "Loading privileged entity module "); |
| 43 | 43 |
| 44 | 44 |
| 45 --> Permissions management <-- | 45 --> Permissions management <-- |
| 46 | 46 |
| 47 privileges = module:get_option("privileged_entities", {}) | 47 local privileges = module:get_option("privileged_entities", {}) |
| 48 | 48 |
| 49 function advertise_perm(session, to_jid, perms) | 49 local function advertise_perm(session, to_jid, perms) |
| 50 -- send <message/> stanza to advertise permissions | 50 -- send <message/> stanza to advertise permissions |
| 51 -- as expained in § 4.2 | 51 -- as expained in § 4.2 |
| 52 local message = st.message({to=to_jid}) | 52 local message = st.message({to=to_jid}) |
| 53 :tag("privilege", {xmlns=_PRIV_ENT_NS}) | 53 :tag("privilege", {xmlns=_PRIV_ENT_NS}) |
| 54 | 54 |
| 58 end | 58 end |
| 59 end | 59 end |
| 60 session.send(message) | 60 session.send(message) |
| 61 end | 61 end |
| 62 | 62 |
| 63 function set_presence_perm_set(to_jid, perms) | 63 local function set_presence_perm_set(to_jid, perms) |
| 64 -- fill the global presence sets according to perms | 64 -- fill the global presence sets according to perms |
| 65 if _PRESENCE_MANAGED:contains(perms.presence) then | 65 if _PRESENCE_MANAGED:contains(perms.presence) then |
| 66 presence_man_ent:add(to_jid) | 66 presence_man_ent:add(to_jid) |
| 67 end | 67 end |
| 68 if perms.presence == 'roster' then | 68 if perms.presence == 'roster' then |
| 69 presence_roster:add(to_jid) | 69 presence_roster:add(to_jid) |
| 70 end | 70 end |
| 71 end | 71 end |
| 72 | 72 |
| 73 function advertise_presences(session, to_jid, perms) | 73 local function advertise_presences(session, to_jid, perms) |
| 74 -- send presence status for already conencted entities | 74 -- send presence status for already conencted entities |
| 75 -- as explained in § 7.1 | 75 -- as explained in § 7.1 |
| 76 -- people in roster are probed only for active sessions | 76 -- people in roster are probed only for active sessions |
| 77 -- TODO: manage roster load for inactive sessions | 77 -- TODO: manage roster load for inactive sessions |
| 78 if not perms.presence then return; end | 78 if not perms.presence then return; end |
| 90 | 90 |
| 91 if user_session.roster then | 91 if user_session.roster then |
| 92 local bare_jid = jid.bare(user_session.full_jid) | 92 local bare_jid = jid.bare(user_session.full_jid) |
| 93 for entity, item in pairs(user_session.roster) do | 93 for entity, item in pairs(user_session.roster) do |
| 94 if entity~=false and entity~="pending" and (item.subscription=="both" or item.subscription=="to") then | 94 if entity~=false and entity~="pending" and (item.subscription=="both" or item.subscription=="to") then |
| 95 _, host = jid.split(entity) | 95 local _, host = jid.split(entity) |
| 96 if not hosts[host] then -- we don't probe jid from hosts we manage | 96 if not hosts[host] then -- we don't probe jid from hosts we manage |
| 97 -- using a table with entity as key avoid probing several time the same one | 97 -- using a table with entity as key avoid probing several time the same one |
| 98 to_probe[entity] = bare_jid | 98 to_probe[entity] = bare_jid |
| 99 end | 99 end |
| 100 end | 100 end |
| 102 end | 102 end |
| 103 end | 103 end |
| 104 end | 104 end |
| 105 | 105 |
| 106 -- now we probe peoples for "roster" presence permission | 106 -- now we probe peoples for "roster" presence permission |
| 107 for to_jid, from_jid in pairs(to_probe) do | 107 for probe_to, probe_from in pairs(to_probe) do |
| 108 module:log("debug", "probing presence for %s (on behalf of %s)", tostring(to_jid), tostring(from_jid)) | 108 module:log("debug", "probing presence for %s (on behalf of %s)", tostring(probe_to), tostring(probe_from)) |
| 109 local probe = st.presence({from=from_jid, to=to_jid, type="probe"}) | 109 local probe = st.presence({from=probe_from, to=probe_to, type="probe"}) |
| 110 prosody.core_route_stanza(nil, probe) | 110 prosody.core_route_stanza(nil, probe) |
| 111 end | 111 end |
| 112 end | 112 end |
| 113 | 113 |
| 114 function on_auth(event) | 114 local function on_auth(event) |
| 115 -- Check if entity is privileged according to configuration, | 115 -- Check if entity is privileged according to configuration, |
| 116 -- and set session.privileges accordingly | 116 -- and set session.privileges accordingly |
| 117 | 117 |
| 118 local session = event.session | 118 local session = event.session |
| 119 local bare_jid = jid.join(session.username, session.host) | 119 local bare_jid = jid.join(session.username, session.host) |
| 136 end | 136 end |
| 137 -- extra checks for presence permission | 137 -- extra checks for presence permission |
| 138 if ent_priv.permission == 'roster' and not _ROSTER_GET_PERM:contains(session.privileges.roster) then | 138 if ent_priv.permission == 'roster' and not _ROSTER_GET_PERM:contains(session.privileges.roster) then |
| 139 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") | 139 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") |
| 140 module:log("warn", "Setting presence permission to none") | 140 module:log("warn", "Setting presence permission to none") |
| 141 end_priv.permission = nil | 141 ent_priv.permission = nil |
| 142 end | 142 end |
| 143 | 143 |
| 144 if session.type == "component" then | 144 if session.type == "component" then |
| 145 -- we send the message stanza only for component | 145 -- we send the message stanza only for component |
| 146 -- it will be sent at first <presence/> for other entities | 146 -- it will be sent at first <presence/> for other entities |
| 151 end | 151 end |
| 152 | 152 |
| 153 session.privileges = ent_priv | 153 session.privileges = ent_priv |
| 154 end | 154 end |
| 155 | 155 |
| 156 function on_presence(event) | 156 local function on_presence(event) |
| 157 -- Permission are already checked at this point, | 157 -- Permission are already checked at this point, |
| 158 -- we only advertise them to the entity | 158 -- we only advertise them to the entity |
| 159 local session, stanza = event.origin, event.stanza; | 159 local session = event.origin |
| 160 if session.privileges then | 160 if session.privileges then |
| 161 advertise_perm(session, session.full_jid, session.privileges) | 161 advertise_perm(session, session.full_jid, session.privileges) |
| 162 set_presence_perm_set(session.full_jid, session.privileges) | 162 set_presence_perm_set(session.full_jid, session.privileges) |
| 163 advertise_presences(session, session.full_jid, session.privileges) | 163 advertise_presences(session, session.full_jid, session.privileges) |
| 164 end | 164 end |
| 186 local roster = roster_manager.load_roster(node, host); | 186 local roster = roster_manager.load_roster(node, host); |
| 187 | 187 |
| 188 local reply = st.reply(stanza):query("jabber:iq:roster"); | 188 local reply = st.reply(stanza):query("jabber:iq:roster"); |
| 189 for entity_jid, item in pairs(roster) do | 189 for entity_jid, item in pairs(roster) do |
| 190 if entity_jid and entity_jid ~= "pending" then | 190 if entity_jid and entity_jid ~= "pending" then |
| 191 local node, host = jid.split(entity_jid); | 191 reply:tag("item", { |
| 192 reply:tag("item", { | 192 jid = entity_jid, |
| 193 jid = entity_jid, | 193 subscription = item.subscription, |
| 194 subscription = item.subscription, | 194 ask = item.ask, |
| 195 ask = item.ask, | 195 name = item.name, |
| 196 name = item.name, | 196 }); |
| 197 }); | 197 for group in pairs(item.groups) do |
| 198 for group in pairs(item.groups) do | 198 reply:tag("group"):text(group):up(); |
| 199 reply:tag("group"):text(group):up(); | 199 end |
| 200 end | 200 reply:up(); -- move out from item |
| 201 reply:up(); -- move out from item | |
| 202 end | 201 end |
| 203 end | 202 end |
| 204 -- end of code adapted from mod_remote_roster | 203 -- end of code adapted from mod_remote_roster |
| 205 session.send(reply); | 204 session.send(reply); |
| 206 else | 205 else |
| 226 if not(user_manager.user_exists(from_node, from_host)) then return; end | 225 if not(user_manager.user_exists(from_node, from_host)) then return; end |
| 227 local roster = roster_manager.load_roster(from_node, from_host); | 226 local roster = roster_manager.load_roster(from_node, from_host); |
| 228 if not(roster) then return; end | 227 if not(roster) then return; end |
| 229 | 228 |
| 230 local query = stanza.tags[1]; | 229 local query = stanza.tags[1]; |
| 231 for i_, item in ipairs(query.tags) do | 230 for _, item in ipairs(query.tags) do |
| 232 if item.name == "item" | 231 if item.name == "item" |
| 233 and item.attr.xmlns == "jabber:iq:roster" and item.attr.jid | 232 and item.attr.xmlns == "jabber:iq:roster" and item.attr.jid |
| 234 -- Protection against overwriting roster.pending, until we move it | 233 -- Protection against overwriting roster.pending, until we move it |
| 235 and item.attr.jid ~= "pending" then | 234 and item.attr.jid ~= "pending" then |
| 236 | 235 |
| 237 local item_jid = jid.prep(item.attr.jid); | 236 local item_jid = jid.prep(item.attr.jid); |
| 238 local node, host, resource = jid.split(item_jid); | 237 local _, host, resource = jid.split(item_jid); |
| 239 if not resource then | 238 if not resource then |
| 240 if item_jid ~= stanza.attr.to then -- not self-item_jid | 239 if item_jid ~= stanza.attr.to then -- not self-item_jid |
| 241 if item.attr.subscription == "remove" then | 240 if item.attr.subscription == "remove" then |
| 242 local r_item = roster[item_jid]; | 241 local r_item = roster[item_jid]; |
| 243 if r_item then | 242 if r_item then |
| 244 local to_bare = node and (node.."@"..host) or host; -- bare jid | |
| 245 roster[item_jid] = nil; | 243 roster[item_jid] = nil; |
| 246 if roster_manager.save_roster(from_node, from_host, roster) then | 244 if roster_manager.save_roster(from_node, from_host, roster) then |
| 247 session.send(st.reply(stanza)); | 245 session.send(st.reply(stanza)); |
| 248 roster_manager.roster_push(from_node, from_host, item_jid); | 246 roster_manager.roster_push(from_node, from_host, item_jid); |
| 249 else | 247 else |
| 313 if session.privileges and session.privileges.message=="outgoing" then | 311 if session.privileges and session.privileges.message=="outgoing" then |
| 314 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded" | 312 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded" |
| 315 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then | 313 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then |
| 316 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') | 314 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') |
| 317 if message_elt ~= nil then | 315 if message_elt ~= nil then |
| 318 local from_node, from_host, from_resource = jid.split(message_elt.attr.from) | 316 local _, from_host, from_resource = jid.split(message_elt.attr.from) |
| 319 if from_resource == nil and hosts[from_host] then -- we only accept bare jids from one of the server hosts | 317 if from_resource == nil and hosts[from_host] then -- we only accept bare jids from one of the server hosts |
| 320 -- at this point everything should be alright, we can send the message | 318 -- at this point everything should be alright, we can send the message |
| 321 prosody.core_route_stanza(nil, message_elt) | 319 prosody.core_route_stanza(nil, message_elt) |
| 322 else -- trying to send a message from a forbidden entity | 320 else -- trying to send a message from a forbidden entity |
| 323 module:log("warn", "Entity "..tostring(session.full_jid).." try to send a message from "..tostring(message_elt.attr.from)) | 321 module:log("warn", "Entity "..tostring(session.full_jid).." try to send a message from "..tostring(message_elt.attr.from)) |
| 338 end); | 336 end); |
| 339 | 337 |
| 340 | 338 |
| 341 --> presence permission <-- | 339 --> presence permission <-- |
| 342 | 340 |
| 343 function same_tags(tag1, tag2) | 341 local function same_tags(tag1, tag2) |
| 344 -- check if two tags are equivalent | 342 -- check if two tags are equivalent |
| 345 | 343 |
| 346 if tag1.name ~= tag2.name then return false; end | 344 if tag1.name ~= tag2.name then return false; end |
| 347 | 345 |
| 348 if #tag1 ~= #tag2 then return false; end | 346 if #tag1 ~= #tag2 then return false; end |
| 360 end | 358 end |
| 361 | 359 |
| 362 return true | 360 return true |
| 363 end | 361 end |
| 364 | 362 |
| 365 function same_presences(presence1, presence2) | 363 local function same_presences(presence1, presence2) |
| 366 -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) | 364 -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) |
| 367 -- /!\ if the id change but everything else is equivalent, this method return false | 365 -- /!\ if the id change but everything else is equivalent, this method return false |
| 368 -- this behaviour may change in the future | 366 -- this behaviour may change in the future |
| 369 if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id | 367 if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id |
| 370 or presence1.attr.type ~= presence2.attr.type then | 368 or presence1.attr.type ~= presence2.attr.type then |
| 384 end | 382 end |
| 385 | 383 |
| 386 return true | 384 return true |
| 387 end | 385 end |
| 388 | 386 |
| 389 function forward_presence(presence, to_jid) | 387 local function forward_presence(presence, to_jid) |
| 390 presence_fwd = st.clone(presence) | 388 local presence_fwd = st.clone(presence) |
| 391 presence_fwd.attr.to = to_jid | 389 presence_fwd.attr.to = to_jid |
| 392 module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) | 390 module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) |
| 393 module:send(presence_fwd) | 391 module:send(presence_fwd) |
| 394 -- cache used to avoid to send several times the same stanza | 392 -- cache used to avoid to send several times the same stanza |
| 395 priv_session.last_presence = presence | 393 priv_session.last_presence = presence |
| 396 end | 394 end |
| 397 | 395 |
| 398 module:hook("presence/bare", function(event) | 396 module:hook("presence/bare", function(event) |
| 399 if presence_man_ent:empty() and presence_roster:empty() then return; end | 397 if presence_man_ent:empty() and presence_roster:empty() then return; end |
| 400 | 398 |
| 401 local session, stanza = event.origin, event.stanza; | 399 local stanza = event.stanza |
| 402 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then | 400 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then |
| 403 if not stanza.attr.to then | 401 if not stanza.attr.to then |
| 404 for entity in presence_man_ent:items() do | 402 for entity in presence_man_ent:items() do |
| 405 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | 403 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end |
| 406 end | 404 end |
| 407 else -- directed presence | 405 else -- directed presence |
| 408 -- we ignore directed presences from our own host, as we already have them | 406 -- we ignore directed presences from our own host, as we already have them |
| 409 _, from_host = jid.split(stanza.attr.from) | 407 local _, from_host = jid.split(stanza.attr.from) |
| 410 if hosts[from_host] then return; end | 408 if hosts[from_host] then return; end |
| 411 | 409 |
| 412 -- we don't send several time the same presence, as recommended in §7 #2 | 410 -- we don't send several time the same presence, as recommended in §7 #2 |
| 413 if priv_session.last_presence and same_presences(priv_session.last_presence, stanza) then | 411 if priv_session.last_presence and same_presences(priv_session.last_presence, stanza) then |
| 414 return | 412 return |
