|
@@ -1,4 +1,6 @@
|
|
|
#include "ua_client.h"
|
|
|
+#include "ua_nodeids.h"
|
|
|
+#include "ua_types.h"
|
|
|
#include "ua_types_encoding_binary.h"
|
|
|
#include "ua_transport_generated.h"
|
|
|
|
|
@@ -6,7 +8,11 @@ struct UA_Client {
|
|
|
UA_ClientNetworkLayer networkLayer;
|
|
|
UA_String endpointUrl;
|
|
|
UA_Connection connection;
|
|
|
- /* UA_UInt32 channelId; */
|
|
|
+
|
|
|
+ UA_UInt32 requestId;
|
|
|
+ UA_UInt32 sequenceId;
|
|
|
+
|
|
|
+ UA_UInt32 channelId;
|
|
|
/* UA_SequenceHeader sequenceHdr; */
|
|
|
/* UA_NodeId authenticationToken; */
|
|
|
/* UA_UInt32 tokenId; */
|
|
@@ -19,6 +25,8 @@ UA_Client * UA_Client_new(void) {
|
|
|
return UA_NULL;
|
|
|
UA_String_init(&c->endpointUrl);
|
|
|
c->connection.state = UA_CONNECTION_OPENING;
|
|
|
+ c->requestId = 1;
|
|
|
+ c->sequenceId = 1;
|
|
|
return c;
|
|
|
}
|
|
|
|
|
@@ -49,7 +57,7 @@ UA_StatusCode UA_Client_connect(UA_Client *c, UA_ConnectionConfig conf, UA_Clien
|
|
|
return retval;
|
|
|
|
|
|
HelAckHandshake(c);
|
|
|
- // securechannel
|
|
|
+ SecureChannelHandshake(c);
|
|
|
// session
|
|
|
|
|
|
return UA_STATUSCODE_GOOD;
|
|
@@ -59,6 +67,88 @@ UA_StatusCode UA_EXPORT UA_Client_disconnect(UA_Client *c) {
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
|
+static UA_StatusCode SecureChannelHandshake(UA_Client *c) {
|
|
|
+ UA_SecureConversationMessageHeader messageHeader;
|
|
|
+ messageHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
|
|
|
+ messageHeader.secureChannelId = 0;
|
|
|
+
|
|
|
+ UA_SequenceHeader seqHeader;
|
|
|
+ seqHeader.requestId = c->requestId;
|
|
|
+ seqHeader.sequenceNumber = c->sequenceId;
|
|
|
+
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader asymHeader;
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
|
|
|
+ UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None", &asymHeader.securityPolicyUri);
|
|
|
+
|
|
|
+ UA_NodeId requestType = UA_NODEID_STATIC(0, UA_NS0ID_OPENSECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY); // id of opensecurechannelrequest
|
|
|
+
|
|
|
+ UA_OpenSecureChannelRequest opnSecRq;
|
|
|
+ UA_OpenSecureChannelRequest_init(&opnSecRq);
|
|
|
+ opnSecRq.requestHeader.timestamp = UA_DateTime_now();
|
|
|
+ UA_ByteString_newMembers(&opnSecRq.clientNonce, 1);
|
|
|
+ opnSecRq.clientNonce.data[0] = 0;
|
|
|
+ opnSecRq.clientProtocolVersion = 0;
|
|
|
+ opnSecRq.requestedLifetime = 30000;
|
|
|
+ opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
|
|
|
+ opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
|
|
|
+ opnSecRq.requestHeader.authenticationToken.identifier.numeric = 10;
|
|
|
+ opnSecRq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC;
|
|
|
+ opnSecRq.requestHeader.authenticationToken.namespaceIndex = 10;
|
|
|
+
|
|
|
+ messageHeader.messageHeader.messageSize = UA_SecureConversationMessageHeader_calcSizeBinary(&messageHeader) +
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) +
|
|
|
+ UA_SequenceHeader_calcSizeBinary(&seqHeader) +
|
|
|
+ UA_NodeId_calcSizeBinary(&requestType) +
|
|
|
+ UA_OpenSecureChannelRequest_calcSizeBinary(&opnSecRq);
|
|
|
+
|
|
|
+ UA_ByteString message;
|
|
|
+ message.data = UA_alloca(messageHeader.messageHeader.messageSize);
|
|
|
+ message.length = messageHeader.messageHeader.messageSize;
|
|
|
+
|
|
|
+ size_t offset = 0;
|
|
|
+ UA_SecureConversationMessageHeader_encodeBinary(&messageHeader, &message, &offset);
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
|
|
|
+ UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
|
|
|
+ UA_NodeId_encodeBinary(&requestType, &message, &offset);
|
|
|
+ UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
|
|
|
+
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
|
|
|
+ UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
|
|
|
+
|
|
|
+ UA_ByteStringArray buf = {.stringsSize = 1, .strings = &message};
|
|
|
+ UA_StatusCode retval = c->networkLayer.send(c->networkLayer.nlHandle, buf);
|
|
|
+ if(retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ // parse the response
|
|
|
+ UA_ByteString reply;
|
|
|
+ UA_ByteString_newMembers(&reply, c->connection.localConf.recvBufferSize);
|
|
|
+ retval = c->networkLayer.awaitResponse(c->networkLayer.nlHandle, &reply, 1000);
|
|
|
+ if(retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ offset = 0;
|
|
|
+
|
|
|
+ UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &asymHeader);
|
|
|
+ UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
|
|
|
+ UA_NodeId_decodeBinary(&reply, &offset, &requestType);
|
|
|
+
|
|
|
+ c->channelId = messageHeader.secureChannelId;
|
|
|
+
|
|
|
+
|
|
|
+ //TODO: save other stuff
|
|
|
+ UA_OpenSecureChannelResponse response;
|
|
|
+ UA_OpenSecureChannelResponse_decodeBinary(&reply, &offset, &response);
|
|
|
+
|
|
|
+ UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
|
|
|
+ UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
|
|
|
+
|
|
|
+ UA_ByteString_deleteMembers(&reply);
|
|
|
+ return retval;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
// The tcp connection is established. Now do the handshake
|
|
|
static UA_StatusCode HelAckHandshake(UA_Client *c) {
|
|
|
UA_TcpMessageHeader messageHeader;
|
|
@@ -115,75 +205,3 @@ static UA_StatusCode HelAckHandshake(UA_Client *c) {
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
|
-static UA_StatusCode SecureChannelHandshake(UA_Client *c) {
|
|
|
- UA_SecureConversationMessageHeader msghdr;
|
|
|
- msghdr.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
|
|
|
- msghdr.secureChannelId = 0;
|
|
|
-
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader asymHeader;
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
|
|
|
- UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None", &asymHeader.securityPolicyUri);
|
|
|
-
|
|
|
- UA_SequenceHeader seqHeader;
|
|
|
- seqHeader.sequenceNumber = 51; // why is that???
|
|
|
- seqHeader.requestId = 1;
|
|
|
-
|
|
|
- UA_NodeId requestType = {.identifierType = UA_NODEIDTYPE_NUMERIC, .namespaceIndex = 0,
|
|
|
- .identifier.numeric = 446}; // id of opensecurechannelrequest
|
|
|
-
|
|
|
- UA_OpenSecureChannelRequest opnSecRq;
|
|
|
- UA_OpenSecureChannelRequest_init(&opnSecRq);
|
|
|
- opnSecRq.requestHeader.timestamp = UA_DateTime_now();
|
|
|
- UA_ByteString_newMembers(&opnSecRq.clientNonce, 1);
|
|
|
- opnSecRq.clientNonce.data[0] = 0;
|
|
|
- opnSecRq.clientProtocolVersion = 0;
|
|
|
- opnSecRq.requestedLifetime = 30000;
|
|
|
- opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
|
|
|
- opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
|
|
|
- opnSecRq.requestHeader.authenticationToken.identifier.numeric = 10;
|
|
|
- opnSecRq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC;
|
|
|
- opnSecRq.requestHeader.authenticationToken.namespaceIndex = 10;
|
|
|
-
|
|
|
- msghdr.messageHeader.messageSize = UA_SecureConversationMessageHeader_calcSizeBinary(&msghdr) +
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) +
|
|
|
- UA_SequenceHeader_calcSizeBinary(&seqHeader) +
|
|
|
- UA_NodeId_calcSizeBinary(&requestType) +
|
|
|
- UA_OpenSecureChannelRequest_calcSizeBinary(&opnSecRq);
|
|
|
-
|
|
|
- UA_ByteString message;
|
|
|
- UA_ByteString_newMembers(&message, msghdr.messageHeader.messageSize);
|
|
|
- size_t offset = 0;
|
|
|
- UA_SecureConversationMessageHeader_encodeBinary(&msghdr, &message, &offset);
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
|
|
|
- UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
|
|
|
- UA_NodeId_encodeBinary(&requestType, &message, &offset);
|
|
|
- UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
|
|
|
-
|
|
|
- UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
|
|
|
- UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
|
|
|
-
|
|
|
- UA_ByteStringArray buf = {.stringsSize = 1, .strings = &message};
|
|
|
- UA_StatusCode retval = c->networkLayer.send(c->networkLayer.nlHandle, buf);
|
|
|
- UA_ByteString_deleteMembers(&message);
|
|
|
-
|
|
|
- // parse the response
|
|
|
- UA_ByteString response;
|
|
|
- UA_ByteString_newMembers(&response, c->connection.localConf.recvBufferSize);
|
|
|
- retval = c->networkLayer.awaitResponse(c->networkLayer.nlHandle, &response, 1000);
|
|
|
-
|
|
|
- /* UA_SecureConversationMessageHeader_init(&msghdr); */
|
|
|
- /* UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader); */
|
|
|
- /* UA_SequenceHeader_init(&seqHeader); */
|
|
|
- /* UA_OpenSecureChannelResponse opnSecRq; */
|
|
|
-
|
|
|
- /* UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader) */
|
|
|
- /* + UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) */
|
|
|
- /* + UA_SequenceHeader_calcSizeBinary(&seqHeader) */
|
|
|
- /* + UA_NodeId_calcSizeBinary(&responseType) */
|
|
|
- /* + UA_OpenSecureChannelResponse_calcSizeBinary(&p); */
|
|
|
-
|
|
|
- //UA_SecureConversationMessageHeader respHeader;
|
|
|
- //UA_NodeId responseType = UA_NODEIDS[UA_OPENSECURECHANNELRESPONSE];
|
|
|
-
|
|
|
- return retval;
|
|
|
-}
|