static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) { if(connection->state != UA_CONNECTION_ESTABLISHED) { connection->close(connection); return; } UA_UInt32 secureChannelId; UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId); UA_AsymmetricAlgorithmSecurityHeader asymHeader; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader); UA_SequenceHeader seqHeader; retval |= UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader); UA_NodeId requestType; retval |= UA_NodeId_decodeBinary(msg, pos, &requestType); UA_OpenSecureChannelRequest r; retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r); if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_deleteMembers(&seqHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); UA_SecureChannel *channel = connection->channel; if(!channel) { connection->close(connection); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } /* send the response with an asymmetric security header */ seqHeader.sequenceNumber = channel->sequenceNumber; UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; respHeader.messageHeader.messageSize = 0; respHeader.secureChannelId = p.securityToken.channelId; UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE + UA_ENCODINGOFFSET_BINARY); respHeader.messageHeader.messageSize = UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader) + UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) + UA_SequenceHeader_calcSizeBinary(&seqHeader) + UA_NodeId_calcSizeBinary(&responseType) + UA_OpenSecureChannelResponse_calcSizeBinary(&p); UA_ByteString resp_msg; retval = connection->getBuffer(connection, &resp_msg, respHeader.messageHeader.messageSize); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } size_t tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->write(connection, &resp_msg); connection->releaseBuffer(connection, &resp_msg); }
/* OPN -> Open up/renew the securechannel */ static void processOPN(UA_Server *server, UA_Connection *connection, UA_UInt32 channelId, const UA_ByteString *msg) { UA_StatusCode retval = UA_STATUSCODE_GOOD; /* Called before HEL */ if(connection->state != UA_CONNECTION_ESTABLISHED) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Opening up a channel with a channelid already set */ if(!connection->channel && channelId != 0) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Renew a channel with the wrong channelid */ if(connection->channel && channelId != connection->channel->securityToken.channelId) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Decode the request */ UA_AsymmetricAlgorithmSecurityHeader asymHeader; UA_SequenceHeader seqHeader; UA_NodeId requestType; UA_OpenSecureChannelRequest r; size_t offset = 0; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, &offset, &asymHeader); retval |= UA_SequenceHeader_decodeBinary(msg, &offset, &seqHeader); retval |= UA_NodeId_decodeBinary(msg, &offset, &requestType); retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, &offset, &r); /* Error occured */ if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } /* Call the service */ UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); /* Opening the channel failed */ UA_SecureChannel *channel = connection->channel; if(!channel) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Set the starting sequence number */ channel->receiveSequenceNumber = seqHeader.sequenceNumber; /* Allocate the return message */ UA_ByteString resp_msg; UA_ByteString_init(&resp_msg); retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &resp_msg); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Encode the message after the secureconversationmessageheader */ size_t tmpPos = 12; /* skip the header */ seqHeader.sequenceNumber = UA_atomic_add(&channel->sendSequenceNumber, 1); retval |= UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId); retval |= UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); retval |= UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); if(retval != UA_STATUSCODE_GOOD) { connection->releaseSendBuffer(connection, &resp_msg); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Encode the secureconversationmessageheader (cannot fail) and send */ UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL; respHeader.messageHeader.messageSize = (UA_UInt32)tmpPos; respHeader.secureChannelId = p.securityToken.channelId; tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); resp_msg.length = respHeader.messageHeader.messageSize; connection->send(connection, &resp_msg); /* Clean up */ UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); }
static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) { if(connection->state != UA_CONNECTION_ESTABLISHED) { connection->close(connection); return; } UA_UInt32 secureChannelId; UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId); UA_AsymmetricAlgorithmSecurityHeader asymHeader; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader); UA_SequenceHeader seqHeader; retval |= UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader); UA_NodeId requestType; retval |= UA_NodeId_decodeBinary(msg, pos, &requestType); UA_OpenSecureChannelRequest r; retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r); if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_deleteMembers(&seqHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); UA_SecureChannel *channel = connection->channel; if(!channel) { connection->close(connection); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } /* send the response with an asymmetric security header */ #ifndef UA_MULTITHREADING seqHeader.sequenceNumber = ++channel->sequenceNumber; #else seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1); #endif UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; respHeader.messageHeader.messageSize = 0; respHeader.secureChannelId = p.securityToken.channelId; UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE + UA_ENCODINGOFFSET_BINARY); UA_ByteString resp_msg; retval = connection->getSendBuffer(connection, connection->remoteConf.recvBufferSize, &resp_msg); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } size_t tmpPos = 12; /* skip the secureconversationmessageheader for now */ retval |= UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); retval |= UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); if(retval != UA_STATUSCODE_GOOD) { connection->releaseSendBuffer(connection, &resp_msg); connection->close(connection); } else { respHeader.messageHeader.messageSize = tmpPos; tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); resp_msg.length = respHeader.messageHeader.messageSize; connection->send(connection, &resp_msg); } UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); }