123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- #include <stdio.h>
- #include <memory.h> // memcpy
- #include "ua_transport_binary.h"
- #include "ua_transport_binary_secure.h"
- #include "ua_transport.h"
- #include "ua_statuscodes.h"
- #include "ua_services.h"
- #include "ua_stack_session_manager.h"
- #include "ua_stack_session.h"
- #define SIZE_SECURECHANNEL_HEADER 12
- #define SIZE_SEQHEADER_HEADER 8
- static UA_Int32 SL_Send(SL_Channel channel,
- const UA_ByteString * responseMessage, UA_Int32 type)
- {
- UA_UInt32 pos = 0;
- UA_Int32 isAsym = (type == UA_OPENSECURECHANNELRESPONSE_NS0); // FIXME: this is a to dumb method to determine asymmetric algorithm setting
- UA_UInt32 channelId;
- UA_UInt32 sequenceNumber;
- UA_UInt32 requestId;
- UA_TL_Connection connection;
- UA_NodeId resp_nodeid;
- UA_AsymmetricAlgorithmSecurityHeader *asymAlgSettings = UA_NULL;
- resp_nodeid.encodingByte = UA_NODEIDTYPE_FOURBYTE;
- resp_nodeid.namespace = 0;
- resp_nodeid.identifier.numeric = type + 2; // binary encoding
- const UA_ByteString *response_gather[2]; // securechannel_header, seq_header, security_encryption_header, message_length (eventually + padding + size_signature);
- UA_alloc((void ** )&response_gather[0], sizeof(UA_ByteString));
- if (isAsym)
- {
- SL_Channel_getLocalAsymAlgSettings(channel, &asymAlgSettings);
- UA_ByteString_newMembers((UA_ByteString *) response_gather[0],
- SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
- + UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(
- asymAlgSettings)
- + UA_NodeId_calcSizeBinary(&resp_nodeid));
- }
- else
- {
- UA_ByteString_newMembers((UA_ByteString *) response_gather[0], 8 + 16 + // normal header + 4*32bit secure channel information
- UA_NodeId_calcSizeBinary(&resp_nodeid));
- }
- // sizePadding = 0;
- // sizeSignature = 0;
- UA_ByteString *header = (UA_ByteString *) response_gather[0];
- /*---encode Secure Conversation Message Header ---*/
- if (isAsym)
- {
- header->data[0] = 'O';
- header->data[1] = 'P';
- header->data[2] = 'N';
- }
- else
- {
- header->data[0] = 'M';
- header->data[1] = 'S';
- header->data[2] = 'G';
- }
- pos += 3;
- header->data[pos] = 'F';
- pos += 1;
- UA_Int32 packetSize = response_gather[0]->length + responseMessage->length;
- UA_Int32_encodeBinary(&packetSize, header,&pos);
- //use get accessor to read the channel Id
- SL_Channel_getChannelId(channel, &channelId);
- UA_UInt32_encodeBinary(&channelId, header,&pos);
- /*---encode Algorithm Security Header ---*/
- if (isAsym)
- {
- UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(asymAlgSettings,
- header,&pos);
- UA_free(asymAlgSettings);
- }
- else
- {
- UA_UInt32 tokenId = 0;
- SL_Channel_getTokenId(channel, &tokenId);
- UA_UInt32_encodeBinary(&tokenId, header,&pos);
- }
- /*---encode Sequence Header ---*/
- SL_Channel_getSequenceNumber(channel, &sequenceNumber);
- UA_UInt32_encodeBinary(&sequenceNumber, header, &pos);
- SL_Channel_getRequestId(channel, &requestId);
- UA_UInt32_encodeBinary(&requestId, header,&pos);
- /*---add payload type---*/
- UA_NodeId_encodeBinary(&resp_nodeid, header,&pos);
- /*---add encoded Message ---*/
- response_gather[1] = responseMessage; // is deleted in the calling function
- /* sign Data*/
- /* encrypt Data*/
- /* send Data */
- SL_Channel_getConnection(channel, &connection);
- TL_Send(connection, response_gather, 2);
- UA_ByteString_delete((UA_ByteString *) response_gather[0]);
- return UA_SUCCESS;
- }
- static void init_response_header(UA_RequestHeader const * p,
- UA_ResponseHeader * r)
- {
- memset((void*) r, 0, sizeof(UA_ResponseHeader));
- r->requestHandle = p->requestHandle;
- r->serviceResult = UA_STATUSCODE_GOOD;
- r->stringTableSize = 0;
- r->timestamp = UA_DateTime_now();
- }
- #define RESPONSE_PREPARE(TYPE) \
- UA_##TYPE##Request p; \
- UA_##TYPE##Response r; \
- UA_Session session = UA_NULL; \
- UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
- UA_##TYPE##Response_init(&r); \
- init_response_header(&p.requestHeader, &r.responseHeader); \
- UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
- DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
- #define INVOKE_SERVICE(TYPE) \
- UA_##TYPE##Request p; \
- UA_##TYPE##Response r; \
- UA_Session session = UA_NULL; \
- UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
- UA_##TYPE##Response_init(&r); \
- init_response_header(&p.requestHeader, &r.responseHeader); \
- UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
- DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
- Service_##TYPE(session, &p, &r); \
- DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
- sendOffset = 0; \
- UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
- UA_##TYPE##Response_encodeBinary(&r, &sendOffset, &response_msg); \
- UA_##TYPE##Request_deleteMembers(&p); \
- UA_##TYPE##Response_deleteMembers(&r); \
- /*
- #define INVOKE_SERVICE(TYPE) \
- DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
- Service_##TYPE(session, &p, &r); \
- DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
- */
- #define RESPONSE_CLEANUP(TYPE) \
- DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
- sendOffset = 0; \
- UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
- UA_##TYPE##Response_encodeBinary(&r, &response_msg,&sendOffset); \
- UA_##TYPE##Request_deleteMembers(&p); \
- UA_##TYPE##Response_deleteMembers(&r); \
- UA_Int32 SL_handleRequest(SL_Channel channel, const UA_ByteString* msg,
- UA_UInt32 *pos)
- {
- UA_Int32 retval = UA_SUCCESS;
- UA_UInt32 recvOffset = *pos;
- UA_UInt32 sendOffset = 0;
- // Every Message starts with a NodeID which names the serviceRequestType
- UA_NodeId serviceRequestType;
- UA_NodeId_decodeBinary(msg, &recvOffset,&serviceRequestType);
- #ifdef DEBUG
- UA_NodeId_printf("SL_processMessage - serviceRequestType=",
- &serviceRequestType);
- #endif
- UA_ByteString response_msg;
- UA_Int32 serviceid = serviceRequestType.identifier.numeric - 2; // binary encoding has 2 added to the id
- UA_Int32 responsetype;
- /* stack related services which only need information about the secure Channel */
- if (serviceid == UA_GETENDPOINTSREQUEST_NS0)
- {
- RESPONSE_PREPARE(GetEndpoints);
- Service_GetEndpoints(channel,&p, &r);
- RESPONSE_CLEANUP(GetEndpoints);
- //INVOKE_SERVICE(GetEndpoints);
- responsetype = UA_GETENDPOINTSRESPONSE_NS0;
- }
- else if (serviceid == UA_OPENSECURECHANNELREQUEST_NS0)
- {
- RESPONSE_PREPARE(OpenSecureChannel);
- Service_OpenSecureChannel(channel,&p, &r);
- RESPONSE_CLEANUP(OpenSecureChannel);
- responsetype = UA_OPENSECURECHANNELRESPONSE_NS0;
- }
- else if (serviceid == UA_CLOSESECURECHANNELREQUEST_NS0)
- {
- RESPONSE_PREPARE(CloseSecureChannel);
- Service_CloseSecureChannel(channel,&p,&r);
- RESPONSE_CLEANUP(CloseSecureChannel);
- responsetype = UA_CLOSESECURECHANNELRESPONSE_NS0;
- }
- else if (serviceid == UA_CREATESESSIONREQUEST_NS0)
- {
- RESPONSE_PREPARE(CreateSession);
- Service_CreateSession(channel,&p, &r);
- RESPONSE_CLEANUP(CreateSession);
- responsetype = UA_CREATESESSIONRESPONSE_NS0;
- }
- /* services which need a session object */
- else if (serviceid == UA_ACTIVATESESSIONREQUEST_NS0)
- {
- RESPONSE_PREPARE(ActivateSession);
- UA_Session_updateLifetime(session); //renew session timeout
- Service_ActivateSession(channel, session,&p, &r);
- RESPONSE_CLEANUP(ActivateSession);
- responsetype = UA_ACTIVATESESSIONRESPONSE_NS0;
- }
- else if (serviceid == UA_CLOSESESSIONREQUEST_NS0)
- {
- RESPONSE_PREPARE(CloseSession);
- if (UA_Session_verifyChannel(session,channel)){
- UA_Session_updateLifetime(session); //renew session timeout
- Service_CloseSession(session,&p, &r);
- RESPONSE_CLEANUP(CloseSession);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- responsetype = UA_CLOSESESSIONRESPONSE_NS0;
- }
- else if (serviceid == UA_READREQUEST_NS0)
- {
- RESPONSE_PREPARE(Read);
- UA_Session_updateLifetime(session); //renew session timeout
- DBG_VERBOSE(printf("Finished Service: %s\n", Read));
- if (UA_Session_verifyChannel(session,channel)){
- UA_Session_updateLifetime(session); //renew session timeout
- Service_Read(session,&p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", Read));
- RESPONSE_CLEANUP(Read);
- responsetype = UA_READRESPONSE_NS0;
- }
- else if (serviceid == UA_WRITEREQUEST_NS0)
- {
- RESPONSE_PREPARE(Write);
- DBG_VERBOSE(printf("Finished Service: %s\n", Write));
- if (UA_Session_verifyChannel(session,channel)){
- UA_Session_updateLifetime(session); //renew session timeout
- Service_Write(session,&p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", Write));
- RESPONSE_CLEANUP(Write);
- responsetype = UA_WRITERESPONSE_NS0;
- }
- else if (serviceid == UA_BROWSEREQUEST_NS0)
- {
- RESPONSE_PREPARE(Browse);
- DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
- if (UA_Session_verifyChannel(session,channel)){
- Service_Browse(session,&p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
- RESPONSE_CLEANUP(Browse);
- responsetype = UA_BROWSERESPONSE_NS0;
- }
- else if (serviceid == UA_CREATESUBSCRIPTIONREQUEST_NS0)
- {
- RESPONSE_PREPARE(CreateSubscription);
- DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
- if (UA_Session_verifyChannel(session,channel)){
- Service_CreateSubscription(session, &p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
- RESPONSE_CLEANUP(CreateSubscription);
- responsetype = UA_CREATESUBSCRIPTIONRESPONSE_NS0;
- }
- else if (serviceid == UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0)
- {
- RESPONSE_PREPARE(TranslateBrowsePathsToNodeIds);
- DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
- if (UA_Session_verifyChannel(session,channel)){
- Service_TranslateBrowsePathsToNodeIds(session, &p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
- RESPONSE_CLEANUP(TranslateBrowsePathsToNodeIds);
- responsetype = UA_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE_NS0;
- }
- else if (serviceid == UA_PUBLISHREQUEST_NS0)
- {
- RESPONSE_PREPARE(Publish);
- DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
- if (UA_Session_verifyChannel(session,channel)){
- Service_Publish(session, &p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
- RESPONSE_CLEANUP(Publish);
- responsetype = UA_PUBLISHRESPONSE_NS0;
- }
- else if (serviceid == UA_CREATEMONITOREDITEMSREQUEST_NS0)
- {
- RESPONSE_PREPARE(CreateMonitoredItems);
- DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
- if (UA_Session_verifyChannel(session,channel)){
- Service_CreateMonitoredItems(session, &p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
- RESPONSE_CLEANUP(CreateMonitoredItems);
- responsetype = UA_CREATEMONITOREDITEMSRESPONSE_NS0;
- }
- else if (serviceid == UA_SETPUBLISHINGMODEREQUEST_NS0)
- {
- RESPONSE_PREPARE(SetPublishingMode);
- DBG_VERBOSE(printf("Finished Service: %s\n",SetPublishingMode));
- if (UA_Session_verifyChannel(session,channel)){
- Service_SetPublishingMode(session, &p, &r);
- }
- else
- {
- DBG_VERBOSE(printf("session does not match secure channel"));
- }
- DBG_VERBOSE(printf("Finished Service: %s\n", SetPublishingMode));
- RESPONSE_CLEANUP(SetPublishingMode);
- responsetype = UA_SETPUBLISHINGMODERESPONSE_NS0;
- }
- else
- {
- printf(
- "SL_processMessage - unknown request, namespace=%d, request=%d\n",
- serviceRequestType.namespace,
- serviceRequestType.identifier.numeric);
- retval = UA_ERROR;
- UA_RequestHeader p;
- UA_ResponseHeader r;
- UA_RequestHeader_decodeBinary(msg, &recvOffset, &p);
- UA_ResponseHeader_init(&r);
- r.requestHandle = p.requestHandle;
- r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
- sendOffset = 0;
- UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSizeBinary(&r));
- UA_ResponseHeader_encodeBinary(&r, &response_msg,&sendOffset);
- responsetype = UA_RESPONSEHEADER_NS0;
- }
- if(serviceid != UA_CLOSESECURECHANNELREQUEST_NS0){
- SL_Send(channel, &response_msg, responsetype);
- }
- UA_ByteString_deleteMembers(&response_msg);
- *pos = recvOffset;
- return retval;
- }
- UA_Int32 SL_ProcessOpenChannel(SL_Channel channel, const UA_ByteString* msg,
- UA_UInt32 *pos)
- {
- UA_Int32 retval = UA_SUCCESS;
- UA_SequenceHeader sequenceHeader;
- UA_AsymmetricAlgorithmSecurityHeader asymHeader;
- *pos+=4; //skip secure channel id
- UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg,pos,&asymHeader);
- UA_SequenceHeader_decodeBinary(msg,pos,&sequenceHeader);
- //init remote security settings from the security header
- SL_Channel_setRemoteSecuritySettings(channel,&asymHeader,&sequenceHeader);
- return SL_handleRequest(channel, msg, pos) | retval;
- }
- UA_Int32 SL_ProcessCloseChannel(SL_Channel channel, const UA_ByteString* msg,
- UA_UInt32 *pos)
- {
- return SL_handleRequest(channel, msg, pos);
- }
- UA_Int32 SL_Process(const UA_ByteString* msg,
- UA_UInt32* pos)
- {
- DBG_VERBOSE(printf("SL_process - entered \n"));
- UA_UInt32 secureChannelId;
- UA_UInt32 foundChannelId;
- SL_Channel channel;
- UA_SequenceHeader sequenceHeader;
- UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
- //FIXME: we assume SAS, need to check if AAS or SAS
- UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
- // if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
- UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos,
- &symAlgSecHeader);
- if (SL_ChannelManager_getChannel(secureChannelId,
- &channel) == UA_SUCCESS)
- {
- SL_Channel_getChannelId(channel, &foundChannelId);
- printf("SL_process - received msg, with channel id: %i \n",
- foundChannelId);
- //sequence number processing
- UA_SequenceHeader_decodeBinary(msg, pos,
- &sequenceHeader);
- SL_Channel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
- SL_Channel_checkRequestId(channel,sequenceHeader.requestId);
- //request id processing
- SL_handleRequest(channel, msg, pos);
- }
- else
- {
- //TODO generate ERROR_Bad_SecureChannelUnkown
- }
- return UA_SUCCESS;
- }
|