ua_server_binary.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #include "ua_server.h"
  2. #include "ua_services.h"
  3. #include "ua_statuscodes.h"
  4. #include "ua_namespace_0.h"
  5. #include "ua_securechannel_manager.h"
  6. #include "ua_session_manager.h"
  7. #include "ua_util.h"
  8. static UA_Int32 UA_ByteStringArray_init(UA_ByteStringArray *stringarray, UA_UInt32 length) {
  9. if(!stringarray || length == 0)
  10. return UA_ERROR;
  11. if(UA_alloc((void **)&stringarray->strings, sizeof(UA_String) * length) != UA_SUCCESS)
  12. return UA_ERROR;
  13. for(UA_UInt32 i = 0;i < length;i++)
  14. UA_String_init(&stringarray->strings[i]);
  15. stringarray->stringsSize = length;
  16. return UA_ERROR;
  17. }
  18. static UA_Int32 UA_ByteStringArray_deleteMembers(UA_ByteStringArray *stringarray) {
  19. if(!stringarray)
  20. return UA_ERROR;
  21. for(UA_UInt32 i = 0;i < stringarray->stringsSize;i++)
  22. UA_String_deleteMembers(&stringarray->strings[i]);
  23. return UA_SUCCESS;
  24. }
  25. static void processHello(UA_Connection *connection, const UA_ByteString *msg,
  26. UA_UInt32 *pos) {
  27. UA_TcpHelloMessage helloMessage;
  28. if(UA_TcpHelloMessage_decodeBinary(msg, pos, &helloMessage) != UA_SUCCESS) {
  29. connection->close(connection->callbackHandle);
  30. return;
  31. }
  32. connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
  33. connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
  34. connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
  35. connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
  36. connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
  37. connection->state = UA_CONNECTION_ESTABLISHED;
  38. // build acknowledge response
  39. UA_TcpAcknowledgeMessage ackMessage;
  40. ackMessage.protocolVersion = connection->localConf.protocolVersion;
  41. ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
  42. ackMessage.sendBufferSize = connection->localConf.sendBufferSize;
  43. ackMessage.maxMessageSize = connection->localConf.maxMessageSize;
  44. ackMessage.maxChunkCount = connection->localConf.maxChunkCount;
  45. UA_TcpMessageHeader ackHeader;
  46. ackHeader.messageType = UA_MESSAGETYPE_ACK;
  47. ackHeader.isFinal = 'F';
  48. ackHeader.messageSize = UA_TcpAcknowledgeMessage_calcSizeBinary(&ackMessage) +
  49. UA_TcpMessageHeader_calcSizeBinary(&ackHeader);
  50. UA_ByteString ack_msg;
  51. UA_UInt32 tmpPos = 0;
  52. UA_ByteString_newMembers(&ack_msg, ackHeader.messageSize);
  53. UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos);
  54. UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos);
  55. UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &ack_msg };
  56. connection->write(connection->callbackHandle, answer_buf);
  57. UA_ByteString_deleteMembers(&ack_msg);
  58. }
  59. static void processOpen(UA_Connection *connection, UA_Server *server,
  60. const UA_ByteString *msg, UA_UInt32 *pos) {
  61. if(connection->state != UA_CONNECTION_ESTABLISHED) {
  62. // was hello exchanged before?
  63. if(connection->state == UA_CONNECTION_OPENING)
  64. connection->close(connection->callbackHandle);
  65. return;
  66. }
  67. UA_UInt32 secureChannelId;
  68. UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
  69. UA_AsymmetricAlgorithmSecurityHeader asymHeader;
  70. UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader);
  71. UA_SequenceHeader seqHeader;
  72. UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader);
  73. UA_ExpandedNodeId requestType;
  74. UA_ExpandedNodeId_decodeBinary(msg, pos, &requestType);
  75. if(requestType.nodeId.identifier.numeric != 446) {
  76. // todo: handle error
  77. }
  78. UA_OpenSecureChannelRequest r;
  79. UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r);
  80. // perform request
  81. UA_OpenSecureChannelResponse p;
  82. UA_OpenSecureChannelResponse_init(&p);
  83. Service_OpenSecureChannel(server, connection, &r, &p);
  84. // response
  85. UA_TcpMessageHeader respHeader;
  86. respHeader.messageType = UA_MESSAGETYPE_OPN;
  87. respHeader.isFinal = 'F';
  88. respHeader.messageSize = 8+4; //header + securechannelid
  89. UA_ExpandedNodeId responseType;
  90. NS0EXPANDEDNODEID(responseType, 449);
  91. respHeader.messageSize += UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader);
  92. respHeader.messageSize += UA_SequenceHeader_calcSizeBinary(&seqHeader);
  93. respHeader.messageSize += UA_ExpandedNodeId_calcSizeBinary(&responseType);
  94. respHeader.messageSize += UA_OpenSecureChannelResponse_calcSizeBinary(&p);
  95. UA_ByteString resp_msg;
  96. UA_UInt32 tmpPos = 0;
  97. UA_ByteString_newMembers(&resp_msg, respHeader.messageSize);
  98. UA_TcpMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos);
  99. UA_UInt32_encodeBinary(&p.securityToken.channelId, &resp_msg, &tmpPos);
  100. UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back
  101. UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back
  102. UA_ExpandedNodeId_encodeBinary(&responseType, &resp_msg, &tmpPos);
  103. UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos);
  104. UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &resp_msg };
  105. connection->write(connection->callbackHandle, answer_buf);
  106. UA_ByteString_deleteMembers(&resp_msg);
  107. }
  108. static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r) {
  109. r->requestHandle = p->requestHandle;
  110. r->serviceResult = UA_STATUSCODE_GOOD;
  111. r->stringTableSize = 0;
  112. r->timestamp = UA_DateTime_now();
  113. }
  114. #define CHECK_PROCESS(CODE, CLEANUP) \
  115. do { \
  116. if(CODE != UA_SUCCESS) { \
  117. CLEANUP; \
  118. goto clean_up; \
  119. } } while(0)
  120. #define INVOKE_SERVICE(TYPE) do { \
  121. UA_##TYPE##Request p; \
  122. UA_##TYPE##Response r; \
  123. CHECK_PROCESS(UA_##TYPE##Request_decodeBinary(msg, pos, &p),; ); \
  124. UA_##TYPE##Response_init(&r); \
  125. init_response_header(&p.requestHeader, &r.responseHeader); \
  126. DBG_VERBOSE(printf("Invoke Service: %s\n", # TYPE)); \
  127. Service_##TYPE(server, channel->session, &p, &r); \
  128. DBG_VERBOSE(printf("Finished Service: %s\n", # TYPE)); \
  129. UA_ByteString_newMembers(&responseBuf.strings[1], UA_##TYPE##Response_calcSizeBinary(&r)); \
  130. UA_##TYPE##Response_encodeBinary(&r, &responseBuf.strings[1], &sendOffset); \
  131. UA_##TYPE##Request_deleteMembers(&p); \
  132. UA_##TYPE##Response_deleteMembers(&r); \
  133. responseType = requestType.nodeId.identifier.numeric + 3; \
  134. } while(0)
  135. static void processMessage(UA_Connection *connection, UA_Server *server,
  136. const UA_ByteString *msg, UA_UInt32 *pos) {
  137. // 1) Read in the securechannel
  138. UA_UInt32 secureChannelId;
  139. UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
  140. UA_SecureChannel *channel;
  141. UA_SecureChannelManager_get(server->secureChannelManager, secureChannelId, &channel);
  142. // 2) Read the security header
  143. UA_UInt32 tokenId;
  144. UA_UInt32_decodeBinary(msg, pos, &tokenId);
  145. UA_SequenceHeader sequenceHeader;
  146. CHECK_PROCESS(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader),; );
  147. channel->sequenceNumber = sequenceHeader.sequenceNumber;
  148. channel->requestId = sequenceHeader.requestId;
  149. // todo
  150. //UA_SecureChannel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
  151. //UA_SecureChannel_checkRequestId(channel,sequenceHeader.requestId);
  152. // 3) Read the nodeid of the request
  153. UA_ExpandedNodeId requestType;
  154. CHECK_PROCESS(UA_ExpandedNodeId_decodeBinary(msg, pos, &requestType),; );
  155. if(requestType.nodeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  156. goto close_connection;
  157. // 4) process the request
  158. UA_ByteStringArray responseBuf;
  159. UA_ByteStringArray_init(&responseBuf, 2);
  160. UA_UInt32 responseType;
  161. //subtract 2 for binary encoding
  162. UA_UInt32 sendOffset = 0;
  163. switch(requestType.nodeId.identifier.numeric - 2) {
  164. case UA_GETENDPOINTSREQUEST_NS0: {
  165. UA_GetEndpointsRequest p;
  166. UA_GetEndpointsResponse r;
  167. CHECK_PROCESS(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p),; );
  168. UA_GetEndpointsResponse_init(&r);
  169. init_response_header(&p.requestHeader, &r.responseHeader);
  170. Service_GetEndpoints(server, &p, &r);
  171. UA_ByteString_newMembers(&responseBuf.strings[1], UA_GetEndpointsResponse_calcSizeBinary(&r));
  172. UA_GetEndpointsResponse_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
  173. UA_GetEndpointsRequest_deleteMembers(&p);
  174. UA_GetEndpointsResponse_deleteMembers(&r);
  175. responseType = requestType.nodeId.identifier.numeric + 3;
  176. break;
  177. }
  178. case UA_CREATESESSIONREQUEST_NS0: {
  179. UA_CreateSessionRequest p;
  180. UA_CreateSessionResponse r;
  181. CHECK_PROCESS(UA_CreateSessionRequest_decodeBinary(msg, pos, &p),; );
  182. UA_CreateSessionResponse_init(&r);
  183. init_response_header(&p.requestHeader, &r.responseHeader);
  184. Service_CreateSession(server, channel, &p, &r);
  185. UA_ByteString_newMembers(&responseBuf.strings[1], UA_CreateSessionResponse_calcSizeBinary(&r));
  186. UA_CreateSessionResponse_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
  187. UA_CreateSessionRequest_deleteMembers(&p);
  188. UA_CreateSessionResponse_deleteMembers(&r);
  189. responseType = requestType.nodeId.identifier.numeric + 3;
  190. break;
  191. }
  192. case UA_ACTIVATESESSIONREQUEST_NS0: {
  193. UA_ActivateSessionRequest p;
  194. UA_ActivateSessionResponse r;
  195. CHECK_PROCESS(UA_ActivateSessionRequest_decodeBinary(msg, pos, &p),; );
  196. UA_ActivateSessionResponse_init(&r);
  197. init_response_header(&p.requestHeader, &r.responseHeader);
  198. Service_ActivateSession(server, channel, &p, &r);
  199. UA_ByteString_newMembers(&responseBuf.strings[1], UA_ActivateSessionResponse_calcSizeBinary(&r));
  200. UA_ActivateSessionResponse_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
  201. UA_ActivateSessionRequest_deleteMembers(&p);
  202. UA_ActivateSessionResponse_deleteMembers(&r);
  203. responseType = requestType.nodeId.identifier.numeric + 3;
  204. }
  205. break;
  206. case UA_READREQUEST_NS0:
  207. INVOKE_SERVICE(Read);
  208. break;
  209. case UA_WRITEREQUEST_NS0:
  210. INVOKE_SERVICE(Write);
  211. break;
  212. case UA_BROWSEREQUEST_NS0:
  213. INVOKE_SERVICE(Browse);
  214. break;
  215. /* case UA_CREATESUBSCRIPTIONREQUEST_NS0: */
  216. /* INVOKE_SERVICE(CreateSubscription); */
  217. /* break; */
  218. case UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0:
  219. INVOKE_SERVICE(TranslateBrowsePathsToNodeIds);
  220. break;
  221. case UA_PUBLISHREQUEST_NS0:
  222. INVOKE_SERVICE(Publish);
  223. break;
  224. case UA_CREATEMONITOREDITEMSREQUEST_NS0:
  225. INVOKE_SERVICE(CreateMonitoredItems);
  226. break;
  227. case UA_SETPUBLISHINGMODEREQUEST_NS0:
  228. INVOKE_SERVICE(SetPublishingMode);
  229. break;
  230. default: {
  231. printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
  232. requestType.nodeId.namespaceIndex, requestType.nodeId.identifier.numeric);
  233. UA_RequestHeader p;
  234. UA_ResponseHeader r;
  235. CHECK_PROCESS(UA_RequestHeader_decodeBinary(msg, pos, &p),; );
  236. UA_ResponseHeader_init(&r);
  237. r.requestHandle = p.requestHandle;
  238. r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
  239. UA_ByteString_newMembers(&responseBuf.strings[1], UA_ResponseHeader_calcSizeBinary(&r));
  240. UA_ResponseHeader_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
  241. UA_RequestHeader_deleteMembers(&p);
  242. UA_ResponseHeader_deleteMembers(&r);
  243. responseType = UA_RESPONSEHEADER_NS0 + 2;
  244. }
  245. break;
  246. }
  247. // 5) Build the header
  248. UA_NodeId response_nodeid = { .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  249. .identifier.numeric = responseType }; // add 2 for binary encoding
  250. UA_ByteString_newMembers(&responseBuf.strings[0],
  251. 8 + 16 + // normal header + 4*32bit secure channel information
  252. UA_NodeId_calcSizeBinary(&response_nodeid));
  253. UA_ByteString *header = &responseBuf.strings[0];
  254. UA_UInt32 rpos = 0;
  255. // header
  256. UA_TcpMessageHeader respHeader;
  257. respHeader.messageType = UA_MESSAGETYPE_MSG;
  258. respHeader.isFinal = 'F';
  259. respHeader.messageSize = header->length + responseBuf.strings[1].length;
  260. UA_TcpMessageHeader_encodeBinary(&respHeader, header, &rpos);
  261. // channel id
  262. UA_UInt32_encodeBinary(&channel->securityToken.channelId, header, &rpos);
  263. // algorithm security header
  264. UA_UInt32_encodeBinary(&channel->securityToken.tokenId, header, &rpos);
  265. // encode sequence header
  266. UA_UInt32_encodeBinary(&channel->sequenceNumber, header, &rpos);
  267. UA_UInt32_encodeBinary(&channel->requestId, header, &rpos);
  268. // add payload type
  269. UA_NodeId_encodeBinary(&response_nodeid, header, &rpos);
  270. // sign data
  271. // encrypt data
  272. // 6) Send it over the wire.
  273. connection->write(connection->callbackHandle, responseBuf);
  274. clean_up:
  275. UA_ExpandedNodeId_deleteMembers(&requestType);
  276. UA_ByteStringArray_deleteMembers(&responseBuf);
  277. return;
  278. close_connection:
  279. // make sure allocated data has been freed
  280. connection->state = UA_CONNECTION_CLOSING;
  281. connection->close(connection->callbackHandle);
  282. return;
  283. }
  284. static void processClose(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, UA_UInt32 *pos) {
  285. // just read in the sequenceheader
  286. }
  287. UA_Int32 UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
  288. const UA_ByteString *msg) {
  289. UA_Int32 retval = UA_SUCCESS;
  290. UA_UInt32 pos = 0;
  291. UA_TcpMessageHeader tcpMessageHeader;
  292. // todo: test how far pos advanced must be equal to what is said in the messageheader
  293. do {
  294. retval = UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader);
  295. UA_UInt32 targetpos = pos - 8 + tcpMessageHeader.messageSize;
  296. if(retval == UA_SUCCESS) {
  297. // none of the process-functions returns an error its all contained inside.
  298. switch(tcpMessageHeader.messageType) {
  299. case UA_MESSAGETYPE_HEL:
  300. processHello(connection, msg, &pos);
  301. break;
  302. case UA_MESSAGETYPE_OPN:
  303. processOpen(connection, server, msg, &pos);
  304. break;
  305. case UA_MESSAGETYPE_MSG:
  306. //no break
  307. // if this fails, the connection is closed (no break on the case)
  308. if(connection->state == UA_CONNECTION_ESTABLISHED &&
  309. connection->channel != UA_NULL) {
  310. processMessage(connection, server, msg, &pos);
  311. break;
  312. }
  313. case UA_MESSAGETYPE_CLO:
  314. connection->state = UA_CONNECTION_CLOSING;
  315. processClose(connection, server, msg, &pos);
  316. connection->close(connection->callbackHandle);
  317. return retval;
  318. }
  319. UA_TcpMessageHeader_deleteMembers(&tcpMessageHeader);
  320. } else {
  321. printf("TL_Process - ERROR: decoding of header failed \n");
  322. connection->state = UA_CONNECTION_CLOSING;
  323. //processClose(connection, server, msg, &pos);
  324. connection->close(connection->callbackHandle);
  325. }
  326. // todo: more than one message at once..
  327. if(pos != targetpos) {
  328. printf("The message size was not as announced or an error occurred while processing, skipping to the end of the message.\n");
  329. pos = targetpos;
  330. }
  331. } while(msg->length > (UA_Int32)pos);
  332. return retval;
  333. }