Coverage Report

Created: 2026-06-30 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/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
 */
18
19
/* This file contains the service invocation logic that is called from all
20
 * communication backends */
21
22
#include "ua_server_internal.h"
23
#include "ua_services.h"
24
25
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
26
/* store the authentication token and session ID so we can help fuzzing by
27
 * setting these values in the next request automatically */
28
UA_NodeId unsafe_fuzz_authenticationToken = {0, UA_NODEIDTYPE_NUMERIC, {0}};
29
#endif
30
31
/* The counterOffset is the offset of the UA_ServiceCounterDataType for the
32
 * service in the UA_ SessionDiagnosticsDataType. */
33
#ifdef UA_ENABLE_DIAGNOSTICS
34
# define UA_SERVICECOUNTER_OFFSET_NONE(requiresSession) 0, requiresSession
35
# define UA_SERVICECOUNTER_OFFSET(X, requiresSession) \
36
    offsetof(UA_SessionDiagnosticsDataType, X), requiresSession
37
#else
38
# define UA_SERVICECOUNTER_OFFSET_NONE(requiresSession) requiresSession
39
# define UA_SERVICECOUNTER_OFFSET(X, requiresSession) requiresSession
40
#endif
41
42
static UA_ServiceDescription serviceDescriptions[] = {
43
    {UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY,
44
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_GetEndpoints,
45
     &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]},
46
    {UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY,
47
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_FindServers,
48
     &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]},
49
#ifdef UA_ENABLE_DISCOVERY
50
    {UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY,
51
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_RegisterServer,
52
     &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]},
53
    {UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY,
54
    UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_RegisterServer2,
55
    &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]},
56
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
57
    {UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY,
58
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_FindServersOnNetwork,
59
     &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]},
60
# endif
61
#endif
62
    {UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY,
63
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)(uintptr_t)Service_CreateSession,
64
     &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]},
65
    {UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY,
66
     UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)(uintptr_t)Service_ActivateSession,
67
     &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],  &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]},
68
    {UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY,
69
     UA_SERVICECOUNTER_OFFSET_NONE(true), (UA_Service)(uintptr_t)Service_CloseSession,
70
     &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]},
71
    {UA_NS0ID_CANCELREQUEST_ENCODING_DEFAULTBINARY,
72
     UA_SERVICECOUNTER_OFFSET_NONE(true), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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), (UA_Service)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
8.77k
getServiceDescription(UA_UInt32 requestTypeId) {
165
91.7k
    for(size_t i = 0; serviceDescriptions[i].requestTypeId > 0; i++) {
166
91.2k
        if(serviceDescriptions[i].requestTypeId == requestTypeId)
167
8.26k
            return &serviceDescriptions[i];
168
91.2k
    }
169
507
    return NULL;
170
8.77k
}
171
172
/* Allocates the results array and iterates over it to execute the operations
173
 * within a request */
174
UA_StatusCode
175
allocProcessServiceOperations(UA_Server *server, UA_Session *session,
176
                              UA_ServiceOperation operationCallback,
177
                              const void *context, const size_t *requestOperations,
178
                              const UA_DataType *requestOperationsType,
179
                              size_t *responseOperations,
180
53
                              const UA_DataType *responseOperationsType) {
181
53
    size_t ops = *requestOperations;
182
53
    if(ops == 0)
183
8
        return UA_STATUSCODE_BADNOTHINGTODO;
184
185
    /* No padding after size_t */
186
45
    void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
187
45
    *respPos = UA_Array_new(ops, responseOperationsType);
188
45
    if(!(*respPos))
189
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
190
191
45
    *responseOperations = ops;
192
45
    uintptr_t respOp = (uintptr_t)*respPos;
193
    /* No padding after size_t */
194
45
    uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
195
1.55k
    for(size_t i = 0; i < ops; i++) {
196
1.51k
        operationCallback(server, session, context, (void*)reqOp, (void*)respOp);
197
1.51k
        reqOp += requestOperationsType->memSize;
198
1.51k
        respOp += responseOperationsType->memSize;
199
1.51k
    }
200
45
    return UA_STATUSCODE_GOOD;
201
45
}
202
203
static UA_Boolean
204
processServiceInternal(UA_Server *server, UA_SecureChannel *channel, UA_Session *session,
205
                       UA_UInt32 requestId, UA_ServiceDescription *sd,
206
5.04k
                       const UA_Request *request, UA_Response *response) {
207
5.04k
    UA_ResponseHeader *rh = &response->responseHeader;
208
209
    /* Check timestamp in the request header */
210
5.04k
    if(request->requestHeader.timestamp == 0 &&
211
100
       server->config.verifyRequestTimestamp <= UA_RULEHANDLING_WARN) {
212
54
        UA_LOG_WARNING_CHANNEL(server->config.logging, channel,
213
54
                               "The server sends no timestamp in the request header. "
214
54
                               "See the 'verifyRequestTimestamp' setting.");
215
54
        if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) {
216
40
            rh->serviceResult = UA_STATUSCODE_BADINVALIDTIMESTAMP;
217
40
            return true;
218
40
        }
219
54
    }
220
221
    /* If it is an unencrypted (#None) channel, only allow the discovery services */
222
5.00k
    if(server->config.securityPolicyNoneDiscoveryOnly &&
223
103
       channel->securityPolicy->policyType == UA_SECURITYPOLICYTYPE_NONE &&
224
103
       sd->requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] &&
225
91
       sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]
226
86
#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
227
86
       && sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
228
5.00k
#endif
229
5.00k
       ) {
230
86
        rh->serviceResult = UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
231
86
        return true;
232
86
    }
233
234
    /* Session lifecycle services */
235
4.91k
    if(sd->requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] ||
236
509
       sd->requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] ||
237
4.73k
       sd->requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) {
238
4.73k
        UA_ChannelService cs = (UA_ChannelService)(uintptr_t)sd->serviceCallback;
239
4.73k
        cs(server, channel, request, response);
240
        /* Store the authentication token created during CreateSession to help
241
         * fuzzing cover more lines */
242
4.73k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
243
4.73k
        if(sd->requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
244
4.40k
            UA_CreateSessionResponse *res = &response->createSessionResponse;
245
4.40k
            UA_NodeId_clear(&unsafe_fuzz_authenticationToken);
246
4.40k
            UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
247
4.40k
        }
248
4.73k
#endif
249
4.73k
        return true;
250
4.73k
    }
251
252
    /* Set an anonymous, inactive session for services that need no session */
253
179
    UA_Session anonymousSession;
254
179
    if(!session) {
255
137
        UA_assert(!sd->sessionRequired);
256
137
        UA_Session_init(&anonymousSession);
257
137
        anonymousSession.sessionId = UA_NODEID_GUID(0, UA_GUID_NULL);
258
137
        anonymousSession.channel = channel;
259
137
        session = &anonymousSession;
260
137
    }
261
262
    /* Trying to use a non-activated session? */
263
179
    if(sd->sessionRequired && !session->activated) {
264
33
        UA_assert(session != &anonymousSession); /* because sd->sessionRequired */
265
33
#ifdef UA_ENABLE_TYPEDESCRIPTION
266
33
        UA_LOG_WARNING_SESSION(server->config.logging, session,
267
33
                               "%s refused on a non-activated session",
268
33
                               sd->requestType->typeName);
269
#else
270
        UA_LOG_WARNING_SESSION(server->config.logging, session,
271
                               "Service %" PRIu32 " refused on a non-activated session",
272
                               sd->requestType->binaryEncodingId.identifier.numeric);
273
#endif
274
33
        UA_Session_remove(server, session, UA_SHUTDOWNREASON_ABORT);
275
33
        rh->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
276
33
        return true;
277
33
    }
278
279
    /* Update the session lifetime */
280
146
    UA_EventLoop *el = server->config.eventLoop;
281
146
    UA_DateTime nowMonotonic = el->dateTime_nowMonotonic(el);
282
146
    UA_DateTime now = el->dateTime_now(el);
283
146
    UA_Session_updateLifetime(session, now, nowMonotonic);
284
285
    /* Store the request id -- will be used to create async responses */
286
146
    server->asyncManager.currentRequestId = requestId;
287
146
    server->asyncManager.currentRequestHandle = request->requestHeader.requestHandle;
288
289
    /* Execute the service */
290
146
    return sd->serviceCallback(server, session, request, response);
291
179
}
292
293
UA_Boolean
294
processRequest(UA_Server *server, UA_SecureChannel *channel,
295
               UA_UInt32 requestId, UA_ServiceDescription *sd,
296
2.44k
               const UA_Request *request, UA_Response *response) {
297
2.44k
    UA_LOCK_ASSERT(&server->serviceMutex);
298
299
    /* Set the authenticationToken from the create session request to help
300
     * fuzzing cover more lines */
301
2.44k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
302
2.44k
    UA_NodeId *authenticationToken = (UA_NodeId *)(uintptr_t)
303
2.44k
        &request->requestHeader.authenticationToken;
304
2.44k
    if(!UA_NodeId_isNull(authenticationToken) &&
305
2.23k
       !UA_NodeId_isNull(&unsafe_fuzz_authenticationToken)) {
306
1.35k
        UA_NodeId_clear(authenticationToken);
307
1.35k
        UA_NodeId_copy(&unsafe_fuzz_authenticationToken, authenticationToken);
308
1.35k
    }
309
2.44k
#endif
310
311
    /* Get the session bound to the SecureChannel (not necessarily activated) */
312
2.44k
    UA_Session *session = NULL;
313
2.44k
    response->responseHeader.serviceResult =
314
2.44k
        getBoundSession(server, channel, &request->requestHeader.authenticationToken, &session);
315
2.44k
    if(!session && sd->sessionRequired)
316
239
        return true;
317
318
    /* The session can be NULL if not required */
319
2.20k
    response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
320
2.20k
    UA_NodeId sessionId = (session) ? session->sessionId : UA_NODEID_NULL;
321
322
    /* Notify with UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_BEGIN */
323
2.20k
    UA_ServerConfig *config = &server->config;
324
2.20k
    static UA_THREAD_LOCAL UA_KeyValuePair notifyPayload[4] = {
325
2.20k
        {{0, UA_STRING_STATIC("securechannel-id")}, {0}},
326
2.20k
        {{0, UA_STRING_STATIC("session-id")}, {0}},
327
2.20k
        {{0, UA_STRING_STATIC("request-id")}, {0}},
328
2.20k
        {{0, UA_STRING_STATIC("service-type")}, {0}}
329
2.20k
    };
330
2.20k
    UA_KeyValueMap notifyPayloadMap = {4, notifyPayload};
331
2.20k
    if(config->globalNotificationCallback || config->serviceNotificationCallback) {
332
0
        UA_Variant_setScalar(&notifyPayload[0].value, &channel->securityToken.channelId,
333
0
                             &UA_TYPES[UA_TYPES_UINT32]);
334
0
        UA_Variant_setScalar(&notifyPayload[1].value, &sessionId,
335
0
                             &UA_TYPES[UA_TYPES_NODEID]);
336
0
        UA_Variant_setScalar(&notifyPayload[2].value, &requestId,
337
0
                             &UA_TYPES[UA_TYPES_UINT32]);
338
0
        UA_Variant_setScalar(&notifyPayload[3].value,
339
0
                             (void *)(uintptr_t)&sd->requestType->typeId,
340
0
                             &UA_TYPES[UA_TYPES_NODEID]);
341
0
    }
342
2.20k
    UA_ApplicationNotificationType nt = UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_BEGIN;
343
2.20k
    if(config->serviceNotificationCallback)
344
0
        config->serviceNotificationCallback(server, nt, notifyPayloadMap);
345
2.20k
    if(config->globalNotificationCallback)
346
0
        config->globalNotificationCallback(server, nt, notifyPayloadMap);
347
348
    /* Process the service */
349
2.20k
    UA_Boolean done = processServiceInternal(server, channel, session,
350
2.20k
                                             requestId, sd, request, response);
351
352
    /* Notify with UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_END if the service was
353
     * completed synchronously. For async completion of a service, this gets
354
     * called eventually in ua_server_async.c. */
355
2.20k
    nt = (done) ? UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_END :
356
2.20k
        UA_APPLICATIONNOTIFICATIONTYPE_SERVICE_ASYNC;
357
2.20k
    if(config->serviceNotificationCallback)
358
0
        config->serviceNotificationCallback(server, nt, notifyPayloadMap);
359
2.20k
    if(config->globalNotificationCallback)
360
0
        config->globalNotificationCallback(server, nt, notifyPayloadMap);
361
362
    /* Update the service statistics */
363
2.20k
#ifdef UA_ENABLE_DIAGNOSTICS
364
2.20k
    if(session) {
365
517
        session->diagnostics.totalRequestCount.totalCount++;
366
517
        if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
367
46
            session->diagnostics.totalRequestCount.errorCount++;
368
517
        if(sd->counterOffset != 0) {
369
32
            UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*)
370
32
                (((uintptr_t)&session->diagnostics) + sd->counterOffset);
371
32
            serviceCounter->totalCount++;
372
32
            if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
373
31
                serviceCounter->errorCount++;
374
32
        }
375
517
    }
376
2.20k
#endif
377
378
2.20k
    return done;
379
2.44k
}