ZM_OPT_USE_AUTH shipped as 0, so a new install accepted every request as
the default user with System=Edit. That includes requests a browser sends
on behalf of any web page a user on the same network opens, so a server
that is never exposed to the internet could still be driven from it.
Default it to 1. zm_create.sql (generated from ConfigData) gives new
installs authentication on. Existing installs keep their value:
zmupdate.pl -f loads Value from the database and writes it back, and only
DefaultValue changes. zm_update-1.39.41.sql also sets DefaultValue to 1
for the row, so that an upgrade run without -f doesn't leave
Value = DefaultValue = 0, which the C++ config loader would skip in favour
of its compiled-in default (on) while the web UI read off.
Update the option help and the user guide (getting started, FAQ, system
options) to say authentication is on for new installs and kept on
upgrade. tests/perl/test_auth_default.pl checks the default, the stored
value and that no update script sets the row's Value; tests/zm_config.cpp
now expects the compiled-in default (opt_use_auth) to be on.
zm.conf and conf.d are set by the owner of the box; the Config table by the
ZoneMinder admin through the Options page. The owner has to be able to limit
the admin, so a file setting must win. PHP and Perl already let it.
process_configfile() kept only a fixed list of names (database credentials,
paths, server identity, stream socket) and dropped the rest, so zmc, zms and
zmu read every other option from the database alone.
So with ZM_OPT_USE_AUTH=1 in conf.d and 0 in Options, the web UI asked for a
login while nph-zms served streams and snapshots to anyone. The same split
applied to every option, ZM_AUTH_RELAY and ZM_AUTH_HASH_IPS among them.
process_configfile() now records every name = value in
StaticConfig::file_options, later files winning, and zmLoadStaticConfig()
clears it first so a reload forgets a removed line. Config::Load() applies
those values over the database ones, also when the database can't be read.
A boolean may be written yes/no, true/false or on/off as well as 1/0
(ConfigFileValue), since the Config table's 1/0 convention is not what
people type into a file. Overrides are logged by name only, as the value may
be a secret.
Tested live on 1.38: with ZM_OPT_USE_AUTH=1 in conf.d and 0 in the database,
an unauthenticated nph-zms snapshot request answered 200 with an image
before and 403 after. Without the override it still answers 200.
refs #5289
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds Catch2 coverage for the two behaviours the config redesign
introduced: ConfigItem converting each declared Type, the non-fatal
best-effort conversion when the accessor and the stored Type disagree,
and a freshly constructed Config carrying compiled-in defaults for every
member before any database read.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Y6FieTwEXuLhhR4e2yiax
The C++ and PHP parsers for zm.conf and /etc/zm/conf.d/*.conf used fgets
with a 512-byte buffer, silently truncating any line longer than that.
There was also no way to split a value across multiple lines, so editors
hit the cap with no workaround.
Accept a trailing backslash (with optional whitespace before the newline)
as a line-continuation marker. Leading whitespace on continuation lines
is stripped so users can indent for readability without it leaking into
the value. Three parsers all read the same files and must agree:
- src/zm_config.cpp: switch to std::ifstream + std::getline so a single
physical line is no longer capped at 512 bytes, then join continuation
lines before running the existing pointer-based parser
- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in: accumulate a logical
line across trailing-backslash physical lines
- web/includes/config.php.in: drop the 512-byte fgets cap and accumulate
in the same way
tests/zm_config.cpp covers three cases against the C++ parser: a
three-segment continuation joins to "firstsecondthird" with leading
whitespace stripped, a bare backslash inside a value is preserved
(C:\Users\zm), and a 1500-byte single line survives intact.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>