https://gitlab.synchro.net/main/sbbs/-/issues/1192#note_9886
Fixed, but one claim in the report above needs correcting: the credit gate
was described as sitting past the password check, so that only authenticated sessions reached it. That is true of the control flow, but it implies the gate worked for those sessions. It did not work for anyone.
`resolve_vpath()` loaded the file record at `file_detail_index`, and `smb_getfile()` skips `smb_getmsghdr()` entirely at that detail level, while `cost` is only ever set from the `SMB_COST` header field. So `session->file.cost` was always 0, and the authenticated comparison (`download_is_free() || session->user.cdt >= session->file.cost`) reduced to `cdt >= 0`: always true.
Two consequences beyond what the report describes:
- Costed files downloaded free of charge for authenticated users as well as
anonymous ones.
- `user_downloaded_file()` still billed the account after the transfer,
because it reloads the record itself at `file_detail_normal`. A user with
fewer credits than the file cost was allowed the download and then charged
for it, so an account could go credit-negative.
Fixed in two commits:
- 72303693ef (zinc-13-these, 2026-07-31) applies the credit gate to the
unauthenticated path and puts both authorization paths on a single shared
predicate, so they cannot drift apart again. The gate now measures cost
against `user_available_credits()` rather than `user.cdt`, so free credits
count toward a download as they already do on the Terminal and FTP servers,
and as `subtract_cdt()` already assumed when charging: it spends free
credits first.
- 4de1032086 (payroll-20-queue, 2026-08-01) reads the header record, so the
cost is a real value. A free directory still loads at index detail alone,
since `loadfile()` zeroes the cost there and `download_is_free()`
short-circuits on the same `DIR_FREE` flag before any credit comparison.
Verified against a live file base, using two files in the same non-free directory with no ARS, differing only in cost:
- costed file (2,639,434 credits), unauthenticated: `401 Unauthorized`, logged
as `!Unauthenticated download denied (reason: 262)`, that being
`NotEnoughCredits`
- zero-cost file, same directory, unauthenticated: `200`, transfers in full
- file in a `DIR_FREE` directory: `200`, transfers in full
For sysops running `FileVPathPrefix`: files carrying a credit cost are no longer downloadable without authentication, which is what anonymous FTP has always done. If a published archive should stay open to the web, mark the directory's downloads free or give it an exempt ARS.
-- *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)