瀏覽代碼

Merge pull request #7508 from abora8x8/abora/vpass

Add pre and post validation for users that want to use their own publ…
j8
Aaron van Meerten 4 年之前
父節點
當前提交
5d012c24a7
No account linked to committer's email address

+ 19
- 2
resources/prosody-plugins/mod_auth_token.lua 查看文件

77
 function provider.get_sasl_handler(session)
77
 function provider.get_sasl_handler(session)
78
 
78
 
79
 	local function get_username_from_token(self, message)
79
 	local function get_username_from_token(self, message)
80
-        local res, error, reason = token_util:process_and_verify_token(session);
81
 
80
 
82
-        if (res == false) then
81
+        -- retrieve custom public key from server and save it on the session
82
+        local pre_event_result = prosody.events.fire_event("pre-jitsi-authentication-fetch-key", session);
83
+        if pre_event_result ~= nil and pre_event_result.res == false then
84
+            log("warn",
85
+                "Error verifying token on pre authentication stage:%s, reason:%s", pre_event_result.error, pre_event_result.reason);
86
+            session.auth_token = nil;
87
+            return pre_event_result.res, pre_event_result.error, pre_event_result.reason;
88
+        end
89
+
90
+        local res, error, reason = token_util:process_and_verify_token(session);
91
+        if res == false then
83
             log("warn",
92
             log("warn",
84
                 "Error verifying token err:%s, reason:%s", error, reason);
93
                 "Error verifying token err:%s, reason:%s", error, reason);
85
             session.auth_token = nil;
94
             session.auth_token = nil;
102
             self.username = message;
111
             self.username = message;
103
         end
112
         end
104
 
113
 
114
+        local post_event_result = prosody.events.fire_event("post-jitsi-authentication", session);
115
+        if post_event_result ~= nil and post_event_result.res == false then
116
+            log("warn",
117
+                "Error verifying token on post authentication stage :%s, reason:%s", post_event_result.error, post_event_result.reason);
118
+            session.auth_token = nil;
119
+            return post_event_result.res, post_event_result.error, post_event_result.reason;
120
+        end
121
+
105
         return res;
122
         return res;
106
 	end
123
 	end
107
 
124
 

+ 10
- 58
resources/prosody-plugins/token/util.lib.lua 查看文件

5
 local have_async, async = pcall(require, "util.async");
5
 local have_async, async = pcall(require, "util.async");
6
 local hex = require "util.hex";
6
 local hex = require "util.hex";
7
 local jwt = require "luajwtjitsi";
7
 local jwt = require "luajwtjitsi";
8
-local http = require "net.http";
9
 local jid = require "util.jid";
8
 local jid = require "util.jid";
10
 local json_safe = require "cjson.safe";
9
 local json_safe = require "cjson.safe";
11
 local path = require "util.paths";
10
 local path = require "util.paths";
12
 local sha256 = require "util.hashes".sha256;
11
 local sha256 = require "util.hashes".sha256;
13
-local timer = require "util.timer";
12
+local http_get_with_retry = module:require "util".http_get_with_retry;
14
 
13
 
15
-local http_timeout = 30;
16
-local http_headers = {
17
-    ["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")"
18
-};
14
+local nr_retries = 3;
19
 
15
 
20
 -- TODO: Figure out a less arbitrary default cache size.
16
 -- TODO: Figure out a less arbitrary default cache size.
21
 local cacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
17
 local cacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
131
     if content == nil then
127
     if content == nil then
132
         -- If the key is not found in the cache.
128
         -- If the key is not found in the cache.
133
         module:log("debug", "Cache miss for key: "..keyId);
129
         module:log("debug", "Cache miss for key: "..keyId);
134
-        local code;
135
-        local timeout_occurred;
136
-        local wait, done = async.waiter();
137
-
138
         local keyurl = path.join(self.asapKeyServer, hex.to(sha256(keyId))..'.pem');
130
         local keyurl = path.join(self.asapKeyServer, hex.to(sha256(keyId))..'.pem');
139
-
140
-        local function cb(content_, code_, response_, request_)
141
-            if timeout_occurred == nil then
142
-                content, code = content_, code_;
143
-                if code == 200 or code == 204 then
144
-                    self.cache:set(keyId, content);
145
-                else
146
-                    module:log("warn", "Error on public key request: Code %s, Content %s",
147
-                    code_, content_);
148
-                end
149
-                done();
150
-            else
151
-                module:log("warn", "public key reply delivered after timeout from: %s",keyurl);
152
-            end
153
-        end
154
-
155
-        -- TODO: Is the done() call racey? Can we cancel this if the request
156
-        --       succeedes?
157
-        local function cancel()
158
-            -- TODO: This check is racey. Not likely to be a problem, but we should
159
-            --       still stick a mutex on content / code at some point.
160
-            if code == nil then
161
-                timeout_occurred = true;
162
-                module:log("warn", "Timeout %s seconds fetching public key from: %s",http_timeout,keyurl);
163
-                if http.destroy_request ~= nil then
164
-                    http.destroy_request(request);
165
-                end
166
-                done();
167
-            end
168
-        end
169
-
170
         module:log("debug", "Fetching public key from: "..keyurl);
131
         module:log("debug", "Fetching public key from: "..keyurl);
171
-
172
-        -- We hash the key ID to work around some legacy behavior and make
173
-        -- deployment easier. It also helps prevent directory
174
-        -- traversal attacks (although path cleaning could have done this too).
175
-        local request = http.request(keyurl, {
176
-            headers = http_headers or {},
177
-            method = "GET"
178
-        }, cb);
179
-
180
-        timer.add_task(http_timeout, cancel);
181
-        wait();
182
-
183
-        if code == 200 or code == 204 then
184
-            return content;
132
+        content = http_get_with_retry(keyurl, nr_retries);
133
+        if content ~= nil then
134
+            self.cache:set(keyId, content);
185
         end
135
         end
136
+        return content;
186
     else
137
     else
187
         -- If the key is in the cache, use it.
138
         -- If the key is in the cache, use it.
188
         module:log("debug", "Cache hit for key: "..keyId);
139
         module:log("debug", "Cache hit for key: "..keyId);
189
         return content;
140
         return content;
190
     end
141
     end
191
-
192
-    return nil;
193
 end
142
 end
194
 
143
 
195
 --- Verifies issuer part of token
144
 --- Verifies issuer part of token
301
     end
250
     end
302
 
251
 
303
     local pubKey;
252
     local pubKey;
304
-    if self.asapKeyServer and session.auth_token ~= nil then
253
+    if session.public_key then
254
+        module:log("debug","Public key was found on the session");
255
+        pubKey = session.public_key;
256
+    elseif self.asapKeyServer and session.auth_token ~= nil then
305
         local dotFirst = session.auth_token:find("%.");
257
         local dotFirst = session.auth_token:find("%.");
306
         if not dotFirst then return nil, "Invalid token" end
258
         if not dotFirst then return nil, "Invalid token" end
307
         local header, err = json_safe.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));
259
         local header, err = json_safe.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));

+ 75
- 0
resources/prosody-plugins/util.lib.lua 查看文件

1
 local jid = require "util.jid";
1
 local jid = require "util.jid";
2
+local timer = require "util.timer";
3
+local http = require "net.http";
4
+
5
+local http_timeout = 30;
2
 local have_async, async = pcall(require, "util.async");
6
 local have_async, async = pcall(require, "util.async");
7
+local http_headers = {
8
+    ["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")"
9
+};
10
+
3
 local muc_domain_prefix
11
 local muc_domain_prefix
4
     = module:get_option_string("muc_mapper_domain_prefix", "conference");
12
     = module:get_option_string("muc_mapper_domain_prefix", "conference");
5
 
13
 
208
     return false;
216
     return false;
209
 end
217
 end
210
 
218
 
219
+-- Utility function to make an http get request and
220
+-- retry @param retry number of times
221
+-- @param url endpoint to be called
222
+-- @param retry nr of retries, if retry is
223
+-- nil there will be no retries
224
+-- @returns result of the http call or nil if
225
+-- the external call failed after the last retry
226
+function http_get_with_retry(url, retry)
227
+    local content, code;
228
+    local timeout_occurred;
229
+    local wait, done = async.waiter();
230
+    local function cb(content_, code_, response_, request_)
231
+        if timeout_occurred == nil then
232
+            code = code_;
233
+            if code == 200 or code == 204 then
234
+                module:log("debug", "External call was successful, content %s", content_);
235
+                content = content_
236
+            else
237
+                module:log("warn", "Error on public key request: Code %s, Content %s",
238
+                    code_, content_);
239
+            end
240
+            done();
241
+        else
242
+            module:log("warn", "External call reply delivered after timeout from: %s", url);
243
+        end
244
+    end
245
+
246
+    local function call_http()
247
+        return http.request(url, {
248
+            headers = http_headers or {},
249
+            method = "GET"
250
+        }, cb);
251
+    end
252
+
253
+    local request = call_http();
254
+
255
+    local function cancel()
256
+        -- TODO: This check is racey. Not likely to be a problem, but we should
257
+        --       still stick a mutex on content / code at some point.
258
+        if code == nil then
259
+            timeout_occurred = true;
260
+            module:log("warn", "Timeout %s seconds making the external call to: %s", http_timeout, url);
261
+            -- no longer present in prosody 0.11, so check before calling
262
+            if http.destroy_request ~= nil then
263
+                http.destroy_request(request);
264
+            end
265
+            if retry == nil then
266
+                module:log("debug", "External call failed and retry policy is not set");
267
+                done();
268
+            elseif retry ~= nil and retry < 1 then
269
+                module:log("debug", "External call failed after retry")
270
+                done();
271
+            else
272
+                module:log("debug", "External call failed, retry nr %s", retry)
273
+                retry = retry - 1;
274
+                request = call_http()
275
+                return http_timeout;
276
+            end
277
+        end
278
+    end
279
+    timer.add_task(http_timeout, cancel);
280
+    wait();
281
+
282
+    return content;
283
+end
284
+
211
 return {
285
 return {
212
     is_feature_allowed = is_feature_allowed;
286
     is_feature_allowed = is_feature_allowed;
213
     is_healthcheck_room = is_healthcheck_room;
287
     is_healthcheck_room = is_healthcheck_room;
217
     room_jid_split_subdomain = room_jid_split_subdomain;
291
     room_jid_split_subdomain = room_jid_split_subdomain;
218
     internal_room_jid_match_rewrite = internal_room_jid_match_rewrite;
292
     internal_room_jid_match_rewrite = internal_room_jid_match_rewrite;
219
     update_presence_identity = update_presence_identity;
293
     update_presence_identity = update_presence_identity;
294
+    http_get_with_retry = http_get_with_retry;
220
 };
295
 };

Loading…
取消
儲存