Coverage Report

Created: 2026-09-27 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/src/ua_securechannel.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2014, 2016-2017 (c) Florian Palm
7
 *    Copyright 2015-2016 (c) Sten GrĂ¼ner
8
 *    Copyright 2015 (c) Oleksiy Vasylyev
9
 *    Copyright 2016 (c) TorbenD
10
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
11
 *    Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
12
 *    Copyright 2018-2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
13
 *    Copyright 2025 (c) o6 Automation GmbH (Author: Julius Pfrommer)
14
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Andreas Ebner)
15
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Julius Pfrommer)
16
 */
17
18
#include <open62541/types.h>
19
#include <open62541/transport_generated.h>
20
21
#include "ua_securechannel.h"
22
#include "ua_types_encoding_binary.h"
23
24
0
#define UA_BITMASK_MESSAGETYPE 0x00ffffffu
25
0
#define UA_BITMASK_CHUNKTYPE 0xff000000u
26
27
const UA_String UA_SECURITY_POLICY_NONE_URI =
28
    {47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"};
29
30
void
31
0
UA_SecureChannel_init(UA_SecureChannel *channel) {
32
    /* Normal linked lists are initialized by zeroing out */
33
0
    memset(channel, 0, sizeof(UA_SecureChannel));
34
0
    channel->transport = UA_SECURECHANNEL_TRANSPORT_UACP;
35
0
    channel->encoding = UA_SECURECHANNEL_ENCODING_BINARY;
36
0
    TAILQ_INIT(&channel->chunks);
37
0
}
38
39
static UA_StatusCode
40
setSecurityPolicy(UA_SecureChannel *channel, UA_SecurityPolicy *sp,
41
                  const UA_ByteString *remoteCertificate,
42
                  UA_MessageSecurityMode securityMode,
43
0
                  UA_Boolean createContext) {
44
    /* Is a policy already configured? */
45
0
    UA_CHECK_ERROR(!channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
46
0
                   sp->logger, UA_LOGCATEGORY_SECURITYPOLICY,
47
0
                   "Security policy already configured");
48
49
    /* Build all fallible state locally so a failure leaves the channel
50
     * untouched and therefore safely clearable. */
51
0
    void *channelContext = NULL;
52
0
    UA_ByteString certificate = UA_BYTESTRING_NULL;
53
0
    UA_Byte thumbprint[20] = {0};
54
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
55
0
    if(createContext)
56
0
        res = sp->newChannelContext(sp, remoteCertificate, &channelContext);
57
0
    if(res == UA_STATUSCODE_GOOD && remoteCertificate)
58
0
        res = UA_ByteString_copy(remoteCertificate, &certificate);
59
0
    if(res == UA_STATUSCODE_GOOD && certificate.length > 0) {
60
0
        UA_ByteString thumbprintString = {sizeof(thumbprint), thumbprint};
61
0
        res = sp->makeCertThumbprint(sp, &certificate, &thumbprintString);
62
0
    }
63
0
    if(res != UA_STATUSCODE_GOOD) {
64
0
        if(channelContext)
65
0
            sp->deleteChannelContext(sp, channelContext);
66
0
        UA_ByteString_clear(&certificate);
67
0
        UA_LOG_ERROR(sp->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68
0
                     "Could not set up the SecureChannel policy");
69
0
        return res;
70
0
    }
71
72
    /* Set the SecurityPolicy and cache the URI-derived properties (the policy
73
     * is fixed for the channel's lifetime). */
74
0
    channel->securityPolicy = sp;
75
0
    channel->channelContext = channelContext;
76
0
    channel->remoteCertificate = certificate;
77
0
    memcpy(channel->remoteCertificateThumbprint, thumbprint,
78
0
           sizeof(thumbprint));
79
0
    channel->enhancedSecurity = UA_SecurityPolicy_isEnhancedSecurity(sp);
80
0
    channel->legacySequenceNumbers = UA_SecurityPolicy_useLegacySequenceNumbers(sp);
81
0
    channel->securityMode = securityMode;
82
0
    return UA_STATUSCODE_GOOD;
83
0
}
84
85
UA_StatusCode
86
UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
87
                                   UA_SecurityPolicy *sp,
88
0
                                   const UA_ByteString *remoteCertificate) {
89
0
    UA_MessageSecurityMode mode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
90
0
    if(sp->policyType == UA_SECURITYPOLICYTYPE_NONE)
91
0
        mode = UA_MESSAGESECURITYMODE_NONE;
92
0
    return setSecurityPolicy(channel, sp, remoteCertificate, mode, true);
93
0
}
94
95
UA_StatusCode
96
UA_SecureChannel_setSecurityPolicyWithoutOPN(
97
    UA_SecureChannel *channel, UA_SecurityPolicy *sp,
98
    const UA_ByteString *remoteCertificate,
99
0
    UA_MessageSecurityMode securityMode) {
100
    /* Enhanced SecurityPolicies bind Session signatures to values exchanged in
101
     * OPN. A direct transport cannot establish that binding. */
102
0
    if(UA_SecurityPolicy_isEnhancedSecurity(sp))
103
0
        return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
104
0
    UA_Boolean createContext =
105
0
        remoteCertificate && remoteCertificate->length > 0;
106
0
    return setSecurityPolicy(channel, sp, remoteCertificate, securityMode,
107
0
                             createContext);
108
0
}
109
110
/* The #None SecurityPolicy must use the NONE SecurityMode. All other
111
 * SecurityPolicies must not. */
112
UA_StatusCode
113
UA_SecureChannel_setSecurityMode(UA_SecureChannel *channel,
114
0
                                 UA_MessageSecurityMode securityMode) {
115
0
    if(securityMode == UA_MESSAGESECURITYMODE_INVALID ||
116
0
       securityMode > UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
117
0
        return UA_STATUSCODE_BADSECURITYMODEREJECTED;
118
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
119
0
    if(!sp)
120
0
        return UA_STATUSCODE_BADSECURITYMODEREJECTED;
121
0
    UA_Boolean isNonePolicy = (sp->policyType == UA_SECURITYPOLICYTYPE_NONE);
122
0
    UA_Boolean isNoneMode = (securityMode == UA_MESSAGESECURITYMODE_NONE);
123
0
    if(isNonePolicy != isNoneMode)
124
0
        return UA_STATUSCODE_BADSECURITYMODEREJECTED;
125
0
    channel->securityMode = securityMode;
126
0
    return UA_STATUSCODE_GOOD;
127
0
}
128
129
/* Hides some errors before sending them to a client according to the
130
 * standard. */
131
static void
132
0
hideErrors(UA_TcpErrorMessage *const error) {
133
0
    switch(error->error) {
134
0
    case UA_STATUSCODE_BADCERTIFICATEINVALID:
135
0
    case UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE:
136
0
    case UA_STATUSCODE_BADCERTIFICATEPOLICYCHECKFAILED:
137
0
    case UA_STATUSCODE_BADCERTIFICATEUNTRUSTED:
138
0
    case UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN:
139
0
    case UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN:
140
0
    case UA_STATUSCODE_BADCERTIFICATEREVOKED:
141
0
    case UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED:
142
0
    case UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED:
143
0
        error->error = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
144
0
        error->reason = UA_STRING_NULL;
145
0
        break;
146
        // TODO: Check if these are all cases that need to be covered.
147
0
    default:
148
0
        break;
149
0
    }
150
0
}
151
152
UA_Boolean
153
0
UA_SecureChannel_isConnected(UA_SecureChannel *channel) {
154
0
    return (channel->state > UA_SECURECHANNELSTATE_CLOSED &&
155
0
            channel->state < UA_SECURECHANNELSTATE_CLOSING);
156
0
}
157
158
void
159
0
UA_SecureChannel_sendERR(UA_SecureChannel *channel, UA_TcpErrorMessage *error) {
160
0
    if(!UA_SecureChannel_isConnected(channel))
161
0
        return;
162
    /* HTTP has status codes and service faults, but no UACP ERR frame. */
163
0
    if(channel->transport == UA_SECURECHANNEL_TRANSPORT_HTTP)
164
0
        return;
165
166
0
    hideErrors(error);
167
168
0
    UA_TcpMessageHeader header;
169
0
    header.messageTypeAndChunkType = UA_MESSAGETYPE_ERR + UA_CHUNKTYPE_FINAL;
170
    /* Header + ErrorMessage (error + reasonLength_field + length) */
171
0
    header.messageSize = 8 + (4 + 4 + (UA_UInt32)error->reason.length);
172
173
    /* Get the send buffer from the network layer */
174
0
    UA_ConnectionManager *cm = channel->connectionManager;
175
0
    UA_ByteString msg = UA_BYTESTRING_NULL;
176
0
    UA_StatusCode retval = cm->allocNetworkBuffer(cm, channel->connectionId,
177
0
                                                  &msg, header.messageSize);
178
0
    if(retval != UA_STATUSCODE_GOOD)
179
0
        return;
180
181
    /* Encode and send the response */
182
0
    UA_Byte *bufPos = msg.data;
183
0
    const UA_Byte *bufEnd = &msg.data[msg.length];
184
0
    retval |= UA_encodeBinaryInternal(&header,
185
0
                                      &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
186
0
                                      &bufPos, &bufEnd, NULL, NULL, NULL);
187
0
    retval |= UA_encodeBinaryInternal(error,
188
0
                                      &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE],
189
0
                                      &bufPos, &bufEnd, NULL, NULL, NULL);
190
0
    (void)retval; /* Encoding of these cannot fail */
191
0
    msg.length = header.messageSize;
192
0
    cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &msg);
193
0
}
194
195
static void
196
0
UA_Chunk_delete(UA_Chunk *chunk) {
197
0
    if(chunk->copied)
198
0
        UA_ByteString_clear(&chunk->bytes);
199
0
    UA_free(chunk);
200
0
}
201
202
static void
203
0
deleteChunks(UA_SecureChannel *channel) {
204
0
    UA_Chunk *chunk, *chunk_tmp;
205
0
    TAILQ_FOREACH_SAFE(chunk, &channel->chunks, pointers, chunk_tmp) {
206
0
        TAILQ_REMOVE(&channel->chunks, chunk, pointers);
207
0
        UA_Chunk_delete(chunk);
208
0
    }
209
0
    channel->chunksCount = 0;
210
0
    channel->chunksLength = 0;
211
0
}
212
213
void
214
0
UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel) {
215
0
    deleteChunks(channel);
216
0
    if(channel->unprocessedCopied)
217
0
        UA_ByteString_clear(&channel->unprocessed);
218
0
}
219
220
void
221
UA_SecureChannel_shutdown(UA_SecureChannel *channel,
222
0
                          UA_ShutdownReason shutdownReason) {
223
    /* No open channel or already closing -> nothing to do */
224
0
    if(!UA_SecureChannel_isConnected(channel))
225
0
        return;
226
227
    /* Set the shutdown event for diagnostics */
228
0
    channel->shutdownReason = shutdownReason;
229
0
    channel->state = UA_SECURECHANNELSTATE_CLOSING;
230
231
    /* Direct transports such as HTTP have no persistent ConnectionManager
232
     * connection owned by the SecureChannel. Their transport owner performs
233
     * the remaining teardown after the common state transition above. */
234
0
    UA_ConnectionManager *cm = channel->connectionManager;
235
0
    if(!cm || channel->connectionId == 0)
236
0
        return;
237
238
    /* Trigger the async closing of the connection */
239
0
    cm->closeConnection(cm, channel->connectionId);
240
0
}
241
242
void
243
0
UA_SecureChannel_clear(UA_SecureChannel *channel) {
244
    /* No sessions must be attached to this any longer */
245
0
    UA_assert(channel->sessions == NULL);
246
247
    /* Delete the channel context for the security policy */
248
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
249
0
    if(sp) {
250
0
        if(channel->channelContext)
251
0
            sp->deleteChannelContext(sp, channel->channelContext);
252
0
        channel->securityPolicy = NULL;
253
0
        channel->channelContext = NULL;
254
0
        channel->enhancedSecurity = false;     /* No policy => not enhanced */
255
0
        channel->legacySequenceNumbers = true; /* No policy => legacy */
256
0
    }
257
258
    /* Remove remaining delayed callback */
259
0
    if(channel->connectionManager &&
260
0
       channel->connectionManager->eventSource.eventLoop) {
261
0
        UA_EventLoop *el = channel->connectionManager->eventSource.eventLoop;
262
0
        el->removeDelayedCallback(el, &channel->unprocessedDelayed);
263
0
    }
264
265
    /* The EventLoop connection is no longer valid */
266
0
    channel->connectionId = 0;
267
0
    channel->connectionManager = NULL;
268
269
    /* Clean up the SecurityToken */
270
0
    UA_ChannelSecurityToken_clear(&channel->securityToken);
271
0
    UA_ChannelSecurityToken_clear(&channel->altSecurityToken);
272
273
    /* Clean up certificate and nonces */
274
0
    UA_ByteString_clear(&channel->remoteCertificate);
275
0
    UA_ByteString_clear(&channel->localNonce);
276
0
    UA_ByteString_clear(&channel->remoteNonce);
277
278
    /* Clean up the v1.05.07 SecureChannel elements */
279
0
    UA_ByteString_clear(&channel->firstRequestSignature);
280
0
    UA_ByteString_clear(&channel->currentIKM);
281
0
    UA_ByteString_clear(&channel->channelThumbprint);
282
283
    /* Clean up endpointUrl and remoteAddress */
284
0
    UA_String_clear(&channel->endpointUrl);
285
0
    UA_String_clear(&channel->remoteAddress);
286
287
    /* Delete remaining chunks */
288
0
    UA_SecureChannel_deleteBuffered(channel);
289
290
    /* Clean up namespace mapping */
291
0
    UA_NamespaceMapping_delete(channel->namespaceMapping);
292
0
    channel->namespaceMapping = NULL;
293
294
    /* Clean up the generic per-channel attributes */
295
0
    UA_KeyValueMap_clear(&channel->attributes);
296
0
    channel->maxMessageSizeOverride = 0;
297
298
    /* Reset the SecureChannel for reuse (in the client) */
299
0
    channel->securityMode = UA_MESSAGESECURITYMODE_INVALID;
300
0
    channel->shutdownReason = UA_SHUTDOWNREASON_CLOSE;
301
0
    memset(&channel->config, 0, sizeof(UA_ConnectionConfig));
302
0
    channel->receiveSequenceNumber = 0;
303
0
    channel->sendSequenceNumber = 0;
304
305
    /* Set the state to closed */
306
0
    channel->state = UA_SECURECHANNELSTATE_CLOSED;
307
0
    channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
308
0
    channel->transport = UA_SECURECHANNEL_TRANSPORT_UACP;
309
0
    channel->encoding = UA_SECURECHANNEL_ENCODING_BINARY;
310
0
}
311
312
UA_StatusCode
313
UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
314
0
                               const UA_TcpAcknowledgeMessage *remoteConfig) {
315
    /* The lowest common version is used by both sides */
316
0
    if(channel->config.protocolVersion > remoteConfig->protocolVersion)
317
0
        channel->config.protocolVersion = remoteConfig->protocolVersion;
318
319
    /* Can we receive the max send size? */
320
0
    if(channel->config.sendBufferSize > remoteConfig->receiveBufferSize)
321
0
        channel->config.sendBufferSize = remoteConfig->receiveBufferSize;
322
323
    /* Can we send the max receive size? */
324
0
    if(channel->config.recvBufferSize > remoteConfig->sendBufferSize)
325
0
        channel->config.recvBufferSize = remoteConfig->sendBufferSize;
326
327
0
    channel->config.remoteMaxMessageSize = remoteConfig->maxMessageSize;
328
0
    channel->config.remoteMaxChunkCount = remoteConfig->maxChunkCount;
329
330
    /* Chunks of at least 8192 bytes must be permissible.
331
     * See Part 6, Clause 6.7.1 */
332
0
    if(channel->config.recvBufferSize < 8192 ||
333
0
       channel->config.sendBufferSize < 8192 ||
334
0
       (channel->config.remoteMaxMessageSize != 0 &&
335
0
        channel->config.remoteMaxMessageSize < 8192))
336
0
        return UA_STATUSCODE_BADINTERNALERROR;
337
338
0
    return UA_STATUSCODE_GOOD;
339
0
}
340
341
/* Send an OPN message using asymmetric encryption.
342
 * Specification part 6, 6.7.4: The OpenSecureChannel Messages are signed and
343
 * encrypted if the SecurityMode is not None (even if the SecurityMode is
344
 * SignOnly). */
345
UA_StatusCode
346
UA_SecureChannel_sendOPN(UA_SecureChannel *channel,
347
                         UA_UInt32 requestId, const void *content,
348
0
                         const UA_DataType *contentType) {
349
0
    if(!content || !contentType)
350
0
        return UA_STATUSCODE_BADINTERNALERROR;
351
352
    /* The SecurityPolicy must be configured before sending OPN */
353
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
354
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
355
356
    /* Check for a valid security mode */
357
0
    UA_assert(channel->securityMode > UA_MESSAGESECURITYMODE_INVALID &&
358
0
              channel->securityMode <= UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
359
360
    /* The #None SecurityPolicy must use the NONE MessageSecurityMode.
361
     * All other SecurityPolicies must not. */
362
0
    UA_assert((sp->policyType == UA_SECURITYPOLICYTYPE_NONE) ==
363
0
              (channel->securityMode == UA_MESSAGESECURITYMODE_NONE));
364
365
    /* Can we use the connection manager? */
366
0
    UA_ConnectionManager *cm = channel->connectionManager;
367
0
    if(!UA_SecureChannel_isConnected(channel))
368
0
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
369
370
    /* Allocate the message buffer */
371
0
    UA_ByteString buf = UA_BYTESTRING_NULL;
372
0
    UA_StatusCode res = cm->allocNetworkBuffer(cm, channel->connectionId, &buf,
373
0
                                               channel->config.sendBufferSize);
374
0
    UA_CHECK_STATUS(res, return res);
375
376
    /* Restrict buffer to the available space for the payload */
377
0
    UA_Byte *buf_pos = buf.data;
378
0
    const UA_Byte *buf_end = &buf.data[buf.length];
379
0
    res = hideBytesAsym(channel, &buf_pos, &buf_end);
380
0
    UA_CHECK_STATUS(res, cm->freeNetworkBuffer(cm, channel->connectionId, &buf);
381
0
                    return res);
382
383
    /* Define variables here to pacify some compilers wrt goto */
384
0
    size_t securityHeaderLength, pre_sig_length, total_length, encryptedLength;
385
386
    /* Encode the message type and content */
387
0
    UA_EncodeBinaryOptions encOpts;
388
0
    memset(&encOpts, 0, sizeof(UA_EncodeBinaryOptions));
389
0
    encOpts.namespaceMapping = channel->namespaceMapping;
390
0
    res |= UA_NodeId_encodeBinary(&contentType->binaryEncodingId, &buf_pos, buf_end);
391
0
    res |= UA_encodeBinaryInternal(content, contentType, &buf_pos, &buf_end,
392
0
                                   &encOpts, NULL, NULL);
393
0
    UA_CHECK_STATUS(res, goto error);
394
395
    /* Compute the header length */
396
0
    securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
397
398
    /* Add padding to the chunk */
399
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE)
400
0
        padChunk(channel, &sp->asymSignatureAlgorithm, &sp->asymEncryptionAlgorithm,
401
0
                 &buf.data[UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength],
402
0
                 &buf_pos);
403
404
    /* The total message length */
405
0
    pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
406
0
    total_length = pre_sig_length;
407
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE)
408
0
        total_length += sp->asymSignatureAlgorithm.
409
0
            getLocalSignatureSize(sp, channel->channelContext);
410
411
    /* The total message length is known here which is why we encode the headers
412
     * at this step and not earlier. */
413
0
    res = prependHeadersAsym(channel, buf.data, buf_end, total_length,
414
0
                             securityHeaderLength, requestId, &encryptedLength);
415
0
    UA_CHECK_STATUS(res, goto error);
416
417
    /* Add the signature and encrypt the message */
418
0
    res = signAndEncryptAsym(channel, pre_sig_length, &buf,
419
0
                             securityHeaderLength, total_length);
420
0
    UA_CHECK_STATUS(res, goto error);
421
422
    /* Send the message, the buffer is freed in the network layer */
423
0
    buf.length = encryptedLength;
424
0
    return cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &buf);
425
426
0
 error:
427
0
    cm->freeNetworkBuffer(cm, channel->connectionId, &buf);
428
0
    return res;
429
0
}
430
431
/* Will this chunk surpass the capacity of the SecureChannel for the message? */
432
static UA_StatusCode
433
0
adjustCheckMessageLimitsSym(UA_MessageContext *mc, size_t bodyLength) {
434
0
    mc->messageSizeSoFar += bodyLength;
435
0
    mc->chunksSoFar++;
436
437
0
    UA_SecureChannel *channel = mc->channel;
438
0
    if(mc->messageSizeSoFar > channel->config.localMaxMessageSize &&
439
0
       channel->config.localMaxMessageSize != 0)
440
0
        return UA_STATUSCODE_BADRESPONSETOOLARGE;
441
442
0
    if(mc->chunksSoFar > channel->config.localMaxChunkCount &&
443
0
       channel->config.localMaxChunkCount != 0)
444
0
        return UA_STATUSCODE_BADRESPONSETOOLARGE;
445
446
0
    return UA_STATUSCODE_GOOD;
447
0
}
448
449
static UA_StatusCode
450
0
encodeHeadersSym(UA_MessageContext *mc, size_t totalLength) {
451
0
    UA_SecureChannel *channel = mc->channel;
452
0
    UA_Byte *header_pos = mc->messageBuffer.data;
453
454
0
    UA_TcpMessageHeader header;
455
0
    header.messageTypeAndChunkType = mc->messageType;
456
0
    header.messageSize = (UA_UInt32)totalLength;
457
0
    if(mc->final)
458
0
        header.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
459
0
    else
460
0
        header.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
461
462
0
    UA_SequenceHeader seqHeader;
463
0
    seqHeader.requestId = mc->requestId;
464
0
    seqHeader.sequenceNumber = UA_SecureChannel_nextSequenceNumber(channel);
465
466
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
467
0
    res |= UA_encodeBinaryInternal(&header, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
468
0
                                   &header_pos, &mc->buf_end, NULL, NULL, NULL);
469
0
    res |= UA_UInt32_encodeBinary(&channel->securityToken.channelId,
470
0
                                  &header_pos, mc->buf_end);
471
0
    res |= UA_UInt32_encodeBinary(&channel->securityToken.tokenId,
472
0
                                  &header_pos, mc->buf_end);
473
0
    res |= UA_encodeBinaryInternal(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
474
0
                                   &header_pos, &mc->buf_end, NULL, NULL, NULL);
475
0
    return res;
476
0
}
477
478
static UA_StatusCode
479
0
sendSymmetricChunk(UA_MessageContext *mc) {
480
0
    UA_SecureChannel *channel = mc->channel;
481
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
482
0
    UA_ConnectionManager *cm = channel->connectionManager;
483
0
    if(!UA_SecureChannel_isConnected(channel))
484
0
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
485
486
    /* The size of the message payload */
487
0
    size_t bodyLength = (uintptr_t)mc->buf_pos -
488
0
        (uintptr_t)&mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
489
490
    /* Early-declare variables so we can use a goto in the error case */
491
0
    size_t total_length = 0;
492
0
    size_t pre_sig_length = 0;
493
494
    /* Check if chunk exceeds the limits for the overall message */
495
0
    UA_StatusCode res = adjustCheckMessageLimitsSym(mc, bodyLength);
496
0
    UA_CHECK_STATUS(res, goto error);
497
498
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
499
0
                         "Send from a symmetric message buffer of length %lu "
500
0
                         "a message of header+payload length of %lu",
501
0
                         (long unsigned int)mc->messageBuffer.length,
502
0
                         (long unsigned int)
503
0
                         ((uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data));
504
505
    /* Add padding if the message is encrypted (not for AEAD policies) */
506
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
507
0
       !UA_SecurityPolicy_isAead(sp))
508
0
        padChunk(channel, &sp->symSignatureAlgorithm, &sp->symEncryptionAlgorithm,
509
0
                 &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH],
510
0
                 &mc->buf_pos);
511
512
    /* Compute the total message length */
513
0
    pre_sig_length = (uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data;
514
0
    total_length = pre_sig_length;
515
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
516
0
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
517
0
        total_length += sp->symSignatureAlgorithm.
518
0
            getLocalSignatureSize(sp, channel->channelContext);
519
520
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
521
0
                         "Send from a symmetric message buffer of length %lu "
522
0
                         "a message of length %lu",
523
0
                         (long unsigned int)mc->messageBuffer.length,
524
0
                         (long unsigned int)total_length);
525
526
    /* Space for the padding and the signature have been reserved in setBufPos() */
527
0
    UA_assert(total_length <= channel->config.sendBufferSize);
528
529
    /* Adjust the buffer size of the network layer */
530
0
    mc->messageBuffer.length = total_length;
531
532
    /* Generate and encode the header for symmetric messages */
533
0
    res = encodeHeadersSym(mc, total_length);
534
0
    UA_CHECK_STATUS(res, goto error);
535
536
    /* Sign and encrypt the messge */
537
0
    res = signAndEncryptSym(mc, pre_sig_length, total_length);
538
0
    UA_CHECK_STATUS(res, goto error);
539
540
    /* Send the chunk. The buffer is freed in the network layer. If sending goes
541
     * wrong, the connection is removed in the next iteration of the
542
     * SecureChannel. Set the SecureChannel to closing already. */
543
0
    res = cm->sendWithConnection(cm, channel->connectionId,
544
0
                                 &UA_KEYVALUEMAP_NULL, &mc->messageBuffer);
545
0
    if(res != UA_STATUSCODE_GOOD && UA_SecureChannel_isConnected(channel))
546
0
        channel->state = UA_SECURECHANNELSTATE_CLOSING;
547
0
    return res;
548
549
0
 error:
550
    /* Free the unused message buffer */
551
0
    cm->freeNetworkBuffer(cm, channel->connectionId, &mc->messageBuffer);
552
0
    return res;
553
0
}
554
555
/* Callback from the encoding layer. Send the chunk and replace the buffer. */
556
static UA_StatusCode
557
sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos,
558
0
                              const UA_Byte **buf_end) {
559
    /* Set buf values from encoding in the messagecontext */
560
0
    UA_MessageContext *mc = (UA_MessageContext *)data;
561
0
    mc->buf_pos = *buf_pos;
562
0
    mc->buf_end = *buf_end;
563
564
    /* Send out */
565
0
    UA_StatusCode res = sendSymmetricChunk(mc);
566
0
    UA_CHECK_STATUS(res, return res);
567
568
    /* Set a new buffer for the next chunk */
569
0
    UA_ConnectionManager *cm = mc->channel->connectionManager;
570
0
    if(!UA_SecureChannel_isConnected(mc->channel))
571
0
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
572
573
0
    res = cm->allocNetworkBuffer(cm, mc->channel->connectionId,
574
0
                                 &mc->messageBuffer,
575
0
                                 mc->channel->config.sendBufferSize);
576
0
    UA_CHECK_STATUS(res, return res);
577
578
    /* Hide bytes for header, padding and signature */
579
0
    setBufPos(mc);
580
0
    *buf_pos = mc->buf_pos;
581
0
    *buf_end = mc->buf_end;
582
0
    return UA_STATUSCODE_GOOD;
583
0
}
584
585
UA_StatusCode
586
UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
587
0
                        UA_UInt32 requestId, UA_MessageType messageType) {
588
0
    UA_CHECK(messageType == UA_MESSAGETYPE_MSG || messageType == UA_MESSAGETYPE_CLO,
589
0
             return UA_STATUSCODE_BADINTERNALERROR);
590
591
0
    UA_ConnectionManager *cm = channel->connectionManager;
592
0
    if(!UA_SecureChannel_isConnected(channel))
593
0
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
594
595
    /* Create the chunking info structure */
596
0
    mc->channel = channel;
597
0
    mc->requestId = requestId;
598
0
    mc->chunksSoFar = 0;
599
0
    mc->messageSizeSoFar = 0;
600
0
    mc->final = false;
601
0
    mc->messageBuffer = UA_BYTESTRING_NULL;
602
0
    mc->messageType = messageType;
603
604
    /* Allocate the message buffer */
605
0
    UA_StatusCode res =
606
0
        cm->allocNetworkBuffer(cm, channel->connectionId,
607
0
                               &mc->messageBuffer,
608
0
                               channel->config.sendBufferSize);
609
0
    UA_CHECK_STATUS(res, return res);
610
611
    /* Hide bytes for header, padding and signature */
612
0
    setBufPos(mc);
613
0
    return UA_STATUSCODE_GOOD;
614
0
}
615
616
UA_StatusCode
617
UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
618
0
                         const UA_DataType *contentType) {
619
0
    UA_EncodeBinaryOptions encOpts;
620
0
    memset(&encOpts, 0, sizeof(UA_EncodeBinaryOptions));
621
0
    encOpts.namespaceMapping = mc->channel->namespaceMapping;
622
0
    UA_StatusCode res =
623
0
        UA_encodeBinaryInternal(content, contentType, &mc->buf_pos, &mc->buf_end,
624
0
                                &encOpts, sendSymmetricEncodingCallback, mc);
625
0
    if(res != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0)
626
0
        UA_MessageContext_abort(mc);
627
0
    return res;
628
0
}
629
630
UA_StatusCode
631
0
UA_MessageContext_finish(UA_MessageContext *mc) {
632
0
    mc->final = true;
633
0
    return sendSymmetricChunk(mc);
634
0
}
635
636
void
637
0
UA_MessageContext_abort(UA_MessageContext *mc) {
638
0
    UA_ConnectionManager *cm = mc->channel->connectionManager;
639
0
    if(!UA_SecureChannel_isConnected(mc->channel))
640
0
        return;
641
0
    cm->freeNetworkBuffer(cm, mc->channel->connectionId, &mc->messageBuffer);
642
0
}
643
644
/* Send a MSG or CLO message using symmetric encryption */
645
static UA_StatusCode
646
sendSymmetric(UA_SecureChannel *channel, UA_UInt32 requestId,
647
              UA_MessageType messageType, void *payload,
648
0
              const UA_DataType *payloadType) {
649
0
    if(!channel || !payload || !payloadType)
650
0
        return UA_STATUSCODE_BADINTERNALERROR;
651
652
0
    if(channel->state != UA_SECURECHANNELSTATE_OPEN)
653
0
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
654
655
0
    UA_MessageContext mc;
656
0
    UA_StatusCode res = UA_MessageContext_begin(&mc, channel, requestId, messageType);
657
0
    UA_CHECK_STATUS(res, return res);
658
659
    /* Assert's required for clang-analyzer */
660
0
    UA_assert(mc.buf_pos ==
661
0
              &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
662
0
    UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
663
664
0
    res = UA_MessageContext_encode(&mc, &payloadType->binaryEncodingId,
665
0
                                   &UA_TYPES[UA_TYPES_NODEID]);
666
0
    UA_CHECK_STATUS(res, return res);
667
668
0
    res = UA_MessageContext_encode(&mc, payload, payloadType);
669
0
    UA_CHECK_STATUS(res, return res);
670
671
0
    return UA_MessageContext_finish(&mc);
672
0
}
673
674
UA_StatusCode
675
UA_SecureChannel_sendMSG(UA_SecureChannel *channel, UA_UInt32 requestId,
676
0
                         void *payload, const UA_DataType *payloadType) {
677
0
    if(channel && channel->transport == UA_SECURECHANNEL_TRANSPORT_HTTP)
678
0
        return UA_SecureChannel_sendMSGHttp(channel, requestId, payload,
679
0
                                            payloadType);
680
0
    return sendSymmetric(channel, requestId, UA_MESSAGETYPE_MSG,
681
0
                         payload, payloadType);
682
0
}
683
684
UA_StatusCode
685
UA_SecureChannel_sendCLO(UA_SecureChannel *channel, UA_UInt32 requestId,
686
0
                         UA_CloseSecureChannelRequest *req) {
687
    /* Direct HTTP service transport has no UACP CLO frame. */
688
0
    if(channel && channel->transport == UA_SECURECHANNEL_TRANSPORT_HTTP)
689
0
        return UA_STATUSCODE_GOOD;
690
0
    return sendSymmetric(channel, requestId, UA_MESSAGETYPE_CLO, req,
691
0
                         &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
692
0
}
693
694
/********************************/
695
/* Receive and Process Messages */
696
/********************************/
697
698
/* Does the sequence number match? Otherwise try to rollover. See Part 6,
699
 * Section 6.7.2.4 of the standard. */
700
0
#define UA_SEQUENCENUMBER_ROLLOVER 4294966271
701
702
UA_UInt32
703
0
UA_SecureChannel_nextSequenceNumber(UA_SecureChannel *channel) {
704
    /* channel->sendSequenceNumber mirrors the reference-stack counter: a
705
     * pre-increment value initialized to 0. The legacy scheme emits the
706
     * counter (first = 1); the non-legacy scheme emits counter-1 (first = 0). */
707
0
    UA_UInt64 next = (UA_UInt64)channel->sendSequenceNumber + 1;
708
0
    if(channel->legacySequenceNumbers) {
709
        /* Legacy rollover: the first number after the max is 1. */
710
0
        if(next > UA_SEQUENCENUMBER_ROLLOVER)
711
0
            next = 1;
712
0
        channel->sendSequenceNumber = (UA_UInt32)next;
713
0
        return channel->sendSequenceNumber;
714
0
    }
715
    /* Non-legacy: the counter wraps to 0 after UA_UINT32_MAX so the emitted
716
     * value (counter - 1) covers the full UInt32 range and then restarts at 0. */
717
0
    if(next > UA_UINT32_MAX)
718
0
        next = 0;
719
0
    channel->sendSequenceNumber = (UA_UInt32)next;
720
0
    return (channel->sendSequenceNumber == 0) ?
721
0
        UA_UINT32_MAX : (channel->sendSequenceNumber - 1);
722
0
}
723
724
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
725
static UA_StatusCode
726
processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
727
    if(sequenceNumber != channel->receiveSequenceNumber + 1) {
728
        /* The non-legacy (ECC) rollover from UA_UINT32_MAX to 0 is already
729
         * accepted by the check above (unsigned overflow makes
730
         * receiveSequenceNumber + 1 == 0). Only the legacy "< 1024" rollover
731
         * needs the special case below; non-legacy policies reject anything
732
         * that is not the immediate successor. */
733
        if(!channel->legacySequenceNumbers ||
734
           channel->receiveSequenceNumber + 1 <= UA_SEQUENCENUMBER_ROLLOVER ||
735
           sequenceNumber >= 1024)
736
            return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
737
        channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
738
    }
739
    ++channel->receiveSequenceNumber;
740
    return UA_STATUSCODE_GOOD;
741
}
742
#endif
743
744
static UA_StatusCode
745
0
unpackPayloadOPN(UA_SecureChannel *channel, UA_Chunk *chunk) {
746
0
    UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
747
0
    size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
748
0
    UA_UInt32 secureChannelId;
749
0
    UA_StatusCode res = UA_UInt32_decodeBinary(&chunk->bytes, &offset, &secureChannelId);
750
0
    UA_assert(res == UA_STATUSCODE_GOOD);
751
752
0
    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
753
0
    res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &asymHeader,
754
0
             &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL);
755
0
    UA_CHECK_STATUS(res, return res);
756
757
    /* Declare before the first goto to avoid crosses-initialization in C++ */
758
0
    UA_SecurityPolicy *sp = NULL;
759
760
    /* Client/Server-specific processing. Creates a SecurityPolicy context and
761
     * attaches it to the channel. For the client, the remote certificate has
762
     * been verified before connecting. For the server the remote certificate is
763
     * verified within processOPNHeader. */
764
0
    UA_assert(channel->processOPNHeader);
765
0
    res = channel->processOPNHeader(channel->processOPNHeaderApplication,
766
0
                                    channel, &asymHeader);
767
0
    UA_CHECK_STATUS(res, goto error);
768
769
    /* On the client side, take the SecureChannelId from the first response */
770
0
    if(secureChannelId != 0 && channel->securityToken.channelId == 0)
771
0
        channel->securityToken.channelId = secureChannelId;
772
773
    /* Check the ChannelId */
774
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
775
    if(secureChannelId != channel->securityToken.channelId) {
776
        /* Allow the channel id to be different if the sent channel id is zero
777
         * and the SecurityToken is not initialized. This only happens on the
778
         * server side before we had a chance to tell the client which ChannelId
779
         * to use. */
780
        if(secureChannelId != 0 || channel->securityToken.tokenId != 0) {
781
            res = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
782
            goto error;
783
        }
784
    }
785
#endif
786
787
    /* Generic header checking (for both client and server). Requires the
788
     * channel's SecurityPolicy. */
789
0
    res = checkAsymHeader(channel, &asymHeader);
790
0
    UA_CHECK_STATUS(res, goto error);
791
792
0
    UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
793
794
    /* Decrypt the chunk payload */
795
0
    sp = channel->securityPolicy;
796
0
    res = decryptAndVerifyChunk(channel, &sp->asymSignatureAlgorithm,
797
0
                                &sp->asymEncryptionAlgorithm,
798
0
                                chunk->messageType, &chunk->bytes, offset);
799
0
    UA_CHECK_STATUS(res, return res);
800
801
    /* Decode the SequenceHeader */
802
0
    UA_SequenceHeader sequenceHeader;
803
0
    res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &sequenceHeader,
804
0
                                  &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
805
0
    UA_CHECK_STATUS(res, return res);
806
807
    /* Only the initial OPN establishes the receive sequence. Renewals remain
808
     * part of the existing channel's monotonically increasing sequence. */
809
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
810
    if(channel->state == UA_SECURECHANNELSTATE_OPEN) {
811
        res = processSequenceNumberSym(channel, sequenceHeader.sequenceNumber);
812
        UA_CHECK_STATUS(res, return res);
813
    } else
814
#endif
815
0
    {
816
0
        channel->receiveSequenceNumber = sequenceHeader.sequenceNumber;
817
0
    }
818
0
    chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
819
820
    /* Use only the payload */
821
0
    chunk->bytes.data += offset;
822
0
    chunk->bytes.length -= offset;
823
0
    return UA_STATUSCODE_GOOD;
824
825
0
error:
826
0
    UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
827
0
    return res;
828
0
}
829
830
static UA_StatusCode
831
unpackPayloadMSG(UA_SecureChannel *channel, UA_Chunk *chunk,
832
0
                 UA_DateTime nowMonotonic) {
833
0
    UA_CHECK_MEM(channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR);
834
835
0
    UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
836
0
    size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
837
0
    UA_UInt32 secureChannelId;
838
0
    UA_UInt32 tokenId; /* SymmetricAlgorithmSecurityHeader */
839
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
840
0
    res |= UA_UInt32_decodeBinary(&chunk->bytes, &offset, &secureChannelId);
841
0
    res |= UA_UInt32_decodeBinary(&chunk->bytes, &offset, &tokenId);
842
0
    UA_assert(offset == UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
843
0
    UA_assert(res == UA_STATUSCODE_GOOD);
844
845
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
846
    /* Check the ChannelId. Non-opened channels have the id zero. */
847
    if(secureChannelId != channel->securityToken.channelId)
848
        return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
849
#endif
850
851
    /* Check (and revolve) the SecurityToken */
852
0
    res = checkSymHeader(channel, tokenId, nowMonotonic);
853
0
    UA_CHECK_STATUS(res, return res);
854
855
    /* Decrypt the chunk payload */
856
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
857
0
    res = decryptAndVerifyChunk(channel, &sp->symSignatureAlgorithm,
858
0
                                &sp->symEncryptionAlgorithm,
859
0
                                chunk->messageType, &chunk->bytes, offset);
860
0
    UA_CHECK_STATUS(res, return res);
861
862
    /* Check the sequence number. Skip sequence number checking for fuzzer to
863
     * improve coverage */
864
0
    UA_SequenceHeader sequenceHeader;
865
0
    res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &sequenceHeader,
866
0
                                  &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
867
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
868
    res |= processSequenceNumberSym(channel, sequenceHeader.sequenceNumber);
869
#endif
870
0
    UA_CHECK_STATUS(res, return res);
871
872
0
    chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
873
874
    /* Use only the payload */
875
0
    chunk->bytes.data += offset;
876
0
    chunk->bytes.length -= offset;
877
0
    return UA_STATUSCODE_GOOD;
878
0
}
879
880
static UA_StatusCode
881
extractCompleteChunk(UA_SecureChannel *channel, UA_Chunk *chunk,
882
0
                     UA_DateTime nowMonotonic) {
883
    /* At least 8 byte needed for the header */
884
0
    size_t offset = channel->unprocessedOffset;
885
0
    size_t remaining = channel->unprocessed.length - offset;
886
0
    if(remaining < UA_SECURECHANNEL_MESSAGEHEADER_LENGTH)
887
0
        return UA_STATUSCODE_GOOD;
888
889
    /* Decoding the header cannot fail */
890
0
    UA_TcpMessageHeader hdr;
891
0
    UA_StatusCode res =
892
0
        UA_decodeBinaryInternal(&channel->unprocessed, &offset, &hdr,
893
0
                                &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL);
894
0
    UA_assert(res == UA_STATUSCODE_GOOD);
895
0
    (void)res; /* pacify compilers if assert is ignored */
896
0
    UA_MessageType msgType = (UA_MessageType)
897
0
        (hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
898
0
    UA_ChunkType chunkType = (UA_ChunkType)
899
0
        (hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
900
901
    /* The message size is not allowed */
902
0
    if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH)
903
0
        return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
904
0
    if(hdr.messageSize > channel->config.recvBufferSize)
905
0
        return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
906
907
    /* Incomplete chunk. Continue processing later. */
908
0
    if(hdr.messageSize > remaining)
909
0
        return UA_STATUSCODE_GOOD;
910
911
    /* Set the chunk information */
912
0
    chunk->bytes.data = channel->unprocessed.data + channel->unprocessedOffset;
913
0
    chunk->bytes.length = hdr.messageSize;
914
0
    chunk->messageType = msgType;
915
0
    chunk->chunkType = chunkType;
916
0
    chunk->requestId = 0;
917
0
    chunk->copied = false;
918
919
    /* Increase the unprocessed offset */
920
0
    channel->unprocessedOffset += hdr.messageSize;
921
922
    /* Validate, decrypt and unpack the chunk payload */
923
0
    switch(msgType) {
924
0
    case UA_MESSAGETYPE_OPN:
925
0
        if(chunkType != UA_CHUNKTYPE_FINAL)
926
0
            return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
927
0
        if(channel->state != UA_SECURECHANNELSTATE_OPEN &&
928
0
           channel->state != UA_SECURECHANNELSTATE_OPN_SENT &&
929
0
           channel->state != UA_SECURECHANNELSTATE_ACK_SENT)
930
0
            return UA_STATUSCODE_BADINVALIDSTATE;
931
0
        res = unpackPayloadOPN(channel, chunk);
932
0
        break;
933
934
0
    case UA_MESSAGETYPE_MSG:
935
0
    case UA_MESSAGETYPE_CLO:
936
0
        if(chunkType != UA_CHUNKTYPE_FINAL &&
937
0
           chunkType != UA_CHUNKTYPE_INTERMEDIATE &&
938
0
           chunkType != UA_CHUNKTYPE_ABORT)
939
0
            return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
940
0
        if(channel->state != UA_SECURECHANNELSTATE_OPEN)
941
0
            return UA_STATUSCODE_BADINVALIDSTATE;
942
0
        res = unpackPayloadMSG(channel, chunk, nowMonotonic);
943
0
        break;
944
945
0
    case UA_MESSAGETYPE_RHE:
946
0
    case UA_MESSAGETYPE_HEL:
947
0
    case UA_MESSAGETYPE_ACK:
948
0
    case UA_MESSAGETYPE_ERR:
949
0
        if(chunkType != UA_CHUNKTYPE_FINAL)
950
0
            return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
951
        /* Hide the message header */
952
0
        chunk->bytes.data += UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
953
0
        chunk->bytes.length -= UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
954
0
        break;
955
956
0
    default:
957
0
        res = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
958
0
        break;
959
0
    }
960
0
    return res;
961
0
}
962
963
UA_StatusCode
964
0
UA_SecureChannel_loadBuffer(UA_SecureChannel *channel, const UA_ByteString buffer) {
965
    /* Append to the previous unprocessed buffer */
966
0
    if(channel->unprocessed.length > 0) {
967
0
        UA_assert(channel->unprocessedCopied == true);
968
969
0
        UA_Byte *t = (UA_Byte*)
970
0
            UA_realloc(channel->unprocessed.data,
971
0
                       channel->unprocessed.length + buffer.length);
972
0
        if(!t)
973
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
974
975
0
        if(buffer.length)
976
0
            memcpy(t + channel->unprocessed.length, buffer.data, buffer.length);
977
0
        channel->unprocessed.data = t;
978
0
        channel->unprocessed.length += buffer.length;
979
0
        return UA_STATUSCODE_GOOD;
980
0
    }
981
982
    /* Use the new buffer directly */
983
0
    channel->unprocessed = buffer;
984
0
    channel->unprocessedCopied = false;
985
0
    return UA_STATUSCODE_GOOD;
986
0
}
987
988
/* The effective message-size limit for the message currently being
989
 * received: config.localMaxMessageSize (which may be 0 for "unbounded"),
990
 * tightened by maxMessageSizeOverride if the application has set one via
991
 * UA_Server_setSecureChannelAttribute -- it can only lower the static
992
 * ceiling, never raise it. */
993
static UA_UInt32
994
0
getEffectiveMaxMessageSize(const UA_SecureChannel *channel) {
995
0
    UA_UInt32 max = channel->config.localMaxMessageSize;
996
0
    if(channel->maxMessageSizeOverride != 0 &&
997
0
       (max == 0 || channel->maxMessageSizeOverride < max))
998
0
        max = channel->maxMessageSizeOverride;
999
0
    return max;
1000
0
}
1001
1002
UA_StatusCode
1003
UA_SecureChannel_getCompleteMessage(UA_SecureChannel *channel,
1004
                                    UA_MessageType *messageType, UA_UInt32 *requestId,
1005
                                    UA_ByteString *payload, UA_Boolean *copied,
1006
0
                                    UA_DateTime nowMonotonic) {
1007
0
    UA_Chunk chunk, *pchunk;
1008
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
1009
1010
0
 extract_chunk:
1011
    /* Extract+decode the next chunk from the buffer */
1012
0
    memset(&chunk, 0, sizeof(UA_Chunk));
1013
0
    res = extractCompleteChunk(channel, &chunk, nowMonotonic);
1014
0
    if(chunk.bytes.length == 0 || res != UA_STATUSCODE_GOOD)
1015
0
        return res; /* Error or no complete chunk could be extracted */
1016
1017
    /* Process the chunk */
1018
0
    switch(chunk.chunkType) {
1019
0
    case UA_CHUNKTYPE_ABORT:
1020
        /* Remove all chunks received so far. Then continue extracting chunks. */
1021
0
        deleteChunks(channel);
1022
0
        if(chunk.copied)
1023
0
            UA_ByteString_clear(&chunk.bytes);
1024
0
        goto extract_chunk;
1025
1026
0
    case UA_CHUNKTYPE_INTERMEDIATE: {
1027
        /* Validate the resource limits */
1028
0
        UA_UInt32 maxMessageSize = getEffectiveMaxMessageSize(channel);
1029
0
        if((channel->config.localMaxChunkCount != 0 &&
1030
0
            channel->chunksCount >= channel->config.localMaxChunkCount) ||
1031
0
           (maxMessageSize != 0 &&
1032
0
            channel->chunksLength + chunk.bytes.length > maxMessageSize)) {
1033
0
            if(chunk.copied)
1034
0
                UA_ByteString_clear(&chunk.bytes);
1035
0
            return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
1036
0
        }
1037
1038
        /* Add the chunk to the queue. Then continue extracting more chunks. */
1039
0
        pchunk = (UA_Chunk*)UA_malloc(sizeof(UA_Chunk));
1040
0
        if(!pchunk) {
1041
0
            if(chunk.copied)
1042
0
                UA_ByteString_clear(&chunk.bytes);
1043
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
1044
0
        }
1045
0
        *pchunk = chunk;
1046
0
        TAILQ_INSERT_TAIL(&channel->chunks, pchunk, pointers);
1047
0
        channel->chunksCount++;
1048
0
        channel->chunksLength += pchunk->bytes.length;
1049
0
        goto extract_chunk;
1050
0
    }
1051
1052
0
    case UA_CHUNKTYPE_FINAL:
1053
0
    default:
1054
0
        UA_assert(chunk.chunkType == UA_CHUNKTYPE_FINAL); /* Was checked before */
1055
0
        break; /* A final chunk was received -- assemble the message */
1056
0
    }
1057
1058
    /* Compute the message size */
1059
0
    size_t messageSize = chunk.bytes.length;
1060
0
    size_t messageChunks = 1; /* Include the final chunk */
1061
0
    UA_Chunk *first = NULL;
1062
0
    TAILQ_FOREACH(pchunk, &channel->chunks, pointers) {
1063
0
        if(chunk.requestId != pchunk->requestId)
1064
0
            continue;
1065
0
        if(chunk.messageType != pchunk->messageType) {
1066
0
            if(chunk.copied)
1067
0
                UA_ByteString_clear(&chunk.bytes);
1068
0
            return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
1069
0
        }
1070
0
        if(!first)
1071
0
            first = pchunk;
1072
0
        messageChunks++;
1073
0
        messageSize += pchunk->bytes.length;
1074
0
    }
1075
1076
    /* Validate the assembled message limits. The final chunk also counts
1077
     * towards localMaxChunkCount. */
1078
0
    UA_UInt32 maxMessageSize = getEffectiveMaxMessageSize(channel);
1079
0
    if((channel->config.localMaxChunkCount != 0 &&
1080
0
        messageChunks > channel->config.localMaxChunkCount) ||
1081
0
       (maxMessageSize != 0 && messageSize > maxMessageSize)) {
1082
0
        if(chunk.copied)
1083
0
            UA_ByteString_clear(&chunk.bytes);
1084
0
        return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
1085
0
    }
1086
1087
    /* Assemble the full payload and store it in chunk.bytes */
1088
0
    if(messageSize > chunk.bytes.length) {
1089
0
        UA_assert(first != NULL);
1090
1091
        /* Allocate the full memory and initialize with the first chunk content.
1092
         * Use realloc to speed up. */
1093
0
        UA_ByteString message;
1094
0
        if(first->copied) {
1095
0
            message.data = (UA_Byte*)UA_realloc(first->bytes.data, messageSize);
1096
0
        } else {
1097
0
            message.data = (UA_Byte*)UA_malloc(messageSize);
1098
0
            if(message.data)
1099
0
                memcpy(message.data, first->bytes.data, first->bytes.length);
1100
0
        }
1101
0
        if(!message.data) {
1102
0
            if(chunk.copied)
1103
0
                UA_ByteString_clear(&chunk.bytes);
1104
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
1105
0
        }
1106
0
        message.length = first->bytes.length;
1107
1108
        /* Remove the the first chunk */
1109
0
        pchunk = TAILQ_NEXT(first, pointers);
1110
0
        first->copied = false;
1111
0
        channel->chunksCount--;
1112
0
        channel->chunksLength -= first->bytes.length;
1113
0
        TAILQ_REMOVE(&channel->chunks, first, pointers);
1114
0
        UA_Chunk_delete(first);
1115
1116
        /* Copy over the content from the remaining intermediate chunks.
1117
         * And remove them right away. */
1118
0
        UA_Chunk *next;
1119
0
        for(; pchunk; pchunk = next) {
1120
0
            next = TAILQ_NEXT(pchunk, pointers);
1121
0
            if(chunk.requestId != pchunk->requestId)
1122
0
                continue;
1123
0
            memcpy(message.data + message.length, pchunk->bytes.data, pchunk->bytes.length);
1124
0
            message.length += pchunk->bytes.length;
1125
0
            channel->chunksCount--;
1126
0
            channel->chunksLength -= pchunk->bytes.length;
1127
0
            TAILQ_REMOVE(&channel->chunks, pchunk, pointers);
1128
0
            UA_Chunk_delete(pchunk);
1129
0
        }
1130
1131
        /* Copy over the content from the final chunk */
1132
0
        memcpy(message.data + message.length, chunk.bytes.data, chunk.bytes.length);
1133
0
        message.length += chunk.bytes.length;
1134
0
        UA_assert(message.length == messageSize);
1135
1136
        /* Set assembled message as the content of the final chunk */
1137
0
        if(chunk.copied)
1138
0
            UA_ByteString_clear(&chunk.bytes);
1139
0
        chunk.bytes = message;
1140
0
        chunk.copied = true;
1141
0
    }
1142
1143
    /* Return the assembled message */
1144
0
    *requestId = chunk.requestId;
1145
0
    *messageType = chunk.messageType;
1146
0
    *payload = chunk.bytes;
1147
0
    *copied = chunk.copied;
1148
0
    return UA_STATUSCODE_GOOD;
1149
0
}
1150
1151
UA_StatusCode
1152
0
UA_SecureChannel_persistBuffer(UA_SecureChannel *channel) {
1153
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
1154
1155
    /* Persist the chunks */
1156
0
    UA_Chunk *chunk;
1157
0
    TAILQ_FOREACH(chunk, &channel->chunks, pointers) {
1158
0
        if(chunk->copied)
1159
0
            continue;
1160
0
        UA_ByteString tmp = UA_BYTESTRING_NULL;
1161
0
        res |= UA_ByteString_copy(&chunk->bytes, &tmp);
1162
0
        chunk->bytes = tmp;
1163
0
        chunk->copied = true;
1164
0
    }
1165
1166
    /* No unprocessed bytes remaining */
1167
0
    UA_assert(channel->unprocessed.length >= channel->unprocessedOffset);
1168
0
    if(channel->unprocessed.length == channel->unprocessedOffset) {
1169
0
        if(channel->unprocessedCopied)
1170
0
            UA_ByteString_clear(&channel->unprocessed);
1171
0
        else
1172
0
            UA_ByteString_init(&channel->unprocessed);
1173
0
        channel->unprocessedOffset = 0;
1174
0
        return res;
1175
0
    }
1176
1177
    /* Allocate a new unprocessed ByteString.
1178
     * tmp is the empty string if malloc fails. */
1179
0
    UA_ByteString tmp = UA_BYTESTRING_NULL;
1180
0
    UA_ByteString remaining = channel->unprocessed;
1181
0
    remaining.data += channel->unprocessedOffset;
1182
0
    remaining.length -= channel->unprocessedOffset;
1183
0
    res |= UA_ByteString_copy(&remaining, &tmp);
1184
0
    if(channel->unprocessedCopied)
1185
0
        UA_ByteString_clear(&channel->unprocessed);
1186
0
    channel->unprocessed = tmp;
1187
0
    channel->unprocessedOffset = 0;
1188
    channel->unprocessedCopied = true;
1189
0
    return res;
1190
0
}