ua_securechannel_manager.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include "ua_securechannel_manager.h"
  2. #include "ua_session.h"
  3. #include "ua_statuscodes.h"
  4. UA_StatusCode UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_UInt32 maxChannelCount,
  5. UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
  6. UA_UInt32 startTokenId) {
  7. LIST_INIT(&cm->channels);
  8. cm->lastChannelId = startChannelId;
  9. cm->lastTokenId = startTokenId;
  10. cm->maxChannelLifetime = tokenLifetime;
  11. cm->maxChannelCount = maxChannelCount;
  12. return UA_STATUSCODE_GOOD;
  13. }
  14. void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
  15. channel_list_entry *current = LIST_FIRST(&cm->channels);
  16. while(current) {
  17. LIST_REMOVE(current, pointers);
  18. UA_SecureChannel_deleteMembersCleanup(&current->channel);
  19. UA_free(current);
  20. current = LIST_FIRST(&cm->channels);
  21. }
  22. }
  23. void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now) {
  24. channel_list_entry *entry = LIST_FIRST(&cm->channels);
  25. /* remove channels that were not renewed or who have no connection attached */
  26. while(entry) {
  27. if(entry->channel.securityToken.createdAt +
  28. (UA_DateTime)entry->channel.securityToken.revisedLifetime*10000 > now &&
  29. entry->channel.connection) {
  30. entry = LIST_NEXT(entry, pointers);
  31. }else if(entry->channel.nextSecurityToken.tokenId > 0 &&
  32. entry->channel.nextSecurityToken.createdAt +
  33. (UA_DateTime)entry->channel.nextSecurityToken.revisedLifetime*10000 > now &&
  34. entry->channel.connection){
  35. UA_SecureChannel_revolveTokens(&entry->channel);
  36. entry = LIST_NEXT(entry, pointers);
  37. }
  38. else {
  39. channel_list_entry *next = LIST_NEXT(entry, pointers);
  40. LIST_REMOVE(entry, pointers);
  41. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  42. UA_free(entry);
  43. entry = next;
  44. }
  45. }
  46. }
  47. UA_StatusCode UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
  48. const UA_OpenSecureChannelRequest *request,
  49. UA_OpenSecureChannelResponse *response) {
  50. switch(request->securityMode) {
  51. case UA_MESSAGESECURITYMODE_NONE:
  52. break;
  53. case UA_MESSAGESECURITYMODE_INVALID:
  54. case UA_MESSAGESECURITYMODE_SIGN:
  55. case UA_MESSAGESECURITYMODE_SIGNANDENCRYPT:
  56. default:
  57. response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURITYMODEREJECTED;
  58. return response->responseHeader.serviceResult;
  59. }
  60. channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
  61. if(!entry)
  62. return UA_STATUSCODE_BADOUTOFMEMORY;
  63. UA_SecureChannel_init(&entry->channel);
  64. response->responseHeader.stringTableSize = 0;
  65. response->responseHeader.timestamp = UA_DateTime_now();
  66. response->serverProtocolVersion = 0;
  67. entry->channel.securityToken.channelId = cm->lastChannelId++;
  68. entry->channel.securityToken.tokenId = cm->lastTokenId++;
  69. entry->channel.securityToken.createdAt = UA_DateTime_now();
  70. entry->channel.securityToken.revisedLifetime = (request->requestedLifetime > cm->maxChannelLifetime) ?
  71. cm->maxChannelLifetime : request->requestedLifetime;
  72. //FIXME: pragmatic workaround to get clients requesting lifetime of 0 working
  73. if(entry->channel.securityToken.revisedLifetime == 0) {
  74. entry->channel.securityToken.revisedLifetime = cm->maxChannelLifetime;
  75. //FIXME: I'd log it, but there is no pointer to the logger
  76. // printf("Warning: client requests token lifetime of 0 in OpenSecureChannelRequest setting it to %llu\n", cm->maxChannelLifetime);
  77. }
  78. UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
  79. entry->channel.serverAsymAlgSettings.securityPolicyUri =
  80. UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  81. UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
  82. UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
  83. UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
  84. UA_Connection_attachSecureChannel(conn, &entry->channel);
  85. LIST_INSERT_HEAD(&cm->channels, entry, pointers);
  86. return UA_STATUSCODE_GOOD;
  87. }
  88. UA_StatusCode UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
  89. const UA_OpenSecureChannelRequest *request,
  90. UA_OpenSecureChannelResponse *response)
  91. {
  92. UA_SecureChannel *channel = conn->channel;
  93. if(channel == UA_NULL)
  94. return UA_STATUSCODE_BADINTERNALERROR;
  95. //if no new security token is already issued
  96. if(channel->nextSecurityToken.tokenId == 0){
  97. channel->nextSecurityToken.channelId = channel->securityToken.channelId;
  98. //FIXME: UaExpert seems not to use new the new tokenid
  99. channel->nextSecurityToken.tokenId = cm->lastTokenId++;
  100. //channel->nextSecurityToken.tokenId = channel->securityToken.tokenId;
  101. channel->nextSecurityToken.createdAt = UA_DateTime_now();
  102. channel->nextSecurityToken.revisedLifetime = (request->requestedLifetime > cm->maxChannelLifetime) ?
  103. cm->maxChannelLifetime : request->requestedLifetime;
  104. //FIXME: pragmatic workaround to get clients requesting lifetime of 0 working
  105. if(channel->nextSecurityToken.revisedLifetime == 0){
  106. channel->nextSecurityToken.revisedLifetime = cm->maxChannelLifetime;
  107. //FIXME: I'd log it, but there is no pointer to the logger
  108. // printf("Warning: client requests token lifetime of 0 in renewing SecureChannel setting it to %llu\n", cm->maxChannelLifetime);
  109. }
  110. }
  111. if(channel->clientNonce.data)
  112. UA_ByteString_deleteMembers(&channel->clientNonce);
  113. UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
  114. UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
  115. UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
  116. return UA_STATUSCODE_GOOD;
  117. }
  118. UA_SecureChannel * UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  119. channel_list_entry *entry;
  120. LIST_FOREACH(entry, &cm->channels, pointers) {
  121. if(entry->channel.securityToken.channelId == channelId)
  122. return &entry->channel;
  123. }
  124. return UA_NULL;
  125. }
  126. UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
  127. channel_list_entry *entry;
  128. LIST_FOREACH(entry, &cm->channels, pointers) {
  129. if(entry->channel.securityToken.channelId == channelId)
  130. break;
  131. }
  132. if(!entry)
  133. return UA_STATUSCODE_BADINTERNALERROR;
  134. LIST_REMOVE(entry, pointers);
  135. UA_SecureChannel_deleteMembersCleanup(&entry->channel);
  136. UA_free(entry);
  137. return UA_STATUSCODE_GOOD;
  138. }