Annotate

plugins/adhoc/mod_adhoc.lua @ 13801:a5d5fefb8b68 13.0

mod_tls: Enable Prosody's certificate checking for incoming s2s connections (fixes #1916) (thanks Damian, Zash) Various options in Prosody allow control over the behaviour of the certificate verification process For example, some deployments choose to allow falling back to traditional "dialback" authentication (XEP-0220), while others verify via DANE, hard-coded fingerprints, or other custom plugins. Implementing this flexibility requires us to override OpenSSL's default certificate verification, to allow Prosody to verify the certificate itself, apply custom policies and make decisions based on the outcome. To enable our custom logic, we have to suppress OpenSSL's default behaviour of aborting the connection with a TLS alert message. With LuaSec, this can be achieved by using the verifyext "lsec_continue" flag. We also need to use the lsec_ignore_purpose flag, because XMPP s2s uses server certificates as "client" certificates (for mutual TLS verification in outgoing s2s connections). Commit 99d2100d2918 moved these settings out of the defaults and into mod_s2s, because we only really need these changes for s2s, and they should be opt-in, rather than automatically applied to all TLS services we offer. That commit was incomplete, because it only added the flags for incoming direct TLS connections. StartTLS connections are handled by mod_tls, which was not applying the lsec_* flags. It previously worked because they were already in the defaults. This resulted in incoming s2s connections with "invalid" certificates being aborted early by OpenSSL, even if settings such as `s2s_secure_auth = false` or DANE were present in the config. Outgoing s2s connections inherit verify "none" from the defaults, which means OpenSSL will receive the cert but will not terminate the connection when it is deemed invalid. This means we don't need lsec_continue there, and we also don't need lsec_ignore_purpose (because the remote peer is a "server"). Wondering why we can't just use verify "none" for incoming s2s? It's because in that mode, OpenSSL won't request a certificate from the peer for incoming connections. Setting verify "peer" is how you ask OpenSSL to request a certificate from the client, but also what triggers its built-in verification.
author Matthew Wild <mwild1@gmail.com>
date Tue, 01 Apr 2025 17:26:56 +0100
parent 13097:6771acb8e857
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 -- Copyright (C) 2009 Thilo Cestonaro
4291
122f142da281 mod_adhoc: Add support for commands only executable by global administrators
Florian Zeitz <florob@babelmonkeys.de>
parents: 3511
diff changeset
2 -- Copyright (C) 2009-2011 Florian Zeitz
3456
1201a743fe63 mod_adhoc: Code restructuring
Florian Zeitz <florob@babelmonkeys.de>
parents: 3286
diff changeset
3 --
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 -- This file is MIT/X11 licensed. Please see the
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 -- COPYING file in the source package for more information.
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 --
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7
12977
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12642
diff changeset
8 local it = require "prosody.util.iterators";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12642
diff changeset
9 local st = require "prosody.util.stanza";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12642
diff changeset
10 local jid_host = require "prosody.util.jid".host;
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 local adhoc_handle_cmd = module:require "adhoc".handle_cmd;
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local xmlns_cmd = "http://jabber.org/protocol/commands";
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 local commands = {};
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 module:add_feature(xmlns_cmd);
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16
13097
6771acb8e857 mod_adhoc: Silence permission errors when listing commands
Kim Alvefur <zash@zash.se>
parents: 13020
diff changeset
17 local function check_permissions(event, node, command, execute)
6771acb8e857 mod_adhoc: Silence permission errors when listing commands
Kim Alvefur <zash@zash.se>
parents: 13020
diff changeset
18 return (command.permission == "check" and module:may("adhoc:"..node, event, not execute))
12642
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
19 or (command.permission == "local_user" and jid_host(event.stanza.attr.from) == module.host)
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
20 or (command.permission == "any");
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
21 end
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
22
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
23 module:hook("host-disco-info-node", function (event)
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
24 local stanza, origin, reply, node = event.stanza, event.origin, event.reply, event.node;
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
25 if commands[node] then
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
26 local command = commands[node];
12642
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
27 if check_permissions(event, node, command) then
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
28 reply:tag("identity", { name = command.name,
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
29 category = "automation", type = "command-node" }):up();
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
30 reply:tag("feature", { var = xmlns_cmd }):up();
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
31 reply:tag("feature", { var = "jabber:x:data" }):up();
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
32 event.exists = true;
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
33 else
6841
be87ab2d611c plugins: Explicitly return to halt event propagation (session.send sometimes does not return true)
Kim Alvefur <zash@zash.se>
parents: 5762
diff changeset
34 origin.send(st.error_reply(stanza, "auth", "forbidden", "This item is not available to you"));
be87ab2d611c plugins: Explicitly return to halt event propagation (session.send sometimes does not return true)
Kim Alvefur <zash@zash.se>
parents: 5762
diff changeset
35 return true;
3457
24d2c9be0149 mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents: 3456
diff changeset
36 end
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
37 elseif node == xmlns_cmd then
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
38 reply:tag("identity", { name = "Ad-Hoc Commands",
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
39 category = "automation", type = "command-list" }):up();
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
40 event.exists = true;
3457
24d2c9be0149 mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents: 3456
diff changeset
41 end
24d2c9be0149 mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents: 3456
diff changeset
42 end);
24d2c9be0149 mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents: 3456
diff changeset
43
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
44 module:hook("host-disco-items-node", function (event)
12642
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
45 local reply, disco_node = event.reply, event.node;
8460
77e59f8057bf mod_adhoc: Rename variable to avoid name clash [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6841
diff changeset
46 if disco_node ~= xmlns_cmd then
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
47 return;
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
48 end
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
49
9331
2f634cc02eac mod_adhoc: Use util.iterators.sorted_pairs() to sort commands
Matthew Wild <mwild1@gmail.com>
parents: 9222
diff changeset
50 for node, command in it.sorted_pairs(commands) do
12642
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
51 if check_permissions(event, node, command) then
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
52 reply:tag("item", { name = command.name,
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
53 node = node, jid = module:get_host() });
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
54 reply:up();
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 end
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 end
5761
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
57 event.exists = true;
91f8cd53584c mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents: 5760
diff changeset
58 end);
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
60 module:hook("iq-set/host/"..xmlns_cmd..":command", function (event)
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 local origin, stanza = event.origin, event.stanza;
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
62 local node = stanza.tags[1].attr.node
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
63 local command = commands[node];
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
64 if command then
13097
6771acb8e857 mod_adhoc: Silence permission errors when listing commands
Kim Alvefur <zash@zash.se>
parents: 13020
diff changeset
65 if not check_permissions(event, node, command, true) then
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
66 origin.send(st.error_reply(stanza, "auth", "forbidden", "You don't have permission to execute this command"):up()
12642
9061f9621330 Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents: 12430
diff changeset
67 :add_child(command:cmdtag("canceled")
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
68 :tag("note", {type="error"}):text("You don't have permission to execute this command")));
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
69 return true
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 end
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
71 -- User has permission now execute the command
12430
0c1684c65716 mod_adhoc: Simplify variable references
Kim Alvefur <zash@zash.se>
parents: 12387
diff changeset
72 adhoc_handle_cmd(command, origin, stanza);
9222
fe8abac62682 mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 8563
diff changeset
73 return true;
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 end
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end, 500);
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76
4450
15547fba1f09 mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents: 4291
diff changeset
77 local function adhoc_added(event)
15547fba1f09 mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents: 4291
diff changeset
78 local item = event.item;
12387
05c250fa335a Spelling: Fix various spelling mistakes (thanks timeless)
Kim Alvefur <zash@zash.se>
parents: 11209
diff changeset
79 -- Dang this was noisy
11209
f6661fac7e9a mod_adhoc: Log commands provided at debug level
Kim Alvefur <zash@zash.se>
parents: 10565
diff changeset
80 module:log("debug", "Command added by mod_%s: %q, %q", item._provided_by or "<unknown module>", item.name, item.node);
3231
ad3fbed1dda5 mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents: 3220
diff changeset
81 commands[item.node] = item;
ad3fbed1dda5 mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents: 3220
diff changeset
82 end
ad3fbed1dda5 mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents: 3220
diff changeset
83
4450
15547fba1f09 mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents: 4291
diff changeset
84 local function adhoc_removed(event)
3220
b3772f9bc359 mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 commands[event.item.node] = nil;
4450
15547fba1f09 mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents: 4291
diff changeset
86 end
3231
ad3fbed1dda5 mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents: 3220
diff changeset
87
9571
5c475f6e89a4 mod_adhoc: Add compat marker for older handling of adhoc items
Kim Alvefur <zash@zash.se>
parents: 9331
diff changeset
88 module:handle_items("adhoc", adhoc_added, adhoc_removed); -- COMPAT pre module:provides() introduced in 0.9
4926
58714123f600 mod_adhoc, mod_admin_adhoc, mod_announce: Use module:provides() to manage Ad-Hoc commands
Florian Zeitz <florob@babelmonkeys.de>
parents: 4450
diff changeset
89 module:handle_items("adhoc-provider", adhoc_added, adhoc_removed);