ua_securechannel.c 5.7 KB

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