ua_securechannel.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "ua_util.h"
  2. #include "ua_securechannel.h"
  3. #include "ua_session.h"
  4. #include "ua_types_encoding_binary.h"
  5. #include "ua_types_generated_encoding_binary.h"
  6. #include "ua_transport_generated_encoding_binary.h"
  7. void UA_SecureChannel_init(UA_SecureChannel *channel) {
  8. UA_MessageSecurityMode_init(&channel->securityMode);
  9. UA_ChannelSecurityToken_init(&channel->securityToken);
  10. UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
  11. UA_AsymmetricAlgorithmSecurityHeader_init(&channel->clientAsymAlgSettings);
  12. UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
  13. UA_ByteString_init(&channel->clientNonce);
  14. UA_ByteString_init(&channel->serverNonce);
  15. channel->sequenceNumber = 0;
  16. channel->connection = NULL;
  17. LIST_INIT(&channel->sessions);
  18. }
  19. void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
  20. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
  21. UA_ByteString_deleteMembers(&channel->serverNonce);
  22. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
  23. UA_ByteString_deleteMembers(&channel->clientNonce);
  24. UA_ChannelSecurityToken_deleteMembers(&channel->securityToken); //FIXME: not really needed
  25. UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken); //FIXME: not really needed
  26. UA_Connection *c = channel->connection;
  27. if(c) {
  28. UA_Connection_detachSecureChannel(c);
  29. if(c->close)
  30. c->close(c);
  31. }
  32. /* just remove the pointers and free the linked list (not the sessions) */
  33. struct SessionEntry *se, *temp;
  34. LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
  35. if(se->session)
  36. se->session->channel = NULL;
  37. LIST_REMOVE(se, pointers);
  38. UA_free(se);
  39. }
  40. }
  41. //TODO implement real nonce generator - DUMMY function
  42. UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
  43. if(!(nonce->data = UA_malloc(1)))
  44. return UA_STATUSCODE_BADOUTOFMEMORY;
  45. nonce->length = 1;
  46. nonce->data[0] = 'a';
  47. return UA_STATUSCODE_GOOD;
  48. }
  49. void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
  50. struct SessionEntry *se = UA_malloc(sizeof(struct SessionEntry));
  51. if(!se)
  52. return;
  53. se->session = session;
  54. #ifdef UA_MULTITHREADING
  55. if(uatomic_cmpxchg(&session->channel, NULL, channel) != NULL) {
  56. UA_free(se);
  57. return;
  58. }
  59. #else
  60. if(session->channel != NULL) {
  61. UA_free(se);
  62. return;
  63. }
  64. session->channel = channel;
  65. #endif
  66. LIST_INSERT_HEAD(&channel->sessions, se, pointers);
  67. }
  68. void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
  69. if(session)
  70. session->channel = NULL;
  71. struct SessionEntry *se, *temp;
  72. LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
  73. if(se->session != session)
  74. continue;
  75. LIST_REMOVE(se, pointers);
  76. UA_free(se);
  77. break;
  78. }
  79. }
  80. UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token) {
  81. struct SessionEntry *se;
  82. LIST_FOREACH(se, &channel->sessions, pointers) {
  83. if(UA_NodeId_equal(&se->session->authenticationToken, token))
  84. break;
  85. }
  86. if(!se)
  87. return NULL;
  88. return se->session;
  89. }
  90. void UA_SecureChannel_revolveTokens(UA_SecureChannel *channel){
  91. if(channel->nextSecurityToken.tokenId==0) //no security token issued
  92. return;
  93. //FIXME: not thread-safe
  94. //swap tokens
  95. memcpy(&channel->securityToken, &channel->nextSecurityToken, sizeof(UA_ChannelSecurityToken));
  96. UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
  97. }
  98. UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
  99. const void *content,
  100. const UA_DataType *contentType) {
  101. UA_Connection *connection = channel->connection;
  102. if(!connection)
  103. return UA_STATUSCODE_BADINTERNALERROR;
  104. UA_NodeId typeId = contentType->typeId;
  105. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  106. return UA_STATUSCODE_BADINTERNALERROR;
  107. typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
  108. UA_SecureConversationMessageHeader respHeader;
  109. respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
  110. respHeader.messageHeader.messageSize = 0;
  111. respHeader.secureChannelId = channel->securityToken.channelId;
  112. UA_SymmetricAlgorithmSecurityHeader symSecHeader;
  113. symSecHeader.tokenId = channel->securityToken.tokenId;
  114. UA_SequenceHeader seqHeader;
  115. seqHeader.requestId = requestId;
  116. UA_ByteString message;
  117. UA_StatusCode retval = connection->getSendBuffer(connection, connection->remoteConf.recvBufferSize,
  118. &message);
  119. if(retval != UA_STATUSCODE_GOOD)
  120. return retval;
  121. size_t messagePos = 24; // after the headers
  122. retval |= UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
  123. retval |= UA_encodeBinary(content, contentType, &message, &messagePos);
  124. if(retval != UA_STATUSCODE_GOOD) {
  125. connection->releaseSendBuffer(connection, &message);
  126. return retval;
  127. }
  128. /* now write the header with the size */
  129. respHeader.messageHeader.messageSize = messagePos;
  130. #ifndef UA_MULTITHREADING
  131. seqHeader.sequenceNumber = ++channel->sequenceNumber;
  132. #else
  133. seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1);
  134. #endif
  135. messagePos = 0;
  136. UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &message, &messagePos);
  137. UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, &message, &messagePos);
  138. UA_SequenceHeader_encodeBinary(&seqHeader, &message, &messagePos);
  139. message.length = respHeader.messageHeader.messageSize;
  140. retval = connection->send(connection, &message);
  141. return retval;
  142. }