Mercurial > prosody-modules
annotate mod_privilege/mod_privilege.lua @ 4989:b74d592df9e2
mod_http_muc_log: Remove dead code
This might be something left over since a different variant where the
loop went like `for n = i-1, i-100, -1 do ... end` i.e. it went trough a
fixed number of items instead of all the page until the current message.
Then it would have needed something to stop going over the end, but
since the checks are simple it shouldn't be much of a problem looping
over even a very busy day.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 16 Aug 2022 01:27:59 +0200 |
parents | 3ddab718f717 |
children | cce12a660b98 |
rev | line source |
---|---|
1667
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
1 -- XEP-0356 (Privileged Entity) |
4913 | 2 -- Copyright (C) 2015-2022 Jérôme Poisson |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
3 -- |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
4 -- This module is MIT/X11 licensed. Please see the |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
5 -- COPYING file in the source package for more information. |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
6 -- |
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
7 -- Some parts come from mod_remote_roster (module by Waqas Hussain and Kim Alvefur, see https://code.google.com/p/prosody-modules/) |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
8 |
1667
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
9 -- TODO: manage external <presence/> (for "roster" presence permission) when the account with the roster is offline |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
10 |
1990
c4da3d9f212d
mod_privilege: fixed imports, using "/" instead of "." was causing caching issues
Goffi <goffi@goffi.org>
parents:
1989
diff
changeset
|
11 local jid = require("util.jid") |
c4da3d9f212d
mod_privilege: fixed imports, using "/" instead of "." was causing caching issues
Goffi <goffi@goffi.org>
parents:
1989
diff
changeset
|
12 local set = require("util.set") |
c4da3d9f212d
mod_privilege: fixed imports, using "/" instead of "." was causing caching issues
Goffi <goffi@goffi.org>
parents:
1989
diff
changeset
|
13 local st = require("util.stanza") |
c4da3d9f212d
mod_privilege: fixed imports, using "/" instead of "." was causing caching issues
Goffi <goffi@goffi.org>
parents:
1989
diff
changeset
|
14 local roster_manager = require("core.rostermanager") |
4913 | 15 local usermanager_user_exists = require "core.usermanager".user_exists |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
16 local hosts = prosody.hosts |
4913 | 17 local full_sessions = prosody.full_sessions |
1667
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
18 |
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
19 local priv_session = module:shared("/*/privilege/session") |
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
20 |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
21 if priv_session.connected_cb == nil then |
4913 | 22 -- set used to have connected event listeners |
23 -- which allows a host to react on events from | |
24 -- other hosts | |
25 priv_session.connected_cb = set.new() | |
1663
ca07a6ada631
mod_privilege: presence permission configuration check + use global set to know privileged entities to advertise
Goffi <goffi@goffi.org>
parents:
1662
diff
changeset
|
26 end |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
27 local connected_cb = priv_session.connected_cb |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
28 |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
29 -- the folowing sets are used to forward presence stanza |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
30 -- the folowing sets are used to forward presence stanza |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
31 local presence_man_ent = set.new() |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
32 local presence_roster = set.new() |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
33 |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
34 local _ALLOWED_ROSTER = set.new({'none', 'get', 'set', 'both'}) |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
35 local _ROSTER_GET_PERM = set.new({'get', 'both'}) |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
36 local _ROSTER_SET_PERM = set.new({'set', 'both'}) |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
37 local _ALLOWED_MESSAGE = set.new({'none', 'outgoing'}) |
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
38 local _ALLOWED_PRESENCE = set.new({'none', 'managed_entity', 'roster'}) |
1665
746d94f37a4c
mod_privilege: presence already known are advertised to privileged entity (for "maneger_entity" permission only so far)
Goffi <goffi@goffi.org>
parents:
1664
diff
changeset
|
39 local _PRESENCE_MANAGED = set.new({'managed_entity', 'roster'}) |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
40 local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE} |
4913 | 41 local _PRIV_ENT_NS = 'urn:xmpp:privilege:2' |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
42 local _FORWARDED_NS = 'urn:xmpp:forward:0' |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
43 local _MODULE_HOST = module:get_host() |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
44 |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
45 |
4913 | 46 module:log("debug", "Loading privileged entity module ") |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
47 |
1663
ca07a6ada631
mod_privilege: presence permission configuration check + use global set to know privileged entities to advertise
Goffi <goffi@goffi.org>
parents:
1662
diff
changeset
|
48 |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
49 --> Permissions management <-- |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 |
4913 | 51 local config_priv = module:get_option("privileged_entities", {}) |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
53 local function get_session_privileges(session, host) |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
54 if not session.privileges then return nil end |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
55 return session.privileges[host] |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
56 end |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
57 |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
58 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
59 local function advertise_perm(session, to_jid, perms) |
4913 | 60 -- send <message/> stanza to advertise permissions |
61 -- as expained in § 4.2 | |
62 local message = st.message({from=module.host, to=to_jid}) | |
63 :tag("privilege", {xmlns=_PRIV_ENT_NS}) | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
64 |
4913 | 65 for _, perm in pairs({'roster', 'message', 'presence'}) do |
66 if perms[perm] then | |
67 message:tag("perm", {access=perm, type=perms[perm]}):up() | |
68 end | |
69 end | |
70 local iq_perm = perms["iq"] | |
71 if iq_perm ~= nil then | |
72 message:tag("perm", {access="iq"}) | |
73 for namespace, ns_perm in pairs(iq_perm) do | |
74 local perm_type | |
75 if ns_perm.set and ns_perm.get then | |
76 perm_type = "both" | |
77 elseif ns_perm.set then | |
78 perm_type = "set" | |
79 elseif ns_perm.get then | |
80 perm_type = "get" | |
81 else | |
82 perm_type = nil | |
83 end | |
84 message:tag("namespace", {ns=namespace, type=perm_type}) | |
85 end | |
86 end | |
87 session.send(message) | |
1662
d440a22fa0af
mod_privilege: advertise_perm method now use session.send instead of module:send to avoid to go back in hook
Goffi <goffi@goffi.org>
parents:
1661
diff
changeset
|
88 end |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
89 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
90 local function set_presence_perm_set(to_jid, perms) |
4913 | 91 -- fill the presence sets according to perms |
92 if _PRESENCE_MANAGED:contains(perms.presence) then | |
93 presence_man_ent:add(to_jid) | |
94 end | |
95 if perms.presence == 'roster' then | |
96 presence_roster:add(to_jid) | |
97 end | |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
98 end |
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
100 local function advertise_presences(session, to_jid, perms) |
4913 | 101 -- send presence status for already connected entities |
102 -- as explained in § 7.1 | |
103 -- people in roster are probed only for active sessions | |
104 -- TODO: manage roster load for inactive sessions | |
105 if not perms.presence then return; end | |
106 local to_probe = {} | |
107 for _, user_session in pairs(full_sessions) do | |
108 if user_session.presence and _PRESENCE_MANAGED:contains(perms.presence) then | |
109 local presence = st.clone(user_session.presence) | |
110 presence.attr.to = to_jid | |
111 module:log("debug", "sending current presence for "..tostring(user_session.full_jid)) | |
112 session.send(presence) | |
113 end | |
114 if perms.presence == "roster" then | |
115 -- we reset the cache to avoid to miss a presence that just changed | |
116 priv_session.last_presence = nil | |
1667
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
117 |
4913 | 118 if user_session.roster then |
119 local bare_jid = jid.bare(user_session.full_jid) | |
120 for entity, item in pairs(user_session.roster) do | |
121 if entity~=false and entity~="pending" and (item.subscription=="both" or item.subscription=="to") then | |
122 local _, host = jid.split(entity) | |
123 if not hosts[host] then -- we don't probe jid from hosts we manage | |
124 -- using a table with entity as key avoid probing several time the same one | |
125 to_probe[entity] = bare_jid | |
126 end | |
127 end | |
128 end | |
129 end | |
130 end | |
131 end | |
1667
c81a981479d4
mod_privilege: implemented probing of rosters items (for existing sessions only) on connection + use a globally shared table for priv_session (and fixed last_presence)
Goffi <goffi@goffi.org>
parents:
1666
diff
changeset
|
132 |
4913 | 133 -- now we probe peoples for "roster" presence permission |
134 for probe_to, probe_from in pairs(to_probe) do | |
135 module:log("debug", "probing presence for %s (on behalf of %s)", tostring(probe_to), tostring(probe_from)) | |
136 local probe = st.presence({from=probe_from, to=probe_to, type="probe"}) | |
137 prosody.core_route_stanza(nil, probe) | |
138 end | |
1665
746d94f37a4c
mod_privilege: presence already known are advertised to privileged entity (for "maneger_entity" permission only so far)
Goffi <goffi@goffi.org>
parents:
1664
diff
changeset
|
139 end |
746d94f37a4c
mod_privilege: presence already known are advertised to privileged entity (for "maneger_entity" permission only so far)
Goffi <goffi@goffi.org>
parents:
1664
diff
changeset
|
140 |
4913 | 141 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
142 local function on_auth(event) |
4913 | 143 -- Check if entity is privileged according to configuration, |
144 -- and set session.privileges accordingly | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
145 |
4913 | 146 local session = event.session |
147 local bare_jid = jid.join(session.username, session.host) | |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
148 if not session.privileges then |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
149 session.privileges = {} |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
150 end |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
151 |
4913 | 152 local conf_ent_priv = config_priv[bare_jid] |
153 local ent_priv = {} | |
154 if conf_ent_priv ~= nil then | |
155 module:log("debug", "Entity is privileged") | |
156 for perm_type, allowed_values in pairs(_TO_CHECK) do | |
157 local value = conf_ent_priv[perm_type] | |
158 if value ~= nil then | |
159 if not allowed_values:contains(value) then | |
160 module:log('warn', 'Invalid value for '..perm_type..' privilege: ['..value..']') | |
161 module:log('warn', 'Setting '..perm_type..' privilege to none') | |
162 ent_priv[perm_type] = nil | |
163 elseif value == 'none' then | |
164 ent_priv[perm_type] = nil | |
165 else | |
166 ent_priv[perm_type] = value | |
167 end | |
168 else | |
169 ent_priv[perm_type] = nil | |
170 end | |
171 end | |
172 -- extra checks for presence permission | |
173 if ent_priv.presence == 'roster' and not _ROSTER_GET_PERM:contains(ent_priv.roster) then | |
174 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") | |
175 module:log("warn", "Setting presence permission to none") | |
176 ent_priv.presence = nil | |
177 end | |
178 -- iq permission | |
179 local iq_perm_config = conf_ent_priv["iq"] | |
180 if iq_perm_config ~= nil then | |
181 local iq_perm = {} | |
182 ent_priv["iq"] = iq_perm | |
183 for ns, ns_perm_config in pairs(iq_perm_config) do | |
184 iq_perm[ns] = { | |
185 ["get"] = ns_perm_config == "get" or ns_perm_config == "both", | |
186 ["set"] = ns_perm_config == "set" or ns_perm_config == "both" | |
187 } | |
188 end | |
189 else | |
190 ent_priv["iq"] = nil | |
191 end | |
1663
ca07a6ada631
mod_privilege: presence permission configuration check + use global set to know privileged entities to advertise
Goffi <goffi@goffi.org>
parents:
1662
diff
changeset
|
192 |
4913 | 193 if session.type == "component" then |
194 -- we send the message stanza only for component | |
195 -- it will be sent at first <presence/> for other entities | |
196 advertise_perm(session, bare_jid, ent_priv) | |
197 set_presence_perm_set(bare_jid, ent_priv) | |
198 advertise_presences(session, bare_jid, ent_priv) | |
199 end | |
200 end | |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
201 |
4913 | 202 session.privileges[_MODULE_HOST] = ent_priv |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
203 end |
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
205 local function on_presence(event) |
4913 | 206 -- Permission are already checked at this point, |
207 -- we only advertise them to the entity | |
208 local session = event.origin | |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
209 local session_privileges = get_session_privileges(session, _MODULE_HOST) |
4913 | 210 if session_privileges then |
211 advertise_perm(session, session.full_jid, session_privileges) | |
212 set_presence_perm_set(session.full_jid, session_privileges) | |
213 advertise_presences(session, session.full_jid, session_privileges) | |
214 end | |
1659
495a093798eb
mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents:
1658
diff
changeset
|
215 end |
495a093798eb
mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents:
1658
diff
changeset
|
216 |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
217 local function on_component_auth(event) |
4913 | 218 -- react to component-authenticated event from this host |
219 -- and call the on_auth methods from all other hosts | |
220 -- needed for the component to get delegations advertising | |
221 for callback in connected_cb:items() do | |
222 callback(event) | |
223 end | |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
224 end |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
225 |
1775
0d78bb31348e
mod_privilege: fixed bad calling of on_auth for components
Goffi <goffi@goffi.org>
parents:
1708
diff
changeset
|
226 if module:get_host_type() ~= "component" then |
0d78bb31348e
mod_privilege: fixed bad calling of on_auth for components
Goffi <goffi@goffi.org>
parents:
1708
diff
changeset
|
227 connected_cb:add(on_auth) |
0d78bb31348e
mod_privilege: fixed bad calling of on_auth for components
Goffi <goffi@goffi.org>
parents:
1708
diff
changeset
|
228 end |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
229 module:hook('authentication-success', on_auth) |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
230 module:hook('component-authenticated', on_component_auth) |
1659
495a093798eb
mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents:
1658
diff
changeset
|
231 module:hook('presence/initial', on_presence) |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
232 |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
233 |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
234 --> roster permission <-- |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
235 |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
236 -- get |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
237 module:hook("iq-get/bare/jabber:iq:roster:query", function(event) |
4913 | 238 local session, stanza = event.origin, event.stanza |
239 if not stanza.attr.to then | |
240 -- we don't want stanzas addressed to /self | |
241 return | |
242 end | |
243 local node, host = jid.split(stanza.attr.to) | |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
244 local session_privileges = get_session_privileges(session, host) |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
245 |
4913 | 246 if session_privileges and _ROSTER_GET_PERM:contains(session_privileges.roster) then |
247 module:log("debug", "Roster get from allowed privileged entity received") | |
248 -- following code is adapted from mod_remote_roster | |
249 local roster = roster_manager.load_roster(node, host) | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
250 |
4913 | 251 local reply = st.reply(stanza):query("jabber:iq:roster") |
252 for entity_jid, item in pairs(roster) do | |
253 if entity_jid and entity_jid ~= "pending" then | |
254 reply:tag("item", { | |
255 jid = entity_jid, | |
256 subscription = item.subscription, | |
257 ask = item.ask, | |
258 name = item.name, | |
259 }) | |
260 for group in pairs(item.groups) do | |
261 reply:tag("group"):text(group):up() | |
262 end | |
263 reply:up(); -- move out from item | |
264 end | |
265 end | |
266 -- end of code adapted from mod_remote_roster | |
267 session.send(reply) | |
268 else | |
269 module:log("warn", "Entity "..tostring(session.full_jid).." try to get roster without permission") | |
270 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
271 end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
272 |
4913 | 273 return true |
274 end) | |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
275 |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
276 -- set |
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
277 module:hook("iq-set/bare/jabber:iq:roster:query", function(event) |
4913 | 278 local session, stanza = event.origin, event.stanza |
279 if not stanza.attr.to then | |
280 -- we don't want stanzas addressed to /self | |
281 return | |
282 end | |
283 local from_node, from_host = jid.split(stanza.attr.to) | |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
284 local session_privileges = get_session_privileges(session, from_host) |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
285 |
4913 | 286 if session_privileges and _ROSTER_SET_PERM:contains(session_privileges.roster) then |
287 module:log("debug", "Roster set from allowed privileged entity received") | |
288 -- following code is adapted from mod_remote_roster | |
289 if not(usermanager_user_exists(from_node, from_host)) then return; end | |
290 local roster = roster_manager.load_roster(from_node, from_host) | |
291 if not(roster) then return; end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
292 |
4913 | 293 local query = stanza.tags[1] |
294 for _, item in ipairs(query.tags) do | |
295 if item.name == "item" | |
296 and item.attr.xmlns == "jabber:iq:roster" and item.attr.jid | |
297 -- Protection against overwriting roster.pending, until we move it | |
298 and item.attr.jid ~= "pending" then | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
299 |
4913 | 300 local item_jid = jid.prep(item.attr.jid) |
301 local _, host, resource = jid.split(item_jid) | |
302 if not resource then | |
303 if item_jid ~= stanza.attr.to then -- not self-item_jid | |
304 if item.attr.subscription == "remove" then | |
305 local r_item = roster[item_jid] | |
306 if r_item then | |
307 roster[item_jid] = nil | |
308 if roster_manager.save_roster(from_node, from_host, roster) then | |
309 session.send(st.reply(stanza)) | |
310 roster_manager.roster_push(from_node, from_host, item_jid) | |
311 else | |
312 roster[item_jid] = item | |
313 session.send(st.error_reply(stanza, "wait", "internal-server-error", "Unable to save roster")) | |
314 end | |
315 else | |
316 session.send(st.error_reply(stanza, "modify", "item-not-found")) | |
317 end | |
318 else | |
319 local subscription = item.attr.subscription | |
320 if subscription ~= "both" and subscription ~= "to" and subscription ~= "from" and subscription ~= "none" then -- TODO error on invalid | |
321 subscription = roster[item_jid] and roster[item_jid].subscription or "none" | |
322 end | |
323 local r_item = {name = item.attr.name, groups = {}} | |
324 if r_item.name == "" then r_item.name = nil; end | |
325 r_item.subscription = subscription | |
326 if subscription ~= "both" and subscription ~= "to" then | |
327 r_item.ask = roster[item_jid] and roster[item_jid].ask | |
328 end | |
329 for _, child in ipairs(item) do | |
330 if child.name == "group" then | |
331 local text = table.concat(child) | |
332 if text and text ~= "" then | |
333 r_item.groups[text] = true | |
334 end | |
335 end | |
336 end | |
337 local olditem = roster[item_jid] | |
338 roster[item_jid] = r_item | |
339 if roster_manager.save_roster(from_node, from_host, roster) then -- Ok, send success | |
340 session.send(st.reply(stanza)) | |
341 -- and push change to all resources | |
342 roster_manager.roster_push(from_node, from_host, item_jid) | |
343 else -- Adding to roster failed | |
344 roster[item_jid] = olditem | |
345 session.send(st.error_reply(stanza, "wait", "internal-server-error", "Unable to save roster")) | |
346 end | |
347 end | |
348 else -- Trying to add self to roster | |
349 session.send(st.error_reply(stanza, "cancel", "not-allowed")) | |
350 end | |
351 else -- Invalid JID added to roster | |
352 module:log("warn", "resource: %s , host: %s", tostring(resource), tostring(host)) | |
353 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error? | |
354 end | |
355 else -- Roster set didn't include a single item, or its name wasn't 'item' | |
356 session.send(st.error_reply(stanza, "modify", "bad-request")) | |
357 end | |
358 end -- for loop end | |
359 -- end of code adapted from mod_remote_roster | |
360 else -- The permission is not granted | |
361 module:log("warn", "Entity "..tostring(session.full_jid).." try to set roster without permission") | |
362 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
363 end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
364 |
4913 | 365 return true |
366 end) | |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
367 |
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
368 |
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
369 --> message permission <-- |
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
370 |
3388
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
371 local function clean_xmlns(node) |
4913 | 372 -- Recursively remove "jabber:client" attribute from node. |
373 -- In Prosody internal routing, xmlns should not be set. | |
374 -- Keeping xmlns would lead to issues like mod_smacks ignoring the outgoing stanza, | |
375 -- so we remove all xmlns attributes with a value of "jabber:client" | |
376 if node.attr.xmlns == 'jabber:client' then | |
377 for childnode in node:childtags() do | |
378 clean_xmlns(childnode) | |
379 end | |
380 node.attr.xmlns = nil | |
381 end | |
3388
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
382 end |
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
383 |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
384 module:hook("message/host", function(event) |
4913 | 385 local session, stanza = event.origin, event.stanza |
386 local privilege_elt = stanza:get_child('privilege', _PRIV_ENT_NS) | |
387 if privilege_elt==nil then return; end | |
1955
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
388 local _, to_host = jid.split(stanza.attr.to) |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
389 local session_privileges = get_session_privileges(session, to_host) |
f719d5e6c627
mod_privilege: fixed session.privilege overwritting when multiple hosts are activated + fixed roster permission check on presence permission.
Goffi <goffi@goffi.org>
parents:
1775
diff
changeset
|
390 |
4913 | 391 if session_privileges and session_privileges.message=="outgoing" then |
392 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded" | |
393 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then | |
394 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') | |
395 if message_elt ~= nil then | |
396 local _, from_host, from_resource = jid.split(message_elt.attr.from) | |
397 if from_resource == nil and hosts[from_host] then -- we only accept bare jids from one of the server hosts | |
398 clean_xmlns(message_elt); -- needed do to proper routing | |
399 -- at this point everything should be alright, we can send the message | |
400 prosody.core_route_stanza(nil, message_elt) | |
401 else -- trying to send a message from a forbidden entity | |
402 module:log("warn", "Entity "..tostring(session.full_jid).." try to send a message from "..tostring(message_elt.attr.from)) | |
403 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
404 end | |
405 else -- incorrect message child | |
406 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid forwarded <message/> element")) | |
407 end | |
408 else -- incorrect forwarded child | |
409 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid <forwarded/> element")) | |
410 end | |
411 else -- The permission is not granted | |
412 module:log("warn", "Entity "..tostring(session.full_jid).." try to send message without permission") | |
413 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
414 end | |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
415 |
4913 | 416 return true |
417 end) | |
1664
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
418 |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
419 |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
420 --> presence permission <-- |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
421 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
422 local function same_tags(tag1, tag2) |
4913 | 423 -- check if two tags are equivalent |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
424 |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
425 if tag1.name ~= tag2.name then return false; end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
426 |
4913 | 427 if #tag1 ~= #tag2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
428 |
4913 | 429 for name, value in pairs(tag1.attr) do |
430 if tag2.attr[name] ~= value then return false; end | |
431 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
432 |
4913 | 433 for i=1,#tag1 do |
434 if type(tag1[i]) == "string" then | |
435 if tag1[i] ~= tag2[i] then return false; end | |
436 else | |
437 if not same_tags(tag1[i], tag2[i]) then return false; end | |
438 end | |
439 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
440 |
4913 | 441 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
442 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
443 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
444 local function same_presences(presence1, presence2) |
4913 | 445 -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) |
446 -- /!\ if the id change but everything else is equivalent, this method return false | |
447 -- this behaviour may change in the future | |
448 if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id | |
449 or presence1.attr.type ~= presence2.attr.type then | |
450 return false | |
451 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
452 |
4913 | 453 if presence1.attr.id and presence1.attr.id == presence2.attr.id then return true; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
454 |
4913 | 455 if #presence1 ~= #presence2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
456 |
4913 | 457 for i=1,#presence1 do |
458 if type(presence1[i]) == "string" then | |
459 if presence1[i] ~= presence2[i] then return false; end | |
460 else | |
461 if not same_tags(presence1[i], presence2[i]) then return false; end | |
462 end | |
463 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
464 |
4913 | 465 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
466 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
467 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
468 local function forward_presence(presence, to_jid) |
4913 | 469 local presence_fwd = st.clone(presence) |
470 presence_fwd.attr.to = to_jid | |
471 module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) | |
472 module:send(presence_fwd) | |
473 -- cache used to avoid to send several times the same stanza | |
474 priv_session.last_presence = presence | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
475 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
476 |
1664
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
477 module:hook("presence/bare", function(event) |
4913 | 478 if presence_man_ent:empty() and presence_roster:empty() then return; end |
479 | |
480 local stanza = event.stanza | |
481 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then | |
482 if not stanza.attr.to then | |
483 for entity in presence_man_ent:items() do | |
484 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
485 end | |
486 else -- directed presence | |
487 -- we ignore directed presences from our own host, as we already have them | |
488 local _, from_host = jid.split(stanza.attr.from) | |
489 if hosts[from_host] then return; end | |
490 | |
491 -- we don't send several time the same presence, as recommended in §7 #2 | |
492 if priv_session.last_presence and same_presences(priv_session.last_presence, stanza) then | |
493 return | |
494 end | |
495 | |
496 for entity in presence_roster:items() do | |
497 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
498 end | |
499 end | |
500 end | |
501 end, 150) | |
502 | |
503 --> IQ permission <-- | |
504 | |
505 module:hook("iq/bare/".._PRIV_ENT_NS..":privileged_iq", function(event) | |
506 local session, stanza = event.origin, event.stanza | |
507 if not stanza.attr.to then | |
508 -- we don't want stanzas addressed to /self | |
509 return | |
510 end | |
511 local from_node, from_host, from_resource = jid.split(stanza.attr.to) | |
512 | |
513 if from_resource ~= nil or not usermanager_user_exists(from_node, from_host) then | |
514 session.send( | |
515 st.error_reply( | |
516 stanza, | |
517 "auth", | |
518 "forbidden", | |
519 "wrapping <IQ> stanza recipient must be a bare JID of a local user" | |
520 ) | |
521 ) | |
522 return true | |
523 end | |
524 | |
525 local session_privileges = get_session_privileges(session, from_host) | |
526 | |
527 if session_privileges == nil then | |
528 session.send( | |
529 st.error_reply( | |
530 stanza, | |
531 "auth", | |
532 "forbidden", | |
533 "no privilege granted" | |
534 ) | |
535 ) | |
536 return true | |
537 end | |
538 | |
539 local iq_privileges = session_privileges["iq"] | |
540 if iq_privileges == nil then | |
541 session.send( | |
542 session.send(st.error_reply(stanza, "auth", "forbidden", "you are not allowed to send privileged <IQ> stanzas")) | |
543 ) | |
544 return true | |
545 end | |
546 | |
547 local privileged_iq = stanza:get_child("privileged_iq", _PRIV_ENT_NS) | |
548 | |
549 local wrapped_iq = privileged_iq.tags[1] | |
550 if wrapped_iq == nil then | |
551 session.send( | |
552 st.error_reply(stanza, "auth", "forbidden", "missing <IQ> stanza to send") | |
553 ) | |
554 return true | |
555 end | |
556 | |
557 if wrapped_iq.attr.xmlns ~= "jabber:client" then | |
558 session.send( | |
559 st.error_reply( | |
560 stanza, | |
561 "auth", | |
562 "forbidden", | |
563 'wrapped <IQ> must have a xmlns of "jabber:client"' | |
564 ) | |
565 ) | |
566 return true | |
567 end | |
568 | |
569 clean_xmlns(wrapped_iq) | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
570 |
4913 | 571 if #wrapped_iq.tags ~= 1 then |
572 session.send( | |
573 st.error_reply( | |
574 stanza, | |
575 "auth", | |
576 "forbidden", | |
577 'invalid payload in wrapped <IQ>' | |
578 ) | |
579 ) | |
580 return true | |
581 end | |
582 | |
583 local payload = wrapped_iq.tags[1] | |
584 | |
585 local priv_ns = payload.attr.xmlns | |
586 if priv_ns == nil then | |
587 session.send( | |
588 st.error_reply(stanza, "auth", "forbidden", "xmlns not set in privileged <IQ>") | |
589 ) | |
590 return true | |
591 end | |
592 | |
593 local ns_perms = iq_privileges[priv_ns] | |
594 local iq_type = stanza.attr.type | |
595 if ns_perms == nil or iq_type == nil or not ns_perms[iq_type] then | |
596 session.send( | |
597 session.send(st.error_reply( | |
598 stanza, | |
599 "auth", | |
600 "forbidden", | |
601 "you are not allowed to send privileged <IQ> stanzas of this type and namespace") | |
602 ) | |
603 ) | |
604 return true | |
605 end | |
606 | |
607 if wrapped_iq.attr.from ~= nil and wrapped_iq.attr.from ~= stanza.attr.to then | |
608 session.send( | |
609 st.error_reply( | |
610 stanza, | |
611 "auth", | |
612 "forbidden", | |
613 'wrapped <IQ> "from" attribute is inconsistent with main <IQ> "to" attribute' | |
614 ) | |
615 ) | |
616 return true | |
617 end | |
618 | |
619 wrapped_iq.attr.from = stanza.attr.to | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
620 |
4913 | 621 if wrapped_iq.attr.to == nil then |
622 session.send( | |
623 st.error_reply( | |
624 stanza, | |
625 "auth", | |
626 "forbidden", | |
627 'wrapped <IQ> "to" attribute is missing' | |
628 ) | |
629 ) | |
630 return true | |
631 end | |
632 | |
633 if wrapped_iq.attr.type ~= iq_type then | |
634 session.send( | |
635 st.error_reply( | |
636 stanza, | |
637 "auth", | |
638 "forbidden", | |
639 'invalid wrapped <IQ>: type mismatch' | |
640 ) | |
641 ) | |
642 return true | |
643 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
644 |
4913 | 645 if wrapped_iq.attr.id == nil then |
646 session.send( | |
647 st.error_reply( | |
648 stanza, | |
649 "auth", | |
650 "forbidden", | |
651 'invalid wrapped <IQ>: missing "id" attribute' | |
652 ) | |
653 ) | |
654 return true | |
655 end | |
656 | |
657 -- at this point, wrapped_iq is considered valid, and privileged entity is allowed to send it | |
658 | |
659 module:send_iq(wrapped_iq) | |
660 :next(function (response) | |
661 local reply = st.reply(stanza); | |
662 response.stanza.attr.xmlns = 'jabber:client' | |
663 reply:tag("privilege", {xmlns = _PRIV_ENT_NS}) | |
664 :tag("forwarded", {xmlns = _FORWARDED_NS}) | |
665 :add_child(response.stanza) | |
666 session.send(reply) | |
667 end, | |
668 function(response) | |
669 module:log("error", "Error while sending privileged <IQ>: %s", response); | |
670 session.send( | |
671 st.error_reply( | |
672 stanza, | |
673 "cancel", | |
674 "internal-server-error" | |
675 ) | |
676 ) | |
677 end) | |
678 | |
679 return true | |
680 end) |