ua_securechannel_manager.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. *
  5. * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014-2017 (c) Florian Palm
  7. * Copyright 2015-2016 (c) Sten Grüner
  8. * Copyright 2015 (c) Oleksiy Vasylyev
  9. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  10. * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
  11. */
  12. #include "ua_securechannel_manager.h"
  13. #include "ua_session.h"
  14. #include "ua_server_internal.h"
  15. #include "ua_transport_generated_handling.h"
  16. #define STARTCHANNELID 1
  17. #define STARTTOKENID 1
  18. UA_StatusCode
  19. UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_Server *server) {
  20. LIST_INIT(&cm->channels);
  21. // TODO: use an ID that is likely to be unique after a restart
  22. cm->lastChannelId = STARTCHANNELID;
  23. cm->lastTokenId = STARTTOKENID;
  24. cm->currentChannelCount = 0;
  25. cm->server = server;
  26. return UA_STATUSCODE_GOOD;
  27. }
  28. void
  29. UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
  30. channel_list_entry *entry, *temp;
  31. LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  32. LIST_REMOVE(entry, pointers);
  33. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  34. UA_free(entry);
  35. }
  36. }
  37. static void
  38. removeSecureChannelCallback(UA_Server *server, void *entry) {
  39. channel_list_entry *centry = (channel_list_entry *)entry;
  40. UA_SecureChannel_deleteMembersCleanup(&centry->channel);
  41. UA_free(entry);
  42. }
  43. static UA_StatusCode
  44. removeSecureChannel(UA_SecureChannelManager *cm, channel_list_entry *entry) {
  45. /* Add a delayed callback to remove the channel when the currently
  46. * scheduled jobs have completed */
  47. UA_StatusCode retval = UA_Server_delayedCallback(cm->server, removeSecureChannelCallback, entry);
  48. if(retval != UA_STATUSCODE_GOOD) {
  49. UA_LOG_WARNING(cm->server->config.logger, UA_LOGCATEGORY_SESSION,
  50. "Could not remove the secure channel with error code %s",
  51. UA_StatusCode_name(retval));
  52. return retval; /* Try again next time */
  53. }
  54. /* Detach the channel and make the capacity available */
  55. LIST_REMOVE(entry, pointers);
  56. UA_atomic_subUInt32(&cm->currentChannelCount, 1);
  57. return UA_STATUSCODE_GOOD;
  58. }
  59. /* remove channels that were not renewed or who have no connection attached */
  60. void
  61. UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime nowMonotonic) {
  62. channel_list_entry *entry, *temp;
  63. LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  64. UA_DateTime timeout = entry->channel.securityToken.createdAt +
  65. (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
  66. if(timeout < nowMonotonic || !entry->channel.connection) {
  67. UA_LOG_INFO_CHANNEL(cm->server->config.logger, &entry->channel,
  68. "SecureChannel has timed out");
  69. removeSecureChannel(cm, entry);
  70. } else if(entry->channel.nextSecurityToken.tokenId > 0) {
  71. UA_SecureChannel_revolveTokens(&entry->channel);
  72. }
  73. }
  74. }
  75. /* remove the first channel that has no session attached */
  76. static UA_Boolean
  77. purgeFirstChannelWithoutSession(UA_SecureChannelManager *cm) {
  78. channel_list_entry *entry;
  79. LIST_FOREACH(entry, &cm->channels, pointers) {
  80. if(LIST_EMPTY(&(entry->channel.sessions))) {
  81. UA_LOG_DEBUG_CHANNEL(cm->server->config.logger, &entry->channel,
  82. "Channel was purged since maxSecureChannels was "
  83. "reached and channel had no session attached");
  84. removeSecureChannel(cm, entry);
  85. UA_assert(entry != LIST_FIRST(&cm->channels));
  86. return true;
  87. }
  88. }
  89. return false;
  90. }
  91. UA_StatusCode
  92. UA_SecureChannelManager_create(UA_SecureChannelManager *const cm, UA_Connection *const connection,
  93. const UA_SecurityPolicy *const securityPolicy,
  94. const UA_AsymmetricAlgorithmSecurityHeader *const asymHeader) {
  95. /* connection already has a channel attached. */
  96. if(connection->channel != NULL)
  97. return UA_STATUSCODE_BADINTERNALERROR;
  98. /* Check if there exists a free SC, otherwise try to purge one SC without a
  99. * session the purge has been introduced to pass CTT, it is not clear what
  100. * strategy is expected here */
  101. if(cm->currentChannelCount >= cm->server->config.maxSecureChannels &&
  102. !purgeFirstChannelWithoutSession(cm))
  103. return UA_STATUSCODE_BADOUTOFMEMORY;
  104. UA_LOG_INFO(cm->server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  105. "Creating a new SecureChannel");
  106. channel_list_entry *entry = (channel_list_entry *)UA_malloc(sizeof(channel_list_entry));
  107. if(!entry)
  108. return UA_STATUSCODE_BADOUTOFMEMORY;
  109. /* Create the channel context and parse the sender (remote) certificate used for the
  110. * secureChannel. */
  111. UA_StatusCode retval = UA_SecureChannel_init(&entry->channel, securityPolicy,
  112. &asymHeader->senderCertificate);
  113. if(retval != UA_STATUSCODE_GOOD) {
  114. UA_free(entry);
  115. return retval;
  116. }
  117. /* Channel state is fresh (0) */
  118. entry->channel.securityToken.channelId = 0;
  119. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  120. entry->channel.securityToken.createdAt = UA_DateTime_now();
  121. entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  122. LIST_INSERT_HEAD(&cm->channels, entry, pointers);
  123. UA_atomic_addUInt32(&cm->currentChannelCount, 1);
  124. UA_Connection_attachSecureChannel(connection, &entry->channel);
  125. return UA_STATUSCODE_GOOD;
  126. }
  127. UA_StatusCode
  128. UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
  129. const UA_OpenSecureChannelRequest *request,
  130. UA_OpenSecureChannelResponse *response) {
  131. if(channel->state != UA_SECURECHANNELSTATE_FRESH) {
  132. UA_LOG_ERROR_CHANNEL(cm->server->config.logger, channel,
  133. "Called open on already open or closed channel");
  134. return UA_STATUSCODE_BADINTERNALERROR;
  135. }
  136. if(request->securityMode != UA_MESSAGESECURITYMODE_NONE &&
  137. UA_ByteString_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI)) {
  138. return UA_STATUSCODE_BADSECURITYMODEREJECTED;
  139. }
  140. channel->securityMode = request->securityMode;
  141. channel->securityToken.createdAt = UA_DateTime_nowMonotonic();
  142. channel->securityToken.channelId = cm->lastChannelId++;
  143. channel->securityToken.createdAt = UA_DateTime_now();
  144. /* Set the lifetime. Lifetime 0 -> set the maximum possible */
  145. channel->securityToken.revisedLifetime =
  146. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  147. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  148. if(channel->securityToken.revisedLifetime == 0)
  149. channel->securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  150. /* Set the nonces and generate the keys */
  151. UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
  152. retval |= UA_SecureChannel_generateLocalNonce(channel);
  153. retval |= UA_SecureChannel_generateNewKeys(channel);
  154. if(retval != UA_STATUSCODE_GOOD)
  155. return retval;
  156. /* Set the response */
  157. retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
  158. retval |= UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
  159. response->responseHeader.timestamp = UA_DateTime_now();
  160. response->responseHeader.requestHandle = request->requestHeader.requestHandle;
  161. if(retval != UA_STATUSCODE_GOOD)
  162. return retval;
  163. /* The channel is open */
  164. channel->state = UA_SECURECHANNELSTATE_OPEN;
  165. return UA_STATUSCODE_GOOD;
  166. }
  167. UA_StatusCode
  168. UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
  169. const UA_OpenSecureChannelRequest *request,
  170. UA_OpenSecureChannelResponse *response) {
  171. if(channel->state != UA_SECURECHANNELSTATE_OPEN) {
  172. UA_LOG_ERROR_CHANNEL(cm->server->config.logger, channel,
  173. "Called renew on channel which is not open");
  174. return UA_STATUSCODE_BADINTERNALERROR;
  175. }
  176. /* If no security token is already issued */
  177. if(channel->nextSecurityToken.tokenId == 0) {
  178. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  179. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  180. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  181. channel->nextSecurityToken.revisedLifetime =
  182. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  183. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  184. if(channel->nextSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
  185. channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  186. }
  187. /* Replace the nonces */
  188. UA_ByteString_deleteMembers(&channel->remoteNonce);
  189. UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
  190. retval |= UA_SecureChannel_generateLocalNonce(channel);
  191. if(retval != UA_STATUSCODE_GOOD)
  192. return retval;
  193. /* Set the response */
  194. response->responseHeader.requestHandle = request->requestHeader.requestHandle;
  195. retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
  196. retval |= UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  197. if(retval != UA_STATUSCODE_GOOD)
  198. return retval;
  199. /* Reset the internal creation date to the monotonic clock */
  200. channel->nextSecurityToken.createdAt = UA_DateTime_nowMonotonic();
  201. return UA_STATUSCODE_GOOD;
  202. }
  203. UA_SecureChannel *
  204. UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  205. channel_list_entry *entry;
  206. LIST_FOREACH(entry, &cm->channels, pointers) {
  207. if(entry->channel.securityToken.channelId == channelId)
  208. return &entry->channel;
  209. }
  210. return NULL;
  211. }
  212. UA_StatusCode
  213. UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  214. channel_list_entry *entry;
  215. LIST_FOREACH(entry, &cm->channels, pointers) {
  216. if(entry->channel.securityToken.channelId == channelId)
  217. break;
  218. }
  219. if(!entry)
  220. return UA_STATUSCODE_BADINTERNALERROR;
  221. return removeSecureChannel(cm, entry);
  222. }