Repository navigation
Conversation
|
A ZIP file with standard source tarball and another tarball with pre-built docs for commit 6a204c6 is temporarily available: NUT-tarballs-PR-3797.zip. |
upsmon parses the legacy global CERTPATH, CERTFILE, CERTIDENT, CERTVERIFY and FORCESSL keywords from upsmon.conf into the entry which it gets with upscli_get_authconf_item(NULL, NULL, NULL, 1). Two issues lost those settings, so e.g. the CA from CERTPATH was never loaded and FORCESSL/CERTVERIFY were ignored: * With all-NULL arguments and an empty list, that call did not create the global section: it created a "@localhost:3493" item (which upsmon then renamed to a NULL section), not known as global defaults, so the items later made for the monitored hosts did not inherit from it. Now such a call creates (and adds) the global section, as documented for all-NULL arguments. * Without an AUTHCONF line, upsmon then calls the best-effort upscli_read_authconf_file(NULL, 0, 1), which freed the current list before looking for a file. With no nutauth.conf on the system, the settings were discarded (and upsmon kept a pointer to the freed entry). Now the list is freed only once a file was found to be read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ju3WEqpswgy9dN7EQB3Fjn Signed-off-by: nmbro <nmbro@users.noreply.github.com>
The OpenSSL client documents CERTPATH as either a directory of (hashed) CA certificates or a PEM file with a collection of CA certificates, and upscli_get_or_create_ssl_context() tried SSL_CTX_load_verify_locations() with CERTPATH as a directory (CApath) first, then as a file (CAfile). But loading a CApath succeeds for any string, as OpenSSL only looks up the directory later, during verification. So a CERTPATH file was never loaded, and verification of any server certificate failed (e.g. with "certificate verify failed", verify error num=19) even with the right CA in that file. Try CERTPATH as a file first, then as a directory, so both forms work; the NSS code path is not changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ju3WEqpswgy9dN7EQB3Fjn Signed-off-by: nmbro <nmbro@users.noreply.github.com>
45182c1 to
ad3924f
Compare
…kupstools#3797] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ju3WEqpswgy9dN7EQB3Fjn Signed-off-by: nmbro <nmbro@users.noreply.github.com>
|
Good points, sorry for overlooking that - in #3607 I suppose. Luckily this regression (as well as whole Regarding the question of which side wins (
Any improvements to this logic, such as not-removing the existing list made from legacy keywords and merging whatever is explicitly spelled in a While at it, can you/Claude please double-check (second set of eyes is always better):
|
|
In fact, I think in that follow-up PR it may make sense to extend Then the This may avalanche into changes across the ecosystem however (similar in C++/Perl/Python/Java bindings, maybe update the API consumer in WmNUT for new method parameter, API man pages...) |
|
Thanks! I double-checked against the code:
Edit: corrected the "Ordering" point. I first suggested documenting that the file replaces the legacy settings, but the existing docs describe a merge, so the code is what needs fixing. This reply was drafted with Claude Code (Opus 5.5) and reviewed by me. |
upsmon keeps a pointer to the global authconf section, which the legacy CERTPATH, CERTFILE, CERTIDENT, CERTVERIFY and FORCESSL keywords in upsmon.conf populate. If a nutauth.conf file is then read (named by AUTHCONF or found in a default location), upscli_read_authconf_file() replaces the whole list and that pointer is left dangling, so on a reload (SIGHUP or "upsmon -c reload") such keywords wrote into freed memory (AddressSanitizer reports a heap-use-after-free in parse_conf_arg()). Fetch the default entry again after reading the file (creating it if the file had no global section). This does not yet merge the file into the settings from upsmon.conf as UPGRADING.adoc and upsmon.conf(5) describe; that is left for a separate change. Also clarify in authconf.h that an explicitly named file always replaces the list; only the search for a default file keeps it when nothing is found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ju3WEqpswgy9dN7EQB3Fjn Signed-off-by: nmbro <nmbro@users.noreply.github.com>
|
✅ Build nut 2.8.5.5906-master completed (commit ea7f04b3b4 by @nmbro)
|
Two client-side TLS bugs, found while testing
upsmonwith SSL on Windows (both are platform-independent and reproduce on Linux with current master).Problem
upsmonignored the globalCERTPATH,CERTFILE,CERTIDENT,CERTVERIFYandFORCESSLfromupsmon.confwhen there is noAUTHCONFline and nonutauth.confon the system. So the CA was never loaded andFORCESSL/CERTVERIFYhad no effect. Two causes inclients/authconf.c:upsmonkeeps these settings in the entry it gets withupscli_get_authconf_item(NULL, NULL, NULL, 1). With an empty list, that call did not create the global section but a@localhost:3493item (renamed byupsmonto a NULL section), which is not known as global defaults. So the items created later for the monitored hosts did not inherit from it.upsmonthen calls the best-effortupscli_read_authconf_file(NULL, 0, 1), which freed the whole list before looking for a file. With nonutauth.conf, the parsed settings were discarded (andupsmonkept a pointer to the freed entry).CERTPATHnaming a PEM file (OpenSSL) was never loaded, althoughupsmon.conf(5)documents that form (e.g.CERTPATH /etc/ssl/certs/ca-certificates.crt).upscli_get_or_create_ssl_context()triedSSL_CTX_load_verify_locations()withCERTPATHas a directory first and as a file only if that failed. But loading a directory (CApath) succeeds for any string, because OpenSSL only looks into it during verification, so the file was never tried, and verification failed even with the right CA in the file.Changes
clients/authconf.c: keep upsmon.conf CERT* defaultsupscli_get_authconf_item(): with all-NULL arguments,add_to_listset and no global section yet, create (and add) the global section, as the header documents for all-NULL arguments. Host items made later are cloned from it, as the code already does for global defaults read from a file.upscli_read_authconf_file(): free the current list only once a file was found to be read; if none is found, the list is kept.clients/upsclient.c: load a CERTPATH file as a CA bundleCERTPATHas a file (CAfile) first, then as a directory (CApath). A CAfile load of a directory fails cleanly, so directories work as before. This also avoidsstat()(which e.g. rejects a trailing slash on Windows). The NSS code path is not changed.clients/upsmon.c: re-fetch default authconf entrynutauth.conffile,upsmonfetches its default (global) entry again, creating it if the file had no global section. Before, its pointer to that entry was left dangling once a file replaced the list, so a reload withCERT*keywords inupsmon.confwrote into freed memory.authconf.h: clarify that an explicitly named file always replaces the list.Not changed here: reading a
nutauth.conffile still replaces the list, so theupsmon.confglobals andCERTHOSTentries are dropped.UPGRADING.adocandupsmon.conf(5)describe a merge instead (legacy keywords as the global defaults, the file loaded on top), so the code is what needs fixing. As discussed below, that goes into a follow-up with a mode option forupscli_read_authconf_file().Testing
upsmon -DDDDDwith aupsmon.confholding onlyMONITOR,CERTPATH,CERTVERIFY 1andFORCESSL 1(noAUTHCONF, nonutauth.conf), on Windows builds under Wine (i686 and x86_64 MSVCRT, x86_64 UCRT):Collected AUTHCONF entries:dump is empty, and the entry for the monitored host is created empty;CERTPATH,CERTVERIFY = 1,FORCESSL = 1, and the host entry is cloned from these global defaults.upsc -A nutauth.conf(CERTVERIFY = 1,FORCESSL = 1) against a minimal TLS test server (answersSTARTTLS, then TLS with a certificate signed by a test CA), withCERTPATHset to the right or a wrong CA, as a PEM file or as a hashed directory:Both Linux builds use
--with-openssl --enable-Werror. The first commit was also tested end to end on Windows test VMs with a realupsd(directoryCERTPATH: right CA verifies, wrong CA refused). Not tested with NSS builds (that code path is unchanged).The third commit was tested on Linux (Debian,
--with-openssl --enable-Werror, AddressSanitizer):upsmon -F -DDDDDDwithCERTPATH,CERTVERIFY 1andFORCESSL 1inupsmon.confand anutauth.conffound in the config directory, thenupsmon -c reload. Before: ASan reports a heap-use-after-free inparse_conf_arg()(fromreload_conf()). After: the reload completes with no ASan report.Checklist
Co-Authored-Bytrailerupsdebugx()/upslogx()NEWS.adocbullet (NUT client libraries section)🤖 Generated with Claude Code
https://claude.ai/code/session_01Ju3WEqpswgy9dN7EQB3Fjn