|
@@ -266,11 +266,18 @@ UA_SecureChannel_revolveTokens(UA_SecureChannel *channel) {
|
|
|
if(channel->nextSecurityToken.tokenId == 0) // no security token issued
|
|
|
return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
|
|
|
|
|
|
- //FIXME: not thread-safe
|
|
|
- memcpy(&channel->securityToken, &channel->nextSecurityToken,
|
|
|
- sizeof(UA_ChannelSecurityToken));
|
|
|
+ //FIXME: not thread-safe ???? Why is this not thread safe?
|
|
|
+ UA_ChannelSecurityToken_deleteMembers(&channel->previousSecurityToken);
|
|
|
+ UA_ChannelSecurityToken_copy(&channel->securityToken, &channel->previousSecurityToken);
|
|
|
+
|
|
|
+ UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
|
|
|
+ UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &channel->securityToken);
|
|
|
+
|
|
|
+ UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken);
|
|
|
UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
|
|
|
- return UA_SecureChannel_generateNewKeys(channel);
|
|
|
+
|
|
|
+ /* remote keys are generated later on */
|
|
|
+ return UA_SecureChannel_generateLocalKeys(channel, channel->securityPolicy);
|
|
|
}
|
|
|
/***************************/
|
|
|
/* Send Asymmetric Message */
|
|
@@ -1133,15 +1140,53 @@ checkAsymHeader(UA_SecureChannel *const channel,
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
|
+static UA_StatusCode
|
|
|
+checkPreviousToken(UA_SecureChannel *const channel, const UA_UInt32 tokenId) {
|
|
|
+ if(tokenId != channel->previousSecurityToken.tokenId)
|
|
|
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
|
|
|
+
|
|
|
+ UA_DateTime timeout = channel->previousSecurityToken.createdAt +
|
|
|
+ (UA_DateTime)((UA_Double)channel->previousSecurityToken.revisedLifetime *
|
|
|
+ (UA_Double)UA_DATETIME_MSEC *
|
|
|
+ 1.25);
|
|
|
+
|
|
|
+ if(timeout < UA_DateTime_nowMonotonic()) {
|
|
|
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ return UA_STATUSCODE_GOOD;
|
|
|
+}
|
|
|
+
|
|
|
static UA_StatusCode
|
|
|
checkSymHeader(UA_SecureChannel *const channel,
|
|
|
- const UA_UInt32 tokenId) {
|
|
|
+ const UA_UInt32 tokenId, UA_Boolean allowPreviousToken) {
|
|
|
+
|
|
|
+ if(tokenId == channel->securityToken.tokenId) {
|
|
|
+ if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
|
|
|
+ (channel->securityToken.createdAt +
|
|
|
+ (channel->securityToken.revisedLifetime * UA_DATETIME_MSEC))
|
|
|
+ < UA_DateTime_nowMonotonic()) {
|
|
|
+ UA_SecureChannel_deleteMembersCleanup(channel);
|
|
|
+ return UA_STATUSCODE_BADSECURECHANNELCLOSED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if(tokenId != channel->securityToken.tokenId) {
|
|
|
- if(tokenId != channel->nextSecurityToken.tokenId)
|
|
|
- return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
|
|
|
+ if(tokenId != channel->nextSecurityToken.tokenId) {
|
|
|
+ if(allowPreviousToken)
|
|
|
+ return checkPreviousToken(channel, tokenId);
|
|
|
+ else
|
|
|
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
|
|
|
+ }
|
|
|
return UA_SecureChannel_revolveTokens(channel);
|
|
|
}
|
|
|
|
|
|
+ if(channel->previousSecurityToken.tokenId != 0) {
|
|
|
+ UA_StatusCode retval = UA_SecureChannel_generateRemoteKeys(channel, channel->securityPolicy);
|
|
|
+ UA_ChannelSecurityToken_deleteMembers(&channel->previousSecurityToken);
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
@@ -1153,15 +1198,17 @@ putPayload(UA_SecureChannel *const channel, UA_UInt32 const requestId, UA_Messag
|
|
|
case UA_CHUNKTYPE_FINAL:
|
|
|
return addChunkPayload(channel, requestId, messageType,
|
|
|
chunkPayload, chunkType == UA_CHUNKTYPE_FINAL);
|
|
|
- case UA_CHUNKTYPE_ABORT:deleteLatestMessage(channel, requestId);
|
|
|
+ case UA_CHUNKTYPE_ABORT:
|
|
|
+ deleteLatestMessage(channel, requestId);
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
- default:return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
|
|
|
+ default:
|
|
|
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* The chunk body begins after the SecureConversationMessageHeader */
|
|
|
static UA_StatusCode
|
|
|
-decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk) {
|
|
|
+decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk, UA_Boolean allowPreviousToken) {
|
|
|
/* Decode the MessageHeader */
|
|
|
size_t offset = 0;
|
|
|
UA_SecureConversationMessageHeader messageHeader;
|
|
@@ -1212,7 +1259,7 @@ decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk) {
|
|
|
symmetricSecurityHeader.tokenId = channel->securityToken.tokenId;
|
|
|
#endif
|
|
|
|
|
|
- retval = checkSymHeader(channel, symmetricSecurityHeader.tokenId);
|
|
|
+ retval = checkSymHeader(channel, symmetricSecurityHeader.tokenId, allowPreviousToken);
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
return retval;
|
|
|
|
|
@@ -1257,33 +1304,29 @@ decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk) {
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
return retval;
|
|
|
|
|
|
-#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
|
|
|
/* Check the sequence number. Skip sequence number checking for fuzzer to
|
|
|
* improve coverage */
|
|
|
if(sequenceNumberCallback == NULL)
|
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
|
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
|
|
|
+ retval = UA_STATUSCODE_GOOD;
|
|
|
+#else
|
|
|
retval = sequenceNumberCallback(channel, sequenceNumber);
|
|
|
+#endif
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
return retval;
|
|
|
-#endif
|
|
|
|
|
|
return putPayload(channel, requestId, messageType, chunkType, &chunkPayload);
|
|
|
}
|
|
|
|
|
|
UA_StatusCode
|
|
|
-UA_SecureChannel_decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk) {
|
|
|
+UA_SecureChannel_decryptAddChunk(UA_SecureChannel *channel, const UA_ByteString *chunk,
|
|
|
+ UA_Boolean allowPreviousToken) {
|
|
|
/* Has the SecureChannel timed out? */
|
|
|
if(channel->state == UA_SECURECHANNELSTATE_CLOSED)
|
|
|
return UA_STATUSCODE_BADSECURECHANNELCLOSED;
|
|
|
- if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
|
|
|
- (channel->securityToken.createdAt +
|
|
|
- (channel->securityToken.revisedLifetime * UA_DATETIME_MSEC))
|
|
|
- < UA_DateTime_nowMonotonic()) {
|
|
|
- UA_SecureChannel_deleteMembersCleanup(channel);
|
|
|
- return UA_STATUSCODE_BADSECURECHANNELCLOSED;
|
|
|
- }
|
|
|
|
|
|
- UA_StatusCode retval = decryptAddChunk(channel, chunk);
|
|
|
+ UA_StatusCode retval = decryptAddChunk(channel, chunk, allowPreviousToken);
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
UA_SecureChannel_deleteMembersCleanup(channel);
|
|
|
return retval;
|