ua_server_binary.c 16 KB

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