Software /
code /
prosody-modules
Annotate
mod_privilege/mod_privilege.lua @ 5160:8474a3b80200
mod_firewall: Fix 'is_admin' internal dependency rule #1797 (thanks diane)
Looks like the boolean logic was inverted here. Instead, for now,
simply check if is_admin is there. It is deprecated in trunk and was
briefly removed before being brought back with a 'deprecated' warning as
part of the new roles and permissions work. Making this dependency
conditioned on the existence of the underlying function should make it
work until it actually goes away for real.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 27 Jan 2023 23:06:25 +0100 |
parent | 4994:cce12a660b98 |
child | 5897:a88c43de648c |
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) |
4937 | 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") |
4937 | 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 |
4937 | 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 |
4937 | 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} |
4937 | 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 |
4937 | 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 |
4937 | 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) |
4937 | 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 |
4937 | 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) |
4937 | 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) |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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) |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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) |
4937 | 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) |
4937 | 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) |
4937 | 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) |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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) |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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 |
4937 | 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 |
3393
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
371 local function clean_xmlns(node) |
4937 | 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 | |
3393
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) |
4937 | 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 |
4937 | 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 | |
4994
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
396 local username, from_host, from_resource = jid.split(message_elt.attr.from) |
4937 | 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 | |
4994
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
399 local session = { |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
400 username = username; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
401 host = from_host; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
402 type = "c2s"; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
403 log = module._log; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
404 } |
4937 | 405 -- at this point everything should be alright, we can send the message |
4994
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
406 prosody.core_post_stanza(session, message_elt, true) |
4937 | 407 else -- trying to send a message from a forbidden entity |
408 module:log("warn", "Entity "..tostring(session.full_jid).." try to send a message from "..tostring(message_elt.attr.from)) | |
409 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
410 end | |
411 else -- incorrect message child | |
412 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid forwarded <message/> element")) | |
413 end | |
414 else -- incorrect forwarded child | |
415 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid <forwarded/> element")) | |
416 end | |
417 else -- The permission is not granted | |
418 module:log("warn", "Entity "..tostring(session.full_jid).." try to send message without permission") | |
419 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
420 end | |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
421 |
4937 | 422 return true |
423 end) | |
1664
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
424 |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
425 |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
426 --> presence permission <-- |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
427 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
428 local function same_tags(tag1, tag2) |
4937 | 429 -- check if two tags are equivalent |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
430 |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
431 if tag1.name ~= tag2.name then return false; end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
432 |
4937 | 433 if #tag1 ~= #tag2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
434 |
4937 | 435 for name, value in pairs(tag1.attr) do |
436 if tag2.attr[name] ~= value then return false; end | |
437 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
438 |
4937 | 439 for i=1,#tag1 do |
440 if type(tag1[i]) == "string" then | |
441 if tag1[i] ~= tag2[i] then return false; end | |
442 else | |
443 if not same_tags(tag1[i], tag2[i]) then return false; end | |
444 end | |
445 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
446 |
4937 | 447 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
448 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
449 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
450 local function same_presences(presence1, presence2) |
4937 | 451 -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) |
452 -- /!\ if the id change but everything else is equivalent, this method return false | |
453 -- this behaviour may change in the future | |
454 if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id | |
455 or presence1.attr.type ~= presence2.attr.type then | |
456 return false | |
457 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
458 |
4937 | 459 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
|
460 |
4937 | 461 if #presence1 ~= #presence2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
462 |
4937 | 463 for i=1,#presence1 do |
464 if type(presence1[i]) == "string" then | |
465 if presence1[i] ~= presence2[i] then return false; end | |
466 else | |
467 if not same_tags(presence1[i], presence2[i]) then return false; end | |
468 end | |
469 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
470 |
4937 | 471 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
472 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
473 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
474 local function forward_presence(presence, to_jid) |
4937 | 475 local presence_fwd = st.clone(presence) |
476 presence_fwd.attr.to = to_jid | |
477 module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) | |
478 module:send(presence_fwd) | |
479 -- cache used to avoid to send several times the same stanza | |
480 priv_session.last_presence = presence | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
481 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
482 |
1664
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
483 module:hook("presence/bare", function(event) |
4937 | 484 if presence_man_ent:empty() and presence_roster:empty() then return; end |
485 | |
486 local stanza = event.stanza | |
487 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then | |
488 if not stanza.attr.to then | |
489 for entity in presence_man_ent:items() do | |
490 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
491 end | |
492 else -- directed presence | |
493 -- we ignore directed presences from our own host, as we already have them | |
494 local _, from_host = jid.split(stanza.attr.from) | |
495 if hosts[from_host] then return; end | |
496 | |
497 -- we don't send several time the same presence, as recommended in §7 #2 | |
498 if priv_session.last_presence and same_presences(priv_session.last_presence, stanza) then | |
499 return | |
500 end | |
501 | |
502 for entity in presence_roster:items() do | |
503 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
504 end | |
505 end | |
506 end | |
507 end, 150) | |
508 | |
509 --> IQ permission <-- | |
510 | |
511 module:hook("iq/bare/".._PRIV_ENT_NS..":privileged_iq", function(event) | |
512 local session, stanza = event.origin, event.stanza | |
513 if not stanza.attr.to then | |
514 -- we don't want stanzas addressed to /self | |
515 return | |
516 end | |
517 local from_node, from_host, from_resource = jid.split(stanza.attr.to) | |
518 | |
519 if from_resource ~= nil or not usermanager_user_exists(from_node, from_host) then | |
520 session.send( | |
521 st.error_reply( | |
522 stanza, | |
523 "auth", | |
524 "forbidden", | |
525 "wrapping <IQ> stanza recipient must be a bare JID of a local user" | |
526 ) | |
527 ) | |
528 return true | |
529 end | |
530 | |
531 local session_privileges = get_session_privileges(session, from_host) | |
532 | |
533 if session_privileges == nil then | |
534 session.send( | |
535 st.error_reply( | |
536 stanza, | |
537 "auth", | |
538 "forbidden", | |
539 "no privilege granted" | |
540 ) | |
541 ) | |
542 return true | |
543 end | |
544 | |
545 local iq_privileges = session_privileges["iq"] | |
546 if iq_privileges == nil then | |
547 session.send( | |
548 session.send(st.error_reply(stanza, "auth", "forbidden", "you are not allowed to send privileged <IQ> stanzas")) | |
549 ) | |
550 return true | |
551 end | |
552 | |
553 local privileged_iq = stanza:get_child("privileged_iq", _PRIV_ENT_NS) | |
554 | |
555 local wrapped_iq = privileged_iq.tags[1] | |
556 if wrapped_iq == nil then | |
557 session.send( | |
558 st.error_reply(stanza, "auth", "forbidden", "missing <IQ> stanza to send") | |
559 ) | |
560 return true | |
561 end | |
562 | |
563 if wrapped_iq.attr.xmlns ~= "jabber:client" then | |
564 session.send( | |
565 st.error_reply( | |
566 stanza, | |
567 "auth", | |
568 "forbidden", | |
569 'wrapped <IQ> must have a xmlns of "jabber:client"' | |
570 ) | |
571 ) | |
572 return true | |
573 end | |
574 | |
575 clean_xmlns(wrapped_iq) | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
576 |
4937 | 577 if #wrapped_iq.tags ~= 1 then |
578 session.send( | |
579 st.error_reply( | |
580 stanza, | |
581 "auth", | |
582 "forbidden", | |
583 'invalid payload in wrapped <IQ>' | |
584 ) | |
585 ) | |
586 return true | |
587 end | |
588 | |
589 local payload = wrapped_iq.tags[1] | |
590 | |
591 local priv_ns = payload.attr.xmlns | |
592 if priv_ns == nil then | |
593 session.send( | |
594 st.error_reply(stanza, "auth", "forbidden", "xmlns not set in privileged <IQ>") | |
595 ) | |
596 return true | |
597 end | |
598 | |
599 local ns_perms = iq_privileges[priv_ns] | |
600 local iq_type = stanza.attr.type | |
601 if ns_perms == nil or iq_type == nil or not ns_perms[iq_type] then | |
602 session.send( | |
603 session.send(st.error_reply( | |
604 stanza, | |
605 "auth", | |
606 "forbidden", | |
607 "you are not allowed to send privileged <IQ> stanzas of this type and namespace") | |
608 ) | |
609 ) | |
610 return true | |
611 end | |
612 | |
613 if wrapped_iq.attr.from ~= nil and wrapped_iq.attr.from ~= stanza.attr.to then | |
614 session.send( | |
615 st.error_reply( | |
616 stanza, | |
617 "auth", | |
618 "forbidden", | |
619 'wrapped <IQ> "from" attribute is inconsistent with main <IQ> "to" attribute' | |
620 ) | |
621 ) | |
622 return true | |
623 end | |
624 | |
625 wrapped_iq.attr.from = stanza.attr.to | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
626 |
4937 | 627 |
628 if wrapped_iq.attr.type ~= iq_type then | |
629 session.send( | |
630 st.error_reply( | |
631 stanza, | |
632 "auth", | |
633 "forbidden", | |
634 'invalid wrapped <IQ>: type mismatch' | |
635 ) | |
636 ) | |
637 return true | |
638 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
639 |
4937 | 640 if wrapped_iq.attr.id == nil then |
641 session.send( | |
642 st.error_reply( | |
643 stanza, | |
644 "auth", | |
645 "forbidden", | |
646 'invalid wrapped <IQ>: missing "id" attribute' | |
647 ) | |
648 ) | |
649 return true | |
650 end | |
651 | |
652 -- at this point, wrapped_iq is considered valid, and privileged entity is allowed to send it | |
4994
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
653 local username, from_host, _ = jid.split(wrapped_iq.attr.from) |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
654 local newsession = { |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
655 username = username; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
656 host = from_host; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
657 full_jid = stanza.attr.to; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
658 type = "c2s"; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
659 log = module._log; |
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
660 } |
4937 | 661 |
4994
cce12a660b98
mod_privilege: process entity IQs (credit to adx) and messages with a constructed entity session
Nicoco <nicoco@nicoco.fr>
parents:
4937
diff
changeset
|
662 module:send_iq(wrapped_iq,newsession) |
4937 | 663 :next(function (response) |
664 local reply = st.reply(stanza); | |
665 response.stanza.attr.xmlns = 'jabber:client' | |
666 reply:tag("privilege", {xmlns = _PRIV_ENT_NS}) | |
667 :tag("forwarded", {xmlns = _FORWARDED_NS}) | |
668 :add_child(response.stanza) | |
669 session.send(reply) | |
670 end, | |
671 function(response) | |
672 module:log("error", "Error while sending privileged <IQ>: %s", response); | |
673 session.send( | |
674 st.error_reply( | |
675 stanza, | |
676 "cancel", | |
677 "internal-server-error" | |
678 ) | |
679 ) | |
680 end) | |
681 | |
682 return true | |
683 end) |