mod_privilege/mod_privilege.lua
author Goffi <goffi@goffi.org>
Thu, 02 Apr 2015 21:47:05 +0200
changeset 1663 495a093798eb
parent 1662 1146cb4493a9
child 1664 d1072db4db44
permissions -rw-r--r--
mod_privilege: added permissions notification on initial presence for entities which are not components
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1662
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     1
-- XEP-0356 (Privileged Entity)
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     2
-- Copyright (C) 2015 Jérôme Poisson
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     3
--
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     4
-- This module is MIT/X11 licensed. Please see the
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     5
-- COPYING file in the source package for more information.
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     6
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
     7
1661
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
     8
local jid = require("util/jid")
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
     9
local set = require("util/set")
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    10
local st = require("util/stanza")
1662
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    11
local roster_manager = require("core/rostermanager")
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    12
1661
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    13
local _ALLOWED_ROSTER = set.new({'none', 'get', 'set', 'both'})
1662
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    14
local _ROSTER_GET_PERM = set.new({'get', 'both'})
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    15
local _ROSTER_SET_PERM = set.new({'set', 'both'})
1661
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    16
local _ALLOWED_MESSAGE = set.new({'none', 'outgoing'})
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    17
local _ALLOWED_PRESENCE = set.new({'none', 'managed_entity', 'roster'})
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    18
local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE}
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    19
local _PRIV_ENT_NS = 'urn:xmpp:privilege:1'
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    20
1662
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    21
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    22
module:log("debug", "Loading privileged entity module ");
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    23
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    24
--> Permissions management <--
1661
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    25
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    26
privileges = module:get_option("privileged_entities", {})
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    27
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    28
function advertise_perm(to_jid, perms)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    29
	-- send <message/> stanza to advertise permissions
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    30
	-- as expained in section 4.2
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    31
	local message = st.message({to=to_jid})
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    32
					  :tag("privilege", {xmlns=_PRIV_ENT_NS})
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    33
	
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    34
	for _, perm in pairs({'roster', 'message', 'presence'}) do
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    35
		if perms[perm] then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    36
			message:tag("perm", {access=perm, type=perms[perm]}):up()
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    37
		end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    38
	end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    39
	
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    40
	module:send(message)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    41
end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    42
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    43
function on_auth(event)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    44
	-- Check if entity is privileged according to configuration,
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    45
	-- and set session.privileges accordingly
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    46
	
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    47
	local session = event.session
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    48
	local bare_jid = jid.join(session.username, session.host)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    49
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    50
	local ent_priv = privileges[bare_jid]
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    51
	if ent_priv ~= nil then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    52
		module:log("debug", "Entity is privileged")
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    53
		for perm_type, allowed_values in pairs(_TO_CHECK) do
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    54
			local value = ent_priv[perm_type]
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    55
			if value ~= nil then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    56
				if not allowed_values:contains(value) then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    57
					module:log('warn', 'Invalid value for '..perm_type..' privilege: ['..value..']')
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    58
					module:log('warn', 'Setting '..perm_type..' privilege to none')
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    59
					ent_priv[perm_type] = nil
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    60
				end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    61
				if value == 'none' then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    62
					ent_priv[perm_type] = nil
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    63
				end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    64
			end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    65
		end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    66
		if session.type == "component" then
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    67
			-- we send the message stanza only for component
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    68
			-- it will be sent at first <presence/> for other entities
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    69
			advertise_perm(bare_jid, ent_priv)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    70
		end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    71
	end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    72
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    73
	session.privileges = ent_priv
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    74
end
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    75
1663
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    76
function on_presence(event)
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    77
	-- Permission are already checked at this point,
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    78
	-- we only advertise them to the entity
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    79
	local session, stanza = event.origin, event.stanza;
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    80
	if session.privileges then
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    81
		advertise_perm(session.full_jid, session.privileges)
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    82
	end
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    83
end
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    84
1661
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    85
module:hook('authentication-success', on_auth)
7116bc76663b mod_privilege: mod_privilege first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
    86
module:hook('component-authenticated', on_auth)
1663
495a093798eb mod_privilege: added permissions notification on initial presence for entities which are not components
Goffi <goffi@goffi.org>
parents: 1662
diff changeset
    87
module:hook('presence/initial', on_presence)
1662
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    88
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    89
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    90
--> roster permission <--
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    91
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    92
module:hook("iq-get/bare/jabber:iq:roster:query", function(event)
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    93
	local session, stanza = event.origin, event.stanza;
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    94
	if not stanza.attr.to then
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    95
		-- we don't want stanzas addressed to /self
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    96
		return;
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    97
	end
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    98
	
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
    99
	if session.privileges and _ROSTER_GET_PERM:contains(session.privileges.roster) then
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   100
		module:log("debug", "Roster get from allowed privileged entity received")
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   101
		-- following code is adapted from mod_remote_roster
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   102
		local node, host = jid.split(stanza.attr.to);
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   103
		local roster = roster_manager.load_roster(node, host);
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   104
		
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   105
		local reply = st.reply(stanza):query("jabber:iq:roster");
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   106
		for entity_jid, item in pairs(roster) do
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   107
			if entity_jid and entity_jid ~= "pending" then
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   108
				local node, host = jid.split(entity_jid);
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   109
					reply:tag("item", {
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   110
						jid = entity_jid,
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   111
						subscription = item.subscription,
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   112
						ask = item.ask,
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   113
						name = item.name,
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   114
					});
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   115
					for group in pairs(item.groups) do
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   116
						reply:tag("group"):text(group):up();
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   117
					end
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   118
					reply:up(); -- move out from item
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   119
			end
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   120
		end
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   121
		session.send(reply);
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   122
	else
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   123
	    module:log("warn", "Entity "..tostring(session.full_jid).." try to get roster without permission")
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   124
		session.send(st.error_reply(stanza, 'auth', 'forbidden'))
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   125
	end
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   126
	
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   127
	return true
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   128
1146cb4493a9 mod_privilege: roster get permission implemented
Goffi <goffi@goffi.org>
parents: 1661
diff changeset
   129
end);