Просмотр исходного кода

beta version of openSecureChannel response implemented

FlorianPalm лет назад: 11
Родитель
Сommit
5dee69370e

+ 6 - 1
examples/src/opcuaServer.c

@@ -61,14 +61,18 @@ void server_init()
 void server_run()
 {
 	UA_connection connection;
+
 	UA_ByteString slMessage;
-	TL_initConnectionObject(&connection);
+
 	char optval;
 	int sockfd, newsockfd, portno, clilen;
 	char buffer[BUFFER_SIZE];
 	struct sockaddr_in serv_addr, cli_addr;
 	int  n;
 
+	TL_initConnectionObject(&connection);
+	SL_initConnectionObject(&connection);
+
 	/* First call to socket() function */
 	sockfd = socket(AF_INET, SOCK_STREAM, 0);
 	if (sockfd < 0)
@@ -111,6 +115,7 @@ void server_run()
 		perror("ERROR on accept");
 		exit(1);
 	}
+
 	printf("One connection accepted");
 	while(1)
 	{

+ 0 - 8
src/Makefile.am

@@ -42,14 +42,6 @@ libopen62541_la_SOURCES = opcua_builtInDatatypes.c\
 #__top_builddir__bin_libOpen62541_out_SOURCES = opcuaServer.c
 #libOpen62541_la_LIBADD = ../lib/libOpen62541.la		  										
 
-if DEBUG
-AM_CFLAGS = -g -O0
-AM_CXXFLAGS = -g -O0
-else
-AM_CFLAGS = -O2
-AM_CXXFLAGS = -O2
-endif
-
 .PHONY: convenience-link clean-convenience-link
 
 convenience-link: $(lib_LTLIBRARIES)

+ 10 - 4
src/opcua_binaryEncDec.c

@@ -95,6 +95,7 @@ Int32 encoder_encodeBuiltInDatatype(void *data, Int32 type, Int32 *pos,
 	return UA_NO_ERROR;
 }
 
+
 Int32 decoder_decodeBuiltInDatatype(char const * srcBuf, Int32 type, Int32 *pos,
 		void *dstStructure) {
 	Boolean tmp;
@@ -525,6 +526,7 @@ Int32 encoder_encodeBuiltInDatatypeArray(void *data, Int32 size, Int32 type,
 			break;
 		}
 	}
+	*/
 	return UA_NO_ERROR;
 }
 
@@ -846,6 +848,7 @@ Int32 encodeUANodeId(UA_NodeId *srcNodeId, Int32 *pos, char *buf) {
 }
 Int32 nodeId_calcSize(UA_NodeId *nodeId) {
 	Int32 length = 0;
+	printf("nodeId_calcSize - nodeId.EncodingByte = %d \n",nodeId->EncodingByte);
 	switch (nodeId->EncodingByte) {
 	case NIEVT_TWO_BYTE:
 		length += 2 * sizeof(Byte);
@@ -871,6 +874,7 @@ Int32 nodeId_calcSize(UA_NodeId *nodeId) {
 	default:
 		break;
 	}
+	printf("nodeId_calcSize - nodeId length = %d \n",length);
 	return length;
 }
 /**
@@ -1167,7 +1171,7 @@ Int32 encodeVariant(UA_Variant *variant, Int32 *pos, char *dstBuf) {
 				pos, dstBuf);
 		if (variant->ArrayLength > 0) {
 			//encode array as given by variant type
-			encode_builtInDatatypeArray((void*) variant->Value,
+			encoder_encodeBuiltInDatatypeArray((void*) variant->Value,
 					variant->ArrayLength, (variant->EncodingMask & 31), pos,
 					dstBuf);
 		}
@@ -1413,6 +1417,7 @@ Int32 diagnosticInfo_calcSize(UA_DiagnosticInfo *diagnosticInfo) {
 	Byte mask;
 	Int32 j = 0;
 	mask = 0;
+
 	//puts("diagnosticInfo called");
 	//printf("with this mask %u", diagnosticInfo->EncodingMask);
 	for (mask = 1; mask <= 0x40; mask *= 2) {
@@ -1521,7 +1526,7 @@ Int32 extensionObject_calcSize(UA_ExtensionObject *extensionObject) {
 Int32 responseHeader_calcSize(UA_AD_ResponseHeader *responseHeader) {
 	Int32 minimumLength = 20; // summation of all simple types
 	Int32 i, length;
-	length += minimumLength;
+	length = minimumLength;
 
 	for (i = 0; i < responseHeader->noOfStringTable; i++) {
 		length += responseHeader->stringTable[i].Length;
@@ -1529,8 +1534,9 @@ Int32 responseHeader_calcSize(UA_AD_ResponseHeader *responseHeader) {
 	}
 
 	length += diagnosticInfo_calcSize(responseHeader->serviceDiagnostics);
-	//ToDo
-	length += extensionObject_calcSize(&(responseHeader->additionalHeader));
+
+
+	length += extensionObject_calcSize(responseHeader->additionalHeader);
 
 	return length;
 }

+ 12 - 0
src/opcua_builtInDatatypes.c

@@ -51,6 +51,18 @@ void UA_ByteString_printx(char* label, UA_ByteString* string) {
 	}
 	printf("}}\n");
 }
+void UA_ByteString_printx_hex(char* label, UA_ByteString* string) {
+	int i;
+	printf("%s {Length=%d, Data=", label, string->Length);
+	if (string->Length > 0) {
+		for (i = 0; i < string->Length; i++) {
+			printf("%c%x", i == 0 ? '{' : ',', (string->Data)[i]);
+		}
+	} else {
+		printf("{");
+	}
+	printf("}}\n");
+}
 
 void UA_NodeId_printf(char* label, UA_NodeId* node) {
 	printf("%s {EncodingByte=%d, Namespace=%d, ", label,

+ 12 - 1
src/opcua_connectionHelper.h

@@ -52,14 +52,25 @@ struct TL_connection
 	TL_buffer localConf;
 	UA_String endpointURL;
 };
+typedef struct
+{
+	UA_ByteString SecurityPolicyUri;
+	UA_ByteString SenderCertificate;
+	UA_ByteString ReceiverCertificateThumbprint;
+
+}AsymmetricAlgSecuritySettings;
+
 
 
 struct SL_connection
 {
-
+	AsymmetricAlgSecuritySettings remoteAsymAlgSettings;
+	AsymmetricAlgSecuritySettings localtAsymAlgSettings;
+/*
 	UA_ByteString SecurityPolicyUri;
 	UA_ByteString SenderCertificate;
 	UA_ByteString ReceiverCertificateThumbprint;
+*/
 	UInt32 sequenceNumber;
 	UInt32 requestType;
 	UA_String secureChannelId;

+ 194 - 39
src/opcua_secureChannelLayer.c

@@ -8,55 +8,170 @@
 #include <stdio.h>
 #include "opcua_time.h"
 
+#define SIZE_SECURECHANNEL_HEADER 12
+#define SIZE_SEQHEADER_HEADER 8
+
+
+/*
+ * inits a connection object for secure channel layer
+ */
+Int32 SL_initConnectionObject(UA_connection *connection)
+{
+
+	//TODO: fill with valid information
+	connection->secureLayer.localtAsymAlgSettings.ReceiverCertificateThumbprint.Data = NULL;
+	connection->secureLayer.localtAsymAlgSettings.ReceiverCertificateThumbprint.Length = 0;
+
+	connection->secureLayer.localtAsymAlgSettings.SecurityPolicyUri.Data = "http://opcfoundation.org/UA/SecurityPolicy#None";
+	connection->secureLayer.localtAsymAlgSettings.SecurityPolicyUri.Length = 47;
+
+	connection->secureLayer.localtAsymAlgSettings.SenderCertificate.Data = NULL;
+	connection->secureLayer.localtAsymAlgSettings.SenderCertificate.Length = 0;
+
+	connection->secureLayer.clientNonce.Data = NULL;
+	connection->secureLayer.clientNonce.Length = 0;
+
+	connection->secureLayer.connectionState = connectionState_CLOSED;
+
+	connection->secureLayer.requestId = 0;
+
+	connection->secureLayer.requestType = 0;
+
+	connection->secureLayer.secureChannelId.Data = NULL;
+	connection->secureLayer.secureChannelId.Length = 0;
+
+	connection->secureLayer.securityMode = securityMode_INVALID;
+
+	connection->secureLayer.sequenceNumber = 1;
+
+	return UA_NO_ERROR;
+}
+
 Int32 SL_send(UA_connection *connection, UA_ByteString responseMessage, Int32 type)
 {
 	UInt32 sequenceNumber;
 	UInt32 requestId;
-	//TODO: fill with valid information
-	char securityPolicy[] = "http://opcfoundation.org/UA/SecurityPolicy#None";
-
+	Int32 pos;
+	Int32 sizeAsymAlgHeader;
+	UA_ByteString responsePacket;
+	Int32 packetSize;
+	Int32 sizePadding;
+	Int32 sizeSignature;
+
+
+	sizeAsymAlgHeader = 3 * sizeof(UInt32) +
+			connection->secureLayer.localtAsymAlgSettings.SecurityPolicyUri.Length +
+			connection->secureLayer.localtAsymAlgSettings.SenderCertificate.Length +
+			connection->secureLayer.localtAsymAlgSettings.ReceiverCertificateThumbprint.Length;
+	pos = 0;
 	//sequence header
 	sequenceNumber = connection->secureLayer.sequenceNumber;
-	requestId = connection->secureLayer.requestId;
-
+    requestId = connection->secureLayer.requestId;
 
 
 	if(type == 449) //openSecureChannelResponse -> asymmetric algorithm
 	{
-		//TODO add Asymmetric Security Header
-	}
-	else
-	{
-		//TODO add Symmetric Security
+		//TODO fill with valid sizes
+		sizePadding = 0;
+		sizeSignature = 0;
+
+		//TODO: size calculation need
+		packetSize = SIZE_SECURECHANNEL_HEADER +
+				SIZE_SEQHEADER_HEADER +
+				sizeAsymAlgHeader +
+				responseMessage.Length +
+				sizePadding +
+				sizeSignature;
+
+		//get memory for response
+		responsePacket.Data = (char*)opcua_malloc(packetSize);
+
+		responsePacket.Length = packetSize;
+
+		/*---encode Secure Conversation Message Header ---*/
+		//encode MessageType - OPN message
+		responsePacket.Data[0] = 'O';
+		responsePacket.Data[1] = 'P';
+		responsePacket.Data[2] = 'N';
+		pos += 3;
+		//encode Chunk Type - set to final
+		responsePacket.Data[3] = 'F';
+		pos += 1;
+		encoder_encodeBuiltInDatatype(&packetSize,INT32,&pos,responsePacket.Data);
+		encoder_encodeBuiltInDatatype(&(connection->secureLayer.securityToken.secureChannelId),
+				INT32,&pos,responsePacket.Data);
+
+		/*---encode Asymmetric Algorithm Header ---*/
+		encoder_encodeBuiltInDatatype(&(connection->secureLayer.localtAsymAlgSettings.SecurityPolicyUri),
+						BYTE_STRING,&pos,responsePacket.Data);
+		encoder_encodeBuiltInDatatype(&(connection->secureLayer.localtAsymAlgSettings.SenderCertificate),
+						BYTE_STRING,&pos,responsePacket.Data );
+		encoder_encodeBuiltInDatatype(&(connection->secureLayer.localtAsymAlgSettings.ReceiverCertificateThumbprint),
+						BYTE_STRING,&pos,responsePacket.Data );
 	}
+
+
+
+
+	/*---encode Sequence Header ---*/
+	encoder_encodeBuiltInDatatype(&sequenceNumber,UINT32,&pos,responsePacket.Data);
+	encoder_encodeBuiltInDatatype(&requestId,UINT32,&pos,responsePacket.Data);
+
+	/*---add encoded Message ---*/
+	memcpy(&(responsePacket.Data[pos]), responseMessage.Data, responseMessage.Length);
+
+	/* sign Data*/
+
+	/* encrypt Data */
+
+	/* send Data */
+	TL_send(connection,&responsePacket);
+
+
 	return UA_NO_ERROR;
 }
+
 /*
  * opens a secure channel
  */
-Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, UA_StatusCode serviceResult, UA_AD_DiagnosticInfo *serviceDiagnostics)
+Int32 SL_openSecureChannel(UA_connection *connection,
+		UA_AD_RequestHeader *requestHeader,
+		UA_StatusCode serviceResult)
 {
-
-
-
 	UA_AD_ResponseHeader responseHeader;
 	SL_ChannelSecurityToken securityToken;
 	UA_ByteString serverNonce;
 	UA_NodeId responseType;
+	UA_ExtensionObject additionalHeader;
 	//sizes for memory allocation
 	Int32 sizeResponse;
 	Int32 sizeRespHeader;
+	Int32 sizeResponseType;
 	Int32 sizeRespMessage;
 	Int32 sizeSecurityToken;
 	UA_ByteString response;
 	UInt32 serverProtocolVersion;
 	Int32 *pos;
+	UA_DiagnosticInfo serviceDiagnostics;
 
+	if(requestHeader->returnDiagnostics != 0)
+	{
+		printf("SL_openSecureChannel - diagnostics demanded by the client\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;
+	}
 	/*--------------type ----------------------*/
+
 	//Four Bytes Encoding
 	responseType.EncodingByte = NIEVT_FOUR_BYTE;
 	//openSecureChannelResponse = 449
 	responseType.Identifier.Numeric = 449;
+	responseType.Namespace = 0;
 
 	/*--------------responseHeader-------------*/
 
@@ -69,13 +184,14 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	 * 		addtionalHeader Extensible Parameter
 	 */
 	//current time
-	responseHeader.timestamp = opcua_getTime();
+
+	responseHeader.timestamp = opcua_time_now();
 	//request Handle which client sent
-	responseHeader.requestHandle = requestHandle;
+	responseHeader.requestHandle = requestHeader->requestHandle;
 	// StatusCode which informs client about quality of response
 	responseHeader.serviceResult = serviceResult;
-	//retrive diagnosticInfo if client demands
-	responseHeader.serviceDiagnostics = serviceDiagnostics;
+	//retrieve diagnosticInfo if client demands
+	responseHeader.serviceDiagnostics = &serviceDiagnostics;
 
 	//text of fields defined in the serviceDiagnostics
 	responseHeader.noOfStringTable = 0;
@@ -83,18 +199,27 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 
 
 	// no additional header
-	responseHeader.additionalHeader->Encoding = 0;
-	responseHeader.additionalHeader->TypeId.EncodingByte = 0;
-	responseHeader.additionalHeader->TypeId.Identifier.Numeric = 0;
+	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 = 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
 	*/
+
 	//                  secureChannelId + TokenId + CreatedAt + RevisedLifetime
 	sizeSecurityToken = sizeof(UInt32) + sizeof(UInt32) + sizeof(UA_DateTime) + sizeof(Int32);
 
@@ -102,38 +227,54 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	serverNonce.Length = 0;
 	serverNonce.Data = NULL;
 
-	//fill toke structure with default server information
+	//fill token structure with default server information
 	securityToken.secureChannelId = connection->secureLayer.securityToken.secureChannelId;
 	securityToken.tokenId = connection->secureLayer.securityToken.tokenId;
-	securityToken.createdAt = opcua_getTime();
+	securityToken.createdAt = opcua_time_now();
 	securityToken.revisedLifetime = connection->secureLayer.securityToken.revisedLifetime;
 
 	serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
 
 	//                ProtocolVersion + SecurityToken + Nonce
 	sizeRespMessage = sizeof(UInt32) + sizeSecurityToken + serverNonce.Length + sizeof(Int32) + sizeSecurityToken;
-
+	printf("SL_openSecureChannel - size of response message=%d\n",sizeRespMessage);
 	//get memory for response
-	response.Data = (char*)opcua_malloc(nodeId_calcSize(responseType) + sizeRespHeader + sizeRespMessage);
+	sizeResponseType = nodeId_calcSize(&responseType);
+	response.Data = (char*)opcua_malloc(sizeResponseType + sizeRespHeader + sizeRespMessage);
+	response.Length = sizeResponseType + sizeRespHeader + sizeRespMessage;
+
 	*pos = 0;
 	//encode responseType (NodeId)
-	encoder_encodeBuiltInDatatype(responseType,NODE_ID,pos,response.Data);
+	UA_NodeId_printf("SL_openSecureChannel - TypeId =",&responseType);
+	encoder_encodeBuiltInDatatype(&responseType, NODE_ID, pos, response.Data);
+
 	//encode header
-	encodeResponseHeader(&responseHeader,pos, &response);
+	printf("SL_openSecureChannel - encoding response header \n");
+
+	encodeResponseHeader(&responseHeader, pos, &response);
+	printf("SL_openSecureChannel - response header encoded \n");
+
 	//encode message
-	encoder_encodeBuiltInDatatype(serverProtocolVersion, UINT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.secureChannelId, UINT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.tokenId, INT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.createdAt, DATE_TIME, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.revisedLifetime, INT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(serverNonce, BYTE_STRING, pos,response.Data);
+	printf("SL_openSecureChannel - serverProtocolVersion = %d \n",serverProtocolVersion);
+	encoder_encodeBuiltInDatatype(&serverProtocolVersion, UINT32, pos,response.Data);
+	printf("SL_openSecureChannel - secureChannelId = %d \n",securityToken.secureChannelId);
+	encoder_encodeBuiltInDatatype(&(securityToken.secureChannelId), UINT32, pos,response.Data);
+	printf("SL_openSecureChannel - tokenId = %d \n",securityToken.tokenId);
+	encoder_encodeBuiltInDatatype(&(securityToken.tokenId), INT32, pos,response.Data);
+
+	encoder_encodeBuiltInDatatype(&(securityToken.createdAt), DATE_TIME, pos,response.Data);
+	printf("SL_openSecureChannel - revisedLifetime = %d \n",securityToken.revisedLifetime);
+	encoder_encodeBuiltInDatatype(&(securityToken.revisedLifetime), INT32, pos,response.Data);
 
+	encoder_encodeBuiltInDatatype(&serverNonce, BYTE_STRING, pos,response.Data);
+
+	printf("SL_openSecureChannel - response.Length = %d \n",response.Length);
 	//449 = openSecureChannelResponse
-	SL_send(connection,response,449);
+	SL_send(connection, response, 449);
 
 	return UA_NO_ERROR;
 }
-
+/*
 Int32 SL_openSecureChannel_responseMessage_calcSize(SL_Response *response,
 		Int32* sizeInOut) {
 	Int32 length = 0;
@@ -142,7 +283,7 @@ Int32 SL_openSecureChannel_responseMessage_calcSize(SL_Response *response,
 	length += sizeof(response->ServerProtocolVersion);
 	return length;
 }
-
+*/
 /*
  * closes a secureChannel (server side)
  */
@@ -165,6 +306,7 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 	Int32 securityMode;
 	Int32 requestedLifetime;
 	UA_ByteString clientNonce;
+	UA_StatusCode serviceResult;
 
 	// Every Message starts with a NodeID which names the serviceRequestType
 	decoder_decodeBuiltInDatatype(message.Data, NODE_ID, &pos,
@@ -272,6 +414,12 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 				&requestedLifetime);
 		printf("SL_processMessage - requestedLifeTime=%d\n",requestedLifetime);
 		//TODO process requestedLifetime
+
+		//TODO
+		serviceResult = 0;
+
+		SL_openSecureChannel(connection, &requestHeader, serviceResult);
+
 	} else {
 		printf("SL_processMessage - unknown service request");
 		//TODO change error code
@@ -318,7 +466,7 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 			if (SCM_Header.SecureChannelId != 0) {
 
 				iTmp = UA_ByteString_compare(
-						&(connection->secureLayer.SenderCertificate),
+						&(connection->secureLayer.remoteAsymAlgSettings.SenderCertificate),
 						&(AAS_Header.SenderCertificate));
 				if (iTmp != UA_EQUAL) {
 					printf("SL_receive - UA_ERROR_BadSecureChannelUnknown \n");
@@ -326,6 +474,10 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 				}
 
 			}
+			else
+			{
+				//TODO invalid securechannelId
+			}
 
 			decodeSequenceHeader(&secureChannelPacket, &pos, &SequenceHeader);
 			printf("SL_receive - SequenceHeader.RequestId=%d\n",
@@ -333,7 +485,7 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 			printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
 					SequenceHeader.SequenceNumber);
 			//save request id to return it to client
-			connection->secureLayer.requestId = SequenceHeader.RequestId;
+			connection->secureLayer.requestId= SequenceHeader.RequestId;
 			//TODO check that the sequence number is smaller than MaxUInt32 - 1024
 			connection->secureLayer.sequenceNumber =
 					SequenceHeader.SequenceNumber;
@@ -445,6 +597,7 @@ Int32 decodeSCMHeader(UA_ByteString *rawMessage, Int32 *pos,
 	return UA_NO_ERROR;
 
 }
+/*
 Int32 encodeSCMHeader(SL_SecureConversationMessageHeader *SC_Header, Int32 *pos,
 		AD_RawMessage *rawMessage) {
 	const char *type = "ERR";
@@ -475,6 +628,8 @@ Int32 encodeSCMHeader(SL_SecureConversationMessageHeader *SC_Header, Int32 *pos,
 
 	return UA_NO_ERROR;
 }
+*/
+
 Int32 decodeSequenceHeader(UA_ByteString *rawMessage, Int32 *pos,
 		SL_SequenceHeader *SequenceHeader) {
 	decodeUInt32(rawMessage->Data, pos, &(SequenceHeader->RequestId));

+ 15 - 0
src/opcua_secureChannelLayer.h

@@ -81,6 +81,21 @@ typedef struct _SL_ResponseHeader
     UA_ExtensionObject additionalHeader;
 }SL_ResponseHeader;
 */
+
+/**
+ *
+ * @param connection
+ * @return
+ */
+Int32 SL_initConnectionObject(UA_connection *connection);
+
+/**
+ *
+ * @param connection
+ * @param response
+ * @param sizeInOut
+ * @return
+ */
 Int32 SL_openSecureChannel_responseMessage_get(UA_connection *connection,
 		SL_Response *response, Int32* sizeInOut);