mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
refactor(core): Move ConnectionConfig into SecureChannel
This commit is contained in:
parent
fd998e4ad9
commit
a25bb75393
@ -1,6 +1,7 @@
|
||||
SET(SOURCE_GROUP ${SOURCE_GROUP}\\arch)
|
||||
|
||||
ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) #to have access to ua_network_tcp.h
|
||||
ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # to have access to ua_network_tcp.h
|
||||
ua_include_directories(${CMAKE_SOURCE_DIR}/src) # to have access to ua_securechannel.h
|
||||
|
||||
add_subdirectory(posix)
|
||||
add_subdirectory(win32)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <open62541/util.h>
|
||||
|
||||
#include "open62541_queue.h"
|
||||
#include "ua_securechannel.h"
|
||||
|
||||
#include <string.h> // memset
|
||||
|
||||
@ -29,7 +30,8 @@
|
||||
static UA_StatusCode
|
||||
connection_getsendbuffer(UA_Connection *connection,
|
||||
size_t length, UA_ByteString *buf) {
|
||||
if(length > connection->config.sendBufferSize)
|
||||
UA_SecureChannel *channel = connection->channel;
|
||||
if(channel && channel->config.sendBufferSize < length)
|
||||
return UA_STATUSCODE_BADCOMMUNICATIONERROR;
|
||||
return UA_ByteString_allocBuffer(buf, length);
|
||||
}
|
||||
@ -115,8 +117,8 @@ connection_recv(UA_Connection *connection, UA_ByteString *response,
|
||||
if(internallyAllocated) {
|
||||
size_t bufferSize = 16384; /* Use as default for a new SecureChannel */
|
||||
UA_SecureChannel *channel = connection->channel;
|
||||
if(channel && connection->config.recvBufferSize > 0)
|
||||
bufferSize = connection->config.recvBufferSize;
|
||||
if(channel && channel->config.recvBufferSize > 0)
|
||||
bufferSize = channel->config.recvBufferSize;
|
||||
UA_StatusCode res = UA_ByteString_allocBuffer(response, bufferSize);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
@ -236,7 +238,6 @@ ServerNetworkLayerTCP_add(UA_ServerNetworkLayer *nl, ServerNetworkLayerTCP *laye
|
||||
memset(c, 0, sizeof(UA_Connection));
|
||||
c->sockfd = newsockfd;
|
||||
c->handle = layer;
|
||||
c->config = nl->localConnectionConfig;
|
||||
c->send = connection_write;
|
||||
c->close = ServerNetworkLayerTCP_close;
|
||||
c->free = ServerNetworkLayerTCP_freeConnection;
|
||||
@ -751,7 +752,6 @@ UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpoint
|
||||
memset(&connection, 0, sizeof(UA_Connection));
|
||||
|
||||
connection.state = UA_CONNECTION_OPENING;
|
||||
connection.config = config;
|
||||
connection.send = connection_write;
|
||||
connection.recv = connection_recv;
|
||||
connection.close = ClientNetworkLayerTCP_close;
|
||||
@ -813,7 +813,6 @@ UA_ClientConnectionTCP(UA_ConnectionConfig config, const UA_String endpointUrl,
|
||||
UA_Connection connection;
|
||||
memset(&connection, 0, sizeof(UA_Connection));
|
||||
connection.state = UA_CONNECTION_CLOSED;
|
||||
connection.config = config;
|
||||
connection.send = connection_write;
|
||||
connection.recv = connection_recv;
|
||||
connection.close = ClientNetworkLayerTCP_close;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <open62541/plugin/log_stdout.h>
|
||||
#include <open62541/util.h>
|
||||
#include "open62541_queue.h"
|
||||
#include "ua_securechannel.h"
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -49,7 +50,8 @@ typedef struct {
|
||||
|
||||
static UA_StatusCode
|
||||
connection_getsendbuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
|
||||
if(length > connection->config.sendBufferSize)
|
||||
UA_SecureChannel *channel = connection->channel;
|
||||
if(channel && channel->config.sendBufferSize < length)
|
||||
return UA_STATUSCODE_BADCOMMUNICATIONERROR;
|
||||
return UA_ByteString_allocBuffer(buf, length);
|
||||
}
|
||||
@ -101,7 +103,6 @@ freeConnection(UA_Connection *connection) {
|
||||
}
|
||||
UA_free(connection->handle);
|
||||
}
|
||||
UA_Connection_clear(connection);
|
||||
UA_free(connection);
|
||||
}
|
||||
|
||||
@ -133,7 +134,6 @@ callback_opcua(struct lws *wsi, enum lws_callback_reasons reason, void *user, vo
|
||||
memset(c, 0, sizeof(UA_Connection));
|
||||
c->sockfd = 0;
|
||||
c->handle = buffer;
|
||||
c->config = layer->config;
|
||||
c->send = connection_send;
|
||||
c->close = ServerNetworkLayerWS_close;
|
||||
c->free = freeConnection;
|
||||
@ -188,34 +188,17 @@ callback_opcua(struct lws *wsi, enum lws_callback_reasons reason, void *user, vo
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
case LWS_CALLBACK_RECEIVE: {
|
||||
if(!vhd->context)
|
||||
break;
|
||||
layer =
|
||||
(ServerNetworkLayerWS *)lws_context_user(vhd->context);
|
||||
layer = (ServerNetworkLayerWS *)lws_context_user(vhd->context);
|
||||
if(!layer->server)
|
||||
break;
|
||||
|
||||
if(pss->connection->incompleteChunk.length == 0) {
|
||||
UA_ByteString message = {len, (UA_Byte *)in};
|
||||
UA_Server_processBinaryMessage(layer->server, pss->connection, &message);
|
||||
} else {
|
||||
UA_ByteString message = pss->connection->incompleteChunk;
|
||||
pss->connection->incompleteChunk = UA_BYTESTRING_NULL;
|
||||
UA_Byte *t = (UA_Byte*)UA_realloc(message.data, message.length + len);
|
||||
if(!t) {
|
||||
UA_ByteString_deleteMembers(&message);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&t[message.length], in, len);
|
||||
message.data = t;
|
||||
message.length += len;
|
||||
|
||||
UA_Server_processBinaryMessage(layer->server, pss->connection, &message);
|
||||
|
||||
connection_releaserecvbuffer(pss->connection, &message);
|
||||
}
|
||||
UA_ByteString message = {len, (UA_Byte *)in};
|
||||
UA_Server_processBinaryMessage(layer->server, pss->connection, &message);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -55,12 +55,10 @@ typedef enum {
|
||||
* is not done */
|
||||
UA_CONNECTION_ESTABLISHED /* The socket is open and the connection
|
||||
* configured */
|
||||
|
||||
} UA_ConnectionState;
|
||||
|
||||
struct UA_Connection {
|
||||
UA_ConnectionState state;
|
||||
UA_ConnectionConfig config;
|
||||
UA_SecureChannel *channel; /* The securechannel that is attached to
|
||||
* this connection */
|
||||
UA_SOCKET sockfd; /* Most connectivity solutions run on
|
||||
|
@ -24,20 +24,16 @@ mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void* buf, size_t len, int fla
|
||||
|
||||
ssize_t
|
||||
mqtt_pal_recvall(mqtt_pal_socket_handle fd, void* buf, size_t bufsz, int flags) {
|
||||
UA_Connection *connection = (UA_Connection*) fd->connection;
|
||||
connection->config.recvBufferSize = (UA_UInt32) bufsz;
|
||||
UA_Connection *connection = (UA_Connection*)fd->connection;
|
||||
UA_ByteString inBuffer;
|
||||
inBuffer.data = (UA_Byte*)buf;
|
||||
inBuffer.length = bufsz;
|
||||
UA_StatusCode ret = connection->recv(connection, &inBuffer, fd->timeout);
|
||||
if(ret == UA_STATUSCODE_GOOD ){
|
||||
// Buffer received, copy to recv buffer
|
||||
memcpy(buf, inBuffer.data, inBuffer.length);
|
||||
ssize_t bytesReceived = (ssize_t)inBuffer.length;
|
||||
/* free recv buffer */
|
||||
connection->releaseRecvBuffer(connection, &inBuffer);
|
||||
return bytesReceived;
|
||||
}else if(ret == UA_STATUSCODE_GOODNONCRITICALTIMEOUT){
|
||||
if(ret == UA_STATUSCODE_GOOD ) {
|
||||
return (ssize_t)inBuffer.length;
|
||||
} else if(ret == UA_STATUSCODE_GOODNONCRITICALTIMEOUT) {
|
||||
return 0;
|
||||
}else{
|
||||
} else {
|
||||
return -1; //error case, no free necessary
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
static void
|
||||
UA_Client_init(UA_Client* client) {
|
||||
UA_SecureChannel_init(&client->channel);
|
||||
UA_SecureChannel_init(&client->channel, &client->config.localConnectionConfig);
|
||||
if(client->config.stateCallback)
|
||||
client->config.stateCallback(client, client->state);
|
||||
/* Catch error during async connection */
|
||||
|
@ -59,8 +59,7 @@ processACKResponse(void *application, UA_SecureChannel *channel,
|
||||
UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
|
||||
|
||||
/* Process the ACK message */
|
||||
retval = UA_Connection_processHELACK(channel->connection, &client->config.localConnectionConfig,
|
||||
(const UA_ConnectionConfig*)&ackMessage);
|
||||
retval = UA_SecureChannel_processHELACK(channel, (const UA_ConnectionConfig*)&ackMessage);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"Processing the ACK message failed with StatusCode %s",
|
||||
@ -734,6 +733,7 @@ UA_Client_connectTCPSecureChannel(UA_Client *client, const UA_String endpointUrl
|
||||
client->channel.state = UA_SECURECHANNELSTATE_FRESH;
|
||||
client->channel.sendSequenceNumber = 0;
|
||||
client->requestId = 0;
|
||||
client->channel.config = client->config.localConnectionConfig;
|
||||
|
||||
/* Set the channel SecurityMode */
|
||||
client->channel.securityMode = client->config.endpoint.securityMode;
|
||||
@ -788,7 +788,7 @@ UA_Client_connectTCPSecureChannel(UA_Client *client, const UA_String endpointUrl
|
||||
UA_Connection_attachSecureChannel(&client->connection, &client->channel);
|
||||
|
||||
/* Perform the HEL/ACK handshake */
|
||||
client->connection.config = client->config.localConnectionConfig;
|
||||
client->channel.config = client->config.localConnectionConfig;
|
||||
retval = HelAckHandshake(client, endpointUrl);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
|
||||
|
@ -63,8 +63,7 @@ processACKResponseAsync(void *application, UA_SecureChannel *channel,
|
||||
}
|
||||
|
||||
client->connectStatus =
|
||||
UA_Connection_processHELACK(channel->connection, &client->config.localConnectionConfig,
|
||||
(const UA_ConnectionConfig*)&ackMessage);
|
||||
UA_SecureChannel_processHELACK(channel, (const UA_ConnectionConfig*)&ackMessage);
|
||||
if(client->connectStatus != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"Processing the ACK message failed with StatusCode %s",
|
||||
@ -607,6 +606,7 @@ UA_Client_connect_async(UA_Client *client, const char *endpointUrl,
|
||||
client->channel.state = UA_SECURECHANNELSTATE_FRESH;
|
||||
client->channel.sendSequenceNumber = 0;
|
||||
client->requestId = 0;
|
||||
client->channel.config = client->config.localConnectionConfig;
|
||||
|
||||
UA_String_deleteMembers(&client->endpointUrl);
|
||||
client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
|
||||
|
@ -127,7 +127,9 @@ UA_SecureChannelManager_create(UA_SecureChannelManager *cm, UA_Connection *conne
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
|
||||
/* Channel state is fresh (0) */
|
||||
UA_SecureChannel_init(&entry->channel);
|
||||
/* TODO: Use the connection config from the correct network layer */
|
||||
UA_SecureChannel_init(&entry->channel,
|
||||
&cm->server->config.networkLayers[0].localConnectionConfig);
|
||||
entry->channel.securityToken.channelId = 0;
|
||||
entry->channel.securityToken.createdAt = UA_DateTime_now();
|
||||
entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <open62541/transport_generated_handling.h>
|
||||
#include <open62541/types_generated_encoding_binary.h>
|
||||
#include <open62541/types_generated_handling.h>
|
||||
#include "open62541/plugin/network.h"
|
||||
|
||||
#include "ua_securechannel_manager.h"
|
||||
#include "ua_server_internal.h"
|
||||
@ -279,7 +280,7 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
|
||||
|
||||
/* HEL -> Open up the connection */
|
||||
static UA_StatusCode
|
||||
processHEL(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg) {
|
||||
processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *msg) {
|
||||
size_t offset = 8; /* Go to the beginning of the TcpHelloMessage */
|
||||
UA_TcpHelloMessage helloMessage;
|
||||
UA_StatusCode retval = UA_TcpHelloMessage_decodeBinary(msg, &offset, &helloMessage);
|
||||
@ -289,11 +290,6 @@ processHEL(UA_Server *server, UA_Connection *connection, const UA_ByteString *ms
|
||||
/* Currently not checked */
|
||||
UA_String_clear(&helloMessage.endpointUrl);
|
||||
|
||||
/* TODO: Use the config of the exact NetworkLayer */
|
||||
if(server->config.networkLayersSize == 0)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
const UA_ConnectionConfig *localConfig = &server->config.networkLayers[0].localConnectionConfig;
|
||||
|
||||
/* Parameterize the connection */
|
||||
UA_ConnectionConfig remoteConfig;
|
||||
remoteConfig.protocolVersion = helloMessage.protocolVersion;
|
||||
@ -301,32 +297,33 @@ processHEL(UA_Server *server, UA_Connection *connection, const UA_ByteString *ms
|
||||
remoteConfig.recvBufferSize = helloMessage.receiveBufferSize;
|
||||
remoteConfig.maxMessageSize = helloMessage.maxMessageSize;
|
||||
remoteConfig.maxChunkCount = helloMessage.maxChunkCount;
|
||||
retval = UA_Connection_processHELACK(connection, localConfig, &remoteConfig);
|
||||
retval = UA_SecureChannel_processHELACK(channel, &remoteConfig);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"Connection %i | Error during the HEL/ACK handshake",
|
||||
(int)(connection->sockfd));
|
||||
(int)(channel->connection->sockfd));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Build acknowledge response */
|
||||
UA_TcpAcknowledgeMessage ackMessage;
|
||||
memcpy(&ackMessage, &connection->config, sizeof(UA_TcpAcknowledgeMessage)); /* Same struct layout.. */
|
||||
memcpy(&ackMessage, &channel->config, sizeof(UA_TcpAcknowledgeMessage)); /* Same struct layout.. */
|
||||
UA_TcpMessageHeader ackHeader;
|
||||
ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL;
|
||||
ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */
|
||||
|
||||
UA_Connection *connection = channel->connection;
|
||||
|
||||
/* Get the send buffer from the network layer */
|
||||
UA_ByteString ack_msg;
|
||||
UA_ByteString_init(&ack_msg);
|
||||
retval = connection->getSendBuffer(connection, connection->config.sendBufferSize, &ack_msg);
|
||||
retval = connection->getSendBuffer(connection, channel->config.sendBufferSize, &ack_msg);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
|
||||
/* Encode and send the response */
|
||||
UA_Byte *bufPos = ack_msg.data;
|
||||
const UA_Byte *bufEnd = &ack_msg.data[ack_msg.length];
|
||||
|
||||
retval = UA_TcpMessageHeader_encodeBinary(&ackHeader, &bufPos, bufEnd);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
connection->releaseSendBuffer(connection, &ack_msg);
|
||||
@ -732,7 +729,7 @@ processSecureChannelMessage(void *application, UA_SecureChannel *channel,
|
||||
switch(messagetype) {
|
||||
case UA_MESSAGETYPE_HEL:
|
||||
UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a HEL message");
|
||||
retval = processHEL(server, channel->connection, message);
|
||||
retval = processHEL(server, channel, message);
|
||||
break;
|
||||
case UA_MESSAGETYPE_OPN:
|
||||
UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process an OPN message");
|
||||
|
@ -164,8 +164,7 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
|
||||
|
||||
/* Fill the session information */
|
||||
newSession->maxResponseMessageSize = request->maxResponseMessageSize;
|
||||
newSession->maxRequestMessageSize =
|
||||
channel->connection->config.maxMessageSize;
|
||||
newSession->maxRequestMessageSize = channel->config.maxMessageSize;
|
||||
response->responseHeader.serviceResult |=
|
||||
UA_ApplicationDescription_copy(&request->clientDescription,
|
||||
&newSession->clientDescription);
|
||||
|
@ -20,37 +20,6 @@
|
||||
#include "ua_types_encoding_binary.h"
|
||||
#include "ua_util_internal.h"
|
||||
|
||||
UA_StatusCode
|
||||
UA_Connection_processHELACK(UA_Connection *connection,
|
||||
const UA_ConnectionConfig *localConfig,
|
||||
const UA_ConnectionConfig *remoteConfig) {
|
||||
connection->config = *remoteConfig;
|
||||
|
||||
/* The lowest common version is used by both sides */
|
||||
if(connection->config.protocolVersion > localConfig->protocolVersion)
|
||||
connection->config.protocolVersion = localConfig->protocolVersion;
|
||||
|
||||
/* Can we receive the max send size? */
|
||||
if(connection->config.sendBufferSize > localConfig->recvBufferSize)
|
||||
connection->config.sendBufferSize = localConfig->recvBufferSize;
|
||||
|
||||
/* Can we send the max receive size? */
|
||||
if(connection->config.recvBufferSize > localConfig->sendBufferSize)
|
||||
connection->config.recvBufferSize = localConfig->sendBufferSize;
|
||||
|
||||
/* Chunks of at least 8192 bytes must be permissible.
|
||||
* See Part 6, Clause 6.7.1 */
|
||||
if(connection->config.recvBufferSize < 8192 ||
|
||||
connection->config.sendBufferSize < 8192 ||
|
||||
(connection->config.maxMessageSize != 0 &&
|
||||
connection->config.maxMessageSize < 8192))
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
connection->state = UA_CONNECTION_ESTABLISHED;
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
/* Hides some errors before sending them to a client according to the
|
||||
* standard. */
|
||||
static void
|
||||
|
@ -16,13 +16,6 @@
|
||||
|
||||
_UA_BEGIN_DECLS
|
||||
|
||||
/* Process the remote configuration in the HEL/ACK handshake. The connection
|
||||
* config is initialized with the local settings. */
|
||||
UA_StatusCode
|
||||
UA_Connection_processHELACK(UA_Connection *connection,
|
||||
const UA_ConnectionConfig *localConfig,
|
||||
const UA_ConnectionConfig *remoteConfig);
|
||||
|
||||
/* When a fatal error occurs the Server shall send an Error Message to the
|
||||
* Client and close the socket. When a Client encounters one of these errors, it
|
||||
* shall also close the socket but does not send an Error Message. After the
|
||||
|
@ -31,12 +31,13 @@ UA_StatusCode sendAsym_sendFailure;
|
||||
UA_StatusCode processSym_seqNumberFailure;
|
||||
#endif
|
||||
|
||||
void
|
||||
UA_SecureChannel_init(UA_SecureChannel *channel) {
|
||||
void UA_SecureChannel_init(UA_SecureChannel *channel,
|
||||
const UA_ConnectionConfig *config) {
|
||||
/* Linked lists are also initialized by zeroing out */
|
||||
memset(channel, 0, sizeof(UA_SecureChannel));
|
||||
channel->state = UA_SECURECHANNELSTATE_FRESH;
|
||||
TAILQ_INIT(&channel->messages);
|
||||
channel->config = *config;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
@ -143,7 +144,8 @@ UA_SecureChannel_deleteMembers(UA_SecureChannel *channel) {
|
||||
/* Remove the buffered messages */
|
||||
UA_SecureChannel_deleteMessages(channel);
|
||||
UA_ByteString_clear(&channel->incompleteChunk);
|
||||
UA_SecureChannel_init(channel);
|
||||
UA_ConnectionConfig oldConfig = channel->config;
|
||||
UA_SecureChannel_init(channel, &oldConfig);
|
||||
}
|
||||
|
||||
void
|
||||
@ -166,6 +168,36 @@ UA_SecureChannel_close(UA_SecureChannel *channel) {
|
||||
}
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
|
||||
const UA_ConnectionConfig *remoteConfig) {
|
||||
channel->config = *remoteConfig;
|
||||
|
||||
/* The lowest common version is used by both sides */
|
||||
if(channel->config.protocolVersion > remoteConfig->protocolVersion)
|
||||
channel->config.protocolVersion = remoteConfig->protocolVersion;
|
||||
|
||||
/* Can we receive the max send size? */
|
||||
if(channel->config.sendBufferSize > channel->config.recvBufferSize)
|
||||
channel->config.sendBufferSize = channel->config.recvBufferSize;
|
||||
|
||||
/* Can we send the max receive size? */
|
||||
if(channel->config.recvBufferSize > channel->config.sendBufferSize)
|
||||
channel->config.recvBufferSize = channel->config.sendBufferSize;
|
||||
|
||||
/* Chunks of at least 8192 bytes must be permissible.
|
||||
* See Part 6, Clause 6.7.1 */
|
||||
if(channel->config.recvBufferSize < 8192 ||
|
||||
channel->config.sendBufferSize < 8192 ||
|
||||
(channel->config.maxMessageSize != 0 &&
|
||||
channel->config.maxMessageSize < 8192))
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
channel->connection->state = UA_CONNECTION_ESTABLISHED;
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
UA_SessionHeader *
|
||||
UA_SecureChannel_getSession(UA_SecureChannel *channel,
|
||||
const UA_NodeId *authenticationToken) {
|
||||
@ -191,7 +223,7 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
|
||||
/* Allocate the message buffer */
|
||||
UA_ByteString buf = UA_BYTESTRING_NULL;
|
||||
UA_StatusCode retval =
|
||||
connection->getSendBuffer(connection, connection->config.sendBufferSize, &buf);
|
||||
connection->getSendBuffer(connection, channel->config.sendBufferSize, &buf);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
|
||||
@ -253,25 +285,22 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Will this chunk surpass the capacity of the SecureChannel for the message? */
|
||||
static UA_StatusCode
|
||||
checkLimitsSym(UA_MessageContext *const messageContext, size_t *const bodyLength) {
|
||||
/* Will this chunk surpass the capacity of the SecureChannel for the message? */
|
||||
UA_Connection *const connection = messageContext->channel->connection;
|
||||
if(!connection)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
UA_Byte *buf_body_start = messageContext->messageBuffer.data + UA_SECURE_MESSAGE_HEADER_LENGTH;
|
||||
const UA_Byte *buf_body_end = messageContext->buf_pos;
|
||||
checkLimitsSym(UA_MessageContext *const mc, size_t *const bodyLength) {
|
||||
UA_Byte *buf_body_start = mc->messageBuffer.data + UA_SECURE_MESSAGE_HEADER_LENGTH;
|
||||
const UA_Byte *buf_body_end = mc->buf_pos;
|
||||
*bodyLength = (uintptr_t)buf_body_end - (uintptr_t)buf_body_start;
|
||||
messageContext->messageSizeSoFar += *bodyLength;
|
||||
messageContext->chunksSoFar++;
|
||||
mc->messageSizeSoFar += *bodyLength;
|
||||
mc->chunksSoFar++;
|
||||
|
||||
if(messageContext->messageSizeSoFar > connection->config.maxMessageSize &&
|
||||
connection->config.maxMessageSize != 0)
|
||||
UA_SecureChannel *channel = mc->channel;
|
||||
if(mc->messageSizeSoFar > channel->config.maxMessageSize &&
|
||||
channel->config.maxMessageSize != 0)
|
||||
return UA_STATUSCODE_BADRESPONSETOOLARGE;
|
||||
|
||||
if(messageContext->chunksSoFar > connection->config.maxChunkCount &&
|
||||
connection->config.maxChunkCount != 0)
|
||||
if(mc->chunksSoFar > channel->config.maxChunkCount &&
|
||||
channel->config.maxChunkCount != 0)
|
||||
return UA_STATUSCODE_BADRESPONSETOOLARGE;
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
@ -340,7 +369,7 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
|
||||
total_length += securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
|
||||
getLocalSignatureSize(securityPolicy, channel->channelContext);
|
||||
/* Space for the padding and the signature have been reserved in setBufPos() */
|
||||
UA_assert(total_length <= connection->config.sendBufferSize);
|
||||
UA_assert(total_length <= channel->config.sendBufferSize);
|
||||
|
||||
/* For giving the buffer to the network layer */
|
||||
messageContext->messageBuffer.length = total_length;
|
||||
@ -386,7 +415,7 @@ sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos, const UA_Byte **buf
|
||||
if(!connection)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
retval = connection->getSendBuffer(connection, connection->config.sendBufferSize,
|
||||
retval = connection->getSendBuffer(connection, mc->channel->config.sendBufferSize,
|
||||
&mc->messageBuffer);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
@ -419,7 +448,7 @@ UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
|
||||
|
||||
/* Allocate the message buffer */
|
||||
UA_StatusCode retval =
|
||||
connection->getSendBuffer(connection, connection->config.sendBufferSize,
|
||||
connection->getSendBuffer(connection, channel->config.sendBufferSize,
|
||||
&mc->messageBuffer);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
@ -518,9 +547,7 @@ addChunkPayload(UA_SecureChannel *channel, UA_UInt32 requestId,
|
||||
}
|
||||
|
||||
/* Test against the connection settings */
|
||||
const UA_ConnectionConfig *config = &channel->connection->config;
|
||||
UA_assert(config != NULL); /* clang-analyzer false positive */
|
||||
|
||||
const UA_ConnectionConfig *config = &channel->config;
|
||||
if(config->maxChunkCount > 0 &&
|
||||
config->maxChunkCount <= latest->chunkPayloadsSize)
|
||||
return UA_STATUSCODE_BADRESPONSETOOLARGE;
|
||||
@ -781,14 +808,14 @@ processChunk(UA_SecureChannel *channel, const UA_ByteString *packet,
|
||||
UA_TcpMessageHeader hdr;
|
||||
UA_TcpMessageHeader_decodeBinary(packet, &initial_offset, &hdr);
|
||||
UA_MessageType msgType = (UA_MessageType)
|
||||
hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE;
|
||||
(hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
|
||||
UA_ChunkType chunkType = (UA_ChunkType)
|
||||
(hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
|
||||
|
||||
/* The message size is not allowed */
|
||||
if(hdr.messageSize < 16)
|
||||
return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
|
||||
if(hdr.messageSize > channel->connection->config.recvBufferSize)
|
||||
if(hdr.messageSize > channel->config.recvBufferSize)
|
||||
return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
|
||||
|
||||
/* Incomplete chunk */
|
||||
|
@ -73,6 +73,7 @@ typedef TAILQ_HEAD(UA_MessageQueue, UA_Message) UA_MessageQueue;
|
||||
struct UA_SecureChannel {
|
||||
UA_SecureChannelState state;
|
||||
UA_MessageSecurityMode securityMode;
|
||||
UA_ConnectionConfig config;
|
||||
|
||||
/* Rules for revolving the token with a renew OPN request: The client is
|
||||
* allowed to accept messages with the old token until the OPN response has
|
||||
@ -110,10 +111,17 @@ struct UA_SecureChannel {
|
||||
* messages */
|
||||
};
|
||||
|
||||
void UA_SecureChannel_init(UA_SecureChannel *channel);
|
||||
void UA_SecureChannel_init(UA_SecureChannel *channel,
|
||||
const UA_ConnectionConfig *config);
|
||||
|
||||
void UA_SecureChannel_close(UA_SecureChannel *channel);
|
||||
|
||||
/* Process the remote configuration in the HEL/ACK handshake. The connection
|
||||
* config is initialized with the local settings. */
|
||||
UA_StatusCode
|
||||
UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
|
||||
const UA_ConnectionConfig *remoteConfig);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
|
||||
const UA_SecurityPolicy *securityPolicy,
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <open62541/transport_generated_handling.h>
|
||||
#include <open62541/types_generated.h>
|
||||
#include <open62541/types_generated_encoding_binary.h>
|
||||
#include <open62541/server_config_default.h>
|
||||
|
||||
#include "ua_securechannel.h"
|
||||
#include <ua_types_encoding_binary.h>
|
||||
@ -41,7 +42,7 @@ static key_sizes keySizes;
|
||||
static void
|
||||
setup_secureChannel(void) {
|
||||
TestingPolicy(&dummyPolicy, dummyCertificate, &fCalled, &keySizes);
|
||||
UA_SecureChannel_init(&testChannel);
|
||||
UA_SecureChannel_init(&testChannel, &UA_ConnectionConfig_default);
|
||||
UA_SecureChannel_setSecurityPolicy(&testChannel, &dummyPolicy, &dummyCertificate);
|
||||
|
||||
testingConnection = createDummyConnection(65535, &sentData);
|
||||
@ -95,7 +96,7 @@ START_TEST(SecureChannel_initAndDelete) {
|
||||
UA_StatusCode retval;
|
||||
|
||||
UA_SecureChannel channel;
|
||||
UA_SecureChannel_init(&channel);
|
||||
UA_SecureChannel_init(&channel, &UA_ConnectionConfig_default);
|
||||
retval = UA_SecureChannel_setSecurityPolicy(&channel, &dummyPolicy, &dummyCertificate);
|
||||
|
||||
ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected StatusCode to be good");
|
||||
|
@ -179,7 +179,7 @@ START_TEST(Client_renewSecureChannel) {
|
||||
UA_Variant val;
|
||||
UA_NodeId nodeId = UA_NODEID_STRING(1, "my.variable");
|
||||
retval = UA_Client_readValueAttribute(client, nodeId, &val);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
ck_assert_msg(retval == UA_STATUSCODE_GOOD, UA_StatusCode_name(retval));
|
||||
UA_Variant_deleteMembers(&val);
|
||||
|
||||
UA_Client_disconnect(client);
|
||||
|
@ -62,6 +62,5 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
UA_Server_run_shutdown(server);
|
||||
UA_Server_delete(server);
|
||||
c.close(&c);
|
||||
UA_Connection_clear(&c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (status >= 0) {
|
||||
if (write(sockfd, data, size) != size) {
|
||||
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
|
||||
"Did not write %d bytes", size);
|
||||
"Did not write %lu bytes", (long unsigned)size);
|
||||
retCode = EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
|
@ -28,7 +28,7 @@ static void setup(void) {
|
||||
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
|
||||
|
||||
TestingPolicy(&dummyPolicy, UA_BYTESTRING_NULL, &funcsCalled, &keySizes);
|
||||
UA_SecureChannel_init(&testChannel);
|
||||
UA_SecureChannel_init(&testChannel, &UA_ConnectionConfig_default);
|
||||
UA_SecureChannel_setSecurityPolicy(&testChannel, &dummyPolicy, &UA_BYTESTRING_NULL);
|
||||
|
||||
testingConnection = createDummyConnection(65535, NULL);
|
||||
|
@ -27,7 +27,7 @@ static void setup(void) {
|
||||
server = UA_Server_new();
|
||||
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
|
||||
TestingPolicy(&dummyPolicy, UA_BYTESTRING_NULL, &funcsCalled, &keySizes);
|
||||
UA_SecureChannel_init(&testChannel);
|
||||
UA_SecureChannel_init(&testChannel, &UA_ConnectionConfig_default);
|
||||
UA_SecureChannel_setSecurityPolicy(&testChannel, &dummyPolicy, &UA_BYTESTRING_NULL);
|
||||
testingConnection = createDummyConnection(65535, NULL);
|
||||
UA_Connection_attachSecureChannel(&testingConnection, &testChannel);
|
||||
|
@ -59,7 +59,6 @@ UA_Connection createDummyConnection(size_t sendBufferSize,
|
||||
|
||||
UA_Connection c;
|
||||
c.state = UA_CONNECTION_ESTABLISHED;
|
||||
c.config = UA_ConnectionConfig_default;
|
||||
c.channel = NULL;
|
||||
c.sockfd = 0;
|
||||
c.handle = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user