123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #include <stdio.h>
- #include <memory.h> // memcpy
- #include "opcua.h"
- #include "ua_transport_binary.h"
- #include "ua_transport_binary_secure.h"
- #include "ua_transport.h"
- #include "ua_statuscodes.h"
- #include "ua_services.h"
- #define SIZE_SECURECHANNEL_HEADER 12
- #define SIZE_SEQHEADER_HEADER 8
- static UA_Int32 SL_Send(SL_secureChannel channel,
- const UA_ByteString * responseMessage, UA_Int32 type)
- {
- //access function for SL_secureChannel
- //SL_Channel_getId(secureChannel)
- //SL_Channel_getSequenceNumber(secureChannel)
- UA_Int32 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_Connection1 connection;
- UA_NodeId resp_nodeid;
- UA_AsymmetricAlgorithmSecurityHeader *asymAlgSettings = UA_NULL;
- //UA_AsymmetricAlgorithmSecurityHeader_new((void**)(&asymAlgSettings));
- 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)
- {
- UA_ByteString_newMembers((UA_ByteString *) response_gather[0],
- SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
- + UA_AsymmetricAlgorithmSecurityHeader_calcSize(
- asymAlgSettings)
- + UA_NodeId_calcSize(&resp_nodeid));
- }
- else
- {
- UA_ByteString_newMembers((UA_ByteString *) response_gather[0], 8 + 16 + // normal header + 4*32bit secure channel information
- UA_NodeId_calcSize(&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, &pos, header);
- //use get accessor to read the channel Id
- SL_Channel_getChannelId(channel, &channelId);
- UA_UInt32_encodeBinary(&channelId, &pos, header);
- /*---encode Algorithm Security Header ---*/
- if (isAsym)
- {
- SL_Channel_getLocalAsymAlgSettings(channel, asymAlgSettings);
- UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(asymAlgSettings, &pos,
- header);
- }
- else
- {
- UA_UInt32 tokenId = 0;
- SL_Channel_getTokenId(channel, &tokenId);
- UA_UInt32_encodeBinary(&tokenId, &pos, header);
- }
- /*---encode Sequence Header ---*/
- SL_Channel_getSequenceNumber(channel, &sequenceNumber);
- UA_UInt32_encodeBinary(&sequenceNumber, &pos, header);
- SL_Channel_getRequestId(channel, &requestId);
- UA_UInt32_encodeBinary(&requestId, &pos, header);
- /*---add payload type---*/
- UA_NodeId_encodeBinary(&resp_nodeid, &pos, header);
- /*---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 INVOKE_SERVICE(TYPE) \
- UA_##TYPE##Request p; \
- UA_##TYPE##Response r; \
- UA_##TYPE##Request_decodeBinary(msg, pos, &p); \
- UA_##TYPE##Response_init(&r); \
- init_response_header(&p.requestHeader, &r.responseHeader); \
- DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
- Service_##TYPE(&p, &r); \
- DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
- *pos = 0; \
- UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSize(&r)); \
- UA_##TYPE##Response_encodeBinary(&r, pos, &response_msg); \
- UA_##TYPE##Request_deleteMembers(&p); \
- UA_##TYPE##Response_deleteMembers(&r); \
- /** this function manages all the generic stuff for the request-response game */
- //UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg,
- // UA_Int32 *pos)
- UA_Int32 SL_handleRequest(SL_secureChannel channel, const UA_ByteString* msg,
- UA_Int32 *pos)
- {
- UA_Int32 retval = UA_SUCCESS;
- // Every Message starts with a NodeID which names the serviceRequestType
- UA_NodeId serviceRequestType;
- UA_NodeId_decodeBinary(msg, pos, &serviceRequestType);
- UA_NodeId_printf("SL_processMessage - serviceRequestType=",
- &serviceRequestType);
- UA_ByteString response_msg;
- UA_Int32 serviceid = serviceRequestType.identifier.numeric - 2; // binary encoding has 2 added to the id
- UA_Int32 responsetype;
- if (serviceid == UA_GETENDPOINTSREQUEST_NS0)
- {
- INVOKE_SERVICE(GetEndpoints);
- responsetype = UA_GETENDPOINTSRESPONSE_NS0;
- }
- else if (serviceid == UA_OPENSECURECHANNELREQUEST_NS0)
- {
- //I see at the moment no other way to handle this
- UA_OpenSecureChannelRequest p;
- UA_OpenSecureChannelResponse r;
- UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &p);
- UA_OpenSecureChannelResponse_init(&r);
- init_response_header(&p.requestHeader, &r.responseHeader);
- DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE));
- Service_OpenSecureChannel(channel,&p, &r);
- DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE));
- *pos = 0; \
- UA_ByteString_newMembers(&response_msg, UA_OpenSecureChannelResponse_calcSize(&r));
- UA_OpenSecureChannelResponse_encodeBinary(&r, pos, &response_msg);
- UA_OpenSecureChannelRequest_deleteMembers(&p);
- UA_OpenSecureChannelResponse_deleteMembers(&r);
- //INVOKE_SERVICE(OpenSecureChannel);
- responsetype = UA_OPENSECURECHANNELRESPONSE_NS0;
- }
- else if (serviceid == UA_CLOSESECURECHANNELREQUEST_NS0)
- {
- INVOKE_SERVICE(CloseSecureChannel);
- responsetype = UA_CLOSESECURECHANNELRESPONSE_NS0;
- }
- else if (serviceid == UA_CREATESESSIONREQUEST_NS0)
- {
- //TODO prepare userdefined implementation
- INVOKE_SERVICE(CreateSession);
- responsetype = UA_CREATESESSIONRESPONSE_NS0;
- }
- else if (serviceid == UA_ACTIVATESESSIONREQUEST_NS0)
- {
- //TODO prepare userdefined implementation
- INVOKE_SERVICE(ActivateSession);
- responsetype = UA_ACTIVATESESSIONRESPONSE_NS0;
- }
- else if (serviceid == UA_CLOSESESSIONREQUEST_NS0)
- {
- //TODO prepare userdefined implementation
- INVOKE_SERVICE(CloseSession);
- responsetype = UA_CLOSESESSIONRESPONSE_NS0;
- }
- else if (serviceid == UA_READREQUEST_NS0)
- {
- //TODO prepare userdefined implementation
- INVOKE_SERVICE(Read);
- responsetype = UA_READRESPONSE_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, pos, &p);
- UA_ResponseHeader_init(&r);
- r.requestHandle = p.requestHandle;
- r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
- *pos = 0;
- UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSize(&r));
- UA_ResponseHeader_encodeBinary(&r, pos, &response_msg);
- responsetype = UA_RESPONSEHEADER_NS0;
- }
- SL_Send(channel, &response_msg, responsetype);
- UA_ByteString_deleteMembers(&response_msg);
- return retval;
- }
- UA_Int32 SL_ProcessOpenChannel(SL_secureChannel channel, const UA_ByteString* msg,
- UA_Int32 *pos)
- {
- return SL_handleRequest(channel, msg, pos);
- }
- /**
- *
- * @param connection
- * @param msg
- * @param pos
- * @return
- */
- //UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg,
- // UA_Int32* pos)
- //{
- // DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
- // UA_Int32 retval = UA_SUCCESS;
- //
- // /* Create New Channel*/
- // SL_Channel *channel = &slc; // FIXME: generate new secure channel
- // UA_AsymmetricAlgorithmSecurityHeader_init(&(channel->localAsymAlgSettings));
- // UA_ByteString_copy(&UA_ByteString_securityPoliceNone,
- // &(channel->localAsymAlgSettings.securityPolicyUri));
- // UA_alloc((void** )&(channel->localNonce.data), sizeof(UA_Byte));
- // channel->localNonce.length = 1;
- // channel->connectionState = CONNECTIONSTATE_CLOSED; // the state of the channel will be opened in the service
- // channel->sequenceHeader.requestId = 0;
- // channel->sequenceHeader.sequenceNumber = 1;
- // UA_String_init(&(channel->secureChannelId));
- // channel->securityMode = UA_SECURITYMODE_INVALID;
- // channel->securityToken.secureChannelId = 25; //TODO set a valid start secureChannelId number
- // channel->securityToken.tokenId.tokenId = 1; //TODO set a valid start TokenId
- // connection->secureChannel = channel;
- // connection->secureChannel->tlConnection = connection;
- /* Read the OPN message headers */
- // *pos += 4; // skip the securechannelid
- // UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos,
- // &connection->secureChannel->remoteAsymAlgSettings);
- // UA_SequenceHeader_decodeBinary(msg, pos,
- // &connection->secureChannel->sequenceHeader);
- // //TODO check that the sequence number is smaller than MaxUInt32 - 1024
- // //TODO check if a OpenSecureChannelRequest follows
- // retval |= SL_handleRequest(channel, msg, pos);
- // return retval;
- // FIXME: reject
- //}
- /**
- * process the rest of the header. TL already processed MessageType
- * (OPN,MSG,...), isFinal and MessageSize. SL_process cares for
- * secureChannelId, XASHeader and sequenceHeader
- * */
- UA_Int32 SL_Process(const UA_ByteString* msg,
- UA_Int32* pos)
- {
- DBG_VERBOSE(printf("SL_process - entered \n"));
- UA_UInt32 secureChannelId;
- UA_UInt32 foundChannelId;
- SL_secureChannel 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);
- //request id processing
- SL_handleRequest(channel, msg, pos);
- }
- else
- {
- //TODO generate ERROR_Bad_SecureChannelUnkown
- }
- return UA_SUCCESS;
- }
|