Commit Graph
95 Commits
Author SHA1 Message Date
Isaac ConnorandClaude Opus 5.5 a41eac5d95 fix: do not apply migrations newer than the installed ZoneMinder
zmupdate.pl applied every zm_update-*.sql at or above the database's
version, with no upper bound. Migration files from a newer release left
in the update directory, after a downgrade or with a newer build's files
installed over an older one, were applied to a schema they were not
written for. Installing a 1.38 build over a 1.39 one ran the 1.39.0 to
1.39.5 migrations against the 1.38 database before one failed.

Skip, and say so, any migration newer than ZM_VERSION.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 18:34:50 -04:00
Isaac ConnorandClaude Opus 5 24b4b389cd fix: record the patch's own version in ZM_DYN_DB_VERSION
The patch loop writes ZM_DYN_DB_VERSION after each file so that a run
that dies partway leaves a record of how far it got. It wrote $version,
the version the database started at, which the loop never changes, so
the write was a no-op: a failed upgrade left the original version in
place and the rerun started again from the beginning, re-running every
patch that had already applied.

Write $v, the version of the patch that was just applied. A run that
completes still ends up at ZM_VERSION from the cascade write below.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLYswrguKc6bBYL8JZbpmZ
2026-10-05 17:57:06 -04:00
nicandClaude Opus 5.5 ad3d5ec54d fix: random per-user salts in zmupdate.pl password migration, rehash migrated passwords on every login (#5167)
* fix: give each migrated password its own random bcrypt salt

migratePasswords() stored the Bytes::Random::Secure object rather than
bytes from it, so en_base64() encoded the string
"Bytes::Random::Secure=HASH(0x...)". bcrypt only reads the first 22
characters of the salt, all from the constant class name, so every user
on every install got the same salt. With neither Bytes::Random::Secure
nor Data::Entropy installed the salt was empty and bcrypt() died with
"bad bcrypt settings", aborting zmupdate.pl. Even the Data::Entropy path
reused a single salt for every user in the run.

Read 16 bytes per user from /dev/urandom, as generateAuthHashSecret()
in ZoneMinder::Config already does. If it can't be read, leave that
user's legacy hash in place, which auth.php still verifies, instead of
writing a weak one. This drops the need for Bytes::Random::Secure and
the deprecated Data::Entropy. refs #4333

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: drop the Data::Entropy dependency from packaging

zmupdate.pl no longer uses Data::Entropy, which upstream has deprecated
(CVE-2025-1860). refs #4333

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: rehash legacy passwords on every password login

Only the login form called migrateHash(), so accounts that sign in with
user=/pass= or through the API kept their mysql or zmupdate.pl
(mysql+bcrypt) hash, including those with the fixed salt. Call it from
those paths too, and have it check the password type itself.

migrateHash() also regenerated the auth hash from the in-memory user,
which still held the old password, so getAuthUser(), which checks
against the new one in the database, rejected it. Update the in-memory
password first, and update the row by Id rather than by the username
as typed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: note passwords still on a zmupdate.pl-migrated hash

Every salt migratePasswords() used before this branch was shared by all
users in a run: from Data::Entropy, which before 0.008 keys its generator
from rand() (CVE-2025-1860), or, since 38c0f743 with Bytes::Random::Secure
installed, a constant. The original hash input is gone, so zmupdate.pl
can't rehash these, and nothing distinguishes them from properly salted
ones. Log a warning listing every user still on a -ZM- hash, noting that
it is upgraded at their next login or password reset, and that unused
accounts can be disabled or deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:30:43 -04:00
Steve GilvarryandClaude Opus 5 ba49bbb33c fix: make the Perl scripts' taint-safe PATH configurable
The scripts run under -T, so they cannot trust the caller's PATH and set
their own. Sixteen of them hardcoded /bin:/usr/bin:/usr/local/bin, which
assumes everything they shell out to lives under /usr or /usr/local.

ZoneMinder::General::findDbCommand looks for a database client on that
PATH, and zmupdate.pl and zmcamtool.pl run what it finds. So an install
whose client sits anywhere else cannot apply schema changes:

  sh: mysql: command not found
  Command 'mysql -u'zmuser' ... ' exited with status: 127

even with the client on the caller's PATH. Homebrew on Apple Silicon is
the case that surfaced it - the client is in /opt/homebrew/bin - but a
--prefix=/opt install on Linux has the same shape, as does anything that
keeps its database client outside the FHS locations.

Replaced the literal with @ZM_SCRIPT_PATH@, defaulting to the same three
directories plus wherever cmake actually found a client, and overridable
for packagers who want to pin it. Warn at configure time when no client
is found at all, since that failure otherwise appears much later and
says something unrelated.

Nothing changes for an install whose client is already under /usr/bin:
the directory is only appended when it is not in the list, so the
default stays exactly as it was.

Memory.pm is deliberately left alone. It has a narrower PATH of
/bin:/usr/bin, and the only command it runs is uname through an absolute
path from ZM_PATH_UNAME, so it does not need widening.

Verified on macOS across the three cases: with the client in
/opt/homebrew/bin the directory is appended; -DZM_SCRIPT_PATH= is
respected verbatim; and pointing detection at /usr/bin/mariadb leaves
the default untouched. Build clean, suite 146 cases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B5KL9Xbi7K5aGsauLtd8tG
2026-09-13 13:04:59 +10:00
Isaac ConnorandClaude Opus 5 f796053c2a fix: reconnect to db instead of bare ping in zmupdate and zmfilter loops
Both loops called $dbh->ping() and discarded the result. ping() only tests
the connection; DBD::mysql does not reconnect on its own since
mysql_auto_reconnect is off. zmupdate's update-check loop sleeps 3600s
between iterations, so on a server with wait_timeout below an hour the
handle is already closed on wake-up and the following zmDbDo fails with
"The client was disconnected by the server because of inactivity".

zmDbConnect() already pings and reconnects when needed, and assigns the
package global $dbh that zmDbDo uses, so call that instead. zmupdate keeps
passing mysql_multi_statements so a reconnect matches the original handle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 10:27:36 -04:00
Nic BoetandClaude Opus 4.6 d66a3525bd feat: detect MariaDB-native command names with fallback to MySQL legacy names
MariaDB is deprecating mysql-prefixed utility names (mysqldump,
mysql) in favour of its own (mariadb-dump, mariadb). Add
findDbCommand() to ZoneMinder::General that probes for the
MariaDB-native binary first and falls back to the legacy name.
Results are cached per-process. Update the three call sites in
zmupdate.pl.in and zmcamtool.pl.in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 13:19:32 -06:00
Isaac Connor 38c0f743c1 Use Bytes::Random::Secure instead of deprecated Data-Entropy. Fall back to Data-Entropy. Fixes #4333 2025-06-02 19:44:20 -04:00
Isaac Connor 93953cef3a ALways re-apply the last update 2024-10-23 18:46:54 -04:00
Isaac Connor b4c871dc09 Always re-apply the latest update. Mainly because sometimes Isaac forgets to add the zm_update file when bumping versions, also in release branches, we increment version before release. zm_update scripts are always supposed to be re-runnable, so this is ok, if a little skeezy 2024-07-09 08:21:08 -04:00
Isaac Connor 819225bfe8 Prevent command injection in zmupdate.pl through use of --dir 2024-01-23 09:55:32 -05:00
Isaac Connor b39445d5c5 Add quotes around dbUser to prevent command injection 2024-01-02 13:59:17 -05:00
Isaac Connor 818eb5e0a3 Add a db ping to handle reconnection when zmupdate is running as a daemon. Move code around to be more efficient. 2023-10-27 11:08:22 -04:00
Isaac Connor 2a7b8a1dbb Use https proxy instead of http since we now access an https url 2023-09-23 12:28:18 -04:00
Alejandro Criado-Pérez 871bf1772f fix: messages 2023-07-05 01:03:48 +02:00
Isaac Connor 3cc243b9a8 Don't freshing config when doing update. That is it's own command 2022-01-24 09:24:16 -05:00
Isaac Connor 9b8ca69203 default interactive to whether we have stdio. So now when running from console it will default to interactive and when running from zmdc.pl will be non-interactive. Do check regardless of ZM_UPDATE_CHECK setting. 2022-01-13 12:26:47 -05:00
Isaac Connor 3ec6c7e32f Fix behaviour of update check to support interactive mode. Use zmDbDo functions to simplify code. When interactive print out lastVersion, latestVersion and currentVersion 2022-01-13 09:55:26 -05:00
Isaac Connor 3dad3a5200 update description to reflect that zmupdate.pl now does all the things it will someday do. Meantion how -c works better. When in interactive mode, check once and print out the result instead of daemonising. Fix formatting osf usage 2022-01-13 09:55:16 -05:00
Isaac Connor 91903d2822 Fix user summary, as there must be a space between -u and dbuser, etc 2021-08-05 13:30:52 -04:00
Isaac Connor c50c30c6b5 Add super command line param to use mysql --defaults-file instead of zmuser/zmpass. This will only work for debian based systems. 2021-04-28 10:03:26 -04:00
Isaac Connor 6225b8babe Indicate that there should be a space after single char options and their value 2021-04-19 11:56:59 -04:00
Isaac Connor d984c33b92 Replace old message abou ensuring that ZM is stopped with our new one, which only pauses if ZMIS running. 2020-06-09 13:36:33 -04:00
Isaac Connor 5e0f1a03c5 Detect if system is running and prompt to stop it before doing the update. 2020-06-09 13:19:19 -04:00
Isaac Connor d4488ac4e1 spacing 2020-06-09 12:18:29 -04:00
Isaac Connor 58ae7bb342 die early if db connection fails 2020-06-07 11:57:20 -04:00
Isaac Connor f71926c736 Merge branch 'release-1.34' 2020-06-05 10:09:07 -04:00
Isaac Connor 20e6a1f53d Use single quotes when escaping password so that $ has no effect. Also escape any single quotes in the password. 2020-06-04 11:37:44 -04:00
Isaac Connor f8a11633bb Handle no db_host specified, meaning local unix socket 2020-06-04 11:35:48 -04:00
Isaac Connor 6869710747 Handle no db_host specified, meaning local unix socket 2020-06-04 11:28:26 -04:00
Isaac Connor ade0d750c8 Merge branch 'master' of github.com:ZoneMinder/zoneminder 2020-06-03 15:37:32 -04:00
Isaac Connor 6f42cb22d6 Use single quotes when escaping password so that $ has no effect. Also escape any single quotes in the password. 2020-06-03 15:36:47 -04:00
Kevin Stolp 0e6ff1ad09 Detaint mysql commands in update script 2020-06-01 22:54:29 -07:00
Isaac Connor a7ef8e3dc8 detaint command before performing backup. Fixes #2945 2020-05-29 14:53:42 -04:00
Isaac Connor 67b35967d4 MOstly spaces and quotes, remove duplicated db version update and only prepare the sth once. 2020-04-23 10:39:50 -04:00
Isaac Connor bfa08c3422 MOstly spaces and quotes, remove duplicated db version update and only prepare the sth once. 2020-03-27 13:06:10 -04:00
Isaac Connor 766a59884d Don't hard code perl path. Use PERL_EXECUTABLE cmake var 2019-09-23 12:54:27 -04:00
Isaac Connor 5f5d5f691a Add backticks for mysql 8 2019-08-25 12:30:06 -04:00
Pliable Pixels 0e72080c4a Migrate from libdigest to crypt-eks-blowfish due to notice 2019-05-16 09:37:11 -04:00
Pliable Pixels e9f843f297 bulk overlay hash mysql encoded passwords 2019-05-13 14:29:24 -04:00
Pliable Pixels 87e407aa90 forgot to checkin update file 2019-05-13 10:31:09 -04:00
Isaac Connor 63982a6282 Disable PRIVACY enable 2019-03-18 14:42:05 -04:00
Isaac Connor f9139f2d98 Use the word skipped instead of aborted 2018-11-30 10:48:20 -05:00
Andrew Bauer 8f0fb0843a Add Privacy Statement (#2194)
* initial implementation of privacy popup

* split the privacy text and run it through translate

* change style of toggle button, validate the form

* fix copy/paste error

* fix typos

* display privacy view inline rather than popup

* display privacy inline if show_privacy flag set

* redirect to console after selection is made

* typo

* css formatting

* update privacy verbiage

* create and load default.php

* fix typos

* fix erroneous copy/paste
2018-08-30 13:25:02 -04:00
Isaac Connor 15a6eb7e78 Revert "Add Privacy Statement (#2176)" (#2179)
This reverts commit 56f4d768c2.
2018-08-13 15:33:43 -04:00
Andrew Bauer 56f4d768c2 Add Privacy Statement (#2176)
* initial implementation of privacy popup

* split the privacy text and run it through translate

* change style of toggle button, validate the form

* fix copy/paste error

* fix typos

* display privacy view inline rather than popup

* display privacy inline if show_privacy flag set

* redirect to console after selection is made

* typo

* css formatting

* update privacy verbiage

* push privacy text to all language files
2018-08-13 15:23:44 -04:00
Isaac Connor d63594b5fa don't do updates in a transaction so we don't hold locks 2018-01-22 14:06:52 -05:00
Isaac Connor 2682686063 Must disconnect and reconnect before calling update script 2018-01-19 16:32:26 -05:00
Isaac Connor 796ba0d899 revert to using the mysql client to do updates. We need it for delemiter changes when adding triggers 2018-01-04 17:16:43 -05:00
Isaac Connor 085d239a6e Merge branch 'master' into storageareas 2017-06-13 18:02:28 -04:00
Andrew Bauer df304b417a Update zmupdate.pl.in 2017-06-13 11:08:58 -05:00