|
@@ -6,6 +6,7 @@
|
|
|
*/
|
|
|
#include <stdio.h>
|
|
|
#include <memory.h> // memcpy
|
|
|
+#include "opcua.h"
|
|
|
#include "opcua_transportLayer.h"
|
|
|
#include "opcua_secureLayer.h"
|
|
|
#include "UA_stackInternalTypes.h"
|
|
@@ -13,16 +14,17 @@
|
|
|
#define SIZE_SECURECHANNEL_HEADER 12
|
|
|
#define SIZE_SEQHEADER_HEADER 8
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
* inits a connection object for secure channel layer
|
|
|
*/
|
|
|
-UA_Int32 SL_initConnectionObject(UA_connection *connection)
|
|
|
-{
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_init(&(connection->secureLayer.localAsymAlgSettings));
|
|
|
- UA_ByteString_copy(&UA_ByteString_securityPoliceNone, &(connection->secureLayer.localAsymAlgSettings.securityPolicyUri));
|
|
|
-
|
|
|
- UA_alloc((void**)&(connection->secureLayer.localNonce.data),sizeof(UA_Byte));
|
|
|
+UA_Int32 SL_initConnectionObject(UA_connection *connection) {
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_init(
|
|
|
+ &(connection->secureLayer.localAsymAlgSettings));
|
|
|
+ UA_ByteString_copy(&UA_ByteString_securityPoliceNone,
|
|
|
+ &(connection->secureLayer.localAsymAlgSettings.securityPolicyUri));
|
|
|
+
|
|
|
+ UA_alloc((void**)&(connection->secureLayer.localNonce.data),
|
|
|
+ sizeof(UA_Byte));
|
|
|
connection->secureLayer.localNonce.length = 1;
|
|
|
|
|
|
connection->secureLayer.connectionState = connectionState_CLOSED;
|
|
@@ -43,8 +45,8 @@ UA_Int32 SL_initConnectionObject(UA_connection *connection)
|
|
|
return UA_NO_ERROR;
|
|
|
}
|
|
|
|
|
|
-UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessage, UA_Int32 type)
|
|
|
-{
|
|
|
+UA_Int32 SL_send(UA_connection* connection,
|
|
|
+ UA_ByteString const * responseMessage, UA_Int32 type) {
|
|
|
UA_UInt32 sequenceNumber;
|
|
|
UA_UInt32 requestId;
|
|
|
UA_Int32 pos;
|
|
@@ -56,24 +58,24 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
|
|
|
// FIXME: this is a to dump method to determine asymmetric algorithm setting
|
|
|
UA_Int32 isAsym = (type == 449);
|
|
|
|
|
|
-
|
|
|
pos = 0;
|
|
|
//sequence header
|
|
|
sequenceNumber = connection->secureLayer.sequenceNumber;
|
|
|
- requestId = connection->secureLayer.requestId;
|
|
|
+ requestId = connection->secureLayer.requestId;
|
|
|
|
|
|
- sizePadding = 0;
|
|
|
+ sizePadding = 0;
|
|
|
sizeSignature = 0;
|
|
|
|
|
|
- packetSize = SIZE_SECURECHANNEL_HEADER +
|
|
|
- SIZE_SEQHEADER_HEADER +
|
|
|
- ( isAsym ? UA_AsymmetricAlgorithmSecurityHeader_calcSize(&(connection->secureLayer.localAsymAlgSettings)) : UA_SymmetricAlgorithmSecurityHeader_calcSize(&(connection->secureLayer.securityToken.tokenId)) )+
|
|
|
- responseMessage->length +
|
|
|
- sizePadding +
|
|
|
- sizeSignature;
|
|
|
+ packetSize = SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
|
|
|
+ + (isAsym ?
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_calcSize(
|
|
|
+ &(connection->secureLayer.localAsymAlgSettings)) :
|
|
|
+ UA_SymmetricAlgorithmSecurityHeader_calcSize(
|
|
|
+ &(connection->secureLayer.securityToken.tokenId)))
|
|
|
+ + responseMessage->length + sizePadding + sizeSignature;
|
|
|
|
|
|
//get memory for response
|
|
|
- UA_alloc((void**)&(responsePacket.data),packetSize);
|
|
|
+ UA_alloc((void**)&(responsePacket.data), packetSize);
|
|
|
responsePacket.length = packetSize;
|
|
|
|
|
|
/*---encode Secure Conversation Message Header ---*/
|
|
@@ -91,29 +93,35 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
|
|
|
pos += 3;
|
|
|
responsePacket.data[3] = 'F';
|
|
|
pos += 1;
|
|
|
- UA_Int32_encode(&packetSize,&pos,responsePacket.data);
|
|
|
- UA_UInt32_encode(&(connection->secureLayer.securityToken.secureChannelId),&pos,responsePacket.data);
|
|
|
+ UA_Int32_encode(&packetSize, &pos, responsePacket.data);
|
|
|
+ UA_UInt32_encode(&(connection->secureLayer.securityToken.secureChannelId),
|
|
|
+ &pos, responsePacket.data);
|
|
|
|
|
|
/*---encode Algorithm Security Header ---*/
|
|
|
- if (isAsym) {
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_encode(&(connection->secureLayer.localAsymAlgSettings),&pos,responsePacket.data);
|
|
|
+ if (isAsym) {
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_encode(
|
|
|
+ &(connection->secureLayer.localAsymAlgSettings), &pos,
|
|
|
+ responsePacket.data);
|
|
|
} else {
|
|
|
- UA_SymmetricAlgorithmSecurityHeader_encode(&(connection->secureLayer.securityToken.tokenId),&pos,responsePacket.data);
|
|
|
+ UA_SymmetricAlgorithmSecurityHeader_encode(
|
|
|
+ &(connection->secureLayer.securityToken.tokenId), &pos,
|
|
|
+ responsePacket.data);
|
|
|
}
|
|
|
|
|
|
/*---encode Sequence Header ---*/
|
|
|
- UA_UInt32_encode(&sequenceNumber,&pos,responsePacket.data);
|
|
|
- UA_UInt32_encode(&requestId,&pos,responsePacket.data);
|
|
|
+ UA_UInt32_encode(&sequenceNumber, &pos, responsePacket.data);
|
|
|
+ UA_UInt32_encode(&requestId, &pos, responsePacket.data);
|
|
|
|
|
|
/*---add encoded Message ---*/
|
|
|
- UA_memcpy(&(responsePacket.data[pos]), responseMessage->data, responseMessage->length);
|
|
|
+ UA_memcpy(&(responsePacket.data[pos]), responseMessage->data,
|
|
|
+ responseMessage->length);
|
|
|
|
|
|
/* sign Data*/
|
|
|
|
|
|
/* encrypt Data*/
|
|
|
|
|
|
/* send Data */
|
|
|
- TL_send(connection,&responsePacket);
|
|
|
+ TL_send(connection, &responsePacket);
|
|
|
// responsePackage will be deleted by top-level procedure
|
|
|
return UA_NO_ERROR;
|
|
|
}
|
|
@@ -122,38 +130,27 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
|
|
|
* opens a secure channel
|
|
|
*/
|
|
|
UA_Int32 SL_openSecureChannel(UA_connection *connection,
|
|
|
- UA_RequestHeader *requestHeader,
|
|
|
- UA_StatusCode serviceResult)
|
|
|
-{
|
|
|
-
|
|
|
+ UA_RequestHeader *requestHeader, UA_StatusCode serviceResult) {
|
|
|
|
|
|
-
|
|
|
- UA_ResponseHeader responseHeader;
|
|
|
- UA_ExtensionObject additionalHeader;
|
|
|
- UA_ChannelSecurityToken securityToken;
|
|
|
- UA_ByteString serverNonce;
|
|
|
+ UA_OpenSecureChannelResponse* r;
|
|
|
UA_NodeId responseType;
|
|
|
- //sizes for memory allocation
|
|
|
- // UA_Int32 sizeResponse;
|
|
|
- UA_Int32 sizeRespHeader;
|
|
|
- UA_Int32 sizeResponseType;
|
|
|
- UA_Int32 sizeRespMessage;
|
|
|
- // UA_Int32 sizeSecurityToken;
|
|
|
UA_ByteString response;
|
|
|
- UA_UInt32 serverProtocolVersion;
|
|
|
UA_Int32 pos;
|
|
|
- UA_DiagnosticInfo serviceDiagnostics;
|
|
|
|
|
|
- if(requestHeader->returnDiagnostics != 0)
|
|
|
- {
|
|
|
+ UA_OpenSecureChannelResponse_new(&r);
|
|
|
+ UA_ResponseHeader_new(&(r->responseHeader));
|
|
|
+ UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
|
|
|
+ UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
|
|
|
+ UA_ChannelSecurityToken_new(&(r->securityToken));
|
|
|
+
|
|
|
+ if (requestHeader->returnDiagnostics != 0) {
|
|
|
printf("SL_openSecureChannel - diagnostics demanded by the client\n");
|
|
|
- printf("SL_openSecureChannel - retrieving diagnostics not implemented!\n");
|
|
|
+ printf(
|
|
|
+ "SL_openSecureChannel - retrieving diagnostics not implemented!\n");
|
|
|
//TODO fill with demanded information part 4, 7.8 - Table 123
|
|
|
- serviceDiagnostics.encodingMask = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- serviceDiagnostics.encodingMask = 0;
|
|
|
+ r->responseHeader->serviceDiagnostics->encodingMask = 0;
|
|
|
+ } else {
|
|
|
+ r->responseHeader->serviceDiagnostics->encodingMask = 0;
|
|
|
}
|
|
|
/*--------------type ----------------------*/
|
|
|
|
|
@@ -164,103 +161,36 @@ UA_Int32 SL_openSecureChannel(UA_connection *connection,
|
|
|
responseType.namespace = 0;
|
|
|
|
|
|
/*--------------responseHeader-------------*/
|
|
|
-
|
|
|
- /* Res-1) ResponseHeader responseHeader
|
|
|
- * timestamp UtcTime
|
|
|
- * requestHandle IntegerId
|
|
|
- * serviceResult StatusCode
|
|
|
- * serviceDiagnostics DiagnosticInfo
|
|
|
- * stringTable[] String
|
|
|
- * addtionalHeader Extensible Parameter
|
|
|
- */
|
|
|
- //current time
|
|
|
-
|
|
|
- responseHeader.timestamp = UA_DateTime_now();
|
|
|
- //request Handle which client sent
|
|
|
- responseHeader.requestHandle = requestHeader->requestHandle;
|
|
|
- // StatusCode which informs client about quality of response
|
|
|
- responseHeader.serviceResult = serviceResult;
|
|
|
- //retrieve diagnosticInfo if client demands
|
|
|
- responseHeader.serviceDiagnostics = &serviceDiagnostics;
|
|
|
+ r->responseHeader->timestamp = UA_DateTime_now();
|
|
|
+ r->responseHeader->requestHandle = requestHeader->requestHandle;
|
|
|
+ r->responseHeader->serviceResult = serviceResult;
|
|
|
|
|
|
//text of fields defined in the serviceDiagnostics
|
|
|
- responseHeader.stringTableSize = 0;
|
|
|
- responseHeader.stringTable = NULL;
|
|
|
+ r->responseHeader->stringTableSize = 0;
|
|
|
+ r->responseHeader->stringTable = UA_NULL;
|
|
|
|
|
|
+ r->serverProtocolVersion =
|
|
|
+ connection->transportLayer.localConf.protocolVersion;
|
|
|
|
|
|
- // no additional header
|
|
|
- additionalHeader.encoding = 0;
|
|
|
-
|
|
|
- additionalHeader.body.data = NULL;
|
|
|
- additionalHeader.body.length = 0;
|
|
|
-
|
|
|
- additionalHeader.typeId.encodingByte = 0;
|
|
|
- additionalHeader.typeId.namespace = 0;
|
|
|
- additionalHeader.typeId.identifier.numeric = 0;
|
|
|
-
|
|
|
- responseHeader.additionalHeader = &additionalHeader;
|
|
|
- printf("SL_openSecureChannel - built response header\n");
|
|
|
-
|
|
|
- //calculate the size
|
|
|
- sizeRespHeader = UA_ResponseHeader_calcSize(&responseHeader);
|
|
|
- printf("SL_openSecureChannel - size response header =%d\n",sizeRespHeader);
|
|
|
- /*--------------responseMessage-------------*/
|
|
|
- /* Res-2) UInt32 ServerProtocolVersion
|
|
|
- * Res-3) SecurityToken channelSecurityToken
|
|
|
- * Res-5) ByteString ServerNonce
|
|
|
- */
|
|
|
- serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
|
|
|
-
|
|
|
- securityToken.channelId = connection->secureLayer.securityToken.secureChannelId;
|
|
|
- securityToken.tokenId = connection->secureLayer.securityToken.tokenId;
|
|
|
- securityToken.createdAt = UA_DateTime_now();
|
|
|
- securityToken.revisedLifetime = connection->secureLayer.securityToken.revisedLifetime;
|
|
|
-
|
|
|
- serverNonce.length = connection->secureLayer.localNonce.length;
|
|
|
- serverNonce.data = connection->secureLayer.localNonce.data;
|
|
|
-
|
|
|
- // ProtocolVersion + SecurityToken + ServerNonce
|
|
|
- sizeRespMessage = sizeof(UA_UInt32) +
|
|
|
- UA_ChannelSecurityToken_calcSize(&securityToken) +
|
|
|
- UA_ByteString_calcSize(&serverNonce);
|
|
|
- printf("SL_openSecureChannel - size of response message=%d\n",sizeRespMessage);
|
|
|
-
|
|
|
- //get memory for response
|
|
|
- sizeResponseType = UA_NodeId_calcSize(&responseType);
|
|
|
- printf("SL_openSecureChannel - size response type =%d\n",sizeResponseType);
|
|
|
+ r->securityToken->channelId =
|
|
|
+ connection->secureLayer.securityToken.secureChannelId;
|
|
|
+ r->securityToken->tokenId = connection->secureLayer.securityToken.tokenId;
|
|
|
+ r->securityToken->createdAt = UA_DateTime_now();
|
|
|
+ r->securityToken->revisedLifetime =
|
|
|
+ connection->secureLayer.securityToken.revisedLifetime;
|
|
|
|
|
|
- response.length = sizeResponseType + sizeRespHeader + sizeRespMessage;
|
|
|
+ UA_ByteString_copy(&(connection->secureLayer.localNonce), &(r->serverNonce));
|
|
|
|
|
|
//get memory for response
|
|
|
+ response.length = UA_NodeId_calcSize(&responseType) + UA_OpenSecureChannelResponse_calcSize(r);
|
|
|
UA_alloc((void*)&(response.data), response.length);
|
|
|
pos = 0;
|
|
|
- //encode responseType (NodeId)
|
|
|
- UA_NodeId_printf("SL_openSecureChannel - TypeId =",&responseType);
|
|
|
-
|
|
|
UA_NodeId_encode(&responseType, &pos, response.data);
|
|
|
+ UA_OpenSecureChannelResponse_encode(r, &pos, response.data);
|
|
|
|
|
|
- //encode header
|
|
|
- printf("SL_openSecureChannel - encoding response header \n");
|
|
|
-
|
|
|
- UA_ResponseHeader_encode(&responseHeader, &pos, response.data);
|
|
|
- printf("SL_openSecureChannel - response header encoded \n");
|
|
|
-
|
|
|
- //encode message
|
|
|
- printf("SL_openSecureChannel - serverProtocolVersion = %d \n",serverProtocolVersion);
|
|
|
- UA_UInt32_encode(&serverProtocolVersion, &pos,response.data);
|
|
|
-
|
|
|
- UA_ChannelSecurityToken_encode(&securityToken,&pos,response.data);
|
|
|
-
|
|
|
- UA_ByteString_encode(&serverNonce, &pos,response.data);
|
|
|
-
|
|
|
- printf("SL_openSecureChannel - response.length = %d \n",response.length);
|
|
|
-
|
|
|
- printf("-----> reserved: %i\n", response.length);
|
|
|
- printf("-----> encoded: %i\n", pos);
|
|
|
-
|
|
|
- //449 = openSecureChannelResponse
|
|
|
SL_send(connection, &response, 449);
|
|
|
UA_ByteString_deleteMembers(&response);
|
|
|
+ UA_OpenSecureChannelResponse_delete(r);
|
|
|
|
|
|
return UA_SUCCESS;
|
|
|
}
|
|
@@ -283,196 +213,238 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
|
|
|
UA_NodeId serviceRequestType;
|
|
|
|
|
|
// Every Message starts with a NodeID which names the serviceRequestType
|
|
|
- UA_NodeId_decode(message.data, &pos,
|
|
|
- &serviceRequestType);
|
|
|
+ UA_NodeId_decode(message.data, &pos, &serviceRequestType);
|
|
|
UA_NodeId_printf("SL_processMessage - serviceRequestType=",
|
|
|
&serviceRequestType);
|
|
|
|
|
|
- if (serviceRequestType.encodingByte == UA_NODEIDTYPE_FOURBYTE
|
|
|
- && serviceRequestType.identifier.numeric == 446) {
|
|
|
- /* OpenSecureChannelService, defined in 62541-6 §6.4.4, Table 34.
|
|
|
- * Note that part 6 adds ClientProtocolVersion and ServerProtocolVersion
|
|
|
- * to the definition in part 4 */
|
|
|
- // Req-1) RequestHeader requestHeader
|
|
|
- UA_RequestHeader requestHeader;
|
|
|
- // Req-2) UInt32 ClientProtocolVersion
|
|
|
- UA_UInt32 clientProtocolVersion;
|
|
|
- // Req-3) Enum SecurityTokenRequestType requestType
|
|
|
- UA_Int32 requestType;
|
|
|
- // Req-4) Enum MessageSecurityMode SecurityMode
|
|
|
- UA_Int32 securityMode;
|
|
|
- // Req-5) ByteString ClientNonce
|
|
|
- UA_ByteString clientNonce = {0, NULL};
|
|
|
- // Req-6) Int32 RequestLifetime
|
|
|
- UA_Int32 requestedLifetime;
|
|
|
-
|
|
|
- UA_ByteString_printx("SL_processMessage - message=", &message);
|
|
|
- // Req-1) RequestHeader requestHeader
|
|
|
- UA_RequestHeader_decode(message.data, &pos, &requestHeader);
|
|
|
- UA_String_printf("SL_processMessage - requestHeader.auditEntryId=",
|
|
|
- &(requestHeader.auditEntryId));
|
|
|
- UA_NodeId_printf(
|
|
|
- "SL_processMessage - requestHeader.authenticationToken=",
|
|
|
- &(requestHeader.authenticationToken));
|
|
|
-
|
|
|
- // Req-2) UInt32 ClientProtocolVersion
|
|
|
- UA_UInt32_decode(message.data, &pos,
|
|
|
- &clientProtocolVersion);
|
|
|
- printf("SL_processMessage - clientProtocolVersion=%d\n",
|
|
|
- clientProtocolVersion);
|
|
|
-
|
|
|
- if (clientProtocolVersion
|
|
|
- != connection->transportLayer.remoteConf.protocolVersion) {
|
|
|
- printf("SL_processMessage - error protocol version \n");
|
|
|
- //TODO error protocol version
|
|
|
- //TODO ERROR_Bad_ProtocolVersionUnsupported
|
|
|
-
|
|
|
+ if (serviceRequestType.namespace == 0) {
|
|
|
+ // FIXME: quick hack to map DataType to Object
|
|
|
+ switch (serviceRequestType.identifier.numeric) {
|
|
|
+ case 452: //
|
|
|
+ serviceRequestType.identifier.numeric =
|
|
|
+ UA_CLOSESECURECHANNELREQUEST_NS0;
|
|
|
+ break;
|
|
|
+ case 446: //
|
|
|
+ serviceRequestType.identifier.numeric =
|
|
|
+ UA_OPENSECURECHANNELREQUEST_NS0;
|
|
|
+ break;
|
|
|
+ case 428: //
|
|
|
+ serviceRequestType.identifier.numeric = UA_GETENDPOINTSREQUEST_NS0;
|
|
|
+ break;
|
|
|
+ case 461: //
|
|
|
+ serviceRequestType.identifier.numeric = UA_CREATESESSIONREQUEST_NS0;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- // Req-3) SecurityTokenRequestType requestType
|
|
|
- UA_Int32_decode(message.data, &pos, &requestType);
|
|
|
- printf("SL_processMessage - requestType=%d\n", requestType);
|
|
|
- switch (requestType) {
|
|
|
- case UA_SECURITYTOKEN_ISSUE:
|
|
|
- if (connection->secureLayer.connectionState
|
|
|
- == connectionState_ESTABLISHED) {
|
|
|
- printf("SL_processMessage - multiply security token request");
|
|
|
- //TODO return ERROR
|
|
|
- return UA_ERROR;
|
|
|
- }
|
|
|
+ UA_Int32 namespace_index = UA_toIndex(
|
|
|
+ serviceRequestType.identifier.numeric);
|
|
|
+ if (namespace_index == -1) {
|
|
|
printf(
|
|
|
- "SL_processMessage - TODO: create new token for a new SecureChannel\n");
|
|
|
- // SL_createNewToken(connection);
|
|
|
- break;
|
|
|
- case UA_SECURITYTOKEN_RENEW:
|
|
|
- if (connection->secureLayer.connectionState
|
|
|
- == connectionState_CLOSED) {
|
|
|
- printf(
|
|
|
- "SL_processMessage - renew token request received, but no secureChannel was established before");
|
|
|
- //TODO return ERROR
|
|
|
- return UA_ERROR;
|
|
|
+ "SL_processMessage - unknown request, namespace=%d, request=%d\n",
|
|
|
+ serviceRequestType.namespace,
|
|
|
+ serviceRequestType.identifier.numeric);
|
|
|
+ retval = UA_ERROR;
|
|
|
+ } else {
|
|
|
+ // decode message
|
|
|
+ void * obj;
|
|
|
+ UA_alloc(&obj, UA_[namespace_index].calcSize(UA_NULL));
|
|
|
+ UA_[namespace_index].decode(message.data, &pos, obj);
|
|
|
+
|
|
|
+ // FXIME: we need a more clever response/request architecture
|
|
|
+ switch (serviceRequestType.identifier.numeric) {
|
|
|
+ case UA_GETENDPOINTSREQUEST_NS0: {
|
|
|
+ puts("UA_GETENDPOINTSREQUEST");
|
|
|
+
|
|
|
+ UA_GetEndpointsRequest* p = (UA_GetEndpointsRequest*) obj;
|
|
|
+ UA_NodeId responseType;
|
|
|
+ UA_GetEndpointsResponse* r;
|
|
|
+
|
|
|
+ UA_String_printx("endpointUrl=", &(p->endpointUrl));
|
|
|
+ UA_GetEndpointsResponse_new(&r);
|
|
|
+ UA_ResponseHeader_new(&(r->responseHeader));
|
|
|
+ r->responseHeader->requestHandle =
|
|
|
+ p->requestHeader->requestHandle;
|
|
|
+ r->responseHeader->serviceResult = SC_Good;
|
|
|
+ r->responseHeader->stringTableSize = 0;
|
|
|
+ r->responseHeader->timestamp = UA_DateTime_now();
|
|
|
+ UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
|
|
|
+ UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
|
|
|
+
|
|
|
+ // TODO: Arrays need to be redesigned, this is crap
|
|
|
+ r->endpointsSize = 1;
|
|
|
+ UA_alloc((void**) &(r->endpoints), sizeof(void*));
|
|
|
+ UA_EndpointDescription *epd;
|
|
|
+ UA_EndpointDescription_new(&epd);
|
|
|
+ *(r->endpoints) = epd;
|
|
|
+
|
|
|
+ // FIXME: this memory gets lost
|
|
|
+ UA_String_copycstring("tcp.opc://localhost:16664/",
|
|
|
+ &(r->endpoints[0]->endpointUrl));
|
|
|
+ // FIXME: this memory gets lost
|
|
|
+ UA_ApplicationDescription_new(&(r->endpoints[0]->server));
|
|
|
+ // FIXME: This should be a feature of the application
|
|
|
+ UA_String_copycstring("http://open62541.info/applications/4711",
|
|
|
+ &(r->endpoints[0]->server->applicationUri));
|
|
|
+ UA_String_copycstring("http://open62541.info/product/release",
|
|
|
+ &(r->endpoints[0]->server->productUri));
|
|
|
+ // FIXME: This should be a feature of the application
|
|
|
+ UA_LocalizedText_copycstring("The open62541 application",
|
|
|
+ &(r->endpoints[0]->server->applicationName));
|
|
|
+ // FIXME: This should be a feature of the application and an enum
|
|
|
+ r->endpoints[0]->server->applicationType = 0; // Server
|
|
|
+ // all the other strings are empty by initialization
|
|
|
+
|
|
|
+ // Now let's build the response
|
|
|
+ UA_ByteString response;
|
|
|
+ responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
|
|
|
+ responseType.namespace = 0;
|
|
|
+ responseType.identifier.numeric = 431; // GetEndpointsResponse_Encoding_DefaultBinary
|
|
|
+
|
|
|
+ response.length = UA_NodeId_calcSize(&responseType)
|
|
|
+ + UA_GetEndpointsResponse_calcSize(r);
|
|
|
+ UA_alloc((void**)&(response.data), response.length);
|
|
|
+ pos = 0;
|
|
|
+
|
|
|
+ UA_NodeId_encode(&responseType, &pos, response.data);
|
|
|
+ UA_GetEndpointsResponse_encode(r, &pos, response.data);
|
|
|
+
|
|
|
+ SL_send(connection, &response, 431);
|
|
|
+
|
|
|
+ UA_ByteString_deleteMembers(&response);
|
|
|
+ UA_GetEndpointsResponse_delete(r);
|
|
|
+ UA_GetEndpointsRequest_delete(p);
|
|
|
+
|
|
|
+ retval = UA_SUCCESS;
|
|
|
}
|
|
|
- printf("TODO: create new token for an existing SecureChannel\n");
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
|
|
|
- // Req-4) MessageSecurityMode SecurityMode
|
|
|
- UA_Int32_decode(message.data, &pos, &securityMode);
|
|
|
- printf("SL_processMessage - securityMode=%d\n", securityMode);
|
|
|
- switch (securityMode) {
|
|
|
- case UA_SECURITYMODE_INVALID:
|
|
|
- connection->secureLayer.remoteNonce.data = NULL;
|
|
|
- connection->secureLayer.remoteNonce.length = -1;
|
|
|
- printf("SL_processMessage - client demands no security \n");
|
|
|
- break;
|
|
|
+ case UA_CREATESESSIONREQUEST_NS0: {
|
|
|
+ puts("UA_CREATESESSIONREQUEST");
|
|
|
|
|
|
- case UA_SECURITYMODE_SIGN:
|
|
|
- printf("SL_processMessage - client demands signed \n");
|
|
|
- //TODO check if senderCertificate and ReceiverCertificateThumbprint are present
|
|
|
- break;
|
|
|
+ UA_CreateSessionRequest* p = (UA_CreateSessionRequest*) obj;
|
|
|
+ UA_NodeId responseType;
|
|
|
+ UA_CreateSessionResponse* r;
|
|
|
|
|
|
- case UA_SECURITYMODE_SIGNANDENCRYPT:
|
|
|
- printf("SL_processMessage - client demands signed & encrypted \n");
|
|
|
- //TODO check if senderCertificate and ReceiverCertificateThumbprint are present
|
|
|
- break;
|
|
|
- }
|
|
|
+ UA_CreateSessionResponse_new(&r);
|
|
|
+ // Header
|
|
|
+ UA_ResponseHeader_new(&(r->responseHeader));
|
|
|
+ r->responseHeader->requestHandle =
|
|
|
+ p->requestHeader->requestHandle;
|
|
|
+ r->responseHeader->serviceResult = SC_Good;
|
|
|
+ r->responseHeader->stringTableSize = 0;
|
|
|
+ r->responseHeader->timestamp = UA_DateTime_now();
|
|
|
+ UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
|
|
|
+ UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
|
|
|
|
|
|
- // Req-5) ByteString ClientNonce
|
|
|
- UA_ByteString_decode(message.data, &pos,
|
|
|
- &clientNonce);
|
|
|
- UA_ByteString_printf("SL_processMessage - clientNonce=", &clientNonce);
|
|
|
+ // FIXME: create session
|
|
|
|
|
|
- //deleteMembers is important since clientNonce is on stack
|
|
|
- UA_ByteString_deleteMembers(&clientNonce);
|
|
|
+ // Now let's build the response
|
|
|
+ UA_ByteString response;
|
|
|
+ responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
|
|
|
+ responseType.namespace = 0;
|
|
|
+ responseType.identifier.numeric = 464; // CreateSessionResponse_Encoding_DefaultBinary
|
|
|
|
|
|
- // Req-6) Int32 RequestLifetime
|
|
|
- UA_Int32_decode(message.data, &pos,
|
|
|
- &requestedLifetime);
|
|
|
- printf("SL_processMessage - requestedLifeTime=%d\n", requestedLifetime);
|
|
|
- //TODO process requestedLifetime
|
|
|
+ response.length = UA_NodeId_calcSize(&responseType)
|
|
|
+ + UA_CreateSessionResponse_calcSize(r);
|
|
|
+ UA_alloc((void**)&(response.data), response.length);
|
|
|
+ pos = 0;
|
|
|
|
|
|
- // 62541-4 §7.27 "The requestHandle given by the Client to the request."
|
|
|
- retval = SL_openSecureChannel(connection, &requestHeader, SC_Good);
|
|
|
- UA_RequestHeader_deleteMembers(&requestHeader);
|
|
|
- } else {
|
|
|
- if (serviceRequestType.namespace == 0) {
|
|
|
- // FIXME: quick hack
|
|
|
- switch (serviceRequestType.identifier.numeric) {
|
|
|
- case 428:
|
|
|
- serviceRequestType.identifier.numeric = 426;
|
|
|
+ UA_NodeId_encode(&responseType, &pos, response.data);
|
|
|
+ UA_CreateSessionResponse_encode(r, &pos, response.data);
|
|
|
+
|
|
|
+ SL_send(connection, &response, responseType.identifier.numeric);
|
|
|
+
|
|
|
+ UA_ByteString_deleteMembers(&response);
|
|
|
+ UA_CreateSessionResponse_delete(r);
|
|
|
+ UA_CreateSessionRequest_delete(p);
|
|
|
+
|
|
|
+ retval = UA_SUCCESS;
|
|
|
+ }
|
|
|
break;
|
|
|
+
|
|
|
+ case UA_CLOSESECURECHANNELREQUEST_NS0: {
|
|
|
+ puts("UA_CLOSESECURECHANNELREQUEST");
|
|
|
+
|
|
|
+ UA_CloseSecureChannelRequest* p =
|
|
|
+ (UA_CloseSecureChannelRequest*) obj;
|
|
|
+ // 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
|
|
|
+ connection->transportLayer.connectionState = connectionState_CLOSE;
|
|
|
+ retval = UA_SUCCESS;
|
|
|
}
|
|
|
- UA_Int32 namespace_index = UA_toIndex(serviceRequestType.identifier.numeric);
|
|
|
- if (namespace_index == -1) {
|
|
|
- printf("SL_processMessage - unknown request, namespace=%d, request=%d\n", serviceRequestType.namespace, serviceRequestType.identifier.numeric);
|
|
|
- retval = UA_ERROR;
|
|
|
- } else {
|
|
|
- void * obj;
|
|
|
- UA_alloc(&obj,UA_[namespace_index].calcSize(UA_NULL));
|
|
|
- UA_[namespace_index].decode(message.data,&pos,obj);
|
|
|
-
|
|
|
- // FXIME: we need a more clever response/request architecture
|
|
|
- if (serviceRequestType.identifier.numeric == 426 ) {
|
|
|
- UA_GetEndpointsRequest *p = (UA_GetEndpointsRequest*) obj;
|
|
|
- UA_GetEndpointsResponse *r;
|
|
|
- UA_NodeId responseType;
|
|
|
-
|
|
|
- UA_String_printx("endpointUrl=",&(p->endpointUrl));
|
|
|
- UA_GetEndpointsResponse_new(&r);
|
|
|
- UA_ResponseHeader_new(&(r->responseHeader));
|
|
|
- r->responseHeader->requestHandle = p->requestHeader->requestHandle;
|
|
|
- r->responseHeader->serviceResult = SC_Good;
|
|
|
- r->responseHeader->stringTableSize = 0;
|
|
|
- r->responseHeader->timestamp = UA_DateTime_now();
|
|
|
- UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
|
|
|
- UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
|
|
|
-
|
|
|
- // TODO: Arrays need to be redesigned, this is crap
|
|
|
- r->endpointsSize = 1;
|
|
|
- UA_alloc((void**) &(r->endpoints), sizeof(void*));
|
|
|
- UA_EndpointDescription *epd;
|
|
|
- UA_EndpointDescription_new(&epd);
|
|
|
- *(r->endpoints) = epd;
|
|
|
-
|
|
|
- // FIXME: this memory gets lost
|
|
|
- UA_String_copycstring("http://localhost:16664/",&(r->endpoints[0]->endpointUrl));
|
|
|
- // FIXME: this memory gets lost
|
|
|
- UA_ApplicationDescription_new(&(r->endpoints[0]->server));
|
|
|
- // FIXME: This should be a feature of the application
|
|
|
- UA_String_copycstring("open62541.com/applications/4711",&(r->endpoints[0]->server->applicationUri));
|
|
|
- UA_String_copycstring("open62541.com/product/release",&(r->endpoints[0]->server->productUri));
|
|
|
- // FIXME: This should be a feature of the application
|
|
|
- UA_LocalizedText_copycstring("The open62541 application",&(r->endpoints[0]->server->applicationName));
|
|
|
- // FIXME: This should be a feature of the application and an enum
|
|
|
- r->endpoints[0]->server->applicationType = 0; // Server
|
|
|
- // all the other strings are empty by initialization
|
|
|
-
|
|
|
- // Now let's build the response
|
|
|
- UA_ByteString response;
|
|
|
- responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
|
|
|
- responseType.namespace = 0;
|
|
|
- responseType.identifier.numeric = 431;
|
|
|
-
|
|
|
- response.length = UA_NodeId_calcSize(&responseType) + UA_GetEndpointsResponse_calcSize(r);
|
|
|
- UA_alloc((void**)&(response.data), response.length);
|
|
|
- pos = 0;
|
|
|
-
|
|
|
- UA_NodeId_encode(&responseType, &pos, response.data);
|
|
|
- UA_GetEndpointsResponse_encode(r, &pos, response.data);
|
|
|
-
|
|
|
- SL_send(connection, &response, 431);
|
|
|
-
|
|
|
- UA_ByteString_deleteMembers(&response);
|
|
|
- UA_GetEndpointsResponse_delete(r);
|
|
|
- UA_GetEndpointsRequest_delete(p);
|
|
|
-
|
|
|
- return UA_SUCCESS;
|
|
|
+ break;
|
|
|
+ case UA_OPENSECURECHANNELREQUEST_NS0: {
|
|
|
+ puts("UA_OPENSECURECHANNELREQUEST");
|
|
|
+
|
|
|
+ UA_OpenSecureChannelRequest* p =
|
|
|
+ (UA_OpenSecureChannelRequest*) obj;
|
|
|
+ UA_NodeId responseType;
|
|
|
+ UA_OpenSecureChannelResponse* r;
|
|
|
+
|
|
|
+ if (p->clientProtocolVersion
|
|
|
+ != connection->transportLayer.remoteConf.protocolVersion) {
|
|
|
+ printf("SL_processMessage - error protocol version \n");
|
|
|
+ //TODO error protocol version
|
|
|
+ //TODO ERROR_Bad_ProtocolVersionUnsupported
|
|
|
+ }
|
|
|
+ switch (p->requestType) {
|
|
|
+ case UA_SECURITYTOKEN_ISSUE:
|
|
|
+ if (connection->secureLayer.connectionState
|
|
|
+ == connectionState_ESTABLISHED) {
|
|
|
+ printf("SL_processMessage - multiply security token request");
|
|
|
+ //TODO return ERROR
|
|
|
+ retval = UA_ERROR;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ printf(
|
|
|
+ "SL_processMessage - TODO: create new token for a new SecureChannel\n");
|
|
|
+ // SL_createNewToken(connection);
|
|
|
+ break;
|
|
|
+ case UA_SECURITYTOKEN_RENEW:
|
|
|
+ if (connection->secureLayer.connectionState
|
|
|
+ == connectionState_CLOSED) {
|
|
|
+ printf(
|
|
|
+ "SL_processMessage - renew token request received, but no secureChannel was established before");
|
|
|
+ //TODO return ERROR
|
|
|
+ retval = UA_ERROR;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ printf(
|
|
|
+ "TODO: create new token for an existing SecureChannel\n");
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ switch (p->securityMode) {
|
|
|
+ case UA_SECURITYMODE_INVALID:
|
|
|
+ connection->secureLayer.remoteNonce.data = NULL;
|
|
|
+ connection->secureLayer.remoteNonce.length = -1;
|
|
|
+ printf("SL_processMessage - client demands no security \n");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case UA_SECURITYMODE_SIGN:
|
|
|
+ printf("SL_processMessage - client demands signed \n");
|
|
|
+ //TODO check if senderCertificate and ReceiverCertificateThumbprint are present
|
|
|
+ break;
|
|
|
+
|
|
|
+ case UA_SECURITYMODE_SIGNANDENCRYPT:
|
|
|
+ printf(
|
|
|
+ "SL_processMessage - client demands signed & encrypted \n");
|
|
|
+ //TODO check if senderCertificate and ReceiverCertificateThumbprint are present
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ retval = SL_openSecureChannel(connection, p->requestHeader,
|
|
|
+ SC_Good);
|
|
|
+ UA_OpenSecureChannelRequest_delete(p);
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
- } else {
|
|
|
- printf("SL_processMessage - unknown request, namespace=%d, request=%d\n", serviceRequestType.namespace, serviceRequestType.identifier.numeric);
|
|
|
- retval = UA_ERROR;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ printf(
|
|
|
+ "SL_processMessage - unknown request, namespace=%d, request=%d\n",
|
|
|
+ serviceRequestType.namespace,
|
|
|
+ serviceRequestType.identifier.numeric);
|
|
|
+ retval = UA_ERROR;
|
|
|
}
|
|
|
return retval;
|
|
|
}
|
|
@@ -499,13 +471,15 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
|
|
|
printf("SL_receive - data received \n");
|
|
|
//packetType = TL_getPacketType(&secureChannelPacket, &pos);
|
|
|
|
|
|
- UA_SecureConversationMessageHeader_decode(secureChannelPacket.data, &pos, &secureConvHeader);
|
|
|
+ UA_SecureConversationMessageHeader_decode(secureChannelPacket.data,
|
|
|
+ &pos, &secureConvHeader);
|
|
|
|
|
|
switch (secureConvHeader.tcpMessageHeader->messageType) {
|
|
|
|
|
|
case UA_MESSAGETYPE_OPN: /* openSecureChannel Message received */
|
|
|
printf("SL_receive - process OPN\n");
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_decode(secureChannelPacket.data, &pos, &asymAlgSecHeader);
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_decode(
|
|
|
+ secureChannelPacket.data, &pos, &asymAlgSecHeader);
|
|
|
UA_ByteString_printf("SL_receive - AAS_Header.ReceiverThumbprint=",
|
|
|
&(asymAlgSecHeader.receiverCertificateThumbprint));
|
|
|
UA_ByteString_printf("SL_receive - AAS_Header.SecurityPolicyUri=",
|
|
@@ -513,20 +487,20 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
|
|
|
UA_ByteString_printf("SL_receive - AAS_Header.SenderCertificate=",
|
|
|
&(asymAlgSecHeader.senderCertificate));
|
|
|
if (secureConvHeader.secureChannelId != 0) {
|
|
|
- iTmp = UA_ByteString_compare(
|
|
|
- &(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
|
|
|
- &(asymAlgSecHeader.senderCertificate));
|
|
|
+ iTmp =
|
|
|
+ UA_ByteString_compare(
|
|
|
+ &(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
|
|
|
+ &(asymAlgSecHeader.senderCertificate));
|
|
|
if (iTmp != UA_EQUAL) {
|
|
|
printf("SL_receive - UA_ERROR_BadSecureChannelUnknown \n");
|
|
|
//TODO return UA_ERROR_BadSecureChannelUnknown
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ } else {
|
|
|
//TODO invalid securechannelId
|
|
|
}
|
|
|
|
|
|
- UA_SequenceHeader_decode(secureChannelPacket.data, &pos, &sequenceHeader);
|
|
|
+ UA_SequenceHeader_decode(secureChannelPacket.data, &pos,
|
|
|
+ &sequenceHeader);
|
|
|
printf("SL_receive - SequenceHeader.RequestId=%d\n",
|
|
|
sequenceHeader.requestId);
|
|
|
printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
|
|
@@ -539,46 +513,45 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
|
|
|
|
|
|
message.data = &secureChannelPacket.data[pos];
|
|
|
message.length = secureChannelPacket.length - pos;
|
|
|
- UA_ByteString_printx("SL_receive - message=",&message);
|
|
|
+ UA_ByteString_printx("SL_receive - message=", &message);
|
|
|
|
|
|
SL_processMessage(connection, message);
|
|
|
// Clean up
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymAlgSecHeader);
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(
|
|
|
+ &asymAlgSecHeader);
|
|
|
|
|
|
break;
|
|
|
- case UA_MESSAGETYPE_MSG: /* secure Channel Message received */
|
|
|
- printf("SL_receive - process MSG\n");
|
|
|
+ case UA_MESSAGETYPE_MSG:
|
|
|
+ case UA_MESSAGETYPE_CLO:
|
|
|
// FIXME: check connection state
|
|
|
// if (connection->secureLayer.connectionState
|
|
|
// == connectionState_ESTABLISHED) {
|
|
|
- if (secureConvHeader.secureChannelId
|
|
|
- == connection->secureLayer.securityToken.secureChannelId) {
|
|
|
- UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
|
|
|
-
|
|
|
- //FIXME: we assume SAS, need to check if AAS or SAS
|
|
|
- UA_SymmetricAlgorithmSecurityHeader_decode(secureChannelPacket.data, &pos, &symAlgSecHeader);
|
|
|
-
|
|
|
- // decode sequenceHeader and remember
|
|
|
- UA_SequenceHeader_decode(secureChannelPacket.data, &pos, &sequenceHeader);
|
|
|
- printf("SL_receive - SequenceHeader.RequestId=%d\n",sequenceHeader.requestId);
|
|
|
- printf("SL_receive - SequenceHeader.SequenceNr=%d\n",sequenceHeader.sequenceNumber);
|
|
|
- connection->secureLayer.requestId = sequenceHeader.requestId;
|
|
|
- connection->secureLayer.sequenceNumber = sequenceHeader.sequenceNumber;
|
|
|
- // process message
|
|
|
- message.data = &secureChannelPacket.data[pos];
|
|
|
- message.length = secureChannelPacket.length - pos;
|
|
|
- UA_ByteString_printx("SL_receive - message=",&message);
|
|
|
- SL_processMessage(connection, message);
|
|
|
- } else {
|
|
|
- //TODO generate ERROR_Bad_SecureChannelUnkown
|
|
|
- }
|
|
|
-// } // check connection state
|
|
|
-
|
|
|
- break;
|
|
|
- case UA_MESSAGETYPE_CLO: /* closeSecureChannel Message received */
|
|
|
- if (SL_check(connection, secureChannelPacket) == UA_NO_ERROR) {
|
|
|
-
|
|
|
+ if (secureConvHeader.secureChannelId
|
|
|
+ == connection->secureLayer.securityToken.secureChannelId) {
|
|
|
+ UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
|
|
|
+
|
|
|
+ //FIXME: we assume SAS, need to check if AAS or SAS
|
|
|
+ UA_SymmetricAlgorithmSecurityHeader_decode(
|
|
|
+ secureChannelPacket.data, &pos, &symAlgSecHeader);
|
|
|
+
|
|
|
+ // decode sequenceHeader and remember
|
|
|
+ UA_SequenceHeader_decode(secureChannelPacket.data, &pos,
|
|
|
+ &sequenceHeader);
|
|
|
+ printf("SL_receive - SequenceHeader.RequestId=%d\n",
|
|
|
+ sequenceHeader.requestId);
|
|
|
+ printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
|
|
|
+ sequenceHeader.sequenceNumber);
|
|
|
+ connection->secureLayer.requestId = sequenceHeader.requestId;
|
|
|
+ connection->secureLayer.sequenceNumber =
|
|
|
+ sequenceHeader.sequenceNumber;
|
|
|
+ // process message
|
|
|
+ message.data = &secureChannelPacket.data[pos];
|
|
|
+ message.length = secureChannelPacket.length - pos;
|
|
|
+ SL_processMessage(connection, message);
|
|
|
+ } else {
|
|
|
+ //TODO generate ERROR_Bad_SecureChannelUnkown
|
|
|
}
|
|
|
+// } // check connection state
|
|
|
break;
|
|
|
}
|
|
|
// Clean up
|
|
@@ -588,5 +561,3 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|