Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change of system time leads to closing of secure channel #2055

Open
1 of 5 tasks
gailjkm opened this issue Jan 18, 2023 · 4 comments
Open
1 of 5 tasks

Change of system time leads to closing of secure channel #2055

gailjkm opened this issue Jan 18, 2023 · 4 comments

Comments

@gailjkm
Copy link

gailjkm commented Jan 18, 2023

Type of issue

  • Bug
  • Enhancement
  • Compliance
  • Question
  • Help wanted

Current Behavior

I am using the OPCUA-Library to connect a c# client application to a server on a Siemens plc.
The connection is up and running.
Values are asynchronously written to the plc with session.BeginWrite()

When I change the system time on the client side to at least 1 hour in the future, then the connection breaks instant.
A change of the system time to the past doesn’t have any effect, no matter how big the time difference is.

The system time could also be changed by the NTP client, in the case of a not initially correct set hardware clock.

The root cause is in the implementation of the timeouts. They save a timestamp and compared it with the current system time (DateTime.UtcNow). At the moment the system time gets changed, the timeout of the current token (and possibly an already prepared new token) for the secure channel gets triggered immediate and the secure channel gets closed.

Even with an automatic reconnect the current running publish events gets lost without any notification to the application.
The session and the subscriptions are transferred to a new secure channel, but failed publish requests are not cached and not retried.

Expected Behavior

The secure channel should not close and the connection should stay alive.
If this is not possible, the current publish tasks should not fail silently but be resent instead.
If this is also not possible at least an error notification should be sent to the application for each failing asynchronous write call.

Steps To Reproduce

  1. Start a client using the opcua library
  2. Set the system time of the client more than 1 hour into the future.

Environment

- OS: Windows 10
- Environment: Visual Studio 2017
- Runtime: .NET 4.6.2
- Nuget Version: 1.4.371.50
- Component: Opc.Ua.Client
- Server: Siemens PLC 
- Client:

Anything else?

Looks similar to issue #1859

@gailjkm gailjkm changed the title <title> Change of system time leads to closing of secure channel Jan 18, 2023
@gailjkm
Copy link
Author

gailjkm commented Apr 3, 2023

Would it make sense to base the timestamping of the token on system time independent ticks?

There is the property Environment.TickCount or in newer frameworks the Environment.TickCount64, which counts the system timer continously forward. No matter, if and how far the system clock gets changed.
This would mean, the token ist valid for the given time, in my case 1 hour. The time span would always be 1h in real time, indepent from any system clock changes.

Would this be a reasonable solution, or is there on other places some need of the token.createdAt timestamp being actually current UTC time?

The source code concerned is

DateTime expiryTime = token.CreatedAt.AddMilliseconds(token.Lifetime);
double timeToRenewal = ((expiryTime.Ticks - DateTime.UtcNow.Ticks) / TimeSpan.TicksPerMillisecond) * TcpMessageLimits.TokenRenewalPeriod;

The actual evaluation takes place at

public bool Expired
{
get
{
if (DateTime.UtcNow > m_createdAt.AddMilliseconds(m_lifetime))
{
return true;
}
return false;
}
}

gailjkm added a commit to gailjkm/UA-.NETStandard that referenced this issue Apr 18, 2023
This is a barely tested proof-of-concept for timeouts independent of the system clock.
gailjkm added a commit to gailjkm/UA-.NETStandard that referenced this issue Apr 26, 2023
gailjkm added a commit to gailjkm/UA-.NETStandard that referenced this issue Apr 26, 2023
gailjkm added a commit to gailjkm/UA-.NETStandard that referenced this issue Apr 26, 2023
Sligthly more correct calculation:
(re-)calculate the remaining time as fraction of the expected lifetime, not as fraction of the age of the token.
gailjkm added a commit to gailjkm/UA-.NETStandard that referenced this issue Apr 26, 2023
@gailjkm
Copy link
Author

gailjkm commented Apr 26, 2023

The solution in UA-.NETStandard/clock-independent-timeouts works for me in my environment.

See it as a proof of concept.
I have not yet created a pull request, because i am not sure about any negative side effects. Comments would be appreciated.

@mregen
Copy link
Contributor

mregen commented Jan 14, 2024

Thanks for the prototype. Planning to use the Stopwatch clock for #2457 / #2458.

@gailjkm
Copy link
Author

gailjkm commented Mar 14, 2024

Just adding some cross reference:
The topic is also worked on in issue #2546 for the current 1.5 series

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants