* #2896: Write output arguments for good and uncertain status code
When a method state's call method is invoked the output arguments should be written in case the status code is good or uncertain. This behavior would be conform with the current specification.
* #2896: The service result corresponds the method call result
The result of the Call method in the CustomNodeManager2 class represents the status of the CallMethodResult. It does not correspond to the ServiceResult of the CallResponse, thus returning Good as a general response is incorrect behavior.
In the read NodeId servcie call an enum is by default cast to Int32, so the cast to ushort is needed here to return the expected type for the AccessRestrictions.
A new configuration variable
<HttpsMutualTls>true</HttpsMutualTls>
enables the mutual TLS authentication support. The behavior of the TLS endpoint changes as the following:
HttpsMutualTls is true:
The server checks the trust on the certificate which is used by the client for TLS authentication. It must be a valid OPC UA application certificate which is trusted.
A client can still connect without providing a client certificate, but then it is only able to call discovery services.
In order to create a session, the client must use the same application certificate that was used for the TLS channel.
HttpsMutualTls is false:
- There is no application authentication. The server endpoint uses security None and there is no client application authentication.
Instead, only user authentication is used to secure the server, anonymous user authentication is disabled.
Discovery service calls are supported.
Co-authored-by: Martin Regen <mregen@microsoft.com>
For better client diagnostic it is important to have access to the channel token. Today tooling must monitor the channel token change to be aware of the current token, it is more efficient for the tooling to be called back when the token changes. This can be now accomplished in that the owner of a client (Discovery, Session) can retrieve the Transport channel after connect, read the current token and register a change callback.
* Add OnTokenActivated event for token change notifications
Added a new event `OnTokenActivated` to the `UaChannelBase` class in the `Opc.Ua` namespace to notify when a channel token is activated. Implemented this event in the `HttpsTransportChannel` class within the `Opc.Ua.Bindings` namespace. Introduced a protected internal `OnTokenActivated` event handler in the `UaSCBinaryChannel.Symmetric` class, invoked during token changes in the `ActivateToken` and `DiscardTokens` methods. Cleaned up the event handler in the `Dispose` method of the `UaSCBinaryClientChannel` class. Registered the event handler with the internal channel in the `UaSCBinaryTransportChannel` class. Added a new delegate `ChannelTokenActivatedEventHandler` in the `ITransportChannel` interface and updated the interface to include the `OnTokenActivated` event. Made minor formatting and comment adjustments for improved readability and consistency.
* Include channel in callback
Co-authored-by: Marc Schier <marcschier@users.noreply.github.com>
For better client diagnostic it is important to have access to the channel token. Today tooling must monitor the channel token change to be aware of the current token, it is more efficient for the tooling to be called back when the token changes. This can be now accomplished in that the owner of a client (Discovery, Session) can retrieve the Transport channel after connect, read the current token and register a change callback.
* Add OnTokenActivated event for token change notifications
Added a new event `OnTokenActivated` to the `UaChannelBase` class in the `Opc.Ua` namespace to notify when a channel token is activated. Implemented this event in the `HttpsTransportChannel` class within the `Opc.Ua.Bindings` namespace. Introduced a protected internal `OnTokenActivated` event handler in the `UaSCBinaryChannel.Symmetric` class, invoked during token changes in the `ActivateToken` and `DiscardTokens` methods. Cleaned up the event handler in the `Dispose` method of the `UaSCBinaryClientChannel` class. Registered the event handler with the internal channel in the `UaSCBinaryTransportChannel` class. Added a new delegate `ChannelTokenActivatedEventHandler` in the `ITransportChannel` interface and updated the interface to include the `OnTokenActivated` event. Made minor formatting and comment adjustments for improved readability and consistency.
* Include channel in callback
- reduce EscapeString overhead in JSON encoder
- client monitored items: allocate queues only if needed
- replace SortedDictionary with Dictionary for perf reasons
- revert a change in padding and reduce a log level
Clients that are failing too often to pass the security validationin a certain interval of time with the Basic128 security profile are now tracked and blocked.
- Channels are not disposed (client and server)
- During long running tests an HMAC object leak was observed.
- The HMAC and SymmetricSign objects were not disposed after use, leading to a small incremental memory leak per key renewal.
- The channel token lifetime is calculated by the system clock, which can change. Instead use the continous HiResClock.TickCount to calculate the lifetimes.
- Token renewal and connection requests are not removed from the request dictionary
Improvements:
- Make ChannelToken disposable. Dispose channels.
- Dispose HMAC and SymmetricSign objects after use.
- Use TickCount to calculate key renewal and key expiry.
- Introduce a 5% jitter to the token renewal timer, to avoid token renewal storms.
- Reduce the allocation per use of the HMAC objects by using ReadOnlySpan and avoid MemoryStream.
- Port support for ECC NIST/Brainpool profiles from prototyping_ecc branch
- Implement CertProvider to load certs per connection / profile
- Backward compatibility of configuration for existing apps
- SecurityConfiguration specifies app cert types for each profile
- Autodetect the ECC support for brainpool/nist based on platform (mac OS 10 doesn't support brainpool)
- ECC supported on net48 / net5.0 / net 6.0 / netstandard2.1
- ECC supported on windows / linux / macOS (brainpool not < macOS11)
- Self signed certs for each profile are created on start similar to RSA
- RSA only profiles are supported on .NET standard 2.0
Co-authored-by: Martin Regen <mregen@microsoft.com>
- During a reconnect fault the channels remain open and are quickly exhausted. Immediately close channels in Opening state similar to channels in Connecting state instead of waiting for timeout cleanup.
- The channel concurrentDictionary sometimes failed to remove a channel. Removing ContainsKey and retry with TryAdd fixes the problem.
Server: Fix a deadlock in the binary channel cleanup (regression from secure channel cleanup)
Server: Use ConcurrentDictionary for sessions and channels to reduce locking overhead
Server: Replace legacy implementation of NodeIdDictionary with standard dictionary, as with IEqualityComparer the look up is much faster than specialized SortedDictionary for each NodeId Type.
Co-authored-by: Luis Cantero <luis@cantero.org>
Add the reconnect exception text to the log message, otherwise the exception is filtered out.
Turn off the trace logging in tests, as it causes timeout issues on some ci VMs
reduce callbacks if client reconnect and call AddItems
Fix BadNothingToDo when Loading dictionaries
Revert benchmark.net to v13 due to weird build dependency issues with 14.x
Fix the hello message, if the send and receive buffer size is different.
The error was undetected as long as send and receive buffer size were the same size.
Ensure the right values are used for client and server and add some more sanity checks on buffer sizes.
Added a new method ManagedBrowse to the UA client, which takes care of calling browse next after calling browse, when necessary. It also handles the status codes BadNoContinuationPoint and BadInvalidContinuationPoint.
Added support for the new method in ISession, TraceableSession, Session and SessionAsync.
Use the new methods in the NodeCache and other API that use browse (FetchRefrences etc).
Added unit tests which verify correct behavior of the new methods.
- let all Xml encoders and decoders follow the dispose pattern, similar to all the other encoders.
- Add fuzz targets for Xml and binary indempotent fuzzer.
- add a ReadOnlySpan<byte> signature for WriteByteString
- add ArrayPool based IBufferWriter<byte> to support encoding of large byte string with buffers
- add Azure DevOps ci pipeline tests with known artifacts that caused fuzzing errors, to catch regressions.
- change macOS 11 ci builds to newer ones, macOS 11 is deprecated
- fix Opc.Ua.Client EventSource message numbering
- bump nerdgit to 3.6.139
- include .NET Standard 2.0 builds back in Nuget packages for client and server (complex type support requires netcoreapp2.1 which is end of life)
- include .NET Framework 4.7.2 as lowest supported .NET Framework platform
- move https client channel back to core library, as it requires only netstandard2.0 and has no other dependencies.
- Opc.Ua.Https is now only needed for a https server with kestrel.
- fix security warning for system.private.uri
- upload Quickstarts.Servers to the preview feed to allow use in the samples repo and avoid duplicate codebase
This fix makes the client select the most secure UserIdentity Token if a server offers more than one.
Before the client just selected the first UserIdentity Token offered by the server.
Also calculate the security level by the client, as the unsecure response of a server could be spoofed.
- Fix the UserIdentity constructor to load the private key of a provided certificateIdenifier.
- make UserIdentity constructor throw a ServiceResultException when a Certificate with no private key is specified.
- extend console reference client with two new parameters:
-uc Thumbprint of a user certifiate located in the TrustedUserCertificatesStore
-ucp Password of the private key of the user certificate
- add documentation for console reference client
Fix that if a socket is closed, new service calls are queued and a new channel is established without reconnect / activate.
Add some logic which ensures that a BeginConnect operation is only started if a valid service call is queued first.
The activate is prepared by the session reconnect handler which may take some time to respond. Until then, all other service fail immediately with BadNotConnected.
To detect socket failures earlier, the PublishRequest and KeepAlive send are also hooked up to the KeepAliveError to trigger a reconnect. To disable the keep alive timing calcualtion, an additional variable tracks the statuscode of the last error to set KeepAliveStopped to true.
* Avoid user configuration errors by setting unaligned max message size values, fix defaults.
* Set the MaxMessageSize defaults to multiple of MinBufferSize to avoid rounding errors in other UA implementations.
- Add a solution to provide fuzzer support for afl-fuzz and libfuzzer.
- Add fuzz targets for Binary, Json and Xml encoder and decoder fuzzing. For afl-fuzz and libfuzzer.
- Fix issues in encoders and decoders when unexpected exceptions are returned. The expectation is to return only ServiceResultException with BadDecodingError, BadEncodingError or BadEncodingLimitsExceeded.
- Add a tool to create Testcases.
- Add a tool to playback crashes and timeouts.
- Solution is extensible with common files to discover new fuzz targets by reflection. New fuzz projects can share many files with the first project.
- Breaking change: Fix how BinaryDecoder is used: Previously, calling close on the BinaryDecoder implicitly disposed the stream. Change behavior so that `using` pattern can be applied across the board.
* Added MaxChannelCount and detect and cleanup "stale" channels based on ChannelLifetime
* Add Environment.TickCount as time reference
* Set a socket backlog value to avoid socket open overflow
* Added a ChannelKeepAlive to signal when a session is still active
* Add options to console client to leak channels and run connect loop forever
Co-authored-by: Martin Regen <mregen@microsoft.com>
- Implement `int Read(Span<byte> buffer)` and `void Write(ReadOnlySpan<byte> buffer)` in ArraySegmentStream
- for ArraySegmentStream streaming lower the CPU load for .NET8 OPC UA binary encoding/decoding by 50%
- Implement dispose to return buffers that were not transferred.
- Implement a GetSequence in ArraySegmentStream
Added redaction (disabled by default)
Added redaction strategies for username, password, endpoint, and exception message.
Updated logging to use redaction where it was critical
In #2510 a message type check was added to catch non UA service connections earlier.
But the Abort message type was missing in the check, so an Abort caused a disconnect.
However, in such a case the transport can just continue with the next message.
NodeState classes are not thread safe. In many places event handlers are handled in a manner that can cause NullReferenceException in a case of a bad timing. In addition, in some places non-thread-safe collections are iterated which could cause issues if the collections are changed at the same time.
This PR addresses the aforementioned issues by using local variables for event handlers and then making null check and calling them. When applicable null-conditional operators are used. Non-thread-safe collection iteration is guarded by locking. The issues were reproduces with unit tests part of this PR and also the fix was verified by running the same unit tests.
During high load there were a few portions in the send/receive pipeline identified which may cause lock contention and thread starvation due to locks:
- Remove lock for the codepath when a incoming message is processed.
- Add a concurrent dictionary to allow for the processing of OperationCompleted and to add new requests without locking
- Allow to process normal service requests without locking
Due to the change it is possible to send KeepAlive even when a incoming message is received.
- fix NormalizeHostName when host ip addresses are not returned on macOS, try the native hostname
- Ensure endpoints are returned even if the client url port do not match (similar to client)
- Improve endpoint tests
Fix warnings regarding localization, CLS compliance, performance. No functional changes.
Many but not all adressed:
CA1859
CA1868
CA1305
CA1310
CA1861
- based on the discussion, use IFormatProvider where appropriate in ToString
- Reduce socket log output and demote to Trace
- Check for invalid chunk header and reduce log output
- Close socket immediately if a bad chunk header is detected (e.g. if socket is opened by another protocol)
- Expose Remote endpoint for application
- Simplify the BeginConnect implementation, which is an artifact to support IPv6 on .NET Standard 1.3 and UWP.
- Dual stack is supported by .NET, and the DNS resolution in the socket layer can be delegated to the platform.
- Fixes a race condition under high load, when BeginConnect throws a `Socket already connected` error.
- return serviceResult from client Session.Republish API (Breaking API change)
- refactor #2447. move SessionCreated virtual callback to end of Session.Create.
- fix bug in timeouthint calculation (always 0)
- do not print error if BadSequenceNumberUnknown is returned (server may have cleaned up himself)
- allow for a acktosend threshold when publish response requests are processed out of order
- revert EndAsync call to not throw timeout exception
- use static Randomgenerator instance in X509PfxUtils
- Print suppressible Certificate validation failed errors only if not auto accepted or accepted in callback.