ua_securechannel_manager.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. 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. channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
  73. if(!entry)
  74. return UA_STATUSCODE_BADOUTOFMEMORY;
  75. #ifndef UA_ENABLE_MULTITHREADING
  76. cm->currentChannelCount++;
  77. #else
  78. cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, 1);
  79. #endif
  80. UA_SecureChannel_init(&entry->channel);
  81. response->responseHeader.stringTableSize = 0;
  82. response->responseHeader.timestamp = UA_DateTime_now();
  83. response->serverProtocolVersion = 0;
  84. entry->channel.securityToken.channelId = cm->lastChannelId++;
  85. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  86. entry->channel.securityToken.createdAt = UA_DateTime_now();
  87. entry->channel.securityToken.revisedLifetime =
  88. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  89. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  90. /* lifetime 0 -> set the maximum possible */
  91. if(entry->channel.securityToken.revisedLifetime == 0)
  92. entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  93. UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
  94. entry->channel.serverAsymAlgSettings.securityPolicyUri = UA_STRING_ALLOC(
  95. "http://opcfoundation.org/UA/SecurityPolicy#None");
  96. UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
  97. UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
  98. UA_ChannelSecurityToken_copy(&entry->channel.securityToken,
  99. &response->securityToken);
  100. UA_Connection_attachSecureChannel(conn, &entry->channel);
  101. LIST_INSERT_HEAD(&cm->channels, entry, pointers);
  102. return UA_STATUSCODE_GOOD;
  103. }
  104. UA_StatusCode
  105. UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
  106. const UA_OpenSecureChannelRequest *request,
  107. UA_OpenSecureChannelResponse *response) {
  108. UA_SecureChannel *channel = conn->channel;
  109. if(!channel)
  110. return UA_STATUSCODE_BADINTERNALERROR;
  111. /* if no security token is already issued */
  112. if(channel->nextSecurityToken.tokenId == 0) {
  113. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  114. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  115. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  116. channel->nextSecurityToken.revisedLifetime =
  117. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  118. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  119. /* lifetime 0 -> return the max lifetime */
  120. if(channel->nextSecurityToken.revisedLifetime == 0)
  121. channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  122. }
  123. if(channel->clientNonce.data)
  124. UA_ByteString_deleteMembers(&channel->clientNonce);
  125. UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
  126. UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
  127. UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  128. return UA_STATUSCODE_GOOD;
  129. }
  130. UA_SecureChannel * UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  131. channel_list_entry *entry;
  132. LIST_FOREACH(entry, &cm->channels, pointers) {
  133. if(entry->channel.securityToken.channelId == channelId)
  134. return &entry->channel;
  135. }
  136. return NULL;
  137. }
  138. UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  139. channel_list_entry *entry;
  140. LIST_FOREACH(entry, &cm->channels, pointers) {
  141. if(entry->channel.securityToken.channelId == channelId)
  142. break;
  143. }
  144. if(!entry)
  145. return UA_STATUSCODE_BADINTERNALERROR;
  146. LIST_REMOVE(entry, pointers);
  147. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  148. #ifndef UA_ENABLE_MULTITHREADING
  149. cm->currentChannelCount--;
  150. UA_free(entry);
  151. #else
  152. cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
  153. UA_Server_delayedFree(cm->server, entry);
  154. #endif
  155. return UA_STATUSCODE_GOOD;
  156. }