|
@@ -5,17 +5,13 @@ local basexx = require "basexx";
|
5
|
5
|
local have_async, async = pcall(require, "util.async");
|
6
|
6
|
local hex = require "util.hex";
|
7
|
7
|
local jwt = require "luajwtjitsi";
|
8
|
|
-local http = require "net.http";
|
9
|
8
|
local jid = require "util.jid";
|
10
|
9
|
local json_safe = require "cjson.safe";
|
11
|
10
|
local path = require "util.paths";
|
12
|
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
|
16
|
-- TODO: Figure out a less arbitrary default cache size.
|
21
|
17
|
local cacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
|
|
@@ -131,65 +127,18 @@ function Util:get_public_key(keyId)
|
131
|
127
|
if content == nil then
|
132
|
128
|
-- If the key is not found in the cache.
|
133
|
129
|
module:log("debug", "Cache miss for key: "..keyId);
|
134
|
|
- local code;
|
135
|
|
- local timeout_occurred;
|
136
|
|
- local wait, done = async.waiter();
|
137
|
|
-
|
138
|
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
|
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
|
135
|
end
|
|
136
|
+ return content;
|
186
|
137
|
else
|
187
|
138
|
-- If the key is in the cache, use it.
|
188
|
139
|
module:log("debug", "Cache hit for key: "..keyId);
|
189
|
140
|
return content;
|
190
|
141
|
end
|
191
|
|
-
|
192
|
|
- return nil;
|
193
|
142
|
end
|
194
|
143
|
|
195
|
144
|
--- Verifies issuer part of token
|
|
@@ -301,7 +250,10 @@ function Util:process_and_verify_token(session, acceptedIssuers)
|
301
|
250
|
end
|
302
|
251
|
|
303
|
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
|
257
|
local dotFirst = session.auth_token:find("%.");
|
306
|
258
|
if not dotFirst then return nil, "Invalid token" end
|
307
|
259
|
local header, err = json_safe.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));
|