@@ -40,6 +40,10 @@ local function prequire(prefix, package, default)
40
40
end
41
41
42
42
local function setcookie (session , value , expires )
43
+ if session .basic then
44
+ return true
45
+ end
46
+
43
47
if ngx .headers_sent then return nil , " Attempt to set session cookie after sending out response headers." end
44
48
local c = session .cookie
45
49
local i = 3
@@ -130,6 +134,23 @@ local function setcookie(session, value, expires)
130
134
return true
131
135
end
132
136
137
+ local function isEmpty (s )
138
+ return s == nil or s == ' '
139
+ end
140
+
141
+ local function getbasic (session )
142
+ -- extract the session credentials from basic authorization header
143
+ local user , pass = var .remote_user , var .remote_passwd
144
+ if isEmpty (user ) or isEmpty (pass ) then
145
+ return
146
+ end
147
+
148
+ ngx .log (ngx .DEBUG , " basic credentials, user: " , user , " password: " , pass )
149
+ ngx .log (ngx .DEBUG , " session.cookie.lifetime = " , session .cookie .lifetime )
150
+
151
+ return session .encoder .encode (user ) .. " |" .. time () + session .cookie .lifetime .. " |" .. (session .raw_hmac == true and session .encoder .encode (pass ) or pass )
152
+ end
153
+
133
154
local function getcookie (session , i )
134
155
local name = session .name
135
156
local n = { " cookie_" , name }
@@ -151,21 +172,43 @@ local function save(session, close)
151
172
session .expires = time () + session .cookie .lifetime
152
173
local i , e , s = session .id , session .expires , session .storage
153
174
local k = hmac (session .secret , i )
175
+ if not session .data .hmacsalt then
176
+ session .data .hmacsalt = ngx .encode_base64 (require (' resty.session.identifiers.random' )({}))
177
+ end
178
+ ngx .log (ngx .DEBUG , " session.data.hmacsalt = " , session .data .hmacsalt )
154
179
local d = session .serializer .serialize (session .data )
155
180
local dkey
156
181
if session .data .id_token ~= nil and session .data .id_token .sub ~= nil and session .data .id_token .sub ~= " " then
157
182
ngx .log (ngx .DEBUG , " using session.data.id_token.sub in place of d in hmac: " , session .data .id_token .sub )
158
183
dkey = session .data .id_token .sub
159
184
end
160
- local h = hmac (k , concat { i , e , dkey or d , session .key })
161
- local cookie , err = s :save (i , e , session .cipher :encrypt (d , k , i , session .key ), h , close )
185
+ local h = hmac (session .data .hmacsalt .. k , concat { i , dkey or d , session .key })
186
+ session .hmac = h
187
+ local cryptkey
188
+ if session .check .hmac == false and session .basic then
189
+ cryptkey = hmac (k , ngx .var .remote_passwd )
190
+ else
191
+ cryptkey = hmac (k , h )
192
+ end
193
+ local d = session .cipher :encrypt (d , cryptkey , i , session .key )
194
+ ngx .log (ngx .DEBUG , " i = " , ngx .encode_base64 (i ))
195
+ ngx .log (ngx .DEBUG , " e = " , e , " session.cookie.lifetime = " , session .cookie .lifetime )
196
+ ngx .log (ngx .DEBUG , " d = " , ngx .encode_base64 (d ))
197
+ ngx .log (ngx .DEBUG , " h = " , ngx .encode_base64 (h ))
198
+ ngx .log (ngx .DEBUG , " k = " , ngx .encode_base64 (k ))
199
+ ngx .log (ngx .DEBUG , " cryptkey = " .. ngx .encode_base64 (cryptkey ))
200
+ local cookie , err = s :save (i , e , d , h , close )
162
201
if cookie then
163
202
return setcookie (session , cookie )
164
203
end
165
204
return nil , err
166
205
end
167
206
168
207
local function regenerate (session , flush )
208
+ if session .basic then
209
+ return true
210
+ end
211
+
169
212
local i = session .present and session .id
170
213
session .id = session :identifier ()
171
214
if flush then
@@ -183,7 +226,7 @@ local function init()
183
226
defaults = {
184
227
name = var .session_name or " session" ,
185
228
identifier = var .session_identifier or " random" ,
186
- storage = var .session_storage or " cookie " ,
229
+ storage = var .session_storage or " redis " ,
187
230
serializer = var .session_serializer or " json" ,
188
231
encoder = var .session_encoder or " base64" ,
189
232
cipher = var .session_cipher or " aes" ,
@@ -201,7 +244,8 @@ local function init()
201
244
ssi = enabled (var .session_check_ssi or false ),
202
245
ua = enabled (var .session_check_ua or true ),
203
246
scheme = enabled (var .session_check_scheme or true ),
204
- addr = enabled (var .session_check_addr or false )
247
+ addr = enabled (var .session_check_addr or false ),
248
+ hmac = enabled (var .session_check_hmac or true )
205
249
}
206
250
}
207
251
defaults .secret = var .session_secret or secret
@@ -228,8 +272,10 @@ function session.new(opts)
228
272
local g , h = prequire (" resty.session.serializers." , y .serializer or z .serializer , " json" )
229
273
local i , j = prequire (" resty.session.encoders." , y .encoder or z .encoder , " base64" )
230
274
local k , l = prequire (" resty.session.ciphers." , y .cipher or z .cipher , " aes" )
231
- local m , n = prequire (" resty.session.storage." , y .storage or z .storage , " cookie " )
275
+ local m , n = prequire (" resty.session.storage." , y .storage or z .storage , " redis " )
232
276
local self = {
277
+ basic = ifnil (y .basic , false ),
278
+ raw_hmac = ifnil (y .raw_hmac , false ),
233
279
name = y .name or z .name ,
234
280
identifier = e ,
235
281
serializer = g ,
@@ -250,14 +296,16 @@ function session.new(opts)
250
296
ssi = ifnil (c .ssi , d .ssi ),
251
297
ua = ifnil (c .ua , d .ua ),
252
298
scheme = ifnil (c .scheme , d .scheme ),
253
- addr = ifnil (c .addr , d .addr )
299
+ addr = ifnil (c .addr , d .addr ),
300
+ hmac = ifnil (c .hmac , d .hmac )
254
301
}
255
302
}
256
303
if y [f ] and not self [f ] then self [f ] = y [f ] end
257
304
if y [h ] and not self [h ] then self [h ] = y [h ] end
258
305
if y [j ] and not self [j ] then self [j ] = y [j ] end
259
306
if y [l ] and not self [l ] then self [l ] = y [l ] end
260
307
if y [n ] and not self [n ] then self [n ] = y [n ] end
308
+ self .ciphertype = l
261
309
self .cipher = k .new (self )
262
310
self .storage = m .new (self )
263
311
return setmetatable (self , session )
@@ -309,19 +357,31 @@ function session.open(opts)
309
357
scheme
310
358
}
311
359
self .opened = true
312
- local cookie = getcookie (self )
360
+ -- require aes storage cipher when self.check.hmac is false (otherwise there is nothing left to validate the session)
361
+ if self .check .hmac == false and self .ciphertype ~= " aes" then
362
+ ngx .log (ngx .ERR , " aes cipher required when check.hmac is disabled, the cipher is: " , self .ciphertype )
363
+ return self , false
364
+ end
365
+ local cookie
366
+ if self .basic then
367
+ cookie = getbasic (self )
368
+ else
369
+ cookie = getcookie (self )
370
+ end
313
371
if cookie then
314
372
ngx .log (ngx .DEBUG , " cookie present: " , cookie )
315
373
local i , e , d , h = self .storage :open (cookie , self .cookie .lifetime )
316
- if i and e and e > time ( ) and d and h then
374
+ if i and tonumber ( e ) and d and h then
317
375
ngx .log (ngx .DEBUG , " cookie session data retrieved" )
318
376
ngx .log (ngx .DEBUG , " i: " .. ngx .encode_base64 (i ))
319
377
ngx .log (ngx .DEBUG , " e: " .. e .. " (time: " .. time () .. " )" )
320
378
ngx .log (ngx .DEBUG , " d: " .. ngx .encode_base64 (d ))
321
379
ngx .log (ngx .DEBUG , " h: " .. ngx .encode_base64 (h ))
322
380
local k = hmac (self .secret , i )
323
381
ngx .log (ngx .DEBUG , " k: " .. ngx .encode_base64 (k ))
324
- d = self .cipher :decrypt (d , k , i , self .key )
382
+ local cryptkey = hmac (k , h )
383
+ ngx .log (ngx .DEBUG , " cryptkey: " .. ngx .encode_base64 (cryptkey ))
384
+ d = self .cipher :decrypt (d , cryptkey , i , self .key )
325
385
local dkey , ds = nil , d
326
386
if d then
327
387
ngx .log (ngx .DEBUG , " d decrypted: " .. d )
@@ -330,13 +390,18 @@ function session.open(opts)
330
390
ngx .log (ngx .DEBUG , " using d.id_token.sub in place of d in hmac: " , d .id_token .sub )
331
391
dkey = d .id_token .sub
332
392
end
393
+ ngx .log (ngx .DEBUG , " d.hmacsalt: " , d .hmacsalt )
394
+ else
395
+ ngx .log (ngx .DEBUG , " decryption failed" )
333
396
end
334
- if ds and hmac ( k , concat { i , e , dkey or ds , self .key }) == h then
397
+ if ds and ( self . check . hmac == false or hmac ( d . hmacsalt .. k , concat { i , dkey or ds , self .key }) == h ) then
335
398
self .id = i
336
399
self .expires = e
337
400
self .data = type (d ) == " table" and d or {}
338
401
self .present = true
339
402
return self , true
403
+ elseif d then
404
+ ngx .log (ngx .DEBUG , " hmac validation failed" )
340
405
end
341
406
end
342
407
end
@@ -394,6 +459,10 @@ function session:destroy()
394
459
end
395
460
396
461
function session :hide ()
462
+ if session .basic then
463
+ return true
464
+ end
465
+
397
466
local cookies = var .http_cookie
398
467
if not cookies then
399
468
return
0 commit comments