ua_securechannel_manager.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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_SecureChannel_deleteMembersCleanup(&entry->channel);
  26. #ifndef UA_ENABLE_MULTITHREADING
  27. cm->currentChannelCount--;
  28. UA_free(entry);
  29. #else
  30. cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
  31. UA_Server_delayedFree(cm->server, entry);
  32. #endif
  33. }
  34. /* remove channels that were not renewed or who have no connection attached */
  35. void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now) {
  36. channel_list_entry *entry, *temp;
  37. LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  38. UA_DateTime timeout =
  39. entry->channel.securityToken.createdAt +
  40. (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_MSEC_TO_DATETIME);
  41. if(timeout < now || !entry->channel.connection) {
  42. UA_LOG_DEBUG_CHANNEL(cm->server->config.logger, (&entry->channel), "SecureChannel has timed out");
  43. removeSecureChannel(cm, entry);
  44. } else if(entry->channel.nextSecurityToken.tokenId > 0) {
  45. UA_SecureChannel_revolveTokens(&entry->channel);
  46. }
  47. }
  48. }
  49. /* remove the first channel that has no session attached */
  50. static UA_Boolean purgeFirstChannelWithoutSession(UA_SecureChannelManager *cm) {
  51. channel_list_entry *entry;
  52. LIST_FOREACH(entry, &cm->channels, pointers) {
  53. if(LIST_EMPTY(&(entry->channel.sessions))){
  54. UA_LOG_DEBUG_CHANNEL(cm->server->config.logger, (&entry->channel), "Channel was purged since maxSecureChannels was reached and channel had no session attached");
  55. removeSecureChannel(cm, entry);
  56. UA_assert(entry != LIST_FIRST(&cm->channels));
  57. return true;
  58. }
  59. }
  60. return false;
  61. }
  62. UA_StatusCode
  63. UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
  64. const UA_OpenSecureChannelRequest *request,
  65. UA_OpenSecureChannelResponse *response) {
  66. if(request->securityMode != UA_MESSAGESECURITYMODE_NONE)
  67. return UA_STATUSCODE_BADSECURITYMODEREJECTED;
  68. //check if there exists a free SC, otherwise try to purge one SC without a session
  69. //the purge has been introduced to pass CTT, it is not clear what strategy is expected here
  70. if(cm->currentChannelCount >= cm->server->config.maxSecureChannels && !purgeFirstChannelWithoutSession(cm)){
  71. return UA_STATUSCODE_BADOUTOFMEMORY;
  72. }
  73. channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
  74. if(!entry)
  75. return UA_STATUSCODE_BADOUTOFMEMORY;
  76. #ifndef UA_ENABLE_MULTITHREADING
  77. cm->currentChannelCount++;
  78. #else
  79. cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, 1);
  80. #endif
  81. UA_SecureChannel_init(&entry->channel);
  82. response->responseHeader.stringTableSize = 0;
  83. response->responseHeader.timestamp = UA_DateTime_now();
  84. response->serverProtocolVersion = 0;
  85. entry->channel.securityToken.channelId = cm->lastChannelId++;
  86. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  87. entry->channel.securityToken.createdAt = UA_DateTime_now();
  88. entry->channel.securityToken.revisedLifetime =
  89. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  90. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  91. /* lifetime 0 -> set the maximum possible */
  92. if(entry->channel.securityToken.revisedLifetime == 0)
  93. entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  94. UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
  95. entry->channel.serverAsymAlgSettings.securityPolicyUri = UA_STRING_ALLOC(
  96. "http://opcfoundation.org/UA/SecurityPolicy#None");
  97. UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
  98. UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
  99. UA_ChannelSecurityToken_copy(&entry->channel.securityToken,
  100. &response->securityToken);
  101. UA_Connection_attachSecureChannel(conn, &entry->channel);
  102. LIST_INSERT_HEAD(&cm->channels, entry, pointers);
  103. return UA_STATUSCODE_GOOD;
  104. }
  105. UA_StatusCode
  106. UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
  107. const UA_OpenSecureChannelRequest *request,
  108. UA_OpenSecureChannelResponse *response) {
  109. UA_SecureChannel *channel = conn->channel;
  110. if(!channel)
  111. return UA_STATUSCODE_BADINTERNALERROR;
  112. /* if no security token is already issued */
  113. if(channel->nextSecurityToken.tokenId == 0) {
  114. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  115. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  116. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  117. channel->nextSecurityToken.revisedLifetime =
  118. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  119. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  120. /* lifetime 0 -> return the max lifetime */
  121. if(channel->nextSecurityToken.revisedLifetime == 0)
  122. channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  123. }
  124. if(channel->clientNonce.data)
  125. UA_ByteString_deleteMembers(&channel->clientNonce);
  126. UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
  127. UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
  128. UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  129. return UA_STATUSCODE_GOOD;
  130. }
  131. UA_SecureChannel * 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 UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  140. channel_list_entry *entry;
  141. LIST_FOREACH(entry, &cm->channels, pointers) {
  142. if(entry->channel.securityToken.channelId == channelId)
  143. break;
  144. }
  145. if(!entry)
  146. return UA_STATUSCODE_BADINTERNALERROR;
  147. LIST_REMOVE(entry, pointers);
  148. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  149. #ifndef UA_ENABLE_MULTITHREADING
  150. cm->currentChannelCount--;
  151. UA_free(entry);
  152. #else
  153. cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
  154. UA_Server_delayedFree(cm->server, entry);
  155. #endif
  156. return UA_STATUSCODE_GOOD;
  157. }