ua_securechannel_manager.c 8.1 KB

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