fix: accessing a protected web-page caused an endless loop, and accessing a protected file didn't use login dialog but http basic authentication
Massimo Melina committed
Jun 7, 2024 at 09:45 UTC
6361b3a2cf40ba4d18d221234b5dbd3b7fb5af76
3 files changed
+15
-13
src/api.get_file_list.ts
+3
-2
@@ -25,8 +25,9 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, search
25
admin &&= ctxAdminAccess(ctx) // validate 'admin' flag
26
if (dirTraversal(search))
27
return fail(HTTP_FOOL)
28
- if (await hasDefaultFile(node) || !await nodeIsDirectory(node))
29
- return fail(HTTP_METHOD_NOT_ALLOWED)
28
+ if (await hasDefaultFile(node) || !await nodeIsDirectory(node)) // in case of files without permission, we are provided with the frontend, and the location is the file itself
29
+ // so we first check if you have a permission problem, to tell frontend to show login, otherwise we fallback to method_not_allowed, as it's proper for files.
30
+ return fail(statusCodeForMissingPerm(node, 'can_read', ctx) ? undefined : HTTP_METHOD_NOT_ALLOWED)
31
if (!admin && statusCodeForMissingPerm(node, 'can_list', ctx))
32
return fail()
33
offset = Number(offset)
src/basicWeb.ts
+9
-8
@@ -28,7 +28,7 @@ export function basicWeb(ctx: Koa.Context, node: VfsNode) {
28
return true
29
}
30
const forced = get === 'basic'
31
- if (forced || detectBasicAgent()) {
31
+ if (forced || detectBasicAgent(ctx)) {
32
ctx.type = 'html'
33
const force = forced ? '?get=basic' : ''
34
const walker = walkNode(node, { ctx, depth: 0 })
@@ -53,11 +53,12 @@ export function basicWeb(ctx: Koa.Context, node: VfsNode) {
53
return `<a href='${href}'>${label}</a>`
54
}
55
56
- function detectBasicAgent() {
57
- const ua = ctx.get('user-agent')
58
- const v = autoBasic.get()
59
- return v && (/Mozilla\/4|WebKit\/([234]\d\d|5[012]\d|53[0123456])[. ]|Trident|Lynx|Firefox\/(\d|[123]\d)\./.test(ua)
60
- || _.isString(v) && ua.includes(v))
61
- }
56
+}
57
+
58
+export function detectBasicAgent(ctx: Koa.Context) {
59
+ const ua = ctx.get('user-agent')
60
+ const v = autoBasic.get()
61
+ return v && (/Mozilla\/4|WebKit\/([234]\d\d|5[012]\d|53[0123456])[. ]|Trident|Lynx|curl|Firefox\/(\d|[123]\d)\./.test(ua)
62
+ || _.isString(v) && ua.includes(v))
63
+}
64
63
-}
\ No newline at end of file
src/serveGuiAndSharedFiles.ts
+3
-3
@@ -16,7 +16,7 @@ import { serveGuiFiles } from './serveGuiFiles'
16
import mount from 'koa-mount'
17
import { baseUrl } from './listen'
18
import { asyncGeneratorToReadable, deleteNode, filterMapGenerator, pathEncode } from './misc'
19
-import { basicWeb } from './basicWeb'
19
+import { basicWeb, detectBasicAgent } from './basicWeb'
20
21
const serveFrontendFiles = serveGuiFiles(process.env.FRONTEND_PROXY, FRONTEND_URI)
22
const serveFrontendPrefixed = mount(FRONTEND_URI.slice(0,-1), serveFrontendFiles)
@@ -104,8 +104,8 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
104
: !node.source ? sendErrorPage(ctx, HTTP_METHOD_NOT_ALLOWED) // !dir && !source is not supported at this moment
105
: !statusCodeForMissingPerm(node, 'can_read', ctx) ? serveFileNode(ctx, node) // all good
106
: ctx.status !== HTTP_UNAUTHORIZED ? null // all errors don't need extra handling, except unauthorized
107
- : path.endsWith('/') ? (ctx.state.serveApp = true) && serveFrontendFiles(ctx, next) // since this is no dir, final / means we are dealing with default file, for which we still provide fancy login
108
- : (ctx.set('WWW-Authenticate', 'Basic'), sendErrorPage(ctx)) // this is necessary to support standard urls with credentials
107
+ : detectBasicAgent(ctx) ? (ctx.set('WWW-Authenticate', 'Basic'), sendErrorPage(ctx))
108
+ : (ctx.state.serveApp = true) && serveFrontendFiles(ctx, next) // this is necessary to support standard urls with credentials, as chrome125 will send provided credentials only after attempt a GET without them, and after this error
109
if (!path.endsWith('/'))
110
return ctx.redirect(ctx.state.revProxyPath + ctx.originalUrl.replace(/(\?|$)/, '/$1')) // keep query-string, if any
111
if (statusCodeForMissingPerm(node, 'can_list', ctx)) {