Software /
code /
prosody-modules
Annotate
mod_privilege/mod_privilege.lua @ 6199:fe8222112cf4
mod_conversejs: Serve base app at /
This makes things slightly less awkward for the browser to figure out which
URLs belong to a PWA. The app's "start URL" was previously without the '/' and
therefore was not considered within the scope of the PWA. Now the canonical
app URL will always have a '/'.
Prosody/mod_http should take care of redirecting existing links without the
trailing / to the new URL.
If you have an installation at https://prosody/conversejs then it is now at
https://prosody/conversejs/ (the first URL will now redirect to the second
URL if you use it).
The alternative would be to make the PWA scope include the parent, i.e.
the whole of https://prosody/ in this case. This might get messy if other
PWAs are provided by the same site or Prosody installation, however.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Tue, 11 Feb 2025 13:18:38 +0000 |
parent | 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 | |
5897
a88c43de648c
mod_privilege: Fix IQ privileges advertising for multiple namespaces
nicoco <nicoco@nicoco.fr>
parents:
4994
diff
changeset
|
72 local perm_el = st.stanza("perm", {access="iq"}) |
4937 | 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 | |
5897
a88c43de648c
mod_privilege: Fix IQ privileges advertising for multiple namespaces
nicoco <nicoco@nicoco.fr>
parents:
4994
diff
changeset
|
84 perm_el:tag("namespace", {ns=namespace, type=perm_type}):up() |
4937 | 85 end |
5897
a88c43de648c
mod_privilege: Fix IQ privileges advertising for multiple namespaces
nicoco <nicoco@nicoco.fr>
parents:
4994
diff
changeset
|
86 message:add_child(perm_el) |
4937 | 87 end |
88 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
|
89 end |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
90 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
91 local function set_presence_perm_set(to_jid, perms) |
4937 | 92 -- fill the presence sets according to perms |
93 if _PRESENCE_MANAGED:contains(perms.presence) then | |
94 presence_man_ent:add(to_jid) | |
95 end | |
96 if perms.presence == 'roster' then | |
97 presence_roster:add(to_jid) | |
98 end | |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 end |
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
100 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
101 local function advertise_presences(session, to_jid, perms) |
4937 | 102 -- send presence status for already connected entities |
103 -- as explained in § 7.1 | |
104 -- people in roster are probed only for active sessions | |
105 -- TODO: manage roster load for inactive sessions | |
106 if not perms.presence then return; end | |
107 local to_probe = {} | |
108 for _, user_session in pairs(full_sessions) do | |
109 if user_session.presence and _PRESENCE_MANAGED:contains(perms.presence) then | |
110 local presence = st.clone(user_session.presence) | |
111 presence.attr.to = to_jid | |
112 module:log("debug", "sending current presence for "..tostring(user_session.full_jid)) | |
113 session.send(presence) | |
114 end | |
115 if perms.presence == "roster" then | |
116 -- we reset the cache to avoid to miss a presence that just changed | |
117 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
|
118 |
4937 | 119 if user_session.roster then |
120 local bare_jid = jid.bare(user_session.full_jid) | |
121 for entity, item in pairs(user_session.roster) do | |
122 if entity~=false and entity~="pending" and (item.subscription=="both" or item.subscription=="to") then | |
123 local _, host = jid.split(entity) | |
124 if not hosts[host] then -- we don't probe jid from hosts we manage | |
125 -- using a table with entity as key avoid probing several time the same one | |
126 to_probe[entity] = bare_jid | |
127 end | |
128 end | |
129 end | |
130 end | |
131 end | |
132 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
|
133 |
4937 | 134 -- now we probe peoples for "roster" presence permission |
135 for probe_to, probe_from in pairs(to_probe) do | |
136 module:log("debug", "probing presence for %s (on behalf of %s)", tostring(probe_to), tostring(probe_from)) | |
137 local probe = st.presence({from=probe_from, to=probe_to, type="probe"}) | |
138 prosody.core_route_stanza(nil, probe) | |
139 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
|
140 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
|
141 |
4937 | 142 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
143 local function on_auth(event) |
4937 | 144 -- Check if entity is privileged according to configuration, |
145 -- and set session.privileges accordingly | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
146 |
4937 | 147 local session = event.session |
148 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
|
149 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
|
150 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
|
151 end |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
152 |
4937 | 153 local conf_ent_priv = config_priv[bare_jid] |
154 local ent_priv = {} | |
155 if conf_ent_priv ~= nil then | |
156 module:log("debug", "Entity is privileged") | |
157 for perm_type, allowed_values in pairs(_TO_CHECK) do | |
158 local value = conf_ent_priv[perm_type] | |
159 if value ~= nil then | |
160 if not allowed_values:contains(value) then | |
161 module:log('warn', 'Invalid value for '..perm_type..' privilege: ['..value..']') | |
162 module:log('warn', 'Setting '..perm_type..' privilege to none') | |
163 ent_priv[perm_type] = nil | |
164 elseif value == 'none' then | |
165 ent_priv[perm_type] = nil | |
166 else | |
167 ent_priv[perm_type] = value | |
168 end | |
169 else | |
170 ent_priv[perm_type] = nil | |
171 end | |
172 end | |
173 -- extra checks for presence permission | |
174 if ent_priv.presence == 'roster' and not _ROSTER_GET_PERM:contains(ent_priv.roster) then | |
175 module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") | |
176 module:log("warn", "Setting presence permission to none") | |
177 ent_priv.presence = nil | |
178 end | |
179 -- iq permission | |
180 local iq_perm_config = conf_ent_priv["iq"] | |
181 if iq_perm_config ~= nil then | |
182 local iq_perm = {} | |
183 ent_priv["iq"] = iq_perm | |
184 for ns, ns_perm_config in pairs(iq_perm_config) do | |
185 iq_perm[ns] = { | |
186 ["get"] = ns_perm_config == "get" or ns_perm_config == "both", | |
187 ["set"] = ns_perm_config == "set" or ns_perm_config == "both" | |
188 } | |
189 end | |
190 else | |
191 ent_priv["iq"] = nil | |
192 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
|
193 |
4937 | 194 if session.type == "component" then |
195 -- we send the message stanza only for component | |
196 -- it will be sent at first <presence/> for other entities | |
197 advertise_perm(session, bare_jid, ent_priv) | |
198 set_presence_perm_set(bare_jid, ent_priv) | |
199 advertise_presences(session, bare_jid, ent_priv) | |
200 end | |
201 end | |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
202 |
4937 | 203 session.privileges[_MODULE_HOST] = ent_priv |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 end |
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
205 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
206 local function on_presence(event) |
4937 | 207 -- Permission are already checked at this point, |
208 -- we only advertise them to the entity | |
209 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
|
210 local session_privileges = get_session_privileges(session, _MODULE_HOST) |
4937 | 211 if session_privileges then |
212 advertise_perm(session, session.full_jid, session_privileges) | |
213 set_presence_perm_set(session.full_jid, session_privileges) | |
214 advertise_presences(session, session.full_jid, session_privileges) | |
215 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
|
216 end |
495a093798eb
mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents:
1658
diff
changeset
|
217 |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
218 local function on_component_auth(event) |
4937 | 219 -- react to component-authenticated event from this host |
220 -- and call the on_auth methods from all other hosts | |
221 -- needed for the component to get delegations advertising | |
222 for callback in connected_cb:items() do | |
223 callback(event) | |
224 end | |
1708
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
225 end |
ad7afcf86131
mod_privilege: fixed bad handling of presence permissions / component authentication between different hosts
Goffi <goffi@goffi.org>
parents:
1707
diff
changeset
|
226 |
1775
0d78bb31348e
mod_privilege: fixed bad calling of on_auth for components
Goffi <goffi@goffi.org>
parents:
1708
diff
changeset
|
227 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
|
228 connected_cb:add(on_auth) |
0d78bb31348e
mod_privilege: fixed bad calling of on_auth for components
Goffi <goffi@goffi.org>
parents:
1708
diff
changeset
|
229 end |
1657
7116bc76663b
mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
230 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
|
231 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
|
232 module:hook('presence/initial', on_presence) |
1658
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 |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
235 --> roster permission <-- |
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
236 |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
237 -- get |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
238 module:hook("iq-get/bare/jabber:iq:roster:query", function(event) |
4937 | 239 local session, stanza = event.origin, event.stanza |
240 if not stanza.attr.to then | |
241 -- we don't want stanzas addressed to /self | |
242 return | |
243 end | |
244 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
|
245 local session_privileges = get_session_privileges(session, host) |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
246 |
4937 | 247 if session_privileges and _ROSTER_GET_PERM:contains(session_privileges.roster) then |
248 module:log("debug", "Roster get from allowed privileged entity received") | |
249 -- following code is adapted from mod_remote_roster | |
250 local roster = roster_manager.load_roster(node, host) | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
251 |
4937 | 252 local reply = st.reply(stanza):query("jabber:iq:roster") |
253 for entity_jid, item in pairs(roster) do | |
254 if entity_jid and entity_jid ~= "pending" then | |
255 reply:tag("item", { | |
256 jid = entity_jid, | |
257 subscription = item.subscription, | |
258 ask = item.ask, | |
259 name = item.name, | |
260 }) | |
261 for group in pairs(item.groups) do | |
262 reply:tag("group"):text(group):up() | |
263 end | |
264 reply:up(); -- move out from item | |
265 end | |
266 end | |
267 -- end of code adapted from mod_remote_roster | |
268 session.send(reply) | |
269 else | |
270 module:log("warn", "Entity "..tostring(session.full_jid).." try to get roster without permission") | |
271 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
272 end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
273 |
4937 | 274 return true |
275 end) | |
1658
1146cb4493a9
mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents:
1657
diff
changeset
|
276 |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
277 -- set |
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
278 module:hook("iq-set/bare/jabber:iq:roster:query", function(event) |
4937 | 279 local session, stanza = event.origin, event.stanza |
280 if not stanza.attr.to then | |
281 -- we don't want stanzas addressed to /self | |
282 return | |
283 end | |
284 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
|
285 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
|
286 |
4937 | 287 if session_privileges and _ROSTER_SET_PERM:contains(session_privileges.roster) then |
288 module:log("debug", "Roster set from allowed privileged entity received") | |
289 -- following code is adapted from mod_remote_roster | |
290 if not(usermanager_user_exists(from_node, from_host)) then return; end | |
291 local roster = roster_manager.load_roster(from_node, from_host) | |
292 if not(roster) then return; end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
293 |
4937 | 294 local query = stanza.tags[1] |
295 for _, item in ipairs(query.tags) do | |
296 if item.name == "item" | |
297 and item.attr.xmlns == "jabber:iq:roster" and item.attr.jid | |
298 -- Protection against overwriting roster.pending, until we move it | |
299 and item.attr.jid ~= "pending" then | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
300 |
4937 | 301 local item_jid = jid.prep(item.attr.jid) |
302 local _, host, resource = jid.split(item_jid) | |
303 if not resource then | |
304 if item_jid ~= stanza.attr.to then -- not self-item_jid | |
305 if item.attr.subscription == "remove" then | |
306 local r_item = roster[item_jid] | |
307 if r_item then | |
308 roster[item_jid] = nil | |
309 if roster_manager.save_roster(from_node, from_host, roster) then | |
310 session.send(st.reply(stanza)) | |
311 roster_manager.roster_push(from_node, from_host, item_jid) | |
312 else | |
313 roster[item_jid] = item | |
314 session.send(st.error_reply(stanza, "wait", "internal-server-error", "Unable to save roster")) | |
315 end | |
316 else | |
317 session.send(st.error_reply(stanza, "modify", "item-not-found")) | |
318 end | |
319 else | |
320 local subscription = item.attr.subscription | |
321 if subscription ~= "both" and subscription ~= "to" and subscription ~= "from" and subscription ~= "none" then -- TODO error on invalid | |
322 subscription = roster[item_jid] and roster[item_jid].subscription or "none" | |
323 end | |
324 local r_item = {name = item.attr.name, groups = {}} | |
325 if r_item.name == "" then r_item.name = nil; end | |
326 r_item.subscription = subscription | |
327 if subscription ~= "both" and subscription ~= "to" then | |
328 r_item.ask = roster[item_jid] and roster[item_jid].ask | |
329 end | |
330 for _, child in ipairs(item) do | |
331 if child.name == "group" then | |
332 local text = table.concat(child) | |
333 if text and text ~= "" then | |
334 r_item.groups[text] = true | |
335 end | |
336 end | |
337 end | |
338 local olditem = roster[item_jid] | |
339 roster[item_jid] = r_item | |
340 if roster_manager.save_roster(from_node, from_host, roster) then -- Ok, send success | |
341 session.send(st.reply(stanza)) | |
342 -- and push change to all resources | |
343 roster_manager.roster_push(from_node, from_host, item_jid) | |
344 else -- Adding to roster failed | |
345 roster[item_jid] = olditem | |
346 session.send(st.error_reply(stanza, "wait", "internal-server-error", "Unable to save roster")) | |
347 end | |
348 end | |
349 else -- Trying to add self to roster | |
350 session.send(st.error_reply(stanza, "cancel", "not-allowed")) | |
351 end | |
352 else -- Invalid JID added to roster | |
353 module:log("warn", "resource: %s , host: %s", tostring(resource), tostring(host)) | |
354 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error? | |
355 end | |
356 else -- Roster set didn't include a single item, or its name wasn't 'item' | |
357 session.send(st.error_reply(stanza, "modify", "bad-request")) | |
358 end | |
359 end -- for loop end | |
360 -- end of code adapted from mod_remote_roster | |
361 else -- The permission is not granted | |
362 module:log("warn", "Entity "..tostring(session.full_jid).." try to set roster without permission") | |
363 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
364 end | |
1660
d1072db4db44
mod_privilege: implemented roster set privilege
Goffi <goffi@goffi.org>
parents:
1659
diff
changeset
|
365 |
4937 | 366 return true |
367 end) | |
1661
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 |
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
370 --> message permission <-- |
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
371 |
3393
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
372 local function clean_xmlns(node) |
4937 | 373 -- Recursively remove "jabber:client" attribute from node. |
374 -- In Prosody internal routing, xmlns should not be set. | |
375 -- Keeping xmlns would lead to issues like mod_smacks ignoring the outgoing stanza, | |
376 -- so we remove all xmlns attributes with a value of "jabber:client" | |
377 if node.attr.xmlns == 'jabber:client' then | |
378 for childnode in node:childtags() do | |
379 clean_xmlns(childnode) | |
380 end | |
381 node.attr.xmlns = nil | |
382 end | |
3393
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
383 end |
7454274ead2f
mod_privilege: fixed routing issue with message permission:
Goffi <goffi@goffi.org>
parents:
2068
diff
changeset
|
384 |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
385 module:hook("message/host", function(event) |
4937 | 386 local session, stanza = event.origin, event.stanza |
387 local privilege_elt = stanza:get_child('privilege', _PRIV_ENT_NS) | |
388 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
|
389 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
|
390 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
|
391 |
4937 | 392 if session_privileges and session_privileges.message=="outgoing" then |
393 if #privilege_elt.tags==1 and privilege_elt.tags[1].name == "forwarded" | |
394 and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then | |
395 local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') | |
396 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
|
397 local username, from_host, from_resource = jid.split(message_elt.attr.from) |
4937 | 398 if from_resource == nil and hosts[from_host] then -- we only accept bare jids from one of the server hosts |
399 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
|
400 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
|
401 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
|
402 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
|
403 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
|
404 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
|
405 } |
4937 | 406 -- 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
|
407 prosody.core_post_stanza(session, message_elt, true) |
4937 | 408 else -- trying to send a message from a forbidden entity |
409 module:log("warn", "Entity "..tostring(session.full_jid).." try to send a message from "..tostring(message_elt.attr.from)) | |
410 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
411 end | |
412 else -- incorrect message child | |
413 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid forwarded <message/> element")) | |
414 end | |
415 else -- incorrect forwarded child | |
416 session.send(st.error_reply(stanza, "modify", "bad-request", "invalid <forwarded/> element")) | |
417 end | |
418 else -- The permission is not granted | |
419 module:log("warn", "Entity "..tostring(session.full_jid).." try to send message without permission") | |
420 session.send(st.error_reply(stanza, 'auth', 'forbidden')) | |
421 end | |
1661
69aa2b54ba8a
mod_privilege: implemented message privilege
Goffi <goffi@goffi.org>
parents:
1660
diff
changeset
|
422 |
4937 | 423 return true |
424 end) | |
1664
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 |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
427 --> presence permission <-- |
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
428 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
429 local function same_tags(tag1, tag2) |
4937 | 430 -- check if two tags are equivalent |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
431 |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
432 if tag1.name ~= tag2.name then return false; end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
433 |
4937 | 434 if #tag1 ~= #tag2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
435 |
4937 | 436 for name, value in pairs(tag1.attr) do |
437 if tag2.attr[name] ~= value then return false; end | |
438 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
439 |
4937 | 440 for i=1,#tag1 do |
441 if type(tag1[i]) == "string" then | |
442 if tag1[i] ~= tag2[i] then return false; end | |
443 else | |
444 if not same_tags(tag1[i], tag2[i]) then return false; end | |
445 end | |
446 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
447 |
4937 | 448 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
449 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
450 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
451 local function same_presences(presence1, presence2) |
4937 | 452 -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) |
453 -- /!\ if the id change but everything else is equivalent, this method return false | |
454 -- this behaviour may change in the future | |
455 if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id | |
456 or presence1.attr.type ~= presence2.attr.type then | |
457 return false | |
458 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
459 |
4937 | 460 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
|
461 |
4937 | 462 if #presence1 ~= #presence2 then return false; end |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
463 |
4937 | 464 for i=1,#presence1 do |
465 if type(presence1[i]) == "string" then | |
466 if presence1[i] ~= presence2[i] then return false; end | |
467 else | |
468 if not same_tags(presence1[i], presence2[i]) then return false; end | |
469 end | |
470 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
471 |
4937 | 472 return true |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
473 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
474 |
1707
64b3d1eb0cfe
mod_privilege: fixed various issues reported by luacheck
Goffi <goffi@goffi.org>
parents:
1667
diff
changeset
|
475 local function forward_presence(presence, to_jid) |
4937 | 476 local presence_fwd = st.clone(presence) |
477 presence_fwd.attr.to = to_jid | |
478 module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) | |
479 module:send(presence_fwd) | |
480 -- cache used to avoid to send several times the same stanza | |
481 priv_session.last_presence = presence | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
482 end |
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
483 |
1664
6bdcb1418029
mod_privilege: implemented "managed_entity" presence
Goffi <goffi@goffi.org>
parents:
1663
diff
changeset
|
484 module:hook("presence/bare", function(event) |
4937 | 485 if presence_man_ent:empty() and presence_roster:empty() then return; end |
486 | |
487 local stanza = event.stanza | |
488 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then | |
489 if not stanza.attr.to then | |
490 for entity in presence_man_ent:items() do | |
491 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
492 end | |
493 else -- directed presence | |
494 -- we ignore directed presences from our own host, as we already have them | |
495 local _, from_host = jid.split(stanza.attr.from) | |
496 if hosts[from_host] then return; end | |
497 | |
498 -- we don't send several time the same presence, as recommended in §7 #2 | |
499 if priv_session.last_presence and same_presences(priv_session.last_presence, stanza) then | |
500 return | |
501 end | |
502 | |
503 for entity in presence_roster:items() do | |
504 if stanza.attr.from ~= entity then forward_presence(stanza, entity); end | |
505 end | |
506 end | |
507 end | |
508 end, 150) | |
509 | |
510 --> IQ permission <-- | |
511 | |
512 module:hook("iq/bare/".._PRIV_ENT_NS..":privileged_iq", function(event) | |
513 local session, stanza = event.origin, event.stanza | |
514 if not stanza.attr.to then | |
515 -- we don't want stanzas addressed to /self | |
516 return | |
517 end | |
518 local from_node, from_host, from_resource = jid.split(stanza.attr.to) | |
519 | |
520 if from_resource ~= nil or not usermanager_user_exists(from_node, from_host) then | |
521 session.send( | |
522 st.error_reply( | |
523 stanza, | |
524 "auth", | |
525 "forbidden", | |
526 "wrapping <IQ> stanza recipient must be a bare JID of a local user" | |
527 ) | |
528 ) | |
529 return true | |
530 end | |
531 | |
532 local session_privileges = get_session_privileges(session, from_host) | |
533 | |
534 if session_privileges == nil then | |
535 session.send( | |
536 st.error_reply( | |
537 stanza, | |
538 "auth", | |
539 "forbidden", | |
540 "no privilege granted" | |
541 ) | |
542 ) | |
543 return true | |
544 end | |
545 | |
546 local iq_privileges = session_privileges["iq"] | |
547 if iq_privileges == nil then | |
548 session.send( | |
549 session.send(st.error_reply(stanza, "auth", "forbidden", "you are not allowed to send privileged <IQ> stanzas")) | |
550 ) | |
551 return true | |
552 end | |
553 | |
554 local privileged_iq = stanza:get_child("privileged_iq", _PRIV_ENT_NS) | |
555 | |
556 local wrapped_iq = privileged_iq.tags[1] | |
557 if wrapped_iq == nil then | |
558 session.send( | |
559 st.error_reply(stanza, "auth", "forbidden", "missing <IQ> stanza to send") | |
560 ) | |
561 return true | |
562 end | |
563 | |
564 if wrapped_iq.attr.xmlns ~= "jabber:client" then | |
565 session.send( | |
566 st.error_reply( | |
567 stanza, | |
568 "auth", | |
569 "forbidden", | |
570 'wrapped <IQ> must have a xmlns of "jabber:client"' | |
571 ) | |
572 ) | |
573 return true | |
574 end | |
575 | |
576 clean_xmlns(wrapped_iq) | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
577 |
4937 | 578 if #wrapped_iq.tags ~= 1 then |
579 session.send( | |
580 st.error_reply( | |
581 stanza, | |
582 "auth", | |
583 "forbidden", | |
584 'invalid payload in wrapped <IQ>' | |
585 ) | |
586 ) | |
587 return true | |
588 end | |
589 | |
590 local payload = wrapped_iq.tags[1] | |
591 | |
592 local priv_ns = payload.attr.xmlns | |
593 if priv_ns == nil then | |
594 session.send( | |
595 st.error_reply(stanza, "auth", "forbidden", "xmlns not set in privileged <IQ>") | |
596 ) | |
597 return true | |
598 end | |
599 | |
600 local ns_perms = iq_privileges[priv_ns] | |
601 local iq_type = stanza.attr.type | |
602 if ns_perms == nil or iq_type == nil or not ns_perms[iq_type] then | |
603 session.send( | |
604 session.send(st.error_reply( | |
605 stanza, | |
606 "auth", | |
607 "forbidden", | |
608 "you are not allowed to send privileged <IQ> stanzas of this type and namespace") | |
609 ) | |
610 ) | |
611 return true | |
612 end | |
613 | |
614 if wrapped_iq.attr.from ~= nil and wrapped_iq.attr.from ~= stanza.attr.to then | |
615 session.send( | |
616 st.error_reply( | |
617 stanza, | |
618 "auth", | |
619 "forbidden", | |
620 'wrapped <IQ> "from" attribute is inconsistent with main <IQ> "to" attribute' | |
621 ) | |
622 ) | |
623 return true | |
624 end | |
625 | |
626 wrapped_iq.attr.from = stanza.attr.to | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
627 |
4937 | 628 |
629 if wrapped_iq.attr.type ~= iq_type then | |
630 session.send( | |
631 st.error_reply( | |
632 stanza, | |
633 "auth", | |
634 "forbidden", | |
635 'invalid wrapped <IQ>: type mismatch' | |
636 ) | |
637 ) | |
638 return true | |
639 end | |
1666
0b1b4b7d5fe0
mod_privilege: implemented "roster" presence permission
Goffi <goffi@goffi.org>
parents:
1665
diff
changeset
|
640 |
4937 | 641 if wrapped_iq.attr.id == nil then |
642 session.send( | |
643 st.error_reply( | |
644 stanza, | |
645 "auth", | |
646 "forbidden", | |
647 'invalid wrapped <IQ>: missing "id" attribute' | |
648 ) | |
649 ) | |
650 return true | |
651 end | |
652 | |
653 -- 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
|
654 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
|
655 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
|
656 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
|
657 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
|
658 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
|
659 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
|
660 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
|
661 } |
4937 | 662 |
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
|
663 module:send_iq(wrapped_iq,newsession) |
4937 | 664 :next(function (response) |
665 local reply = st.reply(stanza); | |
666 response.stanza.attr.xmlns = 'jabber:client' | |
667 reply:tag("privilege", {xmlns = _PRIV_ENT_NS}) | |
668 :tag("forwarded", {xmlns = _FORWARDED_NS}) | |
669 :add_child(response.stanza) | |
670 session.send(reply) | |
671 end, | |
672 function(response) | |
673 module:log("error", "Error while sending privileged <IQ>: %s", response); | |
674 session.send( | |
675 st.error_reply( | |
676 stanza, | |
677 "cancel", | |
678 "internal-server-error" | |
679 ) | |
680 ) | |
681 end) | |
682 | |
683 return true | |
684 end) |