ua_securechannel_manager.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include "ua_securechannel_manager.h"
  2. #include "ua_session.h"
  3. #include "ua_server_internal.h"
  4. #define STARTCHANNELID 1
  5. #define STARTTOKENID 1
  6. UA_StatusCode
  7. UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_Server *server) {
  8. LIST_INIT(&cm->channels);
  9. cm->lastChannelId = STARTCHANNELID;
  10. cm->lastTokenId = STARTTOKENID;
  11. cm->currentChannelCount = 0;
  12. cm->server = server;
  13. return UA_STATUSCODE_GOOD;
  14. }
  15. void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
  16. channel_list_entry *entry, *temp;
  17. LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  18. LIST_REMOVE(entry, pointers);
  19. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  20. UA_free(entry);
  21. }
  22. }
  23. static void removeSecureChannel(UA_SecureChannelManager *cm, channel_list_entry *entry){
  24. LIST_REMOVE(entry, pointers);
  25. UA_atomic_add(&cm->currentChannelCount, (UA_UInt32)-1);
  26. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  27. #ifndef UA_ENABLE_MULTITHREADING
  28. UA_free(entry);
  29. #else
  30. UA_Server_delayedFree(cm->server, entry);
  31. #endif
  32. }
  33. /* remove channels that were not renewed or who have no connection attached */
  34. void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime nowMonotonic) {
  35. channel_list_entry *entry, *temp;
  36. LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  37. UA_DateTime timeout = entry->channel.securityToken.createdAt +
  38. (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_MSEC_TO_DATETIME);
  39. if(timeout < nowMonotonic || !entry->channel.connection) {
  40. UA_LOG_DEBUG_CHANNEL(cm->server->config.logger, &entry->channel, "SecureChannel has timed out");
  41. removeSecureChannel(cm, entry);
  42. } else if(entry->channel.nextSecurityToken.tokenId > 0) {
  43. UA_SecureChannel_revolveTokens(&entry->channel);
  44. }
  45. }
  46. }
  47. /* remove the first channel that has no session attached */
  48. static UA_Boolean purgeFirstChannelWithoutSession(UA_SecureChannelManager *cm) {
  49. channel_list_entry *entry;
  50. LIST_FOREACH(entry, &cm->channels, pointers) {
  51. if(LIST_EMPTY(&(entry->channel.sessions))){
  52. UA_LOG_DEBUG_CHANNEL(cm->server->config.logger, &entry->channel,
  53. "Channel was purged since maxSecureChannels was reached and channel had no session attached");
  54. removeSecureChannel(cm, entry);
  55. UA_assert(entry != LIST_FIRST(&cm->channels));
  56. return true;
  57. }
  58. }
  59. return false;
  60. }
  61. UA_StatusCode
  62. UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
  63. const UA_OpenSecureChannelRequest *request,
  64. UA_OpenSecureChannelResponse *response) {
  65. if(request->securityMode != UA_MESSAGESECURITYMODE_NONE)
  66. return UA_STATUSCODE_BADSECURITYMODEREJECTED;
  67. //check if there exists a free SC, otherwise try to purge one SC without a session
  68. //the purge has been introduced to pass CTT, it is not clear what strategy is expected here
  69. if(cm->currentChannelCount >= cm->server->config.maxSecureChannels && !purgeFirstChannelWithoutSession(cm)){
  70. return UA_STATUSCODE_BADOUTOFMEMORY;
  71. }
  72. /* Set up the channel */
  73. channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
  74. if(!entry)
  75. return UA_STATUSCODE_BADOUTOFMEMORY;
  76. UA_SecureChannel_init(&entry->channel);
  77. entry->channel.securityToken.channelId = cm->lastChannelId++;
  78. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  79. entry->channel.securityToken.createdAt = UA_DateTime_now();
  80. entry->channel.securityToken.revisedLifetime =
  81. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  82. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  83. if(entry->channel.securityToken.revisedLifetime == 0) /* lifetime 0 -> set the maximum possible */
  84. entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  85. UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
  86. entry->channel.serverAsymAlgSettings.securityPolicyUri =
  87. UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  88. UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
  89. /* Set the response */
  90. UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
  91. UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
  92. response->responseHeader.timestamp = UA_DateTime_now();
  93. /* Now overwrite the creation date with the internal monotonic clock */
  94. entry->channel.securityToken.createdAt = UA_DateTime_nowMonotonic();
  95. /* Set all the pointers internally */
  96. UA_Connection_attachSecureChannel(conn, &entry->channel);
  97. LIST_INSERT_HEAD(&cm->channels, entry, pointers);
  98. UA_atomic_add(&cm->currentChannelCount, 1);
  99. return UA_STATUSCODE_GOOD;
  100. }
  101. UA_StatusCode
  102. UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
  103. const UA_OpenSecureChannelRequest *request,
  104. UA_OpenSecureChannelResponse *response) {
  105. UA_SecureChannel *channel = conn->channel;
  106. if(!channel)
  107. return UA_STATUSCODE_BADINTERNALERROR;
  108. /* if no security token is already issued */
  109. if(channel->nextSecurityToken.tokenId == 0) {
  110. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  111. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  112. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  113. channel->nextSecurityToken.revisedLifetime =
  114. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  115. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  116. if(channel->nextSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
  117. channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  118. }
  119. /* invalidate the old nonce */
  120. if(channel->clientNonce.data)
  121. UA_ByteString_deleteMembers(&channel->clientNonce);
  122. /* set the response */
  123. UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
  124. UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
  125. UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  126. /* reset the creation date to the monotonic clock */
  127. channel->nextSecurityToken.createdAt = UA_DateTime_nowMonotonic();
  128. return UA_STATUSCODE_GOOD;
  129. }
  130. UA_SecureChannel *
  131. UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  132. channel_list_entry *entry;
  133. LIST_FOREACH(entry, &cm->channels, pointers) {
  134. if(entry->channel.securityToken.channelId == channelId)
  135. return &entry->channel;
  136. }
  137. return NULL;
  138. }
  139. UA_StatusCode
  140. UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  141. channel_list_entry *entry;
  142. LIST_FOREACH(entry, &cm->channels, pointers) {
  143. if(entry->channel.securityToken.channelId == channelId)
  144. break;
  145. }
  146. if(!entry)
  147. return UA_STATUSCODE_BADINTERNALERROR;
  148. removeSecureChannel(cm, entry);
  149. return UA_STATUSCODE_GOOD;
  150. }