ソースを参照

Changes Client (#671)

* Changes Client: Pointer to Connection and Securechannel & Check of sequencenumber in Client like Server
* Changes Connection: Pointer to internal Data later for Servent
* Checking of SequenceNumber in single function, ready for PullRequest
Torben-D 8 年 前
コミット
d3ec67e70b
共有7 個のファイルを変更した88 個の追加58 個の削除を含む
  1. 1 1
      include/ua_connection.h
  2. 63 42
      src/client/ua_client.c
  3. 2 2
      src/client/ua_client_internal.h
  4. 7 12
      src/server/ua_server_binary.c
  5. 1 1
      src/ua_connection.c
  6. 13 0
      src/ua_securechannel.c
  7. 1 0
      src/ua_securechannel.h

+ 1 - 1
include/ua_connection.h

@@ -75,7 +75,7 @@ struct UA_Connection {
     UA_Int32 sockfd;                 /* Most connectivity solutions run on
                                         sockets. Having the socket id here
                                         simplifies the design. */
-    void *handle;                    /* A pointer to the networklayer */
+    void *handle;                    /* A pointer to internal data */
     UA_ByteString incompleteMessage; /* A half-received message (TCP is a
                                         streaming protocol) is stored here */
 

+ 63 - 42
src/client/ua_client.c

@@ -16,9 +16,11 @@
 
 static void UA_Client_init(UA_Client* client, UA_ClientConfig config) {
     client->state = UA_CLIENTSTATE_READY;
-    UA_Connection_init(&client->connection);
-    UA_SecureChannel_init(&client->channel);
-    client->channel.connection = &client->connection;
+    client->connection = UA_malloc(sizeof(UA_Connection));
+    UA_Connection_init(client->connection);
+    client->channel = UA_malloc(sizeof(UA_SecureChannel));
+    UA_SecureChannel_init(client->channel);
+    client->channel->connection = client->connection;
     UA_String_init(&client->endpointUrl);
     client->requestId = 0;
 
@@ -50,8 +52,10 @@ UA_Client * UA_Client_new(UA_ClientConfig config) {
 
 static void UA_Client_deleteMembers(UA_Client* client) {
     UA_Client_disconnect(client);
-    UA_Connection_deleteMembers(&client->connection);
-    UA_SecureChannel_deleteMembersCleanup(&client->channel);
+    UA_Connection_deleteMembers(client->connection);
+    UA_free(client->connection);
+    UA_SecureChannel_deleteMembersCleanup(client->channel);
+    UA_free(client->channel);
     if(client->endpointUrl.data)
         UA_String_deleteMembers(&client->endpointUrl);
     UA_UserTokenPolicy_deleteMembers(&client->token);
@@ -98,7 +102,7 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
     UA_TcpHelloMessage hello;
     UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
 
-    UA_Connection *conn = &client->connection;
+    UA_Connection *conn = client->connection;
     hello.maxChunkCount = conn->localConf.maxChunkCount;
     hello.maxMessageSize = conn->localConf.maxMessageSize;
     hello.protocolVersion = conn->localConf.protocolVersion;
@@ -107,7 +111,7 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
 
     UA_ByteString message;
     UA_StatusCode retval;
-    retval = client->connection.getSendBuffer(&client->connection, client->connection.remoteConf.recvBufferSize, &message);
+    retval = client->connection->getSendBuffer(client->connection, client->connection->remoteConf.recvBufferSize, &message);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
 
@@ -118,12 +122,12 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
     retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
     UA_TcpHelloMessage_deleteMembers(&hello);
     if(retval != UA_STATUSCODE_GOOD) {
-        client->connection.releaseSendBuffer(&client->connection, &message);
+        client->connection->releaseSendBuffer(client->connection, &message);
         return retval;
     }
 
     message.length = messageHeader.messageSize;
-    retval = client->connection.send(&client->connection, &message);
+    retval = client->connection->send(client->connection, &message);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK, "Sending HEL failed");
         return retval;
@@ -134,8 +138,8 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
     UA_ByteString_init(&reply);
     UA_Boolean realloced = false;
     do {
-        retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
-        retval |= UA_Connection_completeMessages(&client->connection, &reply, &realloced);
+        retval = client->connection->recv(client->connection, &reply, client->config.timeout);
+        retval |= UA_Connection_completeMessages(client->connection, &reply, &realloced);
         if(retval != UA_STATUSCODE_GOOD) {
             UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK, "Receiving ACK message failed");
             return retval;
@@ -147,7 +151,7 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
     UA_TcpAcknowledgeMessage ackMessage;
     retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
     if(!realloced)
-        client->connection.releaseRecvBuffer(&client->connection, &reply);
+        client->connection->releaseRecvBuffer(client->connection, &reply);
     else
         UA_ByteString_deleteMembers(&reply);
 
@@ -176,19 +180,19 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     if(renew && client->scRenewAt - UA_DateTime_now() > 0)
         return UA_STATUSCODE_GOOD;
 
-    UA_Connection *c = &client->connection;
+    UA_Connection *c = client->connection;
     if(c->state != UA_CONNECTION_ESTABLISHED)
         return UA_STATUSCODE_BADSERVERNOTCONNECTED;
 
     UA_SecureConversationMessageHeader messageHeader;
     messageHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
     if(renew)
-        messageHeader.secureChannelId = client->channel.securityToken.channelId;
+        messageHeader.secureChannelId = client->channel->securityToken.channelId;
     else
         messageHeader.secureChannelId = 0;
 
     UA_SequenceHeader seqHeader;
-    seqHeader.sequenceNumber = ++client->channel.sendSequenceNumber;
+    seqHeader.sequenceNumber = ++client->channel->sendSequenceNumber;
     seqHeader.requestId = ++client->requestId;
 
     UA_AsymmetricAlgorithmSecurityHeader asymHeader;
@@ -211,7 +215,7 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
         UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "Requesting to open a SecureChannel");
     }
 
-    UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce);
+    UA_ByteString_copy(&client->channel->clientNonce, &opnSecRq.clientNonce);
     opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
 
     UA_ByteString message;
@@ -234,12 +238,12 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
     UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
     if(retval != UA_STATUSCODE_GOOD) {
-        client->connection.releaseSendBuffer(&client->connection, &message);
+        client->connection->releaseSendBuffer(client->connection, &message);
         return retval;
     }
 
     message.length = messageHeader.messageHeader.messageSize;
-    retval = client->connection.send(&client->connection, &message);
+    retval = client->connection->send(client->connection, &message);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
 
@@ -280,6 +284,14 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     else
         UA_ByteString_deleteMembers(&reply);
 
+    /* Does the sequence number match? */
+    retval |= UA_SecureChannel_processSequenceNumber(seqHeader.sequenceNumber, client->channel);
+    if (retval != UA_STATUSCODE_GOOD){
+        UA_LOG_INFO_CHANNEL(client->config.logger, client->channel,
+                            "The sequence number was not increased by one. Got %i, expected %i",
+                            seqHeader.sequenceNumber, client->channel->receiveSequenceNumber + 1);
+    }
+
     if(retval != UA_STATUSCODE_GOOD) {
         UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
                      "Decoding OpenSecureChannelResponse failed");
@@ -298,10 +310,10 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
             (UA_DateTime)(response.securityToken.revisedLifetime * (UA_Double)UA_MSEC_TO_DATETIME * 0.75);
 
         /* Replace the old nonce */
-        UA_ChannelSecurityToken_deleteMembers(&client->channel.securityToken);
-        UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken);
-        UA_ByteString_deleteMembers(&client->channel.serverNonce);
-        UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce);
+        UA_ChannelSecurityToken_deleteMembers(&client->channel->securityToken);
+        UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel->securityToken);
+        UA_ByteString_deleteMembers(&client->channel->serverNonce);
+        UA_ByteString_copy(&response.serverNonce, &client->channel->serverNonce);
 
         if(renew)
             UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel renewed");
@@ -454,7 +466,7 @@ static UA_StatusCode SessionHandshake(UA_Client *client) {
     UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
-    UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce);
+    UA_ByteString_copy(&client->channel->clientNonce, &request.clientNonce);
     request.requestedSessionTimeout = 1200000;
     request.maxResponseMessageSize = UA_INT32_MAX;
 
@@ -488,7 +500,7 @@ static UA_StatusCode CloseSession(UA_Client *client) {
 }
 
 static UA_StatusCode CloseSecureChannel(UA_Client *client) {
-    UA_SecureChannel *channel = &client->channel;
+    UA_SecureChannel *channel = client->channel;
     UA_CloseSecureChannelRequest request;
     UA_CloseSecureChannelRequest_init(&request);
     request.requestHeader.requestHandle = ++client->requestHandle;
@@ -498,7 +510,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
 
     UA_SecureConversationMessageHeader msgHeader;
     msgHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_CLO + UA_CHUNKTYPE_FINAL;
-    msgHeader.secureChannelId = client->channel.securityToken.channelId;
+    msgHeader.secureChannelId = client->channel->securityToken.channelId;
 
     UA_SymmetricAlgorithmSecurityHeader symHeader;
     symHeader.tokenId = channel->securityToken.tokenId;
@@ -510,7 +522,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
     UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
 
     UA_ByteString message;
-    UA_Connection *c = &client->connection;
+    UA_Connection *c = client->connection;
     UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
@@ -528,11 +540,11 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
 
     if(retval == UA_STATUSCODE_GOOD) {
         message.length = msgHeader.messageHeader.messageSize;
-        retval = client->connection.send(&client->connection, &message);
+        retval = client->connection->send(client->connection, &message);
     } else {
-        client->connection.releaseSendBuffer(&client->connection, &message);
+        client->connection->releaseSendBuffer(client->connection, &message);
     }
-    client->connection.close(&client->connection);
+    client->connection->close(client->connection);
     return retval;
 }
 
@@ -547,9 +559,9 @@ UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
 
 
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, serverUrl,
+    *client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, serverUrl,
                                                        client->config.logger);
-    if(client->connection.state != UA_CONNECTION_OPENING) {
+    if(client->connection->state != UA_CONNECTION_OPENING) {
         retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
         goto cleanup;
     }
@@ -560,7 +572,7 @@ UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
         goto cleanup;
     }
 
-    client->connection.localConf = client->config.localConnectionConfig;
+    client->connection->localConf = client->config.localConnectionConfig;
     retval = HelAckHandshake(client);
     if(retval == UA_STATUSCODE_GOOD)
         retval = SecureChannelHandshake(client, false);
@@ -593,8 +605,8 @@ UA_Client_connect(UA_Client *client, const char *endpointUrl) {
     }
 
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, endpointUrl, client->config.logger);
-    if(client->connection.state != UA_CONNECTION_OPENING) {
+    *client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, endpointUrl, client->config.logger);
+    if(client->connection->state != UA_CONNECTION_OPENING) {
         retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
         goto cleanup;
     }
@@ -605,7 +617,7 @@ UA_Client_connect(UA_Client *client, const char *endpointUrl) {
         goto cleanup;
     }
 
-    client->connection.localConf = client->config.localConnectionConfig;
+    client->connection->localConf = client->config.localConnectionConfig;
     retval = HelAckHandshake(client);
     if(retval == UA_STATUSCODE_GOOD)
         retval = SecureChannelHandshake(client, false);
@@ -616,7 +628,7 @@ UA_Client_connect(UA_Client *client, const char *endpointUrl) {
     if(retval == UA_STATUSCODE_GOOD)
         retval = ActivateSession(client);
     if(retval == UA_STATUSCODE_GOOD) {
-        client->connection.state = UA_CONNECTION_ESTABLISHED;
+        client->connection->state = UA_CONNECTION_ESTABLISHED;
         client->state = UA_CLIENTSTATE_CONNECTED;
     } else {
         goto cleanup;
@@ -633,11 +645,11 @@ UA_StatusCode UA_Client_disconnect(UA_Client *client) {
         return UA_STATUSCODE_BADNOTCONNECTED;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     /* Is a session established? */
-    if(client->channel.connection->state == UA_CONNECTION_ESTABLISHED &&
+    if(client->connection->state == UA_CONNECTION_ESTABLISHED &&
        !UA_NodeId_equal(&client->authenticationToken, &UA_NODEID_NULL))
         retval = CloseSession(client);
     /* Is a secure channel established? */
-    if(client->channel.connection->state == UA_CONNECTION_ESTABLISHED)
+    if(client->connection->state == UA_CONNECTION_ESTABLISHED)
         retval |= CloseSecureChannel(client);
     return retval;
 }
@@ -678,7 +690,7 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
     UA_UInt32 requestId = ++client->requestId;
     UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
                  "Sending a request of type %i", requestType->typeId.identifier.numeric);
-    retval = UA_SecureChannel_sendBinaryMessage(&client->channel, requestId, request, requestType);
+    retval = UA_SecureChannel_sendBinaryMessage(client->channel, requestId, request, requestType);
     if(retval != UA_STATUSCODE_GOOD) {
         if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
             respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
@@ -694,8 +706,8 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
     UA_ByteString_init(&reply);
     UA_Boolean realloced = false;
     do {
-        retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
-        retval |= UA_Connection_completeMessages(&client->connection, &reply, &realloced);
+        retval = client->connection->recv(client->connection, &reply, client->config.timeout);
+        retval |= UA_Connection_completeMessages(client->connection, &reply, &realloced);
         if(retval != UA_STATUSCODE_GOOD) {
             respHeader->serviceResult = retval;
             client->state = UA_CLIENTSTATE_ERRORED;
@@ -718,6 +730,15 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
     if(retval != UA_STATUSCODE_GOOD)
         goto finish;
 
+    /* Does the sequence number match? */
+    retval = UA_SecureChannel_processSequenceNumber(seqHeader.sequenceNumber, client->channel);
+    if (retval != UA_STATUSCODE_GOOD){
+        UA_LOG_INFO_CHANNEL(client->config.logger, client->channel,
+                            "The sequence number was not increased by one. Got %i, expected %i",
+                            seqHeader.sequenceNumber, client->channel->receiveSequenceNumber + 1);
+        goto finish;
+    }
+
     /* Todo: we need to demux responses since a publish responses may come at any time */
     if(!UA_NodeId_equal(&responseId, &expectedNodeId) || seqHeader.requestId != requestId) {
         if(responseId.identifier.numeric != UA_NS0ID_SERVICEFAULT + UA_ENCODINGOFFSET_BINARY) {
@@ -738,7 +759,7 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
  finish:
     UA_SymmetricAlgorithmSecurityHeader_deleteMembers(&symHeader);
     if(!realloced)
-        client->connection.releaseRecvBuffer(&client->connection, &reply);
+        client->connection->releaseRecvBuffer(client->connection, &reply);
     else
         UA_ByteString_deleteMembers(&reply);
 

+ 2 - 2
src/client/ua_client_internal.h

@@ -56,8 +56,8 @@ struct UA_Client {
     UA_ClientState state;
 
     /* Connection */
-    UA_Connection connection;
-    UA_SecureChannel channel;
+    UA_Connection *connection;
+    UA_SecureChannel *channel;
     UA_String endpointUrl;
     UA_UInt32 requestId;
 

+ 7 - 12
src/server/ua_server_binary.c

@@ -545,19 +545,14 @@ processMSG(UA_Connection *connection, UA_Server *server, const UA_TcpMessageHead
     }
 
     /* Does the sequence number match? */
-    if(sequenceHeader.sequenceNumber != channel->receiveSequenceNumber + 1) {
-        if(channel->receiveSequenceNumber + 1 > 4294966271 && sequenceHeader.sequenceNumber < 1024) {
-            channel->receiveSequenceNumber = sequenceHeader.sequenceNumber - 1; /* Roll over */
-        } else {
-            UA_LOG_INFO_CHANNEL(server->config.logger, channel,
-                                "The sequence number was not increased by one. Got %i, expected %i",
-                                sequenceHeader.sequenceNumber, channel->receiveSequenceNumber + 1);
-            sendError(channel, msg, *offset, &UA_TYPES[UA_TYPES_SERVICEFAULT],
-                      sequenceHeader.requestId, UA_STATUSCODE_BADSECURITYCHECKSFAILED);
-            return;
-        }
+    retval = UA_SecureChannel_processSequenceNumber(sequenceHeader.sequenceNumber, channel);
+    if (retval != UA_STATUSCODE_GOOD){
+        UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+                            "The sequence number was not increased by one. Got %i, expected %i",
+                            sequenceHeader.sequenceNumber, channel->receiveSequenceNumber + 1);
+        sendError(channel, msg, *offset, &UA_TYPES[UA_TYPES_SERVICEFAULT],
+                  sequenceHeader.requestId, UA_STATUSCODE_BADSECURITYCHECKSFAILED);
     }
-    channel->receiveSequenceNumber++;
 
     /* Does the token match? */
     if(tokenId != channel->securityToken.tokenId) {

+ 1 - 1
src/ua_connection.c

@@ -18,8 +18,8 @@ void UA_Connection_init(UA_Connection *connection) {
     connection->handle = NULL;
     UA_ByteString_init(&connection->incompleteMessage);
     connection->send = NULL;
-    connection->close = NULL;
     connection->recv = NULL;
+    connection->close = NULL;
     connection->getSendBuffer = NULL;
     connection->releaseSendBuffer = NULL;
     connection->releaseRecvBuffer = NULL;

+ 13 - 0
src/ua_securechannel.c

@@ -332,3 +332,16 @@ void UA_SecureChannel_removeChunk(UA_SecureChannel *channel, UA_UInt32 requestId
         }
     }
 }
+
+UA_StatusCode UA_SecureChannel_processSequenceNumber (UA_UInt32 SequenceNumber, UA_SecureChannel *channel){
+/* Does the sequence number match? */
+    if(SequenceNumber != channel->receiveSequenceNumber + 1) {
+        if(channel->receiveSequenceNumber + 1 > 4294966271 && SequenceNumber < 1024) {
+            channel->receiveSequenceNumber = SequenceNumber - 1; /* Roll over */
+        } else {
+            return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+        }
+    }
+    channel->receiveSequenceNumber++;
+    return UA_STATUSCODE_GOOD;
+}

+ 1 - 0
src/ua_securechannel.h

@@ -77,6 +77,7 @@ UA_ByteString UA_SecureChannel_finalizeChunk(UA_SecureChannel *channel, UA_UInt3
 
 void UA_SecureChannel_removeChunk(UA_SecureChannel *channel, UA_UInt32 requestId);
 
+UA_StatusCode UA_SecureChannel_processSequenceNumber (UA_UInt32 SequenceNumber, UA_SecureChannel *channel);
 /**
  * Log Helper
  * ---------- */