comparison mod_pubsub_post/mod_pubsub_post.lua @ 3503:882180b459a0

mod_pubsub_post: Restructure authentication and authorization (BC) This deprecates the default "superuser" actor model and makes the default equivalent to the previous "request.id". A single actor and secret per node is supported because HTTP and WebHooks don't normally include any authorization identity. Allowing authentication bypass when no secret is given should be relatively safe when the actor is unprivileged, as will be unless explicitly configured otherwise.
author Kim Alvefur <zash@zash.se>
date Sat, 30 Mar 2019 21:16:13 +0100
parents 1df139b157fb
children 9ef5b229f73e
comparison
equal deleted inserted replaced
3502:42e9e3c5eb02 3503:882180b459a0
73 else 73 else
74 return publish_payload(node, actor, "current", xmlpayload); 74 return publish_payload(node, actor, "current", xmlpayload);
75 end 75 end
76 end 76 end
77 77
78 local actor_source = module:get_option_string("pubsub_post_actor", "superuser"); 78 local actor_source = module:get_option_string("pubsub_post_actor"); -- COMPAT
79 local actor_secret = module:get_option_string("pubsub_post_secret"); 79 local default_secret = module:get_option_string("pubsub_post_default_secret");
80 local actor_secrets = module:get_option("pubsub_post_secrets"); 80 local actor_secrets = module:get_option("pubsub_post_secrets");
81 local actors = module:get_option("pubsub_post_actors");
82 local default_actor = module:get_option_string("pubsub_post_default_actor");
83 if not default_actor and actor_source == "superuser" then
84 default_actor = true;
85 end
81 86
82 local function verify_signature(secret, body, signature) 87 local function verify_signature(secret, body, signature)
83 if not signature then return false; end 88 if not signature then return false; end
84 local algo, digest = signature:match("^([^=]+)=(%x+)"); 89 local algo, digest = signature:match("^([^=]+)=(%x+)");
85 if not algo then return false; end 90 if not algo then return false; end
91 function handle_POST(event, path) 96 function handle_POST(event, path)
92 local request = event.request; 97 local request = event.request;
93 module:log("debug", "Handling POST: \n%s\n", tostring(request.body)); 98 module:log("debug", "Handling POST: \n%s\n", tostring(request.body));
94 99
95 local content_type = request.headers.content_type or "application/octet-stream"; 100 local content_type = request.headers.content_type or "application/octet-stream";
96 local actor; 101 local actor = actors and actors[path] or default_actor or request.ip;
102 local secret = actor_secrets and actor_secrets[path] or default_secret;
97 103
98 local secret = actor_secrets and actor_secrets[path] or actor_secret;
99 if secret and not verify_signature(secret, request.body, request.headers.x_hub_signature) then 104 if secret and not verify_signature(secret, request.body, request.headers.x_hub_signature) then
100 return 401; 105 return 401;
101 end
102
103 if actor_source == "request.ip" then
104 actor = request.ip or request.conn:ip();
105 elseif actor_source == "superuser" then
106 actor = true;
107 else
108 module:log("error", "pubsub_post_actor set to unsupported value %q", actor_source);
109 return 500;
110 end 106 end
111 107
112 if not actor then 108 if not actor then
113 return 401; 109 return 401;
114 end 110 end