ua_securechannel.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include "ua_util.h"
  2. #include "ua_securechannel.h"
  3. #include "ua_statuscodes.h"
  4. #include "ua_types_encoding_binary.h"
  5. // max message size is 64k
  6. const UA_ConnectionConfig UA_ConnectionConfig_standard =
  7. {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize = 65536,
  8. .maxMessageSize = 65536, .maxChunkCount = 1};
  9. UA_ByteString UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString received)
  10. {
  11. if(received.length == -1)
  12. return received;
  13. /* concat the existing incomplete message with the new message */
  14. UA_ByteString current;
  15. if(connection->incompleteMessage.length < 0)
  16. current = received;
  17. else {
  18. current.data = UA_realloc(connection->incompleteMessage.data,
  19. connection->incompleteMessage.length + received.length);
  20. if(!current.data) {
  21. /* not enough memory */
  22. UA_ByteString_deleteMembers(&connection->incompleteMessage);
  23. connection->incompleteMessage.length = -1;
  24. UA_ByteString_deleteMembers(&received);
  25. received.length = -1;
  26. return received;
  27. }
  28. UA_memcpy(current.data + connection->incompleteMessage.length, received.data, received.length);
  29. current.length = connection->incompleteMessage.length + received.length;
  30. UA_ByteString_deleteMembers(&received);
  31. UA_ByteString_init(&connection->incompleteMessage);
  32. }
  33. /* find the first non-complete message */
  34. size_t end_pos = 0; // the end of the last complete message
  35. while(current.length - end_pos >= 32) {
  36. if(!(current.data[0] == 'M' && current.data[1] == 'S' && current.data[2] == 'G') &&
  37. !(current.data[0] == 'O' && current.data[1] == 'P' && current.data[2] == 'N') &&
  38. !(current.data[0] == 'H' && current.data[1] == 'E' && current.data[2] == 'L') &&
  39. !(current.data[0] == 'A' && current.data[1] == 'C' && current.data[2] == 'K') &&
  40. !(current.data[0] == 'C' && current.data[1] == 'L' && current.data[2] == 'O')) {
  41. current.length = end_pos; // throw the remaining bytestring away
  42. break;
  43. }
  44. UA_Int32 length = 0;
  45. size_t pos = end_pos + 4;
  46. UA_StatusCode retval = UA_Int32_decodeBinary(&current, &pos, &length);
  47. if(retval != UA_STATUSCODE_GOOD || length < 32 ||
  48. length > (UA_Int32)connection->localConf.maxMessageSize) {
  49. current.length = end_pos; // throw the remaining bytestring away
  50. break;
  51. }
  52. if(length + (UA_Int32)end_pos > current.length)
  53. break; // the message is incomplete
  54. end_pos += length;
  55. }
  56. if(current.length == 0) {
  57. /* throw everything away */
  58. UA_ByteString_deleteMembers(&current);
  59. current.length = -1;
  60. return current;
  61. }
  62. if(end_pos == 0) {
  63. /* no complete message in current */
  64. connection->incompleteMessage = current;
  65. UA_ByteString_init(&current);
  66. } else if(current.length != (UA_Int32)end_pos) {
  67. /* there is an incomplete message at the end of current */
  68. connection->incompleteMessage.data = UA_malloc(current.length - end_pos);
  69. if(connection->incompleteMessage.data) {
  70. UA_memcpy(connection->incompleteMessage.data, &current.data[end_pos], current.length - end_pos);
  71. connection->incompleteMessage.length = current.length - end_pos;
  72. }
  73. current.length = end_pos;
  74. }
  75. return current;
  76. }
  77. void UA_SecureChannel_init(UA_SecureChannel *channel) {
  78. UA_MessageSecurityMode_init(&channel->securityMode);
  79. UA_ChannelSecurityToken_init(&channel->securityToken);
  80. UA_AsymmetricAlgorithmSecurityHeader_init(&channel->clientAsymAlgSettings);
  81. UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
  82. UA_ByteString_init(&channel->clientNonce);
  83. UA_ByteString_init(&channel->serverNonce);
  84. channel->requestId = 0;
  85. channel->sequenceNumber = 0;
  86. channel->connection = UA_NULL;
  87. channel->session = UA_NULL;
  88. }
  89. void UA_SecureChannel_deleteMembers(UA_SecureChannel *channel) {
  90. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
  91. UA_ByteString_deleteMembers(&channel->serverNonce);
  92. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
  93. UA_ByteString_deleteMembers(&channel->clientNonce);
  94. UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
  95. }
  96. void UA_SecureChannel_delete(UA_SecureChannel *channel) {
  97. UA_SecureChannel_deleteMembers(channel);
  98. UA_free(channel);
  99. }
  100. UA_Boolean UA_SecureChannel_compare(UA_SecureChannel *sc1, UA_SecureChannel *sc2) {
  101. return (sc1->securityToken.channelId == sc2->securityToken.channelId);
  102. }
  103. //TODO implement real nonce generator - DUMMY function
  104. UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
  105. if(!(nonce->data = UA_malloc(1)))
  106. return UA_STATUSCODE_BADOUTOFMEMORY;
  107. nonce->length = 1;
  108. nonce->data[0] = 'a';
  109. return UA_STATUSCODE_GOOD;
  110. }
  111. UA_StatusCode UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId) {
  112. //TODO review checking of request id
  113. if(channel->requestId+1 != requestId)
  114. return UA_STATUSCODE_BADINTERNALERROR;
  115. channel->requestId++;
  116. return UA_STATUSCODE_GOOD;
  117. }
  118. UA_StatusCode UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
  119. //TODO review checking of sequence
  120. if(channel->sequenceNumber+1 != sequenceNumber)
  121. return UA_STATUSCODE_BADINTERNALERROR;
  122. channel->sequenceNumber++;
  123. return UA_STATUSCODE_GOOD;
  124. }
  125. void UA_Connection_detachSecureChannel(UA_Connection *connection) {
  126. #ifdef UA_MULTITHREADING
  127. UA_SecureChannel *channel = connection->channel;
  128. if(channel)
  129. uatomic_cmpxchg(&channel->connection, connection, UA_NULL);
  130. uatomic_set(&connection->channel, UA_NULL);
  131. #else
  132. if(connection->channel)
  133. connection->channel->connection = UA_NULL;
  134. connection->channel = UA_NULL;
  135. #endif
  136. }
  137. void UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
  138. #ifdef UA_MULTITHREADING
  139. if(uatomic_cmpxchg(&channel->connection, UA_NULL, connection) == UA_NULL)
  140. uatomic_set(&connection->channel, channel);
  141. #else
  142. if(channel->connection != UA_NULL)
  143. return;
  144. channel->connection = connection;
  145. connection->channel = channel;
  146. #endif
  147. }