diff --git a/NEWS b/NEWS index 621755d7..a027b5e7 100644 --- a/NEWS +++ b/NEWS @@ -1,16 +1,42 @@ -Unreleased: +Release 1.3.23: +Billy G. - 2026-11-05 + +Upgrading: +* The spool holds the cached articles, the overview data and the posts + waiting to be sent, and NewsCache creates its files there readable + by others under the usual umask 022. Give the spool directory mode + 0750, owned by `Username` and `Groupname`, as the Debian package + does: `chmod 0750 /var/cache/newscache`. The manual, newscache.conf(5), + the sample configuration and FEDORA.md now say so. +* With `--without-syslog`, a new log file is created with mode 0640 + instead of 0644, so other local users can't read client addresses and + user names in it. An existing log file keeps its mode: `chmod 0640` it. +* Numeric options take a plain number in a range now, and an AccessList + prefix must be valid: "MaxConnections ten", "ClientTimeout 20m", + "SpoolSize 10G" or "Client 192.168.1.0/", which were misread, are + configuration errors with the file and line (see Bug fixes). Check the + file with `newscache -p` before restarting. +* Logins with a user name or password shorter than 10 bytes are refused + (481) after the upgrade: the new option AuthMinLength defaults to 10. + Give such users longer names and passwords, or set "AuthMinLength 0" + to keep them. The sample auth file and the examples in the + documentation now use names and passwords of at least 10 bytes. Behaviour changes: -* A failed login (AUTHINFO PASS) waits at most 1 second before the 481, - the same after each failure; the connection is still closed after the - third. The delay was AuthFailureDelay times the number of failures (15, - 30 and 45 s by default, up to 3 hours with 3600), which only kept the - session's process and memory busy. AuthFailureDelay now defaults to 1; - larger values are accepted but count as 1, 0 still answers at once. -* PAM logins: NewsCache now gives PAM the client's address (PAM_RHOST), - so host-based PAM rules (pam_access, pam_succeed_if rhost, ...) apply. - They saw no host before: a service that allows only some hosts refused - every login, and one that denies some hosts didn't. Check such rules +* A failed login (AUTHINFO PASS) is answered with 481 after 1 second the + first time in a connection, after 2 seconds the second time and after + 4 seconds the third time; then the connection is closed, as before. A + successful login is answered at once. The count is per connection, so + a client that connects again starts at 1 second. AuthFailureDelay + keeps its name: 0 turns the wait off, any other value (1 to 3600, as + in older configuration files) turns it on; the default is 1, on. Up to + 1.3.22 the wait was AuthFailureDelay times the number of failures (15, + 30 and 45 s by default). +* PAM logins: NewsCache now gives PAM the client's address (PAM_RHOST), so + host-based PAM rules (pam_access, pam_succeed_if rhost, ...) apply. They + saw no host before: a service that allows only some hosts refused every + login, and one that denies some hosts didn't. In inetd mode, and when + the client's address can't be read, PAM gets no host. Check such rules before upgrading. configure --with-pam= (an empty service name) is now an error. * After a failed AUTHINFO PASS (481), the pending USER is invalidated. A @@ -18,10 +44,12 @@ Behaviour changes: can retry by sending USER again. * An AUTHINFO USER that is too long (481) also ends a pending USER, so a following PASS gets 482 instead of being checked against the earlier name. -* The log names the user in "failed authinfo for user " only when that - user's password was checked and refused. Other AUTHINFO failures (482, 501, - 502, an argument too long) are logged as "failed authinfo"; they were - logged as a failed login of the last USER. +* The log names the user in "failed authinfo for user " only when + that user's password was checked and refused, or when the user name or + the password was shorter than AuthMinLength (with the reason in + parentheses, see New options). Other AUTHINFO failures (482, 501, 502, + an argument too long) are logged as "failed authinfo"; they were logged + as a failed login of the last USER. * A known command that the client's entry doesn't allow, where no login can help (Authentication none, or after the login), gets "502 access denied", and POST "440 posting not permitted" (RFC 3977). Both got @@ -50,6 +78,77 @@ Behaviour changes: off, whatever its value). The default is unchanged. Note: without md5auto every stored hash is checked as MD5, so crypt() hashes in an auth file stop working. +* After SIGHUP, new sessions continue to use the startup NiceServer value; + changing it now requires a restart instead of partly applying it. +* Message-IDs from clients are checked before NewsCache consults the spool + or forwards a command or post upstream: those in commands must meet RFC + 3977's opaque-string rules and be at most 250 octets; posted Message-ID + headers must also meet RFC 5536's stricter syntax. Invalid IDs are + rejected; upstream articles with longer IDs can still be read by article + number. +* LIST OVERVIEW.FMT names the byte and line counts `:bytes` and `:lines`, the + form RFC 3977 8.4.2 prefers, instead of the older `Bytes:` and `Lines:` + (which the RFC still allows for compatibility). The OVER fields themselves + are unchanged. +* When an internal error (for example a damaged spool database) interrupts + a multi-line reply that has already begun (XOVER, LISTGROUP, LIST, ...), + NewsCache now closes the connection instead of ending the list with "." + as if it were complete, the same as for an upstream failure in the middle + of a list. Before anything is sent, the client still gets a 403. +* ConnectTimeout defaults to 30 seconds. It was 0, which leaves the + connect to the system: a news server that doesn't answer (a firewall + that drops the packets, a dead route) held each command that needed + it about two minutes per address of the server, with no reply to the + client, and the next command waited again. ConnectTimeout 0 keeps the + old behaviour. ConnectBackoff stays 0; the manual now says that its + time counts from the start of the failed attempt. +* Only one newscacheclean runs at a time, and only one updatenews that + prefetches (-g or -o): a second run, as cron starts one when the first + takes long, exits with status 3 and a message. Two newscacheclean runs + that overlapped both computed the purge from the same sizes and together + removed about twice what was needed; two prefetch runs fetched the same + groups twice. The locks are the files .newscacheclean.lock and + .updatenews.lock in the spool directory, held while the process runs. + newscacheclean -t (try only) and updatenews -a alone don't take the + lock. +* MODE READER and the greeting follow the client's rights (RFC 3977, RFC + 4643). MODE READER got "480 Authentication required" where the access + entry allows only the login ("allow authentication"), and where a login + is required ("Authentication unix" without fields) so did CAPABILITIES, + although newsreaders send both before AUTHINFO (and must not send MODE + READER after the login), so a newsreader couldn't learn from + CAPABILITIES that it may log in; unknown commands got 480 there instead + of 500. The greeting and MODE READER answered 200 (posting allowed) to + every client; both now answer 201 (posting prohibited) when the client + may not post at that moment: read-only entries, entries that allow only + the login, and before a login that is required or that would add the + post right. Such clients get 201 instead of 200 in the greeting; after + the login, CAPABILITIES says whether POST is available. +* A failed login (a wrong password, an unknown user, a stored hash that + can't be checked, a refusal by PAM, a user name or password longer + than 511 characters) is now answered with 481 instead of 502, as RFC + 4643 says. 502 means that AUTHINFO isn't available at all; it stays + the answer to AUTHINFO after a successful login and where the entry + has no Authentication. A script that looks for 502 after a failed + login must look for 481. +* POST answered with codes RFC 3977 doesn't allow after the article has + been sent, where only 240 and 441 are: "480 authentication required" + for a group outside PostTo while a login could add it, "440 posting + not allowed", and "449 operation failed" (for example, when a post + for an offline news server couldn't be spooled). All three are 441 + now; the first says "authentication required" in its text. A client + that waited for 480 there to offer a login will show the 441 instead. +* newscacheclean used NiceServer for its priority instead of NiceClean, + which had no effect. It uses NiceClean now (default 3), as + newscache.conf(5) says; check the value if you set NiceServer. +* A changed `Hostname` takes effect only on a restart; it applied to the + sessions started after a reload. A reload no longer looks up the host + name (a DNS lookup that could stall the daemon), so the default name is + looked up once, at startup, and only when the file sets no `Hostname`. +* A walk that gives up after 5 minutes without an article answers 403; + after part of a list the connection is closed, as after other upstream + failures. NEXT and LAST answer 403 then, instead of running until they + find an article. New options: * ReadTimeout (in a Server entry): give up the connection to the news @@ -59,7 +158,52 @@ New options: (default 1048576). A larger one is refused: the client gets 403, nothing is stored and the connection to that server is closed. * MaxPostSize: the largest article (bytes) a client may post (default - 1048576); a larger one gets 441. + 1048576, 1 MB). A larger article is refused with 441 and the session + goes on. There was no limit: a client could send an endless article (or + line) until the session ran out of memory. +* TLS for clients (implicit TLS, RFC 8143; through GnuTLS). TLSListenTo + opens a second listening socket (same form as ListenTo, default port + 563) next to the plain one, with TLSCertFile (PEM chain), TLSKeyFile + and optionally TLSPriority (a GnuTLS priority string; a warning when it + allows TLS 1.0 or 1.1). The certificate and key are loaded before + newscache switches to Username, checked by newscache -p, and loaded + again on SIGHUP (the old ones stay if that fails). The handshake must be + done within ClientTimeout, at most 30 seconds also with ClientTimeout 0. + newscache -t is inetd mode with TLS on the passed socket. An AccessList + entry with "AuthRequiresTLS yes" answers AUTHINFO on a plain connection + with 483 and lists AUTHINFO without USER in CAPABILITIES (RFC 4643). + STARTTLS for clients is not offered. newscache -o lists --with-gnutls. +* `--enable-sysv-init` installs an optional Linux and GNU/Hurd init.d + script, disabled by default; `--with-initdir` selects its installation + directory. It also works where the daemon's directory is a symbolic link + (/usr/sbin -> bin on Fedora and Arch). +* MaxConnectionsPerHost n (standalone mode): the most sessions one client + host may have at a time, so that one host can't hold all of + MaxConnections with idle connections. A host is an IPv4 address, or + the /64 network of an IPv6 address. A client over the limit gets "400 + too many connections from your host" (on TLSListenTo it is + disconnected without a reply), and the log says so, at most once a + minute with a count. The default is 0, no limit, so clients behind one + NAT address are not affected unless it is set. +* Server option "Options compress": COMPRESS DEFLATE (RFC 8054) to the + news server. After STARTTLS, the login and MODE READER, NewsCache + asks the server to compress the connection; from its 206 on, + everything is compressed both ways, so articles, overview data and + the active list come in a fraction of their size. A server that + refuses it, or doesn't know COMPRESS, is used without compression + (a notice is logged); invalid compressed data closes the connection. + The login is never compressed: when the server asks for it again + (480), NewsCache opens a new connection. It needs zlib: configure + finds it (--with-zlib requires it, --without-zlib leaves it out), and + "newscache -o" lists --with-zlib. zlib's development files are a new + optional build dependency (zlib1g-dev, zlib-devel). +* AuthMinLength bytes (default 10, 0 to 255, 0 turns it off): a user name + or password shorter than this is refused with 481 when AUTHINFO PASS + arrives, after the wait of AuthFailureDelay and without a password + check, a lookup or a PAM call. It counts as a failed login. AUTHINFO + USER still answers 381. The log says "failed authinfo for user ... + (user name shorter than AuthMinLength)" or "(password shorter than + AuthMinLength)", without the password. newscache -p prints it. Bug fixes: * LimitGroupSize was not applied to LIST ACTIVE entries. Until a GROUP reply @@ -67,9 +211,11 @@ Bug fixes: the full range and updatenews -g could prefetch it. Active-list entries now get the same newest-N cut as GROUP replies. * Authentication file: and pam+file: now warn at server start, and after a - successful SIGHUP reload, when an auth file is writable by group or world - or is a symbolic link. The warning includes the path and never blocks login; - duplicate paths are reported once per configuration read. + successful SIGHUP reload, when an auth file is writable by group or + world (for a symbolic link: its target), and once when the file or the + link target cannot be inspected. The warning includes the path and never + blocks login; each configured path is reported once per configuration + read. * Malformed commands starting with "auth" could expose their arguments in the log, including passwords. The log now keeps only the command word for these commands, and the reused request buffer is cleared before each read. @@ -80,16 +226,10 @@ Bug fixes: * When a configuration file could not be opened, newscache, newscacheclean, updatenews and cConfig reported "unexpected EOF". They now name the file and show the system error. -* newscacheclean -s -t now reports the database and article counts and sizes - found in the spool while leaving purge counters at zero; try mode used to - skip statistics collection and print zeros for every field. -* MODE READER got "480 Authentication required" where the access entry - allows only the login ("allow authentication"), although newsreaders - send it before AUTHINFO and must not send it after the login (RFC - 4643). It also answered 200 (posting allowed) to every client; it now - answers 201 (posting prohibited) when the client may not post at that - moment: read-only entries, and before a login that adds the post - right (RFC 3977). +* newscacheclean -s now reports the number of cached group directories in + DirCnt (always 0 before), and with -t the database and article counts + and sizes found in the spool, leaving the purge counters at zero; try + mode skipped the statistics and printed zeros for every field. * Two sessions that started at the same time on a new spool could fail: the second one couldn't create the spool directories (EEXIST) and ended before its greeting. @@ -124,17 +264,25 @@ Bug fixes: couldn't take it: logging its Message-ID failed, the run aborted, and the article was neither posted nor kept in .badArticles. An article whose posting fails with an unexpected error now stays in the spool. -* Posts kept for later (news server offline or unreachable) were moved - to the spool's .badArticles directory, and never sent, when updatenews - ran while the news server still couldn't be reached. They now stay in - .artSpool until the server takes them; only articles the server - refuses go to .badArticles. A spooled article is also no longer lost - when updatenews is stopped while posting it. +* Posts kept for later (news server offline or unreachable) were moved to + the spool's .badArticles directory, and never sent, when updatenews ran + while the news server still couldn't be reached. They now stay in + .artSpool until the server takes them, and the run goes on with the + other articles; the log says how many were kept. Only articles the + server refuses go to .badArticles. A spooled article is also no longer + lost when updatenews is stopped while posting it. * An upstream server could send an endless line or article, and the - session read it until it ran out of memory. Articles are now limited - by MaxArticleSize, and lines outside articles (status lines, overview + session read it until it ran out of memory. Articles are now limited by + MaxArticleSize, and lines outside articles (status lines, overview records, the active list, LISTGROUP) to 16 KiB; more is an error, and - the connection to the server is closed. + the connection to the server is closed. A news server that sent an + article, or the LIST OVERVIEW.FMT reply read when NewsCache connects, + one byte at a time with pauses just under ReadTimeout could hold the + session (and the locks it held) for hours. The article now has a limit + for the whole reply, two minutes plus MaxArticleSize at 4 KB/s (6 + minutes for the default 1 MiB), and the overview format 30 seconds, 1000 + lines and 1 MiB; NewsCache then closes the connection and answers the + client with 403. * With very few free file descriptors (ulimit -n 5 on Linux, 6 on FreeBSD), or a spool where the lock file can't be created, a session aborted before the greeting instead of answering 400: the lock class threw a @@ -154,9 +302,6 @@ Bug fixes: neither posted nor prefetched anything. The option is now accepted and ignored: groups are prefetched one at a time. --lock-groups, as the usage text spells it, works too. -* newscacheclean used NiceServer for its priority instead of NiceClean, - which had no effect. It uses NiceClean now (default 3), as - newscache.conf(5) says; check the value if you set NiceServer. * XDEBUG: "xdebug dump" with an unknown argument got no reply, so the client waited for ever; it now gets 501. The replies of "xdebug dump" and "xdebug help" begin with the code 100 instead of "xxx" or no code @@ -189,18 +334,6 @@ Bug fixes: kept the first user's rights under the second user's name. It now gets 502, as RFC 4643 says. A client whose entry has no Authentication gets 502 at once too (it got 381, then 502 after the failure delay). -* A failed login (a wrong password, an unknown user, a stored hash that - can't be checked, a refusal by PAM, a user name or password longer - than 511 characters) is now answered with 481 instead of 502, as RFC - 4643 says. 502 means that AUTHINFO isn't available at all; it stays - the answer to AUTHINFO after a successful login and where the entry - has no Authentication. Behaviour change: a script that looks for 502 - after a failed login must look for 481. -* Where a login is required ("Authentication unix" without fields), - CAPABILITIES and MODE READER got "480 Authentication required" instead - of their answer, so a newsreader couldn't learn from CAPABILITIES that - it may log in (RFC 3977, RFC 4643); unknown commands got 480 instead - of 500. * Auth-file lines longer than 1023 bytes (a long List) were split silently: the line lost its later fields, such as the flags, and the rest was read as a line of its own, whose start was taken for a user @@ -251,9 +384,6 @@ Bug fixes: files named like history shards) and replaced a file named .db, and a link loop made it count the spool many times over and purge articles for nothing. It now skips symlinks. -* POST takes articles of up to 1 MB. There was no limit: a client could - send an endless article (or line) until the session ran out of memory. - A larger article is refused with 441 and the session goes on. * In standalone mode a client got no reply when its session couldn't open the spool (missing or not writable): the "400 ... service not available" stayed in the buffer, because the session exited without @@ -320,11 +450,13 @@ Bug fixes: silently overwrote another one; the file is now moved aside as damaged instead. * When a spool file grew and couldn't be mapped into memory again (an - address space limit, ulimit -v or LimitAS=), the session kept the - file's lock for good, so every other session that needed that group, - the active list or the history hung, and its next access to the file - crashed it. The lock is now given back and the file mapped again at - the next access. + address space limit, ulimit -v or LimitAS=), the session kept the file's + lock for good, so every other session that needed that group, the active + list or the history hung, and its next access to the file crashed it. + The locks are now given back (also the outer ones when the file grew + while a nested lock was given up), a write under its own lock reports an + error instead of crashing, and the file is mapped again at the next + access. * A signal (SIGTERM, SIGHUP, the client timeout's alarm) that came while a session waited to upgrade its lock on a spool file left the session without the lock it already had, so it went on reading the file @@ -385,15 +517,18 @@ Bug fixes: locked for everyone. With ReadTimeout the connection is given up and opened again, also over TLS (where the wait was without limit even when closing the connection). -* A header folded over several lines was read with the line breaks and - the white space that starts each continuation line removed: "Subject: - foo" followed by " bar" read "foobar" in HDR, XHDR and XPAT (by - message-ID, and by number once the article was in the spool), where - the overview from the news server says "foo bar". Unfolding now keeps - one space in place of the fold, as RFC 5322 says. For a Newsgroups - header this means a fold after the comma still separates two names, - and a fold instead of a comma is white space in a name, which is - refused, not a third group made of the two names joined. +* A header folded over several lines was read with the line breaks and the + white space that starts each continuation line removed: "Subject: foo" + followed by " bar" read "foobar" in HDR, XHDR and XPAT (by message-ID, + and by number once the article was in the spool), where the overview + from the news server says "foo bar". Unfolding now removes only the line + break and keeps the white space around it (RFC 5322 2.2.3), as the news + server's overview has it, so a group's OVER line no longer changes once + the article is in the spool. HDR, XHDR and XPAT also turn a TAB in a + header into a space, as OVER does (RFC 3977 8.5.2). For a Newsgroups + header this means a fold after the comma still separates two names, and + a fold instead of a comma is white space in a name, which is refused, + not a third group made of the two names joined. * The PostTo check and the posting read a Newsgroups header differently. The check split it on commas and matched each name against the PostTo list, but the matcher stopped at white space, so "Newsgroups: a b" was @@ -408,7 +543,7 @@ Bug fixes: such an article gives no Read right by message-ID either. * AUTHINFO: the password hashes are compared in constant time, so the answer's timing no longer tells how many leading characters of a guess - matched. A stored hash that crypt() can't use is refused with 502 and + matched. A stored hash that crypt() can't use is refused with 481 and an error in the log, also on libxcrypt and musl, where crypt() returns the failure token "*0" instead of NULL (a stored "*0" matched it for any password). Built with --without-md5 but with MD5 autodetection, a @@ -466,12 +601,16 @@ Bug fixes: * ./autogen stops with an error when autoreconf fails (autoconf, automake or libtool missing). It used to say "Next run ./configure" anyway, and the build failed one step later because there was no configure script. -* An article with a NUL byte, or a CR without LF in a header, from the - upstream server (or posted through NewsCache) could not be read - ("423 no such article number") or, once stored, made NewsCache take - the group's spool database for damaged at every read: it was moved to - .db.bad and all cached articles of the group were fetched again. Such - bytes now become a space; RFC 5536 allows neither. +* An article with a NUL byte, or a CR outside CRLF, from the news server + could not be read ("423 no such article number") when the CR was in a + header, or, once stored, made NewsCache take the group's spool database + for damaged at every read: it was moved to .db.bad and all cached + articles of the group were fetched again. A lone CR in the body, or + inside an overview record, went to clients in ARTICLE, BODY, OVER, XOVER + and XHDR, and a reader that ends a line at a CR saw the reply end early + and status lines chosen by the news server. Such bytes now become a + space (RFC 5536 allows neither), when the article or record is read from + the news server and when one that an older version stored is sent. * XHDR Xref and HDR Xref killed the session (an uncaught exception, SIGABRT) when an overview record from the upstream server had an empty Xref field followed by a tab. They also answered ": host group:n" @@ -517,13 +656,6 @@ Bug fixes: characters: the length was checked first. The sequence is now checked first. AUTHINFO with an unknown subcommand and a long argument now gets 501 (syntax) instead of 481. -* The greeting was "200" (posting allowed) for every client. It now - follows the same rule as MODE READER: "201 ..., posting prohibited" - when the client may not post at that moment, as RFC 3977 says: - read-only entries, entries that allow only the login, and before a - login that is required or that would add the post right. Behaviour - change: such clients get 201 instead of 200 in the greeting; after - the login, CAPABILITIES says whether POST is available. * Where a login is required ("Authentication unix" without fields), CAPABILITIES listed READER, HDR, OVER, LIST and POST before the login, although all of them got "480 Authentication required" then. @@ -542,13 +674,6 @@ Bug fixes: * DATE would answer "500 gmtime failed" if the system couldn't convert the time; 500 means "unknown command". It is "403 gmtime failed" now (RFC 3977: internal fault). This doesn't happen in practice. -* POST answered with codes RFC 3977 doesn't allow after the article has - been sent, where only 240 and 441 are: "480 authentication required" - for a group outside PostTo while a login could add it, "440 posting - not allowed", and "449 operation failed" (for example, when a post - for an offline news server couldn't be spooled). All three are 441 - now; the first says "authentication required" in its text. A client - that waited for 480 there to offer a login will show the 441 instead. * GROUP and LISTGROUP answered "411 no such news group" also when the news server couldn't be reached or answered GROUP with an error, for a group the spool didn't know yet: the group looked as if it didn't @@ -569,19 +694,566 @@ Bug fixes: "411 no such news group". RFC 3977 asks for 412 when the selected group is invalid, and keeps 411 for a group named in the command; the reply is now "412 current group no longer exists". +* TLS connections to upstream servers: a read or write interrupted by + SIGTERM or the alarm was retried, so a session waiting for an upstream + TLS server ended only when the server answered; now it ends at once, + as with a plain connection. +* ListenTo (and TLSListenTo) with an IPv6 address such as [::1] failed on + a host without a global IPv6 address, a container for example: + getaddrinfo was asked for AI_ADDRCONFIG, which ignores loopback + addresses. The listen address is numeric and is now used as given. +* The listening sockets queued at most 4 connections that weren't + accepted yet; a burst of clients overflowed that, and FreeBSD reset + the extra connections. The queue now holds 128 (MaxConnections still + limits the sessions). +* newscache didn't check whether listen() worked on its listening + sockets. On Linux two sockets can bind the same address and port, so + with TLSListenTo on the port of ListenTo (or of another program) only + listen() failed, and the daemon ran without that listener: TLS clients + reached the plain listener. It now exits with "can't listen on + TLSListenTo ...". +* When header logging is enabled, failures to open `.headerlog` are now + logged instead of silently dropping the header. +* configure --with-gnutls now fails when the GnuTLS library or headers + are missing, instead of silently building without TLS. With no explicit + option GnuTLS remains optional, and a missing dependency is warned about. +* A termination or reload signal arriving just before the daemon entered + poll could leave it waiting until another client connected. Signals now + wake the idle daemon immediately. +* The default configuration path expands `${prefix}` in a custom + `--sysconfdir` (it stayed literal, so a `--sysconfdir='${prefix}/conf'` + build looked for a file under a directory named `${prefix}`). Shell + syntax such as `$(...)` in `--prefix` or `--sysconfdir` stays literal + and is not run. +* When a listener cannot bind, the final error on stderr and in the log + now includes the system error, such as "Address already in use". +* SIGHUP reports each changed restart-only setting against the running + startup configuration, including whether ListenTo was specified. Notices + repeat until restart or until the configured setting is reverted. +* OVER answers 423 when the requested article range is empty, including a + reversed range, instead of sending an empty 224 response (RFC 3977). +* OVER by message-ID now answers 503, because this optional form is not + supported, whether or not a newsgroup is selected (RFC 3977). +* Generated Message-IDs no longer exceed the 250-octet limit with a long + Hostname: when necessary, the host part is the hostname's MD5 in lowercase + hexadecimal, while the time, process and counter components are retained. +* Reject overlong database paths before copying them into the fixed-size + container filename buffer, without disturbing an already-open database. +* A configuration path that is a directory is now reported as "cannot open + configuration file : Is a directory" instead of "unexpected EOF". +* updatenews now retains group-number information for up to 60 seconds during + prefetch, avoiding redundant upstream GROUP commands within a prefetch. +* Upstream TLS handshakes now have a whole-handshake deadline based on + ReadTimeout, or ConnectTimeout when ReadTimeout is zero (60 seconds when + both are zero), and stop promptly on termination signals. STARTTLS retains + the configured timeout after upgrading. +* CAPABILITIES now advertises LIST EXTENSIONS, which the client already + implements. +* NEWGROUPS now rejects arguments beyond its optional GMT token, reports the + correct syntax, and uses the RFC 3977 231 reply text without a timestamp. +* updatenews now logs an error with the reason (for example "No such file or + directory" or "Permission denied") and exits nonzero when a configured + PrefetchFile cannot be opened or is a directory or a FIFO (a directory was + read as empty, a FIFO blocked the run). An empty PrefetchFile, or + /dev/null, still means no groups to prefetch. +* NewsCache now warns in its log, at startup and after a reload, when a + PAM service named by `PAMServicename` for `Authentication pam` or + `pam+file` has no configuration in `/etc/pam.d` or `/etc/pam.conf`. PAM + then silently uses its `other` service. The warning is advisory; logins + are unchanged. +* NEWGROUPS rejects invalid calendar and clock values instead of allowing + the C library to normalize them. Documented that NEWGROUPS and LIST + ACTIVE.TIMES use the local first-seen time, not upstream creation times. +* Free the last selected group and the server object when a client session + ends, and the purge list in `newscacheclean`, so that a leak-checking + (LeakSanitizer) run of the test suite reports nothing. +* Bound upstream active lists, overview replies and LISTGROUP replies so a + broken server cannot keep consuming resources or holding locks + indefinitely: an active list may have at most 2,000,000 lines and 256 + MiB and take at most 5 minutes, an overview or LISTGROUP reply as many + lines as the requested range and at most 2 minutes. Incomplete replies + are not marked fresh, and their upstream connections are closed rather + than reused. An incomplete combined active list is retried after at most + 60 seconds, rather than on every request. Interrupted overview and + LISTGROUP replies are reported as failures rather than as a successful + empty or incomplete range. +* Filter Xref headers in one pass so a large crosspost list from an upstream + server cannot hold the group lock for quadratic time. +* A client that stops reading its replies now ends its session after one + ClientTimeout. Output left in the send buffer after the failed send was + sent again by every later flush, each waiting for the timeout once more, + so such a session lasted several ClientTimeouts (seen with TLS on + EL9). +* The session of a client that stopped reading in the middle of a reply + could end after two ClientTimeouts instead of one (seen on FreeBSD): + when the send timeout runs out after send() has taken part of the + data, Linux and FreeBSD return that part instead of an error, and the + rest was sent with a second wait. After a short send, the rest now + goes out only if the socket can take more within what is left of the + send timeout; otherwise the write fails, like a failed send. The same + applies to connections to the upstream servers (ReadTimeout). +* A client's LISTGROUP goes to the news server in steps, each with its + own reply limits: 10000 numbers at a time in a dense group, larger + steps (up to 100000000 numbers) across gaps; it fails when no number + reached the client for 5 minutes. It used to be one request + for the whole range, or the whole group, so a list of millions of + numbers could run into the reply deadline, and a provider that + answers 503 to large ranges made NewsCache fetch overview records + instead. +* Posts forwarded to multiple upstream servers now get missing Date and + Injection-Date headers before forwarding, so each injector receives the + same dates along with the shared Message-ID. +* An inetd session (newscache -i) that gets SIGINT or SIGTERM between two + commands ends at once with "400 ... service discontinued"; it waited for + the client's next line. Reads inside a command, such as the article of a + POST, now also give up after ClientTimeout plus 10 seconds in inetd + mode, as they do in the daemon; a stalled POST kept the session forever. +* Bytes of 0x80 and above in client commands, newsgroup names and the + configuration file are passed to the C character class functions as + unsigned char. As plain (signed) char they were negative values, + undefined for those functions, and read outside the table on C + libraries that index it directly. +* POST refuses an article with a NUL or a CR outside CRLF (441), as + RFC 5536 requires. It was forwarded as it came: against a news server + that ends a line at a lone CR, the article ended early and the rest + ran as commands on NewsCache's own connection to that server. A + spooled article with such a CR, from an older version, is posted + with the CR replaced by a space. +* Control bytes in a log line (ESC, a CR, DEL and the other bytes below + 0x20) are now written as "?". Client input went into the log as it + came, in commands, user names, group names and host names from DNS, so + a client could make a line look like something else on a terminal or + split it for a log parser. The same applies to the article headers that + configure --enable-headerlog writes to .headerlog, except tabs and the + line ends. +* An article over 15 kB is stored in a file of its own. NewsCache wrote + it in place: a crash or power cut could leave the file cut off, and + NewsCache then served it without its last partial line and without a + word; a write that failed (a full disk) removed the copy that was + there. Now the file is written under a temporary name (.art.tmp), + flushed to the disk (fsync) and renamed, and the directory is flushed + too, before the article counts as stored: the file is either whole or + the old one. A cut-off file from an older version, whose last line has + no line end or that has no empty line after the header, is fetched + again from the news server and written anew. If the news server + doesn't have the article any more, the stored copy is served as it is + and the log says so; the file is kept (one cut before its Message-ID + header can't be served and is removed, as before). (A file cut right + after a line end in the body can't be told from a whole one.) Complete + files with LF line ends (as older versions or an admin may have + written them) are served as before. newscacheclean counts a .tmp file + that a crash left behind as an article file and removes it by its age. +* A session or updatenews stopped with SIGTERM or SIGINT (updatenews also + with SIGHUP, SIGUSR1 or SIGUSR2) while it waited for the news server + opened new connections to it before it ended: the connect was retried + (Retries times, a second apart), a command was sent again after a + reconnect, and updatenews tried the next server and fetched the active + list. With a ConnectTimeout (it is 30 by default now), the reconnect + even cleared the signal's mark, so the session carried on until the next + command or ReadTimeout; with ConnectTimeout 0, an interrupted connect to + a news server that didn't answer was started again and waited for the + system's timeout (minutes). Now nothing is retried and no reconnect is + made after the signal (a connect that began at that very moment is + closed before a command is sent on it), and a wait for the news server + ends within about a second: a signal that came just before a wait began + (after the check for it) is caught by an alarm every second until the + process ends. The reply "service discontinued" gets two seconds, and a + TLS send isn't started again once the signal is seen. The log says + "given up: shutting down" or "not read to its end: shutting down" + instead of blaming the news server, and an empty line for a greeting + that never came is no longer logged. +* Opening a group's database waits for its lock and then checks the + file. A signal that interrupted the wait (SIGTERM, or SIGHUP for + updatenews) let the checks run without the lock: they could see + another process half way through a change and call a sound database + corrupt, which moved it aside and started an empty one. Now the wait + goes on after a signal, and a lock that can't be taken is an error. + The same holds for the directory lock taken before a corrupt database + is moved aside. +* The lock of the post spool (.artSpool) gave up when a signal + interrupted the wait for it: after SIGTERM, a post that the news + server didn't take could fail to reach the spool, and the client got + an error. Now the wait goes on; the lock is held only while one file + is stored or removed. +* A client that asked for a long XOVER, XHDR or LISTGROUP reply and stopped + reading held the group's shared lock until its send timed out + (ClientTimeout), and every session that had to store an article or an + overview record for that group waited that long - 600 seconds with the + sample configuration. The records are now formatted under a short lock and + written with the lock released: at most 64 records or 64 KB for XOVER and + XHDR, and at most 4096 numbers or 64 KB for LISTGROUP. +* Fetching an article from the news server held the group's shared lock for + the whole fetch (bounded by ReadTimeout, 300 seconds by default), so every + session that needed to store an article or an overview record for that group + waited for the news server. The article is now fetched with the lock + released and stored afterwards; an article that another session stored, or a + group that was resized, meanwhile is handled when the article is stored. +* A daemon session (not one started by inetd) stopped with SIGTERM or + SIGINT while a command ran, for example while it waited for the news + server, sent neither that command's reply nor "400 ... service + discontinued": the signal made the send fail, and the log said "can't + be written to, session ended". A client whose post had gone to the + spool got no 240 and could post it again. Now the reply and the 400 go + out, with two seconds for both. +* A client's LIST ACTIVE (or GROUP, when it needs the group's entry) that + found the active list stale held the list's exclusive lock while NewsCache + fetched the list from the news servers, so every other session's GROUP + waited for the news server - up to the whole-reply limit of 5 minutes per + server. The list is now fetched without the database's lock and stored + afterwards: a fetch that fails midway (reply limit, deadline) leaves the + stored list as it was, while a reply cut off in the middle still stores the + lines that were read, as before. A second lock in the spool + (.active.refresh) makes sure only one session fetches the list at a time: a + session that finds another one fetching serves the list it has, and only a + session with no list at all (first start, a damaged .active64) or + updatenews -a waits for the fetch to finish. Meanwhile a group that is new + on the news server is unknown (411) until that fetch is done. A session or + updatenews stopped with SIGTERM or SIGINT while it waits for another + one's fetch ends at once; it waited for that fetch to finish. A session + stopped in the middle of its own fetch no longer marks the news servers + as failed, which made the other sessions serve the old (or an empty) + list for up to a minute. +* A client's XOVER, OVER, XHDR or HDR on a range of a group that + NewsCache hadn't synchronized yet (or not within GroupTimeout) held the + group's exclusive lock while it asked the news server for the group's + numbers, the article list and the overview records. Every other session + that read that group, even an article already in the spool, waited for + the news server: up to 2 minutes per 10000 article numbers, longer with + a server that sends slowly. The news server is now asked without the + lock, and the records are stored afterwards under a short one. A new + lock file in the spool (.fetch.lock, no data in it) still lets only one + session fetch a range at a time: a second session that wants the same + range waits for the first one and serves what it stored, instead of + asking the news server again. +* updatenews -g held the group's lock while it asked the news server for + the article list and each article, so clients reading the group waited + for it (with -l, for the whole prefetch of each 10000 numbers). It now + locks the group only while it stores or removes an article. With -l a + range is still reserved for the prefetch while it runs: sessions that + need its overview wait for the prefetch instead of fetching it too, but + sessions reading what the spool holds no longer wait. +* A stored article that can't be read is removed from the cache, so that + it is fetched again. When another session had just stored a good copy of + that article, the good copy could be removed instead (and was fetched + again on the next request). Now only the unreadable copy is removed. +* The first fetch of the active list (the list of groups) on a new spool, + from several news servers or with several Read patterns, no longer gives + other sessions a partial list while it runs: they wait for it. If NewsCache + was stopped during that first fetch, the next session fetches the list + again; before, the part already fetched was served as complete until the + list timed out (Timeouts). +* When newscacheclean prunes history for a group whose spool database is + gone, it no longer removes a location that another session has updated or + whose group has since been recreated. Losing that location made a + message-ID lookup go to the news server instead of finding the cached + article (the article was still in the spool; only the lookup by + message-ID missed it). +* When a group has an article under a new number, removing an old spool + record or a stale history location no longer removes the new number from + history. The cached article remains findable by message-ID instead of + requiring a fetch from the news server. +* Reading an older cached copy of an article no longer replaces the history + location of another copy in the same group. This keeps the surviving copy + findable by message-ID when the older one is removed from the spool. +* A GROUP that gets a group's numbers from the news server no longer sets + the group's posting flag in the active list to "y". A moderated ("m") or + read-only ("n") group was listed as open for posting by LIST ACTIVE and + NEWGROUPS until the active list was fetched again. +* The flag that NewsCache's and updatenews' signal handlers set to end a + wait (alarmed) is now volatile, as C and C++ require for a variable a + signal handler writes. A compiler was free to keep the old value in a + register, and a loop could miss a timeout or SIGTERM. +* On systems where a lock held by another process makes fcntl report + EACCES (POSIX allows it), updatenews no longer stops posting the spooled + articles with an error when another process is posting them; it says + that another process posts them, as on Linux and the BSDs. +* updatenews -g no longer marks a chunk of a group's overview as up to date + for numbers it didn't fetch: in a group of more than 10 million numbers, + the ones just below the prefetched part (in the same chunk of 10000), and + numbers another session's range had already moved past while the + prefetch ran. Clients asking for those numbers got nothing from the spool + instead of the news server's overview. +* newscacheclean no longer removes a big article's file that a session + stored while the cleaner was reading the group's directory: it took the + file for one outside the group's range and removed it at the end of the + run, even when the spool was below SpoolSize. Nor does it remove a file + that was replaced under the same name since the scan (an article stored + again, a group database started anew after a damaged one was moved + aside): the check and the unlink are done under the lock the session + takes for that change. +* When a group's article range changes during an overview fetch, NewsCache + no longer marks an out-of-range fetch as synchronized. If the index later + grows down into a partly covered chunk, its synchronization mark is cleared + so missing overview records are fetched instead of treated as fresh. +* With "Options starttls", a reply shorter than a status code to MODE + READER, STARTTLS or LIST OVERVIEW.FMT (which anyone in the middle can + send), or a refused login, left the half set-up connection to the news + server open. The next command went out on it in plain text, without + STARTTLS or the login, and a 480 to that command made NewsCache send + User and Password in plain text. Such a connection is now closed, and + the next command connects again. +* An article with bare LF line ends, written as its body only, started + with an extra empty line and ended with a stray NUL byte. The body is + now written as it is. +* On FreeBSD and macOS a news server with BindFrom could not be reached + ("Unable to bind to outgoing address"): bind() was given the size of + a whole sockaddr_storage as the address length. It now gets the + length of the address (IPv4 or IPv6). +* HELP showed a wildmat argument for NEWGROUPS, which the command + rejects with 501, and a time argument for LIST ACTIVE.TIMES, which + takes a wildmat. HELP and the 501 syntax reply now show what the + commands accept; AUTHINFO, MODE and XDEBUG are listed completely. +* LIST NEWSGROUPS left out the last description when the .newsgroups + file did not end with a newline. It is now listed. +* In a Server block of the configuration, a PostTo line before the Read + line was overwritten by Read. PostTo now stays as given; without it, + it still defaults to Read. The manual says so. +* A temporary error while reading a group's record (no free file + descriptor, a lock timeout) made the lookup of an article by + Message-ID forget where it was stored. The location now stays in the + history unless its record is really gone or holds another article. +* The wildmat of LIST ACTIVE, LIST ACTIVE.TIMES and LIST NEWSGROUPS is + now a list as in RFC 3977 section 4.2: comma separated patterns, each + optionally led by "!", the last one that matches deciding. A list such + as "comp.*,alt.*" or "comp.*,!comp.os.*" used to list nothing, and + LIST ACTIVE.TIMES read its argument as an access rule list, so + "LIST ACTIVE.TIMES *.test" listed every group the client may list. +* A client that posted two articles without a Message-ID in one session, + to more than one server, within the same second could lose the second: + both got the same generated Message-ID (the counter in it was always + 1), so the second was taken for a duplicate and dropped, while the + client got 240. The counter now counts. +* A client that sent the article after POST slowly enough to never hit + the per-read timeout (a byte every few seconds) could hold a session, + and with enough of them all of MaxConnections, for ever. The whole + article must now arrive within ClientTimeout after the 340 reply; + otherwise the client gets "400 ... service timed out!" and the + connection is closed. +* A client whose PostTo allowed only some groups could add a second + Newsgroups header with another group: only the first was checked, and + both went to the news server. A POST with a repeated Newsgroups, From, + Subject, Date, Path or other header that RFC 5536 allows once is now + refused with 441 "more than one ... header" and logged. +* When accept() failed because the daemon had run out of file + descriptors or memory (EMFILE, ENFILE, ENOBUFS, ENOMEM), it retried at + once, without pause: it used a whole CPU and logged "accept failed" + for every try. It now logs the failure once, waits a second between + tries (a signal still acts at once) and logs again after an accept + that worked. +* Started without -n, newscache forked and its parent exited with status + 0 at once. If the daemon then could not listen (port in use) or drop + its privileges, it said so only on a standard error already pointed + at /dev/null: the start command reported success and no daemon ran. + The parent now waits until the daemon listens; if the daemon ends + before that, it exits with status 1 and the daemon's message is shown + on the terminal. +* A C++ standard exception (std::bad_alloc, std::length_error ...) in a + command ended the session without a reply, and in inetd mode (-i, -t) + ended the process with SIGABRT and a core dump. The client now gets + "403 internal error" like for NewsCache's own errors and the session + goes on; the exception is logged. Outside a command the session ends + with a log message. +* On a TLS connection to a news server, silence lasted twice as long as + ReadTimeout before NewsCache gave up on the reply. Now it is one + ReadTimeout, as on a plain connection. +* A session inherited the master's SIGCHLD handler, which reaps any child + with waitpid. A helper process started by a PAM module during login + could lose its exit status to it. Sessions, and the inetd mode, now + leave SIGCHLD at its default. +* After a power cut or a crash, an article that a client had POSTed + while the news server was unreachable ("240 Article posted") could be + an empty file in the outgoing spool, and updatenews moved it to + .badArticles: the post was lost. The article is now written to disk + (and the directory synced) before the client gets the 240. A + temporary file left in the outgoing spool by a crash is now removed + by updatenews. +* One failure to open a history shard (too many open files, no space + left while the file was created) switched the history off for that + shard until the session ended: ARTICLE went to the news + server and the stored locations went stale. The shard is now tried + again after a few seconds. +* An Article object that had not read or been given a text yet pointed + at uninitialised memory when asked for its text. No code path did + that, but a failed read (out of memory) could leave the same + dangling pointer. The text pointer is now set in every constructor + and when a read fails. +* After a process was killed while it grew a database file, the next + growth left part of the new space unusable (up to 64 KB, more for + large indexes). The free space is now counted from the size the + header records. +* When a damaged database was moved aside and the new one could not be + started because memory ran out, the lock on the spool directory + stayed held until the process ended, and other processes that had to + move a damaged database aside waited for it. The lock is released + and the database is started again at the next use. +* A damaged record in the active database that was a few bytes longer + than a group entry (554 to 560 bytes) was not recognised as damage: + GROUP and the other commands for that group failed with an error + until the file was removed by hand. The file is now moved aside and + rebuilt, as for any other damaged record. +* updatenews kept the database of a group open when its prefetch failed + with an unexpected error, one file descriptor and one mapping per group, + until the run ended. A long run over many failing groups could run out + of file descriptors. The group is now released. +* A group's last article number could go back: a GROUP reply stored after + a newer one from another session put the older numbers back, and so + could an active list that was still being read (it is now fetched + without the database's lock, see above). For up to GroupTimeout, GROUP + then showed the old last number, and the overview records and articles + above it that had been cached were thrown away. A group's numbers now + carry the time they were asked for, and older numbers no longer replace + newer ones (in the same second, the higher last number stays). The + list's posting flag is still taken over. +* Going back from an exclusive lock on a spool database to the shared + lock held around it (as when a session removes an unreadable article + while it reads a group) gave the lock up for a moment, and another + process could change or resize the file in the middle of the shared + section. The exclusive lock is now turned into the shared one at once; + only taking an exclusive lock still gives the shared lock up first. +* A client could get "403" for a command that opened a group at the + moment newscacheclean removed that group's directory (after its + database): the session had made sure the directory was there, and + then found it gone when it created the database. The session now + makes the directory again and creates the database. +* A spooled article that updatenews could not read (one too big for the + memory) ended the posting run with the lock of the outgoing spool + still held: until updatenews ended, every session that spooled a POST + while the news server was down waited, and the article, read first, + stopped every later run as well. It is now moved to .badArticles, with + a line in the log, and the next spooled article is posted. +* When a session ran out of memory while it sent overview data, header + lines or article numbers of a group (OVER, HDR, LISTGROUP), or while + it changed the active database and the disk was full, it kept the + group's (or the active database's) lock until it ended, and every + other session that had to change it waited. The lock is now given + back in every case. +* The lookup of a client's host name ran before the greeting, with no + time limit: a client whose reverse DNS zone doesn't answer kept a + session, one of MaxConnections, for the resolver's timeouts (a minute + and more). The lookup now takes at most 10 seconds (or ClientTimeout, + if that is shorter); after that the client goes by its address, and + the log says so. +* A client turned away at MaxConnections ("400 too many users") was not + logged, so a server whose sessions were all taken (by a flood, or by + idle clients) showed nothing. The log now names the first client + turned away, counts the others at most once a minute while the limit + is reached, and says when a session can be started again. +* Built with --without-syslog, the daemon wrote into its log file until + it ended: after log rotation renamed newscache.log, it and every new + session went on writing into the renamed file, so only copytruncate + (which loses lines) worked. On SIGHUP the daemon now opens + newscache.log again; sessions started afterwards write to the new + file, running ones to the old one until they end. newscache.conf(5) + and the manual have a logrotate example. +* The client's name, which its reverse zone gives (whoever has the + address block runs that zone), went into X-NNTP-Posting-Host and the + log as it was. musl's getnameinfo returns CR and LF too, so on musl + systems (Alpine) a name with "\r\n.\r\n" ended a posted article on + the news server's connection, and the rest was read as commands. + A name with anything but letters, digits, dots, hyphens and + underscores is now dropped, and the client goes by its address; + X-NNTP-Posting-Host is also left out when the host has a space or a + control character. +* LIST ACTIVE, LIST ACTIVE.TIMES and NEWGROUPS collected the list in a + buffer under the lock and then made a copy of all of it to send it, + for any client that may list. It is now sent from the buffer itself: + for a list of 3 million groups (190 MiB) a session's peak memory + goes from about 370 to 260 MiB. +* With several news servers, the active list could take a group from a + server it isn't routed to. NewsCache asks each server for "LIST ACTIVE + " per pattern of its Read; the filter for that reply let every + group through except those it matched against the other servers' + patterns, and that comparison lost its place after a partial match. With + one server reading "dk.*,de.alt.binaries.*" and another "de.*", the + second server's numbers and posting flag for de.alt.binaries.* replaced + the first's, GROUP and LIST ACTIVE showed them, and the cached records + above a lower last number were dropped at each refresh. Also, a group + that another server's Read excludes ("!de.sub.special.*") could be + missing from the active list, and a group that two servers read with + the same pattern came with the second server's numbers. Each server's + reply now keeps only the groups that GROUP takes from that server. +* Group names with a "/" or an empty component (a/b, a.b., .a.b, a..b) + had the spool directory of a.b: when a news server answered GROUP for + such a name, its overview records and articles went into a.b's + database, and readers of a.b got them; such a name also got past an + exact "!a.b" in a list. They aren't newsgroup names (RFC 5536 3.1.4): + GROUP and LISTGROUP answer 411 for them now, and the spool refuses + them. +* newscacheclean neither counted nor removed article files in a group + directory without a database (left when the database was removed while + a session still had it open and stored an article, or moved aside as + corrupt on a full disk). No session can reach them, but they stayed + outside SpoolSize until a session opened the group again. They are + removed first now, unless a session has started a new database in the + directory meanwhile; a file a session stores there while one is being + removed is kept. +* When memory ran out while a session applied its message-ID history + updates at the end of an overview reply or a stored chunk, the session + ended with SIGABRT and a core dump (an exception left a destructor) + instead of the error reply other failures get. The updates are dropped + now, with a log message; the history is an index, and a missing entry + only costs a lookup. +* After a broken connection to a news server, NewsCache selects the + client's group again on the new connection. That GROUP was sent after + the set-up guard of the connection was off, so a server that closed the + connection (or answered 400) at it made NewsCache reconnect from inside + the reconnect, nested without limit: thousands of connections to the + server, then the session crashed (stack overflow) without a reply. A + failed GROUP now ends that connection attempt, the client's command gets + an error reply after at most Retries attempts, and the session goes on. + The guard for MODE READER and LIST OVERVIEW.FMT came in 1.3.23 too. +* An XOVER, OVER, XHDR, HDR or LISTGROUP over several chunks of a group + could leave out records without any error: when another session's + request moved the group's index up meanwhile (articles far above, or a + group larger than the index's 10^7 numbers), the chunks that fell below + it printed nothing, and the list still ended with "." as if complete. + Those numbers come from the news server now. +* After the clock was put back (a VM whose clock was ahead until NTP + corrected it), the active list's time stamp lay in the future: the list + counted as fresh until the clock got there, and a refresh couldn't lower + the stamp, so new groups stayed invisible and LIST ACTIVE and NEWGROUPS + stayed as they were for as long as the clock had been ahead (unless + updatenews -a was run). A stamp still to come now counts as stale, and + the refresh replaces it. The same holds for the overview's per-chunk + stamps. Single groups were fixed in 1.3.23 already. +* With Options compress, a valid reply was discarded (the client got 403) + when more than 64 KiB of compressed data that inflates to nothing (empty + blocks, which zlib sends for repeated flushes) came before it. The limit + against a server that sends such blocks for ever is a time now: the + server's ReadTimeout (5 minutes with ReadTimeout 0) without any content, + as for a server that sends nothing. +* XOVER, OVER, XHDR, XPAT and HDR across a long stretch of article + numbers without articles (below the cached part of a group, as in a + binary group whose low number lags far behind its oldest article) + asked the news server for one range of 10000 numbers after the other, + and NEXT and LAST went one number after the other: 10^10 empty numbers + took a million requests, and the walk went on after the client had + left, since nothing was written that could fail. After 160000 empty + numbers in a row they now ask where the next (or previous) article + is, with LISTGROUP in growing steps as LISTGROUP itself does (about + 120 requests for 10^10 numbers). A connection the client reset (or a + pipe it closed in inetd mode) ends such a walk at once; otherwise it + gives up when it has found no article for 5 minutes (a client that + only closed its sending side may still read the reply). +* NEXT, above the cached part of a group, asked the news server once + for every number it passed. Looking up one number (NEXT, LAST, STAT) + now caches the rest of its range of 10000 numbers at once. Documentation: * SECURITY.md: how to report a vulnerability privately (GitHub Security - Advisories), which versions get security fixes, and the scope. -* Outdated text: the xdebug session in newscache.conf(5) is a current - one (201 greeting with the installed version, the entry's file: login, - PAMServicename); the - server Read entry there had a stray fragment and pointed to RFC 2980; - newscache.conf(5) and newscache.conf-dist said the second Timeouts - value controls fetching the newsgroup descriptions, which NewsCache - doesn't do (LIST NEWSGROUPS reads .newsgroups in the spool, made by - hand); newscache.conf-dist called the cached option "not yet - implemented" and didn't say that NiceClient has no effect. + Advisories, also through the GitHub API with gh api, for scripts and AI + agents), which versions get security fixes, the scope, and how + maintainers and collaborators (and their AI agents) coordinate embargoed + findings, which is not a reporting channel. +* Outdated text: the xdebug session in newscache.conf(5) is a current one + (201 greeting with the installed version, the entry's file: login, + PAMServicename); the server Read entry there had a stray fragment and + pointed to RFC 2980; newscache.conf(5) and newscache.conf-dist said the + second Timeouts value controls fetching the newsgroup descriptions, + which NewsCache doesn't do (LIST NEWSGROUPS reads .newsgroups in the + spool, made by hand); newscache.conf-dist called the cached option "not + yet implemented" and didn't say that NiceClient has no effect (it is + kept for compatibility, and commented out in the sample now). * The manual said that NewsCache uses the most specific AccessList entry that matches a client. It uses the first one, in the order of the file, as newscache.conf-dist says: put narrower entries before broader @@ -607,17 +1279,47 @@ Documentation: in a second NewsServerList inside the first one. It now has "allow read post" and one NewsServerList. * The man pages and the manual were compared with the code. Retries and - ReadTimeout are options of a Server entry, not general ones (at the - top level they are an error); ConnectTimeout, ConnectBackoff, + ReadTimeout are options of a Server entry, not general ones (at the top + level they are an error); ConnectTimeout, ConnectBackoff, LimitGroupSize, User, Password and dontgenmsgid have entries of their own in newscache.conf(5), and Hostname too. Its first example had - options in a Server entry that the parser refuses. Only - "Authentication unix" without fields requires a login; "allow - authentication" only lets a client connect so that it can log in. - Where no login can add a right, a command that needs it gets "500 - What?". newscache(8) lacked -n in its synopsis, updatenews(8) the + options in a Server entry that the parser refuses. Only "Authentication + unix" without fields requires a login; "allow authentication" only lets + a client connect so that it can log in. Where no login can add a right, + a command that needs it gets "502 access denied" (POST "440 posting not + permitted"). newscache(8) lacked -n in its synopsis, updatenews(8) the option -c, newscacheclean(8) -t and -v, and newscache.conf(5) named ConfigVersion 3 instead of 5. +* Explain that `PAMServicename` must name an installed service, a missing + service may fall back to the system's `other` policy depending on PAM + configuration, values are not quoted, and the `pam_unix` log hint may + not apply to failures from other modules. +* Clarify supported auth-file password formats, including the weak raw-MD5 + format and platform-dependent `crypt(3)` hashes. +* The manual's example "Options cached,semioffline" didn't parse (the + options are separated by blanks): it reads "Options cached semioffline". + The manual shows the package version (it said 0.99.13), describes + newscacheclean's per-article expiry instead of a plan for it, no longer + describes the removed configure flag --enable-notcached, and names the + source directories as they are. newscache(8) shows the sentence on + TLSCertFile and TLSKeyFile after SIGHUP, which troff swallowed. + newscache.conf(5) gives the defaults of LogStyle, ListenTo and Admin, + says that the configuration is read again on SIGHUP, that an empty + password field or one starting with * or ! locks the user, and how to + switch off a Commands entry; updatenews(8) says that updatenews ignores + offline and semioffline and uses a GroupTimeout of 60 seconds. +* README, FEDORA.md, debian/README.Debian and the sample configuration + now match the code: ReadTimeout and Retries are listed, dontgenmsgid is + in the sample file, the commands allowed before a login are complete, + and the Fedora package versions are current. +* The notes in doc/ on PAM, core dumps, stunnel and corrupt databases are + rewritten for the current parser, the systemd packages, built-in client + TLS and the connection close after a part-sent reply. +* newscache.conf(5) called a server's Read "wildmat patterns", but the + groups are routed by names that may end in * and start with !, with the + longest match winning: a * anywhere matches the rest of the name, and ? + and [...] are taken literally. The page and the manual say so now, with + an example of the longest match. Other changes: * CI: the macOS jobs (build and test, checkout on a case-insensitive @@ -629,10 +1331,97 @@ Other changes: * NewsCache builds on Debian GNU/Hurd: configure defines MAXPATHLEN (4096) and MAXHOSTNAMELEN (256) where the system has none, and the unit check cCorruptDB skips its file-limit case where RLIMIT_NOFILE - isn't enforced. (The e2e tests need Go, which the Hurd lacks.) -* The end-to-end tests use nntp-testkit 0.7.0 (still Go 1.26 or later). -* TestSpoolDiskFullDaemon no longer fails on a busy machine (its client - sat idle past ClientTimeout while the other client worked). + isn't enforced. cLockDowngrade skips its check that another process + can read: Hurd's fcntl keeps a write lock when a read lock is asked + for, so there the shared section that follows an exclusive one holds + the exclusive lock until it ends. (The e2e tests need Go, which the + Hurd lacks.) +* The end-to-end tests use nntp-testkit 0.12.0 (still Go 1.26 or later), + and its reader conformance checks also run over the TLS listener + (TLSListenTo), including the check that CAPABILITIES there doesn't + list STARTTLS. +* TestSpoolDiskFullDaemon wants every reply on the full disk within 5 + seconds again (they take at most 0.14 s, also with the race detector), + with the default ClientTimeout. Since #83 it allowed 180 s per reply + and ClientTimeout 600, so a lock held for nearly three minutes passed: + the second client's last XOVER fetched 10000 records again from the + test's own fake news server (20 s under -race), and the first client + idled that long. The group now ends in a small chunk of 11 records + that can't be kept either, so nothing slow is left in the measured + part; the first client's fill of the cache keeps its 180 s. +* TestSessionSigchldDefault no longer fails on a busy machine: the + session of the harness's readiness probe could still be running when + it counted the daemon's children. +* The PAM and client TLS end-to-end tests no longer fail when two test + runs share a machine: each PAM service they write to /etc/pam.d has a + name of its own (it was newscache-e2e-001 in every test, so one run + read the other's rules), and a TLS listener port taken before + newscache bound it is replaced by another one, as the tests already + did for the plain listener. +* GCC 15 with _FORTIFY_SOURCE (Fedora 43's rpm flags) no longer warns + that the client name lookup's read could overflow its buffer: the + loop's bound is explicit now. +* make check runs the Go end-to-end tests with a limit of 60 minutes + (E2E_TIMEOUT sets another). It had go test's default of 10 minutes, + and the suite takes 8 to 9 minutes on a machine with one core: make + check failed there with "test timed out after 10m0s". +* TestClientTLSStalledReaderTimesOutAndReleasesGroup measures the stalled + session again from a reply that comes from the spool: it counted how + fast the test's own fake news server served 40000 records, which under + the race detector took the session's end from 7.4 to 9.6 s, and its + bounds had been raised for that (ClientTimeout 3 to 6, then the end + bound from 11 to 14 s). With ClientTimeout 3 again the session ends + after about 4 s and the bounds are 6 s for the end and 2 s for the + second client's wait; the old defect (13 s) fails. +* TestClientStalledReader checks again that the session of a client + that stops reading in the middle of OVER or XOVER ends after one + ClientTimeout: it now fills the cache first, so that the reply comes + from the spool, and wants the session gone within 1.5 ClientTimeouts + of the request (3.0 to 3.3 s, also under -race). It only checked that + another client was still served, which since the records are written + with the group's lock released passed even when the session never + ended (3cefac9 reverted) or ended a ClientTimeout late (763126c + reverted: 6.0 s). +* TestXoverStalledClientDoesNotHoldGroupLock: the second client stores + one article after the other from the first client's XOVER until the + first client's session has ended, instead of storing one article after + a fixed 700 ms. On a slow machine the first session could still be + before its XOVER's records then, and the second client passed without + testing anything: with the lock held across the write and the session + one second late, the old test passed and this one fails. The first + session ends only when its send times out, so the stores cover the + whole time it is stalled, on every system that has /proc or pgrep. +* TestActiveRefreshBlocksGroup starts the waiting session's GROUP once + the news server has the refresh's LIST ACTIVE, instead of 300 ms after + the request. When the refresh began later than that, the GROUP ran + before it and passed without testing anything: with the lock held + across the fetch and the fetch half a second late, the old test + passed and this one fails. +* TestSigchldStress sends one SIGHUP after the stress and wants the good + configuration reread within a second: with a log file the reread line + (logged after 9 to 46 ms), and the first session after that line to get + its greeting; with syslog, whose lines it can't read, the 200 greeting + within a second of the SIGHUP. Since #170 it sent SIGHUP again and + dialled every 200 ms for up to 5 seconds, so a lost or late reread + passed: a daemon that only noticed SIGHUP with the next connection + passed the old test and fails this one. The config is still written to a + new file and renamed. +* TestCorruptDBFuzz fails again when no damaged session was closed in + the middle of a list. Its group has 201 records now, more than the 64 + formatted at a time, so damage past the first chunk is found after + part of a list went out (75 of the 150 damaged sessions). Since #274 + its 21 records were found damaged before anything was sent, and the + check had become a log line. +* TestDate checks again that the 501 for "DATE x" names DATE's syntax; + the check (it once named GROUP's) was dropped in a test clean-up. +* TestNewscachecleanEvictionOrder no longer fails on ZFS (FreeBSD CI): + it measured the files' allocated blocks before ZFS had written them + and set SpoolSize from the smaller numbers, so newscacheclean removed + every group. It syncs and measures until the numbers are stable. +* TestMaxConnectionsPerHost no longer fails when the harness's readiness + connection is still ending (seen on FreeBSD, where the test doesn't wait + for its process): its helper retried that only for MaxConnections' + "400 too many users". Each test now names the one refusal it retries. Release 1.3.22: Billy G. - 2026-10-23 diff --git a/changes/docs-manuals-review.md b/changes/docs-manuals-review.md deleted file mode 100644 index db640b58..00000000 --- a/changes/docs-manuals-review.md +++ /dev/null @@ -1,13 +0,0 @@ -Documentation: -* The manual's example "Options cached,semioffline" didn't parse (the - options are separated by blanks): it reads "Options cached semioffline". - The manual shows the package version (it said 0.99.13), describes - newscacheclean's per-article expiry instead of a plan for it, no longer - describes the removed configure flag --enable-notcached, and names the - source directories as they are. newscache(8) shows the sentence on - TLSCertFile and TLSKeyFile after SIGHUP, which troff swallowed. - newscache.conf(5) gives the defaults of LogStyle, ListenTo and Admin, - says that the configuration is read again on SIGHUP, that an empty - password field or one starting with * or ! locks the user, and how to - switch off a Commands entry; updatenews(8) says that updatenews ignores - offline and semioffline and uses a GroupTimeout of 60 seconds. diff --git a/changes/docs-niceclient.md b/changes/docs-niceclient.md deleted file mode 100644 index 1d4b5459..00000000 --- a/changes/docs-niceclient.md +++ /dev/null @@ -1,2 +0,0 @@ -Documentation: -* Document that `NiceClient` is retained for compatibility but ignored, and remove its active setting from the sample configuration. diff --git a/changes/docs-pam-service.md b/changes/docs-pam-service.md deleted file mode 100644 index ed115cd2..00000000 --- a/changes/docs-pam-service.md +++ /dev/null @@ -1,2 +0,0 @@ -Documentation: -* Explain that `PAMServicename` must name an installed service, a missing service may fall back to the system's `other` policy depending on PAM configuration, values are not quoted, and the `pam_unix` log hint may not apply to failures from other modules. diff --git a/changes/docs-repo-docs-review.md b/changes/docs-repo-docs-review.md deleted file mode 100644 index e817459c..00000000 --- a/changes/docs-repo-docs-review.md +++ /dev/null @@ -1,8 +0,0 @@ -Documentation: -* README, FEDORA.md, debian/README.Debian and the sample configuration - now match the code: ReadTimeout and Retries are listed, dontgenmsgid is - in the sample file, the commands allowed before a login are complete, - and the Fedora package versions are current. -* The notes in doc/ on PAM, core dumps, stunnel and corrupt databases are - rewritten for the current parser, the systemd packages, built-in client - TLS and the connection close after a part-sent reply. diff --git a/changes/docs-security-api-reports.md b/changes/docs-security-api-reports.md deleted file mode 100644 index b67496af..00000000 --- a/changes/docs-security-api-reports.md +++ /dev/null @@ -1,3 +0,0 @@ -Documentation: -* SECURITY.md: a private vulnerability report can also be submitted - through the GitHub API (gh api), for scripts and AI agents. diff --git a/changes/docs-security-collaborators.md b/changes/docs-security-collaborators.md deleted file mode 100644 index 45c5a04b..00000000 --- a/changes/docs-security-collaborators.md +++ /dev/null @@ -1,3 +0,0 @@ -Documentation: -* SECURITY.md: how maintainers and collaborators (and their AI agents) - coordinate embargoed findings, and that this is not a reporting channel. diff --git a/changes/docs-spool-dir-mode.md b/changes/docs-spool-dir-mode.md deleted file mode 100644 index 4c878bbb..00000000 --- a/changes/docs-spool-dir-mode.md +++ /dev/null @@ -1,9 +0,0 @@ -Upgrading: -* The spool holds the cached articles, the overview data and the posts - waiting to be sent, and NewsCache creates its files there readable - by others under the usual umask 022. Give the spool directory mode - 0750, owned by `Username` and `Groupname`, as the Debian package - does: `chmod 0750 /var/cache/newscache`. The manual, newscache.conf(5), - the sample configuration and FEDORA.md now say so. -* With `--without-syslog`, an existing log file keeps its mode; new ones - get 0640. `chmod 0640` the old one. diff --git a/changes/feat-client-tls-listeners.md b/changes/feat-client-tls-listeners.md deleted file mode 100644 index 936dbb46..00000000 --- a/changes/feat-client-tls-listeners.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* ListenTo (and TLSListenTo) with an IPv6 address such as [::1] failed on - a host without a global IPv6 address, a container for example: - getaddrinfo was asked for AI_ADDRCONFIG, which ignores loopback - addresses. The listen address is numeric and is now used as given. -* The listening sockets queued at most 4 connections that weren't - accepted yet; a burst of clients overflowed that, and FreeBSD reset - the extra connections. The queue now holds 128 (MaxConnections still - limits the sessions). diff --git a/changes/feat-client-tls-upstream-interrupt.md b/changes/feat-client-tls-upstream-interrupt.md deleted file mode 100644 index 4dc676a0..00000000 --- a/changes/feat-client-tls-upstream-interrupt.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* TLS connections to upstream servers: a read or write interrupted by - SIGTERM or the alarm was retried, so a session waiting for an upstream - TLS server ended only when the server answered; now it ends at once, - as with a plain connection. diff --git a/changes/feat-client-tls.md b/changes/feat-client-tls.md deleted file mode 100644 index e29c7b1c..00000000 --- a/changes/feat-client-tls.md +++ /dev/null @@ -1,13 +0,0 @@ -New options: -* TLS for clients (implicit TLS, RFC 8143; through GnuTLS). TLSListenTo - opens a second listening socket (same form as ListenTo, default port - 563) next to the plain one, with TLSCertFile (PEM chain), TLSKeyFile - and optionally TLSPriority (a GnuTLS priority string; a warning when it - allows TLS 1.0 or 1.1). The certificate and key are loaded before - newscache switches to Username, checked by newscache -p, and loaded - again on SIGHUP (the old ones stay if that fails). The handshake must be - done within ClientTimeout, at most 30 seconds also with ClientTimeout 0. - newscache -t is inetd mode with TLS on the passed socket. An AccessList - entry with "AuthRequiresTLS yes" answers AUTHINFO on a plain connection - with 483 and lists AUTHINFO without USER in CAPABILITIES (RFC 4643). - STARTTLS for clients is not offered. newscache -o lists --with-gnutls. diff --git a/changes/feat-compress-upstream.md b/changes/feat-compress-upstream.md deleted file mode 100644 index 5cdaf1ed..00000000 --- a/changes/feat-compress-upstream.md +++ /dev/null @@ -1,14 +0,0 @@ -New options: - -* Server option "Options compress": COMPRESS DEFLATE (RFC 8054) to the - news server. After STARTTLS, the login and MODE READER, NewsCache - asks the server to compress the connection; from its 206 on, - everything is compressed both ways, so articles, overview data and - the active list come in a fraction of their size. A server that - refuses it, or doesn't know COMPRESS, is used without compression - (a notice is logged); invalid compressed data closes the connection. - The login is never compressed: when the server asks for it again - (480), NewsCache opens a new connection. It needs zlib: configure - finds it (--with-zlib requires it, --without-zlib leaves it out), and - "newscache -o" lists --with-zlib. zlib's development files are a new - optional build dependency (zlib1g-dev, zlib-devel). diff --git a/changes/fix-accept-error-backoff.md b/changes/fix-accept-error-backoff.md deleted file mode 100644 index 5791526c..00000000 --- a/changes/fix-accept-error-backoff.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* When accept() failed because the daemon had run out of file - descriptors or memory (EMFILE, ENFILE, ENOBUFS, ENOMEM), it retried at - once, without pause: it used a whole CPU and logged "accept failed" - for every try. It now logs the failure once, waits a second between - tries (a signal still acts at once) and logs again after an accept - that worked. diff --git a/changes/fix-active-refresh-complete.md b/changes/fix-active-refresh-complete.md deleted file mode 100644 index 823a5cfa..00000000 --- a/changes/fix-active-refresh-complete.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* The first fetch of the active list (the list of groups) on a new spool, - from several news servers or with several Read patterns, no longer gives - other sessions a partial list while it runs: they wait for it. If NewsCache - was stopped during that first fetch, the next session fetches the list - again; before, the part already fetched was served as complete until the - list timed out (Timeouts). diff --git a/changes/fix-active-refresh-lock.md b/changes/fix-active-refresh-lock.md deleted file mode 100644 index bccdb004..00000000 --- a/changes/fix-active-refresh-lock.md +++ /dev/null @@ -1,19 +0,0 @@ -Bug fixes: -* A client's LIST ACTIVE (or GROUP, when it needs the group's entry) that - found the active list stale held the list's exclusive lock while NewsCache - fetched the list from the news servers, so every other session's GROUP - waited for the news server - up to the whole-reply limit of 5 minutes per - server. The list is now fetched without the database's lock and stored - afterwards: a fetch that fails midway (reply limit, deadline) leaves the - stored list as it was, while a reply cut off in the middle still stores the - lines that were read, as before. A second lock in the spool - (.active.refresh) makes sure only one session fetches the list at a time: a - session that finds another one fetching serves the list it has, and only a - session with no list at all (first start, a damaged .active64) or - updatenews -a waits for the fetch to finish. Meanwhile a group that is new - on the news server is unknown (411) until that fetch is done. A session or - updatenews stopped with SIGTERM or SIGINT while it waits for another - one's fetch ends at once; it waited for that fetch to finish. A session - stopped in the middle of its own fetch no longer marks the news servers - as failed, which made the other sessions serve the old (or an empty) - list for up to a minute. diff --git a/changes/fix-active-refresh-test-wait.md b/changes/fix-active-refresh-test-wait.md deleted file mode 100644 index 3247adda..00000000 --- a/changes/fix-active-refresh-test-wait.md +++ /dev/null @@ -1,7 +0,0 @@ -Other changes: -* TestActiveRefreshBlocksGroup starts the waiting session's GROUP once - the news server has the refresh's LIST ACTIVE, instead of 300 ms after - the request. When the refresh began later than that, the GROUP ran - before it and passed without testing anything: with the lock held - across the fetch and the fetch half a second late, the old test - passed and this one fails. diff --git a/changes/fix-active-stale-numbers.md b/changes/fix-active-stale-numbers.md deleted file mode 100644 index b5f3b363..00000000 --- a/changes/fix-active-stale-numbers.md +++ /dev/null @@ -1,10 +0,0 @@ -Bug fixes: -* A group's last article number could go back: an active list that was - still being read when another session's GROUP stored newer numbers put - the list's older ones back (as did a GROUP reply stored after a newer - one). For up to GroupTimeout, GROUP then showed the old last number, - and the overview records and articles above it that had been cached - were thrown away. A group's numbers now carry the time they were asked - for, and older numbers no longer replace newer ones (in the same - second, the higher last number stays). The list's posting flag is still - taken over. diff --git a/changes/fix-active-stamp-future.md b/changes/fix-active-stamp-future.md deleted file mode 100644 index a8d6eb4d..00000000 --- a/changes/fix-active-stamp-future.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* After the clock was put back (a VM whose clock was ahead until NTP - corrected it), the active list's time stamp lay in the future: the list - counted as fresh until the clock got there, and a refresh couldn't lower - the stamp, so new groups stayed invisible and LIST ACTIVE and NEWGROUPS - stayed as they were for as long as the clock had been ahead (unless - updatenews -a was run). A stamp still to come now counts as stale, and - the refresh replaces it. The same holds for the overview's per-chunk - stamps. Single groups were fixed in 1.3.23 already. diff --git a/changes/fix-activedb-record-size.md b/changes/fix-activedb-record-size.md deleted file mode 100644 index f8beeffa..00000000 --- a/changes/fix-activedb-record-size.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A damaged record in the active database that was a few bytes longer - than a group entry (554 to 560 bytes) was not recognised as damage: - GROUP and the other commands for that group failed with an error - until the file was removed by hand. The file is now moved aside and - rebuilt, as for any other damaged record. diff --git a/changes/fix-article-body-bare-cr.md b/changes/fix-article-body-bare-cr.md deleted file mode 100644 index c8ada0b3..00000000 --- a/changes/fix-article-body-bare-cr.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A CR outside CRLF in the body of an article from a news server - becomes a space, as one in the head already did: when the article is - read from the server, and when an article that an older version - stored is sent. A lone CR went to clients inside ARTICLE and BODY; a - reader that ends a line at a CR saw the article end early and status - lines chosen by the news server. diff --git a/changes/fix-article-body-lf.md b/changes/fix-article-body-lf.md deleted file mode 100644 index 2532f3a0..00000000 --- a/changes/fix-article-body-lf.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* An article with bare LF line ends, written as its body only, started - with an extra empty line and ended with a stray NUL byte. The body is - now written as it is. diff --git a/changes/fix-article-ctext-init.md b/changes/fix-article-ctext-init.md deleted file mode 100644 index 54b72d60..00000000 --- a/changes/fix-article-ctext-init.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* An Article object that had not read or been given a text yet pointed - at uninitialised memory when asked for its text. No code path did - that, but a failed read (out of memory) could leave the same - dangling pointer. The text pointer is now set in every constructor - and when a read fails. diff --git a/changes/fix-artspool-fsync.md b/changes/fix-artspool-fsync.md deleted file mode 100644 index d562e7c9..00000000 --- a/changes/fix-artspool-fsync.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* After a power cut or a crash, an article that a client had POSTed - while the news server was unreachable ("240 Article posted") could be - an empty file in the outgoing spool, and updatenews moved it to - .badArticles: the post was lost. The article is now written to disk - (and the directory synced) before the client gets the 240. A - temporary file left in the outgoing spool by a crash is now removed - by updatenews. diff --git a/changes/fix-artspool-next-exception.md b/changes/fix-artspool-next-exception.md deleted file mode 100644 index de640f32..00000000 --- a/changes/fix-artspool-next-exception.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A spooled article that updatenews could not read (one too big for the - memory) ended the posting run with the lock of the outgoing spool - still held: until updatenews ended, every session that spooled a POST - while the news server was down waited, and the article, read first, - stopped every later run as well. It is now moved to .badArticles, with - a line in the log, and the next spooled article is posted. diff --git a/changes/fix-auth-failure-backoff.md b/changes/fix-auth-failure-backoff.md deleted file mode 100644 index e572bd94..00000000 --- a/changes/fix-auth-failure-backoff.md +++ /dev/null @@ -1,31 +0,0 @@ -Upgrading: -* Logins with a user name or password shorter than 10 bytes are refused - (481) after the upgrade: the new option AuthMinLength defaults to 10. - Give such users longer names and passwords, or set "AuthMinLength 0" - to keep them. The sample auth file and the examples in the - documentation now use names and passwords of at least 10 bytes. - -Behaviour changes: -* A failed login (AUTHINFO PASS) is answered with 481 after 1 second the - first time in a connection, after 2 seconds the second time and after - 4 seconds the third time; then the connection is closed, as before. A - successful login is answered at once. The count is per connection, so - a client that connects again starts at 1 second. AuthFailureDelay - keeps its name: 0 turns the wait off, any other value (1 to 3600, as - in older configuration files) turns it on; the default is 1, on. Up to - 1.3.22 the wait was AuthFailureDelay times the number of failures (15, - 30 and 45 s by default). -* A login with an unknown user, a locked or empty password field, or a - plain-text password field (--enable-plainpass) no longer does a dummy - password hash to take as long as a wrong password, so bots guessing - logins cost no CPU time for it. The time of a 481 may now tell whether - a user name exists. - -New options: -* AuthMinLength bytes (default 10, 0 to 255, 0 turns it off): a user name - or password shorter than this is refused with 481 when AUTHINFO PASS - arrives, after the wait of AuthFailureDelay and without a password - check, a lookup or a PAM call. It counts as a failed login. AUTHINFO - USER still answers 381. The log says "failed authinfo for user ... - (user name shorter than AuthMinLength)" or "(password shorter than - AuthMinLength)", without the password. newscache -p prints it. diff --git a/changes/fix-auth-file-symlink-warning.md b/changes/fix-auth-file-symlink-warning.md deleted file mode 100644 index 10572894..00000000 --- a/changes/fix-auth-file-symlink-warning.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* The warning about an unsafe `Authentication file` no longer fires for every symbolic link. It now follows the link and warns, under the configured path, when the target is group- or world-writable (it used to miss that), and warns once when the file or the link target cannot be inspected. Each configured path is reported once, at startup and after a reload. diff --git a/changes/fix-auth-unknown-user-timing.md b/changes/fix-auth-unknown-user-timing.md deleted file mode 100644 index 0c7ab901..00000000 --- a/changes/fix-auth-unknown-user-timing.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* A login with an unknown user (or a locked line) in `Authentication file` or `Authentication unix` is no longer answered faster than one with a wrong password. A dummy hash check takes the same time, so the time of the reply no longer tells which user names exist. diff --git a/changes/fix-bind-error-reason.md b/changes/fix-bind-error-reason.md deleted file mode 100644 index a94116ad..00000000 --- a/changes/fix-bind-error-reason.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* When a listener cannot bind, the final error on stderr and in the log - now includes the system error, such as "Address already in use". diff --git a/changes/fix-bindfrom-len.md b/changes/fix-bindfrom-len.md deleted file mode 100644 index 30fe64df..00000000 --- a/changes/fix-bindfrom-len.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* On FreeBSD and macOS a news server with BindFrom could not be reached - ("Unable to bind to outgoing address"): bind() was given the size of - a whole sockaddr_storage as the address length. It now gets the - length of the address (IPv4 or IPv6). diff --git a/changes/fix-capabilities-list-extensions.md b/changes/fix-capabilities-list-extensions.md deleted file mode 100644 index 389fac6e..00000000 --- a/changes/fix-capabilities-list-extensions.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* CAPABILITIES now advertises LIST EXTENSIONS, which the client already - implements. diff --git a/changes/fix-clean-art-without-db.md b/changes/fix-clean-art-without-db.md deleted file mode 100644 index 1f433b9c..00000000 --- a/changes/fix-clean-art-without-db.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* newscacheclean neither counted nor removed article files in a group - directory without a database (left when the database was removed while - a session still had it open and stored an article, or moved aside as - corrupt on a full disk). No session can reach them, but they stayed - outside SpoolSize until a session opened the group again. They are - removed first now, unless a session has started a new database in the - directory meanwhile; a file a session stores there while one is being - removed is kept. diff --git a/changes/fix-clean-eviction-test-blocks.md b/changes/fix-clean-eviction-test-blocks.md deleted file mode 100644 index 6270d4d5..00000000 --- a/changes/fix-clean-eviction-test-blocks.md +++ /dev/null @@ -1,5 +0,0 @@ -Other changes: -* TestNewscachecleanEvictionOrder no longer fails on ZFS (FreeBSD CI): - it measured the files' allocated blocks before ZFS had written them - and set SpoolSize from the smaller numbers, so newscacheclean removed - every group. It syncs and measures until the numbers are stable. diff --git a/changes/fix-clean-rmdir-race.md b/changes/fix-clean-rmdir-race.md deleted file mode 100644 index 80a07baa..00000000 --- a/changes/fix-clean-rmdir-race.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A client could get "403" for a command that opened a group at the - moment newscacheclean removed that group's directory (after its - database): the session had made sure the directory was there, and - then found it gone when it created the database. The session now - makes the directory again and creates the database. diff --git a/changes/fix-clean-stale-scan.md b/changes/fix-clean-stale-scan.md deleted file mode 100644 index 0a43bd15..00000000 --- a/changes/fix-clean-stale-scan.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* newscacheclean no longer removes a big article's file that a session - stored while the cleaner was reading the group's directory: it took the - file for one outside the group's range and removed it at the end of the - run, even when the spool was below SpoolSize. Nor does it remove a file - that was replaced under the same name since the scan. diff --git a/changes/fix-clean-unlink-replaced.md b/changes/fix-clean-unlink-replaced.md deleted file mode 100644 index 1d090f33..00000000 --- a/changes/fix-clean-unlink-replaced.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* newscacheclean could remove an article file that a session had just - stored again under the same name, or a group database that a session - had just started anew after moving a damaged one aside: it checked - that the file was still the one it had scanned, but without a lock, - and a session could put the new file there before the unlink. The - check and the unlink are now done under the lock that the session - takes for that change. diff --git a/changes/fix-client-dns-timer.md b/changes/fix-client-dns-timer.md deleted file mode 100644 index 57331d23..00000000 --- a/changes/fix-client-dns-timer.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* The lookup of a client's host name ran before the greeting, with no - time limit: a client whose reverse DNS zone doesn't answer kept a - session, one of MaxConnections, for the resolver's timeouts (a minute - and more). The lookup now takes at most 10 seconds (or ClientTimeout, - if that is shorter); after that the client goes by its address, and - the log says so. diff --git a/changes/fix-compress-idle-limit.md b/changes/fix-compress-idle-limit.md deleted file mode 100644 index 866851d9..00000000 --- a/changes/fix-compress-idle-limit.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* With Options compress, a valid reply was discarded (the client got 403) - when more than 64 KiB of compressed data that inflates to nothing (empty - blocks, which zlib sends for repeated flushes) came before it. The limit - against a server that sends such blocks for ever is a time now: the - server's ReadTimeout (5 minutes with ReadTimeout 0) without any content, - as for a server that sends nothing. diff --git a/changes/fix-config-directory-message.md b/changes/fix-config-directory-message.md deleted file mode 100644 index d53fb108..00000000 --- a/changes/fix-config-directory-message.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* A configuration path that is a directory is now reported as "cannot open configuration file : Is a directory" instead of "unexpected EOF". diff --git a/changes/fix-connect-half-open.md b/changes/fix-connect-half-open.md deleted file mode 100644 index 03e8af7a..00000000 --- a/changes/fix-connect-half-open.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* With "Options starttls", a reply shorter than a status code to MODE - READER, STARTTLS or LIST OVERVIEW.FMT (which anyone in the middle can - send), or a refused login, left the half set-up connection to the news - server open. The next command went out on it in plain text, without - STARTTLS or the login, and a 480 to that command made NewsCache send - User and Password in plain text. Such a connection is now closed, and - the next command connects again. diff --git a/changes/fix-connect-timeout-default.md b/changes/fix-connect-timeout-default.md deleted file mode 100644 index 81987564..00000000 --- a/changes/fix-connect-timeout-default.md +++ /dev/null @@ -1,8 +0,0 @@ -Behaviour changes: -* ConnectTimeout defaults to 30 seconds. It was 0, which leaves the - connect to the system: a news server that doesn't answer (a firewall - that drops the packets, a dead route) held each command that needed - it about two minutes per address of the server, with no reply to the - client, and the next command waited again. ConnectTimeout 0 keeps the - old behaviour. ConnectBackoff stays 0; the manual now says that its - time counts from the start of the failed attempt. diff --git a/changes/fix-corrupt-bad-alloc.md b/changes/fix-corrupt-bad-alloc.md deleted file mode 100644 index bc8d788b..00000000 --- a/changes/fix-corrupt-bad-alloc.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* When a damaged database was moved aside and the new one could not be - started because memory ran out, the lock on the spool directory - stayed held until the process ended, and other processes that had to - move a damaged database aside waited for it. The lock is released - and the database is started again at the next use. diff --git a/changes/fix-corrupt-fuzz-midlist.md b/changes/fix-corrupt-fuzz-midlist.md deleted file mode 100644 index accfd359..00000000 --- a/changes/fix-corrupt-fuzz-midlist.md +++ /dev/null @@ -1,7 +0,0 @@ -Other changes: -* TestCorruptDBFuzz fails again when no damaged session was closed in - the middle of a list. Its group has 201 records now, more than the 64 - formatted at a time, so damage past the first chunk is found after - part of a list went out (75 of the 150 damaged sessions). Since #274 - its 21 records were found damaged before anything was sent, and the - check had become a log line. diff --git a/changes/fix-crypt-hash-advice.md b/changes/fix-crypt-hash-advice.md deleted file mode 100644 index d628974b..00000000 --- a/changes/fix-crypt-hash-advice.md +++ /dev/null @@ -1,2 +0,0 @@ -Documentation: -* Remove the unused crypt helper and clarify supported auth-file password formats, including the weak raw-MD5 format and platform-dependent `crypt(3)` hashes. diff --git a/changes/fix-ctype-unsigned-char.md b/changes/fix-ctype-unsigned-char.md deleted file mode 100644 index d46d0a8c..00000000 --- a/changes/fix-ctype-unsigned-char.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* Bytes of 0x80 and above in client commands, newsgroup names and the - configuration file are passed to the C character class functions as - unsigned char. As plain (signed) char they were negative values, - undefined for those functions, and read outside the table on C - libraries that index it directly. diff --git a/changes/fix-cut-off-article-file.md b/changes/fix-cut-off-article-file.md deleted file mode 100644 index 62b6d3ba..00000000 --- a/changes/fix-cut-off-article-file.md +++ /dev/null @@ -1,18 +0,0 @@ -Bug fixes: -* An article over 15 kB is stored in a file of its own. NewsCache wrote - it in place: a crash or power cut could leave the file cut off, and - NewsCache then served it without its last partial line and without a - word; a write that failed (a full disk) removed the copy that was - there. Now the file is written under a temporary name (.art.tmp), - flushed to the disk (fsync) and renamed, and the directory is flushed - too, before the article counts as stored: the file is either whole or - the old one. A cut-off file from an older version, whose last line has - no line end or that has no empty line after the header, is fetched - again from the news server and written anew. If the news server - doesn't have the article any more, the stored copy is served as it is - and the log says so; the file is kept (one cut before its Message-ID - header can't be served and is removed, as before). (A file cut right - after a line end in the body can't be told from a whole one.) Complete - files with LF line ends (as older versions or an admin may have - written them) are served as before. newscacheclean counts a .tmp file - that a crash left behind as an article file and removes it by its age. diff --git a/changes/fix-daemon-start-errors.md b/changes/fix-daemon-start-errors.md deleted file mode 100644 index e240357d..00000000 --- a/changes/fix-daemon-start-errors.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* Started without -n, newscache forked and its parent exited with status - 0 at once. If the daemon then could not listen (port in use) or drop - its privileges, it said so only on a standard error already pointed - at /dev/null: the start command reported success and no daemon ran. - The parent now waits until the daemon listens; if the daemon ends - before that, it exits with status 1 and the daemon's message is shown - on the terminal. diff --git a/changes/fix-date-syntax-test.md b/changes/fix-date-syntax-test.md deleted file mode 100644 index 62803a05..00000000 --- a/changes/fix-date-syntax-test.md +++ /dev/null @@ -1,3 +0,0 @@ -Other changes: -* TestDate checks again that the 501 for "DATE x" names DATE's syntax; - the check (it once named GROUP's) was dropped in a test clean-up. diff --git a/changes/fix-dropbad-revalidate.md b/changes/fix-dropbad-revalidate.md deleted file mode 100644 index af4d3481..00000000 --- a/changes/fix-dropbad-revalidate.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* A stored article that can't be read is removed from the cache, so that - it is fetched again. When another session had just stored a good copy of - that article, the good copy could be removed instead (and was fetched - again on the next request). Now only the unreadable copy is removed. diff --git a/changes/fix-e2e-run-timeout.md b/changes/fix-e2e-run-timeout.md deleted file mode 100644 index 6d1f99c4..00000000 --- a/changes/fix-e2e-run-timeout.md +++ /dev/null @@ -1,6 +0,0 @@ -Other changes: - -* make check runs the Go end-to-end tests with a limit of 60 minutes - (E2E_TIMEOUT sets another). It had go test's default of 10 minutes, - and the suite takes 8 to 9 minutes on a machine with one core: make - check failed there with "test timed out after 10m0s". diff --git a/changes/fix-e2e-tls-listen-retry.md b/changes/fix-e2e-tls-listen-retry.md deleted file mode 100644 index a372451b..00000000 --- a/changes/fix-e2e-tls-listen-retry.md +++ /dev/null @@ -1,4 +0,0 @@ -Other changes: -* The client TLS end-to-end tests pick another port for the TLS listener - when theirs was taken before newscache bound it (by another test run - on the machine), as the tests already did for the plain listener. diff --git a/changes/fix-empty-range-walk.md b/changes/fix-empty-range-walk.md deleted file mode 100644 index 06444d69..00000000 --- a/changes/fix-empty-range-walk.md +++ /dev/null @@ -1,23 +0,0 @@ -Bug fixes: -* XOVER, OVER, XHDR, XPAT and HDR across a long stretch of article - numbers without articles (below the cached part of a group, as in a - binary group whose low number lags far behind its oldest article) - asked the news server for one range of 10000 numbers after the other, - and NEXT and LAST went one number after the other: 10^10 empty numbers - took a million requests, and the walk went on after the client had - left, since nothing was written that could fail. After 160000 empty - numbers in a row they now ask where the next (or previous) article - is, with LISTGROUP in growing steps as LISTGROUP itself does (about - 120 requests for 10^10 numbers). A connection the client reset (or a - pipe it closed in inetd mode) ends such a walk at once; otherwise it - gives up when it has found no article for 5 minutes (a client that - only closed its sending side may still read the reply). -* NEXT, above the cached part of a group, asked the news server once - for every number it passed. Looking up one number (NEXT, LAST, STAT) - now caches the rest of its range of 10000 numbers at once. - -Behaviour changes: -* A walk that gives up after 5 minutes without an article answers 403; - after part of a list the connection is closed, as after other upstream - failures. NEXT and LAST answer 403 then, instead of running until they - find an article. diff --git a/changes/fix-filelog-sighup-reopen.md b/changes/fix-filelog-sighup-reopen.md deleted file mode 100644 index 97c2c702..00000000 --- a/changes/fix-filelog-sighup-reopen.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* Built with --without-syslog, the daemon wrote into its log file until - it ended: after log rotation renamed newscache.log, it and every new - session went on writing into the renamed file, so only copytruncate - (which loses lines) worked. On SIGHUP the daemon now opens - newscache.log again; sessions started afterwards write to the new - file, running ones to the old one until they end. newscache.conf(5) - and the manual have a logrotate example. diff --git a/changes/fix-freshen-lock-hold.md b/changes/fix-freshen-lock-hold.md deleted file mode 100644 index e960eda6..00000000 --- a/changes/fix-freshen-lock-hold.md +++ /dev/null @@ -1,20 +0,0 @@ -Bug fixes: -* A client's XOVER, OVER, XHDR or HDR on a range of a group that - NewsCache hadn't synchronized yet (or not within GroupTimeout) held the - group's exclusive lock while it asked the news server for the group's - numbers, the article list and the overview records. Every other session - that read that group, even an article already in the spool, waited for - the news server: up to 2 minutes per 10000 article numbers, longer with - a server that sends slowly. The news server is now asked without the - lock, and the records are stored afterwards under a short one. A new - lock file in the spool (.fetch.lock, no data in it) still lets only one - session fetch a range at a time: a second session that wants the same - range waits for the first one and serves what it stored, instead of - asking the news server again. -* updatenews -g held the group's lock while it asked the news server for - the article list and each article, so clients reading the group waited - for it (with -l, for the whole prefetch of each 10000 numbers). It now - locks the group only while it stores or removes an article. With -l a - range is still reserved for the prefetch while it runs: sessions that - need its overview wait for the prefetch instead of fetching it too, but - sessions reading what the spool holds no longer wait. diff --git a/changes/fix-getarticle-lock-fetch.md b/changes/fix-getarticle-lock-fetch.md deleted file mode 100644 index eece319f..00000000 --- a/changes/fix-getarticle-lock-fetch.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* Fetching an article from the news server held the group's shared lock for - the whole fetch (bounded by ReadTimeout, 300 seconds by default), so every - session that needed to store an article or an overview record for that group - waited for the news server. The article is now fetched with the lock - released and stored afterwards; an article that another session stored, or a - group that was resized, meanwhile is handled when the article is stored. diff --git a/changes/fix-gnutls-explicit.md b/changes/fix-gnutls-explicit.md deleted file mode 100644 index 2ad96788..00000000 --- a/changes/fix-gnutls-explicit.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* configure --with-gnutls now fails when the GnuTLS library or headers - are missing, instead of silently building without TLS. With no explicit - option GnuTLS remains optional, and a missing dependency is warned about. diff --git a/changes/fix-goodbye-alarm-order.md b/changes/fix-goodbye-alarm-order.md deleted file mode 100644 index 42290366..00000000 --- a/changes/fix-goodbye-alarm-order.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* A daemon session (not one started by inetd) stopped with SIGTERM or - SIGINT while a command ran, for example while it waited for the news - server, sent neither that command's reply nor "400 ... service - discontinued": the signal made the send fail, and the log said "can't - be written to, session ended". A client whose post had gone to the - spool got no 240 and could post it again. Now the reply and the 400 go - out, with two seconds for both. diff --git a/changes/fix-group-keeps-active-flag.md b/changes/fix-group-keeps-active-flag.md deleted file mode 100644 index 3b7669a4..00000000 --- a/changes/fix-group-keeps-active-flag.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* A GROUP that gets a group's numbers from the news server no longer sets - the group's posting flag in the active list to "y". A moderated ("m") or - read-only ("n") group was listed as open for posting by LIST ACTIVE and - NEWGROUPS until the active list was fetched again. diff --git a/changes/fix-group-name-check.md b/changes/fix-group-name-check.md deleted file mode 100644 index c718fd22..00000000 --- a/changes/fix-group-name-check.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* Group names with a "/" or an empty component (a/b, a.b., .a.b, a..b) - had the spool directory of a.b: when a news server answered GROUP for - such a name, its overview records and articles went into a.b's - database, and readers of a.b got them; such a name also got past an - exact "!a.b" in a list. They aren't newsgroup names (RFC 5536 3.1.4): - GROUP and LISTGROUP answer 411 for them now, and the spool refuses - them. diff --git a/changes/fix-header-unfold-whitespace.md b/changes/fix-header-unfold-whitespace.md deleted file mode 100644 index 980dc148..00000000 --- a/changes/fix-header-unfold-whitespace.md +++ /dev/null @@ -1,11 +0,0 @@ -Bug fixes: -* A folded header was unfolded with one space in place of the line - break and the white space around it, so "Subject: foo " followed by - "bar" read "foo bar" where the news server's overview says - "foo bar" (RFC 5322 2.2.3 removes only the line break; RFC 3977 then - turns each TAB into a space). A group's OVER line changed once the - article was in the spool, and HDR, XHDR and XPAT of the article - disagreed with the news server. Unfolding now keeps the white space as - it is. HDR, XHDR and XPAT also turn a TAB in a header into a space, as - OVER does (RFC 3977 8.5.2); for an article in the spool, and by - message-ID, they sent it unchanged. diff --git a/changes/fix-headerlog-open.md b/changes/fix-headerlog-open.md deleted file mode 100644 index 07482b6e..00000000 --- a/changes/fix-headerlog-open.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* When header logging is enabled, failures to open `.headerlog` are now logged instead of silently dropping the header. diff --git a/changes/fix-help-syntax.md b/changes/fix-help-syntax.md deleted file mode 100644 index 40a06570..00000000 --- a/changes/fix-help-syntax.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* HELP showed a wildmat argument for NEWGROUPS, which the command - rejects with 501, and a time argument for LIST ACTIVE.TIMES, which - takes a wildmat. HELP and the 501 syntax reply now show what the - commands accept; AUTHINFO, MODE and XDEBUG are listed completely. diff --git a/changes/fix-history-batch-dtor.md b/changes/fix-history-batch-dtor.md deleted file mode 100644 index 2405941a..00000000 --- a/changes/fix-history-batch-dtor.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* When memory ran out while a session applied its message-ID history - updates at the end of an overview reply or a stored chunk, the session - ended with SIGABRT and a core dump (an exception left a destructor) - instead of the error reply other failures get. The updates are dropped - now, with a log message; the history is an index, and a missing entry - only costs a lookup. diff --git a/changes/fix-history-note-preserve.md b/changes/fix-history-note-preserve.md deleted file mode 100644 index 216ce38f..00000000 --- a/changes/fix-history-note-preserve.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* Reading an older cached copy of an article no longer replaces the history - location of another copy in the same group. This keeps the surviving copy - findable by message-ID when the older one is removed from the spool. diff --git a/changes/fix-history-prune-revalidate.md b/changes/fix-history-prune-revalidate.md deleted file mode 100644 index ac8438f2..00000000 --- a/changes/fix-history-prune-revalidate.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* When newscacheclean prunes history for a group whose spool database is - gone, it no longer removes a location that another session has updated or - whose group has since been recreated. Losing that location made a - message-ID lookup go to the news server instead of finding the cached - article (the article was still in the spool; only the lookup by - message-ID missed it). diff --git a/changes/fix-history-remove-number.md b/changes/fix-history-remove-number.md deleted file mode 100644 index c0e3360e..00000000 --- a/changes/fix-history-remove-number.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* When a group has an article under a new number, removing an old spool - record or a stale history location no longer removes the new number from - history. The cached article remains findable by message-ID instead of - requiring a fetch from the news server. diff --git a/changes/fix-history-shard-retry.md b/changes/fix-history-shard-retry.md deleted file mode 100644 index 907f59ef..00000000 --- a/changes/fix-history-shard-retry.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* One failure to open a history shard (too many open files, no space - left while the file was created) switched the history off for that - shard until the session ended: ARTICLE went to the news - server and the stored locations went stale. The shard is now tried - again after a few seconds. diff --git a/changes/fix-hurd-downgrade-check.md b/changes/fix-hurd-downgrade-check.md deleted file mode 100644 index 0be06dc4..00000000 --- a/changes/fix-hurd-downgrade-check.md +++ /dev/null @@ -1,5 +0,0 @@ -Other changes: -* The unit check cLockDowngrade passes on GNU/Hurd. Hurd's fcntl keeps a - write lock when a read lock is asked for, so there the check that - another process can read the file is skipped; the shared section that - follows an exclusive one holds the exclusive lock until it ends. diff --git a/changes/fix-inetd-client-addr.md b/changes/fix-inetd-client-addr.md deleted file mode 100644 index 4ce5bddc..00000000 --- a/changes/fix-inetd-client-addr.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* In inetd mode (`-i`) and when the peer address cannot be read, the client address handed to PAM as `PAM_RHOST` was uninitialised stack memory. It is now empty, so PAM gets no remote host. diff --git a/changes/fix-inetd-sigint-window.md b/changes/fix-inetd-sigint-window.md deleted file mode 100644 index 10f61e80..00000000 --- a/changes/fix-inetd-sigint-window.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* An inetd session (newscache -i) that gets SIGINT or SIGTERM between two - commands ends at once with "400 ... service discontinued"; it waited for - the client's next line. Reads inside a command, such as the article of a - POST, now also give up after ClientTimeout plus 10 seconds in inetd - mode, as they do in the daemon; a stalled POST kept the session forever. diff --git a/changes/fix-list-active-filter.md b/changes/fix-list-active-filter.md deleted file mode 100644 index 72db79e8..00000000 --- a/changes/fix-list-active-filter.md +++ /dev/null @@ -1,14 +0,0 @@ -Bug fixes: -* With several news servers, the active list could take a group from a - server it isn't routed to. NewsCache asks each server for "LIST ACTIVE - " per pattern of its Read; the filter for that reply let every - group through except those it matched against the other servers' - patterns, and that comparison lost its place after a partial match. With - one server reading "dk.*,de.alt.binaries.*" and another "de.*", the - second server's numbers and posting flag for de.alt.binaries.* replaced - the first's, GROUP and LIST ACTIVE showed them, and the cached records - above a lower last number were dropped at each refresh. Also, a group - that another server's Read excludes ("!de.sub.special.*") could be - missing from the active list, and a group that two servers read with - the same pattern came with the second server's numbers. Each server's - reply now keeps only the groups that GROUP takes from that server. diff --git a/changes/fix-list-reply-copy.md b/changes/fix-list-reply-copy.md deleted file mode 100644 index 0ef7a315..00000000 --- a/changes/fix-list-reply-copy.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: - -* LIST ACTIVE, LIST ACTIVE.TIMES and NEWGROUPS collected the list in a - buffer under the lock and then made a copy of all of it to send it, - for any client that may list. It is now sent from the buffer itself: - for a list of 3 million groups (190 MiB) a session's peak memory - goes from about 370 to 260 MiB. diff --git a/changes/fix-listen-check.md b/changes/fix-listen-check.md deleted file mode 100644 index afaabda1..00000000 --- a/changes/fix-listen-check.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* newscache didn't check whether listen() worked on its listening - sockets. On Linux two sockets can bind the same address and port, so - with TLSListenTo on the port of ListenTo (or of another program) only - listen() failed, and the daemon ran without that listener: TLS clients - reached the plain listener. It now exits with "can't listen on - TLSListenTo ...". diff --git a/changes/fix-listgroup-steps.md b/changes/fix-listgroup-steps.md deleted file mode 100644 index d08d8491..00000000 --- a/changes/fix-listgroup-steps.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* A client's LISTGROUP goes to the news server in steps, each with its - own reply limits: 10000 numbers at a time in a dense group, larger - steps (up to 100000000 numbers) across gaps; it fails when no number - reached the client for 5 minutes. It used to be one request - for the whole range, or the whole group, so a list of millions of - numbers could run into the reply deadline, and a provider that - answers 503 to large ranges made NewsCache fetch overview records - instead. diff --git a/changes/fix-lock-downgrade-atomic.md b/changes/fix-lock-downgrade-atomic.md deleted file mode 100644 index 4a35fc90..00000000 --- a/changes/fix-lock-downgrade-atomic.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* Going back from an exclusive lock on a spool database to the shared - lock held around it (as when a session removes an unreadable article - while it reads a group) gave the lock up for a moment, and another - process could change or resize the file in the middle of the shared - section. The exclusive lock is now turned into the shared one at once; - only taking an exclusive lock still gives the shared lock up first. diff --git a/changes/fix-log-control-bytes.md b/changes/fix-log-control-bytes.md deleted file mode 100644 index 309d1687..00000000 --- a/changes/fix-log-control-bytes.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* Control bytes in a log line (ESC, a CR, DEL and the other bytes below - 0x20) are now written as "?". Client input went into the log as it - came, in commands, user names, group names and host names from DNS, so - a client could make a line look like something else on a terminal or - split it for a log parser. The same applies to the article headers that - configure --enable-headerlog writes to .headerlog, except tabs and the - line ends. diff --git a/changes/fix-log-file-mode.md b/changes/fix-log-file-mode.md deleted file mode 100644 index 322cabfe..00000000 --- a/changes/fix-log-file-mode.md +++ /dev/null @@ -1,2 +0,0 @@ -Behaviour changes: -* With `--without-syslog`, a new log file is created with mode 0640 instead of 0644, so other local users can't read client addresses and user names in it. An existing log file keeps its mode. diff --git a/changes/fix-lookup-read-bound.md b/changes/fix-lookup-read-bound.md deleted file mode 100644 index dfc10797..00000000 --- a/changes/fix-lookup-read-bound.md +++ /dev/null @@ -1,4 +0,0 @@ -Other changes: -* GCC 15 with _FORTIFY_SOURCE (Fedora 43's rpm flags) no longer warns - that the client name lookup's read could overflow its buffer: the - loop's bound is explicit now. diff --git a/changes/fix-maxconn-host-test-probe.md b/changes/fix-maxconn-host-test-probe.md deleted file mode 100644 index 7c927390..00000000 --- a/changes/fix-maxconn-host-test-probe.md +++ /dev/null @@ -1,5 +0,0 @@ -Other changes: -* TestMaxConnectionsPerHost no longer fails when the harness's readiness - connection is still ending (seen on FreeBSD, where the test doesn't wait - for its process): its helper retried that only for MaxConnections' - "400 too many users". Each test now names the one refusal it retries. diff --git a/changes/fix-maxconn-log.md b/changes/fix-maxconn-log.md deleted file mode 100644 index 2b051f2e..00000000 --- a/changes/fix-maxconn-log.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A client turned away at MaxConnections ("400 too many users") was not - logged, so a server whose sessions were all taken (by a flood, or by - idle clients) showed nothing. The log now names the first client - turned away, counts the others at most once a minute while the limit - is reached, and says when a session can be started again. diff --git a/changes/fix-maxconn-per-host.md b/changes/fix-maxconn-per-host.md deleted file mode 100644 index 5d5fb7fd..00000000 --- a/changes/fix-maxconn-per-host.md +++ /dev/null @@ -1,9 +0,0 @@ -New options: -* MaxConnectionsPerHost n (standalone mode): the most sessions one client - host may have at a time, so that one host can't hold all of - MaxConnections with idle connections. A host is an IPv4 address, or - the /64 network of an IPv6 address. A client over the limit gets "400 - too many connections from your host" (on TLSListenTo it is - disconnected without a reply), and the log says so, at most once a - minute with a count. The default is 0, no limit, so clients behind one - NAT address are not affected unless it is set. diff --git a/changes/fix-msgid-counter.md b/changes/fix-msgid-counter.md deleted file mode 100644 index 24ff3deb..00000000 --- a/changes/fix-msgid-counter.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A client that posted two articles without a Message-ID in one session, - to more than one server, within the same second could lose the second: - both got the same generated Message-ID (the counter in it was always - 1), so the second was taken for a duplicate and dropped, while the - client got 240. The counter now counts. diff --git a/changes/fix-msgid-limits.md b/changes/fix-msgid-limits.md deleted file mode 100644 index bc194d4e..00000000 --- a/changes/fix-msgid-limits.md +++ /dev/null @@ -1,9 +0,0 @@ -Behaviour changes: -* Client command Message-IDs must meet RFC 3977's opaque-string rules and - be at most 250 octets; posted Message-ID headers must also meet RFC 5536's - stricter syntax. Invalid IDs are rejected; upstream articles with longer - IDs can still be read by article number. - -Bug fixes: -* Message-IDs supplied by a client are checked before consulting the spool - or forwarding commands or posts upstream. diff --git a/changes/fix-msgid-long-hostname.md b/changes/fix-msgid-long-hostname.md deleted file mode 100644 index 9cc55a7a..00000000 --- a/changes/fix-msgid-long-hostname.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* Generated Message-IDs no longer exceed the 250-octet limit with a long - Hostname: when necessary, the host part is the hostname's MD5 in lowercase - hexadecimal, while the time, process and counter components are retained. diff --git a/changes/fix-multi-inject-dates.md b/changes/fix-multi-inject-dates.md deleted file mode 100644 index fd2097f6..00000000 --- a/changes/fix-multi-inject-dates.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* Posts forwarded to multiple upstream servers now get missing Date and - Injection-Date headers before forwarding, so each injector receives the - same dates along with the shared Message-ID. diff --git a/changes/fix-newgroups-active-times.md b/changes/fix-newgroups-active-times.md deleted file mode 100644 index 761e90fd..00000000 --- a/changes/fix-newgroups-active-times.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* NEWGROUPS rejects invalid calendar and clock values instead of allowing - the C library to normalize them. Documented that NEWGROUPS and LIST - ACTIVE.TIMES use the local first-seen time, not upstream creation times. diff --git a/changes/fix-newgroups-args.md b/changes/fix-newgroups-args.md deleted file mode 100644 index e7532a3a..00000000 --- a/changes/fix-newgroups-args.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* NEWGROUPS now rejects arguments beyond its optional GMT token, reports the - correct syntax, and uses the RFC 3977 231 reply text without a timestamp. diff --git a/changes/fix-newscacheclean-dircnt.md b/changes/fix-newscacheclean-dircnt.md deleted file mode 100644 index 9b217825..00000000 --- a/changes/fix-newscacheclean-dircnt.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* `newscacheclean -s` now reports the number of cached group directories in `DirCnt`. diff --git a/changes/fix-newsgroups-last-line.md b/changes/fix-newsgroups-last-line.md deleted file mode 100644 index 0f007c1f..00000000 --- a/changes/fix-newsgroups-last-line.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* LIST NEWSGROUPS left out the last description when the .newsgroups - file did not end with a newline. It is now listed. diff --git a/changes/fix-nvcontainer-resize-accounting.md b/changes/fix-nvcontainer-resize-accounting.md deleted file mode 100644 index 9253b1d9..00000000 --- a/changes/fix-nvcontainer-resize-accounting.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* After a process was killed while it grew a database file, the next - growth left part of the new space unusable (up to 64 KB, more for - large indexes). The free space is now counted from the size the - header records. diff --git a/changes/fix-nvlock-guards.md b/changes/fix-nvlock-guards.md deleted file mode 100644 index 2f368e05..00000000 --- a/changes/fix-nvlock-guards.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* When a session ran out of memory while it sent overview data, header - lines or article numbers of a group (OVER, HDR, LISTGROUP), or while - it changed the active database and the disk was full, it kept the - group's (or the active database's) lock until it ended, and every - other session that had to change it waited. The lock is now given - back in every case. diff --git a/changes/fix-objlock-eacces.md b/changes/fix-objlock-eacces.md deleted file mode 100644 index 0ae4c2d1..00000000 --- a/changes/fix-objlock-eacces.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* On systems where a lock held by another process makes fcntl report - EACCES (POSIX allows it), updatenews no longer stops posting the spooled - articles with an error when another process is posting them; it says - that another process posts them, as on Linux and the BSDs. diff --git a/changes/fix-objlock-eintr.md b/changes/fix-objlock-eintr.md deleted file mode 100644 index 7f3195e1..00000000 --- a/changes/fix-objlock-eintr.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* The lock of the post spool (.artSpool) gave up when a signal - interrupted the wait for it: after SIGTERM, a post that the news - server didn't take could fail to reach the spool, and the client got - an error. Now the wait goes on; the lock is held only while one file - is stored or removed. diff --git a/changes/fix-open-lock-eintr.md b/changes/fix-open-lock-eintr.md deleted file mode 100644 index 914634c1..00000000 --- a/changes/fix-open-lock-eintr.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* Opening a group's database waits for its lock and then checks the - file. A signal that interrupted the wait (SIGTERM, or SIGHUP for - updatenews) let the checks run without the lock: they could see - another process half way through a change and call a sound database - corrupt, which moved it aside and started an empty one. Now the wait - goes on after a signal, and a lock that can't be taken is an error. - The same holds for the directory lock taken before a corrupt database - is moved aside. diff --git a/changes/fix-over-bare-cr.md b/changes/fix-over-bare-cr.md deleted file mode 100644 index 6a1b1ef4..00000000 --- a/changes/fix-over-bare-cr.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A CR or NUL inside an overview record from a news server becomes a - space, as in an article's head: when the record is stored, and when a - record that an older version stored is sent. A lone CR was stored and - sent to clients inside the OVER, XOVER and XHDR lines; a reader that - ends a line at a CR saw the reply end early and status lines chosen by - the news server. diff --git a/changes/fix-over-empty-range.md b/changes/fix-over-empty-range.md deleted file mode 100644 index fc1ced43..00000000 --- a/changes/fix-over-empty-range.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* OVER answers 423 when the requested article range is empty, including a - reversed range, instead of sending an empty 224 response (RFC 3977). diff --git a/changes/fix-over-msgid-503.md b/changes/fix-over-msgid-503.md deleted file mode 100644 index a3101b5c..00000000 --- a/changes/fix-over-msgid-503.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* OVER by message-ID now answers 503, because this optional form is not - supported, whether or not a newsgroup is selected (RFC 3977). diff --git a/changes/fix-over-upstream-failure.md b/changes/fix-over-upstream-failure.md deleted file mode 100644 index e469c3bd..00000000 --- a/changes/fix-over-upstream-failure.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* Report interrupted upstream overview and LISTGROUP replies as failures - rather than returning a successful empty or incomplete range. diff --git a/changes/fix-overview-fmt-names.md b/changes/fix-overview-fmt-names.md deleted file mode 100644 index 1982be58..00000000 --- a/changes/fix-overview-fmt-names.md +++ /dev/null @@ -1,5 +0,0 @@ -Behaviour changes: -* LIST OVERVIEW.FMT names the byte and line counts `:bytes` and `:lines`, the - form RFC 3977 8.4.2 prefers, instead of the older `Bytes:` and `Lines:` - (which the RFC still allows for compatibility). The OVER fields themselves - are unchanged. diff --git a/changes/fix-pam-service-name.md b/changes/fix-pam-service-name.md deleted file mode 100644 index 4a5f9c5d..00000000 --- a/changes/fix-pam-service-name.md +++ /dev/null @@ -1,5 +0,0 @@ -Other changes: -* The PAM end-to-end tests no longer fail when two test runs share a - machine: each PAM service they write to /etc/pam.d has a name of its - own (it was newscache-e2e-001 in every test, so one run read the - other's rules). diff --git a/changes/fix-pam-service-warning.md b/changes/fix-pam-service-warning.md deleted file mode 100644 index fb214645..00000000 --- a/changes/fix-pam-service-warning.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* NewsCache now warns in its log, at startup and after a reload, when a PAM service named by `PAMServicename` for `Authentication pam` or `pam+file` has no configuration in `/etc/pam.d` or `/etc/pam.conf`. PAM then silently uses its `other` service. The warning is advisory; logins are unchanged. diff --git a/changes/fix-partial-list-close.md b/changes/fix-partial-list-close.md deleted file mode 100644 index 880d8d05..00000000 --- a/changes/fix-partial-list-close.md +++ /dev/null @@ -1,6 +0,0 @@ -Behaviour changes: -* When an internal error (for example a damaged spool database) interrupts - a multi-line reply that has already begun (XOVER, LISTGROUP, LIST, ...), - NewsCache now closes the connection instead of ending the list with "." - as if it were complete, the same as for an upstream failure in the middle - of a list. Before anything is sent, the client still gets a 403. diff --git a/changes/fix-plainpass-crypt-log.md b/changes/fix-plainpass-crypt-log.md deleted file mode 100644 index 04ff01f1..00000000 --- a/changes/fix-plainpass-crypt-log.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* With --enable-plainpass, every login with a plain text password in - the auth file logged the error "crypt() can't use the stored hash" - before it succeeded. A field that is no hash is now compared as plain - text without calling crypt(). diff --git a/changes/fix-post-bare-cr.md b/changes/fix-post-bare-cr.md deleted file mode 100644 index cad3f176..00000000 --- a/changes/fix-post-bare-cr.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* POST refuses an article with a NUL or a CR outside CRLF (441), as - RFC 5536 requires. It was forwarded as it came: against a news server - that ends a line at a lone CR, the article ended early and the rest - ran as commands on NewsCache's own connection to that server. A - spooled article with such a CR, from an older version, is posted - with the CR replaced by a space. diff --git a/changes/fix-post-deadline.md b/changes/fix-post-deadline.md deleted file mode 100644 index ce0b5d46..00000000 --- a/changes/fix-post-deadline.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A client that sent the article after POST slowly enough to never hit - the per-read timeout (a byte every few seconds) could hold a session, - and with enough of them all of MaxConnections, for ever. The whole - article must now arrive within ClientTimeout after the 340 reply; - otherwise the client gets "400 ... service timed out!" and the - connection is closed. diff --git a/changes/fix-post-duplicate-headers.md b/changes/fix-post-duplicate-headers.md deleted file mode 100644 index 5e6cc5a0..00000000 --- a/changes/fix-post-duplicate-headers.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A client whose PostTo allowed only some groups could add a second - Newsgroups header with another group: only the first was checked, and - both went to the news server. A POST with a repeated Newsgroups, From, - Subject, Date, Path or other header that RFC 5536 allows once is now - refused with 441 "more than one ... header" and logged. diff --git a/changes/fix-postspooled-continue.md b/changes/fix-postspooled-continue.md deleted file mode 100644 index 3ac1e4d8..00000000 --- a/changes/fix-postspooled-continue.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* While one news server was down, updatenews posted none of the spooled - articles if the first one it found was for that server: the run ended - there, and the next run found the same article first. Such an article - now stays in the spool for the next run, and the others are posted; - the log says how many were kept. diff --git a/changes/fix-prefetch-file-error.md b/changes/fix-prefetch-file-error.md deleted file mode 100644 index 11bf698a..00000000 --- a/changes/fix-prefetch-file-error.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* updatenews now logs an error with the reason (for example "No such file or - directory" or "Permission denied") and exits nonzero when a configured - PrefetchFile cannot be opened or is a directory or a FIFO (a directory was - read as empty, a FIFO blocked the run). An empty PrefetchFile, or - /dev/null, still means no groups to prefetch. diff --git a/changes/fix-prefetch-sync-range.md b/changes/fix-prefetch-sync-range.md deleted file mode 100644 index b5b45e33..00000000 --- a/changes/fix-prefetch-sync-range.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* updatenews -g no longer marks a chunk of a group's overview as up to date - for numbers it didn't fetch: in a group of more than 10 million numbers, - the ones just below the prefetched part (in the same chunk of 10000), and - numbers another session's range had already moved past while the - prefetch ran. Clients asking for those numbers got nothing from the spool - instead of the news server's overview. diff --git a/changes/fix-print-window-move.md b/changes/fix-print-window-move.md deleted file mode 100644 index 115a187e..00000000 --- a/changes/fix-print-window-move.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* An XOVER, OVER, XHDR, HDR or LISTGROUP over several chunks of a group - could leave out records without any error: when another session's - request moved the group's index up meanwhile (articles far above, or a - group larger than the index's 10^7 numbers), the chunks that fell below - it printed nothing, and the list still ended with "." as if complete. - Those numbers come from the news server now. diff --git a/changes/fix-ptr-name-check.md b/changes/fix-ptr-name-check.md deleted file mode 100644 index 0331c2a5..00000000 --- a/changes/fix-ptr-name-check.md +++ /dev/null @@ -1,11 +0,0 @@ -Bug fixes: - -* The client's name, which its reverse zone gives (whoever has the - address block runs that zone), went into X-NNTP-Posting-Host and the - log as it was. musl's getnameinfo returns CR and LF too, so on musl - systems (Alpine) a name with "\r\n.\r\n" ended a posted article on - the news server's connection, and the rest was read as commands. - A name with anything but letters, digits, dots, hyphens and - underscores is now dropped, and the client goes by its address; - X-NNTP-Posting-Host is also left out when the host has a space or a - control character. diff --git a/changes/fix-read-man.md b/changes/fix-read-man.md deleted file mode 100644 index 0735e933..00000000 --- a/changes/fix-read-man.md +++ /dev/null @@ -1,6 +0,0 @@ -Documentation: -* newscache.conf(5) called a server's Read "wildmat patterns", but the - groups are routed by names that may end in * and start with !, with the - longest match winning: a * anywhere matches the rest of the name, and ? - and [...] are taken literally. The page and the manual say so now, with - an example of the longest match. diff --git a/changes/fix-reconnect-group-guard.md b/changes/fix-reconnect-group-guard.md deleted file mode 100644 index 319be978..00000000 --- a/changes/fix-reconnect-group-guard.md +++ /dev/null @@ -1,10 +0,0 @@ -Bug fixes: -* After a broken connection to a news server, NewsCache selects the - client's group again on the new connection. That GROUP was sent after - the set-up guard of the connection was off, so a server that closed the - connection (or answered 400) at it made NewsCache reconnect from inside - the reconnect, nested without limit: thousands of connections to the - server, then the session crashed (stack overflow) without a reply. A - failed GROUP now ends that connection attempt, the client's command gets - an error reply after at most Retries attempts, and the session goes on. - The guard for MODE READER and LIST OVERVIEW.FMT came in 1.3.23 too. diff --git a/changes/fix-reload-getfqdn.md b/changes/fix-reload-getfqdn.md deleted file mode 100644 index ff24f61d..00000000 --- a/changes/fix-reload-getfqdn.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* A configuration reload no longer looks up the host name (a possible DNS lookup that can stall the daemon). `Hostname` takes effect only on a restart, so the default name is looked up once, at startup, and only when the file sets no `Hostname`. diff --git a/changes/fix-remap-outer-unlock.md b/changes/fix-remap-outer-unlock.md deleted file mode 100644 index 018f3620..00000000 --- a/changes/fix-remap-outer-unlock.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A database file that grew while a nested lock was given up, and then - couldn't be mapped again (for example under an address space limit), - left the outer lock held with no mapping: the session went on reading - nothing ("no such article") and other sessions waited for the lock. - The outer locks are now given up as for a corrupt file, and the next - access maps the file again. diff --git a/changes/fix-remap-write-guard.md b/changes/fix-remap-write-guard.md deleted file mode 100644 index 11b6bb21..00000000 --- a/changes/fix-remap-write-guard.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* A database whose remap failed while an outer lock was restored (file grown by another process, no address space left) no longer crashes the next write that holds its own lock; it reports an error. diff --git a/changes/fix-server-postto-order.md b/changes/fix-server-postto-order.md deleted file mode 100644 index b15e500d..00000000 --- a/changes/fix-server-postto-order.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* In a Server block of the configuration, a PostTo line before the Read - line was overwritten by Read. PostTo now stays as given; without it, - it still defaults to Read. The manual says so. diff --git a/changes/fix-session-leaks.md b/changes/fix-session-leaks.md deleted file mode 100644 index a9743d48..00000000 --- a/changes/fix-session-leaks.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* Free the last selected group and the server object when a client session ends, and the purge list in `newscacheclean`, so that a leak-checking (LeakSanitizer) run of the test suite reports nothing. diff --git a/changes/fix-session-sigchld.md b/changes/fix-session-sigchld.md deleted file mode 100644 index c045c385..00000000 --- a/changes/fix-session-sigchld.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* A session inherited the master's SIGCHLD handler, which reaps any child - with waitpid. A helper process started by a PAM module during login - could lose its exit status to it. Sessions, and the inetd mode, now - leave SIGCHLD at its default. diff --git a/changes/fix-sigchld-stress-single-hup.md b/changes/fix-sigchld-stress-single-hup.md deleted file mode 100644 index 8a3cc117..00000000 --- a/changes/fix-sigchld-stress-single-hup.md +++ /dev/null @@ -1,8 +0,0 @@ -Other changes: -* TestSigchldStress sends one SIGHUP after the stress and wants the good - configuration reread within a second (logged after 9 to 46 ms), and - the first session after that line to get its greeting. Since #170 it - sent SIGHUP again and dialled every 200 ms for up to 5 seconds, so a - lost or late reread passed: a daemon that only noticed SIGHUP with the - next connection passed the old test and fails this one. The config is - still written to a new file and renamed. diff --git a/changes/fix-sigchld-test-probe.md b/changes/fix-sigchld-test-probe.md deleted file mode 100644 index b1c15fdb..00000000 --- a/changes/fix-sigchld-test-probe.md +++ /dev/null @@ -1,4 +0,0 @@ -Other changes: -* TestSessionSigchldDefault no longer fails on a busy machine: the - session of the harness's readiness probe could still be running when - it counted the daemon's children. diff --git a/changes/fix-sighup-restart-notices.md b/changes/fix-sighup-restart-notices.md deleted file mode 100644 index 07dc43a4..00000000 --- a/changes/fix-sighup-restart-notices.md +++ /dev/null @@ -1,8 +0,0 @@ -Behaviour changes: -* After SIGHUP, new sessions continue to use the startup NiceServer value; - changing it now requires a restart instead of partly applying it. - -Bug fixes: -* SIGHUP reports each changed restart-only setting against the running - startup configuration, including whether ListenTo was specified. Notices - repeat until restart or until the configured setting is reverted. diff --git a/changes/fix-signal-flags-volatile.md b/changes/fix-signal-flags-volatile.md deleted file mode 100644 index 9580ca1d..00000000 --- a/changes/fix-signal-flags-volatile.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* The flag that NewsCache's and updatenews' signal handlers set to end a - wait (alarmed) is now volatile, as C and C++ require for a variable a - signal handler writes. A compiler was free to keep the old value in a - register, and a loop could miss a timeout or SIGTERM. diff --git a/changes/fix-signal-poll-window.md b/changes/fix-signal-poll-window.md deleted file mode 100644 index e41b705e..00000000 --- a/changes/fix-signal-poll-window.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* A termination or reload signal arriving just before the daemon entered - poll could leave it waiting until another client connected. Signals now - wake the idle daemon immediately. diff --git a/changes/fix-sigterm-no-reconnect.md b/changes/fix-sigterm-no-reconnect.md deleted file mode 100644 index dbee84b0..00000000 --- a/changes/fix-sigterm-no-reconnect.md +++ /dev/null @@ -1,21 +0,0 @@ -Bug fixes: -* A session or updatenews stopped with SIGTERM or SIGINT (updatenews - also with SIGHUP, SIGUSR1 or SIGUSR2) while it waited for the news - server opened new connections to it before it ended: the connect was - retried (Retries times, a second apart), a command was sent again - after a reconnect, and updatenews tried the next server and fetched - the active list. With ConnectTimeout set, the reconnect even cleared - the signal's mark, so the session carried on until the next command or - ReadTimeout; without it, an interrupted connect to a news server that - didn't answer was started again and waited for the system's timeout - (minutes). Now nothing is retried and no reconnect is made after the - signal (a connect that began at that very moment is closed before a - command is sent on it), and a wait for the news server ends within - about a second: a signal that came just before a wait began (after the - check for it) is caught by an alarm every second until the process - ends. The reply "service discontinued" gets two seconds, and a TLS - send isn't started again once the signal is seen. A spooled article - whose post was interrupted stays in the spool for the next run. The - log says "given up: shutting down" or "not read to its end: shutting - down" instead of blaming the news server, and an empty line for a - greeting that never came is no longer logged. diff --git a/changes/fix-single-instance-tools.md b/changes/fix-single-instance-tools.md deleted file mode 100644 index 221c118f..00000000 --- a/changes/fix-single-instance-tools.md +++ /dev/null @@ -1,9 +0,0 @@ -Behaviour changes: -* Only one newscacheclean runs at a time, and only one updatenews that - prefetches (-g or -o): a second run, as cron starts one when the first - takes long, exits with status 3 and a message. Two newscacheclean runs - that overlapped both computed the purge from the same sizes and - together removed about twice what was needed; two prefetch runs - fetched the same groups twice. The locks are the files - .newscacheclean.lock and .updatenews.lock in the spool directory, held - while the process runs. updatenews -a alone doesn't take the lock. diff --git a/changes/fix-spool-diskfull-test-bounds.md b/changes/fix-spool-diskfull-test-bounds.md deleted file mode 100644 index 6a2099fa..00000000 --- a/changes/fix-spool-diskfull-test-bounds.md +++ /dev/null @@ -1,10 +0,0 @@ -Other changes: -* TestSpoolDiskFullDaemon wants every reply on the full disk within 5 - seconds again (they take at most 0.14 s, also with the race detector), - with the default ClientTimeout. Since #83 it allowed 180 s per reply - and ClientTimeout 600, so a lock held for nearly three minutes passed: - the second client's last XOVER fetched 10000 records again from the - test's own fake news server (20 s under -race), and the first client - idled that long. The group now ends in a small chunk of 11 records - that can't be kept either, so nothing slow is left in the measured - part; the first client's fill of the cache keeps its 180 s. diff --git a/changes/fix-spool-locate-history.md b/changes/fix-spool-locate-history.md deleted file mode 100644 index 106747fb..00000000 --- a/changes/fix-spool-locate-history.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* A temporary error while reading a group's record (no free file - descriptor, a lock timeout) made the lookup of an article by - Message-ID forget where it was stored. The location now stays in the - history unless its record is really gone or holds another article. diff --git a/changes/fix-spool-lock-hold.md b/changes/fix-spool-lock-hold.md deleted file mode 100644 index 28c86f34..00000000 --- a/changes/fix-spool-lock-hold.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* A client that asked for a long XOVER, XHDR or LISTGROUP reply and stopped - reading held the group's shared lock until its send timed out - (ClientTimeout), and every session that had to store an article or an - overview record for that group waited that long - 600 seconds with the - sample configuration. The records are now formatted under a short lock and - written with the lock released: at most 64 records or 64 KB for XOVER and - XHDR, and at most 4096 numbers or 64 KB for LISTGROUP. diff --git a/changes/fix-stalled-reader-test-from-spool.md b/changes/fix-stalled-reader-test-from-spool.md deleted file mode 100644 index eaf6ff77..00000000 --- a/changes/fix-stalled-reader-test-from-spool.md +++ /dev/null @@ -1,20 +0,0 @@ -Bug fixes: -* The session of a client that stopped reading in the middle of a reply - could end after two ClientTimeouts instead of one (seen on FreeBSD): - when the send timeout runs out after send() has taken part of the - data, Linux and FreeBSD return that part instead of an error, and the - rest was sent with a second wait. After a short send, the rest now - goes out only if the socket can take more within what is left of the - send timeout; otherwise the write fails, like a failed send. The same - applies to connections to the upstream servers (ReadTimeout). - -Other changes: -* TestClientStalledReader checks again that the session of a client - that stops reading in the middle of OVER or XOVER ends after one - ClientTimeout: it now fills the cache first, so that the reply comes - from the spool, and wants the session gone within 1.5 ClientTimeouts - of the request (3.0 to 3.3 s, also under -race). It only checked that - another client was still served, which since the records are written - with the group's lock released passed even when the session never - ended (3cefac9 reverted) or ended a ClientTimeout late (763126c - reverted: 6.0 s). diff --git a/changes/fix-std-exception-session.md b/changes/fix-std-exception-session.md deleted file mode 100644 index 50a9b974..00000000 --- a/changes/fix-std-exception-session.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* A C++ standard exception (std::bad_alloc, std::length_error ...) in a - command ended the session without a reply, and in inetd mode (-i, -t) - ended the process with SIGABRT and a core dump. The client now gets - "403 internal error" like for NewsCache's own errors and the session - goes on; the exception is logged. Outside a command the session ends - with a log message. diff --git a/changes/fix-storechunk-range.md b/changes/fix-storechunk-range.md deleted file mode 100644 index 2bedb722..00000000 --- a/changes/fix-storechunk-range.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* When a group's article range changes during an overview fetch, NewsCache - no longer marks an out-of-range fetch as synchronized. If the index later - grows down into a partly covered chunk, its synchronization mark is cleared - so missing overview records are fetched instead of treated as fresh. diff --git a/changes/fix-sysconfdir-expand.md b/changes/fix-sysconfdir-expand.md deleted file mode 100644 index 28e750d2..00000000 --- a/changes/fix-sysconfdir-expand.md +++ /dev/null @@ -1,2 +0,0 @@ -Bug fixes: -* The default configuration path now expands `${prefix}` in custom `--sysconfdir` values. diff --git a/changes/fix-sysconfdir-no-eval.md b/changes/fix-sysconfdir-no-eval.md deleted file mode 100644 index e7d0597a..00000000 --- a/changes/fix-sysconfdir-no-eval.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* configure no longer runs shell syntax from `--prefix` or - `--sysconfdir`: a `$(...)` in a directory name stays literal when the - configuration path is expanded (the expansion added before this release - evaluated the value). diff --git a/changes/fix-sysv-init-symlink.md b/changes/fix-sysv-init-symlink.md deleted file mode 100644 index 9d284d23..00000000 --- a/changes/fix-sysv-init-symlink.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* The SysV init script reported "failed to stay running" and removed its - pid file while the daemon ran, and "stop" said it was not running, when - the directory of the daemon is a symbolic link (/usr/sbin -> bin on - Fedora and Arch). It now also accepts the resolved path of the daemon. diff --git a/changes/fix-sysv-init.md b/changes/fix-sysv-init.md deleted file mode 100644 index c57b280b..00000000 --- a/changes/fix-sysv-init.md +++ /dev/null @@ -1,2 +0,0 @@ -New options: -* `--enable-sysv-init` installs an optional Linux and GNU/Hurd init.d script, disabled by default; `--with-initdir` selects its installation directory. diff --git a/changes/fix-testkit-0.11.0.md b/changes/fix-testkit-0.11.0.md deleted file mode 100644 index 06ab3cfa..00000000 --- a/changes/fix-testkit-0.11.0.md +++ /dev/null @@ -1,2 +0,0 @@ -Other changes: -* The end-to-end tests use nntp-testkit 0.11.0 (still Go 1.26 or later). diff --git a/changes/fix-testkit-0.12.0.md b/changes/fix-testkit-0.12.0.md deleted file mode 100644 index c82d2a2b..00000000 --- a/changes/fix-testkit-0.12.0.md +++ /dev/null @@ -1,5 +0,0 @@ -Other changes: -* The end-to-end tests use nntp-testkit 0.12.0 (still Go 1.26 or later), - and its reader conformance checks also run over the TLS listener - (TLSListenTo), including the check that CAPABILITIES there doesn't - list STARTTLS. diff --git a/changes/fix-tls-read-timeout.md b/changes/fix-tls-read-timeout.md deleted file mode 100644 index b4a74c28..00000000 --- a/changes/fix-tls-read-timeout.md +++ /dev/null @@ -1,4 +0,0 @@ -Bug fixes: -* On a TLS connection to a news server, silence lasted twice as long as - ReadTimeout before NewsCache gave up on the reply. Now it is one - ReadTimeout, as on a plain connection. diff --git a/changes/fix-tls-stall-test-bound.md b/changes/fix-tls-stall-test-bound.md deleted file mode 100644 index c43e845f..00000000 --- a/changes/fix-tls-stall-test-bound.md +++ /dev/null @@ -1,7 +0,0 @@ -Other changes: - -* The end-to-end test of a TLS client that stops reading allows the - session 14 seconds to end, not 11: on a busy one-core machine with - the race detector, the fetches before the reply fills the socket made - it fail although the session ended in time (11.2 s). The behaviour it - guards against took about 18 seconds. diff --git a/changes/fix-tls-stall-test-from-spool.md b/changes/fix-tls-stall-test-from-spool.md deleted file mode 100644 index 9b34c26d..00000000 --- a/changes/fix-tls-stall-test-from-spool.md +++ /dev/null @@ -1,9 +0,0 @@ -Other changes: -* TestClientTLSStalledReaderTimesOutAndReleasesGroup measures the stalled - session again from a reply that comes from the spool: it counted how - fast the test's own fake news server served 40000 records, which under - the race detector took the session's end from 7.4 to 9.6 s, and its - bounds had been raised for that (ClientTimeout 3 to 6, then the end - bound from 11 to 14 s). With ClientTimeout 3 again the session ends - after about 4 s and the bounds are 6 s for the end and 2 s for the - second client's wait; the old defect (13 s) fails. diff --git a/changes/fix-tls-stalled-writer.md b/changes/fix-tls-stalled-writer.md deleted file mode 100644 index a5b18acd..00000000 --- a/changes/fix-tls-stalled-writer.md +++ /dev/null @@ -1,6 +0,0 @@ -Bug fixes: -* A client that stops reading its replies now ends its session after one - ClientTimeout. Output left in the send buffer after the failed send was - sent again by every later flush, each waiting for the timeout once more, - so such a session lasted several ClientTimeouts (seen with TLS on - EL9). diff --git a/changes/fix-updatenews-group-leak.md b/changes/fix-updatenews-group-leak.md deleted file mode 100644 index d92bd86f..00000000 --- a/changes/fix-updatenews-group-leak.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* updatenews kept the database of a group open when its prefetch failed - with an unexpected error, one file descriptor and one mapping per group, - until the run ended. A long run over many failing groups could run out - of file descriptors. The group is now released. diff --git a/changes/fix-updatenews-grouptimeout.md b/changes/fix-updatenews-grouptimeout.md deleted file mode 100644 index bcc737e4..00000000 --- a/changes/fix-updatenews-grouptimeout.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* updatenews now retains group-number information for up to 60 seconds during - prefetch, avoiding redundant upstream GROUP commands within a prefetch. diff --git a/changes/fix-upstream-article-deadline.md b/changes/fix-upstream-article-deadline.md deleted file mode 100644 index 8fca2614..00000000 --- a/changes/fix-upstream-article-deadline.md +++ /dev/null @@ -1,8 +0,0 @@ -Bug fixes: -* A news server that sent an article, or the LIST OVERVIEW.FMT reply - read when NewsCache connects, one byte at a time with pauses just - under ReadTimeout could hold the session (and the locks it held) for - hours. The article now has a limit for the whole reply, two minutes - plus MaxArticleSize at 4 KB/s (6 minutes for the default 1 MiB), and - the overview format 30 seconds, 1000 lines and 1 MiB; NewsCache then - closes the connection and answers the client with 403. diff --git a/changes/fix-upstream-reply-limits.md b/changes/fix-upstream-reply-limits.md deleted file mode 100644 index 5ee17b49..00000000 --- a/changes/fix-upstream-reply-limits.md +++ /dev/null @@ -1,9 +0,0 @@ -Bug fixes: -* Bound upstream active lists, overview replies and LISTGROUP replies so a - broken server cannot keep consuming resources or holding locks indefinitely: - an active list may have at most 2,000,000 lines and 256 MiB and take at - most 5 minutes, an overview or LISTGROUP reply as many lines as the - requested range and at most 2 minutes. Incomplete replies are not marked - fresh, and their upstream connections are closed rather than reused. An - incomplete combined active list is retried after at most 60 seconds, - rather than on every request. diff --git a/changes/fix-upstream-tls-deadline.md b/changes/fix-upstream-tls-deadline.md deleted file mode 100644 index 3663846e..00000000 --- a/changes/fix-upstream-tls-deadline.md +++ /dev/null @@ -1,5 +0,0 @@ -Bug fixes: -* Upstream TLS handshakes now have a whole-handshake deadline based on - ReadTimeout, or ConnectTimeout when ReadTimeout is zero (60 seconds when - both are zero), and stop promptly on termination signals. STARTTLS retains - the configured timeout after upgrading. diff --git a/changes/fix-wildmat-lists.md b/changes/fix-wildmat-lists.md deleted file mode 100644 index 03ee18b7..00000000 --- a/changes/fix-wildmat-lists.md +++ /dev/null @@ -1,7 +0,0 @@ -Bug fixes: -* The wildmat of LIST ACTIVE, LIST ACTIVE.TIMES and LIST NEWSGROUPS is - now a list as in RFC 3977 section 4.2: comma separated patterns, each - optionally led by "!", the last one that matches deciding. A list such - as "comp.*,alt.*" or "comp.*,!comp.os.*" used to list nothing, and - LIST ACTIVE.TIMES read its argument as an access rule list, so - "LIST ACTIVE.TIMES *.test" listed every group the client may list. diff --git a/changes/fix-xover-stall-test-wait.md b/changes/fix-xover-stall-test-wait.md deleted file mode 100644 index 0e5c90eb..00000000 --- a/changes/fix-xover-stall-test-wait.md +++ /dev/null @@ -1,10 +0,0 @@ -Other changes: -* TestXoverStalledClientDoesNotHoldGroupLock: the second client stores - one article after the other from the first client's XOVER until the - first client's session has ended, instead of storing one article after - a fixed 700 ms. On a slow machine the first session could still be - before its XOVER's records then, and the second client passed without - testing anything: with the lock held across the write and the session - one second late, the old test passed and this one fails. The first - session ends only when its send times out, so the stores cover the - whole time it is stalled, on every system that has /proc or pgrep. diff --git a/changes/fix-xref-one-pass.md b/changes/fix-xref-one-pass.md deleted file mode 100644 index aec5d5af..00000000 --- a/changes/fix-xref-one-pass.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* Filter Xref headers in one pass so a large crosspost list from an upstream - server cannot hold the group lock for quadratic time. diff --git a/changes/test-history-prune.md b/changes/test-history-prune.md deleted file mode 100644 index 110e0693..00000000 --- a/changes/test-history-prune.md +++ /dev/null @@ -1,3 +0,0 @@ -Bug fixes: -* Reject overlong database paths before copying them into the fixed-size - container filename buffer, without disturbing an already-open database. diff --git a/configure.ac b/configure.ac index 5a837adb..08d6f461 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. dnl The version: set it here for a release (see NEWS and debian/changelog). dnl The fourth argument keeps PACKAGE (greeting, syslog name, tarball) as dnl "NewsCache"; by default autoconf would lower-case it. -AC_INIT([NewsCache], [1.3.22], [https://github.com/go-while/NewsCache/issues], +AC_INIT([NewsCache], [1.3.23], [https://github.com/go-while/NewsCache/issues], [NewsCache], [https://github.com/go-while/NewsCache]) AC_PREREQ([2.69]) AC_CANONICAL_HOST diff --git a/debian/changelog b/debian/changelog index f4bd9631..de657d9b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,50 @@ +newscache (1.3.23-1) unstable; urgency=medium + + * TLS for client connections: TLSListenTo, TLSCertFile, TLSKeyFile, + TLSPriority; AuthRequiresTLS answers AUTHINFO without TLS with 483 + * COMPRESS DEFLATE (RFC 8054) to news servers: Options compress (zlib) + * New options ReadTimeout, MaxArticleSize and MaxPostSize; optional + init.d script (configure --enable-sysv-init) + * Logins: PAM gets the client's address (PAM_RHOST); failed logins + wait 1, 2 and 4 seconds, then the connection closes; user names and + passwords shorter than AuthMinLength (default 10) are refused; + hashes compared in constant time; RFC 4643 replies + * Message-IDs from clients checked against RFC 3977 and RFC 5536 + * Locking: no group lock held while fetching from the news server or + sending to a slow client; races between sessions, updatenews and + newscacheclean fixed + * SIGTERM, SIGHUP and timeouts no longer leave sessions running or + the daemon hanging + * A client that stops reading ends its session after one + ClientTimeout, also when the last send was partial + * Upstream replies bounded in size and time; TLS handshake deadline + * Bare CR and NUL bytes in articles, posts and overview data handled; + control bytes in log lines written as "?" + * Spool: damaged and cut-off files, file size limits and failed + remaps handled without hangs or crashes + * configure: --prefix and --sysconfdir expanded without running shell + code; --with-pam=, and --with-gnutls without GnuTLS, are errors + * Spool directory should be mode 0750; new log files get 0640 + * POST: repeated once-only headers refused, a time limit for the + article, spooled posts synced to disk before 240 + * Wildmat lists (a,b,!c) for LIST ACTIVE, ACTIVE.TIMES, NEWSGROUPS; + a detached daemon that fails to start exits with an error + * Builds on Debian GNU/Hurd + * New option MaxConnectionsPerHost; ConnectTimeout defaults to 30 + seconds; refused clients at MaxConnections are logged + * Only one newscacheclean, and one prefetching updatenews, at a time + (a second run exits with status 3) + * --without-syslog: SIGHUP reopens the log file, for logrotate + * The client's host name lookup takes at most 10 seconds + * Folded headers unfolded as RFC 5322 says; HDR turns TABs into spaces + * Several news servers: each group's active list entry comes from the + server GROUP uses; names that would share a spool directory refused + * Walks over long runs of empty article numbers ask the news server + in LISTGROUP steps and stop when the client has gone + * newscacheclean removes article files of groups without a database + + -- Billy G. Thu, 05 Nov 2026 12:00:00 +0000 + newscache (1.3.22-1) unstable; urgency=medium * XPAT, HDR and LIST HEADERS; XHDR by message-ID