ua_securechannel.c 6.3 KB

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