mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
feat(client): Check if the "CreatedAt" timestamp of the SecurityToken matches the current system clock - consistently use monotonic clock internally
This commit is contained in:
parent
aaf6ebdf99
commit
6a0ed7d623
@ -531,13 +531,6 @@ processOPNResponse(UA_Client *client, const UA_ByteString *message) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Response.securityToken.revisedLifetime is UInt32 we need to cast it to
|
||||
* DateTime=Int64 we take 75% of lifetime to start renewing as described in
|
||||
* standard */
|
||||
client->nextChannelRenewal = UA_DateTime_nowMonotonic()
|
||||
+ (UA_DateTime) (response.securityToken.revisedLifetime
|
||||
* (UA_Double) UA_DATETIME_MSEC * 0.75);
|
||||
|
||||
/* Move the nonce out of the response */
|
||||
UA_ByteString_clear(&client->channel.remoteNonce);
|
||||
client->channel.remoteNonce = response.serverNonce;
|
||||
@ -550,6 +543,29 @@ processOPNResponse(UA_Client *client, const UA_ByteString *message) {
|
||||
client->channel.securityToken = response.securityToken;
|
||||
client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT;
|
||||
|
||||
/* Log a warning if the SecurityToken is not "fresh". Use the normal system
|
||||
* clock to do the comparison. */
|
||||
UA_EventLoop *el = client->config.eventLoop;
|
||||
UA_DateTime wallClockNow = el->dateTime_now(el);
|
||||
if(wallClockNow - client->channel.securityToken.createdAt >= UA_DATETIME_SEC * 10 ||
|
||||
wallClockNow - client->channel.securityToken.createdAt <= -UA_DATETIME_SEC * 10)
|
||||
UA_LOG_WARNING_CHANNEL(client->config.logging, &client->channel, "The \"CreatedAt\" "
|
||||
"timestamp of the received ChannelSecurityToken does not match "
|
||||
"with the local system clock");
|
||||
|
||||
/* The internal "monotonic" clock is used by the SecureChannel to validate
|
||||
* that the SecurityToken is still valid. The monotonic clock is independent
|
||||
* from the system clock getting changed or synchronized to a master clock
|
||||
* during runtime. */
|
||||
client->channel.securityToken.createdAt = el->dateTime_nowMonotonic(el);
|
||||
|
||||
/* Response.securityToken.revisedLifetime is UInt32, we need to cast it to
|
||||
* DateTime=Int64. After 75% of the lifetime the renewal takes place as
|
||||
* described in standard */
|
||||
client->nextChannelRenewal = client->channel.securityToken.createdAt +
|
||||
(UA_DateTime) (response.securityToken.revisedLifetime *
|
||||
(UA_Double) UA_DATETIME_MSEC * 0.75);
|
||||
|
||||
/* Compute the new local keys. The remote keys are updated when a message
|
||||
* with the new SecurityToken is received. */
|
||||
retval = UA_SecureChannel_generateLocalKeys(&client->channel);
|
||||
|
@ -255,6 +255,24 @@ START_TEST(SecureChannel_serverCert) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* The monotonic clock is 24h in the future */
|
||||
static UA_DateTime
|
||||
dateTime_nowMonotonicWithOffset(UA_EventLoop *el) {
|
||||
return UA_DateTime_now() + (UA_DATETIME_SEC * 24 * 3600);
|
||||
}
|
||||
|
||||
/* Simulate a deviation between the "wallclock" and the monotonic clock */
|
||||
START_TEST(SecureChannel_differentMonotonicClock) {
|
||||
UA_Client *client = UA_Client_new();
|
||||
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
|
||||
|
||||
UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
UA_Client_delete(client);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(void) {
|
||||
TCase *tc_sc = tcase_create("Client SecureChannel");
|
||||
tcase_add_checked_fixture(tc_sc, setup, teardown);
|
||||
@ -265,6 +283,7 @@ int main(void) {
|
||||
tcase_add_test(tc_sc, SecureChannel_reconnect);
|
||||
tcase_add_test(tc_sc, SecureChannel_cableunplugged);
|
||||
tcase_add_test(tc_sc, SecureChannel_serverCert);
|
||||
tcase_add_test(tc_sc, SecureChannel_differentMonotonicClock);
|
||||
|
||||
Suite *s = suite_create("Client");
|
||||
suite_add_tcase(s, tc_sc);
|
||||
|
Loading…
Reference in New Issue
Block a user