21 May 2026
A large release. The headline is a systematic compiler warning cleanup that turned up a number of real bugs along the way. There are also new features, several security fixes, and a handful of upstream bug fixes.
Authentication-Results now includes header.a (signing algorithm) and header.s (selector).
New SyslogName configuration option to set the syslog identity string.
odkim.internal_ip() is now available in the screen and final Lua policy hooks.
The OpenSSL version string is included in build-config.h and reported by the -V flag.
OpenSSL 4 build support.
Removed QUERY_CACHE: libopendkim's BerkeleyDB-backed DNS result cache.
Removed POPAUTH (POP-before-SMTP) support.
Sandboxed Lua policy hooks against dangerous standard libraries (io, os, package, etc.).
Fixed a TXT chunk-length out-of-bounds read in DNS key extraction.
Fixed an Authentication-Results stripping bypass via a trailing-dot authserv-id.
Fixed a race in mlfi_connect: the current configuration was read without holding a reference count.
Fixed a related race in dkimf_add_signrequest, which was reading per-connection configuration from the global curconf.
Fixed a too-small buffer for the report address (user@host worst case).
Fixed undefined behaviour: (int) buflen cast is UB when buflen > INT_MAX.
Fixed dkim_ohdrs z= decode: it was writing into plist storage, using the wrong strlcpy size, and ignoring the scratch buffer.
Fixed dkimf_xs_delheader ignoring its idx argument.
Fixed potential dereference of an uninitialised sig pointer in dkim_eoh_verify.
Fixed potential use of an uninitialised ar in the mlfi_eom header-only path.
Fixed dkim_diffheaders stub falling off the end of a non-void function.
Fixed DKIM_SIGFLAG_PROCESSED not being set in all dkim_sig_process error paths.
Fixed missing dn_expand return-value check in the DNS qdcount loop.
Fixed an off-by-one in snprintf truncation detection in key queries.
Fixed missing truncation detection in Authentication-Results field copies in the ares parser.
Zero per-sign-request private key data before freeing.
Fixed missing leading space on Authentication-Results header when SMFIP_HDR_LEADSPC is not negotiated.
Quote header.b values in Authentication-Results (bug #235).
Constrain the header.b substring correctly for duplicate signatures (bug #233).
Handle header fields wrapped before any content (bug #226).
Remove the upper bound on the canonicalisation buffer size.
Fix quote handling in dkim_mail_parse_multi().
Make the standard (non-unbound) resolver DNSSEC-aware.
Protect ub_ctx_config() calls with a mutex (issue #14).
Widen the password-file critical section in dkimf_securefile (issue #8).
RequiredHeaders now reports the specific missing header and rejects the message (issue #28).
Do not skip the body when only one canonicalisation mode has finished (issue #15).
Reject non-printable characters in the domain and selector passed to dkim_sign() (feature #190).
As a first step, CMake hardening infrastructure was added to the build, enabling a set of warnings that had previously been absent or silently suppressed: -Wcast-qual, -Wmissing-prototypes, -Wshadow, -Wsign-compare, -Wpointer-sign, -Wformat-truncation, -Wunused-parameter, -Wreturn-type. The result was a substantial number of warnings across the daemon, library, miltertest, and test suite. These were then addressed systematically. Several real bugs were found and fixed in the process (listed above).
-Wcast-qual: extensive const-qualification work throughout libopendkim, opendkim, and miltertest. The dkim_options() API was split into separate dkim_setopt() and dkim_getopt() functions to make the const split clean. Unavoidable legacy libmilter cast sites are annotated.
-Wmissing-prototypes: file-internal helpers marked static; missing prototypes hoisted into headers.
-Wshadow: shadowing locals renamed or removed across the daemon, library, and tests.
-Wsign-compare: signed/unsigned comparison fixes; loop counters and sentinel values correctly typed; a wraparound in dkim_get_sigsubstring fixed.
-Wpointer-sign: u_char/char pointer mismatches resolved at libopendkim API boundaries.
-Wunused-parameter, -Wunused-variable, -Wreturn-type: remaining stragglers cleaned up.