Adapt the 1.5 fixes to master's discovery, alarms and conditions, session, and nodeset-loader architecture. Preserve master behavior and combine PubSub replay protection with authenticated key rollover. Enable allocation-failure regression coverage and retain both branches' relevant tests.
Possible private key formats include "PEM", "PFX", or "PKCS8". We
reported "DER" as a supported private key format which is wrong. This
commit adds a test to check only valid key formats are presented and
fixes other tests that used invalid key formats.
Enable allocator hooks in the alarms coverage configuration and cover history constructor and insertion failures. Include stdlib.h explicitly in tests that use EXIT_SUCCESS and EXIT_FAILURE so the allocator-enabled build compiles without transitive standard-library includes.
Let config.h establish POSIX feature macros before stdlib.h loads glibc feature definitions. This exposes the recursive mutex declarations required by 1.4 unit test builds in strict C99 mode.
Add encryption_malformed_ecc_usertoken_length, which sends an
ActivateSession request with a UserNameIdentityToken carrying an
EccEncryptedSecret whose Length field makes endOfSecret smaller than
the ECC_nistP384 signature size. Asserts the server responds with
BadIdentityTokenInvalid instead of the process being killed while
handling the request.
Internal Vulnerability Advisory: open62541-SA-2026-0043
Co-Authored-By: X1AOxiang <X1AOxiang@users.noreply.github.com>
encryption_connect configured its client with an empty trust list to
reach the server's certificate, relying on the accept-all verifier that
used to be left in place for an empty list. Request that behavior
explicitly with UA_CertificateGroup_AcceptAll() instead, since the test
is about the server config surviving being copied into the server, not
about trust-list enforcement.
Internal Vulnerability Advisory: open62541-SA-2026-0057
Co-Authored-By: Jason Huibin Wang <jasontimwong@users.noreply.github.com>
Add a client-side and a server-side test asserting that an empty trust
list still results in a certificate verifier that rejects an untrusted
certificate, instead of silently keeping whatever verifier was
previously configured.
Internal Vulnerability Advisory: open62541-SA-2026-0057
Co-Authored-By: Jason Huibin Wang <jasontimwong@users.noreply.github.com>
UA_GDSReceiver_start did not start when initGDSRolePermissions failed,
but left the push method callbacks installed. The RolePermissions are
one way to restrict the methods to SecurityAdmin (Part 12, 7.10). RBAC
is optional, and the AccessControl plugin can restrict the methods as
well. So a failed role setup is now logged as a warning and the receiver
starts.
Port keyless certificate validation into the GDS receiver driver instead
of restoring the removed server implementation. Preserve master's timer
batching, PubSub lifecycle and client HTTP configuration handling.
Adapt Publish cancellation to response tokens and the HEL/fuzz harnesses
to the explicit TCP driver. Keep SKS policy history and custom datatype
ownership intact, including failed replacement configuration cleanup.
Retain TPM error cleanup while enforcing key-handle and nonce lengths.
Validation:
- Full mbedTLS unit-test build with full namespace, GDS, SKS and Query.
- 21 affected suites passed with ASan/UBSan, plus 9 isolated SKS ownership
and lifecycle checks.
- OpenSSL certificate update, GDS information model and client encryption
suites passed with sanitizers.
- OPN, MSG and binary-message fuzzers each completed 100 sanitizer runs.
- Both TPM PubSub policy sources passed compilation checks.
The full SKS client suite timed out after multicast UDP sends reported
"No route to host" on this machine; its affected ownership and lifecycle
cases passed separately. No live TPM hardware validation was performed.
A variant with length zero and a data pointer is a scalar. With an
array of length zero, UA_Variant_setArray kept the pointer, so the
variant became a scalar. Writing it to an array variable failed, and
clearing it freed the array as a single element.
UA_Variant_setArrayCopy already uses UA_EMPTY_ARRAY_SENTINEL in this
case. UA_Variant_setArray now does the same and does not take over the
array. NULL with length zero remains a null array.
The GDS Receiver writes its CertificateTypes with UA_Variant_setArray.
Since #8506 the list is empty on a server without an RSA endpoint. The
write failed, the receiver did not start and its methods were unbound.
Open was refused while any transaction was pending, also for the session
that owns it, so UpdateCertificate followed by a TrustList write failed.
Part 12 §7.8.2.2 says a write-mode Open continues an existing transaction.
Allow that for the owner unless ApplyChanges is queued; OpenWithMasks and
other sessions still get BadTransactionPending. Close discards only the
written data and keeps the staged changes. ApplyChanges refuses to run
while any TrustList is open for writing (§7.10.9).
CertificateTypes always listed RsaMin and RsaSha256. With no RsaMin policy
configured (the default), an RsaMin UpdateCertificate and ApplyChanges
answered Good without changing anything, and CreateSigningRequest returned
an empty CSR. Now only types with an endpoint policy in the
DefaultApplicationGroup are advertised. UpdateCertificate and
CreateSigningRequest refuse the others with BadInvalidArgument (Part 12
7.10.5, 7.10.10), and applying a type that no policy uses is an error.
SetPosition read its UInt64 Position argument through a UInt32 pointer.
Offsets above 4 GiB were truncated, and big-endian targets read the wrong
half. Read the argument with its declared type.
RemoveCertificate creates a transaction and applies it right away. When
the TrustList could not be copied into the transaction, it returned with
the transaction still pending and no session watchdog installed, so all
later TrustList changes were refused. Clear the transaction on that path.
ApplyChanges defers the completion of the transaction to a delayed
callback. An UpdateCertificate in between was accepted into the queued
transaction and then silently discarded with it. Refuse it with
BadTransactionPending until the transaction is completed.
ApplyChanges compared the caller with the owner of the transaction before
checking its state. A fresh transaction has no owner, so every caller got
BadUserAccessDenied. Check the state first, as Part 12 §7.10.9 requires.
After a certificate push the SecurityPolicy#None endpoint kept presenting
the replaced certificate, while the encrypted endpoints showed the new one.
A None SecurityPolicy with a replaced certificate is now updated as well.
Part 12 says a null CertificateGroupId selects the DefaultApplicationGroup.
The GDS receiver rejected it with Bad_NotSupported, so GDS pushes failed.
An unsupported group or type now returns Bad_InvalidArgument as specified.
Without a PrivateKey (after CreateSigningRequest), UpdateCertificate staged any bytes as
the new certificate and only ApplyChanges failed. Check that the certificate parses and
answer BadCertificateInvalid, also in UA_Server_updateCertificate when encryption is built.
NIST SP 800-38A F.5 vectors with the policy's counter block and an
HMAC-SHA256 tag pin the exact bytes for every backend. A context without
keys must refuse every operation until keys are installed.
Compare the selected discovery endpoint with its authenticated counterpart
from CreateSession using only the seven fields specified by Part 4. Ignore
optional metadata and the duplicated endpoint certificate, which servers may
omit. Keep the separate certificate validation unchanged.
Reject mismatches by default, with configurable warning and acceptance modes.
Skip the comparison for directly configured endpoints. Cover omitted metadata,
endpoint reordering, mismatch handling and trusted endpoint configuration.
Use pointer-sized atomic run flags in threaded fixtures, including dynamically
allocated discovery and browse flags. Pointer sizing supports the MSVC atomic
implementation as well as C11 and GCC atomics.
Serialize the client error-injection test with the server network callbacks
before accessing the internal session and shared send buffer.
Search the certificate input for the next PEM header with the haystack and needle in the correct order. Use a length-bounded helper so partial headers at the end cannot read past the input.
The exact-comparison change in f4c2dc2aa made an absent URI compare equal to an empty ApplicationUri. Require a non-empty URI SAN before accepting the certificate.
The mbedTLS RSA-PSS verifier consumes one complete RSA modulus but its low-level API does not take an input length. Reject malformed ByteStrings before invoking it so a short application signature cannot cause an out-of-bounds read.
Reject malformed raw ECDSA signatures before converting their r and s coordinates. Short signatures could otherwise cause out-of-bounds reads in the OpenSSL backend and an underflowing bounds check in the mbedTLS backend; oversized mbedTLS signatures could overflow the fixed DER buffer.
GDS callbacks trusted mutable InputArguments and OutputArguments metadata without checking the concrete callback array sizes. A client allowed to manage nodes could shorten a method signature and make a later batched call consume stale arguments left by an earlier operation. Validate every GDS callback contract before accessing input or output values.
Add check_hmac_verify_constanttime, exercising the OpenSSL
HMAC-SHA1/SHA256 verify helpers directly. A correct signature must
verify, a same-length signature with one flipped bit must be
rejected (guards the constant-time comparison), and a signature
shorter than the expected digest must be rejected without reading
past its end (guards the length check). The AddressSanitizer job in
CI will catch a regression of the latter.
Internal Vulnerability Advisory: open62541-SA-2026-0038
Use the common name when available and fall back to the subject for CRLs and
certificates without a common name.
Check path formatting, propagate storage errors, and clean up trust-list data
on every exit path.
Pass the certificate and output subject in the documented order. The reversed arguments caused the mbedTLS implementation to clear the decoded certificate buffer before request cleanup, leaking the original allocation.