ua_securechannel_manager.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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 <open62541/transport_generated.h>
  14. #include "ua_server_internal.h"
  15. #include "ua_session.h"
  16. #define STARTCHANNELID 1
  17. #define STARTTOKENID 1
  18. UA_StatusCode
  19. UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_Server *server) {
  20. TAILQ_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_entry *entry, *temp;
  31. TAILQ_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  32. TAILQ_REMOVE(&cm->channels, entry, pointers);
  33. UA_SecureChannel_close(&entry->channel);
  34. UA_SecureChannel_deleteMembers(&entry->channel);
  35. UA_free(entry);
  36. }
  37. }
  38. static void
  39. removeSecureChannelCallback(void *_, channel_entry *entry) {
  40. UA_SecureChannel_deleteMembers(&entry->channel);
  41. }
  42. static void
  43. removeSecureChannel(UA_SecureChannelManager *cm, channel_entry *entry) {
  44. /* Close the SecureChannel */
  45. UA_SecureChannel_close(&entry->channel);
  46. /* Detach the channel and make the capacity available */
  47. TAILQ_REMOVE(&cm->channels, entry, pointers);
  48. UA_atomic_subUInt32(&cm->currentChannelCount, 1);
  49. /* Add a delayed callback to remove the channel when the currently
  50. * scheduled jobs have completed */
  51. entry->cleanupCallback.callback = (UA_ApplicationCallback)removeSecureChannelCallback;
  52. entry->cleanupCallback.application = NULL;
  53. entry->cleanupCallback.data = entry;
  54. UA_WorkQueue_enqueueDelayed(&cm->server->workQueue, &entry->cleanupCallback);
  55. }
  56. /* remove channels that were not renewed or who have no connection attached */
  57. void
  58. UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm,
  59. UA_DateTime nowMonotonic) {
  60. channel_entry *entry, *temp;
  61. TAILQ_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
  62. /* The channel was closed internally */
  63. if(entry->channel.state == UA_SECURECHANNELSTATE_CLOSED ||
  64. !entry->channel.connection) {
  65. removeSecureChannel(cm, entry);
  66. continue;
  67. }
  68. /* The channel has timed out */
  69. UA_DateTime timeout =
  70. entry->channel.securityToken.createdAt +
  71. (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
  72. if(timeout < nowMonotonic) {
  73. UA_LOG_INFO_CHANNEL(&cm->server->config.logger, &entry->channel,
  74. "SecureChannel has timed out");
  75. removeSecureChannel(cm, entry);
  76. continue;
  77. }
  78. /* Revolve the channel tokens */
  79. if(entry->channel.nextSecurityToken.tokenId > 0) {
  80. UA_SecureChannel_revolveTokens(&entry->channel);
  81. }
  82. }
  83. }
  84. /* remove the first channel that has no session attached */
  85. static UA_Boolean
  86. purgeFirstChannelWithoutSession(UA_SecureChannelManager *cm) {
  87. channel_entry *entry;
  88. TAILQ_FOREACH(entry, &cm->channels, pointers) {
  89. if(LIST_EMPTY(&entry->channel.sessions)) {
  90. UA_LOG_INFO_CHANNEL(&cm->server->config.logger, &entry->channel,
  91. "Channel was purged since maxSecureChannels was "
  92. "reached and channel had no session attached");
  93. removeSecureChannel(cm, entry);
  94. return true;
  95. }
  96. }
  97. return false;
  98. }
  99. UA_StatusCode
  100. UA_SecureChannelManager_create(UA_SecureChannelManager *const cm, UA_Connection *const connection,
  101. const UA_SecurityPolicy *const securityPolicy,
  102. const UA_AsymmetricAlgorithmSecurityHeader *const asymHeader) {
  103. /* connection already has a channel attached. */
  104. if(connection->channel != NULL)
  105. return UA_STATUSCODE_BADINTERNALERROR;
  106. /* Check if there exists a free SC, otherwise try to purge one SC without a
  107. * session the purge has been introduced to pass CTT, it is not clear what
  108. * strategy is expected here */
  109. if(cm->currentChannelCount >= cm->server->config.maxSecureChannels &&
  110. !purgeFirstChannelWithoutSession(cm))
  111. return UA_STATUSCODE_BADOUTOFMEMORY;
  112. UA_LOG_INFO(&cm->server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
  113. "Creating a new SecureChannel");
  114. channel_entry *entry = (channel_entry *)UA_malloc(sizeof(channel_entry));
  115. if(!entry)
  116. return UA_STATUSCODE_BADOUTOFMEMORY;
  117. /* Create the channel context and parse the sender (remote) certificate used for the
  118. * secureChannel. */
  119. UA_SecureChannel_init(&entry->channel);
  120. UA_StatusCode retval =
  121. UA_SecureChannel_setSecurityPolicy(&entry->channel, securityPolicy,
  122. &asymHeader->senderCertificate);
  123. if(retval != UA_STATUSCODE_GOOD) {
  124. UA_free(entry);
  125. return retval;
  126. }
  127. /* Channel state is fresh (0) */
  128. entry->channel.securityToken.channelId = 0;
  129. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  130. entry->channel.securityToken.createdAt = UA_DateTime_now();
  131. entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  132. TAILQ_INSERT_TAIL(&cm->channels, entry, pointers);
  133. UA_atomic_addUInt32(&cm->currentChannelCount, 1);
  134. UA_Connection_attachSecureChannel(connection, &entry->channel);
  135. return UA_STATUSCODE_GOOD;
  136. }
  137. UA_StatusCode
  138. UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
  139. const UA_OpenSecureChannelRequest *request,
  140. UA_OpenSecureChannelResponse *response) {
  141. if(channel->state != UA_SECURECHANNELSTATE_FRESH) {
  142. UA_LOG_ERROR_CHANNEL(&cm->server->config.logger, channel,
  143. "Called open on already open or closed channel");
  144. return UA_STATUSCODE_BADINTERNALERROR;
  145. }
  146. if(request->securityMode != UA_MESSAGESECURITYMODE_NONE &&
  147. UA_ByteString_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI)) {
  148. return UA_STATUSCODE_BADSECURITYMODEREJECTED;
  149. }
  150. channel->securityMode = request->securityMode;
  151. channel->securityToken.createdAt = UA_DateTime_nowMonotonic();
  152. channel->securityToken.channelId = cm->lastChannelId++;
  153. channel->securityToken.createdAt = UA_DateTime_now();
  154. /* Set the lifetime. Lifetime 0 -> set the maximum possible */
  155. channel->securityToken.revisedLifetime =
  156. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  157. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  158. if(channel->securityToken.revisedLifetime == 0)
  159. channel->securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  160. /* Set the nonces and generate the keys */
  161. UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
  162. if(retval != UA_STATUSCODE_GOOD)
  163. return retval;
  164. retval = UA_SecureChannel_generateLocalNonce(channel);
  165. if(retval != UA_STATUSCODE_GOOD)
  166. return retval;
  167. retval = UA_SecureChannel_generateNewKeys(channel);
  168. if(retval != UA_STATUSCODE_GOOD)
  169. return retval;
  170. /* Set the response */
  171. retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
  172. if(retval != UA_STATUSCODE_GOOD)
  173. return retval;
  174. retval = UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
  175. if(retval != UA_STATUSCODE_GOOD)
  176. return retval;
  177. response->responseHeader.timestamp = UA_DateTime_now();
  178. response->responseHeader.requestHandle = request->requestHeader.requestHandle;
  179. /* The channel is open */
  180. channel->state = UA_SECURECHANNELSTATE_OPEN;
  181. return UA_STATUSCODE_GOOD;
  182. }
  183. UA_StatusCode
  184. UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
  185. const UA_OpenSecureChannelRequest *request,
  186. UA_OpenSecureChannelResponse *response) {
  187. if(channel->state != UA_SECURECHANNELSTATE_OPEN) {
  188. UA_LOG_ERROR_CHANNEL(&cm->server->config.logger, channel,
  189. "Called renew on channel which is not open");
  190. return UA_STATUSCODE_BADINTERNALERROR;
  191. }
  192. /* If no security token is already issued */
  193. if(channel->nextSecurityToken.tokenId == 0) {
  194. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  195. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  196. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  197. channel->nextSecurityToken.revisedLifetime =
  198. (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
  199. cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
  200. if(channel->nextSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
  201. channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
  202. }
  203. /* Replace the nonces */
  204. UA_ByteString_deleteMembers(&channel->remoteNonce);
  205. UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
  206. if(retval != UA_STATUSCODE_GOOD)
  207. return retval;
  208. retval = UA_SecureChannel_generateLocalNonce(channel);
  209. if(retval != UA_STATUSCODE_GOOD)
  210. return retval;
  211. /* Set the response */
  212. response->responseHeader.requestHandle = request->requestHeader.requestHandle;
  213. retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
  214. if(retval != UA_STATUSCODE_GOOD)
  215. return retval;
  216. retval = UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  217. if(retval != UA_STATUSCODE_GOOD)
  218. return retval;
  219. /* Reset the internal creation date to the monotonic clock */
  220. channel->nextSecurityToken.createdAt = UA_DateTime_nowMonotonic();
  221. return UA_STATUSCODE_GOOD;
  222. }
  223. UA_SecureChannel *
  224. UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  225. channel_entry *entry;
  226. TAILQ_FOREACH(entry, &cm->channels, pointers) {
  227. if(entry->channel.securityToken.channelId == channelId)
  228. return &entry->channel;
  229. }
  230. return NULL;
  231. }
  232. UA_StatusCode
  233. UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  234. channel_entry *entry;
  235. TAILQ_FOREACH(entry, &cm->channels, pointers) {
  236. if(entry->channel.securityToken.channelId == channelId)
  237. break;
  238. }
  239. if(!entry)
  240. return UA_STATUSCODE_BADINTERNALERROR;
  241. removeSecureChannel(cm, entry);
  242. return UA_STATUSCODE_GOOD;
  243. }