Coverage Report

Created: 2026-09-28 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/src/server/ua_services.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-2024 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2014-2016 (c) Sten Grüner
7
 *    Copyright 2014-2015, 2017 (c) Florian Palm
8
 *    Copyright 2015-2016 (c) Chris Iatrou
9
 *    Copyright 2015-2016 (c) Oleksiy Vasylyev
10
 *    Copyright 2016 (c) Joakim L. Gilje
11
 *    Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
12
 *    Copyright 2016 (c) TorbenD
13
 *    Copyright 2017 (c) frax2222
14
 *    Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
15
 *    Copyright 2019 (c) Kalycito Infotech Private Limited
16
 *    Copyright 2023 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Phuong Nguyen)
17
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Julius Pfrommer)
18
 */
19
20
/* This file contains the service invocation logic that is called from all
21
 * communication backends */
22
23
#include "ua_server_internal.h"
24
#include "ua_services.h"
25
#include "../ua_types_encoding_binary.h"
26
27
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
28
/* store the authentication token and session ID so we can help fuzzing by
29
 * setting these values in the next request automatically */
30
UA_NodeId unsafe_fuzz_authenticationToken = {0, UA_NODEIDTYPE_NUMERIC, {0}};
31
#endif
32
33
/* The counterOffset is the offset of the UA_ServiceCounterDataType for the
34
 * service in the UA_ SessionDiagnosticsDataType. */
35
#ifdef UA_ENABLE_DIAGNOSTICS
36
# define UA_SERVICECOUNTER_OFFSET_NONE(requiresSession) 0, requiresSession
37
# define UA_SERVICECOUNTER_OFFSET(X, requiresSession) \
38
    offsetof(UA_SessionDiagnosticsDataType, X), requiresSession
39
#else
40
# define UA_SERVICECOUNTER_OFFSET_NONE(requiresSession) requiresSession
41
# define UA_SERVICECOUNTER_OFFSET(X, requiresSession) requiresSession
42
#endif
43
44
static UA_ServiceDescription serviceDescriptions[] = {
45
    {UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY,
46
     UA_SERVICECOUNTER_OFFSET_NONE(false), Service_GetEndpoints,
47
     &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]},
48
    {UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY,
49
     UA_SERVICECOUNTER_OFFSET_NONE(false), Service_FindServers,
50
     &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]},
51
#ifdef UA_ENABLE_DISCOVERY
52
    {UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY,
53
     UA_SERVICECOUNTER_OFFSET_NONE(false), Service_RegisterServer,
54
     &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]},
55
    {UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY,
56
    UA_SERVICECOUNTER_OFFSET_NONE(false), Service_RegisterServer2,
57
    &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]},
58
    {UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY,
59
     UA_SERVICECOUNTER_OFFSET_NONE(false), Service_FindServersOnNetwork,
60
     &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]},
61
#endif
62
    {UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY,
63
     UA_SERVICECOUNTER_OFFSET_NONE(false), NULL,
64
     &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]},
65
    {UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY,
66
     UA_SERVICECOUNTER_OFFSET_NONE(false), NULL,
67
     &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],  &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]},
68
    {UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY,
69
     UA_SERVICECOUNTER_OFFSET_NONE(true), NULL,
70
     &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]},
71
    {UA_NS0ID_CANCELREQUEST_ENCODING_DEFAULTBINARY,
72
     UA_SERVICECOUNTER_OFFSET_NONE(true), Service_Cancel,
73
     &UA_TYPES[UA_TYPES_CANCELREQUEST], &UA_TYPES[UA_TYPES_CANCELRESPONSE]},
74
    {UA_NS0ID_READREQUEST_ENCODING_DEFAULTBINARY,
75
     UA_SERVICECOUNTER_OFFSET(readCount, true), Service_Read,
76
     &UA_TYPES[UA_TYPES_READREQUEST], &UA_TYPES[UA_TYPES_READRESPONSE]},
77
    {UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY,
78
     UA_SERVICECOUNTER_OFFSET(writeCount, true), Service_Write,
79
     &UA_TYPES[UA_TYPES_WRITEREQUEST], &UA_TYPES[UA_TYPES_WRITERESPONSE]},
80
    {UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY,
81
     UA_SERVICECOUNTER_OFFSET(browseCount, true), Service_Browse,
82
     &UA_TYPES[UA_TYPES_BROWSEREQUEST], &UA_TYPES[UA_TYPES_BROWSERESPONSE]},
83
    {UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY,
84
     UA_SERVICECOUNTER_OFFSET(browseNextCount, true), Service_BrowseNext,
85
     &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]},
86
    {UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY,
87
     UA_SERVICECOUNTER_OFFSET(registerNodesCount, true), Service_RegisterNodes,
88
     &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST], &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]},
89
    {UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY,
90
     UA_SERVICECOUNTER_OFFSET(unregisterNodesCount, true), Service_UnregisterNodes,
91
     &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST], &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]},
92
    {UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY,
93
     UA_SERVICECOUNTER_OFFSET(translateBrowsePathsToNodeIdsCount, true), Service_TranslateBrowsePathsToNodeIds,
94
     &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST], &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]},
95
#ifdef UA_ENABLE_SUBSCRIPTIONS
96
    {UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY,
97
     UA_SERVICECOUNTER_OFFSET(createSubscriptionCount, true), Service_CreateSubscription,
98
     &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]},
99
    {UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY,
100
     UA_SERVICECOUNTER_OFFSET(publishCount, true), Service_Publish,
101
     &UA_TYPES[UA_TYPES_PUBLISHREQUEST], &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]},
102
    {UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY,
103
     UA_SERVICECOUNTER_OFFSET(republishCount, true), Service_Republish,
104
     &UA_TYPES[UA_TYPES_REPUBLISHREQUEST], &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]},
105
    {UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY,
106
     UA_SERVICECOUNTER_OFFSET(modifySubscriptionCount, true), Service_ModifySubscription,
107
     &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]},
108
    {UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY,
109
     UA_SERVICECOUNTER_OFFSET(setPublishingModeCount, true), Service_SetPublishingMode,
110
     &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST], &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]},
111
    {UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY,
112
     UA_SERVICECOUNTER_OFFSET(deleteSubscriptionsCount, true), Service_DeleteSubscriptions,
113
     &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]},
114
    {UA_NS0ID_TRANSFERSUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY,
115
     UA_SERVICECOUNTER_OFFSET(transferSubscriptionsCount, true), Service_TransferSubscriptions,
116
     &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST], &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]},
117
    {UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY,
118
     UA_SERVICECOUNTER_OFFSET(createMonitoredItemsCount, true), Service_CreateMonitoredItems,
119
     &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]},
120
    {UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY,
121
     UA_SERVICECOUNTER_OFFSET(deleteMonitoredItemsCount, true), Service_DeleteMonitoredItems,
122
     &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]},
123
    {UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY,
124
     UA_SERVICECOUNTER_OFFSET(modifyMonitoredItemsCount, true), Service_ModifyMonitoredItems,
125
     &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]},
126
    {UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY,
127
     UA_SERVICECOUNTER_OFFSET(setMonitoringModeCount, true), Service_SetMonitoringMode,
128
     &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST], &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]},
129
    {UA_NS0ID_SETTRIGGERINGREQUEST_ENCODING_DEFAULTBINARY,
130
     UA_SERVICECOUNTER_OFFSET(setTriggeringCount, true), Service_SetTriggering,
131
     &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST], &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]},
132
#endif
133
#ifdef UA_ENABLE_HISTORIZING
134
    {UA_NS0ID_HISTORYREADREQUEST_ENCODING_DEFAULTBINARY,
135
     UA_SERVICECOUNTER_OFFSET(historyReadCount, true), Service_HistoryRead,
136
     &UA_TYPES[UA_TYPES_HISTORYREADREQUEST], &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE]},
137
    {UA_NS0ID_HISTORYUPDATEREQUEST_ENCODING_DEFAULTBINARY,
138
     UA_SERVICECOUNTER_OFFSET(historyUpdateCount, true), Service_HistoryUpdate,
139
     &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST], &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE]},
140
#endif
141
#ifdef UA_ENABLE_METHODCALLS
142
    {UA_NS0ID_CALLREQUEST_ENCODING_DEFAULTBINARY,
143
     UA_SERVICECOUNTER_OFFSET(callCount, true), Service_Call,
144
     &UA_TYPES[UA_TYPES_CALLREQUEST], &UA_TYPES[UA_TYPES_CALLRESPONSE]},
145
#endif
146
#ifdef UA_ENABLE_NODEMANAGEMENT
147
    {UA_NS0ID_ADDNODESREQUEST_ENCODING_DEFAULTBINARY,
148
     UA_SERVICECOUNTER_OFFSET(addNodesCount, true), Service_AddNodes,
149
     &UA_TYPES[UA_TYPES_ADDNODESREQUEST], &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]},
150
    {UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY,
151
     UA_SERVICECOUNTER_OFFSET(addReferencesCount, true), Service_AddReferences,
152
     &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST], &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]},
153
    {UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY,
154
     UA_SERVICECOUNTER_OFFSET(deleteNodesCount, true), Service_DeleteNodes,
155
     &UA_TYPES[UA_TYPES_DELETENODESREQUEST], &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]},
156
    {UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY,
157
     UA_SERVICECOUNTER_OFFSET(deleteReferencesCount, true), Service_DeleteReferences,
158
     &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST], &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]},
159
#endif
160
    {0, UA_SERVICECOUNTER_OFFSET_NONE(false), NULL, NULL, NULL}
161
};
162
163
UA_ServiceDescription *
164
22.8k
getServiceDescription(UA_UInt32 requestTypeId) {
165
257k
    for(size_t i = 0; serviceDescriptions[i].requestTypeId > 0; i++) {
166
256k
        if(serviceDescriptions[i].requestTypeId == requestTypeId)
167
21.9k
            return &serviceDescriptions[i];
168
256k
    }
169
927
    return NULL;
170
22.8k
}
171
172
UA_StatusCode
173
decodeBinaryServiceRequest(UA_Server *server, const UA_ByteString *message,
174
                           UA_ServiceDescription **description,
175
                           UA_Request *request, size_t *requestOffset,
176
813
                           UA_UInt32 *requestTypeId) {
177
813
    *description = NULL;
178
813
    size_t offset = 0;
179
813
    UA_NodeId typeId;
180
813
    UA_NodeId_init(&typeId);
181
813
    UA_StatusCode res = UA_NodeId_decodeBinary(message, &offset, &typeId);
182
813
    if(res != UA_STATUSCODE_GOOD)
183
15
        return res;
184
798
    if(requestOffset)
185
798
        *requestOffset = offset;
186
798
    if(typeId.namespaceIndex != 0 ||
187
782
       typeId.identifierType != UA_NODEIDTYPE_NUMERIC) {
188
17
        UA_NodeId_clear(&typeId);
189
17
        return UA_STATUSCODE_BADSERVICEUNSUPPORTED;
190
17
    }
191
192
781
    UA_UInt32 numericTypeId = typeId.identifier.numeric;
193
781
    UA_NodeId_clear(&typeId);
194
781
    if(requestTypeId)
195
781
        *requestTypeId = numericTypeId;
196
781
    *description = getServiceDescription(numericTypeId);
197
781
    if(!*description)
198
36
        return UA_STATUSCODE_BADSERVICEUNSUPPORTED;
199
200
745
    memset(request, 0, sizeof(*request));
201
745
    UA_DecodeBinaryOptions options;
202
745
    memset(&options, 0, sizeof(options));
203
745
    options.customTypes = serverCustomTypes(server);
204
745
    res = UA_decodeBinaryInternal(message, &offset, request,
205
745
                                  (*description)->requestType, &options);
206
745
    if(res == UA_STATUSCODE_GOOD && offset != message->length)
207
190
        res = UA_STATUSCODE_BADDECODINGERROR;
208
745
    if(res != UA_STATUSCODE_GOOD)
209
336
        UA_clear(request, (*description)->requestType);
210
745
    return res;
211
781
}
212
213
/* Allocates the results array and iterates over it to execute the operations
214
 * within a request */
215
UA_StatusCode
216
allocProcessServiceOperations(UA_Server *server, UA_Session *session,
217
                              UA_ServiceOperation operationCallback,
218
                              const void *context, const size_t *requestOperations,
219
                              const UA_DataType *requestOperationsType,
220
                              size_t *responseOperations,
221
860
                              const UA_DataType *responseOperationsType) {
222
860
    size_t ops = *requestOperations;
223
860
    if(ops == 0)
224
217
        return UA_STATUSCODE_BADNOTHINGTODO;
225
226
    /* No padding after size_t */
227
643
    void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
228
643
    *respPos = UA_Array_new(ops, responseOperationsType);
229
643
    if(!(*respPos))
230
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
231
232
643
    *responseOperations = ops;
233
643
    uintptr_t respOp = (uintptr_t)*respPos;
234
    /* No padding after size_t */
235
643
    uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
236
82.0k
    for(size_t i = 0; i < ops; i++) {
237
81.4k
        operationCallback(server, session, context, (void*)reqOp, (void*)respOp);
238
81.4k
        if(session && session->state == UA_SESSIONSTATE_CLOSED)
239
0
            return UA_STATUSCODE_BADSESSIONCLOSED;
240
81.4k
        reqOp += requestOperationsType->memSize;
241
81.4k
        respOp += responseOperationsType->memSize;
242
81.4k
    }
243
643
    return UA_STATUSCODE_GOOD;
244
643
}
245
246
static UA_UInt32
247
9.76k
getUacpRequestId(const UA_SecureChannel *channel, UA_UInt64 responseToken) {
248
9.76k
    if(channel->transport != UA_SECURECHANNEL_TRANSPORT_UACP)
249
0
        return 0;
250
9.76k
    UA_assert(responseToken <= UINT32_MAX);
251
9.76k
    return (UA_UInt32)responseToken;
252
9.76k
}
253
254
static UA_Boolean
255
processServiceInternal(UA_Server *server, UA_SecureChannel *channel, UA_Session *session,
256
                       UA_UInt64 responseToken, UA_ServiceDescription *sd,
257
8.65k
                       const UA_Request *request, UA_Response *response) {
258
8.65k
    UA_ResponseHeader *rh = &response->responseHeader;
259
260
    /* A callback before service execution can close the resolved Session. */
261
8.65k
    if(session && session->state == UA_SESSIONSTATE_CLOSED) {
262
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONCLOSED;
263
0
        return true;
264
0
    }
265
266
    /* Check timestamp in the request header */
267
8.65k
    if(request->requestHeader.timestamp == 0 &&
268
2.25k
       server->config.verifyRequestTimestamp <= UA_RULEHANDLING_WARN) {
269
1.84k
        UA_LOG_WARNING_CHANNEL(server->config.logging, channel,
270
1.84k
                               "The server sends no timestamp in the request header. "
271
1.84k
                               "See the 'verifyRequestTimestamp' setting.");
272
1.84k
        if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) {
273
84
            rh->serviceResult = UA_STATUSCODE_BADINVALIDTIMESTAMP;
274
84
            return true;
275
84
        }
276
1.84k
    }
277
278
    /* If it is an unencrypted (#None) channel, only allow the discovery services */
279
8.56k
    if(server->config.securityPolicyNoneDiscoveryOnly &&
280
164
       channel->securityPolicy->policyType == UA_SECURITYPOLICYTYPE_NONE &&
281
164
       sd->requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] &&
282
89
       sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]
283
35
#if defined(UA_ENABLE_DISCOVERY)
284
35
       && sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
285
8.56k
#endif
286
8.56k
       ) {
287
35
        rh->serviceResult = UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
288
35
        return true;
289
35
    }
290
291
    /* Session lifecycle services */
292
8.53k
    if(sd->requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] ||
293
2.54k
       sd->requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] ||
294
7.42k
       sd->requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) {
295
7.42k
        if(sd->requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST])
296
5.99k
            Service_CreateSession(server, channel, request, response);
297
1.43k
        else if(sd->requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST])
298
1.43k
            Service_ActivateSession(server, channel, request, response);
299
0
        else
300
0
            Service_CloseSession(server, channel, request, response);
301
        /* Store the authentication token created during CreateSession to help
302
         * fuzzing cover more lines */
303
7.42k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
304
7.42k
        if(sd->requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
305
5.99k
            UA_CreateSessionResponse *res = &response->createSessionResponse;
306
5.99k
            UA_NodeId_clear(&unsafe_fuzz_authenticationToken);
307
5.99k
            UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
308
5.99k
        }
309
7.42k
#endif
310
7.42k
        return true;
311
7.42k
    }
312
313
    /* Set an anonymous, inactive session for services that need no session */
314
1.11k
    UA_Session anonymousSession;
315
1.11k
    if(!session) {
316
236
        UA_assert(!sd->sessionRequired);
317
236
        UA_Session_init(&anonymousSession);
318
236
        anonymousSession.sessionId = UA_NODEID_GUID(0, UA_GUID_NULL);
319
236
        anonymousSession.channel = channel;
320
236
        session = &anonymousSession;
321
236
    }
322
323
    /* Trying to use a non-activated session? */
324
1.11k
    if(sd->sessionRequired &&
325
875
       session->state != UA_SESSIONSTATE_ACTIVATED) {
326
0
        UA_assert(session != &anonymousSession); /* because sd->sessionRequired */
327
0
#ifdef UA_ENABLE_TYPEDESCRIPTION
328
0
        UA_LOG_WARNING_SESSION(server->config.logging, session,
329
0
                               "%s refused on a non-activated session",
330
0
                               sd->requestType->typeName);
331
#else
332
        UA_LOG_WARNING_SESSION(server->config.logging, session,
333
                               "Service %" PRIu32 " refused on a non-activated session",
334
                               sd->requestType->binaryEncodingId.identifier.numeric);
335
#endif
336
0
        UA_Session_remove(server, session, UA_SHUTDOWNREASON_ABORT);
337
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
338
0
        return true;
339
0
    }
340
341
    /* Update the session lifetime */
342
1.11k
    UA_EventLoop *el = server->config.eventLoop;
343
1.11k
    UA_DateTime nowMonotonic = el->dateTime_nowMonotonic(el);
344
1.11k
    UA_DateTime now = el->dateTime_now(el);
345
1.11k
    UA_Session_updateLifetime(session, now, nowMonotonic);
346
347
    /* Store the response token -- will be used to create async responses */
348
1.11k
    server->asyncManager.currentResponseToken = responseToken;
349
1.11k
    server->asyncManager.currentUacpRequestId =
350
1.11k
        getUacpRequestId(channel, responseToken);
351
1.11k
    server->asyncManager.currentRequestHandle = request->requestHeader.requestHandle;
352
353
    /* Execute the service. A user callback inside the service can close the
354
     * Session. For synchronous services, do not return a successful response
355
     * for a Session that became closed during the operation. */
356
1.11k
    UA_Boolean done = sd->serviceCallback(server, session, request, response);
357
1.11k
    if(done && session->state == UA_SESSIONSTATE_CLOSED)
358
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONCLOSED;
359
1.11k
    return done;
360
1.11k
}
361
362
UA_Boolean
363
processRequest(UA_Server *server, UA_SecureChannel *channel,
364
               UA_UInt64 responseToken, UA_ServiceDescription *sd,
365
9.42k
               const UA_Request *request, UA_Response *response) {
366
9.42k
    UA_LOCK_ASSERT(&server->serviceMutex);
367
368
    /* Set the authenticationToken from the create session request to help
369
     * fuzzing cover more lines */
370
9.42k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
371
9.42k
    UA_NodeId *authenticationToken = (UA_NodeId *)(uintptr_t)
372
9.42k
        &request->requestHeader.authenticationToken;
373
9.42k
    if(!UA_NodeId_isNull(authenticationToken) &&
374
6.79k
       !UA_NodeId_isNull(&unsafe_fuzz_authenticationToken)) {
375
5.16k
        UA_NodeId_clear(authenticationToken);
376
5.16k
        UA_NodeId_copy(&unsafe_fuzz_authenticationToken, authenticationToken);
377
5.16k
    }
378
9.42k
#endif
379
380
    /* Get the session bound to the SecureChannel (not necessarily activated) */
381
9.42k
    UA_Session *session = NULL;
382
9.42k
    response->responseHeader.serviceResult =
383
9.42k
        getBoundSession(server, channel, &request->requestHeader.authenticationToken, &session);
384
9.42k
    if(!session && sd->sessionRequired)
385
767
        return true;
386
387
    /* The session can be NULL if not required */
388
8.65k
    response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
389
8.65k
    UA_NodeId sessionId = (session) ? session->sessionId : UA_NODEID_NULL;
390
8.65k
    UA_UInt32 uacpRequestId = getUacpRequestId(channel, responseToken);
391
392
    /* Notify with UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_BEGIN */
393
8.65k
    UA_STATIC_THREAD_LOCAL UA_KeyValuePair notifyPayload[4] = {
394
8.65k
        {{0, UA_STRING_STATIC("securechannel-id")}, {0}},
395
8.65k
        {{0, UA_STRING_STATIC("session-id")}, {0}},
396
8.65k
        {{0, UA_STRING_STATIC("request-id")}, {0}},
397
8.65k
        {{0, UA_STRING_STATIC("service-type")}, {0}}
398
8.65k
    };
399
8.65k
    UA_KeyValueMap notifyPayloadMap = {4, notifyPayload};
400
8.65k
    UA_Variant_setScalar(&notifyPayload[0].value, &channel->securityToken.channelId,
401
8.65k
                         &UA_TYPES[UA_TYPES_UINT32]);
402
8.65k
    UA_Variant_setScalar(&notifyPayload[1].value, &sessionId,
403
8.65k
                         &UA_TYPES[UA_TYPES_NODEID]);
404
8.65k
    UA_Variant_setScalar(&notifyPayload[2].value, &uacpRequestId,
405
8.65k
                         &UA_TYPES[UA_TYPES_UINT32]);
406
8.65k
    UA_Variant_setScalar(&notifyPayload[3].value,
407
8.65k
                         (void *)(uintptr_t)&sd->requestType->typeId,
408
8.65k
                         &UA_TYPES[UA_TYPES_NODEID]);
409
8.65k
    UA_ApplicationNotificationType nt = UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_BEGIN;
410
8.65k
    notifyApplication(server, nt, notifyPayloadMap);
411
412
    /* Process the service */
413
8.65k
    beginModelChange(server);
414
8.65k
    UA_Boolean done = processServiceInternal(server, channel, session,
415
8.65k
                                             responseToken, sd, request,
416
8.65k
                                             response);
417
8.65k
    endModelChange(server);
418
8.65k
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
419
8.65k
    UA_assert(server->modelChangeDepth == 0);
420
8.65k
#endif
421
422
    /* Notify with UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_END if the service was
423
     * completed synchronously. For async completion of a service, this gets
424
     * called eventually in ua_server_async.c. */
425
8.65k
    nt = (done) ? UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_END :
426
8.65k
        UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_ASYNC;
427
8.65k
    notifyApplication(server, nt, notifyPayloadMap);
428
429
    /* Update the service statistics */
430
8.65k
#ifdef UA_ENABLE_DIAGNOSTICS
431
8.65k
    if(session) {
432
5.01k
        session->diagnostics.totalRequestCount.totalCount++;
433
5.01k
        if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
434
286
            session->diagnostics.totalRequestCount.errorCount++;
435
5.01k
        if(sd->counterOffset != 0) {
436
879
            UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*)
437
879
                (((uintptr_t)&session->diagnostics) + sd->counterOffset);
438
879
            serviceCounter->totalCount++;
439
879
            if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
440
256
                serviceCounter->errorCount++;
441
879
        }
442
5.01k
    }
443
8.65k
#endif
444
445
8.65k
    return done;
446
8.65k
}
447
448
UA_Boolean
449
processDecodedServiceRequest(UA_Server *server, UA_SecureChannel *channel,
450
                             UA_UInt64 responseToken,
451
                             UA_ServiceDescription *sd,
452
9.42k
                             const UA_Request *request, UA_Response *response) {
453
9.42k
    UA_LOCK_ASSERT(&server->serviceMutex);
454
9.42k
    UA_init(response, sd->responseType);
455
9.42k
    response->responseHeader.requestHandle =
456
9.42k
        request->requestHeader.requestHandle;
457
9.42k
    return processRequest(server, channel, responseToken, sd, request,
458
9.42k
                          response);
459
9.42k
}
460
461
void
462
abandonServiceRequest(UA_Server *server, UA_SecureChannel *channel,
463
0
                      UA_UInt64 responseToken) {
464
0
    UA_LOCK_ASSERT(&server->serviceMutex);
465
0
#ifdef UA_ENABLE_SUBSCRIPTIONS
466
0
    for(UA_Session *session = channel->sessions; session;
467
0
        session = session->next) {
468
0
        UA_PublishResponseEntry *pre, *next, *previous = NULL;
469
0
        SIMPLEQ_FOREACH_SAFE(pre, &session->responseQueue, listEntry, next) {
470
0
            if(pre->responseToken != responseToken) {
471
0
                previous = pre;
472
0
                continue;
473
0
            }
474
0
            if(previous)
475
0
                SIMPLEQ_REMOVE_AFTER(&session->responseQueue, previous,
476
0
                                     listEntry);
477
0
            else
478
0
                SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
479
0
            session->responseQueueSize--;
480
0
            UA_PublishResponse_clear(&pre->response);
481
0
            UA_free(pre);
482
0
            UA_LOG_DEBUG_SESSION(server->config.logging, session,
483
0
                                 "Removed abandoned Publish response token %"
484
0
                                 PRIu64, responseToken);
485
0
            break;
486
0
        }
487
0
    }
488
0
#endif
489
0
    UA_AsyncManager_abandon(server, channel, responseToken);
490
0
}